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
|
||||
export const REPORT_DOWNVOTES_THRESHOLD = 1;
|
||||
|
||||
// Earth radius as recommended by the International Union of Geodesy and
|
||||
// Geophysics
|
||||
// https://rosettacode.org/wiki/Haversine_formula
|
||||
export const EARTH_RADIUS = 6371000; // in meters
|
||||
// Earth radius at equator
|
||||
export const EARTH_RADIUS = 6378137; // in meters
|
||||
|
||||
// Keep reports only in a given radius around map center.
|
||||
export const KEEP_REPORTS_METERS_AROUND = 10000; // in meters
|
||||
|
@ -1,6 +1,5 @@
|
||||
|
||||
import {
|
||||
EARTH_RADIUS,
|
||||
MOCK_LOCATION_GPX_PLAYBACK_SPEED,
|
||||
MOCK_LOCATION_UPDATE_INTERVAL,
|
||||
MOCK_LOCATION_USE_GPX,
|
||||
@ -15,20 +14,25 @@ if (process.env.NODE_ENV !== 'production') {
|
||||
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) {
|
||||
const lat1 = (latLng1[0] * Math.PI) / 180;
|
||||
const lng1 = (latLng1[1] * Math.PI) / 180;
|
||||
const cos = Math.cos((latLng1[0] + latLng2[0]) / 2 * 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;
|
||||
const lng2 = (latLng2[1] * Math.PI) / 180;
|
||||
// Multipliers for converting longitude and latitude degrees into distance
|
||||
// (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 = (
|
||||
(Math.sin((lat2 - lat1) / 2.0) ** 2)
|
||||
+ (Math.cos(lat1) * Math.cos(lat2) * (Math.sin((lng2 - lng1) / 2.0) ** 2))
|
||||
);
|
||||
const c = 2.0 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||
|
||||
return EARTH_RADIUS * c;
|
||||
const dx = (latLng1[1] - latLng2[1]) * kx;
|
||||
const dy = (latLng1[0] - latLng2[0]) * ky;
|
||||
return Math.sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
export function mockLocationRandom() {
|
||||
|
Loading…
Reference in New Issue
Block a user