0
votes

I'm working on a Windows Store App (C#) using Bing Maps.

I want to be able to, given collection of Locations (latitude and longitude pairs), determine what the zoom level for the map should be, and what its center point (Location) should be.

From the collection of Location values, I extract the four "extreme" cardinal points that need to be displayed (furthest north, south, east, and west).

IOW, if I want to display pushpins throughout San Francisco, I want to get the zoom level to show just that city and nothing more. If I want to display pushpins scattered across the U.S., ... you get the picture.

This is what I have so far (just a rough draft/pseudocode, as you can see):

Determine the extreme cardinal values of a set of Locations (code not shown; should be trivial). Create an instance of my custom class:

public class GeoSpatialBoundaries
{
    public double furthestNorth { get; set; }
    public double furthestSouth { get; set; }
    public double furthestWest { get; set; }
    public double furthestEast { get; set; }
}

...then call these methods, passing that instance:

// This seems easy enough, but perhaps my solution is over-simplistic
public static Location GetMapCenter(GeoSpatialBoundaries gsb)
{
    double lat = (gsb.furthestNorth + gsb.furthestSouth) / 2;
    double lon = (gsb.furthestWest + gsb.furthestEast) / 2;
    return new Location(lat, lon);
}

// This math may be off; just showing my general approach
public static int GetZoomLevel(GeoSpatialBoundaries gsb)
{
    double latitudeRange = gsb.furthestNorth - gsb.furthestSouth;
    double longitudeRange = gsb.furthestEast - gsb.furthestWest;
    int latZoom = GetZoomForLat(latitudeRange);
    int longZoom = GetZoomForLong(longitudeRange);
    return Math.Max(latZoom, longZoom);
}

Here's where I really get lost, though. How do I determine the zoom level to return (between 1..20) based on these vals? Here's a very rough idea (GetZoomForLat() is basically the same):

// Bing Zoom levels range from 1 (the whole earth) to 20 (the tippy-top of the cat's whiskers)
private static int GetZoomForLong(double longitudeRange)
{
    // TODO: What Zoom level ranges should I set up as the cutoff points? IOW, should it be something like:
    if (longitudeRange > 340) return 1;
    else if (longitudeRange > 300) return 2;
    // etc.? What should the cutoff points be?
    else return 1;
}

Does anyone have any suggestions or links that can point me to how to implement these functions?

2

2 Answers

1
votes

You can use the LocationRect class to set the bounding box, see the MSDN:

http://msdn.microsoft.com/en-us/library/hh846491.aspx

Then you use the Map class and its SetView() method, see the MSDN:

http://msdn.microsoft.com/en-us/library/hh846504.aspx

Here is a code that would work (where map is your map control instance):

var collection = new LocationCollection();
collection.Add(new Location(47.5, 2.75));
collection.Add(new Location(48.5, 2.75));
collection.Add(new Location(43.5, 5.75));
map.SetView(new LocationRect(collection));

So you can use each coordinates of the elements that you want to display on your map in the collection to generate the bounding box and set the view accordingly.