2012-04-19 71 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>