In the past it has been useful to be able to determine the best map view to display an array of locations. In the AJAX control there is a method call SetMapView which determines the best map view for an array of coordinates. The VEWS and Silverlight control do not have this functionality. A long time ago someone wanted to know how to determine the best map view before loading the map. This required us to calculate out the best map view ourselves using map scale information. I later implemented the same method when working with the VEWS so that I could geo-reference images from the Imagery service (http://rbrundritt.spaces.live.com/blog/cns!E7DBA9A4BFD458C5!488.entry). The method worked fairly well but I knew there was a better way to do this. When working with the Silverlight control I came across a situation where I needed this functionality again so I decided to create the updated method for determining the best map view using similar math that is used for the tiling system. This eliminated the need to maintain a list of scales for each zoom level and also reduce the amount of calculations that needed to be performed. Below is the updated algorithm for determining the best map view for a list of locations:
/// <summary> double maxLat = -85; //calculate bounding rectangle if (locations[i].Latitude < minLat) if (locations[i].Longitude > maxLon) if (locations[i].Longitude < minLon) center.Latitude = (maxLat + minLat) / 2; double zoom1=0, zoom2=0; //Determine the best zoom level based on the map scale and bounding coordinate information //use the most zoomed out of the two zoom levels mapView = new MapViewSpecification(center, zoomLevel); return mapView; |
HI There: First this algorithim is working beautifully for many shapes (Country polygon) drawn, However when Im plotting only the United States The map is panned to the side (the US is not in the center)… Why is that?
It’s likely centered to the left of the USA as Hawii and Alaska are off that way.
If only one location is to be plotted, can we set a default zoom level or is there some calculation?
You could add simple logic that sets a default zoom level if only one location is provided.
It has to be calculated as the width and height of the map can vary. Can the above code be changed for that?
Simply use events to determine when the map dimensions change and recall this method. This method only calculates the best map view for the map at a single instance. It doesn’t do any monitoring.
When the above logic is used to calculate for pushpins, I get a zoom value of 11 and one of the pushpin is not appearing in the image. But when the zoom is 10 all of them appears.
check the link below. Am I doing something wrong?
http://dev.virtualearth.net/REST/v1/Imagery/Map/road/33.0997,-96.6821/10?pushpin=33.0997,-96.6821;1;1&pushpin=33.121754,-96.662309;1;2&pushpin=33.1286,-96.7298;1;3&pushpin=33.0376,-96.7077;1;4&pushpin=33.1048,-96.8123;1;5&v=1&mapsize=350,400&o=xml&key=bingKey
You need to provide a buffer value into the calculation. The buffer value should be the half the width of the pushpin. This ensures that the pushpin shows up. Based on what I see I would recommend a buffer of 20 pixels.
How to determine the width of pushpin?
You have to approximate this as there is no way to determine this unless you are using a custom pushpin and another workaround I created. As I said before use a buffer of 20 pixel which is approximately the width of the pushpin in the example provided.
Dude, thanks a lot for this code, I was looking for a way to calculate the zoom for some bounds and you just saved my live, I ported this to JavaScript and works awesome!
Hi,
I found this as a handy article.
But, I did struggle to understand the zoom formula:
Math.Log(180.0 / 256.0 * (mapHeight – 2*buffer) / (maxLat – minLat)) / Math.Log(2);
It would be great if you can describe each constants being used in the formula and how did you derive formula.
Thanks in advance for the help.
The math behind this is actually pretty straight forward. This calculation determines the best zoom level based on the height of the map. In the code sample I also do the same based on the width of the map and then take the most zoomed out value of the two. The Log(x)/Log(2) where x is the rest of the math is the opposite of 2^x. Basically the with and height of the map in pixels at any zoom level is equal to 256 pixels * 2^zoom. The buffer simply accounts for a pixel sized buffer around the map and is used to account for the size of pushpin icons as the calculation itself without the buffer only accounts for the single pixels of the coordinates and does not account for the pushpin icon size. A lot of the math is based on this article: http://msdn.microsoft.com/en-us/library/bb259689.aspx
Thanks a bunch for the detailed reply.
Very helpful — thank you!
This is best solution for map zoom based on pins
crowbarsolutions.com/adjusting-zoom-level-to-add-padding-to-map-bounding-boxes-bing-maps-v7/
This algorithm is good for any platform and uses pixel buffering which is more accurate. The version of Bing Maps in the post you mention is deprecated. In Azure Maps you can do the following:
var bounds = atlas.data.BoundingBox.fromPositions(locations);
//Or if you have shapes.
//var bounds = atlas.data.BoundingBox.fromData(shapes);
//You can then pass a padding value when setting the map camera.
map.setCamera({ bounds: bounds, padding: 30 });
If you simple want to zoom into clusters, this sample shows how to do that in Azure Maps.
https://azuremapscodesamples.azurewebsites.net/index.html?sample=Point%20Clusters%20in%20Bubble%20Layer