diff --git a/README.md b/README.md index 7453af5..5dd0299 100644 --- a/README.md +++ b/README.md @@ -16,15 +16,50 @@ Simple Examples --------------- ```javascript +'use strict'; + +var S2 = require('s2-geometry').S2; + +var lat = 40.2574448; +var lng = -111.7089464; var level = 15; -var latlng = { lat: 40.2574448, lng: -111.7089464 }; -var cell = S2.S2Cell.FromLatLng(latlng, level); -cell.getNeighbors(); // [ cellLeft, cellDown, cellRight, cellUp ] -cell.getLatLng(); // { lat: 40.2574448, lng: -111.7089464 } -var key = cell.toHilbertQuadkey(); +// +// Convert from Lat / Lng +// +var key = S2.latLngToKey(lat, lng, level); +// '4/032212303102210' + + + +// +// Convert between Hilbert Curve Quadtree Key and S2 Cell Id +// +var id = S2.keyToId(key); +// '9749618446378729472' + +var key = S2.idToKey(id); +// '9749618446378729472' + + + +// +// Neighbors +// +var neighbors = S2.latLngToNeighborKeys(lat, lng, level); +// [ keyLeft, keyDown, keyRight, keyUp ] + + + +// +// Previous, Next, and Step +// +var nextKey = S2.nextKey(key); +var prevKey = S2.prevKey(key); + +var backTenKeys = S2.stepKey(key, -10); ``` Previous and Next @@ -37,14 +72,16 @@ You can get the previous and next S2CellId from any given Key: 3. Convert the Key to an Id (uint64 string) ```javascript -var key = S2.latLngToKey(40.2574448, -111.7089464); // '4/032212303102210' -var id = S2.toId(key); // '9749618446378729472' +var key = S2.latLngToKey(40.2574448, -111.7089464, 15); // '4/032212303102210' +var id = S2.keyToId(key); // '9749618446378729472' var nextKey = S2.nextKey(key); -var nextId = S2.toId(nextKey); +var nextId = S2.keyToId(nextKey); var prevKey = S2.prevKey(key); -var prevId = S2.toId(prevKey); +var prevId = S2.keyToId(prevKey); + +var backTenKeys = S2.stepKey(key, -10); // See it console.log(prevKey); // '4/032212303102203' @@ -53,7 +90,7 @@ console.log(nextKey); // '4/032212303102211' console.log(nextId); ``` -convert Cell Id to Quadkey +convert Cell Id to Hilbert Curve Quad Tree ------------------ Convert from base 10 (decimal) `S2 Cell Id` to base 4 `quadkey` (aka hilbert curve quadtree id) @@ -69,7 +106,7 @@ var face = parts[0]; // 4 var position = parts[1]; // '032212303102210'; var level = '032212303102210'.length; // 15 -var cellId = S2.fromFacePosLevel(face, position, level); +var cellId = S2.facePosLevelToId(face, position, level); console.log(cellId); ``` @@ -83,7 +120,7 @@ Example '9749618446378729472' becomes '4/032212303102210' var cellId = '9749618446378729472'; -var hilbertQuadkey = S2.toHilbertQuadkey(cellId); +var hilbertQuadkey = S2.idToKey(cellId); console.log(hilbertQuadkey); ``` diff --git a/src/s2geometry.js b/src/s2geometry.js index 9667bd2..b13b09d 100644 --- a/src/s2geometry.js +++ b/src/s2geometry.js @@ -186,7 +186,7 @@ S2.IJToST = function(ij,order,offsets) { // note: rather then calculating the final integer hilbert position, we just return the list of quads // this ensures no precision issues whth large orders (S3 cell IDs use up to 30), and is more // convenient for pulling out the individual bits as needed later -var pointToHilbertQuadList = function(x,y,order,sq) { +var pointToHilbertQuadList = function(x,y,order,face) { var hilbertMap = { 'a': [ [0,'d'], [1,'a'], [3,'b'], [2,'a'] ], 'b': [ [2,'b'], [1,'b'], [3,'a'], [0,'c'] ], @@ -194,7 +194,10 @@ var pointToHilbertQuadList = function(x,y,order,sq) { 'd': [ [0,'a'], [3,'c'], [1,'d'], [2,'d'] ] }; - var currentSquare=sq||'a'; + if ('number' !== typeof face) { + console.warn(new Error("called pointToHilbertQuadList without face value, defaulting to '0'").stack); + } + var currentSquare = (face % 2) ? 'd' : 'a'; var positions = []; for (var i=order-1; i>=0; i--) { @@ -286,36 +289,21 @@ S2.S2Cell.prototype.getCornerLatLngs = function() { S2.S2Cell.prototype.getFaceAndQuads = function () { - var sq; - - switch(this.face) { - case 0: - /* fallthru */ - case 2: - /* fallthru */ - case 4: - sq = 'a'; - break; - - case 1: - /* fallthru */ - case 3: - /* fallthru */ - case 5: - sq = 'd'; - break; - } - - var quads = pointToHilbertQuadList(this.ij[0], this.ij[1], this.level, sq); + var quads = pointToHilbertQuadList(this.ij[0], this.ij[1], this.level, this.face); return [this.face,quads]; }; S2.S2Cell.prototype.toHilbertQuadkey = function () { - var quads = pointToHilbertQuadList(this.ij[0], this.ij[1], this.level); + var quads = pointToHilbertQuadList(this.ij[0], this.ij[1], this.level, this.face); return this.face.toString(10) + '/' + quads.join(''); }; +S2.latLngToNeighborKeys = S2.S2Cell.latLngToNeighborKeys = function (lat, lng, level) { + return S2.S2Cell.FromLatLng({ lat: lat, lng: lng }, level).getNeighbors().map(function (cell) { + return cell.toHilbertQuadkey(); + }); +}; S2.S2Cell.prototype.getNeighbors = function() { var fromFaceIJWrap = function(face,ij,level) { @@ -362,7 +350,7 @@ S2.FACE_BITS = 3; S2.MAX_LEVEL = 30; S2.POS_BITS = (2 * S2.MAX_LEVEL) + 1; // 61 (60 bits of data, 1 bit lsb marker) -S2.fromFacePosLevel = function (faceN, posS, levelN) { +S2.facePosLevelToId = S2.S2Cell.facePosLevelToId = S2.fromFacePosLevel = function (faceN, posS, levelN) { var Long = exports.dcodeIO && exports.dcodeIO.Long || require('long'); var faceB; var posB; @@ -398,13 +386,19 @@ S2.fromFacePosLevel = function (faceN, posS, levelN) { return Long.fromString(bin, true, 2).toString(10); }; -S2.toId = S2.toCellId = S2.fromKey = function (key) { +S2.keyToId = S2.S2Cell.keyToId += S2.toId = S2.toCellId = S2.fromKey += function (key) { var parts = key.split('/'); return S2.fromFacePosLevel(parts[0], parts[1], parts[1].length); }; -S2.toKey = S2.fromId = S2.fromCellId = S2.toHilbertQuadkey = function (idS) { +S2.idToKey = S2.S2Cell.idToKey += S2.S2Cell.toKey = S2.toKey += S2.fromId = S2.fromCellId += S2.S2Cell.toHilbertQuadkey = S2.toHilbertQuadkey += function (idS) { var Long = exports.dcodeIO && exports.dcodeIO.Long || require('long'); var bin = Long.fromString(idS, true, 10).toString(2); @@ -431,7 +425,8 @@ S2.toKey = S2.fromId = S2.fromCellId = S2.toHilbertQuadkey = function (idS) { return faceS + '/' + posS; }; -S2.latLngToKey = S2.latLngToQuadkey = function (lat, lng, level) { +S2.S2Cell.latLngToKey = S2.latLngToKey += S2.latLngToQuadkey = function (lat, lng, level) { // TODO // // S2.idToLatLng(id) @@ -481,11 +476,11 @@ S2.stepKey = function (key, num) { return faceS + '/' + otherS; }; -S2.prevKey = function (key) { +S2.S2Cell.prevKey = S2.prevKey = function (key) { return S2.stepKey(key, -1); }; -S2.nextKey = function (key) { +S2.S2Cell.nextKey = S2.nextKey = function (key) { return S2.stepKey(key, 1); }; diff --git a/tests/js-vs-go.js b/tests/js-vs-go.js index b3934a3..4e2048e 100644 --- a/tests/js-vs-go.js +++ b/tests/js-vs-go.js @@ -9,6 +9,18 @@ function checkReal(loc) { var jKey = jQuad[0] + '/' + jQuad[1].join(''); if (loc.quadkey !== jKey) { + loc.badFace = jCell.face; + loc.badI = jCell.ij[0]; + loc.badJ = jCell.ij[1]; + loc.badQuad = jKey; + loc.badId = jS2.toId(jKey); + console.log(JSON.stringify(loc, null, ' ') + ','); + console.log(''); + console.log('Lat/Lng:', loc.lat, loc.lng); + console.log(''); + console.log('I, J:'); + console.log('=', loc.i, loc.j); + console.log('j', jCell.ij.join(', ')); console.log(''); console.log('Quadkey'); console.log('=', loc.quadkey); diff --git a/tests/simple.js b/tests/simple.js new file mode 100644 index 0000000..6a5a03d --- /dev/null +++ b/tests/simple.js @@ -0,0 +1,24 @@ +'use strict'; + +var S2 = require('../src/s2geometry.js').S2; + +var lat = 40.2574448; +var lng = -111.7089464; +var level = 15; + +var key = S2.latLngToKey(lat, lng, level); +// '4/032212303102210' +console.log(key); + +var id = S2.keyToId(key); +// '9749618446378729472' +console.log(id); + +var neighbors = S2.latLngToNeighborKeys(lat, lng, level); +// [ keyLeft, keyDown, keyRight, keyUp ] +console.log(neighbors); + +var nextKey = S2.nextKey(key); +console.log(nextKey); +var prevKey = S2.prevKey(key); +console.log(prevKey);