2012-04-16 87 views
2

目前我使用的公式如下,但它是作爲Vincenty公式,你可以找到這個鏈接不太準確: http://www.movable-type.co.uk/scripts/latlong-vincenty-direct.html的Javascript和谷歌地圖圈

我的問題是,有人可以幫助簡化JavaScript代碼,所以我可以在我的公式中實現它?我正在嘗試學習JavaScript,但它超出了我的能力。

EX = LAT2 EY = lon2

林思的最簡單的方法是將通過代碼運行,並做360度以計算前/ EY座標的陣列。

<script type="text/javascript"> 

function drawCircle(point, radius, dir, addtoBounds) { 
var d2r = Math.PI/180; // degrees to radians 
var r2d = 180/Math.PI; // radians to degrees 
var earthsradius = 6378137; 

    var points = 360; 

    // find the radius in lat/lon 
    var rlat = (radius/earthsradius) * r2d; 
    var rlng = rlat/Math.cos(point.lat() * d2r); 


    var extp = new Array(); 
    if (dir==1) {var start=0;var end=points+1} // one extra here makes sure we connect the 
    else  {var start=points+1;var end=0} 
    for (var i=start; (dir==1 ? i < end : i > end); i=i+dir) 
    { 
    var theta = Math.PI * (i/(points/2));//i is number of points + 1 
var lat1=point.lat()*d2r; 
var lon1=point.lng()*d2r; 
var d=radius; 
var R=earthsradius; 

var ex = Math.asin(Math.sin(lat1)*Math.cos(d/R) + 
       Math.cos(lat1)*Math.sin(d/R)*Math.cos(theta)); 
var ey = lon1 + Math.atan2(Math.sin(theta)*Math.sin(d/R)*Math.cos(lat1), 
       Math.cos(d/R)-Math.sin(lat1)*Math.sin(ex)); 
    extp.push(new google.maps.LatLng(ex*r2d, ey*r2d)); 
    if (addtoBounds) bounds.extend(extp[extp.length-1]); 



    } 
    // alert(extp.length); 
    return extp; 


    } 

這裏是直接的公式轉換爲php。我正在嘗試將此代碼放入Google地圖代碼中。可移動類型的鏈接實際上在JavaScript中有這樣的代碼,但由於我知道PHP更好,我轉換它來測試它,這完美的作品。

<?php 
$lat1 = 29.10860062; 
$lon1 = -95.46209717; 
$a = 6378137; 
$b = 6356752.314245; 
$f = 1/298.257223563; // WGS-84 ellipsoid params 
$brng = 32.8; 


$s = 1796884.48; 
$alpha1 = deg2rad($brng); 
$sinAlpha1 = sin($alpha1); 
$cosAlpha1 = cos($alpha1); 
$tanU1 = (1-$f) * tan(deg2rad($lat1)); 
$cosU1 = 1/sqrt((1 + pow($tanU1,2))); 
$sinU1 = $tanU1*$cosU1; 
$sigma1 = atan2($tanU1, $cosAlpha1); 
$sinAlpha = $cosU1 * $sinAlpha1; 
$cosSqAlpha = 1 - pow($sinAlpha,2); 
$uSq = $cosSqAlpha * (pow($a,2) - pow($b,2))/(pow($b,2)); 
$A = 1 + $uSq/16384*(4096+$uSq*(-768+$uSq*(320-175*$uSq))); 
$B = $uSq/1024 * (256+$uSq*(-128+$uSq*(74-47*$uSq))); 
$sigma = $s/($b*$A); 
$sigmaP = 2*pi; 

$limit = 100; 
$counter = 1; 

while ($counter <= $limit) { 
$cos2SigmaM = cos(2*$sigma1 + $sigma); 
$sinSigma = sin($sigma); 
$cosSigma = cos($sigma); 
$deltaSigma = $B*$sinSigma*($cos2SigmaM+$B/4*($cosSigma*(-1+2*pow($cos2SigmaM,2))-$B/6*$cos2SigmaM*(-3+4*pow($sinSigma,2))*(-3+4*pow($cos2SigmaM,2)))); 
$sigmaP = $sigma; 
$sigma = $s/($b*$A) + $deltaSigma; 
$counter = $counter+1; 
}; 

$tmp = $sinU1*$sinSigma - $cosU1*$cosSigma*$cosAlpha1; 
$lat2 = atan2($sinU1*$cosSigma + $cosU1*$sinSigma*$cosAlpha1,(1-$f)*sqrt(pow($sinAlpha,2)+ pow($tmp,2))); 
$lambda = atan2($sinSigma*$sinAlpha1, $cosU1*$cosSigma - $sinU1*$sinSigma*$cosAlpha1); 
$C = $f/16*$cosSqAlpha*(4+$f*(4-3*$cosSqAlpha)); 
$L = $lambda - (1-$C) * $f * $sinAlpha *($sigma + $C*$sinSigma*($cos2SigmaM+$C*$cosSigma*(-1+2*pow($cos2SigmaM,2)))); 

if (deg2rad($lon1)+$L+(3*pi)<(2*pi)) { 
( $lon2 = (deg2rad($lon1)+$L+(3*pi))-pi); 
} else { 
( $lon2 = ((deg2rad($lon1)+$L+3*pi))%(2*pi))-pi;} 

$revAz = atan2($sinAlpha, -$tmp); // final bearing, if required 

?> 
+1

[此問題及其答案](http://stackoverflow.com/questions/10027094/holes-in-a-polygon)有幫助嗎? – 2012-04-16 13:59:37

+1

我很欣賞你把這段代碼放進去的時間。我非常感謝它,但正如我做了一些挖掘。我發現Haversine公式對於我所需要的不太準確。 Vincenty公式是我正在尋找的。我正試圖使你的代碼適應新的公式。任何幫助都會很棒。再次感謝你。 – 2012-04-16 14:06:21

+1

啊哈。與名稱不符。 – 2012-04-16 14:38:27

回答

2

既然你提供的鏈接已經提供了在JavaScript中最難的部分是完整的公式,你可以複製它,並調用它,而不是重寫它給你的函數。只要記住來源。我刪除了未被使用的變量。另外,我只是將361硬編碼到公式中,因爲您只是將它分配給點變量。如果您要將度數傳遞到公式中,您可以將其更改回來。我分開for循環,對我來說這更具可讀性,我不認爲你以前的方式像你打算的那樣工作。當使用度和弧度時,我總是將這些轉換包裝到函數中,因爲它提高了可讀性。要做到這一點,我用prototype迷上了,直到Number對象JavaScript作爲這裏看到:

Number.prototype.toRad = function() { 
    //'this' is the current number the function is acting on. 
    //e.g. 360.toRad() == 2PI radians 
    return this * Math.PI/180; 
} 

Number.prototype.toDeg = function() { 
    return this * 180/Math.PI; 
} 

不太難理解,原型,您可以擴展在JavaScript對象,類似於基於類的語言繼承。網上有很多資源可以幫助澄清。

這裏是返工畫圓功能:

function drawCircle(point, radius, dir, addtoBounds) { 
    //best practice is to use [] rather then new Array(), 
    //both do the same thing. 
    var extp = []; 
    if (dir == 1) { 
     for (var i = 0; i < 361; i++) { 
      //destVincenty function returns a object with 
      //lat, lon, and final bearing.  
      var destPoint = destVincenty(point.lat(), point.lng(), i, radius); 

      //add new point 
      extp.push(new google.maps.LatLng(destPoint.lat, destPoint.lon)); 
      if (addtoBounds) bounds.extend(extp[extp.length - 1]); 
     } 
    } 
    else { 
     for (var i = 361; i > 0; i--) {  
      var destPoint = destVincenty(point.lat(), point.lng(), i, radius); 
      extp.push(new google.maps.LatLng(destPoint.lat, destPoint.lon)); 
      if (addtoBounds) bounds.extend(extp[extp.length - 1]); 
     } 
    } 

    return extp; 
} 

這裏是一個fiddle of it working

+1

我確定了爲什麼我的學習速度很慢,它不會告訴你錯誤在哪裏,就像php一樣。布萊恩,在我給了我這個代碼讓它工作了一小時後,我花了一個小時,不得不改變一些東西,這個公式完美無瑕。我添加了Andrew Leach上週提供的陰影(請參閱他發佈的鏈接)。非常感謝你的時間。 – 2012-04-16 18:56:33

+1

是的,JavaScript調試有時可能會很痛苦。有許多工具可以幫助定位和調試錯誤。以下是一些最常見的列表。就我個人而言,我喜歡Firebug和IE9內置的開發者工具。 http://www.smashingmagazine.com/2008/11/18/15-helpful-in-browser-web-development-tools/ – 2012-04-16 19:45:28