Create Random Circular Polygons With Holes

A Polygon is a kind of ogc feature that represents a continuous geographic area that is identified by a closed curve that is comprised of linear segments. A Polygon with mutliple parts is a MultiPolygon. While a Polygon is not allowed to have multiple separate parts, it can have any number of holes. A hole is defined by a linear ring and describes an area that will not be filled. A Dough-nut shape would be an example of a polygon with a single hole. The holes should not overlap. Examples of polygons with holes might be a lake with an island, or a . The code below chooses a random central location and radius and then generates a circular polygon described by 36 separate points for each polygon feature. A smaller circle is then cut out of each polygon by a single hole. Features represent a coupling of geometric shapes with non-geometric attributes. In this case the elevation value corresponds to an attribute of the integer data type. Each feature has exactly one measured elevation value, regardless of the number of coordinates in the geometric shape.


using MapWindow.Data;
using MapWindow.Geometries;
using MapWindow.Projections;
private void BuildPolygonWithHole()
    // Setup a new "shapefile" by using the featureset object
    FeatureSet fs = new FeatureSet(FeatureTypes.Line);
    // You can control things like the projection with this object
    fs.Projection = KnownCoordinateSystems.Projected.UtmNad1983.NAD1983UTMZone11N;
    // The DataTable is a standard .Net DataTable, so you can add columns the normal way and use with DataGrid controls
    fs.DataTable.Columns.Add("Elevation", typeof(int));


    // Set up the specs for creating random points.  If you already know the point values from a file this is not necessary.
    Random rnd = new Random(DateTime.Now.Millisecond);
    const int YMIN = 0;
    const int YSPAN = 1000;
    const int XMIN = 0;
    const int XSPAN = 1000;

    // In a loop we are creating 100 different points using the box established above.
    for (int i = 0; i < 10; i++)
        // random center
        Coordinate center = new Coordinate(XMIN + rnd.NextDouble() * XSPAN, YMIN + rnd.NextDouble() * YSPAN);
        // random radius from 10 to 100
        double radius = 10 + rnd.Next() * 90;
        // An array of coordinates that defines a single, continuous line
        Coordinate[] coords = new Coordinate[36];
        // Filled regions are defined by Shapefile specs to be clockwise
        for (int j = 35; j >= 0; j--)
            // A coordinate is the simple X and Y location
            coords[j] = new Coordinate(center.X + radius * Math.Cos(j * Math.PI / 18), center.Y + radius * Math.Sin(j * Math.PI / 18));
        Coordinate[] hole = new Coordinate[36];
        // Holes are defined as counter clockwise by shapefile spec.
        // In fact rendering rules are as long as it is in the opposite direction
        // and overlaps the shell it will be drawn as a hole. 
        for (int j = 0; j < 36; j++)
            // A coordinate is the simple X and Y location
            hole[j] = new Coordinate(center.X + radius/2 * Math.Cos(j * Math.PI / 18), center.Y + radius/2 * Math.Sin(j * Math.PI / 18));
        // Create a LinearRing for the hole
        LinearRing ring = new LinearRing(hole);
        // Since multiple holes are supported, make this an array with one member.
        LinearRing[] rings = new LinearRing[1];
        rings[0] = ring;

        // Temporarilly there is no constructor overload that just takes an array
        // of coordinates but also has rings, so this creates the linear ring that 
        // represents the shell.
        LinearRing shell = new LinearRing(coords);

        // A point has geoemtry capabilities like testing intersection with polygons etc.
        Polygon pg = new Polygon(shell, rings);
        // A feature also has attributes related to the featureset
        // Features can be created directly, passing the point into the constructor, but there is a glitch
        // right now that may not update the DataRow property of the feature correctly once it is added.
        IFeature currentFeature = fs.AddFeature(pg);

        // Working with the current feature allows you to control attribute content as well as the feature content.
        currentFeature.DataRow["Elevation"] = rnd.Next(0, 100);
    fs.SaveAs(@"C:\test.shp", true);

Last edited Feb 26, 2010 at 11:36 PM by Shade1974, version 4


No comments yet.