Public
Edited
Feb 12, 2021
Importers
10 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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;

// Trace the projected tile (which will be a polygon),
// to see whether it

s.polygonStart();
s.lineStart();

for (var lng = left; right + step / 2 > lng && !inside; lng += step) {
s.point(lng, lat_max);
}
// Why are these unnecessary?!
// for (var v_lat = top; latmap((v_lat += step)) < lat_min && !inside; ) {
// console.log("b");
// s.point(right, latmap(v_lat));
// }
for (var lng = right; lng > left - step / 2 && !inside; lng -= step) {
s.point(lng, lat_min);
}
// Why are these unnecessary?!
// for (var v_lat = bottom; latmap((v_lat -= step)) > lat_max && !inside; ) {
// console.log("d");
// s.point(left, latmap(v_lat));
// }

// Unnecessary?
// if (!inside) s.point(left, lat_max);

s.lineEnd();
s.polygonEnd();

if (!inside) return;

if (360 / N >= diff) {
tiles.push({
type: "Polygon",
// Don't understand how we can get away with so few vertical points in this object,
// ..apparently they do produce smooth curves. Must have something to do how geoPath works?
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;
}
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more