Last active
May 1, 2024 16:50
-
-
Save missinglink/d0a085188a8eab2ca66db385bb7c023a to your computer and use it in GitHub Desktop.
wrap latitude and longitude values around the poles in order to normalize their ranges
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
/** | |
normalize co-ordinates that lie outside of the normal ranges. | |
longitude wrapping simply requires adding +- 360 to the value until it comes | |
in to range. | |
for the latitude values we need to flip the longitude whenever the latitude | |
crosses a pole. | |
**/ | |
function wrap( lat, lon ){ | |
var point = { lat: lat, lon: lon }; | |
var quadrant = Math.floor( Math.abs( lat ) / 90) % 4; | |
var pole = ( lat > 0 ) ? 90 : -90; | |
var offset = lat % 90; | |
switch( quadrant ){ | |
case 0: | |
point.lat = offset; | |
break; | |
case 1: | |
point.lat = pole - offset; | |
point.lon += 180; | |
break; | |
case 2: | |
point.lat = -offset | |
point.lon += 180; | |
break; | |
case 3: | |
point.lat = -pole + offset; | |
break; | |
} | |
if( point.lon > 180 || point.lon < -180 ){ | |
point.lon -= Math.floor(( point.lon + 180 ) / 360) * 360; | |
} | |
return point; | |
} | |
module.exports = wrap; |
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 wrap = require('./wrap'); | |
module.exports.tests = {}; | |
module.exports.tests.control = function(test, common) { | |
test('control - no wrapping required', function (t) { | |
var norm = wrap(55.555, 22.222); | |
t.equal(norm.lat, 55.555); | |
t.equal(norm.lon, 22.222); | |
t.end(); | |
}); | |
}; | |
module.exports.tests.latitude_positive = function(test, common) { | |
test('positive latitude wrapping - 1 degree', function (t) { | |
var norm = wrap(1, 0); | |
t.equal(norm.lat, 1); | |
t.equal(norm.lon, 0); | |
t.end(); | |
}); | |
test('positive latitude wrapping - 91 degrees', function (t) { | |
var norm = wrap(91, 0); | |
t.equal(norm.lat, 89); | |
t.equal(norm.lon, 180); | |
t.end(); | |
}); | |
test('positive latitude wrapping - 181 degrees', function (t) { | |
var norm = wrap(181, 0); | |
t.equal(norm.lat, -1); | |
t.equal(norm.lon, 180); | |
t.end(); | |
}); | |
test('positive latitude wrapping - 271 degrees', function (t) { | |
var norm = wrap(271, 0); | |
t.equal(norm.lat, -89); | |
t.equal(norm.lon, 0); | |
t.end(); | |
}); | |
test('positive latitude wrapping - 361 degrees', function (t) { | |
var norm = wrap(361, 0); | |
t.equal(norm.lat, 1); | |
t.equal(norm.lon, 0); | |
t.end(); | |
}); | |
test('positive latitude wrapping - 631 degrees', function (t) { | |
var norm = wrap(631, 0); | |
t.equal(norm.lat, -89); | |
t.equal(norm.lon, 0); | |
t.end(); | |
}); | |
test('positive latitude wrapping - 721 degrees', function (t) { | |
var norm = wrap(721, 0); | |
t.equal(norm.lat, 1); | |
t.equal(norm.lon, 0); | |
t.end(); | |
}); | |
}; | |
module.exports.tests.latitude_negative = function(test, common) { | |
test('negative latitude wrapping - 1 degree', function (t) { | |
var norm = wrap(-1, 0); | |
t.equal(norm.lat, -1); | |
t.equal(norm.lon, 0); | |
t.end(); | |
}); | |
test('negative latitude wrapping - 91 degrees', function (t) { | |
var norm = wrap(-91, 0); | |
t.equal(norm.lat, -89); | |
t.equal(norm.lon, 180); | |
t.end(); | |
}); | |
test('negative latitude wrapping - 181 degrees', function (t) { | |
var norm = wrap(-181, 0); | |
t.equal(norm.lat, 1); | |
t.equal(norm.lon, 180); | |
t.end(); | |
}); | |
test('negative latitude wrapping - 271 degrees', function (t) { | |
var norm = wrap(-271, 0); | |
t.equal(norm.lat, 89); | |
t.equal(norm.lon, 0); | |
t.end(); | |
}); | |
test('negative latitude wrapping - 361 degrees', function (t) { | |
var norm = wrap(-361, 0); | |
t.equal(norm.lat, -1); | |
t.equal(norm.lon, 0); | |
t.end(); | |
}); | |
test('negative latitude wrapping - 631 degrees', function (t) { | |
var norm = wrap(-631, 0); | |
t.equal(norm.lat, 89); | |
t.equal(norm.lon, 0); | |
t.end(); | |
}); | |
test('negative latitude wrapping - 721 degrees', function (t) { | |
var norm = wrap(-721, 0); | |
t.equal(norm.lat, -1); | |
t.equal(norm.lon, 0); | |
t.end(); | |
}); | |
}; | |
module.exports.tests.longitude_positive = function(test, common) { | |
test('positive longitude wrapping - 1 degree', function (t) { | |
var norm = wrap(0, 1); | |
t.equal(norm.lat, 0); | |
t.equal(norm.lon, 1); | |
t.end(); | |
}); | |
test('positive longitude wrapping - 181 degrees', function (t) { | |
var norm = wrap(0, 181); | |
t.equal(norm.lat, 0); | |
t.equal(norm.lon, -179); | |
t.end(); | |
}); | |
test('positive longitude wrapping - 271 degrees', function (t) { | |
var norm = wrap(0, 271); | |
t.equal(norm.lat, 0); | |
t.equal(norm.lon, -89); | |
t.end(); | |
}); | |
test('positive longitude wrapping - 361 degrees', function (t) { | |
var norm = wrap(0, 361); | |
t.equal(norm.lat, 0); | |
t.equal(norm.lon, 1); | |
t.end(); | |
}); | |
test('positive longitude wrapping - 631 degrees', function (t) { | |
var norm = wrap(0, 631); | |
t.equal(norm.lat, 0); | |
t.equal(norm.lon, -89); | |
t.end(); | |
}); | |
test('positive longitude wrapping - 721 degrees', function (t) { | |
var norm = wrap(0, 721); | |
t.equal(norm.lat, 0); | |
t.equal(norm.lon, 1); | |
t.end(); | |
}); | |
}; | |
module.exports.tests.longitude_negative = function(test, common) { | |
test('negative longitude wrapping - 1 degree', function (t) { | |
var norm = wrap(0, -1); | |
t.equal(norm.lat, 0); | |
t.equal(norm.lon, -1); | |
t.end(); | |
}); | |
test('negative longitude wrapping - 181 degrees', function (t) { | |
var norm = wrap(0, -181); | |
t.equal(norm.lat, 0); | |
t.equal(norm.lon, 179); | |
t.end(); | |
}); | |
test('negative longitude wrapping - 271 degrees', function (t) { | |
var norm = wrap(0, -271); | |
t.equal(norm.lat, 0); | |
t.equal(norm.lon, 89); | |
t.end(); | |
}); | |
test('negative longitude wrapping - 361 degrees', function (t) { | |
var norm = wrap(0, -361); | |
t.equal(norm.lat, 0); | |
t.equal(norm.lon, -1); | |
t.end(); | |
}); | |
test('negative longitude wrapping - 631 degrees', function (t) { | |
var norm = wrap(0, -631); | |
t.equal(norm.lat, 0); | |
t.equal(norm.lon, 89); | |
t.end(); | |
}); | |
test('negative longitude wrapping - 721 degrees', function (t) { | |
var norm = wrap(0, -721); | |
t.equal(norm.lat, 0); | |
t.equal(norm.lon, -1); | |
t.end(); | |
}); | |
}; | |
module.exports.all = function (tape, common) { | |
function test(name, testFunction) { | |
return tape('SANTIZE wrap ' + name, testFunction); | |
} | |
for( var testCase in module.exports.tests ){ | |
module.exports.tests[testCase](test, common); | |
} | |
}; |
thanks.
You're welcome ;)
I'm not sure how people are finding this gist but I should mention that this was merged into the Pelias geocoder codebase.
:) I believe it showed up in a google search on wrapping lat lon...
The "negative latitude wrapping - 721 degrees" test is not given. Twice the positive latitude wrapping - 721 degrees test is given.
This is great! I ported it to Rust: https://gist.github.com/austenadler/ad22593c9492820a59217b6c84d301d6
Thanks @missinglink. This was really helpful :)
Was very useful, as @rjdverbeek-tud mentioned, there is a test missing / improperly copied.
Oops, I've updated the incorrect test case, thanks for spotting that.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you for your gist. The code let me understand the meaning of wrap !