export type BoundingBox = { south: number north: number west: number east: number } export default class GeoLocation { public lat: number public lon: number constructor(lat: number, lon: number) { this.lat = lat this.lon = lon } public toCartesian ( boundingBox: BoundingBox, xMax: number, yMax: number ): {x: number, y: number} { const { lat, lon } = this const { south, north, west, east } = boundingBox const x = ((lon - west) / (east - west)) * xMax const y = ((north - lat) / (north - south)) * yMax return { x, y} } public toString() { return `(${this.lat}, ${this.lon})` } /** * Gives the distance between two points on the Earth's surface using the Haversine formula. * The returned distance is in meters. */ public haversineDistance (other: GeoLocation): number { const R = 6371000 // Earth's radius in meters const toRadians = (deg: number) => (deg * Math.PI) / 180 const dLat = toRadians(other.lat - this.lat) const dLon = toRadians(other.lon - this.lon) const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(toRadians(this.lat)) * Math.cos(toRadians(other.lat)) * Math.sin(dLon / 2) * Math.sin(dLon / 2) const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)) return R * c // Distance in meters } }