2012-04-19 90 views
2

嘿家伙,所以我试图使用谷歌地图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); 
} 

有人可以帮我解决请。我真的想让这个工作。

+0

我需要大约正是你正在尝试做的更多的信息。我可以帮助Google地图的一部分,我不太了解数学。我建议你用变量替换37.470625和-122.266823。这些是你的目的地吗?我对代码做了一些更改,以便从地图中心绘制一条直线到计算出的lat2,lon2。 http://jsfiddle.net/X25dZ/ – 2012-04-19 14:24:49

+0

基本上我想让用户能够在远处输入。然后我想在这个距离的谷歌地图上绘制一条线,但仅限于我的默认起点的东边。所以基本上我会有一条线在美国横跨整个美国,因为我想我的出发点是在旧金山。具有挑战性的是我没有明确地有一个终点。我只有默认的起点和线的距离。所以例如最后我的地图看起来像这样:http://jsfiddle.net/X25dZ/1/ – cclerville 2012-04-19 15:02:19

回答

0

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

Calculating coordinates given a bearing and a distance

你需要做的是解决所有的数学开头,这样什么:

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

对不起,我没能产生一个完整的工作解决方案:(

+0

这帮助了我很多。谢谢! – cclerville 2012-04-20 19:53:34

2

的数学是一切都在这里解释: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。


在同一页建议添加方法到号码,从度转换为弧度,然后再返回:

/** 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

0

可以通过克里斯俯伏使用的方法rhumbDestinationPoint从库https://github.com/chrisveness/geodesy,也参见这里http://www.movable-type.co.uk/scripts/latlong.html

rhumbDestinationPoint应用于LatLon对象和以六十进制需要作为第一个参数在米,作为第二个参数的轴承的距离度,即0是北,90是东,180是南和270是西。

我刚刚粘贴从https://raw.githubusercontent.com/chrisveness/geodesy/master/latlon-spherical.jsrhumbDestinationPoint下面的代码片段(改编自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 \t 
 
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 
 
/* 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>