Google地图会计算一个标题,该标题将两个已知标题分成两部分

时间:2014-10-29 18:57:40

标签: google-maps google-maps-api-3

我使用Google地图中的google.maps.geometry.spherical.computeHeading方法计算JS中Polygon的路径标题。

我想要做的是计算每两个标题之间的标题。

例如,如果第一条路径的标题是45而第二条路线的标题是135,那么我要寻找的标题应该是90.或者如果第一个标题是350而第二个标题是90,标题I& #39;我要找的是40。

我知道我在这里错过了一些基本的几何学(我在学校里从未擅长数学)。

此外,如果有人知道更优雅的方法来获得多边形的两个路径之间的标题,我愿意接受建议。

更新

我实际上找到了解决问题的方法。它不是很优雅,但它与之前提出的SO问题中的答案非常相似。

  /*
   * h1 = first heading
   * h2 = second heading
   *
   */
  if (h1 < 0) {
    h1 = 360 - Math.abs(h1);
  }

  h2 = (h2 >= 180) ? h2 - 180 : h2 + 180;

  // get average of both headings (i.e. the middle)
  bisect = ((h2 + h1) / 2);

  // if bisect is > than the h1, we need the inverse
  if (bisect > h1) {
    bisect = bisect -180;
  }

1 个答案:

答案 0 :(得分:2)

基本答案:

将所有数字保持在-180到+180的范围内,计算最短距离(将小于180; 180是特殊情况,它有两个答案,两个方向垂直于该线)

假设centerMark位于两条线的公共点,angle1marker和angle2marker从该点开始行。

var hdg1 = google.maps.geometry.spherical.computeHeading(centerMark.getPosition(), angle1marker.getPosition());
var hdg2 = google.maps.geometry.spherical.computeHeading(centerMark.getPosition(), angle2marker.getPosition());
if (hdg1 > 180) hdg1 -= 360;
if (hdg1 <= -180) hdg1 += 360;
if (hdg2 > 180) hdg2 -= 360;
if (hdg2 <= -180) hdg2 += 306;

var deltaHdg =  (hdg1 - hdg2);
if (deltaHdg > 180) deltaHdg -= 360;
if (deltaHdg <= -180) deltaHdg += 360;

var bisectHdg = deltaHdg / 2 + hdg2;
var bisectPosn = google.maps.geometry.spherical.computeOffset(centerMark.getPosition(), 1000, bisectHdg);

代码段:

var map;
var infowindow = new google.maps.InfoWindow();
var bisectLine = null;
var bisectMark = null;
var centerMark = null;
var angle1marker = null;
var angle2marker = null;

function initialize() {
  geocoder = new google.maps.Geocoder();
  var latlng = new google.maps.LatLng(-34.397, 150.644);
  var mapOptions = {
    zoom: 15,
    center: latlng
  }
  map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);

  centerMark = new google.maps.Marker({
    map: map,
    position: map.getCenter()
  });
  angle1marker = new google.maps.Marker({
    map: map,
    draggable: true,
    position: google.maps.geometry.spherical.computeOffset(map.getCenter(), 1000, 45)
  });
  google.maps.event.addListener(angle1marker, 'dragend', bisectAngle);

  angle2marker = new google.maps.Marker({
    map: map,
    draggable: true,
    position: google.maps.geometry.spherical.computeOffset(map.getCenter(), 1000, 30)
  });
  google.maps.event.addListener(angle2marker, 'dragend', bisectAngle);

  var poly1 = new google.maps.Polyline({
    path: [centerMark.getPosition(), angle1marker.getPosition()],
    map: map
  });
  poly1.binder = new MVCArrayBinder(poly1.getPath());
  angle1marker.bindTo('position', poly1.binder, '1');

  var poly2 = new google.maps.Polyline({
    path: [centerMark.getPosition(), angle2marker.getPosition()],
    map: map
  });
  poly2.binder = new MVCArrayBinder(poly2.getPath());
  angle2marker.bindTo('position', poly2.binder, '1');

  var bounds = new google.maps.LatLngBounds();
  bounds.extend(centerMark);
  bounds.extend(angle1marker);
  bounds.extend(angle2marker);

  map.fitBounds(bounds);
}
google.maps.event.addDomListener(window, 'load', initialize);

function bisectAngle() {
  var hdg1 = google.maps.geometry.spherical.computeHeading(centerMark.getPosition(), angle1marker.getPosition());
  var hdg2 = google.maps.geometry.spherical.computeHeading(centerMark.getPosition(), angle2marker.getPosition());
  if (hdg1 > 180) hdg1 -= 360;
  if (hdg1 <= -180) hdg1 += 360;
  if (hdg2 > 180) hdg2 -= 360;
  if (hdg2 <= -180) hdg2 += 306;

  var deltaHdg = (hdg1 - hdg2);
  if (deltaHdg > 180) deltaHdg -= 360;
  if (deltaHdg <= -180) deltaHdg += 360;
  var bisectHdg = deltaHdg / 2 + hdg2;
  document.getElementById('info').innerHTML = "a1=" + hdg1.toFixed(2) + ", a2=" + hdg2.toFixed(2) + ", bA=" + bisectHdg.toFixed(2);
  var bisectPosn = google.maps.geometry.spherical.computeOffset(centerMark.getPosition(), 1000, bisectHdg);
  if (bisectMark && bisectMark.setMap) {
    // bisectMark.setMap(null);
    bisectMark.setPosition(bisectPosn);
  } else {
    bisectMark = new google.maps.Marker({
      position: bisectPosn,
      map: map
    });
  }
  if (bisectLine && bisectLine.setMap) {
    // bisectLine.setMap(null);
    bisectLine.setPath([centerMark.getPosition(), bisectPosn]);
  } else {
    bisectLine = new google.maps.Polyline({
      path: [centerMark.getPosition(), bisectPosn],
      map: map
    });
  }
}

/*
 * Use bindTo to allow dynamic drag of markers to refresh poly.
 */

function MVCArrayBinder(mvcArray) {
  this.array_ = mvcArray;
}
MVCArrayBinder.prototype = new google.maps.MVCObject();
MVCArrayBinder.prototype.get = function(key) {
  if (!isNaN(parseInt(key))) {
    return this.array_.getAt(parseInt(key));
  } else {
    this.array_.get(key);
  }
}
MVCArrayBinder.prototype.set = function(key, val) {
  if (!isNaN(parseInt(key))) {
    this.array_.setAt(parseInt(key), val);
  } else {
    this.array_.set(key, val);
  }
}
html,
body,
#map-canvas {
  height: 100%;
  width: 100%;
  margin: 0px;
  padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?sensor=false&libraries=geometry&ext=.js"></script>
<div id="info"></div>
<div id="map-canvas"></div>