This project has moved. For the latest updates, please go here.

Darken the map around a specific polygon area

Dec 15, 2015 at 11:36 AM
Edited Dec 15, 2015 at 11:37 AM
Greetings! Really sorry to bother you, but there is one thing that just doesn't click with me. So I have a specific area made out of an array of locations (the work area) and I need to darken the map around it. Problem is that since it is in locations I have to transform it to an ordinary viewport to use GeometryGroup with EvenOdd fill rule. But due to the fact that the locations are in the VM I can't get access to the map. And I can't really get the locations in the View.xaml.cs code either. Is there a way to make an EvenOdd fill rule with just map elements (like MapPolyline for example) and locations?

Thanks for the great control by the way! Really well made and maintained
Coordinator
Dec 15, 2015 at 1:30 PM
You could use a MapPath, which has a Data property that takes a Geometry in logical (i.e. cartesian) map coordinates. The cartesian coordinates are ranging from -180 to 180 in x-direction (identical to longitude) and from -180 to 180 in y-direction, and are calculated by the MapTransform of the map control or by the static LatitudeToY method in class MercatorTransform.

Once you have geometries in these coordinates, you can simply put them in a GeometryGroup with a FillRule, as shown with the two circles in the sample application.

An alternative may be MapPolyline, which also has a FillRule. You may set Locations that define and inner and outer ring.
Dec 15, 2015 at 2:46 PM
I have tried using the exact solution you suggest making a -180 to 180 polyline in GeometryGroup like in the example, but MapPolyline can not be added to GeometryGroup. Or am I missing something?
About the second method: I have seen the FillRule in the polyline but how can you make two polylines in one? If you make two polygons in location there will be a line leading from one ring to the other because it is the next node. The Data property of the polyline can't take MapPath or MapPolyline and with the GeometryGroup it's the same as in the first situation.

Also, absolutely out of topic yet still important question: is there a way to force refresh a map layer? I have a dynamic layer but it only refreshes when i zoom in and out (well with the standart events)

Thank you for your help
Coordinator
Dec 15, 2015 at 3:52 PM
Edited Dec 15, 2015 at 4:47 PM
You shouldn't add a MapPolyline to a GeometryGroup. What I actually said is that you should add a Geometry (e.g. a PathGeometry) in cartesian coordinates.

Then it's unclear what you mean with "refresh". What is a "dynamic map layer"? If you add or remove elements to/from a MapPanel, it will redraw automatically.
Coordinator
Dec 15, 2015 at 8:32 PM
Edited Dec 15, 2015 at 8:38 PM
You see what I mean if you add something like this to your application:
<map:MapPath Fill="Black" Opacity="0.5">
    <map:MapPath.Data>
        <GeometryGroup FillRule="EvenOdd">
            <RectangleGeometry Rect="-1000,-1000,2000,2000"/>
            <RectangleGeometry Rect="8,63,1,1"/>
        </GeometryGroup>
    </map:MapPath.Data>
</map:MapPath>
The transformed y-values 63 and 64 (i.e. 63 + 1 height) correspond to approximate latitudes 53°10' and 53°45.5'. You might now replace the second RectangleGeometry by a PathGeometry with your polyline points in transformed coordinates.
Dec 18, 2015 at 1:11 PM
Edited Dec 19, 2015 at 9:25 AM
There lies the actual problem. I can't convert to cartesian coordinates since it requiers the map element itself. I can not get it (the map) in the VM and I can't get the polygon out of the VM. Another thing that adds up to the problem is that i can have any figure, not only a rectangle, so I need to convert both coordinates and not only Y. I've tried to convert to pixels and tiles but I don't know how to get to cartesian map object coordinates and these convertions are zoomlevel-specific.
Coordinator
Dec 19, 2015 at 5:25 PM
Edited Dec 22, 2015 at 1:38 PM
As already said, x coordinates are transformed identical, which means the cartesian x value is the same as the longitude value. As also said, there is the static LatitudeToY method in class MercatorTransform. You can easily use that in your view model.

So the transform would just look like this:
Point p = new Point(
    location.Longitude,
    MercatorTransform.LatitudeToY(location.Latitude)); 
Marked as answer by Imhotebkin on 12/22/2015 at 4:36 AM
Dec 22, 2015 at 12:38 PM
That worked perfectly, thanks=)

To anyone that will do something like this with a figure, don't forget to set a startpoint to the first node