protected void AddTraverseInfoToGrid(IGSPlan Plan, DataGridView TraverseGrid, List <IVector3D> Traverse, List <IVector3D> AdjustedTraverse, List <string> FromToList) { ICadastralUnitConversion pCadUnitConverter = new CadastralUnitConversionClass(); double dMetersPerUnit = pCadUnitConverter.ConvertDouble(1, Plan.DistanceUnits, esriCadastralDistanceUnits.esriCDUMeter); IAngularConverter pAngConv = new AngularConverterClass(); Utilities Utils = new Utilities(); List <string> lstAdjustedCourses = new List <string>(); List <string> lstResiduals = new List <string>(); foreach (IVector3D vect in AdjustedTraverse) { pAngConv.SetAngle(vect.Azimuth, esriDirectionType.esriDTNorthAzimuth, esriDirectionUnits.esriDURadians); int iPrec = 7; if (Plan.AngleUnits == esriDirectionUnits.esriDUDegreesMinutesSeconds) { iPrec = 0; } string sBearing = pAngConv.GetString(Plan.DirectionFormat, Plan.AngleUnits, iPrec); string sAdjusted = Utils.FormatDirectionDashesToDegMinSecSymbols(sBearing) + ", " + (vect.Magnitude / dMetersPerUnit).ToString("0.000"); lstAdjustedCourses.Add(sAdjusted); } int i = 0; foreach (IVector3D vect in Traverse) { pAngConv.SetAngle(vect.Azimuth, esriDirectionType.esriDTNorthAzimuth, esriDirectionUnits.esriDURadians); int iPrec = 7; if (Plan.AngleUnits == esriDirectionUnits.esriDUDegreesMinutesSeconds) { iPrec = 0; } string sBearing = pAngConv.GetString(Plan.DirectionFormat, Plan.AngleUnits, iPrec); string sDescription = Utils.FormatDirectionDashesToDegMinSecSymbols(sBearing) + ", " + (vect.Magnitude / dMetersPerUnit).ToString("0.000"); string sDistResidual = ((vect.Magnitude - AdjustedTraverse[i].Magnitude) / dMetersPerUnit).ToString("0.000"); //get the angle difference between the vectors IVector3D vec1 = new Vector3DClass(); vec1.PolarSet(vect.Azimuth, 0, 1); IVector3D vec2 = new Vector3DClass(); vec2.PolarSet(AdjustedTraverse[i].Azimuth, 0, 1); double dAngleDifference = Math.Acos(vec1.DotProduct(vec2)); pAngConv.SetAngle(dAngleDifference, esriDirectionType.esriDTPolar, esriDirectionUnits.esriDURadians); string sAngResidual = pAngConv.GetString(esriDirectionType.esriDTPolar, Plan.AngleUnits, iPrec); sAngResidual = Utils.FormatDirectionDashesToDegMinSecSymbols(sAngResidual); TraverseGrid.Rows.Add(FromToList[i], sDescription, lstAdjustedCourses[i], sAngResidual + ", " + sDistResidual); i++; } }
public IGeometry CreateSphere(IPoint centerPoint, double radius, double minLon = 0.0, double maxLon = 360.0, double minLat = -90.0, double maxLat = 90.0, double stepAngle = 18.0, bool bSmooth = false, bool bFlipS = false, bool bFlipT = false) { IMultiPatch patch = new MultiPatchClass(); IGeometryCollection pGCol = patch as IGeometryCollection; IGeometry2 pGeom; IPoint pt; IPointCollection pStrip; IVector3D pVector = new Vector3DClass(); IEncode3DProperties pGE = new GeometryEnvironmentClass(); double xStep = (maxLon - minLon) / stepAngle; double yStep = (maxLat - minLat) / (stepAngle / 2.0); double lonRange = maxLon - minLon; double latRange = maxLat - minLat; object missing = Type.Missing; double lon = minLon; while (lon < maxLon) { pStrip = new TriangleStripClass(); double lat = minLat; while (lat < maxLat) { double azi = DegreesToRadians(lon); double inc = DegreesToRadians(lat); pVector.PolarSet(-azi, inc, radius); pt = new PointClass(); pt.X = centerPoint.X + pVector.XComponent; pt.Y = centerPoint.Y + pVector.YComponent; pt.Z = centerPoint.Z + pVector.ZComponent; double s = (lon - minLon) / lonRange; if (bFlipS) { s = 1 + (s * -1); } if (s <= 0) { s = 0.001; } else if (s >= 1) { s = 0.999; } double t = (maxLat - lat) / latRange; if (bFlipT) { t = 1 + (t * -1); } if (t <= 0) { t = 0.001; } else if (t >= 1) { t = 0.999; } double m = 0.0; pGE.PackTexture2D(s, t, out m); if (bSmooth) { pVector.Normalize(); pGE.PackNormal(pVector, out m); } pt.M = m; pStrip.AddPoint(pt, ref missing, ref missing); if ((lat != -90) && (lat != 90)) { azi = (lon + xStep) * Math.PI / 180.00; inc = lat * Math.PI / 180.00; pVector.PolarSet(-azi, inc, radius); pt = new PointClass(); pt.X = centerPoint.X + pVector.XComponent; pt.Y = centerPoint.Y + pVector.YComponent; pt.Z = centerPoint.Z + pVector.ZComponent; s = (lon + xStep - minLon) / lonRange; if (bFlipS) { s = 1 + (s * -1); } if (s <= 0) { s = 0.001; } else if (s >= 1) { s = 0.999; } t = (maxLat - lat) / latRange; if (bFlipT) { t = 1 + (t * -1); } if (t <= 0) { t = 0.001; } else if (t >= 1) { t = 0.999; } m = 0.0; pGE.PackTexture2D(s, t, out m); if (bSmooth) { pVector.Normalize(); pGE.PackNormal(pVector, out m); } pt.M = m; pStrip.AddPoint(pt, ref missing, ref missing); } lat = lat + yStep; } pGeom = pStrip as IGeometry2; pGCol.AddGeometry(pGeom, ref missing, ref missing); lon = lon + xStep; } IMAware pMAware = patch as IMAware; pMAware.MAware = true; return(patch); }
protected override void OnClick() { ICadastralEditor pCadEd = (ICadastralEditor)ArcMap.Application.FindExtensionByName("esriCadastralUI.CadastralEditorExtension"); IParcelEditManager pParcEditorMan = (IParcelEditManager)pCadEd; ICadastralPacketManager pCadPacketMan = (ICadastralPacketManager)pCadEd; //bool bStartedWithPacketOpen = pCadPacketMan.PacketOpen; if (pParcEditorMan == null) { return; } IEditor pEd = (IEditor)ArcMap.Application.FindExtensionByName("esri object editor"); if (pEd.EditState == esriEditState.esriStateNotEditing) { MessageBox.Show("Please start editing and try again."); return; } IParcelConstruction pConstr = pParcEditorMan.ParcelConstruction; IParcelConstruction4 pConstr4 = pConstr as IParcelConstruction4; ICadastralPoints pCadastralPts = pConstr4 as ICadastralPoints; ICadastralEditorSettings2 pCadastralEditorSettings2 = pCadEd as ICadastralEditorSettings2; ICadastralFixedPoints pFixedPoints = pCadastralPts as ICadastralFixedPoints; IPointCalculation pPointCalc = new PointCalculationClass(); if (pConstr == null) { return; } IGSLine pParcelLine = null; IMetricUnitConverter pMetricUnitConv = (IMetricUnitConverter)pCadEd; IGSPoint pStartPoint = null; List <int> lstPointIds = new List <int>(); List <IVector3D> Traverse = new List <IVector3D>(); //get rotation here IParcelConstructionData pConstrData = pConstr4.ConstructionData; IConstructionParentParcels pConstructionParentParcels = pConstrData as IConstructionParentParcels; ICadastralUndoRedo pCadUndoRedo = pConstr as ICadastralUndoRedo; try { int iParcelID = -1; if (pConstructionParentParcels.ParentParcelCount > 0) { pConstructionParentParcels.GetParentParcel(0, ref iParcelID); } ICadastralParcel pCadaParcel = pCadPacketMan.JobPacket as ICadastralParcel; IGSParcel pGSParcel = null; if (pCadaParcel != null) { pGSParcel = pCadaParcel.GetParcel(iParcelID); } //if in measurement view then rotation is 0 double TheRotation = 0; if (pGSParcel == null) { pGSParcel = pConstr.Parcel; } if (!pCadastralEditorSettings2.MeasurementView) { TheRotation = pGSParcel.Rotation;//radians } if (TheRotation == 123456789) { TheRotation = 0; } pPointCalc.Rotation = TheRotation; IGSPoint pClosingPoint = null; #region simple method as fall-back bool bUseSimpleStackSelection = false; if (bUseSimpleStackSelection) { //bool bLineSelectionSequence = false; //IGSLine pLastSelectedGSLineInGrid = null; //for (int i = 0; i < pConstr.LineCount; i++) //{ // if (pConstr.GetLineSelection(i)) // { // if (pConstr.GetLine(i, ref pParcelLine)) // { // if (!bLineSelectionSequence) //first line // { // pStartPoint = pCadastralPts.GetPoint(pParcelLine.FromPoint); // pToPoint = pCadastralPts.GetPoint(pParcelLine.ToPoint); // } // pPointCalc.AddLine(pParcelLine); // pLastSelectedGSLineInGrid = pParcelLine; // pToPoint = pCadastralPts.GetPoint(pParcelLine.ToPoint); // lstPointIds.Add(pToPoint.Id); // } // bLineSelectionSequence = true; // double dBear = pParcelLine.Bearing; //Azimuth of IVector3D is north azimuth radians zero degrees north // double dDist = pParcelLine.Distance; // IVector3D vec = new Vector3DClass(); // vec.PolarSet(dBear, 0, dDist); ////Azimuth of IVector3D is north azimuth radians zero degrees north // Traverse.Add(vec); // } // else // { // if (bLineSelectionSequence && pConstr.GetLine(i, ref pParcelLine) && HasLineSelectionAfter(pConstr, i)) // //if there was a prior selection and this line is a complete line, and there is no later selection // { // MessageBox.Show("Please select a continuous set of lines for closure."); // return; // } // } //} //pClosingPoint = pCadastralPts.GetPoint(pLastSelectedGSLineInGrid.ToPoint); } else #endregion {//build a forward star for the selected lines IEnumCELines pCELines = new EnumCELinesClass(); IEnumGSLines pEnumGSLines = (IEnumGSLines)pCELines; ILongArray pLongArray = new LongArrayClass(); int iFirstToNode = -1; for (int i = 0; i < pConstr.LineCount; i++) { if (pConstr.GetLineSelection(i)) { if (pConstr.GetLine(i, ref pParcelLine)) { if (iFirstToNode < 0) { iFirstToNode = pParcelLine.ToPoint; } pLongArray.Add(i); pCELines.Add(pParcelLine); } } } if (pCELines.Count == 0) { MessageBox.Show("No lines selected. Please select a continuous set of lines for closure." + Environment.NewLine + "Line selection should not have branches.", "Traverse"); return; } IParcelLineFunctions3 ParcelLineFx = new ParcelFunctionsClass(); IGSForwardStar pFwdStar = ParcelLineFx.CreateForwardStar(pEnumGSLines); //forward star object is now created for all the selected lines, //need to first re-sequence the lines, and test for branching and discontinuity int iBranches = 0; int iTracedLines = 0; int iLoops = 0; int iTerminals = 0; List <int> LineIDList = new List <int>(); List <int> FromList = new List <int>(); List <int> ToList = new List <int>(); List <string> FromToLine = new List <string>(); bool bTraceSucceeded = TraceLines(ref pFwdStar, iFirstToNode, ref iBranches, ref iTracedLines, ref iLoops, ref iTerminals, ref FromToLine, ref FromList, ref ToList, 0); if (iBranches > 0) { MessageBox.Show("Please select a continuous set of lines for closure." + Environment.NewLine + "Line selection should not have branches.", "Traverse"); return; } if (iTracedLines < pLongArray.Count) { MessageBox.Show("Please select a continuous set of lines for closure." + Environment.NewLine + "Selected Lines should be connected in a single sequence without branches.", "Traverse"); return; } //if it's a single loop check to see if the sequence needs to be reversed //CW or CCW based on bearings if (iLoops == 1) { bool bIsReversed = false; foreach (int i in FromList) { if (i < 0) { bIsReversed = true; } else { bIsReversed = false; break; } } if (bIsReversed) {//all courses are running reversed, so reverse the whole sequence FromToLine.Clear(); FromList.Reverse(); ToList.Reverse(); int iNewFrom = -ToList[ToList.Count - 1]; int iNewTo = -FromList[ToList.Count - 1]; string sNewFromTo = iNewFrom.ToString() + "," + iNewTo.ToString(); FromToLine.Add(sNewFromTo); for (int i = 1; i < ToList.Count; i++) { iNewFrom = -ToList[i - 1]; iNewTo = -FromList[i - 1]; sNewFromTo = iNewFrom.ToString() + "," + iNewTo.ToString(); FromToLine.Add(sNewFromTo); } } } LineIDList.Clear(); FromList.Clear(); ToList.Clear(); pLongArray.RemoveAll(); pCadUndoRedo.StartUndoRedoSession("Adjust Traverse"); if (iLoops == 0) { //re-sequence using TraceLines function based on either end point, because the order of //selected construction lines in grid don't control start or end point FromToLine.Clear(); int iTerminus = -1; iTracedLines = 0; iBranches = 0; iLoops = 0; iTerminals = 0; FindTerminusForSequence(ref pFwdStar, iFirstToNode, ref iTerminus, 0); if (iTerminus == -1) { pCadUndoRedo.WriteUndoRedoSession(false); return; } TraceLines(ref pFwdStar, iTerminus, ref iBranches, ref iTracedLines, ref iLoops, ref iTerminals, ref FromToLine, ref FromList, ref ToList, 0); } List <IVector3D> SequencedTraverse = new List <IVector3D>(); IGSLine pGSLineInPath = null; foreach (string s in FromToLine) { string[] sFromTo = s.Split(','); int iFrom = Convert.ToInt32(sFromTo[0]); int iTo = Convert.ToInt32(sFromTo[1]); bool bReversed = pFwdStar.GetLine(iFrom, iTo, ref pGSLineInPath); if (bReversed) { IGSLine pGSLine180 = new GSLineClass(); pGSLine180.FromPoint = pGSLineInPath.ToPoint; pGSLine180.ToPoint = pGSLineInPath.FromPoint; pGSLine180.Bearing = pGSLineInPath.Bearing + Math.PI; pGSLine180.Distance = pGSLineInPath.Distance; IVector3D vec180 = new Vector3DClass(); vec180.PolarSet(pGSLine180.Bearing, 0, pGSLine180.Distance); //Azimuth of IVector3D is north azimuth radians zero degrees north Traverse.Add(vec180); lstPointIds.Add(pGSLine180.ToPoint); pPointCalc.AddLine(pGSLine180); } else { double dBear = pGSLineInPath.Bearing; double dDist = pGSLineInPath.Distance; IVector3D vec = new Vector3DClass(); vec.PolarSet(dBear, 0, dDist); //Azimuth of IVector3D is north azimuth radians zero degrees north Traverse.Add(vec); lstPointIds.Add(pGSLineInPath.ToPoint); pPointCalc.AddLine(pGSLineInPath); } if (pStartPoint == null) { if (bReversed) { pStartPoint = pCadastralPts.GetPoint(pGSLineInPath.ToPoint); } else { pStartPoint = pCadastralPts.GetPoint(pGSLineInPath.FromPoint); } } if (bReversed) { pClosingPoint = pCadastralPts.GetPoint(pGSLineInPath.FromPoint); } else { pClosingPoint = pCadastralPts.GetPoint(pGSLineInPath.ToPoint); } } } if (pStartPoint == null) { pCadUndoRedo.WriteUndoRedoSession(false); return; } IPoint pStart = new PointClass(); pStart.X = pStartPoint.X; pStart.Y = pStartPoint.Y; string sAdjustMethod = "Compass"; esriParcelAdjustmentType eAdjMethod = esriParcelAdjustmentType.esriParcelAdjustmentCompass; if (pCadastralEditorSettings2.ParcelAdjustment == esriParcelAdjustmentType.esriParcelAdjustmentNone || pCadastralEditorSettings2.ParcelAdjustment == esriParcelAdjustmentType.esriParcelAdjustmentCompass) { eAdjMethod = esriParcelAdjustmentType.esriParcelAdjustmentCompass; } else if (pCadastralEditorSettings2.ParcelAdjustment == esriParcelAdjustmentType.esriParcelAdjustmentCrandall) { sAdjustMethod = "Crandall"; eAdjMethod = pCadastralEditorSettings2.ParcelAdjustment; } else if (pCadastralEditorSettings2.ParcelAdjustment == esriParcelAdjustmentType.esriParcelAdjustmentTransit) { sAdjustMethod = "Transit"; eAdjMethod = pCadastralEditorSettings2.ParcelAdjustment; } pPointCalc.CalculatePoints(eAdjMethod, pStartPoint.Id, pStartPoint, pClosingPoint.Id, pClosingPoint, true); ITraverseClosure pClose = pPointCalc.Closure; List <string> lstCoursesFromTo = new List <string>(); List <IVector3D> AdjustedTraverse = new List <IVector3D>(); double dAdjustedPointX = 0; double dAdjustedPointY = 0; double dPreviousPointX = 0; double dPreviousPointY = 0; for (int i = 0; i < pClose.CourseCount; i++) { IGSPoint pPt = pCadastralPts.GetPoint(lstPointIds[i]); dAdjustedPointY = pPointCalc.GetCalculatedPoint(lstPointIds[i], ref dAdjustedPointX); string sFromTo = ""; IVector3D pAdjustedLine = new Vector3DClass(); if (i == 0) { sFromTo = pStartPoint.Id.ToString() + "-" + lstPointIds[i].ToString(); pAdjustedLine.SetComponents(dAdjustedPointX - pStartPoint.X, dAdjustedPointY - pStartPoint.Y, 0); } else { sFromTo = lstPointIds[i - 1].ToString() + "-" + lstPointIds[i].ToString(); pAdjustedLine.SetComponents(dAdjustedPointX - dPreviousPointX, dAdjustedPointY - dPreviousPointY, 0); } lstCoursesFromTo.Add(sFromTo); IVector3D Z_Axis = new Vector3DClass(); Z_Axis.SetComponents(0, 0, 100); pAdjustedLine.Rotate(TheRotation, Z_Axis); AdjustedTraverse.Add(pAdjustedLine); dPreviousPointX = dAdjustedPointX; dPreviousPointY = dAdjustedPointY; pPt.X = dAdjustedPointX; pPt.Y = dAdjustedPointY; if (!pCadastralEditorSettings2.MeasurementView) { pFixedPoints.SetFixedPoint(lstPointIds[i], true); } } double dMisclosureDistance = pClose.MisclosureDistance; double dMisclosureBearing = pClose.MisclosureDirection; IVector MiscloseVector = new Vector3DClass(); IEditProperties2 pEdProps = pEd as IEditProperties2; IAngularConverter pAngConv = new AngularConverterClass(); pAngConv.SetAngle(dMisclosureBearing, esriDirectionType.esriDTNorthAzimuth, esriDirectionUnits.esriDURadians); //int iPrec = 7; //if (pConstr.Parcel.Plan.AngleUnits == esriDirectionUnits.esriDUDegreesMinutesSeconds) // iPrec = 0; string sMiscloseBearing = pAngConv.GetString(pEdProps.DirectionType, pEdProps.DirectionUnits, pEdProps.AngularUnitPrecision); Utilities UTIL = new Utilities(); string sRatio = "High Accuracy"; if (pClose.RelativeErrorRatio < 10000) { sRatio = "1:" + pClose.RelativeErrorRatio.ToString("0"); } if (dMisclosureDistance >= 0.001) { sMiscloseBearing = UTIL.FormatDirectionDashesToDegMinSecSymbols(sMiscloseBearing); } else { sMiscloseBearing = "----"; } ICadastralUnitConversion pCadUnitConverter = new CadastralUnitConversionClass(); double dMetersPerUnit = pCadUnitConverter.ConvertDouble(1, pConstr.Parcel.Plan.DistanceUnits, esriCadastralDistanceUnits.esriCDUMeter); string sReport = "Closure:" + Environment.NewLine + " error: " + sRatio + Environment.NewLine + " distance: " + (dMisclosureDistance / dMetersPerUnit).ToString("0.000") + Environment.NewLine + " bearing: " + sMiscloseBearing + Environment.NewLine + " xdist: " + (pClose.MisclosureX / dMetersPerUnit).ToString("0.000") + Environment.NewLine + " ydist: " + (pClose.MisclosureY / dMetersPerUnit).ToString("0.000") + Environment.NewLine + " courses: " + (pClose.CourseCount) + Environment.NewLine + Environment.NewLine + "Adjustment:" + Environment.NewLine + " method: " + sAdjustMethod; dlgTraverseResults dlgTraverseResults = new dlgTraverseResults(); AddTraverseInfoToGrid(pConstr.Parcel.Plan, dlgTraverseResults.dataGridView1, Traverse, AdjustedTraverse, lstCoursesFromTo); dlgTraverseResults.txtMiscloseReport.Text = sReport; DialogResult dRes = dlgTraverseResults.ShowDialog(); if (dRes == DialogResult.Cancel) { //since we cancelled, set the points back foreach (int i in lstPointIds) { pFixedPoints.SetFixedPoint(i, false); } pCadUndoRedo.WriteUndoRedoSession(false); } else { pCadUndoRedo.WriteUndoRedoSession(true); } } catch (Exception ex) { MessageBox.Show(ex.Message + Environment.NewLine + "Line number:" + ex.LineNumber().ToString() + " in " + ex.TargetSite.Name, "Traverse"); pCadUndoRedo.WriteUndoRedoSession(false); } }
protected override void OnClick() { IEditor pEd = (IEditor)ArcMap.Editor; IEditor2 pEd2 = (IEditor2)ArcMap.Editor; IEditProperties pEdProps1 = pEd as IEditProperties; IEditProperties2 pEdProps2 = pEd as IEditProperties2; IEditSketch2 pSketch2 = ArcMap.Editor as IEditSketch2; ISegmentCollection pSegColl = pSketch2.Geometry as ISegmentCollection; double dLineDirection = 0; ISketchTool sketchTool = ArcMap.Application.CurrentTool.Command as ISketchTool; if (sketchTool.Constraint == esriSketchConstraint.esriConstraintAngle) { dLineDirection = sketchTool.AngleConstraint; } else { ILine pRubberBandLine = new LineClass(); pRubberBandLine.PutCoords(pSketch2.LastPoint, pEd2.Location); dLineDirection = pRubberBandLine.Angle; } IAngularConverter pAngConv = new AngularConverterClass(); pAngConv.SetAngle(dLineDirection, esriDirectionType.esriDTPolar, esriDirectionUnits.esriDURadians); int iSegCnt = pSegColl.SegmentCount; dlgSpiralParameters SpiralEntryDialog = new dlgSpiralParameters(); string sBearing = pAngConv.GetString(pEdProps2.DirectionType, pEdProps2.DirectionUnits, pEdProps2.AngularUnitPrecision); SpiralEntryDialog.txtDirection.Text = sBearing; //Display the dialog DialogResult pDialogResult = SpiralEntryDialog.ShowDialog(); esriCurveDensifyMethod DensifyMethod = esriCurveDensifyMethod.esriCurveDensifyByAngle; //default double dDensifyParameter = 2 * Math.PI / 180; //2 degrees //default if (SpiralEntryDialog.optCustomDensification.Checked) { DensifyMethod = (esriCurveDensifyMethod)SpiralEntryDialog.cboDensificationType.SelectedIndex; if (DensifyMethod == esriCurveDensifyMethod.esriCurveDensifyByAngle) { dDensifyParameter = Convert.ToDouble(SpiralEntryDialog.numAngleDensification.Value) * Math.PI / 180; } else { if (!Double.TryParse(SpiralEntryDialog.txtDensifyValue.Text, out dDensifyParameter)) { dDensifyParameter = 2; } } } if (pDialogResult != DialogResult.OK) { return; } if (SpiralEntryDialog.txtStartRadius.Text.ToLower().Trim() == "infinity" && SpiralEntryDialog.txtEndRadius.Text.ToLower().Trim() == "infinity") { return; } double dSpiralRadius1 = Double.MaxValue; //default to infinity double dFromCurvature = 0; if (SpiralEntryDialog.txtStartRadius.Text.ToLower() != "infinity") { if (Double.TryParse(SpiralEntryDialog.txtStartRadius.Text, out dSpiralRadius1)) { dFromCurvature = 1 / dSpiralRadius1; } else { return; } } double dSpiralRadius2 = Double.MaxValue; //default to infinity double dToCurvature = 0; if (SpiralEntryDialog.txtEndRadius.Text.ToLower() != "infinity") { if (Double.TryParse(SpiralEntryDialog.txtEndRadius.Text, out dSpiralRadius2)) { dToCurvature = 1 / dSpiralRadius2; } else { return; } } bool bIsCCW = (dSpiralRadius1 > dSpiralRadius2) ? SpiralEntryDialog.optRight.Checked : SpiralEntryDialog.optLeft.Checked; bool bSpecialCaseCircularArc = (dSpiralRadius1 == dSpiralRadius2); if (!pAngConv.SetString(SpiralEntryDialog.txtDirection.Text, pEdProps2.DirectionType, pEdProps2.DirectionUnits)) { return; } double dNorthAzimuthRadians = pAngConv.GetAngle(esriDirectionType.esriDTNorthAzimuth, esriDirectionUnits.esriDURadians); IVector3D pVec = new Vector3DClass(); pVec.PolarSet(dNorthAzimuthRadians, 0, 500); IPoint pTangentPoint = new PointClass(); pTangentPoint.PutCoords(pSketch2.LastPoint.X + pVec.XComponent, pSketch2.LastPoint.Y + pVec.YComponent); //double dStreamingTol = pEdProps1.StreamTolerance; //if (dStreamingTol == 0) // dStreamingTol = 0.001 * 5000; //metric //double dSpiralOffsetGeometryPrecision = 0.001 * 250; //metric 0.25 m IPolyline6 theSpiralPolyLine = null; double dExitTangent = 0; if (SpiralEntryDialog.cboPathLengthParameter.SelectedIndex == 0) { double dSpiralArcLength; if (!Double.TryParse(SpiralEntryDialog.txtPathLengthParameter.Text, out dSpiralArcLength)) { return; } if (bSpecialCaseCircularArc) { ILine pInTangentLine = new LineClass(); pInTangentLine.PutCoords(pSketch2.LastPoint, pTangentPoint); ISegment pTangentSegment = (ISegment)pInTangentLine; IConstructCircularArc2 pCircArcConstr = new ESRI.ArcGIS.Geometry.CircularArcClass() as IConstructCircularArc2; pCircArcConstr.ConstructTangentRadiusArc(pTangentSegment, false, bIsCCW, dSpiralRadius1, dSpiralArcLength); ICircularArc pArcSegment = pCircArcConstr as ICircularArc; //Get chord Line from tangent curve constructor ILine pChordLine = new LineClass(); pChordLine.PutCoords(pArcSegment.FromPoint, pArcSegment.ToPoint); double dPolarRadians = pChordLine.Angle; //to get the chord azimuth pCircArcConstr.ConstructBearingRadiusArc(pSketch2.LastPoint, dPolarRadians, bIsCCW, dSpiralRadius1, dSpiralArcLength); dExitTangent = pArcSegment.ToAngle + Math.PI / 2; ISegmentCollection segCollection = new PolylineClass() as ISegmentCollection; object obj = Type.Missing; segCollection.AddSegment((ISegment)pArcSegment, ref obj, ref obj); theSpiralPolyLine = segCollection as IPolyline6; } else { theSpiralPolyLine = ConstructSpiralbyLength(pSketch2.LastPoint, pTangentPoint, dFromCurvature, dToCurvature, bIsCCW, dSpiralArcLength, DensifyMethod, dDensifyParameter, out dExitTangent); } } if (SpiralEntryDialog.cboPathLengthParameter.SelectedIndex == 1) { if (!pAngConv.SetString(SpiralEntryDialog.txtPathLengthParameter.Text, esriDirectionType.esriDTPolar, pEdProps2.DirectionUnits)) { return; } double dSpiralDeltaAngle = pAngConv.GetAngle(esriDirectionType.esriDTPolar, esriDirectionUnits.esriDURadians); if (bSpecialCaseCircularArc) { ILine pInTangentLine = new LineClass(); pInTangentLine.PutCoords(pSketch2.LastPoint, pTangentPoint); ISegment pTangentSegment = (ISegment)pInTangentLine; IConstructCircularArc2 pCircArcConstr = new ESRI.ArcGIS.Geometry.CircularArcClass() as IConstructCircularArc2; pCircArcConstr.ConstructTangentRadiusAngle(pTangentSegment, false, bIsCCW, dSpiralRadius1, dSpiralDeltaAngle); ICircularArc pArcSegment = pCircArcConstr as ICircularArc; //Get chord Line from tangent curve constructor ILine pChordLine = new LineClass(); pChordLine.PutCoords(pArcSegment.FromPoint, pArcSegment.ToPoint); double dPolarRadians = pChordLine.Angle; //to get the chord azimuth pCircArcConstr.ConstructBearingRadiusAngle(pSketch2.LastPoint, dPolarRadians, bIsCCW, dSpiralRadius1, dSpiralDeltaAngle); dExitTangent = pArcSegment.ToAngle + Math.PI / 2; ISegmentCollection segCollection = new PolylineClass() as ISegmentCollection; object obj = Type.Missing; segCollection.AddSegment((ISegment)pArcSegment, ref obj, ref obj); theSpiralPolyLine = segCollection as IPolyline6; } else { theSpiralPolyLine = ConstructSpiralbyDeltaAngle(pSketch2.LastPoint, pTangentPoint, dFromCurvature, dToCurvature, bIsCCW, dSpiralDeltaAngle, DensifyMethod, dDensifyParameter, out dExitTangent); } } if (theSpiralPolyLine == null) { MessageBox.Show("A spiral could not be created with the entered parameters."); return; } ISegmentCollection pSpiralSegCollection = theSpiralPolyLine as ISegmentCollection; //Start a sketch operation and insert the new envelope into the sketch ISketchOperation2 sketchOp = new SketchOperationClass(); sketchOp.Start(ArcMap.Editor); sketchOp.MenuString = "Add Spiral"; pSegColl.AddSegmentCollection(pSpiralSegCollection); IGeometry geom = pSegColl as IGeometry; pSketch2.Geometry = geom; //set the angle constraint to the exit tangent of the spiral sketchTool.Constraint = esriSketchConstraint.esriConstraintAngle; sketchTool.AngleConstraint = dExitTangent; sketchOp.Finish(ArcMap.Document.ActiveView.Extent, esriSketchOperationType.esriSketchOperationGeneral, null); }
private bool TraceLines(ref IGSForwardStar FwdStar, int StartNodeId, ref int BranchCount, ref int TracedLinesCount, ref int LoopCount, ref int TerminusCount, ref List <string> FromToLine, ref List <int> FromList, ref List <int> ToList, int iInfinityChecker) { iInfinityChecker++; if (iInfinityChecker > 5000) { return(false); } //(This is a self-calling function.) In this context 5000 downstream lines is like infinity, //so exit gracefully, and avoid probable endless loop. //Possible cause of endless loop? Corrupted data; example, a line with the same from and to point id IVector3D vect = new Vector3DClass(); try { ILongArray iLngArr = FwdStar.get_ToNodes(StartNodeId); //get_ToNodes returns an array of radiated points, not "TO" points in the fabric data model sense int iCnt2 = 0; iCnt2 = iLngArr.Count; if (iCnt2 == 1) { TerminusCount++; } IGSLine pGSLine = null; for (int i = 0; i < iCnt2; i++) { int i2 = iLngArr.get_Element(i); string sFromTo = StartNodeId.ToString() + "," + i2.ToString(); string sToFrom = i2.ToString() + "," + StartNodeId.ToString(); if (FromToLine.Contains(sFromTo) || FromToLine.Contains(sToFrom)) { if (FromToLine.Contains(sFromTo)) { LoopCount++; } continue; } if (iCnt2 > 2) { BranchCount++; } TracedLinesCount++; FromToLine.Add(StartNodeId.ToString() + "," + i2.ToString()); bool bIsReversed = FwdStar.GetLine(StartNodeId, i2, ref pGSLine); if (bIsReversed) { FromList.Add(-StartNodeId); ToList.Add(-i2); vect.PolarSet(pGSLine.Bearing + Math.PI, 0, pGSLine.Distance); //Azimuth of IVector3D is north azimuth radians zero degrees north } else { FromList.Add(StartNodeId); ToList.Add(i2); vect.PolarSet(pGSLine.Bearing, 0, pGSLine.Distance); //Azimuth of IVector3D is north azimuth radians zero degrees north } if (!TraceLines(ref FwdStar, i2, ref BranchCount, ref TracedLinesCount, ref LoopCount, ref TerminusCount, ref FromToLine, ref FromList, ref ToList, iInfinityChecker)) { return(false); } } return(true); } catch { return(false); } }
public bool HasTangentCurveMatchFeatures(IFeatureClass FeatureClass, IPolycurve inPolycurve, string WhereClause, double AngleToleranceTangentCompareInDegrees, double StraightLinesBreakLessThanInDegrees, double MaximumDeltaInDegrees, double ExcludeTangentsShorterThan, out int outFoundTangentCurvesCount, ref List<string> CurveInfoFromNeighbours) { outFoundTangentCurvesCount = 0; ILine pOriginalChord = new Line(); pOriginalChord.PutCoords(inPolycurve.FromPoint, inPolycurve.ToPoint); IVector3D vecOriginalSelected = new Vector3DClass(); vecOriginalSelected.PolarSet(pOriginalChord.Angle, 0, 1); int idxRadius = FeatureClass.FindField("RADIUS"); if (idxRadius == -1) return false; int idxCenterPointID = FeatureClass.FindField("CENTERPOINTID"); if (idxCenterPointID == -1) return false; object val = null; IGeometryBag pGeomBag = new GeometryBagClass(); IGeometryCollection pGeomColl = (IGeometryCollection)pGeomBag; IGeometry MultiPartPolyLine = new PolylineClass(); //qi IGeoDataset pGeoDS = (IGeoDataset)FeatureClass; ISpatialReference spatialRef = pGeoDS.SpatialReference; MultiPartPolyLine.SpatialReference = spatialRef; IGeometryCollection geometryCollection2 = MultiPartPolyLine as IGeometryCollection; ILine pTangentLineAtEnd = new Line(); //new ILine pTangentLineAtStart = new Line(); //new object objMissing = Type.Missing; for (int i = 0; i < 2; i++) { ILine pThisLine = null; if (i == 0) { inPolycurve.QueryTangent(esriSegmentExtension.esriExtendAtTo, 1.0, true, 0.2, pTangentLineAtEnd); pThisLine = new Line(); pThisLine.PutCoords(pTangentLineAtEnd.FromPoint, pTangentLineAtEnd.ToPoint); pGeomColl.AddGeometry(pThisLine); } else { inPolycurve.QueryTangent(esriSegmentExtension.esriExtendAtFrom, 0.0, true, 0.2, pTangentLineAtStart); pThisLine = new Line(); pThisLine.PutCoords(pTangentLineAtStart.FromPoint, pTangentLineAtStart.ToPoint); pGeomColl.AddGeometry(pThisLine); } //Create a new path for each line. ISegmentCollection newPath = new PathClass(); newPath.AddSegment((ISegment)pThisLine, ref objMissing, ref objMissing); //The spatial reference associated with geometryCollection will be assigned to all incoming paths and segments. geometryCollection2.AddGeometry(newPath as IGeometry, ref objMissing, ref objMissing); } //now buffer the lines IGeometryCollection outBufferedGeometryCol = new GeometryBagClass(); for (int jj = 0; jj < geometryCollection2.GeometryCount; jj++) { IPath pPath = geometryCollection2.get_Geometry(jj) as IPath; IGeometryCollection pPolyL = new PolylineClass(); pPolyL.AddGeometry((IGeometry)pPath); ITopologicalOperator topologicalOperator = (ITopologicalOperator)pPolyL; IPolygon pBuffer = topologicalOperator.Buffer(0.1) as IPolygon; outBufferedGeometryCol.AddGeometry(pBuffer, ref objMissing, ref objMissing); } ITopologicalOperator pUnionedBuffers = null; pUnionedBuffers = new PolygonClass() as ITopologicalOperator; pUnionedBuffers.ConstructUnion((IEnumGeometry)outBufferedGeometryCol); ISpatialFilter pSpatFilt = new SpatialFilter(); pSpatFilt.WhereClause = WhereClause; pSpatFilt.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects; pSpatFilt.SearchOrder = esriSearchOrder.esriSearchOrderSpatial; pSpatFilt.Geometry = (IGeometry)pUnionedBuffers; IFeatureCursor pFeatCursLines = null; try { pFeatCursLines = FeatureClass.Search(pSpatFilt, false); } catch (Exception ex) { MessageBox.Show(ex.Message); return false; } IVector3D vecFoundGeom = new Vector3DClass(); IFeature pFeat = pFeatCursLines.NextFeature(); bool bHasTangentStraightLineAtJunction = false; List<int> lstLargeBreak = new List<int>(); while (pFeat != null) { IGeometry pFoundLineGeom = pFeat.ShapeCopy; IPolycurve pFoundLineAsPolyCurve = pFoundLineGeom as IPolycurve; int iRelativeOrientation = GetRelativeOrientation(pFoundLineAsPolyCurve, inPolycurve); //iRelativeOrientation == 1 --> closest points are original TO and found TO //iRelativeOrientation == 2 --> closest points are original TO and found FROM //iRelativeOrientation == 3 --> closest points are original FROM and found TO //iRelativeOrientation == 4 --> closest points are original FROM and found FROM //if the feature has no radius attribute, skip. double dRadius = 0; int iCtrPoint = -1; val = pFeat.get_Value(idxRadius); if (val == DBNull.Value) dRadius = 0; else dRadius = (double)val; val = pFeat.get_Value(idxCenterPointID); IPolycurve pPolyCurve = pFoundLineGeom as IPolycurve; ILine pFoundChordCandidate = new LineClass(); pFoundChordCandidate.PutCoords(pPolyCurve.FromPoint, pPolyCurve.ToPoint); //first check for liklihood that subject line is supposed to stay straight, by //geometry chord bearing angle break test vecFoundGeom.PolarSet(pFoundChordCandidate.Angle, 0, 1); double dDotProd = vecFoundGeom.DotProduct(vecOriginalSelected); double dAngleCheck = Math.Acos(dDotProd) * 180 / Math.PI; //in degrees dAngleCheck = Math.Abs(dAngleCheck); double dLargeAngleBreakInDegrees = 3; if (dAngleCheck > dLargeAngleBreakInDegrees && dAngleCheck < (180 - dLargeAngleBreakInDegrees)) //large angle break non-tangent, greater than 3 degrees { if (!lstLargeBreak.Contains(iRelativeOrientation)) lstLargeBreak.Add(iRelativeOrientation); } if ((dAngleCheck <= StraightLinesBreakLessThanInDegrees || (180 - dAngleCheck) < StraightLinesBreakLessThanInDegrees) && val == DBNull.Value && dRadius == 0 && !(pPolyCurve.Length< ExcludeTangentsShorterThan)) { if (lstLargeBreak.Contains(iRelativeOrientation)) bHasTangentStraightLineAtJunction = true; } if (val == DBNull.Value || dRadius == 0 || pPolyCurve.Length< ExcludeTangentsShorterThan) {//if the feature has a null centrpointID then skip. Marshal.ReleaseComObject(pFeat); pFeat = pFeatCursLines.NextFeature(); continue; } if (Math.Abs(inPolycurve.Length / dRadius * 180 / Math.PI) > MaximumDeltaInDegrees) { //if the resulting curve would have a central angle more than MaximumDeltaInDegrees degrees then skip Marshal.ReleaseComObject(pFeat); pFeat = pFeatCursLines.NextFeature(); continue; } iCtrPoint = (int)val; //if geometry of curve neighbour curves have been cracked then there can be more than one segment //however since all segments would be circular arcs, just need to test the first segment ISegmentCollection pFoundLineGeomSegs = pFoundLineGeom as ISegmentCollection; ISegment pSeg = pFoundLineGeomSegs.get_Segment(0); if (!(pSeg is ICircularArc)) { Marshal.ReleaseComObject(pFeat); pFeat = pFeatCursLines.NextFeature(); continue; } dRadius = (double)pFeat.get_Value(idxRadius); IVector3D vect1 = new Vector3DClass(); IVector3D vect2 = new Vector3DClass(); ILine tang = new Line(); double dUnitSignChange = 1; if (iRelativeOrientation == 1) //closest points are original TO and found TO { dUnitSignChange = -1; vect1.PolarSet(pTangentLineAtEnd.Angle, 0, 1); pFoundLineAsPolyCurve.QueryTangent(esriSegmentExtension.esriExtendAtTo, 1.0, true, 1, tang); vect2.PolarSet(tang.Angle, 0, 1); } else if (iRelativeOrientation == 2)//closest points are original TO and found FROM { vect1.PolarSet(pTangentLineAtEnd.Angle, 0, 1); pFoundLineAsPolyCurve.QueryTangent(esriSegmentExtension.esriExtendAtFrom, 0.0, true, 1, tang); vect2.PolarSet(tang.Angle, 0, 1); } else if (iRelativeOrientation == 3)//closest points are original FROM and found TO { vect1.PolarSet(pTangentLineAtStart.Angle, 0, 1); pFoundLineAsPolyCurve.QueryTangent(esriSegmentExtension.esriExtendAtTo, 1.0, true, 1, tang); vect2.PolarSet(tang.Angle, 0, 1); } else if (iRelativeOrientation == 4)//closest points are original FROM and found FROM { dUnitSignChange = -1; vect1.PolarSet(pTangentLineAtStart.Angle, 0, 1); pFoundLineAsPolyCurve.QueryTangent(esriSegmentExtension.esriExtendAtFrom, 0.0, true, 1, tang); vect2.PolarSet(tang.Angle, 0, 1); } dDotProd = vect1.DotProduct(vect2); dAngleCheck = Math.Acos(dDotProd) * 180 / Math.PI; //in degrees dAngleCheck = Math.Abs(dAngleCheck); if (dAngleCheck < AngleToleranceTangentCompareInDegrees || (180 - dAngleCheck) < AngleToleranceTangentCompareInDegrees) { double dDerivedRadius = dRadius * dUnitSignChange; string sHarvestedCurveInfo = pFeat.OID.ToString() + "," + dDerivedRadius.ToString("#.000") + "," + iCtrPoint.ToString() + "," + "t"; CurveInfoFromNeighbours.Add(sHarvestedCurveInfo); outFoundTangentCurvesCount++; } Marshal.ReleaseComObject(pFeat); pFeat = pFeatCursLines.NextFeature(); } Marshal.FinalReleaseComObject(pFeatCursLines); if (bHasTangentStraightLineAtJunction) return false; //open to logic change to be less conservative bool bHasParallelCurveFeaturesNearby = (outFoundTangentCurvesCount > 0); return bHasParallelCurveFeaturesNearby; }
public bool HasParallelCurveMatchFeatures(IFeatureClass FeatureClass, IPolycurve inPolycurve, string WhereClause, double AngleToleranceTangentCompareInDegrees, double OrthogonalSearchDistance, out int outFoundLinesCount, out int outFoundParallelCurvesCount, ref List<string> CurveInfoFromNeighbours) { outFoundLinesCount = 0; outFoundParallelCurvesCount = 0; ILine pOriginalChord = new Line(); pOriginalChord.PutCoords(inPolycurve.FromPoint, inPolycurve.ToPoint); IVector3D vecOriginalSelected = new Vector3DClass(); vecOriginalSelected.PolarSet(pOriginalChord.Angle, 0, 1); int idxRadius = FeatureClass.FindField("RADIUS"); if (idxRadius == -1) return false; int idxCenterPointID = FeatureClass.FindField("CENTERPOINTID"); if (idxCenterPointID == -1) return false; object val = null; IGeometryBag pGeomBag = new GeometryBagClass(); IGeometryCollection pGeomColl = (IGeometryCollection)pGeomBag; IGeometry MultiPartPolyLine = new PolylineClass(); //qi IGeoDataset pGeoDS = (IGeoDataset)FeatureClass; ISpatialReference spatialRef = pGeoDS.SpatialReference; MultiPartPolyLine.SpatialReference = spatialRef; IGeometryCollection geometryCollection2 = MultiPartPolyLine as IGeometryCollection; ILine pNormalLine = new Line(); //new for (int i = -1; i < 2; i = i + 2) { double dOffset = OrthogonalSearchDistance * i; inPolycurve.QueryNormal(esriSegmentExtension.esriNoExtension, 0.5, true, dOffset, pNormalLine); ILine pThisLine = new Line(); pThisLine.PutCoords(pNormalLine.FromPoint, pNormalLine.ToPoint); pGeomColl.AddGeometry(pThisLine); //Although each line is connected to the other, create a new path for each line //this allows for future changes in case the input needs to be altered to separate paths. ISegmentCollection newPath = new PathClass(); object obj = Type.Missing; newPath.AddSegment((ISegment)pThisLine, ref obj, ref obj); //The spatial reference associated with geometryCollection will be assigned to all incoming paths and segments. geometryCollection2.AddGeometry(newPath as IGeometry, ref obj, ref obj); } ISpatialFilter pSpatFilt = new SpatialFilter(); pSpatFilt.WhereClause = WhereClause; pSpatFilt.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects; pSpatFilt.SearchOrder = esriSearchOrder.esriSearchOrderSpatial; pSpatFilt.Geometry = pGeomBag; IFeatureCursor pFeatCursLines = null; try { pFeatCursLines = FeatureClass.Search(pSpatFilt, false); } catch (Exception ex) { MessageBox.Show(ex.Message); return false; } IFeature pFeat = pFeatCursLines.NextFeature(); while (pFeat != null) { IGeometry pFoundLineGeom = pFeat.ShapeCopy; //if the feature has no radius attribute, skip. double dRadius = 0; int iCtrPoint = -1; val = pFeat.get_Value(idxRadius); if (val == DBNull.Value) dRadius = 0; else dRadius = (double)val; if (dRadius == 0) {//null or zero radius so skip. Marshal.ReleaseComObject(pFeat); pFeat = pFeatCursLines.NextFeature(); continue; } val = pFeat.get_Value(idxCenterPointID); if (val == DBNull.Value) {//null centrpointID so skip. Marshal.ReleaseComObject(pFeat); pFeat = pFeatCursLines.NextFeature(); continue; } iCtrPoint = (int)val; ITopologicalOperator6 pTopoOp6 = (ITopologicalOperator6)MultiPartPolyLine; IGeometry pResultGeom = pTopoOp6.IntersectEx(pFoundLineGeom, false, esriGeometryDimension.esriGeometry0Dimension); if (pResultGeom == null) { Marshal.ReleaseComObject(pFeat); pFeat = pFeatCursLines.NextFeature(); continue; } if (pResultGeom.IsEmpty) { Marshal.ReleaseComObject(pFeat); pFeat = pFeatCursLines.NextFeature(); continue; } ISegmentCollection pFoundLineGeomSegs = pFoundLineGeom as ISegmentCollection; bool bHasCurves = false; pFoundLineGeomSegs.HasNonLinearSegments(ref bHasCurves); if (!bHasCurves) { Marshal.ReleaseComObject(pFeat); pFeat = pFeatCursLines.NextFeature(); continue; } IPointCollection5 PtColl = (IPointCollection5)pResultGeom; if (PtColl.PointCount > 1) { Marshal.ReleaseComObject(pFeat); pFeat = pFeatCursLines.NextFeature(); continue; } IPolycurve pPolyCurve4Tangent = pFoundLineGeom as IPolycurve; for (int j = 0; j < PtColl.PointCount; j++) { IPoint p = PtColl.get_Point(j); IPoint outPoint = new Point(); double dDistanceAlong = 0; double dDistanceFromCurve = 0; bool bOffsetRight = true; //work out if the point is to the left or right of the original inPolycurve.QueryPointAndDistance(esriSegmentExtension.esriNoExtension, p, false, outPoint, ref dDistanceAlong, ref dDistanceFromCurve, ref bOffsetRight); ILine pTangent = new Line(); dDistanceAlong = 0; dDistanceFromCurve = 0; bool bOnRight = true; pPolyCurve4Tangent.QueryPointAndDistance(esriSegmentExtension.esriNoExtension, p, false, outPoint, ref dDistanceAlong, ref dDistanceFromCurve, ref bOnRight); pPolyCurve4Tangent.QueryTangent(esriSegmentExtension.esriNoExtension, dDistanceAlong, false, 100, pTangent); //compare the tangent bearing with the normal to check for orthogonality IVector3D vecTangent = new Vector3DClass(); vecTangent.PolarSet(pTangent.Angle, 0, 1); IVector3D vecNormal = new Vector3DClass(); vecNormal.PolarSet(pNormalLine.Angle, 0, 1); ILine pHitDistanceForRadiusDifference = new Line(); pHitDistanceForRadiusDifference.PutCoords(pNormalLine.FromPoint, outPoint); double dRadiusDiff = pHitDistanceForRadiusDifference.Length; double dDotProd = vecTangent.DotProduct(vecNormal); double dAngleCheck = Math.Acos(dDotProd) * 180 / Math.PI; //in degrees dAngleCheck = Math.Abs(dAngleCheck - 90); if (dAngleCheck < AngleToleranceTangentCompareInDegrees) { //work out concavity orientation with respect to the original line using the radius sign and dot product dDotProd = vecOriginalSelected.DotProduct(vecTangent); double dTangentCheck = Math.Acos(dDotProd) * 180 / Math.PI; // in degrees //dTangentCheck at this point should be close to 0 or 180 degrees. outFoundLinesCount++; bool bIsConvex = ((dTangentCheck < 90 && dRadius < 0 && !bOffsetRight) || (dTangentCheck > 90 && dRadius > 0 && !bOffsetRight) || (dTangentCheck < 90 && dRadius > 0 && bOffsetRight) || (dTangentCheck > 90 && dRadius < 0 && bOffsetRight)); double dUnitSignChange = 1; if (!bIsConvex) dUnitSignChange = -1; double dDerivedRadius = (Math.Abs(dRadius)) + dRadiusDiff * dUnitSignChange; dUnitSignChange = 1; //now compute inferred left/right for candidate if (bIsConvex && !bOffsetRight) dUnitSignChange = -1; if (!bIsConvex && bOffsetRight) dUnitSignChange = -1; dDerivedRadius = dDerivedRadius * dUnitSignChange; string sHarvestedCurveInfo = pFeat.OID.ToString() + "," + dDerivedRadius.ToString("#.000") + "," + iCtrPoint.ToString() + "," + dRadiusDiff.ToString("#.000"); CurveInfoFromNeighbours.Add(sHarvestedCurveInfo); } } Marshal.ReleaseComObject(pFeat); pFeat = pFeatCursLines.NextFeature(); } Marshal.FinalReleaseComObject(pFeatCursLines); bool bHasParallelCurveFeaturesNearby = (outFoundLinesCount > 0); return bHasParallelCurveFeaturesNearby; }
protected void AddTraverseInfoToGrid(IGSPlan Plan, DataGridView TraverseGrid, List<IVector3D> Traverse, List<IVector3D> AdjustedTraverse, List<string> FromToList) { ICadastralUnitConversion pCadUnitConverter = new CadastralUnitConversionClass(); double dMetersPerUnit = pCadUnitConverter.ConvertDouble(1, Plan.DistanceUnits, esriCadastralDistanceUnits.esriCDUMeter); IAngularConverter pAngConv = new AngularConverterClass(); Utilities Utils = new Utilities(); List<string> lstAdjustedCourses = new List<string>(); List<string> lstResiduals = new List<string>(); foreach (IVector3D vect in AdjustedTraverse) { pAngConv.SetAngle(vect.Azimuth, esriDirectionType.esriDTNorthAzimuth, esriDirectionUnits.esriDURadians); int iPrec = 7; if (Plan.AngleUnits == esriDirectionUnits.esriDUDegreesMinutesSeconds) iPrec = 0; string sBearing = pAngConv.GetString(Plan.DirectionFormat, Plan.AngleUnits, iPrec); string sAdjusted = Utils.FormatDirectionDashesToDegMinSecSymbols(sBearing) + ", " + (vect.Magnitude / dMetersPerUnit).ToString("0.000"); lstAdjustedCourses.Add(sAdjusted); } int i = 0; foreach (IVector3D vect in Traverse) { pAngConv.SetAngle(vect.Azimuth, esriDirectionType.esriDTNorthAzimuth, esriDirectionUnits.esriDURadians); int iPrec = 7; if(Plan.AngleUnits == esriDirectionUnits.esriDUDegreesMinutesSeconds) iPrec=0; string sBearing = pAngConv.GetString(Plan.DirectionFormat, Plan.AngleUnits, iPrec); string sDescription = Utils.FormatDirectionDashesToDegMinSecSymbols(sBearing) + ", " + (vect.Magnitude/dMetersPerUnit).ToString("0.000"); string sDistResidual= ((vect.Magnitude-AdjustedTraverse[i].Magnitude)/dMetersPerUnit).ToString("0.000"); //get the angle difference between the vectors IVector3D vec1 = new Vector3DClass(); vec1.PolarSet(vect.Azimuth, 0, 1); IVector3D vec2 = new Vector3DClass(); vec2.PolarSet(AdjustedTraverse[i].Azimuth, 0, 1); double dAngleDifference = Math.Acos(vec1.DotProduct(vec2)); pAngConv.SetAngle(dAngleDifference, esriDirectionType.esriDTPolar, esriDirectionUnits.esriDURadians); string sAngResidual = pAngConv.GetString(esriDirectionType.esriDTPolar, Plan.AngleUnits, iPrec); sAngResidual = Utils.FormatDirectionDashesToDegMinSecSymbols(sAngResidual); TraverseGrid.Rows.Add(FromToList[i], sDescription, lstAdjustedCourses[i], sAngResidual + ", " + sDistResidual); i++; } }
private bool TraceLines(ref IGSForwardStar FwdStar, int StartNodeId, ref int BranchCount, ref int TracedLinesCount, ref int LoopCount, ref int TerminusCount, ref List<string> FromToLine, ref List<int> FromList, ref List<int> ToList, int iInfinityChecker) { iInfinityChecker++; if (iInfinityChecker > 5000) return false; //(This is a self-calling function.) In this context 5000 downstream lines is like infinity, //so exit gracefully, and avoid probable endless loop. //Possible cause of endless loop? Corrupted data; example, a line with the same from and to point id IVector3D vect = new Vector3DClass(); try { ILongArray iLngArr = FwdStar.get_ToNodes(StartNodeId); //get_ToNodes returns an array of radiated points, not "TO" points in the fabric data model sense int iCnt2 = 0; iCnt2 = iLngArr.Count; if (iCnt2 == 1) TerminusCount++; IGSLine pGSLine = null; for (int i = 0; i < iCnt2; i++) { int i2 = iLngArr.get_Element(i); string sFromTo = StartNodeId.ToString() + "," + i2.ToString(); string sToFrom = i2.ToString() + "," + StartNodeId.ToString(); if (FromToLine.Contains(sFromTo) || FromToLine.Contains(sToFrom)) { if (FromToLine.Contains(sFromTo)) LoopCount++; continue; } if (iCnt2 > 2) BranchCount++; TracedLinesCount++; FromToLine.Add(StartNodeId.ToString() + "," + i2.ToString()); bool bIsReversed = FwdStar.GetLine(StartNodeId, i2, ref pGSLine); if (bIsReversed) { FromList.Add(-StartNodeId); ToList.Add(-i2); vect.PolarSet(pGSLine.Bearing + Math.PI, 0, pGSLine.Distance); //Azimuth of IVector3D is north azimuth radians zero degrees north } else { FromList.Add(StartNodeId); ToList.Add(i2); vect.PolarSet(pGSLine.Bearing, 0, pGSLine.Distance); //Azimuth of IVector3D is north azimuth radians zero degrees north } if (!TraceLines(ref FwdStar, i2, ref BranchCount, ref TracedLinesCount,ref LoopCount, ref TerminusCount, ref FromToLine,ref FromList, ref ToList, iInfinityChecker)) return false; } return true; } catch { return false; } }
protected override void OnClick() { ICadastralEditor pCadEd = (ICadastralEditor)ArcMap.Application.FindExtensionByName("esriCadastralUI.CadastralEditorExtension"); IParcelEditManager pParcEditorMan = (IParcelEditManager)pCadEd; ICadastralPacketManager pCadPacketMan = (ICadastralPacketManager)pCadEd; //bool bStartedWithPacketOpen = pCadPacketMan.PacketOpen; if (pParcEditorMan == null) return; IEditor pEd = (IEditor)ArcMap.Application.FindExtensionByName("esri object editor"); if (pEd.EditState == esriEditState.esriStateNotEditing) { MessageBox.Show("Please start editing and try again."); return; } IParcelConstruction pConstr = pParcEditorMan.ParcelConstruction; IParcelConstruction4 pConstr4 = pConstr as IParcelConstruction4; ICadastralPoints pCadastralPts = pConstr4 as ICadastralPoints; ICadastralEditorSettings2 pCadastralEditorSettings2 = pCadEd as ICadastralEditorSettings2; ICadastralFixedPoints pFixedPoints = pCadastralPts as ICadastralFixedPoints; IPointCalculation pPointCalc = new PointCalculationClass(); if (pConstr == null) return; IGSLine pParcelLine = null; IMetricUnitConverter pMetricUnitConv = (IMetricUnitConverter)pCadEd; IGSPoint pStartPoint = null; List<int> lstPointIds = new List<int>(); List<IVector3D> Traverse = new List<IVector3D>(); //get rotation here IParcelConstructionData pConstrData = pConstr4.ConstructionData; IConstructionParentParcels pConstructionParentParcels = pConstrData as IConstructionParentParcels; ICadastralUndoRedo pCadUndoRedo = pConstr as ICadastralUndoRedo; try { int iParcelID = -1; if (pConstructionParentParcels.ParentParcelCount>0) pConstructionParentParcels.GetParentParcel(0, ref iParcelID); ICadastralParcel pCadaParcel = pCadPacketMan.JobPacket as ICadastralParcel; IGSParcel pGSParcel = null; if (pCadaParcel != null) pGSParcel = pCadaParcel.GetParcel(iParcelID); //if in measurement view then rotation is 0 double TheRotation = 0; if (pGSParcel == null) pGSParcel = pConstr.Parcel; if (!pCadastralEditorSettings2.MeasurementView) TheRotation = pGSParcel.Rotation;//radians if (TheRotation == 123456789) TheRotation = 0; pPointCalc.Rotation = TheRotation; IGSPoint pClosingPoint = null; #region simple method as fall-back bool bUseSimpleStackSelection = false; if (bUseSimpleStackSelection) { //bool bLineSelectionSequence = false; //IGSLine pLastSelectedGSLineInGrid = null; //for (int i = 0; i < pConstr.LineCount; i++) //{ // if (pConstr.GetLineSelection(i)) // { // if (pConstr.GetLine(i, ref pParcelLine)) // { // if (!bLineSelectionSequence) //first line // { // pStartPoint = pCadastralPts.GetPoint(pParcelLine.FromPoint); // pToPoint = pCadastralPts.GetPoint(pParcelLine.ToPoint); // } // pPointCalc.AddLine(pParcelLine); // pLastSelectedGSLineInGrid = pParcelLine; // pToPoint = pCadastralPts.GetPoint(pParcelLine.ToPoint); // lstPointIds.Add(pToPoint.Id); // } // bLineSelectionSequence = true; // double dBear = pParcelLine.Bearing; //Azimuth of IVector3D is north azimuth radians zero degrees north // double dDist = pParcelLine.Distance; // IVector3D vec = new Vector3DClass(); // vec.PolarSet(dBear, 0, dDist); ////Azimuth of IVector3D is north azimuth radians zero degrees north // Traverse.Add(vec); // } // else // { // if (bLineSelectionSequence && pConstr.GetLine(i, ref pParcelLine) && HasLineSelectionAfter(pConstr, i)) // //if there was a prior selection and this line is a complete line, and there is no later selection // { // MessageBox.Show("Please select a continuous set of lines for closure."); // return; // } // } //} //pClosingPoint = pCadastralPts.GetPoint(pLastSelectedGSLineInGrid.ToPoint); } else #endregion {//build a forward star for the selected lines IEnumCELines pCELines = new EnumCELinesClass(); IEnumGSLines pEnumGSLines = (IEnumGSLines)pCELines; ILongArray pLongArray = new LongArrayClass(); int iFirstToNode = -1; for (int i = 0; i < pConstr.LineCount; i++) { if (pConstr.GetLineSelection(i)) { if (pConstr.GetLine(i, ref pParcelLine)) { if (iFirstToNode < 0) iFirstToNode = pParcelLine.ToPoint; pLongArray.Add(i); pCELines.Add(pParcelLine); } } } if (pCELines.Count==0) { MessageBox.Show("No lines selected. Please select a continuous set of lines for closure." + Environment.NewLine + "Line selection should not have branches.", "Traverse"); return; } IParcelLineFunctions3 ParcelLineFx = new ParcelFunctionsClass(); IGSForwardStar pFwdStar = ParcelLineFx.CreateForwardStar(pEnumGSLines); //forward star object is now created for all the selected lines, //need to first re-sequence the lines, and test for branching and discontinuity int iBranches = 0; int iTracedLines = 0; int iLoops = 0; int iTerminals = 0; List<int> LineIDList = new List<int>(); List<int> FromList = new List<int>(); List<int> ToList = new List<int>(); List<string> FromToLine = new List<string>(); bool bTraceSucceeded = TraceLines(ref pFwdStar, iFirstToNode, ref iBranches, ref iTracedLines, ref iLoops, ref iTerminals, ref FromToLine, ref FromList, ref ToList, 0); if (iBranches > 0) { MessageBox.Show("Please select a continuous set of lines for closure." + Environment.NewLine + "Line selection should not have branches.", "Traverse"); return; } if (iTracedLines < pLongArray.Count) { MessageBox.Show("Please select a continuous set of lines for closure." + Environment.NewLine + "Selected Lines should be connected in a single sequence without branches.", "Traverse"); return; } //if it's a single loop check to see if the sequence needs to be reversed //CW or CCW based on bearings if (iLoops == 1) { bool bIsReversed = false; foreach (int i in FromList) { if (i < 0) bIsReversed = true; else { bIsReversed = false; break; } } if (bIsReversed) {//all courses are running reversed, so reverse the whole sequence FromToLine.Clear(); FromList.Reverse(); ToList.Reverse(); int iNewFrom = -ToList[ToList.Count-1]; int iNewTo = -FromList[ToList.Count-1]; string sNewFromTo = iNewFrom.ToString() + "," + iNewTo.ToString(); FromToLine.Add(sNewFromTo); for (int i =1; i < ToList.Count ;i++) { iNewFrom = -ToList[i-1]; iNewTo = -FromList[i-1]; sNewFromTo = iNewFrom.ToString() + "," + iNewTo.ToString(); FromToLine.Add(sNewFromTo); } } } LineIDList.Clear(); FromList.Clear(); ToList.Clear(); pLongArray.RemoveAll(); pCadUndoRedo.StartUndoRedoSession("Adjust Traverse"); if (iLoops == 0) { //re-sequence using TraceLines function based on either end point, because the order of //selected construction lines in grid don't control start or end point FromToLine.Clear(); int iTerminus = -1; iTracedLines = 0; iBranches = 0; iLoops = 0; iTerminals = 0; FindTerminusForSequence(ref pFwdStar, iFirstToNode, ref iTerminus, 0); if (iTerminus == -1) { pCadUndoRedo.WriteUndoRedoSession(false); return; } TraceLines(ref pFwdStar, iTerminus, ref iBranches, ref iTracedLines, ref iLoops, ref iTerminals, ref FromToLine, ref FromList, ref ToList, 0); } List<IVector3D> SequencedTraverse = new List<IVector3D>(); IGSLine pGSLineInPath = null; foreach (string s in FromToLine) { string[] sFromTo = s.Split(','); int iFrom = Convert.ToInt32(sFromTo[0]); int iTo = Convert.ToInt32(sFromTo[1]); bool bReversed = pFwdStar.GetLine(iFrom, iTo, ref pGSLineInPath); if (bReversed) { IGSLine pGSLine180 = new GSLineClass(); pGSLine180.FromPoint = pGSLineInPath.ToPoint; pGSLine180.ToPoint = pGSLineInPath.FromPoint; pGSLine180.Bearing = pGSLineInPath.Bearing + Math.PI; pGSLine180.Distance = pGSLineInPath.Distance; IVector3D vec180 = new Vector3DClass(); vec180.PolarSet(pGSLine180.Bearing, 0, pGSLine180.Distance); //Azimuth of IVector3D is north azimuth radians zero degrees north Traverse.Add(vec180); lstPointIds.Add(pGSLine180.ToPoint); pPointCalc.AddLine(pGSLine180); } else { double dBear = pGSLineInPath.Bearing; double dDist = pGSLineInPath.Distance; IVector3D vec = new Vector3DClass(); vec.PolarSet(dBear, 0, dDist); //Azimuth of IVector3D is north azimuth radians zero degrees north Traverse.Add(vec); lstPointIds.Add(pGSLineInPath.ToPoint); pPointCalc.AddLine(pGSLineInPath); } if (pStartPoint == null) { if (bReversed) pStartPoint = pCadastralPts.GetPoint(pGSLineInPath.ToPoint); else pStartPoint = pCadastralPts.GetPoint(pGSLineInPath.FromPoint); } if (bReversed) pClosingPoint = pCadastralPts.GetPoint(pGSLineInPath.FromPoint); else pClosingPoint = pCadastralPts.GetPoint(pGSLineInPath.ToPoint); } } if (pStartPoint == null) { pCadUndoRedo.WriteUndoRedoSession(false); return; } IPoint pStart = new PointClass(); pStart.X = pStartPoint.X; pStart.Y = pStartPoint.Y; string sAdjustMethod = "Compass"; esriParcelAdjustmentType eAdjMethod = esriParcelAdjustmentType.esriParcelAdjustmentCompass; if (pCadastralEditorSettings2.ParcelAdjustment == esriParcelAdjustmentType.esriParcelAdjustmentNone || pCadastralEditorSettings2.ParcelAdjustment == esriParcelAdjustmentType.esriParcelAdjustmentCompass) eAdjMethod = esriParcelAdjustmentType.esriParcelAdjustmentCompass; else if (pCadastralEditorSettings2.ParcelAdjustment == esriParcelAdjustmentType.esriParcelAdjustmentCrandall) { sAdjustMethod = "Crandall"; eAdjMethod = pCadastralEditorSettings2.ParcelAdjustment; } else if (pCadastralEditorSettings2.ParcelAdjustment == esriParcelAdjustmentType.esriParcelAdjustmentTransit) { sAdjustMethod = "Transit"; eAdjMethod = pCadastralEditorSettings2.ParcelAdjustment; } pPointCalc.CalculatePoints(eAdjMethod, pStartPoint.Id, pStartPoint, pClosingPoint.Id, pClosingPoint, true); ITraverseClosure pClose = pPointCalc.Closure; List<string> lstCoursesFromTo = new List<string>(); List<IVector3D> AdjustedTraverse = new List<IVector3D>(); double dAdjustedPointX = 0; double dAdjustedPointY = 0; double dPreviousPointX = 0; double dPreviousPointY = 0; for (int i = 0; i < pClose.CourseCount; i++) { IGSPoint pPt = pCadastralPts.GetPoint(lstPointIds[i]); dAdjustedPointY = pPointCalc.GetCalculatedPoint(lstPointIds[i], ref dAdjustedPointX); string sFromTo = ""; IVector3D pAdjustedLine = new Vector3DClass(); if (i == 0) { sFromTo = pStartPoint.Id.ToString() + "-" + lstPointIds[i].ToString(); pAdjustedLine.SetComponents(dAdjustedPointX - pStartPoint.X, dAdjustedPointY - pStartPoint.Y, 0); } else { sFromTo = lstPointIds[i - 1].ToString() + "-" + lstPointIds[i].ToString(); pAdjustedLine.SetComponents(dAdjustedPointX - dPreviousPointX, dAdjustedPointY - dPreviousPointY, 0); } lstCoursesFromTo.Add(sFromTo); IVector3D Z_Axis = new Vector3DClass(); Z_Axis.SetComponents(0, 0, 100); pAdjustedLine.Rotate(TheRotation, Z_Axis); AdjustedTraverse.Add(pAdjustedLine); dPreviousPointX = dAdjustedPointX; dPreviousPointY = dAdjustedPointY; pPt.X = dAdjustedPointX; pPt.Y = dAdjustedPointY; if (!pCadastralEditorSettings2.MeasurementView) pFixedPoints.SetFixedPoint(lstPointIds[i], true); } double dMisclosureDistance = pClose.MisclosureDistance; double dMisclosureBearing = pClose.MisclosureDirection; IVector MiscloseVector = new Vector3DClass(); IEditProperties2 pEdProps = pEd as IEditProperties2; IAngularConverter pAngConv = new AngularConverterClass(); pAngConv.SetAngle(dMisclosureBearing, esriDirectionType.esriDTNorthAzimuth, esriDirectionUnits.esriDURadians); //int iPrec = 7; //if (pConstr.Parcel.Plan.AngleUnits == esriDirectionUnits.esriDUDegreesMinutesSeconds) // iPrec = 0; string sMiscloseBearing = pAngConv.GetString(pEdProps.DirectionType, pEdProps.DirectionUnits, pEdProps.AngularUnitPrecision); Utilities UTIL = new Utilities(); string sRatio = "High Accuracy"; if (pClose.RelativeErrorRatio < 10000) sRatio = "1:" + pClose.RelativeErrorRatio.ToString("0"); if (dMisclosureDistance >= 0.001) sMiscloseBearing = UTIL.FormatDirectionDashesToDegMinSecSymbols(sMiscloseBearing); else sMiscloseBearing = "----"; ICadastralUnitConversion pCadUnitConverter = new CadastralUnitConversionClass(); double dMetersPerUnit = pCadUnitConverter.ConvertDouble(1, pConstr.Parcel.Plan.DistanceUnits, esriCadastralDistanceUnits.esriCDUMeter); string sReport = "Closure:" + Environment.NewLine + " error: " + sRatio + Environment.NewLine + " distance: " + (dMisclosureDistance / dMetersPerUnit).ToString("0.000") + Environment.NewLine + " bearing: " + sMiscloseBearing + Environment.NewLine + " xdist: " + (pClose.MisclosureX / dMetersPerUnit).ToString("0.000") + Environment.NewLine + " ydist: " + (pClose.MisclosureY / dMetersPerUnit).ToString("0.000") + Environment.NewLine + " courses: " + (pClose.CourseCount) + Environment.NewLine + Environment.NewLine + "Adjustment:" + Environment.NewLine + " method: " + sAdjustMethod; dlgTraverseResults dlgTraverseResults = new dlgTraverseResults(); AddTraverseInfoToGrid(pConstr.Parcel.Plan, dlgTraverseResults.dataGridView1, Traverse, AdjustedTraverse, lstCoursesFromTo); dlgTraverseResults.txtMiscloseReport.Text = sReport; DialogResult dRes = dlgTraverseResults.ShowDialog(); if (dRes == DialogResult.Cancel) { //since we cancelled, set the points back foreach (int i in lstPointIds) pFixedPoints.SetFixedPoint(i, false); pCadUndoRedo.WriteUndoRedoSession(false); } else pCadUndoRedo.WriteUndoRedoSession(true); } catch (Exception ex) { MessageBox.Show(ex.Message + Environment.NewLine + "Line number:" + ex.LineNumber().ToString() + " in " + ex.TargetSite.Name, "Traverse"); pCadUndoRedo.WriteUndoRedoSession(false); } }