Haversine Distance Formula(ここにあります: 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 で遊んでください
他の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;
}
簡単な解決策を試してみませんか? Numberプロトタイプを拡張する代わりに、toRadを通常の関数として定義するだけです。
_function toRad(x) {
return x * Math.PI / 180;
}
_
そしてtoRad
をどこでも呼び出します:
_var dLat = toRad(lat2-lat1);
_
Numberプロトタイプの拡張は、常に期待どおりに機能するとは限りません。たとえば、123.toRad()を呼び出しても機能しません。 var x1 = lat2 - lat1; x1.toRad();
を実行すると、_(lat2-lat1).toRad()
_を実行するよりもうまく機能すると思います
ES6 JavaScript/NodeJSリファクタリングバージョン:
/**
* Calculates the haversine distance between point A, and B.
* @param {number[]} latlngA [lat, lng] point A
* @param {number[]} latlngB [lat, lng] point B
* @param {boolean} isMiles If we are using miles, else km.
*/
const haversineDistance = (latlngA, latlngB, isMiles) => {
const toRadian = angle => (Math.PI / 180) * angle;
const distance = (a, b) => (Math.PI / 180) * (a - b);
const RADIUS_OF_EARTH_IN_KM = 6371;
let lat1 = latlngA[0];
let lat2 = latlngB[0];
const lon1 = latlngA[1];
const lon2 = latlngB[1];
const dLat = distance(lat2, lat1);
const dLon = distance(lon2, lon1);
lat1 = toRadian(lat1);
lat2 = toRadian(lat2);
// Haversine Formula
const a =
Math.pow(Math.sin(dLat / 2), 2) +
Math.pow(Math.sin(dLon / 2), 2) * Math.cos(lat1) * Math.cos(lat2);
const c = 2 * Math.asin(Math.sqrt(a));
let finalDistance = RADIUS_OF_EARTH_IN_KM * c;
if (isMiles) {
finalDistance /= 1.60934;
}
return finalDistance;
};
これを関数の下に置いたとき
test()
を呼び出すポイントの上に配置するだけです。 test
関数自体が宣言されている場所は重要ではありません。
冗長性を削減し、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));
}
関数でこれらの拡張機能を呼び出す前に、Numberプロトタイプを拡張する必要があります。
だからちょうど確認してください
Number.prototype.toRad = function() {
return this * Math.PI / 180;
}
呼び出されますbefore関数が呼び出されます。
JavaScriptでリファクタリングされた別の回答を次に示します。
getHaversineDistance = (firstLocation, secondLocation) => {
const earthRadius = 6371; // km
const diffLat = (secondLocation.lat-firstLocation.lat) * Math.PI / 180;
const diffLng = (secondLocation.lng-firstLocation.lng) * Math.PI / 180;
const arc = Math.cos(
firstLocation.lat * Math.PI / 180) * Math.cos(secondLocation.lat * Math.PI / 180)
* Math.sin(diffLng/2) * Math.sin(diffLng/2)
+ Math.sin(diffLat/2) * Math.sin(diffLat/2);
const line = 2 * Math.atan2(Math.sqrt(arc), Math.sqrt(1-arc));
const distance = earthRadius * line;
return distance;
}
const philly = { lat: 39.9526, lng: -75.1652 }
const nyc = { lat: 40.7128, lng: -74.0060 }
const losAngeles = { lat: 34.0522, lng: -118.2437 }
console.log(getHaversineDistance(philly, nyc)) //129.61277152662188
console.log(getHaversineDistance(philly, losAngeles)) //3843.4534005980404
これはJava上記のtalkolのソリューションの実装です。彼または彼女のソリューションは私たちにとって非常にうまく機能しました。元の質問はjavascriptのためでした。 Java特定のjavascriptソリューションの実装が他の人が使用できる場合に備えて共有するだけです。
// 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;
}