Fastest Way to Parse Points in Polygon Feature Class?

5030
5
04-29-2010 05:05 PM
RafaelFerraro
New Contributor II
Hello everyone,

What is the fastest way to parse the points of a polygon feature class?  I have been using the IPolygon4 InteriorRingBag and ExteriorRingBag properties, and then looping through the point collections for interior/exterior rings.  It is ridiculously slow. 

Any other suggestions?
0 Kudos
5 Replies
EricPaitz
Esri Contributor
You might be able to cast your IPolygon to IPointCollection and just loop through those points but I am not sure it will run any faster. Do your polygons have one outer ring (like a zipcode) or are they more like a donut with an inner and and outer ring? I am not sure how the IPointColleciton will handle a polygon with holes but you can try it. Can you post a code snippet?

What language are you using? If speed is your biggest concern then you might want to try one of the other ArcObjects APIs like VC++ for Windows or C++ for Windows/Linux/Solaris. http://resources.esri.com/arcgisengine/index.cfm?fa=forDevelopers

If your Feature Class is stored in SDE then you might want to take a look at the ArcSDE C API. http://edndoc.esri.com/arcsde/9.3/api/capi/capi.htm I am actually trying to learn how to use this API because we are looking for a way to generate large numbers of shapes as fast a possible. The C API has a chance to give us the performance we need and it might be what you need to.
0 Kudos
RafaelFerraro
New Contributor II
Thanks for your response.

The current code I am using came straight from an ESRI C# example.  I am dealing with multi-part polygons, that have inner and outer rings.  Ideally, I would like the function to be robust enough to handle any feature class; shapefile, in-memory, SDE...etc.

I have been testing against shapefiles and in-memory feature classes that have 10 "donut circles".  Each circle has one inner and outer ring, each ring with 365 points, for a total 7300 points.  I am not sitting in front of my workstation at the moment so I cant give the exact performance statistics, but is was somewhere around ~10 sec to read this shapefile, WITHOUT the writeline statements.

Using the MapWin GIS component to read the same shapefile finishes <1 sec.

        public static void PolygonToString(IPolygon4 polygon)

        {

               IGeometryBag exteriorRingGeometryBag = polygon.ExteriorRingBag;
               IGeometryCollection exteriorRingGeometryCollection = exteriorRingGeometryBag as IGeometryCollection;
               Trace.WriteLine("polygon.ExteriorRingCount = " + exteriorRingGeometryCollection.GeometryCount);

               for (int i = 0; i < exteriorRingGeometryCollection.GeometryCount; i++)
               {

                      Trace.WriteLine("polygon.ExteriorRing[" + i + "]");
                      IGeometry exteriorRingGeometry = exteriorRingGeometryCollection.get_Geometry(i);
                      IPointCollection exteriorRingPointCollection = exteriorRingGeometry as IPointCollection;

                      for (int j = 0; j < exteriorRingPointCollection.PointCount; j++)
                      {
                             Trace.WriteLine("Point[" + j + "] = " + PointToString(exteriorRingPointCollection.get_Point(j)));
                      }

                      IGeometryBag interiorRingGeometryBag = polygon.get_InteriorRingBag(exteriorRingGeometry as IRing);
                      IGeometryCollection interiorRingGeometryCollection = interiorRingGeometryBag as IGeometryCollection;
                      Trace.WriteLine("polygon.InteriorRingCount[exteriorRing" + i + "] = " + interiorRingGeometryCollection.GeometryCount);

                      for (int k = 0; k < interiorRingGeometryCollection.GeometryCount; k++)
                      {

                             Trace.WriteLine("polygon.InteriorRing[" + k + "]");
                             IGeometry interiorRingGeometry = interiorRingGeometryCollection.get_Geometry(k);
                             IPointCollection interiorRingPointCollection = interiorRingGeometry as IPointCollection;

                             for (int m = 0; m < interiorRingPointCollection.PointCount; m++)
                             {

                                    Trace.WriteLine("Point[" + m + "] = " + PointToString(interiorRingPointCollection.get_Point(m)));
                             }
                      }
               }
        }

 

        private static string PointToString(IPoint point)

        {
            return (point.X + ", " + point.Y + ", " + point.Z);
        }
EricPaitz
Esri Contributor
As far as I understand it using ArcObjects with .NET (VB.NET or C#.NET) there is a lot of interop between the COM world (ArcObjects) and the .NET world. This interop can have a negative effect on performance. One simple thing to try with your code example would be to not allocate any new memory or objects in the loops. I see several objects being declared in the loops, maybe try declaring everything outside the main loop and just reuse the variables inside the loop. This is a long shot but its something to try and at least rule out. I am not sure if there is much you can do to speed up the .NET code.

There is also a new Interface called IGeometryBridge and a structure called WKSPoint that might help. This link might help understand these new objects.
http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000363000000

This page titled "Performance of ArcObjects" is a must read for your issue. It looks like its now part of the ArcGIS 10 documentation but its the same basic document its been for several versions.
http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//0001000000wm000000

They talk about how it takes a long time to dig into a Geometry Object using ArcObjects from .NET and compare it to the Visual C++ ArcObjects API which has no interop to deal with if I understand it correctly.

Here is the help link for the Visual C++ version of the ArcObjects API.
http://resources.esri.com/help/9.3/arcgisengine/com_cpp/vcpp_start.htm

I know this means learning a new API and new syntax but if performance is what you are looking for while trying to support different kinds of Feature Classes (everything from a Shapefile to an SDE Feature Class) then I think this is the way to go.
0 Kudos
IanMcCrorie
New Contributor
Hi,

Doing something very similar, looping exterior and interior rings. Only doing one feature at a time on finishing an edit and using this to create an SDOGeometry. Speed is not really an issue, using C# in ArcMap 9.1 (I know - ancient - but too much code to upgrade easily)

I have a problem though where the user has edited the shape using the Arc tool. At the end of the edit the only recorded vertices for the arc section of the polygon are the first and last points. Does anyone know an easy way to get the arc as a series of vertices? If edits are saved the arc section becomes a series of vertices but I don't want to have to save edits before accessing them.

Ian
0 Kudos
JosephArmbruster
New Contributor III
Using the IPointCollection for a polygon only makes sense if you do not have multipart geometry, since you can not tell where a part begins and ends.  If I do not care about the part-to-part relationships, I find the easiest way is to use the IGeometryCollection interface.  All you need to do is iterate from 0 to GeometryCount, get the geometry and then use the IPointCollection interface to obtain the individual points.  Like this:

IGeometryCollection geometries = polygon_feature.Shape as IGeometryCollection;
for(int i=0; i<geometries.GeometryCount; ++i)
{
  IPointCollection point_collection = geometries.Geometry as IPointCollection;
  // do something
}
0 Kudos