diff --git a/sanitiser/wrap.js b/sanitiser/wrap.js index f1a482e5..c89088e7 100644 --- a/sanitiser/wrap.js +++ b/sanitiser/wrap.js @@ -1,23 +1,37 @@ /** 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 flip = false; var point = { lat: lat, lon: lon }; - - // north pole - if( point.lat > 90 ){ - point.lat = 90 - point.lat % 90; - point.lon += 180; - } - - // south pole - else if( point.lat < -90 ){ - point.lat = -90 - point.lat % 90; - point.lon += 180; + 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; } // reduce lon diff --git a/test/unit/sanitiser/_geo_common.js b/test/unit/sanitiser/_geo_common.js index d8e174d3..93ec5d11 100644 --- a/test/unit/sanitiser/_geo_common.js +++ b/test/unit/sanitiser/_geo_common.js @@ -12,60 +12,61 @@ module.exports.tests.interface = function(test, common) { }); }; +// @note: for better coverage see unit tests for 'wrap.js'. module.exports.tests.wrapping = function(test, common) { test('control - no wrapping required', function (t) { var clean = {}; var params = { - 'point.lat': 40.7, - 'point.lon': -73.9 + 'point.lat': +1.1, + 'point.lon': -1.1 }; sanitize.sanitize_point( 'point', clean, params, false ); - t.equal(clean['point.lat'], params['point.lat']); - t.equal(clean['point.lon'], params['point.lon']); + t.equal(clean['point.lat'], +1.1, 'not changed'); + t.equal(clean['point.lon'], -1.1, 'not changed'); t.end(); }); test('positive longitude wrapping', function (t) { var clean = {}; var params = { - 'point.lat': 40.7, - 'point.lon': 195.1 + 'point.lat': +1.1, + 'point.lon': +181.1 }; sanitize.sanitize_point( 'point', clean, params, false ); - t.equal(clean['point.lat'], 40.7); - t.equal(clean['point.lon'], -164.9); + t.equal(clean['point.lat'], +1.1, 'not changed'); + t.equal(clean['point.lon'], -178.9, 'equal to (-180 + 1.1)'); t.end(); }); test('negative longitude wrapping', function (t) { var clean = {}; var params = { - 'point.lat': 40.7, - 'point.lon': -195.1 + 'point.lat': -1.1, + 'point.lon': -181.1 }; sanitize.sanitize_point( 'point', clean, params, false ); - t.equal(clean['point.lat'], 40.7); - t.equal(clean['point.lon'], 164.9); + t.equal(clean['point.lat'], -1.1, 'not changed'); + t.equal(clean['point.lon'], +178.9, 'equal to (+180 - 1.1)'); t.end(); }); test('positive latitudinal wrapping', function (t) { var clean = {}; var params = { - 'point.lat': 98.1, - 'point.lon': -73.9 + 'point.lat': 91.1, + 'point.lon': 1.1 }; sanitize.sanitize_point( 'point', clean, params, false ); - t.equal(clean['point.lat'], 81.9); - t.equal(clean['point.lon'], 106.1); + t.equal(clean['point.lat'], +88.9, 'equal to (+90 - 1.1)'); + t.equal(clean['point.lon'], -178.9, 'equal to (-180 - 1.1)'); // polar flip t.end(); }); test('negative latitudinal wrapping', function (t) { var clean = {}; var params = { - 'point.lat': -98.1, - 'point.lon': -73.9 + 'point.lat': -91.1, + 'point.lon': -1.1 }; sanitize.sanitize_point( 'point', clean, params, false ); - t.equal(clean['point.lat'], -81.9); - t.equal(clean['point.lon'], 106.1); + t.equal(clean['point.lat'], -88.9, 'equal to (-90 + 1.1)'); + t.equal(clean['point.lon'], +178.9, 'equal to (+180 - 1.1)'); // polar flip t.end(); }); }; diff --git a/test/unit/sanitiser/wrap.js b/test/unit/sanitiser/wrap.js index 73e2ec0e..ea9a75a5 100644 --- a/test/unit/sanitiser/wrap.js +++ b/test/unit/sanitiser/wrap.js @@ -3,59 +3,179 @@ var wrap = require('../../../sanitiser/wrap'); module.exports.tests = {}; -module.exports.tests.wrapping = function(test, common) { +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(); }); - test('positive longitude wrapping', function (t) { +}; + +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('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.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 (double)', function (t) { - var norm = wrap(0, 541); + test('positive longitude wrapping - 271 degrees', function (t) { + var norm = wrap(0, 271); t.equal(norm.lat, 0); - t.equal(norm.lon, -179); + t.equal(norm.lon, -89); t.end(); }); - test('negative longitude wrapping', function (t) { - var norm = wrap(0, -181); + test('positive longitude wrapping - 361 degrees', function (t) { + var norm = wrap(0, 361); t.equal(norm.lat, 0); - t.equal(norm.lon, 179); + 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('negative longitude wrapping (double)', function (t) { - var norm = wrap(0, -541); + 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('positive latitudinal wrapping', function (t) { - var norm = wrap(91, 0); - t.equal(norm.lat, 89); - t.equal(norm.lon, 180); + 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('positive latitudinal wrapping (double)', function (t) { - var norm = wrap(271, 0); - t.equal(norm.lat, 89); - t.equal(norm.lon, 180); + 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 latitudinal wrapping', function (t) { - var norm = wrap(-91, 0); - t.equal(norm.lat, -89); - t.equal(norm.lon, 180); + 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 latitudinal wrapping (double)', function (t) { - var norm = wrap(-271, 0); - t.equal(norm.lat, -89); - t.equal(norm.lon, 180); + 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(); }); };