Last active
November 14, 2021 15:29
-
-
Save bdchauvette/b115347142b0dd033d89 to your computer and use it in GitHub Desktop.
Code Sample
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
/** Converts degrees to radians */ | |
function toRadians(degrees) { | |
return degrees * Math.PI / 180; | |
} | |
/** Converts DMS coordinate to decimal coordinate */ | |
function toDecimalDegrees(coord) { | |
/** Extracts the digits from an arc unit containing punctuation */ | |
function getDigits(unit) { | |
var digits = /^\d+/; | |
return +unit.match(digits)[0]; | |
} | |
/** Determines whether a coordinate is south of the Equator or west of the Prime Meridian */ | |
function isNegHemisphere(hemisphere) { | |
return (hemisphere === 'S' || hemisphere === 'W'); | |
} | |
var coord = coord.split(' '); | |
var degrees = getDigits(coord[0]); | |
var minutes = getDigits(coord[1]) / 60; | |
var seconds = getDigits(coord[2]) / 60 / 60; | |
var hemisphere = isNegHemisphere(coord[3]) ? -1 : 1; | |
var decimal = (degrees + minutes + seconds) * hemisphere; | |
return decimal; | |
} | |
/** Converts a DMS lat/lng string to a more useful object */ | |
function parseCoords(coord) { | |
var coord = coord.split(', '); | |
return { | |
lat: toDecimalDegrees(coord[0]), | |
lng: toDecimalDegrees(coord[1]) | |
}; | |
} | |
/** Finds the distance in km between two coordinates in DMS */ | |
function distance(coord1, coord2) { | |
var coord1 = parseCoords(coord1); | |
var coord2 = parseCoords(coord2); | |
// Haversine formula | |
// http://www.movable-type.co.uk/scripts/latlong.html | |
var EARTH_RADIUS = 6371; | |
var lat1 = toRadians(coord1.lat); | |
var lat2 = toRadians(coord2.lat); | |
var Δlat = toRadians(coord2.lat - coord1.lat); | |
var Δlng = toRadians(coord2.lng - coord1.lng); | |
var a = Math.sin(Δlat / 2) * Math.sin(Δlat / 2) + | |
Math.cos(lat1) * Math.cos(lat2) * | |
Math.sin(Δlng / 2) * Math.sin(Δlng / 2); | |
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); | |
var d = EARTH_RADIUS * c; | |
// Round the distance to the lower 10km | |
var distance = Math.floor(d / 10) * 10; | |
return distance; | |
} | |
if (process.env.NODE_ENV === 'test') { | |
module.exports = { | |
distance: distance, | |
toRadians: toRadians, | |
toDecimalDegrees: toDecimalDegrees, | |
parseCoords: parseCoords | |
}; | |
} else { | |
module.exports = distance; | |
} |
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
var assert = require('assert'); | |
var distance = require('./distance').distance; | |
var toRadians = require('./distance').toRadians; | |
var toDecimalDegrees = require('./distance').toDecimalDegrees; | |
var parseCoords = require('./distance').parseCoords; | |
describe('toRadians()', function() { | |
it('Converts degrees to radians', function() { | |
assert.equal(toRadians(90), Math.PI / 2); | |
assert.equal(toRadians(180), Math.PI); | |
}); | |
}); | |
describe('toDecimalDegrees()', function() { | |
it('Converts DMS to Decimal', function() { | |
var coords = [ | |
{ dms: '48° 12′ 30″ N', dec: 48.208333333333336 }, | |
{ dms: '16° 22′ 23″ E', dec: 16.373055555555556 }, | |
{ dms: '23° 33′ 0″ S', dec: -23.55 }, | |
{ dms: '46° 38′ 0″ W', dec: -46.63333333333333 }, | |
{ dms: '58° 18′ 0″ N', dec: 58.3 }, | |
{ dms: '134° 25′ 0″ W', dec: -134.41666666666666 }, | |
{ dms: '33° 51′ 35″ S', dec: -33.859722222222224 }, | |
{ dms: '151° 12′ 40″ E', dec: 151.2111111111111 } | |
]; | |
coords.forEach(function(coord) { | |
assert.equal(toDecimalDegrees(coord.dms), coord.dec); | |
}); | |
}); | |
}); | |
describe('parseCoords()', function() { | |
it('Converts a coordinate string to an object', function() { | |
var coords = '47° 48′ 00″ N, 13° 02′ 00″ E'; | |
var expected = { lat: 47.8, lng: 13.033333333333333 }; | |
assert.deepEqual(parseCoords(coords), expected); | |
}); | |
}); | |
describe('distance()', function() { | |
it('Outputs correct distance', function() { | |
var c0 = '47° 48′ 00″ N, 13° 02′ 00″ E'; | |
var c1 = '38° 53′ 42″ N, 77° 02′ 12″ W'; | |
var c2 = '18° 56′ 00″ S, 47° 31′ 00″ E'; | |
var c3 = '22° 54′ 30″ S, 43° 11′ 47″ W'; | |
var c4 = '48° 12′ 30″ N, 16° 22′ 23″ E'; | |
var c5 = '23° 33′ 0″ S, 46° 38′ 0″ W'; | |
var c6 = '48° 12′ 30″ N, 16° 22′ 23″ E'; | |
var c7 = '58° 18′ 0″ N, 134° 25′ 0″ W'; | |
assert.equal(distance(c0, c0), 0); | |
assert.equal(distance(c0, c1), 6920); | |
assert.equal(distance(c1, c3), 7720); | |
assert.equal(distance(c3, c2), 9270); | |
assert.equal(distance(c2, c0), 8170); | |
assert.equal(distance(c2, c1), 14270); | |
assert.equal(distance(c0, c3), 9650); | |
assert.equal(distance(c4, c5), 10130); | |
assert.equal(distance(c6, c7), 7870); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
About
This code was written for the Captain's Distance Request problem at Code Wars.
Description
Complete the function so it returns the distance between two given coordinates. Examples of given coordinates are:
Expected Output
Examples of inputs and the expected outputs: