Select to view content in your preferred language

Deleting feature stops working

1109
6
12-06-2010 03:37 PM
AKitch
by
Regular Contributor
Hi All

I'm attempting to run a batch process which cuts a polygon and deletes the original polygon after inserting the two new 'post cut' polygons into the feature class. The code I've included below works fine and then all of a sudden it just stops deleting the 'pre-cut' polygon. This then causes problems else where in the process where I find intersecting polygons and should only return one and of course it finds two and throws an error. As you can see I've even tried to pause the code to let ArcObjects do it's thing with no success. Any ideas out there why all of a sudden the polygons stop getting deleted?

Cheers

Adrian

        private void CutPolygonFeature(IPoint offsetPoint1, IPoint offsetPoint2, ref IFeature pFeatPoly, ref IFeatureClass polyFC, ref IApplication App)
        {
            IPolyline pLine;
            ITopologicalOperator4 pTopo;
            IGeometryCollection pGeoCol;
            IFeature pFeatNew;
            int i, j;

            try
            {

                pLine = CreatePolylineByPoints(offsetPoint1, offsetPoint2);

                //cut with intLine
                pTopo = (ITopologicalOperator4)pFeatPoly.Shape;
                pGeoCol = pTopo.Cut2(pLine);

                pEditor.StartOperation();
                for (i = 0; i < pGeoCol.GeometryCount; i++)
                {
                    pFeatNew = polyFC.CreateFeature();
                    pFeatNew.Shape = pGeoCol.get_Geometry(i);
                    for (j = 2; j < pFeatPoly.Fields.FieldCount; j++)
                    {
                        pFeatNew.set_Value(j, pFeatPoly.get_Value(j));
                    }
                    pFeatNew.Store();
                }

                pFeatPoly.Delete();
                polyFC.Update(null, true);
                Thread.Sleep(100);
                pEditor.StopOperation("Cut made");
                //function to activate the save edits command button on the Editor toolbar
                ArcCom.SaveEdits(App);
                Thread.Sleep(100);

            }
            finally
            {
                offsetPoint1 = null;
                offsetPoint2 = null;
                pLine = null;
                pTopo = null;
                pGeoCol = null;
                pFeatNew = null;
            }

        }
0 Kudos
6 Replies
JeffreyHamblin
Occasional Contributor
Hi Adrian,

Are you calling your CutPolygonFeature() method in a loop? Maybe using a cursor to get the ref pFeatPoly? Are you using Search to return the cursor with recycling enabled? Have you tried wrapping the whole operation in an edit session instead of using a separate one for each method call?

Just stabbing in the dark, but maybe you could post the code that calls the method.


-Jeff
0 Kudos
AKitch
by
Regular Contributor
Hi Jeff

Yes the CutPolygonFeature() is called in a loop. A cursor does retrieve the pFeatPoly in another method (with recycling enabled) which I've included in the code below. The whole process is wrapped in an edit session but I have to save edits as I go because the next iteration relies on the results of the current iteration.

I�??ve included the basic code that encompasses the CutPolygonFeature() method to reflect the overall process involved. I hope this is enough info. I�??m happy to clarify further if needed.

Cheers

//==== Pre set variables ======
IPointArray centerPoints; //points derived from intervals along a line
IPointArray offsetPointsA; //points offset from reciprocal centerPoints
IPointArray offsetPointsB; //points offset from reciprocal centerPoints in other direction
IApplication App;
IFeatureLayer polyLayer; //Polygon feature layer
IFeatureClass polyFC; //Feature class of polyLayer
//==============================

public void ProcessPolygonCuts()
{

 IEditor pEditor;
 IFeature pFeatPoly;
 IPoint offsetPoint1;
 IPoint offsetPoint2;
 IPolyline pLine;

 pEditor = EditSessionStart(App, polyLayer); //method included below

 //for each densify point set skipping end points
 for (int i = 1; i < centerPoints.Count - 1; i++)
 {

  //get intersect of poly feature from densified centre point
  //there should be no overlapping polygons so this should only return one feature
  pFeatPoly = GetIntersectPolygon(polyLayer, centerPoints.get_Element(i)); //method included below

  //draw line between offset line points and get centre point
  pLine = CreatePolylineByPoints(offsetPointsA.get_Element(i), offsetPointsB.get_Element(i));
  pLine.QueryPoint(esriSegmentExtension.esriNoExtension, 0.5, true, centrePoint);

  //calc closest intersect point with poly feature from a polyline ray in one direction from centre point
  offsetPoint1 = GetClosestIntersectPoint((IPolygon5)pFeatPoly.ShapeCopy, centrePoint, offsetPointsA.get_Element(i), 2000); //distance in metres

  // calc closest intersect point with poly feature from a polyline ray in other direction from centre point
  offsetPoint2 = GetClosestIntersectPoint((IPolygon5)pFeatPoly.ShapeCopy, centrePoint, offsetPointsB.get_Element(i), 2000);

  //cut poly feature
  if (offsetPoint1 != null && offsetPoint2 != null)
  {
   //cut the polygon feature with the line created from the two offset points.
   CutPolygonFeature(offsetPoint1, offsetPoint2, ref pFeatPoly, ref polyFC, ref App);
  }

 }


 pEditor.StopEditing(true);
 
 MessageBox("Finished");

}


//============================================================================
private IFeature GetIntersectPolygon(IFeatureLayer pFL, IPoint focalPoint)
{
    IFeatureSelection intFSelection;
    ISpatialFilter pSpatialFilter = null;
    ICursor cursor;
    IFeatureCursor MapCursor;

    try
    {

 intFSelection = (IFeatureSelection)pFL;
 pSpatialFilter = new SpatialFilterClass();
 pSpatialFilter.Geometry = (IGeometry)focalPoint;
 pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;

 intFSelection.SelectFeatures(pSpatialFilter, esriSelectionResultEnum.esriSelectionResultNew, false);

 if (intFSelection.SelectionSet.Count > 1) {
     return null;
     //throw new Exception("More than one feature selected in polygon layer - Function GetIntersectPolygon"); 
 }

 intFSelection.SelectionSet.Search(null, true, out cursor);
 MapCursor = (IFeatureCursor)cursor;
 return MapCursor.NextFeature();

    }
    finally
    {
 intFSelection = null;
 pSpatialFilter = null;
 cursor = null;
 MapCursor = null;
 pFL = null;
 focalPoint = null;
    }
}

//============================================================================
public IEditor EditSessionStart(IApplication application, IFeatureLayer pFLayer)
{
    UID pUID = new UID();
    pUID.Value = "esriEditor.Editor";
    IDataset pDS;
    IEditor2 pEd = (IEditor2)application.FindExtensionByCLSID(pUID);

    try{
 if (pEd.EditState != esriEditState.esriStateEditing)
 {
     pDS = (IDataset)pFLayer.FeatureClass; //.FeatureDataset;
     pEd.StartEditing(pDS.Workspace);
 }

 return pEd;
    }
    catch (Exception ex)
    {
 throw new Exception(ex.Message + " - EditSessionStart");
    }
    finally
    {
 application = null;
 pFLayer = null;
 pUID = null;
 pEd = null;
 pDS = null;
    }
}
0 Kudos
AlexanderGray
Honored Contributor
I am not sure why you are creating a new feature and deleting the old one.  I would think a more efficient way to do it would be to update the pFeatPoly with the first element of the geometry collection (if the collection contains at least one element) and create new features with other elements of the geometry collection.  I prefer to create new features using an insert cursor and a featurebuffer.  If you are having difficulties updating or deleting features, I suggest you use a non-recycling cursor.  I also suggest you use Ifeaturecursor.deletefeature instead of IFeature.delete.  If you use insert cursor, if you flush the cursor I think you will see your changes without having to call save but I would have to test this.  Also unless you need undo capabilities I am not sure why you need to frame everything in an operation.
0 Kudos
JeffreyHamblin
Occasional Contributor
I'll second most of what agray1 wrote, although I guess the edit operation is needed if the features participate in a topology or network.

I would certainly try a non-recycling cursor first, since that's an easy change to test.

Next, take a close look at the IFeature ref that is getting passed around.

Lastly, try moving the edit ops outside the loops.

Out of curiosity, how many times does the outer loop typically interate?

-Jeff
0 Kudos
AKitch
by
Regular Contributor
Thanks Alex and Jeff

Your advice seems to have solved the issues. I tried the non-recycling cursor alone which still failed. So I went the insert cursor and featurebuffer way which seems to have done the trick. I removed the Edit Ops completely as I don't need to undo. I wasn't sure if they were needed and didn't want to fill the 'undo history' (if that exists) which is why I originally had the Edit Ops in the loop. The update feature instead of deleting is also working well. Hadn't thought of that. I haven't had much experience using cursors to their fullest so looks like I've got some reading to do.

As to your last query Jeff. The outer loop in the code I supplied can have up to ~400 iterations but usually substantially less. That loop is actually a part of code that is accessed occasionally in another (outer outer) loop. The CutPolygonFeature() method is accessed mainly from this outer outer loop potentially several 1000 times. I'm running the process on the full dataset tonight so will see if it can handle it. In short I'm dicing a set of regional polygons into very small directional sub-regions. This is being done by cutting the relevant region polygon with regular perpendicular lines stemming from a directional line running along the length and centre of the region polygon.

Thanks again for the advice. Very valuable and appreciated.

Cheers
0 Kudos
AlexanderGray
Honored Contributor
If you are editing an SDE database and no one is accessing it at the time.  You might consider locking everyone out, connecting as the data owner and putting the featureclass in loadonlymode (IFeatureClassLoad.)  That will avoid updating the spatial index and should make it faster.
Good Luck
0 Kudos