3

My questions seems trivial but it is a real blocker for me. So please help!!!

How can I, using ArcObjects with C#, select only those polylines in one layer that intersect with each other?

It sounds like a very straight forward task, but I can't find another way than using a feature cursor. Which would take ages and is not efficient from my point of view.

Many Thanks in advance!

Hubert

4 Answers 4

3

You can do this by using a topology. The workflow would depend on your data source and processing environment. One way to accomplish this:

  • Create a temporary file geodatabase workspace
  • Create a feature dataset inside this workspace
  • Import your feature class into the feature dataset
  • Create a topology based on the imported feature class and set the geometry rules (Esri Topology Rule Constants)
  • Validate the topology
  • Cast the ITopology to IErrorFeatureContainer and loop through the errors
  • The OID of each offending feature is stored in the error object, you can use the OID to select your features
1
  • Thanks Rich! I had tried this route before but didn't get any errors in the errorFeatureContainer. It turns out that I had not validated the topology. Now it works. Thanks for pointing that out! One thing to remember is that in order to get all intersecting OIDs one needs to get all distinct values of both OriginOIDs and DestinationOIDs of the ITopologyErrorFeature.
    – Hubert
    Commented Apr 8, 2013 at 11:18
3

Use IMapTopology2 to create an in-memory topology. After calling IMapTopology2.Cache.Build, loop through each topologyedge in IMapTopology2.Cache.Edges and make a list of all OIDs where the topologyedge has more than one parent.

In the past I've used IFeatureSelection.SelectionSet.AddList without any problems, but now I see Esri is recommending IGeodatabaseBridge2.Addlist instead.

1
  • Hi Kirk, I'm sure your approach would work as well. I haven't had the time to test it and as most of my code was written already apart from the validating line (see comment below Rich's answer), I went with that. But thanks a lot! If I have a few moments to breath I will give your solution a try.
    – Hubert
    Commented Apr 8, 2013 at 11:21
0

I use following code snippet to get intersecting polylines:

IGeometryCollection GetIntersectPolylines(IPolyline polyline1, IPolyline polyline2)
{
    var topOperator = (ITopologicalOperator)(polyline1);
    var resultGeom = topOperator.Intersect(polyline2, esriGeometryDimension.esriGeometry1Dimension);
    var polylineCollection = (IGeometryCollection)resultGeom;
}
0

I had a similar problem with overlapping catchments (polygons). I solved it using the FeatureIndex class and the IndexQuery2 interface. It is quite fast.

Note that the IIndexQuery2.IntersectedFeatures method includes touching polygons (and would include touching polylines in your case), so I used the IRelationalOperator2 on the result to make sure they were actually overlapping and not just touching. You may want to do the same with IRelationalOperator2.Crosses (though I'm not sure exactly what this means in terms of polylines--it might include polylines that touch at a point, but don't actually cross over each other).

private List<int> CheckForInternalOverlaps(IFeatureClass featureClass)
{
  List<int> overlappingOids = new List<int>();
  IFeatureIndex indexer = new FeatureIndexClass();
  try
  {
    indexer.FeatureClass = featureClass;
    indexer.Index(null, ((IGeoDataset)featureClass).Extent);

    IIndexQuery2 indexQuery = (IIndexQuery2)indexer;
    IFeatureCursor cursor = featureClass.Search(null, false);
    try
    {
      IFeature catchment = cursor.NextFeature();
      while (catchment != null)
      {
        try
        {
          object queriedIds;
          indexQuery.IntersectedFeatures(catchment.Shape, out queriedIds);
          int[] idArray = queriedIds as int[];
          if (idArray != null && idArray.Length > 1)
          {
            // Intersected features will include, source feature itself, and adjacent, non-overlapping features
            // We need to check for both.

            IRelationalOperator2 relationOp = catchment.Shape as IRelationalOperator2;
            for (int i = 0; i < idArray.Length; i++)
            {
              if (idArray[i] == catchment.OID)
                continue;

              if (relationOp.Overlaps(featureClass.GetFeature(idArray[i]).Shape))
              {
                overlappingOids.Add(catchment.OID);
                break;
              }
            }
          }
        }
        finally
        {
          Marshal.ReleaseComObject(catchment);
        }
        catchment = cursor.NextFeature();
      }
    }
    finally
    {
      Marshal.ReleaseComObject(cursor);
    }
  }
  finally
  {
    Marshal.ReleaseComObject(indexer);
  }

  return overlappingOids;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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