diff --git a/src/s2geometry.js b/src/s2geometry.js index 0e2166b..807ee43 100644 --- a/src/s2geometry.js +++ b/src/s2geometry.js @@ -200,6 +200,30 @@ S2.IJToST = function(ij,order,offsets) { ]; }; + + +var rotateAndFlipQuadrant = function(n, point, rx, ry) +{ + var newX, newY; + if(ry == 0) + { + if(rx == 1){ + point.x = n - 1 - point.x; + point.y = n - 1 - point.y + + } + + var x = point.x; + point.x = point.y + point.y = x; + } + +} + + + + + // hilbert space-filling curve // based on http://blog.notdot.net/2009/11/Damn-Cool-Algorithms-Spatial-indexing-with-Quadtrees-and-Hilbert-Curves // note: rather then calculating the final integer hilbert position, we just return the list of quads @@ -240,6 +264,55 @@ var pointToHilbertQuadList = function(x,y,order,face) { S2.S2Cell = function(){}; +S2.S2Cell.FromHilbertQuadKey = function(hilbertQuadkey) { + var parts = hilbertQuadkey.split('/'); + var face = parseInt(parts[0]); + var position = parts[1]; + var maxLevel = position.length; + var point = { + x : 0, + y: 0 + } + + for(var i = maxLevel - 1; i >= 0; i--) + { + + var level = maxLevel - i; + var bit = position[i]; + var rx = 0, ry = 0; + if(bit == '1') + { + ry = 1; + } + else if(bit == '2') + { + rx = 1; + ry = 1; + } + else if(bit == '3') + { + rx = 1; + } + + var val = Math.pow(2, level - 1) + rotateAndFlipQuadrant(val, point, rx, ry); + + point.x += val * rx; + point.y += val * ry; + + } + + if(face % 2 == 1) + { + var t = point.x; + point.x = point.y; + point.y = t; + } + + + return S2.S2Cell.FromFaceIJ(parseInt(face),[point.x, point.y],level) + +} //static method to construct S2.S2Cell.FromLatLng = function(latLng, level) { if (latLng.lat == null || latLng.lng == null) { diff --git a/tests/hilbertToCell.js b/tests/hilbertToCell.js new file mode 100644 index 0000000..6798d89 --- /dev/null +++ b/tests/hilbertToCell.js @@ -0,0 +1,43 @@ +var S2 = require('../src/s2geometry.js').S2; + + + + +for(var level = 1; level <= 20; level++) +{ + var success = 0; + var total = 0; + for (var x = -180.0; x < 180; x += 0.5) { + for (var y = -180.0; y < 180; y += 0.5) { + + var latlng = { lat: x, lng: y }; + var cell = S2.S2Cell.FromLatLng(latlng, level); + var quadKey = cell.toHilbertQuadkey(); + var cell2 = S2.S2Cell.FromHilbertQuadKey(quadKey); + + if(cell.face != cell2.face || + cell.ij[0] != cell2.ij[0] || + cell.ij[1] != cell2.ij[1] || + cell.level != cell2.level) + { + /*console.log({ + cell: cell, + cell2: cell2})*/ + + } + else + { + success++; + } + total++; + // check equal + } + } + + console.log("level:" + level + "\t total:" + total + "\t success:" + success) +} + + + + +