|
/* |
|
* get DMS from DD |
|
*/ |
|
function getDms(val) { |
|
let degrees, minutes, seconds, result; |
|
|
|
val = Math.abs(val); |
|
|
|
degrees = Math.floor(val); |
|
result = degrees + "º "; |
|
|
|
minutes = Math.floor((val - degrees) * 60); |
|
result += minutes + "' "; |
|
|
|
seconds = Math.round((val - degrees - minutes / 60) * 3600 * 1000) / 1000; |
|
result += seconds + '" '; |
|
|
|
return result; |
|
} |
|
|
|
/* |
|
* finalize conversion from DD to DMS |
|
* returns coordinates as a string in format X-XX° X-XX′ X-XX″ (N|S), X-XX° X-XX′ X-XX″ (E|W) |
|
*/ |
|
function ddToDms(lat, lng) { |
|
let latDMS, lngDMS, resultDMS; |
|
|
|
lat = parseFloat(lat); |
|
lng = parseFloat(lng); |
|
|
|
latDMS = getDms(lat); |
|
latDMS += (lat >= 0)? 'N' : 'S'; |
|
|
|
lngDMS = getDms(lng); |
|
lngDMS += (lng >= 0)? 'E' : 'W'; |
|
|
|
resultDMS = latDMS + ', ' + lngDMS; |
|
|
|
return resultDMS; |
|
} |
|
|
|
/* |
|
* get distance between two GPS coordinates |
|
* returns distance between GPS coordinates in kilometers |
|
* coordinates should be provided in format X-XX° X-XX′ X-XX″ (N|S), X-XX° X-XX′ X-XX″ (E|W) |
|
*/ |
|
function getDistance(coord1, coord2) { |
|
coord1 = coord1.split(', ').map(item => unescape(item).split(/[º'"]\s/)); |
|
coord2 = coord2.split(', ').map(item => unescape(item).split(/[º'"]\s/)); |
|
const R = 6371; |
|
let lat1 = (coord1[0][3] === 'S') ? -1 : 1; |
|
let lat2 = (coord2[0][3] === 'S') ? -1 : 1; |
|
let lon1 = (coord1[1][3] === 'W') ? -1 : 1; |
|
let lon2 = (coord2[1][3] === 'W') ? -1 : 1; |
|
|
|
coord1 = coord1.map(item => item.map(itm => parseInt(itm))); |
|
coord2 = coord2.map(item => item.map(itm => parseInt(itm))); |
|
|
|
lat1 = lat1 * (coord1[0][0] + (coord1[0][1] + coord1[0][2] / 60) / 60); |
|
lat2 = lat2 * (coord2[0][0] + (coord2[0][1] + coord2[0][2] / 60) / 60); |
|
lon1 = lon1 * (coord1[1][0] + (coord1[1][1] + coord1[1][2] / 60) / 60); |
|
lon2 = lon2 * (coord2[1][0] + (coord2[1][1] + coord2[1][2] / 60) / 60); |
|
|
|
const latDiff = (lat2 - lat1) * Math.PI / 180; |
|
const lonDiff = (lon2 - lon1) * Math.PI / 180; |
|
|
|
lat1 = lat1 * Math.PI / 180; |
|
lat2 = lat2 * Math.PI / 180; |
|
lon1 = lon1 * Math.PI / 180; |
|
lon2 = lon2 * Math.PI / 180; |
|
|
|
const x = Math.pow(Math.sin(latDiff/2), 2) + Math.pow(Math.sin(lonDiff/2), 2) * Math.cos(lat1) * Math.cos(lat2); |
|
const y = 2 * Math.atan2(Math.sqrt(x), Math.sqrt(1 - x)); |
|
const distance = R * y; |
|
return distance; |
|
} |
|
|
|
/* |
|
* TEST 1 |
|
*/ |
|
let coord1 = '47° 28′ 0″ N, 13° 2′ 0″ E'; |
|
let coord2 = '47° 28′ 0″ N, 13° 2′ 0″ E'; |
|
|
|
const distance1 = getDistance(coord1, coord2); // 0 |
|
console.log('distance1:', distance1); |
|
|
|
/* |
|
* TEST 2 |
|
* convert given DD coordinates to DMS first, then get distance |
|
*/ |
|
const lat1 = 90; |
|
const lng1 = 81; |
|
const lat2 = 45; |
|
const lng2 = 93; |
|
|
|
const dmsCoords1 = ddToDms(lat1, lng1); |
|
const dmsCoords2 = ddToDms(lat2, lng2); |
|
console.log('dmsCoords1:', dmsCoords1); |
|
console.log('dmsCoords2:', dmsCoords2); |
|
|
|
const distance2 = getDistance(dmsCoords1, dmsCoords2); |
|
console.log('distance2:', distance2); |