diff --git a/code/map_data.js b/code/map_data.js index 76d72e89..89e8eeb2 100644 --- a/code/map_data.js +++ b/code/map_data.js @@ -12,34 +12,30 @@ window.requestData = function() { requests.abort(); cleanUp(); - var magic = convertCenterLat(map.getCenter().lat); - var R = calculateR(magic); - var bounds = map.getBounds(); - // convert to point values - topRight = convertLatLngToPoint(bounds.getNorthEast(), magic, R); - bottomLeft = convertLatLngToPoint(bounds.getSouthWest() , magic, R); - // how many quadrants intersect the current view? - quadsX = Math.abs(bottomLeft.x - topRight.x); - quadsY = Math.abs(bottomLeft.y - topRight.y); + + var x1 = lngToTile(bounds.getNorthWest().lng, map.getZoom()); + var x2 = lngToTile(bounds.getNorthEast().lng, map.getZoom()); + var y1 = latToTile(bounds.getNorthWest().lat, map.getZoom()); + var y2 = latToTile(bounds.getSouthWest().lat, map.getZoom()); // will group requests by second-last quad-key quadrant tiles = {}; // walk in x-direction, starts right goes left - for(var i = 0; i <= quadsX; i++) { - var x = Math.abs(topRight.x - i); - var qk = pointToQuadKey(x, topRight.y); - var bnds = convertPointToLatLng(x, topRight.y, magic, R); - if(!tiles[qk.slice(0, -1)]) tiles[qk.slice(0, -1)] = []; - tiles[qk.slice(0, -1)].push(generateBoundsParams(qk, bnds)); - - // walk in y-direction, starts top, goes down - for(var j = 1; j <= quadsY; j++) { - var qk = pointToQuadKey(x, topRight.y + j); - var bnds = convertPointToLatLng(x, topRight.y + j, magic, R); - if(!tiles[qk.slice(0, -1)]) tiles[qk.slice(0, -1)] = []; - tiles[qk.slice(0, -1)].push(generateBoundsParams(qk, bnds)); + for (var x = x1; x <= x2; x++) { + for (var y = y1; y <= y2; y++) { + var tile_id = pointToTileId(map.getZoom(), x, y); + var bucket = Math.floor(x / 2) + "" + Math.floor(y / 2); + if (!tiles[bucket]) + tiles[bucket] = []; + tiles[bucket].push(generateBoundsParams( + tile_id, + tileToLat(y + 1, map.getZoom()), + tileToLng(x, map.getZoom()), + tileToLat(y, map.getZoom()), + tileToLng(x + 1, map.getZoom()) + )); } } diff --git a/code/map_data_calc_tools.js b/code/map_data_calc_tools.js index eca1b7e9..98535759 100644 --- a/code/map_data_calc_tools.js +++ b/code/map_data_calc_tools.js @@ -1,65 +1,45 @@ - // MAP DATA REQUEST CALCULATORS ////////////////////////////////////// // Ingress Intel splits up requests for map data (portals, links, // fields) into tiles. To get data for the current viewport (i.e. what // is currently visible) it first calculates which tiles intersect. // For all those tiles, it then calculates the lat/lng bounds of that // tile and a quadkey. Both the bounds and the quadkey are “somewhat” -// required to get complete data. No idea how the projection between -// lat/lng and tiles works. -// What follows now are functions that allow conversion between tiles -// and lat/lng as well as calculating the quad key. The variable names -// may be misleading. -// The minified source for this code was in gen_dashboard.js after the -// “// input 89” line (alternatively: the class was called “Xe”). +// required to get complete data. +// +// Convertion functions courtesy of +// http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames -window.convertCenterLat = function(centerLat) { - return Math.round(256 * 0.9999 * Math.abs(1 / Math.cos(centerLat * DEG2RAD))); +window.lngToTile = function(lng, zoom) { + return Math.floor((lng + 180) / 360 * Math.pow(2, zoom)); } -window.calculateR = function(convCenterLat) { - return 1 << window.map.getZoom() - (convCenterLat / 256 - 1); +window.latToTile = function(lat, zoom) { + return Math.floor((1 - Math.log(Math.tan(lat * Math.PI / 180) + + 1 / Math.cos(lat * Math.PI / 180)) / Math.PI) / 2 * Math.pow(2, zoom)); } -window.convertLatLngToPoint = function(latlng, magic, R) { - var x = (magic + latlng.lng * magic / 180)*R; - var l = Math.sin(latlng.lat * DEG2RAD); - var y = (magic + Math.log((1+l)/(1-l)) * -(magic / (2*Math.PI)))*R; - return {x: Math.floor(x/magic), y: Math.floor(y/magic)}; +window.tileToLng = function(x, zoom) { + return x / Math.pow(2, zoom) * 360 - 180; } -window.convertPointToLatLng = function(x, y, magic, R) { - var e = {}; - e.sw = { - // orig function put together from all over the place - // lat: (2 * Math.atan(Math.exp((((y + 1) * magic / R) - (magic/ 2)) / (-1*(magic / (2 * Math.PI))))) - Math.PI / 2) / (Math.PI / 180), - // shortened version by your favorite algebra program. - lat: (360*Math.atan(Math.exp(Math.PI - Math.PI*(y+1)/R)))/Math.PI - 90, - lng: 180*x/R-180 - }; - e.ne = { - //lat: (2 * Math.atan(Math.exp(((y * magic / R) - (magic/ 2)) / (-1*(magic / (2 * Math.PI))))) - Math.PI / 2) / (Math.PI / 180), - lat: (360*Math.atan(Math.exp(Math.PI - Math.PI*y/R)))/Math.PI - 90, - lng: 180*(x+1)/R-180 - }; - return e; +window.tileToLat = function(y, zoom) { + var n = Math.PI - 2 * Math.PI * y / Math.pow(2, zoom); + return 180 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))); } -// calculates the quad key for a given point. The point is not(!) in -// lat/lng format. -window.pointToQuadKey = function(x, y) { - return window.map.getZoom() + "_" + x + "_" + y; +window.pointToTileId = function(zoom, x, y) { + return zoom + "_" + x + "_" + y; } -// given quadkey and bounds, returns the format as required by the +// given tile id and bounds, returns the format as required by the // Ingress API to request map data. -window.generateBoundsParams = function(quadkey, bounds) { +window.generateBoundsParams = function(tile_id, minLat, minLng, maxLat, maxLng) { return { - id: quadkey, - qk: quadkey, - minLatE6: Math.round(bounds.sw.lat * 1E6), - minLngE6: Math.round(bounds.sw.lng * 1E6), - maxLatE6: Math.round(bounds.ne.lat * 1E6), - maxLngE6: Math.round(bounds.ne.lng * 1E6) + id: tile_id, + qk: tile_id, + minLatE6: Math.round(minLat * 1E6), + minLngE6: Math.round(minLng * 1E6), + maxLatE6: Math.round(maxLat * 1E6), + maxLngE6: Math.round(maxLng * 1E6) }; }