mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-13 17:23:02 +00:00
180 lines
5.4 KiB
JavaScript
180 lines
5.4 KiB
JavaScript
import _filter from 'lodash-es/filter';
|
|
import _find from 'lodash-es/find';
|
|
import { range as d3_range } from 'd3-array';
|
|
import { geoExtent } from '../geo';
|
|
|
|
|
|
export function utilTile() {
|
|
var _size = [960, 500];
|
|
var _scale = 256;
|
|
var _scaleExtent = [0, 20];
|
|
var _translate = [_size[0] / 2, _size[1] / 2];
|
|
var _zoomDelta = 0;
|
|
var _margin = 0;
|
|
|
|
function bound(val) {
|
|
return Math.min(_scaleExtent[1], Math.max(_scaleExtent[0], val));
|
|
}
|
|
|
|
function nearNullIsland(x, y, z) {
|
|
if (z >= 7) {
|
|
var center = Math.pow(2, z - 1);
|
|
var width = Math.pow(2, z - 6);
|
|
var min = center - (width / 2);
|
|
var max = center + (width / 2) - 1;
|
|
return x >= min && x <= max && y >= min && y <= max;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function tile() {
|
|
var z = Math.max(Math.log(_scale) / Math.LN2 - 8, 0);
|
|
var z0 = bound(Math.round(z + _zoomDelta));
|
|
var k = Math.pow(2, z - z0 + 8);
|
|
var origin = [
|
|
(_translate[0] - _scale / 2) / k,
|
|
(_translate[1] - _scale / 2) / k
|
|
];
|
|
|
|
var cols = d3_range(
|
|
Math.max(0, Math.floor(-origin[0]) - _margin),
|
|
Math.max(0, Math.ceil(_size[0] / k - origin[0]) + _margin)
|
|
);
|
|
var rows = d3_range(
|
|
Math.max(0, Math.floor(-origin[1]) - _margin),
|
|
Math.max(0, Math.ceil(_size[1] / k - origin[1]) + _margin)
|
|
);
|
|
|
|
var tiles = [];
|
|
for (var i = 0; i < rows.length; i++) {
|
|
var y = rows[i];
|
|
for (var j = 0; j < cols.length; j++) {
|
|
var x = cols[j];
|
|
|
|
if (i >= _margin && i <= rows.length - _margin &&
|
|
j >= _margin && j <= cols.length - _margin) {
|
|
tiles.unshift([x, y, z0]); // tiles in view at beginning
|
|
} else {
|
|
tiles.push([x, y, z0]); // tiles in margin at the end
|
|
}
|
|
}
|
|
}
|
|
|
|
tiles.translate = origin;
|
|
tiles.scale = k;
|
|
|
|
return tiles;
|
|
}
|
|
|
|
|
|
/**
|
|
* getTiles() returns array of d3 geo tiles.
|
|
* Using d3.geo.tiles.js from lib, gets tile extents for each grid tile in a grid created from
|
|
* an area around (and including) the current map view extents.
|
|
*/
|
|
tile.getTiles = function(projection, dimensions, tilezoom, margin) {
|
|
|
|
// s is the current map scale
|
|
// z is the 'Level of Detail', or zoom-level, where Level 1 is far from the earth, and Level 23 is close to the ground.
|
|
// ts ('tile size') here is the formula for determining the width/height of the map in pixels, but with a modification.
|
|
// See 'Ground Resolution and Map Scale': //https://msdn.microsoft.com/en-us/library/bb259689.aspx.
|
|
// As used here, by subtracting constant 'tileZoom' from z (the level), you end up with a much smaller value for the tile size (in pixels).
|
|
var s = projection.scale() * 2 * Math.PI;
|
|
var z = Math.max(Math.log(s) / Math.log(2) - 8, 0);
|
|
var ts = 256 * Math.pow(2, z - tilezoom);
|
|
var origin = [
|
|
s / 2 - projection.translate()[0],
|
|
s / 2 - projection.translate()[1]
|
|
];
|
|
|
|
var tiler = this
|
|
.scaleExtent([tilezoom, tilezoom])
|
|
.scale(s)
|
|
.size(dimensions)
|
|
.translate(projection.translate())
|
|
.margin(margin || 0); // request nearby tiles so we can connect sequences.
|
|
|
|
var tiles = tiler()
|
|
.map(function(tile) {
|
|
var x = tile[0] * ts - origin[0];
|
|
var y = tile[1] * ts - origin[1];
|
|
|
|
return {
|
|
id: tile.toString(),
|
|
xyz: tile,
|
|
extent: geoExtent(
|
|
projection.invert([x, y + ts]),
|
|
projection.invert([x + ts, y])
|
|
)
|
|
};
|
|
});
|
|
|
|
return tiles;
|
|
};
|
|
|
|
|
|
tile.filterNullIsland = function(tiles) {
|
|
return tiles.filter(function(t) {
|
|
return !nearNullIsland(t.xyz[0], t.xyz[1], t.xyz[2]);
|
|
});
|
|
};
|
|
|
|
|
|
// remove inflight requests that no longer cover the view..
|
|
tile.removeInflightRequests = function(cache, tiles, callback, modifier) {
|
|
return _filter(cache.inflight, function(v, i) {
|
|
var wanted = _find(tiles, function(tile) { return i === tile.id + modifier; });
|
|
if (!wanted) {
|
|
delete cache.inflight[i];
|
|
}
|
|
return !wanted;
|
|
}).map(callback); // abort request
|
|
};
|
|
|
|
|
|
tile.scaleExtent = function(val) {
|
|
if (!arguments.length) return _scaleExtent;
|
|
_scaleExtent = val;
|
|
return tile;
|
|
};
|
|
|
|
|
|
tile.size = function(val) {
|
|
if (!arguments.length) return _size;
|
|
_size = val;
|
|
return tile;
|
|
};
|
|
|
|
|
|
tile.scale = function(val) {
|
|
if (!arguments.length) return _scale;
|
|
_scale = val;
|
|
return tile;
|
|
};
|
|
|
|
|
|
tile.translate = function(val) {
|
|
if (!arguments.length) return _translate;
|
|
_translate = val;
|
|
return tile;
|
|
};
|
|
|
|
|
|
tile.zoomDelta = function(val) {
|
|
if (!arguments.length) return _zoomDelta;
|
|
_zoomDelta = +val;
|
|
return tile;
|
|
};
|
|
|
|
|
|
// number to extend the rows/columns beyond those covering the viewport
|
|
tile.margin = function(val) {
|
|
if (!arguments.length) return _margin;
|
|
_margin = +val;
|
|
return tile;
|
|
};
|
|
|
|
|
|
return tile;
|
|
}
|