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