4

我正在尝试使用 google maps API V3 从默认起点画一条线,并在给定距离的情况下进入给定方向。例如,假设我的默认起点是旧金山,并且用户输入了一个距离,我希望能够根据该输入距离绘制一条向东穿过美国的直线。我遇到了一个叫做轴承的东西,但我不确定如何正确使用它。这是我正在使用的代码:

function initializeMap(){

var mapOptions = {
center: new google.maps.LatLng(36.033036, -93.8655744),
zoom: 4,
mapTypeId: google.maps.MapTypeId.ROADMAP
};   

var map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);

var R = 6378137;
var dis = parseInt(document.form['input']['val'].value);
var bearing = 80; 
var lat2 = Math.asin(   Math.sin(37.470625)*Math.cos(dis/R)+Math.cos(37.470625)*Math.sin(dis/R)*Math.cos(bearing) );
var lon2 = -122.266823 + Math.atan2(Math.sin(bearing)*Math.sin(dis/R)*Math.cos(37.470625),Math.cos(dis/R)-Math.sin(37.470625)*Math.sin(-122.266823));


var impactP = new google.maps.Polyline({
  path: new google.maps.LatLng(lat2,lon2), 
              strokeColor: "#FF0000",
  strokeOpacity: 1.0,
          strokeWeight: 2
        });
impactP.setMap(map);
}

有人可以帮帮我吗?我真的很想让这个工作。

4

3 回答 3

3

数学都在这里解释:http ://www.movable-type.co.uk/scripts/latlong.html#destPoint

var lat2 = Math.asin( Math.sin(lat1)*Math.cos(d/R) + 
              Math.cos(lat1)*Math.sin(d/R)*Math.cos(brng) );
var lon2 = lon1 + Math.atan2(Math.sin(brng)*Math.sin(d/R)*Math.cos(lat1), 
                     Math.cos(d/R)-Math.sin(lat1)*Math.sin(lat2));

请注意,lat1,lon1(您的起点)和lat2,lon2(终点)是弧度而不是度数。d是行进的距离和R地球的半径。只要它们是相同的单位,它们就可以是任何单位。

如果您以弧度工作,看起来您在问题中的代码可以工作。

如果您在北半球以 90° 的方位开始,您最终会稍微向南(您的最终方位将超过 90°)。球面几何真是个奇妙的东西!

如果您想要一条恒定方位线,因此 90° 线在地图上是直线且水平的,您需要 Rhumb 线:http ://www.movable-type.co.uk/scripts/latlong.html#rhumblines 。这要复杂得多,但该页面再次允许根据距离和方位计算端点,并解释了必要的数学和 Javascript。


同一页面建议向 Number 添加方法以将度数转换为弧度并再次转换:

/** Converts numeric degrees to radians */
if (typeof(Number.prototype.toRad) === "undefined") {
  Number.prototype.toRad = function() {
    return this * Math.PI / 180;
  }
}

/** Converts radians to numeric (signed) degrees */
if (typeof(Number.prototype.toDeg) === "undefined") {
  Number.prototype.toDeg = function() {
    return this * 180 / Math.PI;
  }
}

因此(78).toRad()1.3613568

于 2012-04-19T15:45:41.667 回答
0

我把谷歌地图脚手架http://jsfiddle.net/khwLd/但我的数学是关闭的:(你可以看到线转向南方。谷歌搜索“查找终端坐标给定方位和距离”给了我一个我转换并检查了但仍未给出预期结果的python函数。

计算给定方位和距离的坐标

您需要做的是在开始时修复所有数学,以便:

getDestination(origin_lat, origin_lng, bearing, distance) 返回 google.maps.LatLng(destination_lat, destination_lng)

抱歉,我无法提供完整的工作解决方案 :(

于 2012-04-19T15:29:20.193 回答
0

您可以使用Chris VenessrhumbDestinationPoint的库https://github.com/chrisveness/geodesy中的方法,另请参见此处http://www.movable-type.co.uk/scripts/latlong.html

rhumbDestinationPoint应用于LatLon对象,并以米为单位的距离作为第一个参数,第二个参数是六十进制的方位,即0北、90东、180南和270西。

rhumbDestinationPoint我刚刚从https://raw.githubusercontent.com/chrisveness/geodesy/master/latlon-spherical.js粘贴到下面的片段(改编自 OP http://jsfiddle.net/X25dZ/1/

function initializeMap() {
  mapCenter = new google.maps.LatLng(36.033036, -93.8655744);
  defaultStart = new google.maps.LatLng(37.470625, -122.266823);
  var mapOptions = {
    center: mapCenter,
    zoom: 2,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };

  var map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);

  var distance_in_meter = 600000;
  var bearing = 90;

  var start = new LatLon(defaultStart.lat(), defaultStart.lng());
  var destination = start.rhumbDestinationPoint(distance_in_meter, bearing);

  var impactP = new google.maps.Polyline({
    map: map,
    path: [defaultStart,
      new google.maps.LatLng(destination.lat, destination.lon)
    ],
    strokeColor: "#FF0000",
    strokeOpacity: 1.0,
    strokeWeight: 2
  });
}

google.maps.event.addDomListener(window, 'load', initializeMap);
html {
  height: 100%
}
body {
  height: 100%;
  margin: 0;
  padding: 0
}
#map-canvas {
  height: 100%
}
#menu {
  position: absolute;
  top: 0px;
  left: 0px;
  padding: 0px;
  font-family: Arial, sans-serif;
}
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>


<script type="text/javascript">
// Taken from https://raw.githubusercontent.com/chrisveness/geodesy/master/latlon-spherical.js	
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
/* Latitude/longitude spherical geodesy tools                         (c) Chris Veness 2002-2016  */
/*                                                                                   MIT Licence  */
/* www.movable-type.co.uk/scripts/latlong.html                                                    */
/* www.movable-type.co.uk/scripts/geodesy/docs/module-latlon-spherical.html                       */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
'use strict';
if (typeof module!='undefined' && module.exports) var Dms = require('./dms'); // ≡ import Dms from 'dms.js'
/**
 * Library of geodesy functions for operations on a spherical earth model.
 *
 * @module   latlon-spherical
 * @requires dms
 */
/**
 * Creates a LatLon point on the earth's surface at the specified latitude / longitude.
 *
 * @constructor
 * @param {number} lat - Latitude in degrees.
 * @param {number} lon - Longitude in degrees.
 *
 * @example
 *     var p1 = new LatLon(52.205, 0.119);
 */
function LatLon(lat, lon) {
// allow instantiation without 'new'
if (!(this instanceof LatLon)) return new LatLon(lat, lon);
this.lat = Number(lat);
this.lon = Number(lon);
}

/**
 * Returns the destination point having travelled along a rhumb line from ‘this’ point the given
 * distance on the  given bearing.
 *
 * @param   {number} distance - Distance travelled, in same units as earth radius (default: metres).
 * @param   {number} bearing - Bearing in degrees from north.
 * @param   {number} [radius=6371e3] - (Mean) radius of earth (defaults to radius in metres).
 * @returns {LatLon} Destination point.
 *
 * @example
 *     var p1 = new LatLon(51.127, 1.338);
 *     var p2 = p1.rhumbDestinationPoint(40300, 116.7); // 50.9642°N, 001.8530°E
 */
LatLon.prototype.rhumbDestinationPoint = function(distance, bearing, radius) {
radius = (radius === undefined) ? 6371e3 : Number(radius);
var δ = Number(distance) / radius; // angular distance in radians
var φ1 = this.lat.toRadians(), λ1 = this.lon.toRadians();
var θ = Number(bearing).toRadians();
var Δφ = δ * Math.cos(θ);
var φ2 = φ1 + Δφ;
// check for some daft bugger going past the pole, normalise latitude if so
if (Math.abs(φ2) > Math.PI/2) φ2 = φ2>0 ? Math.PI-φ2 : -Math.PI-φ2;
var Δψ = Math.log(Math.tan(φ2/2+Math.PI/4)/Math.tan(φ1/2+Math.PI/4));
var q = Math.abs(Δψ) > 10e-12 ? Δφ / Δψ : Math.cos(φ1); // E-W course becomes ill-conditioned with 0/0
var Δλ = δ*Math.sin(θ)/q;
var λ2 = λ1 + Δλ;
return new LatLon(φ2.toDegrees(), (λ2.toDegrees()+540) % 360 - 180); // normalise to −180..+180°
};


/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
/**
 * Checks if another point is equal to ‘this’ point.
 *
 * @param   {LatLon} point - Point to be compared against this point.
 * @returns {bool}   True if points are identical.
 *
 * @example
 *   var p1 = new LatLon(52.205, 0.119);
 *   var p2 = new LatLon(52.205, 0.119);
 *   var equal = p1.equals(p2); // true
 */
LatLon.prototype.equals = function(point) {
if (!(point instanceof LatLon)) throw new TypeError('point is not LatLon object');
if (this.lat != point.lat) return false;
if (this.lon != point.lon) return false;
return true;
};
/**
 * Returns a string representation of ‘this’ point, formatted as degrees, degrees+minutes, or
 * degrees+minutes+seconds.
 *
 * @param   {string} [format=dms] - Format point as 'd', 'dm', 'dms'.
 * @param   {number} [dp=0|2|4] - Number of decimal places to use - default 0 for dms, 2 for dm, 4 for d.
 * @returns {string} Comma-separated latitude/longitude.
 */
LatLon.prototype.toString = function(format, dp) {
return Dms.toLat(this.lat, format, dp) + ', ' + Dms.toLon(this.lon, format, dp);
};
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
/** Extend Number object with method to convert numeric degrees to radians */
if (Number.prototype.toRadians === undefined) {
Number.prototype.toRadians = function() { return this * Math.PI / 180; };
}
/** Extend Number object with method to convert radians to numeric (signed) degrees */
if (Number.prototype.toDegrees === undefined) {
Number.prototype.toDegrees = function() { return this * 180 / Math.PI; };
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
if (typeof module != 'undefined' && module.exports) module.exports = LatLon; // ≡ export default LatLon    </script>


<div id="map-canvas"></div>

于 2017-02-04T13:39:25.627 回答