Skip to content

Instantly share code, notes, and snippets.

@missinglink
Last active May 1, 2024 16:50
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save missinglink/d0a085188a8eab2ca66db385bb7c023a to your computer and use it in GitHub Desktop.
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
/**
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;
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);
}
};
@zhuang-hao-ming
Copy link

Thank you for your gist. The code let me understand the meaning of wrap !

@johanjohan
Copy link

thanks.

@missinglink
Copy link
Author

missinglink commented Jul 5, 2020

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.

@johanjohan
Copy link

:) I believe it showed up in a google search on wrapping lat lon...

@rjdverbeek-tud
Copy link

The "negative latitude wrapping - 721 degrees" test is not given. Twice the positive latitude wrapping - 721 degrees test is given.

@austenadler
Copy link

@lantson
Copy link

lantson commented Dec 13, 2023

Thanks @missinglink. This was really helpful :)

@ClancyWalters
Copy link

Was very useful, as @rjdverbeek-tud mentioned, there is a test missing / improperly copied.

@missinglink
Copy link
Author

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