Use cheap-ruler rather than Haversine formula
This commit is contained in:
parent
ff1b987463
commit
ce58f5f601
@ -31,10 +31,8 @@ export const UPDATE_REPORTS_DISTANCE_THRESHOLD = 500; // in meters
|
|||||||
// Minimal number of downvotes needed for a report to be masked
|
// Minimal number of downvotes needed for a report to be masked
|
||||||
export const REPORT_DOWNVOTES_THRESHOLD = 1;
|
export const REPORT_DOWNVOTES_THRESHOLD = 1;
|
||||||
|
|
||||||
// Earth radius as recommended by the International Union of Geodesy and
|
// Earth radius at equator
|
||||||
// Geophysics
|
export const EARTH_RADIUS = 6378137; // in meters
|
||||||
// https://rosettacode.org/wiki/Haversine_formula
|
|
||||||
export const EARTH_RADIUS = 6371000; // in meters
|
|
||||||
|
|
||||||
// Keep reports only in a given radius around map center.
|
// Keep reports only in a given radius around map center.
|
||||||
export const KEEP_REPORTS_METERS_AROUND = 10000; // in meters
|
export const KEEP_REPORTS_METERS_AROUND = 10000; // in meters
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
EARTH_RADIUS,
|
|
||||||
MOCK_LOCATION_GPX_PLAYBACK_SPEED,
|
MOCK_LOCATION_GPX_PLAYBACK_SPEED,
|
||||||
MOCK_LOCATION_UPDATE_INTERVAL,
|
MOCK_LOCATION_UPDATE_INTERVAL,
|
||||||
MOCK_LOCATION_USE_GPX,
|
MOCK_LOCATION_USE_GPX,
|
||||||
@ -15,20 +14,25 @@ if (process.env.NODE_ENV !== 'production') {
|
|||||||
mockGPX = require('mock_gpx.json'); // eslint-disable-line global-require
|
mockGPX = require('mock_gpx.json'); // eslint-disable-line global-require
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cheap distance computation based on
|
||||||
|
* https://blog.mapbox.com/fast-geodesic-approximations-with-cheap-ruler-106f229ad016.
|
||||||
|
*/
|
||||||
export function distance(latLng1, latLng2) {
|
export function distance(latLng1, latLng2) {
|
||||||
const lat1 = (latLng1[0] * Math.PI) / 180;
|
const cos = Math.cos((latLng1[0] + latLng2[0]) / 2 * Math.PI / 180);
|
||||||
const lng1 = (latLng1[1] * Math.PI) / 180;
|
const cos2 = 2 * cos * cos - 1;
|
||||||
|
const cos3 = 2 * cos * cos2 - cos;
|
||||||
|
const cos4 = 2 * cos * cos3 - cos2;
|
||||||
|
const cos5 = 2 * cos * cos4 - cos3;
|
||||||
|
|
||||||
const lat2 = (latLng2[0] * Math.PI) / 180;
|
// Multipliers for converting longitude and latitude degrees into distance
|
||||||
const lng2 = (latLng2[1] * Math.PI) / 180;
|
// (http://1.usa.gov/1Wb1bv7)
|
||||||
|
kx = 1000 * (111.41513 * cos - 0.09455 * cos3 + 0.00012 * cos5);
|
||||||
|
ky = 1000 * (111.13209 - 0.56605 * cos2 + 0.0012 * cos4);
|
||||||
|
|
||||||
const a = (
|
const dx = (latLng1[1] - latLng2[1]) * kx;
|
||||||
(Math.sin((lat2 - lat1) / 2.0) ** 2)
|
const dy = (latLng1[0] - latLng2[0]) * ky;
|
||||||
+ (Math.cos(lat1) * Math.cos(lat2) * (Math.sin((lng2 - lng1) / 2.0) ** 2))
|
return Math.sqrt(dx * dx + dy * dy);
|
||||||
);
|
|
||||||
const c = 2.0 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
||||||
|
|
||||||
return EARTH_RADIUS * c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mockLocationRandom() {
|
export function mockLocationRandom() {
|
||||||
|
Loading…
Reference in New Issue
Block a user