From 6eaf84d9e2180136f270205377f099dec041c5a1 Mon Sep 17 00:00:00 2001 From: ztimson Date: Fri, 30 Aug 2019 14:09:09 -0400 Subject: [PATCH] Added some new geo math utilities --- .../dimensionsDialog.component.ts | 2 +- src/app/services/map.service.ts | 4 +- src/app/utils.ts | 47 ++++++++++++++----- 3 files changed, 38 insertions(+), 15 deletions(-) diff --git a/src/app/components/dimensionsDialog/dimensionsDialog.component.ts b/src/app/components/dimensionsDialog/dimensionsDialog.component.ts index 3c7771f..4941ee3 100644 --- a/src/app/components/dimensionsDialog/dimensionsDialog.component.ts +++ b/src/app/components/dimensionsDialog/dimensionsDialog.component.ts @@ -10,7 +10,7 @@ export class DimensionsDialogComponent { dimensionsOut: number[]; constructor(private ref: MatDialogRef, @Inject(MAT_DIALOG_DATA) public dimensions: string[]) { - this.dimensionsOut = Array(dimensions.length).fill(0); + this.dimensionsOut = Array(dimensions.length).fill(null); } close() { diff --git a/src/app/services/map.service.ts b/src/app/services/map.service.ts index dad7ce3..15ddd74 100644 --- a/src/app/services/map.service.ts +++ b/src/app/services/map.service.ts @@ -1,5 +1,5 @@ import {BehaviorSubject} from "rxjs"; -import {distanceInM} from "../utils"; +import {latLngDistance} from "../utils"; import {environment} from "../../environments/environment"; import {Circle, LatLng, Marker, Measurement} from "../models/mapSymbol"; @@ -146,7 +146,7 @@ export class MapService { let group = L.layerGroup([line, decoration]).addTo(this.map); group.symbol = m; line.on('click', e => this.click.next({event: e, symbol: group})); - let distance = distanceInM(m.latlng.lat, m.latlng.lng, m.latlng2.lat, m.latlng2.lng); + let distance = latLngDistance(m.latlng, m.latlng2); line.bindPopup(`${distance > 1000 ? Math.round(distance / 100) / 10 : Math.round(distance)} ${distance > 1000 ? 'k' : ''}m`, {autoClose: false, closeOnClick: false}).openPopup(); return group; } diff --git a/src/app/utils.ts b/src/app/utils.ts index b3014a9..cacc12f 100644 --- a/src/app/utils.ts +++ b/src/app/utils.ts @@ -1,3 +1,7 @@ +import {LatLng} from "./models/mapSymbol"; + +export const R = 6_371; // Radius of the Earth + export function copyToClipboard(value: string) { let el = document.createElement('textarea'); el.value = value; @@ -10,18 +14,37 @@ export function copyToClipboard(value: string) { } export function deg2rad(deg) { - return deg * (Math.PI/180); + return deg * Math.PI / 180; } -export function distanceInM(lat1: number, lon1: number, lat2: number, lon2: number) { - const R = 6371; // Radius of the earth in km - let dLat = deg2rad(lat2-lat1); // deg2rad below - let dLon = deg2rad(lon2-lon1); - let a = - Math.sin(dLat/2) * Math.sin(dLat/2) + - Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * - Math.sin(dLon/2) * Math.sin(dLon/2) - ; - let c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); - return R * c * 1000 +export function latLngBearing(latLng, latLng2) { + let dLng = (latLng2.lng - latLng.lng); + let y = Math.sin(dLng) * Math.cos(latLng2.lat); + let x = Math.cos(latLng.lat) * Math.sin(latLng2.lat) - Math.sin(latLng.lat) * Math.cos(latLng2.lat) * Math.cos(dLng); + return (360 - ((rad2deg(Math.atan2(y, x)) + 360) % 360)); +} + +export function latLngDistance(latLng, latLng2) { + let dLat = deg2rad(latLng2.lat - latLng.lat); + let dLng = deg2rad(latLng2.lng - latLng.lng); + let a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(deg2rad(latLng.lat)) * Math.cos(deg2rad(latLng2.lat)) * Math.sin(dLng/2) * Math.sin(dLng/2); + return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)) * 1000 +} + +export function rad2deg(rad) { + return rad * 180 / Math.PI +} + +export function relativeLatLng(latLng: LatLng, meters: number, deg: number) { + let brng = deg2rad(deg); + let d = meters / 1000; + let lat = deg2rad(latLng.lat); + let lng = deg2rad(latLng.lng); + + let latOut = Math.asin(Math.sign(lat) * Math.cos(d / R) + Math.cos(lat) * Math.sin(d / R) * Math.cos(brng)); + let lngOut = lng + Math.atan2(Math.sin(brng) * Math.sin(d / R) * Math.cos(lat), Math.cos(d / R) - Math.sin(lat) * Math.sin(latOut)); + latOut = rad2deg(latOut); + lngOut = rad2deg(lngOut); + + return {lat: latOut, lng: lngOut}; }