Как конвертировать из (x, y) экранных координат в LatLng (Google Maps)

Я использую приложение с помощью Google Maps и Leap Motion и то, что я хочу прямо сейчас, и я немного застрял, - это способ преобразования (x, y) экранных координат в объект LatLng Google Maps.

Я хочу достичь этого, чтобы начать, например, панораму (Просмотр улиц) в точке, где пользователь указывает с помощью Leap Motion.

Я знаю о наличии функции fromPointToLatLng, но я не знаю, как правильно использовать его и как я могу перевести координаты x и y в переменные lat lng.

Не могли бы вы мне помочь?

Ответ 1

После некоторых исследований и некоторых неудач я придумал решение. Следуя документации из этой ссылки, я узнал, что точки google вычисляются в диапазоне от x: [0-256], y: [0-256] (a плитка составляет 256x256 пикселей), а точка (0,0) - самая левая точка карты (для получения дополнительной информации см. ссылку).

Однако мой подход таков:

  • с координатами x и y (которые являются координатами на экране - на карте) Я вычислил процент, в котором координаты x и y были помещены в ответ на div, содержащий карту (в моем случае отверстие окна)

  • вычислил границы NortEast и SouthWest LatLng (видимой) карты

  • преобразует границы в google Points

  • вычислил новые lat и lng в точках google с помощью границ и процентов от x и y

  • преобразован обратно в 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));
    

Надеюсь, что это решение тоже поможет кому-то!:)

Ответ 2

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);
}

Ответ 4

Добавление альтернативного решения на основе существующего кода вопроса SO, несмотря на то, что оригинальный плакат нашел решение.

Основываясь на этом ответе, мы можем найти необходимую часть для Google Maps API v3 для преобразования. Он фокусируется на изменении положения карты. Для его изменения, чтобы прочитать позицию с экрана, необходимо вычислить разницу в координатах экрана от центра экрана.

Я переименовал функцию для этого примера в pixelOffsetToLatLng и изменил ее, чтобы вернуть позицию (кроме этого, не слишком отличающуюся от кода в ответе выше):

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;
}

Чтобы вызвать его, вам необходимо передать координаты X и Y, которые у вас есть на элементе веб-страницы:

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

Для стороны leap.js вам просто нужно сопоставить координаты leap.js с веб-страницей либо путем экспериментов, либо с помощью плагина с настройками экрана, который работает следующим образом:

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
});

Здесь пример Codepen о том, как читать координаты с помощью Leap.js в 2D-среде: http://codepen.io/raimo/pen/pKIko

Вы можете центрировать представление Карт Google с помощью мыши или захватить вашу руку над контроллером Leap Motion (см. красный "курсор" для визуальной подсказки).

Ответ 5

Судя по всему, Google решил сделать жизнь проще.

Вот встроенное решение:

Point point = googleMap.getProjection.toScreenLocation(latLang)

LatLang latlang = googleMap.getProjection.fromScreenLocation(point)

Ответ 6

С небольшим поиском google я нашел this. Он вычисляет точки с информацией о проекции карт и текущем уровне масштабирования. Сообщение содержит объяснение того, как это работает, хотя оно действительно просто.

Ответ 7

Вам нужно знать (x0,y0) центра вашего элемента карты, (lat0,lng0) центра карты и отношение r градусов на пиксель, соответствующее уровню масштабирования карты. Тогда

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

Обратите внимание, что это упрощенная линеаризованная модель, работающая для карт с небольшими областями.