ThinkGeo.com    |     Documentation    |     Premium Support

Polygon Simplification

I'm looking for a way to programmatically simplify a polygon. Do you have any suggestions of tools to use that could be called from .NET code and possibly use the WellKnownText or WellKnownBinary format for easily passing shapes back and forth? Are there any furture plans to include this functionality within Map Suite?



Rob, 
  
 In fact, we used to work on it years ago (in 2005 maybe) but couldn’t have a good result. I remembered we need to set some properties for the simplification,  if those properties are too big, it will lose the original shape and if they are too small, just nothing changed. It’s difficult to decide which is a good value for those properties though as the polygons are quite different from each other,  we can hardly find a good value suitable for every one.  Years have passed and maybe now there are some really good algorithm, I will still add it to the 3.0 tracking system and if we can figure it out, we will definitely add it to the products. 
  
 Thanks, 
  
 Ben

In fact, Rob, we found some good simplification algorithm within NTS today. Further investigation is still needed to test if that really works great and if yes, we will integrate that in the near future. :) 
  
 Ben

Sounds good. Can’t wait. 
  
 As for the properties, it would be great if they were exposed within the API so we could set the level of simplification we need.

Rob,


  I am not sure how long it will be to add the API.  Actually the API is fairly simple but to release the next version might be longer than you wanted to wait.  What I did was to show you the code beneath.  It is a bit crazy and the new API will wrap this nicely but if you can't wait you can play around with this. 


Important – You need to add a reference to NtsTopologySuite.dll and GeoAPI.dll.  You can find them where you reference all the other dlls for Map Suite.  Make sure to use the includes I have in the code.


David


 






        // IMPORTANT - Add reference to NetTopologySuite.dll & GeoApi.dll
        //using GisSharpBlog.NetTopologySuite.Geometries;
        //using GisSharpBlog.NetTopologySuite.Simplify;
        //using GisSharpBlog.NetTopologySuite.IO;

        private void Test()
        {
            // Here I get a shape from a shape file for testing
            ShapeFileFeatureLayer worldLayer = new ShapeFileFeatureLayer(@"..\..\SampleData\Countries02.shp");
            worldLayer.Open();
            Feature feature = worldLayer.FeatureSource.GetFeatureById("2", ReturningColumnsType.NoColumns);
            worldLayer.Close();

            // I set the tolerance.  The tolerance is measured in the unit of the
            // geometry.  If decimal degrees then 1 decimal degree, if feet then one 
            // foot etc.
            double tolerance = 1;
            MultipolygonShape simplifedShape = Simplify(feature, tolerance);
        }

        private static MultipolygonShape Simplify(Feature feature, double tolerance)
        {
            return Simplify(feature.GetShape(), tolerance);
        }

        private static MultipolygonShape Simplify(BaseShape shape, double tolerance)
        {
            // I convert the feature to a geometry in NTS
            byte[] ShapeWKB = shape.GetWellKnownBinary();
            WKBReader reader = new WKBReader();
            Geometry geometry = (Geometry)reader.Read(ShapeWKB);
            
            // There is also a faster DouglasPeuckerSimplifier but it may not keep the
            // origional shape            
            Geometry simplifiedGeometry = (Geometry)TopologyPreservingSimplifier.Simplify(geometry, tolerance);

            // I convert the result back to our shape type but I don't
            // know if it is a poygon or multi polygon
            BaseShape unknownShape = PolygonShape.CreateShapeFromWellKnownData(simplifiedGeometry.AsBinary());

            // I just convert everything to multipolygon since it can hodl any 
            // result.  If the result was a polygon then just add it to a 
            // multipolygon.  It won't hurt it only had one polygon in it
            MultipolygonShape simplifiedMultiPolygon = null;
            if (unknownShape.GetWellKnownType() == WellKnownType.Polygon)
            {
                simplifiedMultiPolygon = new MultipolygonShape();
                simplifiedMultiPolygon.Polygons.Add((PolygonShape)unknownShape);
            }
            else if (unknownShape.GetWellKnownType() == WellKnownType.Multipolygon)
            {
                simplifiedMultiPolygon = (MultipolygonShape)unknownShape;
            }

            // In the end you are left with just the simplifiedMultiPolygon
            return simplifiedMultiPolygon;
        }



Thanks, this is perfect. You guys are fast!

Rob, 
  
   This has been on my mind lately so I decided to dive in.  You know how it is, if you put stuff off then it just end up biting you in the butt later.  Better to just do it and get it finished, it makes the days, and nights, go by fast and produce happy customers.   
  
 David