void OnBeforeStopParcelEditing()
        {
            if (m_ParcelEditHelperExt.RecordToField)
            {
                return;
            }

            IParcelConstruction4 pTrav    = (IParcelConstruction4)m_pParcEditorMan.ParcelConstruction;
            IEnumGSLines         pGSLines = pTrav.GetLines(false, false);

            pGSLines.Reset();
            IGSLine   pGSLine   = null;
            IGSParcel pGSParcel = null;

            pGSLines.Next(ref pGSParcel, ref pGSLine);
            while (pGSLine != null)
            {
                IGSAttributes pLineAtts = (IGSAttributes)pGSLine;
                double        brgRecord = Convert.ToDouble(pGSLine.Bearing);
                brgRecord = brgRecord * 180 / Math.PI;
                pLineAtts.SetProperty(m_ParcelEditHelperExt.FieldName, brgRecord);
                //pGSParcel.Modified();
                pGSLines.Next(ref pGSParcel, ref pGSLine);
            }

            pTrav.UpdateGridFromGSLines(true, false);
        }
        protected override void OnClick()
        {
            ICadastralEditor           pCadEd         = (ICadastralEditor)ArcMap.Application.FindExtensionByName("esriCadastralUI.CadastralEditorExtension");
            IParcelEditManager         pParcEditorMan = (IParcelEditManager)pCadEd;
            ICadastralExtensionManager pCadMan        = pCadEd as ICadastralExtensionManager;
            ICadastralPacketManager    pCadPacketMan  = (ICadastralPacketManager)pCadEd;

            //bool bStartedWithPacketOpen = pCadPacketMan.PacketOpen;

            if (!(pCadMan.ContextItem is IGSLine))
            {
                return;
            }

            IGSLine pGSLine = pCadMan.ContextItem as IGSLine;

            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;
            ICadastralLinePoints2Ex pCadLPsEx = pConstr as ICadastralLinePoints2Ex;

            ILongArray pLngArrBefore = pCadLPsEx.LinePoints;
            List <int> lstLPBefore   = new List <int>();

            for (int i = 0; i < pLngArrBefore.Count; i++)
            {
                lstLPBefore.Add(pLngArrBefore.get_Element(i));
            }

            //first get the current set of breakpoints
            Utilities FabUTILS = new Utilities();

            FabUTILS.ExecuteCommand("{9987F18B-8CC4-4548-8C41-7DB51F289BB3}"); //Run COTS Breakline command

            ILongArray pLngArrAfter = pCadLPsEx.LinePoints;
            List <int> lstLPAfter   = new List <int>();

            for (int i = 0; i < pLngArrAfter.Count; i++)
            {
                lstLPAfter.Add(pLngArrAfter.get_Element(i));
            }

            List <int> lstNewBreakPoints = lstLPAfter.Except(lstLPBefore).ToList();

            if (lstNewBreakPoints.Count == 0)
            {
                return;
            }

            IParcelConstruction4 pConstr4      = pConstr as IParcelConstruction4;
            ICadastralPoints     pCadastralPts = pConstr4 as ICadastralPoints;

            IEnumCELines pCELines     = new EnumCELinesClass();
            IEnumGSLines pEnumGSLines = (IEnumGSLines)pCELines;

            pCELines.Add(pGSLine);

            //check if it's a construction line or parent line
            bool         bIsParentLine            = true;
            IEnumGSLines pEnumGSConstructionLines = pConstr4.GetLines(false, false);

            IGSLine   pGSTestLine = null;
            IGSParcel pGSParc     = null;

            pEnumGSConstructionLines.Reset();
            pEnumGSConstructionLines.Next(ref pGSParc, ref pGSTestLine);
            while (pGSTestLine != null)
            {
                if ((pGSLine.FromPoint == pGSTestLine.FromPoint) && (pGSLine.ToPoint == pGSTestLine.ToPoint))
                {
                    bIsParentLine = false;
                    break;
                }
                pEnumGSConstructionLines.Next(ref pGSParc, ref pGSTestLine);
            }

            IParcelLineFunctions3 pParcLineFunctions = new ParcelFunctionsClass();
            IEnumGSLines          pNewLinesEnum      = pParcLineFunctions.BreakLinesAtLinePoints(pEnumGSLines, pCadastralPts, true, false);

            IGSParcel          pGSParcel    = null;
            IGSLine            pGSNewLine   = null;
            ICadastralUndoRedo pCadUndoRedo = pConstr as ICadastralUndoRedo;

            pCadUndoRedo.StartUndoRedoSession("Break-line");

            pNewLinesEnum.Reset();
            pNewLinesEnum.Next(ref pGSParcel, ref pGSNewLine);
            while (pGSNewLine != null)
            {
                pConstr4.InsertGridRow(-1, pGSNewLine, true);
                pNewLinesEnum.Next(ref pGSParcel, ref pGSNewLine);
            }

            ICadastralUnbuildableLines pUnbuildable = pConstr4 as ICadastralUnbuildableLines;

            if (bIsParentLine)
            {
                pUnbuildable.AddLine(pGSLine);
            }
            else
            {
                pConstr4.Planarize(0.001); //delete the original construction line
            }
            pCadUndoRedo.WriteUndoRedoSession(true);
        }
        protected override void OnClick()
        {
            ICadastralEditor            pCadEd         = (ICadastralEditor)ArcMap.Application.FindExtensionByName("esriCadastralUI.CadastralEditorExtension");
            ICadastralFabric            pCadFabric     = pCadEd.CadastralFabric;
            ICadastralExtensionManager2 pCadExtMan     = (ICadastralExtensionManager2)pCadEd;
            IParcelEditManager          pParcEditorMan = (IParcelEditManager)pCadEd;
            IParcelConstruction         pTrav          = pParcEditorMan.ParcelConstruction;

            //Test for the visibility of the parcel details window
            IDockableWindowManager pDocWinMgr = (IDockableWindowManager)ArcMap.Application;
            UID pUID = new UIDClass();

            pUID.Value = "{28531B78-7C42-4785-805D-2A7EC8879EA1}";//ArcID.ParcelDetails
            IDockableWindow pParcelDet = pDocWinMgr.GetDockableWindow(pUID);

            if (!pParcelDet.IsVisible())
            {
                MessageBox.Show("The Parcel Details window is not visible. \r\nThere is no data to save.");
                return;
            }

            //Make sure the lines grid is selected
            Utilities UTILS = new Utilities();

            UTILS.SelectCadastralPropertyPage((ICadastralExtensionManager)pCadExtMan, "lines");

            //test to make sure there is data there to be saved
            IParcelConstruction3 pConstr = (IParcelConstruction3)pTrav;
            IGSParcel            pParcel = null;

            //
            try
            {
                pParcel = pTrav.Parcel;
            }
            catch (COMException err)
            {
                MessageBox.Show(err.Message + Environment.NewLine + "ERROR: Select a parcel or add lines to the grid. \r\nThere is no data to save. ");
                return;
            }
            //define the file that needs to be saved
            // Display .Net dialog for File saving.
            SaveFileDialog saveFileDialog = new SaveFileDialog();

            // Set File Filter
            saveFileDialog.Filter           = "Comma-delimited(*.csv)|*.csv|All Files|*.*";
            saveFileDialog.FilterIndex      = 1;
            saveFileDialog.RestoreDirectory = true;
            // Warn on overwrite
            saveFileDialog.OverwritePrompt = true;
            // Don't need to Show Help
            saveFileDialog.ShowHelp = false;
            // Set Dialog Title
            saveFileDialog.Title = "Save file";

            // Display Open File Dialog
            if (saveFileDialog.ShowDialog() != DialogResult.OK)
            {
                saveFileDialog = null;
                return;
            }
            TextWriter tw = null;

            try
            {
                tw = new StreamWriter(saveFileDialog.FileName);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }

            try
            {
                IGSPlan pPlan = pTrav.Parcel.Plan;
                int     iDF   = (int)pPlan.DirectionFormat;
                switch (iDF)
                {
                case (int)esriDirectionType.esriDTNorthAzimuth:
                    tw.WriteLine("DT,NA");
                    break;

                case (int)esriDirectionType.esriDTPolar:
                    tw.WriteLine("DT,P");
                    break;

                case (int)esriDirectionType.esriDTQuadrantBearing:
                    tw.WriteLine("DT,QB");
                    break;

                case (int)esriDirectionType.esriDTSouthAzimuth:
                    tw.WriteLine("DT,SA");
                    break;

                default:
                    tw.WriteLine("DT,NA");
                    break;
                }

                int iAU = (int)pPlan.AngleUnits;
                switch (iAU)
                {
                case (int)esriDirectionUnits.esriDUDecimalDegrees:
                    tw.WriteLine("DU,DD");
                    break;

                case (int)esriDirectionUnits.esriDUDegreesMinutesSeconds:
                    tw.WriteLine("DU,DMS");
                    break;

                case (int)esriDirectionUnits.esriDUGons:
                case (int)esriDirectionUnits.esriDUGradians:
                    tw.WriteLine("DU,G");
                    break;

                case (int)esriDirectionUnits.esriDURadians:
                    tw.WriteLine("DU,R");
                    break;

                default:
                    tw.WriteLine("DU,R");
                    break;
                }

                ICadastralUnitConversion pUnitConv = new CadastralUnitConversionClass();
                double dMetricConversion           = pUnitConv.ConvertDouble(1, pPlan.DistanceUnits, esriCadastralDistanceUnits.esriCDUMeter);
                string sLU = Convert.ToString(dMetricConversion);

                tw.WriteLine("ToMetricFactor," + sLU);

                IEnumGSLines pGSLines = pTrav.GetLines();
                pGSLines.Reset();
                IGSLine   pGSLine   = null;
                IGSParcel pGSParcel = null;
                pGSLines.Next(ref pGSParcel, ref pGSLine);
                while (pGSLine != null)
                {
                    int iFromPt  = pGSLine.FromPoint;     //from point
                    int iToPt    = pGSLine.ToPoint;       //to point
                    int iLineCat = (int)pGSLine.Category; //line category
                    if (iLineCat == 4)
                    {
                        pGSLines.Next(ref pGSParcel, ref pGSLine);
                        continue;                            //ignore radial lines
                    }
                    int    iLineUserType = pGSLine.LineType; //line user type
                    int    iAccCat       = pGSLine.Accuracy; //accuracy
                    double dDistance     = pGSLine.Distance; //distance
                    double dChord        = pGSLine.Distance; //chord
                    double dRadius       = pGSLine.Radius;   //radius

                    string sLineCat      = Convert.ToString(iLineCat);
                    string sLineUserType = Convert.ToString(iLineUserType);

                    if (iLineUserType > 2140000000)
                    {
                        sLineUserType = "";
                    }

                    string sAccCat = Convert.ToString(iAccCat);
                    string sFromPt = Convert.ToString(iFromPt);//from point

                    //following need conversion
                    string sDirection = NorthAzRadians_2_DirectionString(pGSLine.Bearing, pPlan.DirectionFormat, pPlan.AngleUnits); //direction
                    string sDistance  = Convert.ToString(dDistance / dMetricConversion);                                            //distance
                    string sRadius    = "";
                    string sChord     = "";

                    if (dRadius != 123456789)
                    {                                                                //circular curve
                        sRadius   = Convert.ToString(dRadius / dMetricConversion);   //radius
                        sChord    = Convert.ToString(dDistance / dMetricConversion); //chord
                        sDistance = "";                                              //distance is replaced with the chord distance
                    }

                    string sToPt = Convert.ToString(iToPt);//to point
                    //write the line
                    tw.WriteLine(sFromPt + "," + sDirection + "," + sDistance + "," + sRadius + "," + sChord + "," + sToPt + ","
                                 + sLineCat + "," + sLineUserType + "," + sAccCat);

                    pGSLines.Next(ref pGSParcel, ref pGSLine);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                tw.Close();
                saveFileDialog = null;
            }
        }
        private void CalculateStatedArea(IQueryFilter m_pQF, ITable pParcelsTable, ICadastralEditor pCadEd, ISpatialReference pMapSR,
                                         double SquareMetersPerUnitFactor, string Suffix, int DecimalPlaces, ref Dictionary <int, string> dict_ParcelSelection2CalculatedArea, ITrackCancel pTrackCancel)
        {
            bool bTrackCancel = (pTrackCancel != null);
            //ILine pLine = new LineClass();

            ICursor   pCursor       = pParcelsTable.Search(m_pQF, false);
            IRow      pParcelRecord = pCursor.NextRow();
            Utilities Utils         = new Utilities();

            IArray                     pParcelFeatArr = new ArrayClass();
            IGeoDataset                pGeoDS         = (IGeoDataset)((IFeatureClass)pParcelsTable).FeatureDataset;
            ISpatialReference          pFabricSR      = pGeoDS.SpatialReference;
            IProjectedCoordinateSystem pPCS           = null;
            double                     dMetersPerUnit = 1;
            bool bFabricIsInGCS = !(pFabricSR is IProjectedCoordinateSystem);

            if (!bFabricIsInGCS)
            {
                pPCS           = (IProjectedCoordinateSystem)pFabricSR;
                dMetersPerUnit = pPCS.CoordinateUnit.MetersPerUnit;
            }
            else
            {
                pPCS           = (IProjectedCoordinateSystem)pMapSR;
                dMetersPerUnit = pPCS.CoordinateUnit.MetersPerUnit;
            }

            //for each parcel record
            while (pParcelRecord != null)
            {
                IFeature pFeat = (IFeature)pParcelRecord;
                //IGeometry pGeom = pFeat.Shape;
                pParcelFeatArr.Add(pFeat);

                Marshal.ReleaseComObject(pParcelRecord);
                if (bTrackCancel)
                {
                    if (!pTrackCancel.Continue())
                    {
                        break;
                    }
                }

                pParcelRecord = pCursor.NextRow();
            }
            Marshal.ReleaseComObject(pCursor);

            ICadastralFeatureGenerator pFeatureGenerator = new CadastralFeatureGeneratorClass();
            IEnumGSParcels             pEnumGSParcels    = pFeatureGenerator.CreateParcelsFromFeatures(pCadEd, pParcelFeatArr, true);

            pEnumGSParcels.Reset();
            Dictionary <int, int>    dict_ParcelAndStartPt = new Dictionary <int, int>();
            Dictionary <int, IPoint> dict_PointID2Point    = new Dictionary <int, IPoint>();

            //dict_PointID2Point -->> this lookup makes an assumption that the fabric TO point geometry is at the same location as the line *geometry* endpoint
            IParcelLineFunctions3 ParcelLineFx = new ParcelFunctionsClass();

            IGSParcel pGSParcel      = pEnumGSParcels.Next();
            int       iFromPtIDX     = -1;
            int       iToPtIDX       = -1;
            int       iParcelIDX     = -1;
            int       iIsMajorFldIdx = -1;

            while (pGSParcel != null)
            {
                IEnumCELines pCELines     = new EnumCELinesClass();
                IEnumGSLines pEnumGSLines = (IEnumGSLines)pCELines;

                IEnumGSLines pGSLinesInner = pGSParcel.GetParcelLines(null, false);
                pGSLinesInner.Reset();
                IGSParcel         pTemp   = null;
                IGSLine           pGSLine = null;
                ICadastralFeature pCF     = (ICadastralFeature)pGSParcel;
                int iParcID = pCF.Row.OID;
                pGSLinesInner.Next(ref pTemp, ref pGSLine);
                bool bStartPointAdded = false;
                int  iFromPtID        = -1;
                while (pGSLine != null)
                {
                    if (pGSLine.Category == esriCadastralLineCategory.esriCadastralLineBoundary ||
                        pGSLine.Category == esriCadastralLineCategory.esriCadastralLineRoad ||
                        pGSLine.Category == esriCadastralLineCategory.esriCadastralLinePartConnection)
                    {
                        pCELines.Add(pGSLine);
                        ICadastralFeature pCadastralLineFeature = (ICadastralFeature)pGSLine;
                        IFeature          pLineFeat             = (IFeature)pCadastralLineFeature.Row;
                        if (iFromPtIDX == -1)
                        {
                            iFromPtIDX = pLineFeat.Fields.FindField("FROMPOINTID");
                        }
                        if (iToPtIDX == -1)
                        {
                            iToPtIDX = pLineFeat.Fields.FindField("TOPOINTID");
                        }
                        if (iParcelIDX == -1)
                        {
                            iParcelIDX = pLineFeat.Fields.FindField("PARCELID");
                        }
                        if (iIsMajorFldIdx == -1)
                        {
                            iIsMajorFldIdx = pLineFeat.Fields.FindField("ISMAJOR");
                        }

                        if (!bStartPointAdded)
                        {
                            iFromPtID        = (int)pLineFeat.get_Value(iFromPtIDX);
                            bStartPointAdded = true;
                        }
                        IPolyline pPolyline = (IPolyline)pLineFeat.ShapeCopy;
                        //if (bFabricIsInGCS)
                        pPolyline.Project(pPCS);
                        //dict_PointID2Point -->> this lookup makes an assumption that the fabric TO point geometry is at the same location as the line *geometry* endpoint
                        int iToPtID = (int)pLineFeat.get_Value(iToPtIDX);
                        //first make sure the point is not already added
                        if (!dict_PointID2Point.ContainsKey(iToPtID))
                        {
                            dict_PointID2Point.Add(iToPtID, pPolyline.ToPoint);
                        }
                    }
                    pGSLinesInner.Next(ref pTemp, ref pGSLine);
                }

                if (pGSParcel.Unclosed)
                {//skip unclosed parcels
                    pGSParcel = pEnumGSParcels.Next();
                    continue;
                }

                ICadastralFeature pCadastralPolygonFeature = (ICadastralFeature)pGSParcel;
                IFeature          pPolygonFeat             = (IFeature)pCadastralPolygonFeature.Row;
                IPolygon          pParcelPolygon           = (IPolygon)pPolygonFeat.ShapeCopy;

                IGSForwardStar pFwdStar = ParcelLineFx.CreateForwardStar(pEnumGSLines);
                //forward star is created for this parcel, now ready to find misclose for the parcel
                List <int>       LineIdsList               = new List <int>();
                List <IVector3D> TraverseCourses           = new List <IVector3D>();
                List <int>       FabricPointIDList         = new List <int>();
                List <double>    RadiusList                = new List <double>();
                List <bool>      IsMajorList               = new List <bool>();
                List <bool>      IsRunningCounterClockwise = new List <bool>();

                bool bPass = false;
                if (!bFabricIsInGCS)
                {
                    bPass = Utils.GetParcelTraverseEx(ref pFwdStar, iIsMajorFldIdx, iFromPtID, dMetersPerUnit,
                                                      ref LineIdsList, ref TraverseCourses, ref FabricPointIDList, ref RadiusList, ref IsMajorList, ref IsRunningCounterClockwise,
                                                      pParcelPolygon, 0, -1, -1, false);
                }
                else
                {
                    bPass = Utils.GetParcelTraverseEx(ref pFwdStar, iIsMajorFldIdx, iFromPtID, dMetersPerUnit * dMetersPerUnit,
                                                      ref LineIdsList, ref TraverseCourses, ref FabricPointIDList, ref RadiusList, ref IsMajorList, ref IsRunningCounterClockwise,
                                                      pParcelPolygon, 0, -1, -1, false);
                }
                //List<double> SysValList = new List<double>();
                IVector3D MiscloseVector = null;
                IPoint[]  FabricPoints   = new IPoint[FabricPointIDList.Count];//from control

                int f = 0;
                foreach (int j in FabricPointIDList)
                {
                    FabricPoints[f++] = dict_PointID2Point[j];
                }

                double dRatio = 10000;
                double dArea  = 0;
                double dGroundToGridFactor = pGSParcel.Scale;
                bool   bHasCircularArcs    = false;
                f = FabricPointIDList.Count - 1;
                IPoint[] AdjustedTraversePoints = Utils.BowditchAdjustEx(TraverseCourses, FabricPoints[f], FabricPoints[f],
                                                                         RadiusList, IsMajorList, IsRunningCounterClockwise, out MiscloseVector, out dRatio, out dArea,
                                                                         out bHasCircularArcs);

                if (MiscloseVector == null)
                {//skip if vector closure failed
                    pGSParcel = pEnumGSParcels.Next();
                    continue;
                }
                //now compare the Geometry polygon area with the computed area to see if we need to use parametric computed area
                // there needs to be at least one circular arc to warrant using this approach.
                IArea  pGeomArea           = pPolygonFeat.ShapeCopy as IArea;
                double dGroundArea         = pGeomArea.Area / (dGroundToGridFactor * dGroundToGridFactor);
                double dAreaPercentageDiff = Math.Abs(dGroundArea - Math.Abs(dArea)) / dGroundArea;

                if (dAreaPercentageDiff > 0.075 && bHasCircularArcs && dRatio > 250)
                {
                    dArea = dGroundArea;
                }
                else if (bHasCircularArcs && dArea < 0 && dRatio > 7500) //if dArea is negative then lines are running counter-clockwise
                {
                    dArea = Math.Abs(dArea);
                }
                else if (bHasCircularArcs && dArea < 0 && pParcelPolygon.ExteriorRingCount > 1)
                {
                    dArea = pGeomArea.Area;
                }

                dArea *= (dMetersPerUnit * dMetersPerUnit); //convert to square meters first
                dArea /= SquareMetersPerUnitFactor;         //convert to the given unit equivalent

                string sFormattedArea = Math.Round(dArea, DecimalPlaces).ToString() + Suffix;
                dict_ParcelSelection2CalculatedArea.Add(pGSParcel.DatabaseId, sFormattedArea);

                pGSParcel = pEnumGSParcels.Next();

                //if (bShowProgressor)
                //{
                //  if (pStepProgressor.Position < pStepProgressor.MaxRange)
                //    pStepProgressor.Step();
                //}
            }
        }