Editing Features on Shapefile backed Map Layer

Developer
Sep 23, 2010 at 3:29 PM

What is the recommended way to dynamically add/modify/delete features in a map?  Let's say I have a Map Layer backed by a large shapefile feature set.  I then, want to add a feature.  I stole some ShapeEditor code and came up with the following:

LineString ls = new LineString(m_coordList);
f = new Feature(ls);
IMapFeatureLayer iLayer = m_map.Layers[nLayerIndex] as IMapFeatureLayer;
iLayer.DataSet.Features.Add(f);
iLayer.DataSet.UpdateEnvelopes();
iLayer.DataSet.InvalidateVertices();

Problem I ran into was that at some point (either getting the Features list or adding the feature) the featureset went OUT of index mode.  So, when it updated envelopes and vertices, the DataSet ShapeRanges and Vertices accessed by the Map Layer during the draw cycle did not get updated, hence the display did not change.  Seems as if the layer needed to go into Edit mode to be in sync, but I'm not sure how to make that happen in the correct way.

I guess there are other ways to skin this cat.  For example, I could have 2 layers for every layer (one layer is the original shape file and the 2nd is the layer for dynamically added shapes).  But, I still need to be able to modify/delete on the original layer or at least delete (followed by an add on the 2nd layer if modifying), so not sure that buys us much.

And, of course, I want to do what gives the best performance.

I also tried iLayer.DataSet.AddFeature(f) which left the feature set in index mode but that did not work either.

Thanks,

Kyle

Developer
Sep 23, 2010 at 5:33 PM
Edited Sep 23, 2010 at 5:35 PM

The first thing is that there seems to be a bug right now so that you have to manually call InitializeVertices after you add a new feature.  This is why it isn't showing up, but I haven't had time to track that bug down yet.  But as to dropping out of IndexMode, this is one of the side-effects I have mentioned before about trying to satisfy everyone, and ending up with a code-base that can work in more ways, but is also more confusing. 

Since (if I remember correctly) you have a penchant for torturing the system with shapefiles with hundreds of thousands of shapes, I would strongly recommend avoiding using the "Features" property.  The instant you touch it, it has to use the Indices and Vertices to build geometric features.  These are required for doing overlay or intersect calculations, but little else.  It probably triples the size of the FeatureSet in memory.  For some example code on how to build features without touching the word "Features", you can look at the source code for WKBFeatureReader.

To make it easier, you can use the "Shape" class.  The "AddShape" method on the featureset should handle the inconvenience of updating the vertex array etc.  It's been a long time since I worked with it, but if memory serves you might have some success with something like the following:

            // Set up the coordinate list for the new shape
            List<Coordinate> coords = new List<Coordinate>();
            coords.Add(new Coordinate(1, 1));
            coords.Add(new Coordinate(2, 1));
            coords.Add(new Coordinate(2, 2));
            coords.Add(new Coordinate(1, 2));

            FeatureSet fs = new FeatureSet();
            fs.Open("filename");
            Shape polygon = new Shape(FeatureType.Polygon);
            polygon.Vertices = new double[]{1,1,2,1,2,2,1,2}; // coordinates as x1,y1,x2,y2...xn,yn
            polygon.AddPart(coords, CoordinateType.Regular);
            polygon.Attributes = new object[]{"field1","field2","etc"};
            fs.AddShape(polygon);

The Attributes business is risky since if the object array types don't match exactly in the correct order with the reset of your table, it will likely fail.  You may want to look at the "ItemArray" property on your DataTable on the FeatureSet to find out what those attributes should look like first.

Ted