Nível de zoom ideal no google maps

Eu gostaria de apresentar uma função em coffeescript para calcular o nível de zoom ideal para o Google Maps. Ele usa a fórmula Haversine.

Primeiro, precisamos definir algumas constantes

@MEAN_RADIUS_EARTH_IN_KM = 6371
@DEG_TO_RAD_DIVISOR = 57.2957795
@ZOOM_FACTOR = 1.6446

Precisamos de uma função para converter graus em radianos

toRadians = (degrees) ->
degrees
/ DEG_TO_RAD_DIVISOR

Então precisamos da fórmula Haversine

# Haversine formula to calculate the great-circle distance between two points, i.e. the shortest distance over the earths surface
haversine
= (maxLat, minLat, maxLng, minLng) ->
dLat
= maxLat - minLat
dLng
= maxLng - minLng
a
= Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(minLat) * Math.cos(maxLat) * Math.sin(dLng/2) * Math.sin(dLng/2)
c
= 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))
MEAN_RADIUS_EARTH_IN_KM
* c

Por último, mas não menos importante, precisamos de uma função para calcular o nível de zoom ideal para mapas do Google

optimalZoomLevel = (maxLat, minLat, maxLng, minLng) ->
# min of height and width of element which contains the map
minMapDimension
= Math.min.apply @, [window.mapCanvas.width(),window.mapCanvas.height()]

[maxLat, minLat, maxLng, minLng] = [maxLat, minLat, maxLng, minLng].map (l) -> toRadians(l)
greatCircleDistance
= haversine(maxLat, minLat, maxLng, minLng)
Math.floor(8 - Math.log(ZOOM_FACTOR * greatCircleDistance / Math.sqrt(2 * (minMapDimension * minMapDimension))) / Math.log (2))

Aqui, a função de inicialização do mapa.

initializeMap = (lat, lng, zoomLevel) ->
mapOptions
=
zoom
: zoomLevel
center
: new google.maps.LatLng(lat, lng)
mapTypeId
: google.maps.MapTypeId.ROADMAP
disableDefaultUI
: true

window
.map = new google.maps.Map(window.mapCanvas[0], mapOptions)

Crie uma referência para a tela do seu mapa

window.mapCanvas = $('#map_canvas')

Calcule o nível de zoom

#generate optimal zoom level for Mediterranean area
zoomLevel
= optimalZoomLevel(44.4, 35.0, 32.4, -2.5)

E inicializar o mapa

initializeMap(41.0, 11.0, zoomLevel)