Display only outside border of active region.

Within this forum we want to offer discussions all around our .NET based Map control including all .Net-language specific questions concerning calls of the xServer-API. Attention: xServer-relevant concepts can be found in further forums such as xRoute or xTour.
User avatar
webdirekt
Posts: 28
Joined: Wed Jul 15, 2015 10:18 am

Display only outside border of active region.

Post 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?
Joost
Posts: 310
Joined: Fri Apr 25, 2014 1:46 pm

Re: Display only outside border of active region.

Post by Joost »

Would it be possible to union the districts into a single geometry representing the active region and displaying this?
Joost Claessen
Senior Technical Consultant
PTV Benelux
User avatar
Oliver Heilig
Posts: 160
Joined: Tue May 13, 2014 12:10 pm
Location: Karlsruhe, Germany
Contact:

Re: Display only outside border of active region.

Post 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
Oliver Heilig
Chief Developer Logistic Services
PTV GROUP - Germany

https://github.com/oliverheilig/
User avatar
Oliver Heilig
Posts: 160
Joined: Tue May 13, 2014 12:10 pm
Location: Karlsruhe, Germany
Contact:

Re: Display only outside border of active region.

Post 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
Oliver Heilig
Chief Developer Logistic Services
PTV GROUP - Germany

https://github.com/oliverheilig/
User avatar
Bernd Welter
Site Admin
Posts: 2695
Joined: Mon Apr 14, 2014 10:28 am
Contact:

Re: Display only outside border of active region.

Post by Bernd Welter »

I LOVE THIS TEAM!
It is so strong - many thanks Oli
Bernd Welter
Technical Partner Manager Developer Components
PTV Logistics - Germany

Bernd at... The Forum,LinkedIn, Youtube, StackOverflow
I like the smell of PTV Developer in the morning... :twisted:
User avatar
webdirekt
Posts: 28
Joined: Wed Jul 15, 2015 10:18 am

Re: Display only outside border of active region.

Post 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 ?
User avatar
Bernd Welter
Site Admin
Posts: 2695
Joined: Mon Apr 14, 2014 10:28 am
Contact:

Re: Display only outside border of active region.

Post 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.
Bernd Welter
Technical Partner Manager Developer Components
PTV Logistics - Germany

Bernd at... The Forum,LinkedIn, Youtube, StackOverflow
I like the smell of PTV Developer in the morning... :twisted:
Joost
Posts: 310
Joined: Fri Apr 25, 2014 1:46 pm

Re: Display only outside border of active region.

Post 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.
Joost Claessen
Senior Technical Consultant
PTV Benelux
User avatar
webdirekt
Posts: 28
Joined: Wed Jul 15, 2015 10:18 am

Re: Display only outside border of active region.

Post 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 ?
User avatar
Oliver Heilig
Posts: 160
Joined: Tue May 13, 2014 12:10 pm
Location: Karlsruhe, Germany
Contact:

Re: Display only outside border of active region.

Post 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
Oliver Heilig
Chief Developer Logistic Services
PTV GROUP - Germany

https://github.com/oliverheilig/
Post Reply