Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I have 2 polygon featureclasses with Polygon ZM features. I am trying to do a ITopologicalOperator.Difference() on these feature classes but it errors saying that:

Geometry cannot have Z values

Does anyone know a way round this?

PS - I am trying to emulate the same functionality as the Erase function in the Geoprocessing API - but you cannot access this functionality in ArcEditor, you must have ArcInfo. I take it. I am taking the right approach?

share|improve this question

migrated from stackoverflow.com May 18 '11 at 22:03

This question came from our site for professional and enthusiast programmers.

1 Answer 1

up vote 4 down vote accepted

The code below works for me with an arceditor license with PolylineZM features in the top layer.

public static void TestErase(IApplication app)
{
    IMxDocument mxDoc = app.Document as IMxDocument;
    IFeatureLayer fLayer = mxDoc.FocusMap.get_Layer(0) as IFeatureLayer;

    IFeatureClass inFC = fLayer.FeatureClass;
    IFeatureClass outFC = CreateFC(@"D:\Projects\igg\beta1feedbacka","erasetest1",inFC.Fields,inFC.ShapeFieldName);

    List<IPolygon> erasurePolygons = new List<IPolygon>();
    erasurePolygons.Add(Env2Polygon(((IActiveView)mxDoc.FocusMap).Extent));

    IWorkspaceEdit wse = ((IDataset)outFC).Workspace as IWorkspaceEdit;
    wse.StartEditing(false);
    wse.StartEditOperation();
    try
    {
        Erase(inFC, outFC, erasurePolygons);
        wse.StopEditOperation();
        wse.StopEditing(true);
    }
    catch (Exception ex)
    {
        wse.AbortEditOperation();
        wse.StopEditing(false);
        throw;
    }
}

public static IPolygon Env2Polygon(IEnvelope env)
{
    IPolygon polygon = new PolygonClass();
    polygon.SpatialReference = env.SpatialReference;
    ((ISegmentCollection)polygon).SetRectangle(env);
    return polygon;
}

public static IFeatureClass CreateFC(string wsPath,string name, IFields flds, string shpFldname)
{
    IWorkspaceFactory wsf = new ShapefileWorkspaceFactoryClass();
    IFeatureWorkspace fws = wsf.OpenFromFile(wsPath, 0) as IFeatureWorkspace;
    IFields fldsClone = ((IClone)flds).Clone() as IFields;
    try
    {
        IDataset ds = fws.OpenFeatureClass(name) as IDataset;
        if (ds != null)
            ds.Delete();
    }
    catch
    {
    }
    return fws.CreateFeatureClass(name, flds, null, null, esriFeatureType.esriFTSimple, shpFldname, string.Empty);
}

public static void Erase(IFeatureClass inFC, IFeatureClass outFC, List<IPolygon> erasurePolygons)
{
    IFeatureCursor inFCur = inFC.Search(null, false);
    IFeatureCursor outFCur = outFC.Insert(false);
    IFeature inFeat;
    IFeatureBuffer outFeat = outFC.CreateFeatureBuffer();
    while ((inFeat = inFCur.NextFeature()) != null)
    {
        IGeometry outGeom = Erase(inFeat.ShapeCopy, erasurePolygons);
        if (outGeom != null && !outGeom.IsEmpty)
        {
            CopyFields(inFeat, outFeat);
            outFeat.Shape = outGeom;
            outFCur.InsertFeature(outFeat);
        }
    }
    Marshal.FinalReleaseComObject(inFCur);
    Marshal.FinalReleaseComObject(outFCur);
}
#endregion

public static void CopyFields(IFeature inFeat, IFeatureBuffer outFeat)
{
    for (int idxOut = 0; idxOut < outFeat.Fields.FieldCount; idxOut++)
    {
        if (!outFeat.Fields.get_Field(idxOut).Editable)
            continue;
        int idxIn = inFeat.Fields.FindField(outFeat.Fields.get_Field(idxOut).Name);
        if (idxIn == -1)
            continue;
        if (inFeat.Fields.get_Field(idxIn).Type == esriFieldType.esriFieldTypeGeometry)
            continue;
        outFeat.set_Value(idxOut,inFeat.get_Value(idxIn));
    }
}

public static IGeometry Erase(IGeometry inGeom, List<IPolygon> erasurePolygons)
{
    ITopologicalOperator topoOp = ((IClone)inGeom).Clone() as ITopologicalOperator;
    foreach (IPolygon polygon in erasurePolygons)
    {
        if (!((IRelationalOperator)topoOp).Disjoint(polygon))
        {
            topoOp = topoOp.Difference(polygon) as ITopologicalOperator;
            if (topoOp == null || ((IGeometry)topoOp).IsEmpty)
                break;
        }
    }
    return (IGeometry)topoOp;
}
share|improve this answer
    
Thanks very much for that Kirk - thats a cracking bit of code that! –  Vidar Jul 5 '10 at 9:48

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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