-
Notifications
You must be signed in to change notification settings - Fork 101
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Distance check approximation * Adjust for 180 deg wraparound in equirectangular distance approximation
- Loading branch information
Showing
4 changed files
with
61 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,55 @@ | ||
const degreesToRadians = (degrees: number) => { | ||
return degrees * Math.PI / 180; | ||
import { Location } from "../types/Location"; | ||
|
||
const degToRad = Math.PI / 180.0; | ||
const radians = (degrees: number) => degrees * degToRad; | ||
|
||
// Radius of Earth in meters | ||
const radiusOfEarth = 6371000; | ||
|
||
// Radius squared of Earth in square meters | ||
const radiusOfEarthSqr = radiusOfEarth * radiusOfEarth; | ||
|
||
export const isWithinRadiusMeters = (p1: Location, p2: Location, r: number): boolean => { | ||
// The equirectangular approximation becomes significantly inaccurate at distances about about 1.5 km | ||
if (r > 1500.0) { | ||
return haversineDistanceCheck(p1, p2, r); | ||
} else { | ||
return equirectangularDistanceCheck(p1, p2, r); | ||
} | ||
} | ||
|
||
const getEquirectangularDistanceSqr = (p1: Location, p2: Location) => { | ||
// Calculate the difference in longitude, adjusting for the 180 deg wraparound | ||
var dLon = p2.lon - p1.lon; | ||
if (dLon > 180.0) dLon -= 360.0; | ||
if (dLon < -180.0) dLon += 360.0; | ||
|
||
const dx = radians(dLon) * Math.cos(radians(p2.lat + p1.lat) / 2.0); | ||
const dy = radians(p2.lat - p1.lat); | ||
|
||
return radiusOfEarthSqr * (dx * dx + dy * dy); | ||
} | ||
|
||
// An approximate distance check which maps spherical points onto a flat surface to quickly estimate distance | ||
const equirectangularDistanceCheck = (p1: Location, p2: Location, r: number): boolean => { | ||
const rSqr = r * r; | ||
const distSqr = getEquirectangularDistanceSqr(p1, p2); | ||
|
||
return distSqr <= rSqr; | ||
} | ||
|
||
export const calculateDistanceInMeters = (lat1: number, lon1: number, lat2: number, lon2: number) => { | ||
const earthRadiusKm = 6371; | ||
// A more accurate distance check for points on the surface of a sphere | ||
const haversineDistanceCheck = (p1: Location, p2: Location, r: number): boolean => { | ||
const lat1 = radians(p1.lat); | ||
const lon1 = radians(p1.lon); | ||
const lat2 = radians(p2.lat); | ||
const lon2 = radians(p2.lon); | ||
|
||
const dLat = degreesToRadians(lat2-lat1); | ||
const dLon = degreesToRadians(lon2-lon1); | ||
const dLat = lat2 - lat1; | ||
const dLon = lon2 - lon1; | ||
|
||
lat1 = degreesToRadians(lat1); | ||
lat2 = degreesToRadians(lat2); | ||
const a = Math.pow(Math.sin(dLat / 2.0), 2) + Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(dLon / 2.0), 2); | ||
const c = 2.0 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); | ||
|
||
const a = Math.sin(dLat/2) * Math.sin(dLat/2) + | ||
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2); | ||
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); | ||
return earthRadiusKm * c * 1000; | ||
return c * radiusOfEarth <= r; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export interface Location { | ||
lat: number | ||
lon: number | ||
geohash: string | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters