IBufferConstruction.ConstructBuffers doesn't always return a result

2536
3
12-03-2015 06:25 AM
PieterLinks
New Contributor III

Hello,

In my program I've created a custom class 'PtClass' which contains an IPoint named 'Pt' and a collection of 'PtClass' named 'Surround'. This class can be written to and restored from XML.

I read several point features from a featureclass 'FC' with a feature cursor.

For every point feature I create an instance of 'PtClass', use the point feature coordinates to create 'Pt' - to be sure there is no link between the feature and the instance - and store the instance to a collection 'PtCollection'.

When finished, I loop every item in 'PtCollection' to search surrounding point features in 'FC' with a spatial cursor, find the corresponding items in 'PtCollection' and put them in 'Surround'.

Finally this collection is stored to XML.

Then I need some overlapping buffers around certain groups of 'PtClass' points (pointList is a List of 'Pt' from 'PtCollection'):

private IGeometryCollection BufferCollection(List<IPoint> pointList, ISpatialReference spatialReference,

                                         double bufferDistance, bool explodeBuffers, bool unionOverlapBuffers)

{

    IGeometryBag bufferBag = new GeometryBag() as IGeometryBag;

    bufferBag.SpatialReference = spatialReference;

    IGeometryCollection bufferCollection = bufferBag as IGeometryCollection;

    object missing = Type.Missing;

    try

    {

        // make a MultiPoint geometry from the collection IPoint's

        IMultipoint mp = new Multipoint() as IMultipoint;

        mp.SpatialReference = spatialReference;

        IGeometryCollection multiPoint = mp as IGeometryCollection;

        foreach (IPoint point in pointList)

        {

            multiPoint.AddGeometry(point, ref missing, ref missing);

        }

        // add the MultiPoint to a geometrybag

        IGeometryBag bag = new GeometryBag() as IGeometryBag;

        bag.SpatialReference = spatialReference;

        IGeometryCollection obstacleBag = bag as IGeometryCollection;

        obstacleBag.AddGeometry((IGeometry)multiPoint, ref missing, ref missing);

        // create an enumerator

        IEnumGeometry enumGeometry = obstacleBag as IEnumGeometry;

        // build buffers around the points

        IBufferConstruction bufferConstruction = new BufferConstruction();

        IBufferConstructionProperties bufferConstructionProperties =

            (IBufferConstructionProperties)bufferConstruction;

        bufferConstructionProperties.ExplodeBuffers = explodeBuffers;

        bufferConstructionProperties.UnionOverlappingBuffers = unionOverlapBuffers;

        bufferConstruction.ConstructBuffers(enumGeometry, bufferDistance, bufferCollection);

    }

    catch (Exception ex)

    {

        // do something with the error

    }

    return bufferCollection;

}

But sometimes it returns an empty collection, unless when I start the program anew, skip the 'FC' search and create 'PtCollection' from XML.

All the featurecursors are non-recycling and are released with Marshal.ReleaseComObject immediately afterwards. I'm using Visual Studio 2010 and ArcGIS 10.2.2.

Does it have anything to do with memory usage?

0 Kudos
3 Replies
DuncanHornby
MVP Frequent Contributor

Are the points always the same coordinate system, ie. are you mixing lat/long with UTM for example?

0 Kudos
PieterLinks
New Contributor III

Yes, the points are in the same coordinate system.

When I noticed the empty IGeometryCollection my featureclass contained 7771 point features, of which 4353 were selected and stored as 'PtClass' into the 'PtCollection'. The spatial search for surrounding points included all points in the featureclass, but the ones whose references were not found in the 'PtCollection' were skipped.

The result of BufferCollection(...) was an empty collection, but a second program run ('PtCollection' loaded from XML) returned 335 buffers (where exploded = true & unionoverlap = true).

I've noiticed with Memory Profiler, when spatial searching, a grow of used instances and bytes, and at about 2/3 of the time a spectacular grow of Generation #0 GCs, at the end of the search 162k instances, 10M9 bytes, 47 Gen #0 (upper line), 8 Gen #1 (middle line) and 1 Gen #2 (lower line).

Memory Profiler GCs.jpg

A second test with a featureclass with 4050 points from which 2278 were selected, gave me in one run a collection of 142 buffers.

Kind greetings,

Pieter

0 Kudos
PieterLinks
New Contributor III

Hello,

It was definitely a problem of memory consumption. This loop for searching surrounding points

foreach(7771 points)

{

  IFeatureCursor = featureClass.Search(spatialFilter, False)

  .... do something with the found features ....

  Marshal.ReleaseComObject(featureCursor)

}

was too much; every other operation using some memory caused a 'Out of memory'-error.

I finally could solve it by using the NetTopologySuite and creating a STRTree.

Kind regards,

Pieter

0 Kudos