function quadTiles(projection, zoomLevel) {
const tiles = [];
let inside;
const N = 2 ** Math.max(0, zoomLevel);
const _remembered_precision = projection.precision();
const s = projection.precision(960).stream({
point() {
inside = true;
},
lineStart() {},
lineEnd() {},
polygonStart() {},
polygonEnd() {}
});
function subdivide(left, top, right, bottom) {
const diff = right - left;
const lat_max = latmap(top);
const lat_min = latmap(bottom);
const step = Math.max(.2, Math.min(1, .01 * zoomLevel)) * diff;
inside = false;
s.polygonStart();
s.lineStart();
for (var lng = left; right + step / 2 > lng && !inside; lng += step) {
s.point(lng, lat_max);
}
for (var lng = right; lng > left - step / 2 && !inside; lng -= step) {
s.point(lng, lat_min);
}
s.lineEnd();
s.polygonEnd();
if (!inside) return;
if (360 / N >= diff) {
tiles.push({
type: "Polygon",
coordinates: [
[
...d3.range(left, right + step / 2, step).map(t => [t, top]),
[right, 0.5 * (top + bottom)],
...d3.range(right, left - step / 2, -step).map(t => [t, bottom]),
[left, 0.5 * (top + bottom)],
[left, top]
].map(([lng, v_lat]) => [lng, latmap(v_lat)])
],
key: [
0 | (((180 + left) / 360) * N),
0 | (((180 + top) / 360) * N),
zoomLevel
],
pre_bounds: { left, top, right, bottom },
coordinate_bounds: {
north: lat_max,
south: lat_min,
west: left,
east: right
},
centroid: [0.5 * (left + right), 0.5 * (lat_max + lat_min)]
});
} else {
const hmid = 0.5 * (left + right);
const vmid = 0.5 * (top + bottom);
subdivide(left, top, hmid, vmid);
subdivide(hmid, top, right, vmid);
subdivide(left, vmid, hmid, bottom);
subdivide(hmid, vmid, right, bottom);
}
}
subdivide(-180, -180, 180, 180);
projection.precision(_remembered_precision);
return tiles;
}