4010 views

Skip to first unread message

Feb 16, 2010, 12:58:49 AM2/16/10

to Google Maps JavaScript API v3

Hi,

I am working on an enhancement to the map accessible at http://travellr.com/map

The idea is to be able to load the map on a country, and have the map

zoomed to appropriately fit the country. For all countries I have co-

ordinates and bounding boxes already.

The problem is that when using Map.fitBounds(), the zoom level

sometimes isn't quite right - for loading on countries I would like to

limit zoom within a min / max, and places like Russia and Canada

break out of that. After using Map.fitBounds(), I could then check the

zoom level once the zoom_changed event fires, and if required update

it, but that seems quite a clunky multi step process.

Ideally I would like to be able to calculate the zoom level prior to

instantiating the map. However the API v3 does not seem to provide a

way to do this.

I have read some solutions akin to:

// mnode = the map node

// bounds = a bounding box

function best_zoom(bounds, mnode) {

var width = mnode.offsetWidth;

var height = mnode.offsetHeight;

var dlat = Math.abs(bounds.maxY - bounds.minY);

var dlon = Math.abs(bounds.maxX - bounds.minX);

// Center latitude in radians

var clat = Math.PI*(bounds.minY + bounds.maxY)/360.;

var C = 0.0000107288;

var z0 = Math.ceil(Math.log(dlat/(C*height))/Math.LN2);

var z1 = Math.ceil(Math.log(dlon/(C*width*Math.cos(clat)))/

Math.LN2);

return (z1 > z0) ? z1 : z0;

}

However this does not seem to provide the correct zoom levels (they

increase as dlat or dlon increase, shouldn't they go down?) - Please

tell me if I am missing something here? Also, where does the constant

C come from?

Thanks for your help.

- Jai

Feb 17, 2010, 8:55:33 PM2/17/10

to Google Maps JavaScript API v3

This is actually a nasty problem when the objects that you are trying

to fit are large. For V2 I used:

to fit are large. For V2 I used:

function zoomRecenter(map, bounds) {

map.setZoom(map.getBoundsZoomLevel(bounds));

map.panTo(bounds.getCenterMap(map));

}

GLatLngBounds.prototype.getCenterMap = function(m) {

var p = m.getCurrentMapType().getProjection();

var b = new GBounds;

b.extend(p.fromLatLngToPixel(this.getNorthEast(), m.getZoom()));

b.extend(p.fromLatLngToPixel(this.getSouthWest(), m.getZoom()));

return new GLatLng(p.fromPixelToLatLng(b.mid(),

m.getZoom()).lat(), this.getCenter().lng());

}

Note the complexity of finding the *pixel* middle of a GBounds.

However, since it isn't possible (currently) in V3 to get the

projection in use by the current basemap, you are somewhat hosed.

You can star the bug at

http://code.google.com/p/gmaps-api-issues/issues/detail?id=2181&q=apitype%3AJavascript3%20type%3ADefect&sort=-id%20-stars&colspec=ID%20Type%20Status%20Introduced%20Fixed%20Summary%20Internal%20Stars

if you want.

Philip

On Feb 16, 12:58 am, Jaidev S <j...@travellr.com> wrote:

> Hi,

>

> I am working on an enhancement to the map accessible athttp://travellr.com/map

Feb 23, 2010, 9:12:18 PM2/23/10

to Google Maps JavaScript API v3

Okay, have worked this out.

C is a value based on your latitude, values I calculated were:

constant_at_0_degrees = 1.406245461070741

constant_at_20_degrees = 1.321415085624082

constant_at_40_degrees = 1.077179995861952

constant_at_60_degrees = 0.703119412486786

constant_at_80_degrees = 0.488332580888611

I found for most countries just using the 60 degree one worked well.

For working out the zoom level to display a bounding box (this is in

ruby but easily translated into JS):

width = width-of-map-element

height = height-of-map-element

bounds_t = top-of-bounding-box

bounds_b = bottom-of-bounding-box

bounds_l = left-of-bounding-box

boubds_r = right-of-bounding-box

dlat = bounds_t - bounds_b

if bounds_l < bounds_r

dlon = bounds_r - bounds_l

else

dlon = 360 - bounds_l + bounds_r

end

z0 = (Math.log(constant_at_60_degrees * height / dlat) /

Math.log(2)).ceil

z1 = (Math.log(constant_at_60_degrees * width / dlon) /

Math.log(2)).ceil

zoom = z1 ? ((z1 > z0) ? z0 : z1) : z0

Happy mapping :)

On Feb 16, 4:58 pm, Jaidev S <j...@travellr.com> wrote:

> Hi,

>

> I am working on an enhancement to the map accessible athttp://travellr.com/map

>

> The idea is to be able to load the map on a country, and have the map

> zoomed to appropriately fit the country. For all countries I have co-

> ordinates and bounding boxes already.

>

> The problem is that whenusingMap.fitBounds(), thezoomlevel

> sometimes isn't quite right - for loading on countries I would like to

> limit zoomwithin a min / max, and places like Russia and Canada

> break out of that. AfterusingMap.fitBounds(), I could then check thezoomlevelonce the zoom_changed event fires, and if required update

> it, but that seems quite a clunky multi step process.

>

> Ideally I would like to be able to calculate thezoomlevelprior to

> instantiating the map. However theAPIv3 does not seem to provide a

> way to do this.

>

> I have read some solutions akin to:

>

> // mnode = the map node

> // bounds = a bounding box

> function best_zoom(bounds, mnode) {

> var width = mnode.offsetWidth;

> var height = mnode.offsetHeight;

>

> var dlat = Math.abs(bounds.maxY - bounds.minY);

> var dlon = Math.abs(bounds.maxX - bounds.minX);

>

> // Center latitude in radians

> var clat = Math.PI*(bounds.minY + bounds.maxY)/360.;

>

> var C = 0.0000107288;

> var z0 = Math.ceil(Math.log(dlat/(C*height))/Math.LN2);

> var z1 = Math.ceil(Math.log(dlon/(C*width*Math.cos(clat)))/

> Math.LN2);

>

> return (z1 > z0) ? z1 : z0;

>

> }

>

> However this does not seem to provide the correctzoomlevels (they

Reply all

Reply to author

Forward

0 new messages

Search

Clear search

Close search

Google apps

Main menu