8

How can I zoom the Microsoft.Phone.Controls.Maps.Map control to the correct zoom level on Windows Phone 7?

I have a LocationCollection of GeoCoordinates and I calculated the Center myself, but now how do I calculate the correct zoom level to fit the LocationCollection?

P.S. Is there an out of the box method to calculate the center of GeoCoordinates so I don't have to calculate it myself?

EDIT: I've found another fine solution: http://4mkmobile.com/2010/09/quick-tip-position-a-map-based-on-a-collection-of-pushpins/

map.SetView(LocationRect.CreateLocationRect(points));

Buju
  • 1,546
  • 3
  • 16
  • 27

3 Answers3

8

You can use the following code to calculate the LocationRect that bounds a set of points, and then pass the LocationRect to the SetView() method on the map control:

var bounds = new LocationRect(
    points.Max((p) => p.Latitude),
    points.Min((p) => p.Longitude),
    points.Min((p) => p.Latitude),
    points.Max((p) => p.Longitude));
map.SetView(bounds);

The map control handles animating from the current position to the new location.

NOTE: You'll need a using statement for System.Linq to get the Min and Max methods.

Derek Lakin
  • 16,179
  • 36
  • 51
  • Yep, this is how I did it. Works nicely. – Chris Rae Jan 14 '11 at 18:24
  • 3
    Thanks, I'll accept your answer, however I've found another fine solution: map.SetView(LocationRect.CreateLocationRect(points)); // http://4mkmobile.com/2010/09/quick-tip-position-a-map-based-on-a-collection-of-pushpins/ – Buju Jan 17 '11 at 10:14
  • Thanks. Glad you found a solution. I'll have to make a mental note that LocationRect helps out more than I thought :) – Derek Lakin Jan 17 '11 at 10:22
  • 1
    This is a nice solution, but note that if your points are around the 180 longitude line, this code will not work. You will get a rectangle in the width of the entire world... – Ran Mar 17 '11 at 16:01
  • 2
    It's called LocationRectangle in Windows Phone 8 if anyone were a bit confused like I was :) – robertk Aug 10 '13 at 19:03
1

Derek has already given the answer so you should accept his, I offer an alternative code for cases where there many points. This approach only iterates the points collection once instead 4 times however it isn't as asthetically pleasing.

 double north, west, south, west;

 north = south = points[0].Latitude;
 west = east = points[0].Longitude;

 foreach (var p in points.Skip(1))
 {
     if (north < p.Latitude) north = p.Latitude;
     if (west > p.Longitude) west = p.Longitude;
     if (south > p.Latitude) south = p.Latitude;
     if (east < p.Longitude) east = p.Longitude
 }
 map.SetView(new LocationRect(north, west, south, east));
AnthonyWJones
  • 187,081
  • 35
  • 232
  • 306
  • +1 .. and I wouldn't call this a premature optimization; I'd call the accepted answer a premature degradation :-) – Ben M Oct 10 '12 at 14:30
0

As suggested by the other answers I use SetView with a LocationRect.

However I found that it always produces to low zoom level, since only integer values was used. If for instance the perfect zoom level would be 5.5, you would get 5.0. To get a proper fit I calculate a new zoom level from TargetZoomLeveland TargetBoundingRectangle:

viewRect = LocationRect.CreateLocationRect(coordinates);
map.SetView(viewRect);
double scale = map.TargetBoundingRectangle.Height/viewRect.Height;
map.ZoomLevel = map.TargetZoomLevel + Math.Log(scale, 2);

This example sets the zoom level to fit viewRect's height on the screen.

Love
  • 1,709
  • 2
  • 22
  • 30