Location Data Logger Design and Implementation, Part 7: The accuracy circle user control

This is part 7 of a series of blog posts on the design and implementation of the location-aware Windows* Store app "Location Data Logger". Download the source code to Location Data Logger here.

The Accuracy Circle User Control

Many, if not most, internet mapping applications and consumer navigation systems don't just display the user's position on the map, they also give the user a visual indicator of the estimated accuracy of the position information. This typically takes the form of a circle centered on the current position with a radius corresponding to the best-guess of accuracy, hence the colloquial term "accuracy circle". The point of the accuracy circle is to tell the user "I think I'm here, but it's possible I'm somewhere else within this circle". The larger the circle, the less confidence there should be about the position report.

Before I go in to the specifics of how an accuracy circle was implemented in Location Data Logger, however, I want to talk a little bit about the term "accuracy", what it means, and how it's calculated.

An aside: What is accuracy?

People use the term "accuracy" a lot in geolocation applications but there are a lot of misconceptions about what it really represents in the physical world, and even more misconceptions about how accurate accuracy really is.

The first rule of accuracy is that accuracy is a lie.

Maybe that's being a little harsh, but it's a statement that I am going to stand behind. What consumer devices report as "accuracy" is not really an accuracy at all, but rather something people in the GNSS world refer to as the "estimated position error", or EPE. The most important word in that term is "estimated". The harsher truth sitting behind all of this is that it is just not possible for a device to determine its own accuracy because there are simply too many factors that impact it, and virtually none of them (such as atmospheric conditions, and multipath and reflection issues) are knowable to the device. The EPE reported by your device is really just a guess, and there are no standards for how that guess is made. Each device manufacturer has their own algorithm for determining EPE based on what the device itself knows about the signals it is receiving, and that value is reported to the upper layers (in our case, to the Windows Geolocation sensor) as "accuracy".

The only figure that a device can actually know about it's own accuracy is something called the dilution of precision, or DOP. This is a value that can be mathematically derived from the number of satellite signals that are being tracked, and their location in the sky relative to the device, sometimes referred to as the satellite geometry or configuration. The more satellites a device can see, and the more spread out the satellites are relative to the observer, the lower the DOP.

The problem with DOP is that it's a unitless number that represents the multiplicative effects of satellite geometry on measuring position. While it has some intuitive value—lower numbers are good, and higher numbers are bad—it isn't a number you can give to a user and have them translate to something more tangible like feet or meters.

A device manufactuer's EPE is an attempt to take DOP and turn it in to something more useful to the user, but these methods are imperfect, they can vary wildly from device to device, and in many cases they are even nonsinsical (I once worked with a device that always reported an accuracy in 4m increments, and another that always said its accuracy was 30m no matter what). This means you shouldn't just take the Accuracy property from the Windows Geolocation sensor with a grain of salt: you may need the whole shaker.

Building the accuracy circle

Despite the fact that Accuracy property reported by the Geolocation sensor is a reliable measurement of a device's accuracy, it is hardly useless and there is some value in plotting it on the map with an accuracy circle. To do this, we need two things:

  1. A user control that will hold the code and XAML to draw the circle
  2. Some math to scale the circle with the scale of the map

The code for first user control is in MapAccuracyCircle.xaml and MapAccuracyCircle.cs.

The user control

For the user control, we want to display three things: the user's position with a dot, an accuracy disc that is shaded and semi-transparent, and a border around the accuracy disc as show below.

To implement this, I went with the canvas in XAML and defined three objects:

<UserControl
    x:Class="Location_Data_Logger.MapAccuracyCircle"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
    <Canvas>      
        <Ellipse x:Name="AccuracyCircle" Fill="CornflowerBlue" Opacity="0.20"/>
        <Ellipse x:Name="AccuracyCircleBorder" Opacity="0.8" Stroke="CornflowerBlue" StrokeThickness="2"/>
        <Ellipse Height="20" Width="20" Fill="CornflowerBlue" Margin="-10,-10,0,0"/>
    </Canvas>
</UserControl>

Note that the drawing order here is important: the semi-transparent disc must be rendered first, followed by the position dot and border. To simplify the rendering of the overlay on the map, the elements should be centered at 0,0 on the canvas. A width and height of the accuracy circle itself and its border are not specified, since they will be set in the application as the accuracy changes. The size of the position dot, however, is fixed at a 10 pixel radius and the Margin property is used to center it at our origin.

The accuracy circle must be updated whenever on of the following occurs:

  1. The device's postion changes
  2. The map view changes

The former is done via the setErrorRadius method in the MapAccuracyCircle object:

public void setErrorRadius(double errorRadius)
{
    if (errorRadius >= 0) radius = errorRadius;
    else return;

    UpdateAccuracyCircle();
}

It is called from within update_position() in the MainPage object.

The latter is done with a handler on the ViewChanged event which is set up when the object is initialized:

private Map _map;

public MapAccuracyCircle (Map map)
{
    this.InitializeComponent();

    _map = map;

    // Set an event handler to update the control when the map view changes

    _map.ViewChanged += (s, e) => { UpdateAccuracyCircle(); };
}

Both of these methods call UpdateAccuracyCircle(), which is responsible for setting the radius of the accuracy circle on the map display.

The math

To draw a circle on the map, we have to turn the accuracy measurement, which is in meters, into an appropriate number of pixels. This requires us to know how many meters are represented by a single pixel in the map display. The Bing* Maps object does not provide a method to determine this so we need to determine it ourselves. This is a rather simple calculation because Microsoft* uses the Mercator projection for Bing Maps, and they even provide the necessary formula in their online article "Bing Maps Tile System":

meters_per_pixel = Math.Cos(_map.Center.Latitude * DEG_TO_RAD) * CIRCUMFERENCE_EARTH / (256 * Math.Pow(2, _map.ZoomLevel));

Once the meters per pixel are known, it's trivial to determine the circle radius in pixels by dividing our current accuracy (error radius) by that value:

pixels = radius / meters_per_pixel;

    AccuracyCircle.Width = AccuracyCircleBorder.Width= AccuracyCircle.Height = AccuracyCircleBorder.Height= pixels;

The circles are centered by setting the Margin property to offset them. 

AccuracyCircle.Margin = AccuracyCircleBorder.Margin=
    new Windows.UI.Xaml.Thickness(-pixels/2, -pixels/2, 0, 0);


← Part 6: The Export Class
Para obtener más información sobre las optimizaciones del compilador, consulte el aviso sobre la optimización.