Cycle through Shapes, Parts and Vertices

For all of the significant power that geometries provide, from doing overlay calculations to buffers and convex hulls, they consume extra memory and are significantly slower for simple tasks. When all you need is access to the shapes, parts and coordinates (as is the case for drawing) or even if you just need to determine if two shapes intersect, you can rely on the FeatureSet.ShapeIndices. The code below demonstrates how this works in C#. Point and MultiPoint shapes only have one part per shape, but in the case of MultiPart, that part may have more than one vertex. For Lines, each part represents the vertices connected by straight lines, while separate parts are not connected. For polygons, the parts may be islands or holes. According to the ArcGIS shapefile specification, each part of a polygon is a simple polygon and the vertices of the polygons are ordered clockwise. (Effectively so that the inside of the shape is on the right side of the line segments.) Holes should be ordered counter clockwise. For rendering with MapWindow 6, as long as the winding order of a hole is the opposite from the islands it will still draw correctly.

private void CycleThroughVertices()
{
    // Prompt the user for a shapefile.
    var layer = App.Map.AddFeatureLayer();

    // The feature set class works directly with vector data.
    // Opening a shapefile from disk loads data in "Index" mode by default.
    IFeatureSet fs = FeatureSet.Open(layer.DataSet.Filename);

    // ShapeRanges can also be created from envelopes.
    Extent extent = App.Map.Extent;

    // The shapes rely on an array of double precision interleaved
    // [X1, Y1, X2, Y2, ... Xn, Yn] coordinates.
    double x1 = fs.Vertex[0];
    double y1 = fs.Vertex[1];

    // The shaperange indexes values based on the coordinate index,
    // not the position in the double array.
    // Do access the coordinate directly from the Vertex, multiply by 2.
    x1 = fs.ShapeIndices[2].StartIndex * 2;
    y1 = fs.ShapeIndices[2].StartIndex * 2 + 1;

    // You can use the startindex and count in order to cycle values manually,
    // but it can be confusing.  To make things simpler, the ShapeIndices support an 
    // enumeration that allows cycling though the shapes, parts and the vertices.
    foreach (ShapeRange shape in fs.ShapeIndices)
    {
        if (shape.Intersects(extent))
            foreach (PartRange part in shape.Parts)
            {
                foreach (Vertex vertex in part)
                {
                    if (vertex.X > 0 && vertex.Y > 0)
                    {
                        // do something
                        Console.WriteLine(vertex.X);
                    }
                }
            }
    }
}

Last edited May 3, 2012 at 10:05 PM by mudnug, version 2

Comments

No comments yet.