1

There was an old GIS soft "ArcView" ; scripts in avenu language which worked much faster than my Add-ins now (made in Visual Studio in С#). So I would like understand what did I do wrong? Why is the modern technology less effective than the old one?

The code calculates intersection area of every combination of polygons in two featureclasses. Featureclass fc1 contains 100 features, FC fc2 contains 1000 features, therefore there are 100,000 combinations.

  1. My first try was "FOR" cycle (without using cursors) this way:

    IMxDocument mxdoc = ArcMap.Application.Document as IMxDocument;
    IActiveView activeView = mxdoc.ActiveView;
    IMap map = activeView as IMap;
    
    ILayer layer1 = map.Layer[0];
    ILayer layer2 = map.Layer[1];
    
    IFeatureClass fclayer1 = (layer1 as IFeatureLayer2).FeatureClass;
    IFeatureClass fclayer2 = (layer2 as IFeatureLayer2).FeatureClass;
    
    IFeature f1;
    IFeature f2;
    IFeature fINTERS;
    
    IGeometry g1;
    IGeometry g2;
    IGeometry gINTERS;
    
    IArea arINTERS;
    double areaINTERS;
    
    ITopologicalOperator topoINTERS;
    
    for (int i = 0; i < fclayer1.FeatureCount(null); i++)
    {
        f1 = fclayer1.GetFeature(i);
        g1 = f1.Shape as IGeometry;
        topoINTERS = g1 as ITopologicalOperator;
    
        for (int j = 0; j < fclayer2.FeatureCount(null); j++)
        {
            f2 = fclayer2.GetFeature(j);
            g2 = f2.Shape as IGeometry;
            gINTERS = topoINTERS.Intersect(g2, esriGeometryDimension.esriGeometry2Dimension);
            fINTERS = fclayer1.CreateFeature();
            fINTERS.Shape = gINTERS;
            arINTERS = fINTERS.Shape as IArea;
            areaINTERS = arINTERS.Area;
            fINTERS.Delete();
        }
    }
    

It takes about 90 minutes to do this calculation!

  1. My second try was "WHILE" cycle (using cursors) this way:

    IFeatureCursor fcur1 = fclayer1.Search(null,true);
    IFeatureCursor fcur2;
    
    IFeature f1 = fcur1.NextFeature();
    IFeature f2;
    IFeature fPEREC;
    
    IGeometry g1;
    IGeometry g2;
    IGeometry gINTERS;
    
    IArea arINTERS;
    double areaINTERS;
    
    ITopologicalOperator topoINTERS;
    
    while (f1 != null)
    {
        g1 = f1.Shape as IGeometry;
        topoINTERS = g1 as ITopologicalOperator;
    
        //update cursor
        fcur2 = fclayer2.Search(null, true);
        f2 = fcur2.NextFeature();
    
        while (f2 != null)
        {
            g2 = f2.Shape as IGeometry;
            gINTERS = topoINTERS.Intersect(g2, esriGeometryDimension.esriGeometry2Dimension);
            fPEREC = fclayer1.CreateFeature();
            fPEREC.Shape = gINTERS;
            arINTERS = fPEREC.Shape as IArea;
            areaINTERS = arINTERS.Area;
            fPEREC.Delete();
    
            f2 = fcur2.NextFeature();
        }
        f1 = fcur1.NextFeature();
    }
    

    This code spends about 2 minutes to do this, it's too long for my purpose too.

  2. Script in avenue (ArcView) spends about 1 second on this task (script uses "FOREACH" cycle, but in C# is not allowed to iterate the features within featureclass this way).

Is there any idea how to optimize this code to make it work faster?

Using: C#, ArcGIS 10.2.2

  • 1
    There is little difference between a 'for' loop and a 'while' loop. The speed increase you see is due to the cursor. And as far as iterating over features in a featureclass, the two methods you have outlined are about the only ways. – Barbarossa Sep 14 '17 at 18:37
  • 1
    The 'for' loop method will only work if all of the OIDs of the feature class are in order from 0 to FeatureCount. There isn't a better way to loop over features that I am aware of. – danielm Sep 14 '17 at 19:16
  • 2
    Don't forget that geometry operations in Avenue are 50-100 times faster. I keep arcview 3 nearby. – FelixIP Sep 14 '17 at 19:18
  • 2
    No, it is not, e.g. gis.stackexchange.com/questions/250245/… however for the task you describe, single line in Python using interest tool will complete under couple of seconds – FelixIP Sep 14 '17 at 19:44
  • 1
    You don't need to code this. Intersect analysis tool does it for you. – FelixIP Sep 14 '17 at 20:41
2

A little off topic answer, sorry for that.

But this is why I didn't bother to follow the Esri route after 3.x. I loved the speed you often could get from Avenue.

But the fundamental problem here I think is that Arc-whatever often uses cursors without using the possibilities of the underlying storage for filtering. I guess that not all polygons in data-set 2 intersects with all polygons in data-set 2. THen handling all those combinations means a huge overhead. That filtering should be done with a spatial index, finding what geometries actually intersect. THen doing the intersection calculation is still quite expensive, but only performed on a few geometries.

90 minutes seems hard to spend on on this anyway, but 2 minutes could be explained by issues like this.

If you do it for example in PostGIS, the planner handles thiose things and don't do more than nessecary with code like:

SELECT a.id, b.id, ST_Area(ST_Intersection(a.geom, b.geom)) 
FROM table1 as a, table2 as b 
WHERE ST_Intersects(A.geom, b.geom);

Maybe you can improve what you are doing by just adding an intersects test before calculating the intersectionopefully you can do that with support from an index.

  • ..."intersects test before calculating the intersectionopefully"... I'll try it, thanks for advice – Alex Sep 15 '17 at 15:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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