Where is my Geofence?

I was playing around with Geofences, and Geocircles, and quickly realized that when you add a Geofence, that is a Geocircle, it is not easy to tell exactly what area the Geofence covers on a map.  For those that do not know a Geofence is a virtual perimeter of a geographical location, and a Geocircle is one type of perimeter in the shape of a circle.   So I set out to find out how one would draw a circle on the map that would represent my Geofence.  This turned out to be a little more difficult than I had wanted it to be and in the end I came across an SDK sample that made things easier.   In this  blog I go over how I originally went about drawing a circle on the map, and then discuss the User Control I found in the SDK which made life easier.

If you want to follow along with this blog, you will need to download the sample at the bottom of the post, install the Bing Maps SDK,  and register an Application key with the Bing Maps SDK.

For starters I had a Bing Map for my view, and then created a Geofence in the shape of a Geocircle with a radius of 25 meters.  The center of the Geofence was my current location.  The following code demonstrates one way to do this.

Copy Code:

`private async Task GeofenceCurrentLocation() { // Get current location Geolocator geo = new Geolocator(); Geoposition pos = await geo.GetGeopositionAsync(); // Get Zoom Level double zoom = 15; // set Target Center _currentLocation.Latitude = pos.Coordinate.Point.Position.Latitude; _currentLocation.Longitude = pos.Coordinate.Point.Position.Longitude; Location mapCenter = new Location(_currentLocation); // Set map view to current location and zoom level myMap.SetView(mapCenter, zoom); // Set up Geocircle at current location with 25 meter radius BasicGeoposition geoPos = new BasicGeoposition(); geoPos.Latitude = pos.Coordinate.Point.Position.Latitude; geoPos.Longitude = pos.Coordinate.Point.Position.Longitude; Geofence fence = new Geofence("TestFence", new Geocircle(geoPos, 25)); GeofenceMonitor.Current.Geofences.Add(fence); }`

Draw a circle on Bing Map Manually

Next, I wanted to draw a circle on my Map, and after combing the docs for Bing Maps found that you can use a MapPolygon to do this.   The MapPolygon takes an array of locations to build the polygon, and since I wanted to draw a circle I needed 360 locations to make up the circle.   I found this blog to help me with the math, and the end result was the following two functions to draw my circle:

Copy Code:

`void DrawCircle(double radius) { MapPolygon polygon = new MapPolygon(); polygon.FillColor = Color.FromArgb(60, 255, 0, 0); //this works in miles polygon.Locations = GetCirclePoints(_currentLocation, radius); MapShapeLayer shapeLayer = new MapShapeLayer(); shapeLayer.Shapes.Add(polygon); myMap.ShapeLayers.Add(shapeLayer); } public LocationCollection GetCirclePoints(Location originalLocation, double radius) { LocationCollection locations = new LocationCollection(); double latitude = originalLocation.Latitude * Math.PI / 180.0; double longitude = originalLocation.Longitude * Math.PI / 180.0; // double x = radius / 3956; // Miles double x = radius / 6371000; // Meters for (int i = 0; i <= 360; i++) { double aRads = i * Math.PI / 180.0; double latRadians = Math.Asin(Math.Sin(latitude) * Math.Cos(x) + Math.Cos(latitude) * Math.Sin(x) * Math.Cos(aRads)); double lngRadians = longitude + Math.Atan2(Math.Sin(aRads) * Math.Sin(x) * Math.Cos(latitude), Math.Cos(x) - Math.Sin(latitude) * Math.Sin(latRadians)); Location loc = new Location(180.0 * latRadians / Math.PI, 180.0 * lngRadians / Math.PI); locations.Add(loc); } return locations; }`

When I run my code, I get my intended result, which is a 25 meter circle on my map.

Draw a circle using a User Control

This worked out well for me and what I needed to accomplish.  However, a couple weeks later I was going through this sample and found a User Control you could easily re-use in any project that wanted to do something similar to this, so I decided to give it a try.   The GeofenceMapControl makes it fairly simple to draw a circle on a Bing Map.   The control has a radius property, so setting the radius to that of the Geofence, and then adding the control to a Map layer at the center of the Geofence makes it really easy to light up the area where the Geofence is located.   Copy the GeofenceMapControl.xaml and GeofenceMapControl.cs files into your project.  You will need to change the x:Class value in the XAML file and the namespace in the C# file to match your projects namespace.

` `

After changing the namespace to match your project you can use it as follows:

Copy Code:

`void DrawCircleWithControl(double radius) { // Create our User Control and set its properties GeofenceMapControl gmc = new GeofenceMapControl(myMap); gmc.RadiusInMeters = radius; // Set its position on the Map Bing.Maps.MapLayer.SetPosition(gmc, _currentLocation); // Create a new Map Layer for the visual element MapLayer ml = new MapLayer(); ml.Children.Add(gmc); // Add the new map layer to the map myMap.Children.Add(ml); }`

The end result when using the GeofenceMapControl User Control is a bit more appealing to the eyes and allows for more flexibility for how the circle appears.

So there you have it, a couple of different methods for lighting up your Geofence’s on a map for troubleshooting, or to get a good idea of what area your Geofence covers.   I hope this helps folks with their Geofence applications, or just in general to better understand how to draw a shape on the map.  Until next time, have fun coding!

- Bret Bentzinger(Microsoft) @awehellyeah

References

Geofencing and geolocation sample  - http://code.msdn.microsoft.com/windowsapps/Geofencing-and-geolocation-d7ea0ef8

Creating an App with Bing Maps - http://msdn.microsoft.com/en-us/library/dn456475.aspx

Draw a Circle around Lat/Longitude Location- http://pietschsoft.com/post/2010/06/28/Silverlight-Bing-Maps-Draw-Circle-Around-Latitude-Longitude-Location

GeoStuff.zip