Page 1 of 2

Display only outside border of active region.

Posted: Fri Feb 02, 2018 5:49 am
by webdirekt
We have one use case of displaying the Active Region on Map. We provide geometry data to Map using SharpMap.Styles.VectorStyle.EnableOutline = true for display geometry for an Active Region.

We have used the ITiledProvider to convert binary geometry data into the Image. The code is as follows for ITiledProvider:

We have used the ITiledProvider to convert binary geometry data in the image of zip code, the code is as follows.

Code: Select all

public Stream GetImageStream(int x, int y, int zoom)
        {
            try
            {
                // the map contains only one layer
                var districts = new VectorLayer("Districts")
                {
                    // set the sharpmap provider for shape files as data source
                    DataSource = <Sharp map Data source>,

                    // use a dynamic style for thematic mapping
                    // the lambda also takes the map instance into account (to scale the border width)
                    Theme = new SharpMap.Rendering.Thematics.CustomTheme(GetCountryStyle)
                };

                // create a transparent sharpmap map with a size of 256x256
                using (var sharpMap = new SharpMap.Map(new Size(256, 256)) { BackColor = Color.Transparent })
                {
                    // add the layer to the map
                    sharpMap.Layers.Add(districts);

                    // calculate the bbox for the tile key and zoom the map 
                    sharpMap.ZoomToBox(TileToMercatorAtZoom(x, y, zoom));

                    // render the map image
                    using (var image = sharpMap.GetMap())
                    {
                        // stream the image to the client
                        var memoryStream = new MemoryStream();

                        image.Save(memoryStream, ImageFormat.Png);
                        memoryStream.Seek(0, SeekOrigin.Begin);

                        return memoryStream;
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        } 

	private SharpMap.Styles.VectorStyle GetCountryStyle(SharpMap.Data.FeatureDataRow featureDataRow)
        {
            // set a linear gradient brush for each country according to the bounding pixel rectangle
            SharpMap.Styles.VectorStyle style = new SharpMap.Styles.VectorStyle();

            // color code for active region
            Color color = System.Drawing.ColorTranslator.FromHtml("#009EE3");
            style.Fill = new SolidBrush(color);

            // set the border width depending on the map scale
            Pen pen = new Pen(Brushes.Black);
            pen.LineJoin = LineJoin.Round;
            style.Outline = pen;

	          // this flag is used to set the border to each zip code shape
            style.EnableOutline = true;
            return style;
        } // GetCountryStyle
Issue :
Currently, we have border to each geometry shape present on the Active Region as shown below:
ActiveRegion.png
ActiveRegion.png
But we want to display only the outside border of whole Active Region, as shown below:
Active_Region_without_inside_border.png
Active_Region_without_inside_border.png
So is there any solution for the issue?

Re: Display only outside border of active region.

Posted: Fri Feb 02, 2018 10:32 am
by Joost
Would it be possible to union the districts into a single geometry representing the active region and displaying this?

Re: Display only outside border of active region.

Posted: Thu Feb 08, 2018 5:29 pm
by Oliver Heilig
Short answer:

You can do this with NetTopologySuite, which is part of SharpMap. The solution is to put all polygons into a GeometryCollection and create a Buffer() with size 0. This gives the desired result.

Sorry, the answer maybe too short. Don't have code for it at hand,

Oli

Re: Display only outside border of active region.

Posted: Thu Feb 08, 2018 5:43 pm
by Oliver Heilig
@Bernd hinted me a method which should be better:

NTS has a dedicated function

http://nettopologysuite.github.io/html/ ... on_op.html

Didn't know this exists, havent used it much lately.

Mea culpa

Oli

Re: Display only outside border of active region.

Posted: Thu Feb 08, 2018 5:49 pm
by Bernd Welter
I LOVE THIS TEAM!
It is so strong - many thanks Oli

Re: Display only outside border of active region.

Posted: Mon Feb 12, 2018 11:49 am
by webdirekt
Thank you for the solution which you have provided, it partially works for us, but we have large number of geometry data that is appox. 1200 geometries, so it is taking time to union all the geometries.

We have used below code :

Code: Select all

GeoAPI.Geometries.IGeometry geometryCollection = geometryFactory.CreateGeometryCollection(geometryList.ToArray());
GeoAPI.Geometries.IGeometry geometryUnion = geometryCollection.Buffer(0.0);
Can you suggest any alternate solution ?

Re: Display only outside border of active region.

Posted: Mon Feb 12, 2018 11:57 am
by Bernd Welter
Well, if the performance is critical and the core geometries are updated onlyonce per year you have to create an additional data storage and layer to save the result of the call which is not executed at runtime but a some administrative task.

Re: Display only outside border of active region.

Posted: Mon Feb 12, 2018 12:11 pm
by Joost
I would try with the dedicated union functions like http://nettopologysuite.github.io/html/ ... union.html . This function uses spatial indexing to merge the polygons and could be faster that the normal operation with such a larger amount of polygons.

Re: Display only outside border of active region.

Posted: Mon Feb 12, 2018 12:26 pm
by webdirekt
Thanks for quick reply,

We have now used following code :

Code: Select all

NetTopologySuite.Operation.Union.CascadedPolygonUnion geometryUnion1 = new NetTopologySuite.Operation.Union.CascadedPolygonUnion(geometryList.ToArray());

GeoAPI.Geometries.IGeometry geometryCollection = geometryFactory.CreateGeometryCollection(geometryList.ToArray());                
GeoAPI.Geometries.IGeometry geometryUnion = geometryUnion1.Union();
But it still takes 6-7 seconds to make Union of all 1200 approx. geometries.

Is there any quicker process to make a Union ?

Re: Display only outside border of active region.

Posted: Mon Feb 12, 2018 12:30 pm
by Oliver Heilig
I knew this would happen ;)

Yes, merging a large set of polygons is slow. If you want to implement a "realtime" interactive merging, the simple incremental merge will fail performance-wise.

map&market uses a special algorithm for merging base polygons. It's called "FastUnion", and we provided it as standalone package several (> 10!) years ago. But we cannot support this anymore.

Generally the trick is to work not with distinct polygons, but with "topologies". Topologies define the common borders between polygons, so the merging is done just by removing common borders. There's a new format called "TopoJSON", which supports this and i have built a sample for this https://github.com/ptv-logistics/xserve ... in-regions, "Create custom regions by merging admin regions with D3".

So if you are running a JavaScript/Node application you would be fine. I don't see any alternatives for other languages though.

Oli