tags:

views:

44

answers:

1

Hi,

I have 2 polygon featureclasses with Polygon ZM features. I am trying to do a ITopologicalOperator.Difference() on these featureclasses 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 funcitonality in ArcEditor, you must have ArcInfo. I take it I am taking the right approach?

+2  A: 

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;
}
Kirk Kuykendall
Thanks very much for that Kirk - thats a cracking bit of code that!
Vidar