Intersecting circles on a Map in Windows Store apps

Joost van Schaik written a nice article how to draw circles on a Map in Windows Phone and in Windows Store apps. You can read it here: http://dotnetbyexample.blogspot.nl/2014/02/drawing-circle-shapes-on-windows-phone.html

In this article i will show how you can Union two circles in a nice way.

Based on the code joost maked, lets assume we have this:

var location1 = new Bing.Maps.Location(52.181427, 5.399780);
var location2 = new Bing.Maps.Location(52.181827, 5.399780);

var layer = new MapShapeLayer();
layer.Shapes.Add(location1.GetCirclePoints(30));
layer.Shapes.Add(location2.GetCirclePoints(30));
Map.ShapeLayers.Add(layer);

Map.Center = location1;
Map.ZoomLevel = 18;

The result will look like

As you can see, the two colors are really over each other and make it harder to see the map tiles. Unfortunately there is no easy solution to render the shape as one shape. So we have to union those shapes. For Windows Phone you can easily use GeoAPI.Net and Net Topology Suite libraries. For Windows Store apps its harder, these lirbaries aren't ported yet.

Porting these libraries isnt too hard, only some classes are heavily depending on IO classes like FileStream and FileInfo. I ported these libraries (and you can download them at the bottom of this post). BUt i have to warn, i didnt maked them async.

After porting i included these libraries in my Windows Store app and created a new extension method

public static MapPolygon Union(this List<MapPolygon> polygons)
{
 List<List<Bing.Maps.Location>> gpsCoordinateLists = polygons.Select(x => x.Locations.Select(y => y).ToList()).ToList();
 var coordinateList = gpsCoordinateLists.Select(x => x.ToCoordinate()).ToList();

 var geometryList = coordinateList.Select(x => new NetTopologySuite.Geometries.Polygon(new LinearRing(x.ToArray()))).Cast<IGeometry>().ToList();
 var unionedGeometry = NetTopologySuite.Operation.Union.CascadedPolygonUnion.Union(geometryList);
 var outPoints = unionedGeometry.Coordinates.ToList();

 var poly = new MapPolygon();
 poly.FillColor = Color.FromArgb(150, 120, 120, 120);
 foreach(var loc in outPoints.ToLocation())
 {
  poly.Locations.Add(loc);
 }
 return poly;
}

and to do the conversion between the Bing.Maps.Location class and the ones that are in GeoAPI.NET, i created these 4:

public static List<Coordinate> ToCoordinate(this List<Bing.Maps.Location> location)
{
    return location.Select(x => x.ToCoordinate()).ToList();
}

public static Coordinate ToCoordinate(this Bing.Maps.Location location)
{
    return new Coordinate(location.Latitude, location.Longitude);
}

public static List<Bing.Maps.Location> ToLocation(this List<Coordinate> location)
{
    return location.Select(x => x.ToLocation()).ToList();
}

public static Bing.Maps.Location ToLocation(this Coordinate location)
{
    return new Bing.Maps.Location(location.X, location.Y);
}

Now need to change a little the way we had the circles to the map, first need to union those two to one new polygon, and add that one to the BingMap controls

var location1 = new Bing.Maps.Location(52.181427, 5.399780);
var location2 = new Bing.Maps.Location(52.181827, 5.399780);

var polygons = new List<MapPolygon>();
polygons.Add(location1.GetCirclePoints(30));
polygons.Add(location2.GetCirclePoints(30));

var layer = new MapShapeLayer();
layer.Shapes.Add(polygons.Union());

Map.ShapeLayers.Add(layer);

Map.Center = location1;
Map.ZoomLevel = 18;

and the result will then look like

I fully ported GeoAPI.NET and NTS to the WIndows Store apps platform so if you already familiar with those libraries, all your other opertions like intersection should word too.

The full source code: Download