I want to create a new parcel in a parcel fabric layer. I have the x, y coordinates for the parcels to be created. I searched around a lot and found really nothing that actually "CREATES" a parcel.

Here is what I have tried so far:

IPointCollection pts = feat.ShapeCopy as IPointCollection; //an existig polygon from another featureclass used for copying x,y,z..
ICadastralPoints cadPoints = new CadastralPacketClass();
for (int i = 0; i < pts.PointCount; i++)
    IPoint p = pts.get_Point(i);
    IGSPoint gsPt = new GSPointClass();
    gsPt.X = p.X;
    gsPt.Y = p.Y;
    gsPt.Z = p.Z;
    gsPt.Type = -1; //just tried when nothing worked..made no difference..

IEnumCELines ceLines = new EnumCELinesClass();

ICadastralLines cadLines = new CadastralPacketClass();
ISegmentCollection segments = feat.ShapeCopy as ISegmentCollection; //an existig polygon from another featureclass used for getting segments
for (int i = 0; i < segments.SegmentCount; i++)
    ISegment seg = segments.get_Segment(i);

    IGSLine gsLine = new GSLineClass();
    double bearingDeg = utils.GetBearing(seg.FromPoint, seg.ToPoint);
    gsLine.Bearing = (Math.PI * bearingDeg) / 180;
    gsLine.Distance = seg.Length;


IEnumGSLines gsLines = ceLines as IEnumGSLines;

IParcelLineFunctions parcelLineFunctions = new ParcelFunctionsClass();
IConstructParcelFunctions constrParcelFunctions = new ParcelFunctionsClass();
ICadastralPacket m_EditPacket = cadExtension.GetEditPacket();

IEnumGSParcels outputParcels = null;
int peRrorLinePointfrom = -1;
int peRrorLinePointTo = -1;

IGSPlan gsPlan = gsParcel.Plan; //gsParcel is an existing parcel..

constrParcelFunctions.ConstructParcelsFromLines(gsPlan, cadPoints, gsLines, m_EditPacket, 1, ref outputParcels, ref peRrorLinePointfrom, ref peRrorLinePointTo);

IGSParcel resultParcel = outputParcels.Next(); //resultParcel is null now..was expecting this to have some value..

Hope anyone would guide me into right direction.

  • what is cadExtension in ICadastralPacket m_EditPacket = cadExtension.GetEditPacket(); Oct 5 '15 at 13:47
  • ArcObjects only, no Python?
    – FelixIP
    Oct 6 '15 at 3:00
  • @FelixIP - no python
    – vinayan
    Oct 6 '15 at 3:58
  • @FaridCher - it is ICadastralExtension
    – vinayan
    Oct 6 '15 at 3:59
  • @FaridCher - are there any detailed documentations available somewhere regarding parcel fabric Arcobjects API?
    – vinayan
    Oct 20 '15 at 12:49

Make sure there is a parcel fabric layer present in the map and you have started editing. add the following assemblies to your project if you have not already.

  • ESRI.ArcGIS.CadastralUI
  • ESRI.ArcGIS.GeoSurvey
  • ESRI.ArcGIS.GeoDatabaseExtensions

Use the following class and its methods to create a parcel fabric object from a selected parcel feature in the map. The methods are tested, however, if your found a bug, let me know.

//@FaridCher at GIS.StackExchange
//can be copied and/or distributed without the express permission

using ESRI.ArcGIS.CadastralUI;
using ESRI.ArcGIS.Editor;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.GeoDatabaseExtensions;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.GeoSurvey;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace MyParcelFabric
    class CreateParcelFabric_FromPolygonSelection
        protected override void OnClick()
            var enums = ArcMap.Document.ActiveView.FocusMap.FeatureSelection as IEnumFeature;
            IFeature feat = enums.Next();
            if (feat == null)

        private void CreateParcelFabric(IFeature polygonFeature)
                UID pUID = new UIDClass();
                pUID.Value = "{114D685F-99B7-4B63-B09F-6D1A41A4DDC1}";
                ICadastralExtensionManager2 pCadExtMan = (ICadastralExtensionManager2)ArcMap.Application.FindExtensionByCLSID(pUID);
                ICadastralEditor pCadEd = (ICadastralEditor)ArcMap.Application.FindExtensionByCLSID(pUID);
                IParcelEditManager pParcEditorMan = (IParcelEditManager)pCadEd;

                IEditor pEd = (IEditor)ArcMap.Application.FindExtensionByName("esri object editor");
                if (pEd.EditState == esriEditState.esriStateNotEditing)
                    MessageBox.Show("Please start editing and try again.");

                ICadastralPacketManager pCadPacketMan = (ICadastralPacketManager)pCadEd;
                bool bStartedWithPacketOpen = pCadPacketMan.PacketOpen;
                if (!bStartedWithPacketOpen)

                //Start map edit session
                ICadastralMapEdit pCadMapEdit = (ICadastralMapEdit)pCadEd;
                pCadMapEdit.StartMapEdit(esriMapEditType.esriMEEmpty, "NewParcel", false);

                //Get job packet
                ICadastralPacket pCadaPacket = pCadPacketMan.JobPacket;

                //Create Plan (new)
                string sPlanName = "My New Plan";
                IGSPlan pGSPlan = null;
                pGSPlan = new GSPlanClass();
                //set values
                pGSPlan.Accuracy = 4;
                pGSPlan.Name = sPlanName;

                //Add the plan to the job packet
                ICadastralPlan pCadaPlan = (ICadastralPlan)pCadaPacket;

                //Create Parcel
                ICadastralParcel pCadaParcel = (ICadastralParcel)pCadaPacket;
                IGSParcel pNewGSParcel = new GSParcelClass();
                //Make sure that any extended attributes on the parcel have their default values set
                IGSAttributes pGSAttributes = (IGSAttributes)pNewGSParcel;
                if (pGSAttributes != null)
                    ICadastralObjectSetup pCadaObjSetup = (ICadastralObjectSetup)pParcEditorMan;

                //Add the parcel to the packet. (do this before addlines)
                //This will enable us to Acquire the parcel ID,
                //Having the parcel attached to the packet allows InsertLine to function.  
                pNewGSParcel.Lot = "NewParcel";
                pNewGSParcel.Type = 7;
                //Set Plan (created above)
                IGSPlan thePlan = pCadaPlan.GetPlan(sPlanName);
                pNewGSParcel.Plan = thePlan;

                ICadastralPoints pCadaPoints = (ICadastralPoints)pCadaPacket;
                IMetricUnitConverter pMetricUnitConv = (IMetricUnitConverter)pCadEd;

                ISegmentCollection segments = polygonFeature.ShapeCopy as ISegmentCollection;

                //first segment point of polygon as the start of ParFab
                var pPt1 = segments.get_Segment(0).FromPoint;
                IZAware pZAw = (IZAware)pPt1;
                pZAw.ZAware = true;
                pPt1.Z = 0; //defaulting to 0

                //Convert the point into metric units, and get a new (in-mem) point id
                IGSPoint pGSPointFrom = pMetricUnitConv.SetGSPoint(pPt1);

                int iID_First_Last = pGSPointFrom.Id;
                int iID1 = iID_First_Last;
                int iID2 = -1;

                int index = 0;
                for (int i = 0; i < segments.SegmentCount; i++)
                    ISegment seg = segments.get_Segment(i);

                    double bearingRad = getBearing(seg.FromPoint, seg.ToPoint);

                    bool computeToPoint = true;
                    if (i == segments.SegmentCount - 1)
                        computeToPoint = false;

                    IGSLine pGSLine = CreateGSLine(pMetricUnitConv, pCadaPoints, ref pPt1,
                      iID1, bearingRad, seg.Length, 0, -1, -1, -1, computeToPoint, out iID2);

                    iID1 = iID2;
                    iID2 = -1;

                    if (i == segments.SegmentCount - 1)
                        pGSLine.ToPoint = iID_First_Last;

                    pNewGSParcel.InsertLine(++index, pGSLine);

                //Add radial lines for circular curves

                //then set join=true on the parcel.
                pNewGSParcel.Joined = true;

                //let the packet know that a change has been made
                    if (!bStartedWithPacketOpen)
                if (!bStartedWithPacketOpen)
                    pEd.StopOperation("New Parcel Fabric");

            catch (Exception ex)

        private IGSLine CreateGSLine(IMetricUnitConverter MetricConversion, ICadastralPoints CadastralPoints,
      ref IPoint FromPointInToPointOut, int FromPointID, double Direction, double Distance,
      double Radius, int Accuracy, int UserLineType, int Category, bool ComputeToPoint, out int ToPointID)
            //In this function, Radius == 0 means a straight line
            //If the radius is >0 or <0 then the line is a circular curve with Distance as the chord length
            //for curves Bearing means chord bearing
            //negative radius means a curve to the left, positive radius curve to the right
            //for no Accuracy, no Type, or no Category pass in -1
            //Bearing is in north azimuth radians

            IGSLine pLine = new GSLineClass();
            pLine.Bearing = Direction; //direction is in radians north azimuth
            double dConvertedDistance = 0;
            MetricConversion.ConvertDistance(esriCadastralUnitConversionType.esriCUCToMetric, Distance, ref dConvertedDistance);
            pLine.Distance = dConvertedDistance;  //needs to be in meters;

            if (Math.Abs(Radius) > 0)
                MetricConversion.ConvertDistance(esriCadastralUnitConversionType.esriCUCToMetric, Radius, ref dConvertedDistance);
                pLine.Radius = dConvertedDistance;  //needs to be in meters;

            pLine.FromPoint = FromPointID;
            pLine.ToPoint = -1;

            if (Accuracy > -1)
                pLine.Accuracy = Accuracy;
            if (UserLineType > -1)
                pLine.LineType = UserLineType;
            if (Category > -1)
                pLine.Category = (ESRI.ArcGIS.GeoDatabaseExtensions.esriCadastralLineCategory)Category;

            //Make sure that any extended attributes on the line have their default values set
            IGSAttributes pGSAttributes = (IGSAttributes)pLine;
            if (pGSAttributes != null)
                ICadastralObjectSetup pCadaObjSetup = (ICadastralObjectSetup)MetricConversion; //QI

            //Compute the new end point for the line.
            //FromPointInToPointOut is in units of the map projection.
            ICurve pCurv = MetricConversion.GetSurveyedLine(pLine, CadastralPoints, false, FromPointInToPointOut);
            //pCurv is also in the units of the map projection. Convert the end point to metric units.

            FromPointInToPointOut = pCurv.ToPoint;//pass the new To point back out
            FromPointInToPointOut.Z = 0;
            IGSPoint pGSPointTo = MetricConversion.SetGSPoint(FromPointInToPointOut);
            if (ComputeToPoint)
                pLine.ToPoint = pGSPointTo.Id;
                ToPointID = pLine.ToPoint;
                ToPointID = -1;

            if (pCurv is ICircularArc)
                ICircularArc pCircArc = (ICircularArc)pCurv;
                IPoint pCtrPt = pCircArc.CenterPoint;
                IZAware pZAw = (IZAware)pCtrPt;
                pZAw.ZAware = true;
                pCtrPt.Z = 0;
                IGSPoint pGSCtrPt = MetricConversion.SetGSPoint(pCtrPt);
                pLine.CenterPoint = pGSCtrPt.Id;

            return pLine;

        private double getBearing(IPoint fromPoint, IPoint toPoint)
            ILine line = new LineClass();
            line.PutCoords(fromPoint, toPoint);
            double angle = line.Angle;
            return Math.PI / 2 - angle;
  • 1
    thanks a lot..I never really expected anyone could answer this..such an authentic answer I even doubt you are the developer of the parcel fabric SDK..your comments beat the comments(virtually empty) in the API documentation.
    – vinayan
    Oct 10 '15 at 6:51
  • The way I guessed the API would work was entirely wrong :D
    – vinayan
    Oct 10 '15 at 7:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.