diff --git a/src/s2geometry.js b/src/s2geometry.js index b8f78ef..ebc0556 100644 --- a/src/s2geometry.js +++ b/src/s2geometry.js @@ -202,7 +202,6 @@ var pointToHilbertQuadList = function(x,y,order) { return positions; }; - // S2Cell class S2.S2Cell = function(){}; @@ -340,10 +339,16 @@ S2.fromFacePosLevel = function (faceN, posS, levelN) { bin += '0'; } - return Long.fromString(bin, true, 2).toString(); + return Long.fromString(bin, true, 2).toString(10); }; -S2.toHilbertQuadkey = function (idS) { +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) { var Long = exports.dcodeIO && exports.dcodeIO.Long || require('long'); var bin = Long.fromString(idS, true, 10).toString(2); var lsbIndex = bin.lastIndexOf('1'); @@ -365,6 +370,61 @@ S2.toHilbertQuadkey = function (idS) { return faceS + '/' + posS; }; +S2.latLngToKey = S2.latLngToQuadkey = function (lat, lng, level) { + // TODO + // + // S2.idToLatLng(id) + // S2.keyToLatLng(key) + // + // .toKeyArray(id) // face,quadtree + // .toKey(id) // hilbert + // .toPoint(id) // ij + // .toId(key) // uint64 (as string) + // .toLong(key) // long.js + // .toLatLng(id) // object? or array?, or string (with comma)? + // maybe S2.HQ.x, S2.GPS.x, S2.CI.x? + return S2.S2Cell.FromLatLng({ lat: lat, lng: lng }, level).toHilbertQuadkey(); +}; + +S2.stepKey = function (key, num) { + var Long = exports.dcodeIO && exports.dcodeIO.Long || require('long'); + var parts = key.split('/'); + + var faceS = parts[0]; + var posS = parts[1]; + var level = parts[1].length; + + var posL = Long.fromString(posS, true, 4); + // TODO handle wrapping (0 === pos + 1) + // (only on the 12 edges of the globe) + var otherL; + if (num > 0) { + otherL = posL.add(Math.abs(num)); + } + else if (num < 0) { + otherL = posL.subtract(Math.abs(num)); + } + var otherS = otherL.toString(4); + + if ('0' === otherS) { + console.warning(new Error("face/position wrapping is not yet supported")); + } + + while (otherS.length < level) { + otherS = '0' + otherS; + } + + return faceS + '/' + otherS; +}; + +S2.prevKey = function (key) { + return S2.stepKey(key, -1); +}; + +S2.nextKey = function (key) { + return S2.stepKey(key, 1); +}; + })('undefined' !== typeof window ? window : module.exports); (function (exports) { diff --git a/tests/prev-next.js b/tests/prev-next.js new file mode 100644 index 0000000..f8835a1 --- /dev/null +++ b/tests/prev-next.js @@ -0,0 +1,50 @@ +'use strict'; + +var S2 = require('../src/s2geometry.js').S2; + +function getNeighbors(lat, lng, step) { + //var step = 10; + var level = 15; + var origin = S2.latLngToQuadkey(lat, lng, level); + var walk = []; + // 10 before and 10 after + var next = S2.nextKey(origin); + var prev = S2.prevKey(origin); + var i; + + for (i = 0; i < step; i++) { + walk.unshift(S2.toId(prev)); + prev = S2.prevKey(prev); + } + + walk.push(S2.toId(origin)); + + for (i = 0; i < step; i++) { + // in range(10): + walk.push(S2.toId(next)); + next = S2.nextKey(next); + } + + return walk; +} + + +// Startup Building in Provo +var lat = 40.2262363; +var lng = -111.6630927; + +var walk = getNeighbors(lat, lng, 5); + +walk.forEach(function (cellId, i) { + var key = S2.fromId(cellId); + var face = parseInt(key.substr(0, 1), 10); + var pos = key.substr(2); + var level = pos.length; + + // TODO + // S2.keyToLatLng(key); + // S2.idToLatLng(id); + + // ! because converting CellId / HilbertQuadkey to LatLng is not implemented... yet + console.log(-((walk.length - 1) / 2) + i, face, cellId, S2.fromId(cellId), '!', level); +});