How to add your own shapes from Shapefiles on map

Mar 30, 2010 at 9:25 AM

I saw this question quite some time on the forum, so I just wanted to share with you how did I managed to add custom shape on the map.

1. Reading data from Shape Files (*.shp) :

I used SharpMap to parse Shape Files, with the code below:

ShapeFile shp = new ShapeFile("C:\Shapefiles\MyShapefile.shp");
shp.Open();

FeatureDataTable dt = new FeatureDataTable();
Collection<uint> GeomIds = new Collection<uint>();
GeomIds = shp.GetObjectIDsInView(shp.GetExtents());

2. Getting shapes inside the SharpMap data to show on map:

This was done using this code, which is taking each shape for a given shape name and creating a Dictionary to keep all shapes:

Dictionary<string, FeatureDataRow> featureList = new Dictionary<string, FeatureDataRow>();
foreach(uint id in GeomIds)
{
    FeatureDataRow dr = shp.GetFeature(id);
    featureList.Add(dr.ItemArray[0].ToString(), dr);
}

3. Placing shape on the map:

Here is the thing: you want to add your shape on the map (in my example I will use Switzerland :). The important thing is that some shape will have more than one polygon (Example: France, with all its island over the world), so the code below is handling Polygon and Multipolygon shapes (name of the shape is mostly store inside the ItemArray[0] value of the feature:

if (row.ItemArray[0].ToString() == "SWITZERLAND")
{
    foreach (FeatureDataRow row in featureList.Values)
    {
        List<PointF> points = new List<PointF>();

        if (row.Geometry is SharpMap.Geometries.Polygon)
        {
            Polygon polygon = row.Geometry as SharpMap.Geometries.Polygon;

            if (polygon.ExteriorRing.Vertices.Count == 0) { return; }

            VEMapShape push = new VEMapShape();
            push.ShapeType = VEShapeType.Polyline;

            foreach (var vertex in polygon.ExteriorRing.Vertices)
            {
                push.Points.Add(new VELatLong(vertex.Y, vertex.X));
            }
            map.AddShape(push, row.ItemArray[0].ToString(), layerid);

        }
        else if (row.Geometry is SharpMap.Geometries.MultiPolygon)
        {
            MultiPolygon multiPolygon = row.Geometry as SharpMap.Geometries.MultiPolygon;
            foreach (Polygon nestedGeometry in multiPolygon.Polygons)
            {
                if (nestedGeometry.ExteriorRing.Vertices.Count == 0) { return; }

                VEMapShape push = new VEMapShape();
                push.ShapeType = VEShapeType.Polyline;

                foreach (var vertex in nestedGeometry.ExteriorRing.Vertices)
                {
                    push.Points.Add(new VELatLong(vertex.Y, vertex.X));
                }
                map.AddShape(push, row.ItemArray[0].ToString(), layerid);
            }
        }
        else
        {
            System.Diagnostics.Debug.WriteLine(String.Format("shape type {0} is not supported yet.", row.Geometry.GetType().Name));
        }
    }
}

IMPORTANT NOTES:

- You will NOT be able to hide a shape from the map; the only way I figured out to have the MapControl to clearly hide a shape is to remove it completely... To achieve this, I am holding on memorx shapes I want to display afeter loading them once, and remove/add shape to a layer on demand.

- Map has alimited number of layers you could use; don't try to add one layer per Country for a World Shapefile sample for instance, because countries at the end of the list will simply not be shown (what I've done is the same have above, but dealing with Shape per continent).

Hope this will help you to add plenty of shapes on the map!

 

Coordinator
Mar 30, 2010 at 5:12 PM

Thanks for sharing JaYmZ666!