5
votes

Lets say I request this image from the google static maps API

https://maps.googleapis.com/maps/api/staticmap?center=52.591370,-2.110748&zoom=18&size=600x600&maptype=satellite&markers=color:blue|52.591370,-2.110748

I get a 600px x 600px image centered at 52.591370,-2.110748. Given the center, the image size and the zoom level, how can I calculate the bounding box of the image in lat lng coordinates. More specifically, how can I calculate the lat/lng of the the bottom left corner and the top right corner.

I have done some research and looked at mercator projection but the articles keep mentioning tile size which is not relevant in this case.

Can anyone help ?

2

2 Answers

4
votes
const _C = { x: 128, y: 128 };
const _J = 256 / 360;
const _L = 256 / (2 * Math.PI);

function tb(a) {
    return 180 * a / Math.PI
}

function sb(a) {
    return a * Math.PI / 180
}

function bounds(a, b, c) {
    null != b && (a = Math.max(a, b));
    null != c && (a = Math.min(a, c));
    return a
}

function latlonToPt(ll) {
  a = bounds(Math.sin(sb(ll[0])), -(1 - 1E-15), 1 - 1E-15);
  return {
    x: _C.x + ll[1] * _J,
    y: _C.y + 0.5 * Math.log((1 + a) / (1 - a)) * - _L
  }
}

function ptToLatlon(pt) {
    return [tb(2 * Math.atan(Math.exp((pt.y - _C.y) / -_L)) - Math.PI / 2),(pt.x - _C.x) / _J]
}


function calculateBbox(ll, zoom, sizeX, sizeY) {
    const cp = latlonToPt(ll);
    const pixelSize = Math.pow(2, -(zoom+1));
    const pwX = sizeX*pixelSize;
    const pwY = sizeY*pixelSize;

    return {
      ne: ptToLatlon({x: cp.x + pwX, y: cp.y - pwY}),
      sw: ptToLatlon({x: cp.x - pwX, y: cp.y + pwY})
    }
}

This solution doesn't require including the Google Map client side map. See example: https://jsfiddle.net/1wy1mm7L/6/

0
votes

I can explain how to calculate NorthEast and SouthWest points of bounding box using Maps JavaScript API.

You have a center position and know that distance from the center to the NorthEast and SouthWest is 300 pixels in both axis.

Have a look at the following code that calculates NE and SW points

var map;
function initMap() {
  var latLng = new google.maps.LatLng(52.591370, -2.110748);

  map = new google.maps.Map(document.getElementById('map'), {
      center: latLng,
      zoom: 18,
      mapTypeId: google.maps.MapTypeId.SATELLITE
  });

  var marker = new google.maps.Marker({
      position: latLng,
      map: map
  });

  google.maps.event.addListener(map, "idle", function() {
      //Verical and horizontal distance from center in pixels
      var h = 300;
      var w = 300;

      var centerPixel = map.getProjection().fromLatLngToPoint(latLng);
      var pixelSize = Math.pow(2, -map.getZoom());

      var nePoint = new google.maps.Point(centerPixel.x + w*pixelSize, centerPixel.y - h*pixelSize);
      var swPoint = new google.maps.Point(centerPixel.x - w*pixelSize, centerPixel.y + h*pixelSize);

      var ne = map.getProjection().fromPointToLatLng(nePoint);
      var sw = map.getProjection().fromPointToLatLng(swPoint);

      var neMarker = new google.maps.Marker({
        position: ne,
        map: map,
        title: "NE: " + ne.toString()
      });

      var swMarker = new google.maps.Marker({
        position: sw,
        map: map,
        title: "SW: " + sw.toString()
      });

      var polygon = new google.maps.Polygon({
          paths: [ne, new google.maps.LatLng(ne.lat(),sw.lng()), sw, new google.maps.LatLng(sw.lat(),ne.lng())],
          map: map, 
          strokeColor: "green"
      });

      console.log("NE: " + ne.toString());
      console.log("SW: " + sw.toString());

  });
}
#map {
  height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html, body {
  height: 100%;
  margin: 0;
  padding: 0;
}
<div id="map"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDztlrk_3CnzGHo7CFvLFqE_2bUKEq1JEU&libraries=geometry&callback=initMap"
    async defer></script>

You can see this example at jsbin as well: http://jsbin.com/jahocos/edit?html,output

Hope this helps!