在Javascript中使用Haversine公式
我试图使用Haversine距离公式(在这里find: http : //www.movable-type.co.uk/scripts/latlong.html ),但我不能得到它的工作,请参阅下面的代码
function test() { var lat2 = 42.741; var lon2 = -71.3161; var lat1 = 42.806911; var lon1 = -71.290611; var R = 6371; // km //has a problem with the .toRad() method below. var dLat = (lat2-lat1).toRad(); var dLon = (lon2-lon1).toRad(); var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) * Math.sin(dLon/2) * Math.sin(dLon/2); var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); var d = R * c; alert(d); }
而错误是:
Uncaught TypeError: Object -0.06591099999999983 has no method 'toRad'
我所理解的是因为它需要做到以下几点:
Number.prototype.toRad = function() { return this * Math.PI / 180; }
但是当我把它放在函数下面时,它仍然会返回相同的错误信息。 我如何使用辅助方法? 还是有其他的方法来编码这个工作吗? 谢谢!
此代码正在工作:
Number.prototype.toRad = function() { return this * Math.PI / 180; } var lat2 = 42.741; var lon2 = -71.3161; var lat1 = 42.806911; var lon1 = -71.290611; var R = 6371; // km //has a problem with the .toRad() method below. var x1 = lat2-lat1; var dLat = x1.toRad(); var x2 = lon2-lon1; var dLon = x2.toRad(); var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) * Math.sin(dLon/2) * Math.sin(dLon/2); var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); var d = R * c; alert(d);
注意我是如何定义x1和x2的。 玩在: https : //tinker.io/3f794
为什么不尝试直接的解决scheme? 而不是扩展Number原型,只需将toRad定义为常规函数即可:
function toRad(x) { return x * Math.PI / 180; }
然后到处叫:
var dLat = toRad(lat2-lat1);
数字原型扩展并不总是按预期方式工作。 例如调用123.toRad()不起作用。 我认为,如果你做var x1 = lat2 - lat1; x1.toRad();
var x1 = lat2 - lat1; x1.toRad();
比(lat2-lat1).toRad()
这是基于其他答案中的3个重构函数!
请注意coords的论据是[经度,纬度]。
function haversineDistance(coords1, coords2, isMiles) { function toRad(x) { return x * Math.PI / 180; } var lon1 = coords1[0]; var lat1 = coords1[1]; var lon2 = coords2[0]; var lat2 = coords2[1]; var R = 6371; // km var x1 = lat2 - lat1; var dLat = toRad(x1); var x2 = lon2 - lon1; var dLon = toRad(x2) var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2); var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); var d = R * c; if(isMiles) d /= 1.60934; return d; }
当我把这个function下面
你只需要把它放在你调用test()
。 test
函数本身被声明的地方并不重要。
在函数中调用这些扩展之前,需要扩展Number原型。
所以只要确保
Number.prototype.toRad = function() { return this * Math.PI / 180; }
在你的函数被调用之前调用。
另一种减less冗余的变体,也与Google LatLng对象兼容:
function haversine_distance(coords1, coords2) { function toRad(x) { return x * Math.PI / 180; } var dLat = toRad(coords2.latitude - coords1.latitude); var dLon = toRad(coords2.longitude - coords1.longitude) var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(toRad(coords1.latitude)) * Math.cos(toRad(coords2.latitude)) * Math.sin(dLon / 2) * Math.sin(dLon / 2); return 12742 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); }
以上是talkol解决scheme的java实现。 他或她的解决scheme对我们来说工作得非常好。 我不是想回答这个问题,因为原来的问题是为了JavaScript。 我只是分享我们的给定的JavaScript解决scheme的Java实现,以防其他人发现它的使用。
// this was a pojo class we used internally... public class GisPostalCode { private String country; private String postalCode; private double latitude; private double longitude; // getters/setters, etc. } public static double distanceBetweenCoordinatesInMiles2(GisPostalCode c1, GisPostalCode c2) { double lat2 = c2.getLatitude(); double lon2 = c2.getLongitude(); double lat1 = c1.getLatitude(); double lon1 = c1.getLongitude(); double R = 6371; // km double x1 = lat2 - lat1; double dLat = x1 * Math.PI / 180; double x2 = lon2 - lon1; double dLon = x2 * Math.PI / 180; double a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(lat1*Math.PI/180) * Math.cos(lat2*Math.PI/180) * Math.sin(dLon/2) * Math.sin(dLon/2); double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); double d = R * c; // convert to miles return d / 1.60934; }