Google Maps Api将我的多边形(矩形)绘制为平行四边形

时间:2018-09-19 13:04:28

标签: javascript google-maps-api-3

我无法在两个城市之间绘制矩形。我在互联网上到处搜索过,甚至找不到在2d平面(而非地球平面)上正确绘制矩形的原因,为什么我的多边形在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地图上绘制它:

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 :(得分:0)

地球是弯曲的。要获得在弯曲球体上显示为矩形的多边形,需要使用考虑到地图投影的计算。

Google Maps Javascript API v3具有spherical geometry library,可用于计算所需的点。

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

proof of concept fiddle

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>