IBufferConstruction.ConstructBuffersByDistances2 - Memory Read/Write Error

785
2
08-14-2012 04:35 AM
JosephKnieriem
New Contributor
I have a polyline layer that needs to be buffered a specific direction (left or right of the line) and a specific distance.  The polyline layer has fields in the attribute table that define each of these criteria for each feature.  Buffers generally range from 12-35 feet. After the variable buffers are created, I need all overlapping sections to be dissolved.  I figured the IBufferConstruction.ConstructBuffersByDistances2() method was the way to go, but I haven't found any working samples out there that use this method.

The help page for the method here: ConstructBuffersByDistances2() says


[INDENT]If you wish to apply a different buffer distance to each input geometry, you can use the ConstructBuffersByDistances2 method, which requires that inputs and outputs be staged in memory first[/INDENT]


I'm fairly new to C# and ArcObjects in general, so I'm guessing this is where my problem lies and I don't know how to fix it!  The feature cursor loop fills out the GeometryBag and DoubleArray properly.  When it gets to the final line of code though, it generates the error message: "Attempted to read or write protected memory". 

The other option, according to the help, would be to implement the IGeometricBufferSourceSink interface.  I couldn't find any code examples of that either.  Any help would be appreciated!

 
     
                IGeometryCollection lineGeoBagColl = new GeometryBagClass();
                IDoubleArray pDoubleArray = new DoubleArrayClass();
                IFeatureCursor _lineFCursor = _inputLineLayer.Search(null, false);                
                IGeometryCollection pOutputGeoColl = new GeometryBagClass();
                IFeature _Feat = _lineFCursor.NextFeature();

                using (ESRI.ArcGIS.ADF.ComReleaser comReleaser = new ComReleaser())
                {

                    do
                    {
                        comReleaser.ManageLifetime(_lineFCursor);
                        Boolean isManaged = false;
                        if (!isManaged)
                        {
                            comReleaser.ManageLifetime(_Feat);
                            isManaged = true;
                        }

                        IRow pRow = _Feat;
                        IPolyline pPolyline = _Feat.ShapeCopy as IPolyline;

                        // Gets the distance from the distance field and adds it to the array.
                        double offsetDistance = (double)pRow.get_Value(_OffsetFieldIndex);
                        pDoubleArray.Add(offsetDistance);

                        // Gets the value in the direction field.  
                        // If the value is L or Left, it will reverse orientation of the line.
                        // The final buffers will all be generated to the right.
                        string offsetDirection = pRow.get_Value(_OffsetDirectionFieldIndex).ToString();
                        offsetDirection = offsetDirection.Trim().ToUpper();
                        if (offsetDirection == "L" || offsetDirection == "LEFT")
                        {
                            pPolyline.ReverseOrientation();
                        }
                        lineGeoBagColl.AddGeometryCollection(pPolyline as IGeometryCollection);

                        _Feat = _lineFCursor.NextFeature();

                    } while (_Feat != null);

                    _lineFCursor.Flush();                    
                }

                IBufferConstruction bc = new BufferConstructionClass();
                IBufferConstructionProperties bcProp = bc as IBufferConstructionProperties;
                bcProp.SideOption = esriBufferConstructionSideEnum.esriBufferRight;
                bcProp.UnionOverlappingBuffers = true;
                bcProp.ExplodeBuffers = true;
                bcProp.EndOption = esriBufferConstructionEndEnum.esriBufferRound;

                IEnumGeometry pEnumGeo = lineGeoBagColl as IEnumGeometry;
                pEnumGeo.Reset();

                bc.ConstructBuffersByDistances2(pEnumGeo, pDoubleArray, pOutputGeoColl);
0 Kudos
2 Replies
NeilClemmons
Regular Contributor III
This is just a guess, but it seems that the method is trying to access a geometry or value that doesn't exist.  This might happen if the number of geometries in the geometry collection doesn't match the number of distances in the array.  You're adding polylines to the geometry collection by calling AddGeometryCollection.  I'm not sure if it makes any difference but you might want to try adding the polylines using AddGeometry.  Also, check the GeometryCount property on the geometry collection and make sure it matches the Count property on the array.  Another possibility is it doesn't like the geometry collection you're passing in to receive the output buffers.  You're instantiating it as a geometry bag.  Try not instantiating it at all.  Just declare the variable and pass it in.  Some ArcObjects methods like to create their own class instances.  One last thing I can think of is that it could be a data problem.  Before adding geometries to your input collection, check to make sure they are not null and not empty.  You should probably check the buffer values too to make sure none of them are 0.
0 Kudos
JosephKnieriem
New Contributor
Thanks Neil!  I had checked the geometry count vs the amount of doubles in the array and checked for null geometries and/or zero value doubles.  Those always checked out fine.  It turns out the problem was the way I added the geometry to the geometry collection.

lineGeoBagColl.AddGeometryCollection(pPolyline as IGeometryCollection);


becomes

object g_missing = Type.Missing;
lineGeoBagColl.AddGeometry(pPolyline as IGeometry, ref g_missing, ref g_missing);


Thanks a ton!
0 Kudos