Google Maps Api рисует мой многоугольник (прямоугольник) в виде параллелограмма - PullRequest
0 голосов
/ 19 сентября 2018

Я не могу справиться с рисованием прямоугольника между двумя городами.Я искал повсюду в Интернете и не могу выяснить, почему мой многоугольник нарисован на Картах Google в виде параллелограмма, даже если на двухмерной плоскости (не плоскости земли) этот прямоугольник нарисован правильно.

Что я заметил, так эточто стороны кривизны параллелограмма зависят от расположения городов на карте.Если два города расположены напротив, моя функция успешно рисует прямоугольник.Но если они расположены по диагонали, то моя функция рисует параллелограмм.В результате следует повернуть прямоугольник с высотой как расстоянием между двумя городами и шириной в виде километров, выбранных пользователем.

Вот моя функция, которая должна рисовать прямоугольник между двумя городами.В качестве аргументов нам нужно указать положение первого города ($ x1 - широта, $ y1 - lng), положение второго города, а в качестве третьего аргумента - радиус в километрах ($ l1) от центральной точки прямоугольника.

function getPolygon($x1,$y1,$x2,$y2,$l1){
    var $l1 = $l1*0.010526; //approx kilometers

    var $distanceV = [($x2 - $x1), ($y2 - $y1)];
    var $vlen = Math.sqrt(Math.pow($distanceV[0], 2) + 
    Math.pow($distanceV[1],2));
    if($vlen == 0)
      return [[0,0],[0,0],[0,0],[0,0]];
    var $l2 = $vlen;
    var $normalized = [($distanceV[0] / $vlen), ($distanceV[1] / $vlen)];
    var $rotated = [(-1 * $normalized[1]), ($normalized[0])];
    var $p1 = [($x1 - $rotated[0] * $l1 / 2), ($y1 - $rotated[1] * $l1 / 2)];
    var $p2 = [($p1[0] + $rotated[0] * $l1), ($p1[1] + $rotated[1] * $l1)];
    var $p3 = [($p1[0] + $normalized[0] * $l2), ($p1[1] + $normalized[1] * $l2)];
    var $p4 = [($p3[0] + $rotated[0] * $l1), ($p3[1] + $rotated[1] * $l1)];

    var $points = [
    {lat: $p1[0], lng: $p1[1]},
    {lat: $p3[0], lng: $p3[1]},
    {lat: $p4[0], lng: $p4[1]},
    {lat: $p2[0], lng: $p2[1]},
    {lat: $p1[0], lng: $p1[1]}
    ];

   return $points;
}

Затем я нарисую его на Google Maps следующим образом:

new google.maps.Polygon({
  paths: getPolygon(first_city_lat, first_city_lng, second_city_lat, second_city_lng, 30),
  strokeColor: '#FF0000',
  strokeOpacity: 0.5,
  strokeWeight: 2,
  fillColor: '#FF0000',
  fillOpacity: 0.05
});

Вот пример, который должен быть прямоугольником между Бирмингемом и Оксфордом: JSFiddle

screenshot of issue

Кроме того, я уверен, что конвертер километров не является точным, и это опять-таки зависит от расположения городов.

1 Ответ

0 голосов
/ 20 сентября 2018

Земля изогнута.Чтобы получить многоугольник, который выглядит прямоугольным на искривленной сфере, вам нужно использовать вычисления, учитывающие проекцию карты.

В JavaScript API Карт Google v3 имеется библиотека сферической геометрии это может быть использовано для вычисления желаемых точек.

function getPolygon($x1,$y1,$x2,$y2,$l1){
  var points = [];
  var city1 = new google.maps.LatLng($x1, $y1);
  var city2 = new google.maps.LatLng($x2, $y2);
  var heading = google.maps.geometry.spherical.computeHeading(city1, city2);
  points.push(google.maps.geometry.spherical.computeOffset(city1, $l1/2*1000, heading+90));
  points.push(google.maps.geometry.spherical.computeOffset(city1, $l1/2*1000, heading-90));
  points.push(google.maps.geometry.spherical.computeOffset(city2, $l1/2*1000, heading-90));
  points.push(google.maps.geometry.spherical.computeOffset(city2, $l1/2*1000, heading+90));
  points.push(points[0]);
  return points;
}

подтверждение концепции скрипта

screenshot of resulting map

фрагмент кода:

var map;
google.maps.event.addDomListener(window, "load", function() {
  var map = new google.maps.Map(document.getElementById("map_div"), {
    center: new google.maps.LatLng(52.489471, -1.898575),
    zoom: 8,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  });

  var trace = new google.maps.Polygon({
    paths: getPolygon(52.489471, -1.898575, 51.752022, -1.257677, 30),
    strokeColor: '#FF0000',
    strokeOpacity: 0.5,
    strokeWeight: 2,
    fillColor: '#FF0000',
    fillOpacity: 0.05,
    map: map
  });

  var bounds = new google.maps.LatLngBounds();
  for (var i = 0; i < trace.getPath().getLength(); i++) {
    bounds.extend(trace.getPath().getAt(i));
  }
  map.fitBounds(bounds);

  function getPolygon($x1, $y1, $x2, $y2, $l1) {
    var points = [];
    var city1 = new google.maps.LatLng($x1, $y1);
    var city2 = new google.maps.LatLng($x2, $y2);
    var heading = google.maps.geometry.spherical.computeHeading(city1, city2);
    points.push(google.maps.geometry.spherical.computeOffset(city1, $l1 / 2 * 1000, heading + 90));
    points.push(google.maps.geometry.spherical.computeOffset(city1, $l1 / 2 * 1000, heading - 90));
    points.push(google.maps.geometry.spherical.computeOffset(city2, $l1 / 2 * 1000, heading - 90));
    points.push(google.maps.geometry.spherical.computeOffset(city2, $l1 / 2 * 1000, heading + 90));
    points.push(points[0]);
    return points;
  }
});
html,
body {
  height: 100%;
  width: 100%;
  margin: 0px;
  padding: 0px;
}

#map_div {
  height: 95%;
}
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?libraries=geometry"></script>
<div id="map_div"></div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...