How to convert from (x, y) screen coordinates to LatLng (Google Maps)

I am implementing an application using Google Maps and Leap Motion and what I want right now, and I am a bit stuck, is a way to convert (x, y) screen coordinates into a Google Maps LatLng object.

I want to achieve this in order to start, for example, a panorama (Street View) at the point where the user is pointing with the Leap Motion.

I know about the presence of fromPointToLatLng function, but I have no clue what is the right approach in using it and how can I translate my x and y coordinates into lat lng variables.

Can you please help me with this?

Answers:

Answer
function latLng2Point(latLng, map) {
  var topRight = map.getProjection().fromLatLngToPoint(map.getBounds().getNorthEast());
  var bottomLeft = map.getProjection().fromLatLngToPoint(map.getBounds().getSouthWest());
  var scale = Math.pow(2, map.getZoom());
  var worldPoint = map.getProjection().fromLatLngToPoint(latLng);
  return new google.maps.Point((worldPoint.x - bottomLeft.x) * scale, (worldPoint.y - topRight.y) * scale);
}

function point2LatLng(point, map) {
  var topRight = map.getProjection().fromLatLngToPoint(map.getBounds().getNorthEast());
  var bottomLeft = map.getProjection().fromLatLngToPoint(map.getBounds().getSouthWest());
  var scale = Math.pow(2, map.getZoom());
  var worldPoint = new google.maps.Point(point.x / scale + bottomLeft.x, point.y / scale + topRight.y);
  return map.getProjection().fromPointToLatLng(worldPoint);
}
Answer

After some research and some fails I came up with a solution. Following the documentation from this link I found out that the google Points are computed in the range of x:[0-256], y:[0-256] (a tile being 256x256 pixels) and the (0,0) point being the leftmost point of the map (check the link for more information).

However, my approach is as it follows:

  • having the x and y coordinates (which are coordinates on the screen - on the map) I computed the percentage where the x and y coordinates were placed in response to the div containing the map (in my case, the hole window)

  • computed the NortEast and SouthWest LatLng bounds of the (visible) map

  • converted the bounds in google Points

  • computed the new lat and lng, in google points, with the help of the boundaries and percentage of x and y

  • converted back to lat lng

      // retrieve the lat lng for the far extremities of the (visible) map
      var latLngBounds = map.getBounds();
      var neBound = latLngBounds.getNorthEast();
      var swBound = latLngBounds.getSouthWest();
    
      // convert the bounds in pixels
      var neBoundInPx = map.getProjection().fromLatLngToPoint(neBound);
      var swBoundInPx = map.getProjection().fromLatLngToPoint(swBound);
    
      // compute the percent of x and y coordinates related to the div containing the map; in my case the screen
      var procX = x/window.innerWidth;
      var procY = y/window.innerHeight;
    
      // compute new coordinates in pixels for lat and lng;
      // for lng : subtract from the right edge of the container the left edge, 
      // multiply it by the percentage where the x coordinate was on the screen
      // related to the container in which the map is placed and add back the left boundary
      // you should now have the Lng coordinate in pixels
      // do the same for lat
      var newLngInPx = (neBoundInPx.x - swBoundInPx.x) * procX + swBoundInPx.x;
      var newLatInPx = (swBoundInPx.y - neBoundInPx.y) * procY + neBoundInPx.y;
    
      // convert from google point in lat lng and have fun :)
      var newLatLng = map.getProjection().fromPointToLatLng(new google.maps.Point(newLngInPx, newLatInPx));
    

Hope this solution will help someone out also! :)

Answer

Check out the easy solution(v3):

map.getProjection().fromLatLngToPoint(marker.position);

https://developers.google.com/maps/documentation/javascript/3.exp/reference#Projection

Answer

Adding an alternate solution based on an existing SO question code, despite the original poster found a solution.

Based on this answer we can find the necessary part for Google Maps API v3 to do the conversion. It focuses on repositioning the center of the map. Modifying it to read the position from the screen requires calculating the difference of the screen coordinates from the screen center.

I renamed the function for the sake of this example to pixelOffsetToLatLng and changed it to return the position (other than that, not too different from the code in the answer above):

function pixelOffsetToLatLng(offsetx,offsety) {
  var latlng = map.getCenter();
  var scale = Math.pow(2, map.getZoom());
  var nw = new google.maps.LatLng(
      map.getBounds().getNorthEast().lat(),
      map.getBounds().getSouthWest().lng()
  );

  var worldCoordinateCenter = map.getProjection().fromLatLngToPoint(latlng);
  var pixelOffset = new google.maps.Point((offsetx/scale) || 0,(offsety/scale) ||0);

  var worldCoordinateNewCenter = new google.maps.Point(
      worldCoordinateCenter.x - pixelOffset.x,
      worldCoordinateCenter.y + pixelOffset.y
  );

  var latLngPosition = map.getProjection().fromPointToLatLng(worldCoordinateNewCenter);

  return latLngPosition;
}

To call it, you need to pass the X and Y coordinates that you have on the web page element:

  var x = mapElement.offsetWidth / 2 - screenPositionX;
  var y = screenPositionY - mapElement.offsetHeight / 2;
  pixelOffsetToLatLng(x,y);

For the leap.js side, you just need to map the leap.js coordinates to the web page, either by experimenting or by using the screen-position plugin that works like this:

var $handCursor = $('#hand-cursor'); // using jQuery here, not mandatory though

Leap.loop(function(frame) {
  if (frame.hands.length > 0) {
    var hand = frame.hands[0];
    $handCursor.css({
      left: hand.screenPosition()[0] + 'px',
      top: hand.screenPosition()[1] + 'px'
    });

    if ((hand.grabStrength >= 0.6 && lastGrabStrength < 0.6)) {
      var x = mapElement.offsetWidth / 2 - hand.screenPosition()[0];
      var y = hand.screenPosition()[1] - mapElement.offsetHeight / 2;
      map.setCenter(pixelOffsetToLatLng(x, y));
    }
  }
}).use('screenPosition', {
  scale: 0.5
});

Here's a Codepen example on how to read the coordinates using Leap.js in 2D environment: http://codepen.io/raimo/pen/pKIko

You can center the Google Maps view using your mouse or by grabbing your hand over the Leap Motion Controller (see the red "cursor" for visual cue).

Answer

Apparently, Google has decided to make life easier.

Here is the built-in solution:

Point point = googleMap.getProjection.toScreenLocation(latLng)

LatLng latlng = googleMap.getProjection.fromScreenLocation(point)

Answer

You need to know (x0,y0) of the center of your map element, (lat0,lng0) of the map center, and the ratio r of degrees per pixel, corresponding to the Map's Zoom level. Then

lat(y) = lat0 + r(y-y0)
lng(x) = lng0 + r(x-x0) 

Note that this is a simplified linearized model, working for maps showing small areas.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.