2

目前我使用的公式如下,但不如 Vincenty 公式准确,您可以在此链接上找到: http ://www.movable-type.co.uk/scripts/latlong-vincenty-direct.html

我的问题是,有人可以帮助简化 javascript 代码,以便我可以在我的公式中实现它吗?我正在尝试学习 javascript,但这有点超出我的能力范围。

ex = lat2 ey = lon2

我认为最简单的方法是运行代码并执行 360 度数组来计算 ex/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的直接公式。我正在尝试将此代码放入谷歌地图代码中。活字链接实际上在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

?>
4

1 回答 1

2

由于您提供的链接已经在 javascript 中提供了公式,因此困难的部分已经完成,您可以复制并调用它,而不是将其重写到您的函数中。只记得注明来源。我删除了未使用的变量。另外,我只是硬编码361到公式中,因为您只是将其分配给点变量。如果要将度数传递给公式,则可以将其更改回来。我分离了for循环,对我来说这更具可读性,而且我认为你以前的工作方式不像你想要的那样工作。在使用度数和弧度时,我总是将这些转换包装成函数,因为它提高了可读性。为此,我使用如下所示将它们连接到NumberJavaScript 中的对象:prototype

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 中扩展对象,类似于基于类的语言中的继承。网上有很多资源可以帮助澄清。

这是重新设计的 drawCircle 函数:

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;
}

这是它的工作原理

于 2012-04-16T16:38:59.547 回答