JavaScript 和 Google map 圈

标签 javascript google-maps-api-3

目前我使用的公式如下,但它不如 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

?>

最佳答案

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

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

不太难理解,原型(prototype)允许您在 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;
}

这是一个fiddle of it working .

关于JavaScript 和 Google map 圈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10175499/

相关文章:

java - windows下如何设置keytool的密码?

ssl - 通过 SSL 使用 Google map API

javascript - 在 Reactjs 中隐藏分页页码

javascript - 拖动和突出显示

javascript - 如何使用 Javascript 在 iframe 中设置 src

javascript - Google map 标记退出需要点击两次

javascript - 谷歌地图地理编码不起作用

javascript - 使用 Firebase Cloud Functions 将值从一个节点复制到多个其他节点

javascript - 集成 CKEditor API 以编程方式在组件中进行调用

google-maps-api-3 - Google map 中的标记掉落事件?