Published
Edited
Aug 25, 2020
3 forks
50 stars
Topographic MappingBubble mapChoroplethAccess to Family planningMD Counties Total Cases MapTendance de la production des déchets en Union EuropéenneAndy's Walgreens COVID-19 Tracker TrackerElection Maps for Incomplete ResultsA better U.S. house election results map?1983 Mayoral Election, Dot density mapsMastodon 🐘Cheat sheet bertinBertin.js: regular squaresWaterlinesNeumorphism Contour Density MapCartographic DoodlesStars and constellationsPlot: Grid choroplethHello Polygon MorphingMapping with pie chartsU.S. Geographic DataHow big are countries... like really!AttitudeB&W Choropleth
Web Mercator Tile Visibility
MARTINI: Real-Time RTIN Terrain Mesh"Magnifying-Glass" projectionsTissot's indicatrixAntipodal mapMapping gridded data with a Voronoi diagramA Map of Every BuildingUrbano Monti’s Planisphere (1587)Bivariate choroplethDIY HillshadeMapbox Map MakerWorld tourHillshaderSimplified Earth with curved shapesHexbin mapInner glowNicolosi vs. StereographicData-driven projections: Darwin's worldSatellite ground track visualizerDirection to shoreHello, OpenLayers!U.S. airports VoronoiHello, NYC Geosearch API!Mapbox Fly-ToSpilhaus shoreline mapWalmart’s growthHow well does population density predict U.S. voting outcomes?Drawing maps from geodata with D3 & ObservableHexgrid maps with d3-hexgridTissot's indicatrixWorld airports VoronoiSwiss Elevation Line GraphsVector tilesVersor draggingOrthographicSolar TerminatorStreaming ShapefilesFake GlobesPeirce Quincuncial🍃 LeafletU.S.G.S. World Earthquake MapUsing Mapbox GL JSUsing Google Maps
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
getVisibleTiles = function(projection, zoom) {
function getVisibleChildren(x, y, z) {
console.log(x, y, z);
let visible = false;
// Define a projection stream based on the input projection. This stream first does all of
// the operations (rotating, clipping, and resampling) that the input projection would do.
// Then, any geometries that survive that process (i.e. are visible in the output projection)
// get passed on to our custom stream, which just sets `visible = true` if it sees a point.
// We'll use this stream to determine if a tile is visible when projected through `projection`.
let stream = projection.stream({
point: () => { visible = true; },
lineStart: () => {},
lineEnd: () => {},
polygonStart: () => {},
polygonEnd: () => {}
});
// calculate screen-space coordinates of tile (x, y, z) in the `mercator` projection below
const extent = mercator.clipExtent();
// we assume that extent is a square, and thus all tiles are also squares
const size = (extent[1][0] - extent[0][0]) / (2 ** z);
const epsilon = 0.001;
const x0 = x * size + epsilon,
y0 = y * size + epsilon,
x1 = (x + 1) * size - epsilon,
y1 = (y + 1) * size - epsilon;

const step = Math.min(size, 1);
const tile = {
type: "Polygon",
coordinates: [
[]
// Interpolate along each of the four edges of the Mercator polygon. This is a rather
// crude way to do interpolation (with a constant step size) but it's easier than the
// adaptive resampling that d3 does natively, which is not available to us here since
// we're not using a projection.
.concat(d3.range(x0, x1 + step / 2, +step).map(x => [x, y0]))
.concat(d3.range(y0, y1 + step / 2, +step).map(y => [x1, y]))
.concat(d3.range(x1, x0 - step / 2, -step).map(x => [x, y1]))
.concat(d3.range(y1, y0 - step / 2, -step).map(y => [x0, y]))
// convert this mercator polygon to a spherical polygon on the Earth
.map(point => mercator.invert(point))
],
};
// Project the spherical polygon representing the tile by feeding it through the stream.
d3.geoStream(tile, stream);
// If any point in the tile was visible in the output projection, then our stream will have
// received that point via its `point` method and set `visible = true`.
if (visible) {
if (z < zoom) {
// if we're not yet at the desired zoom level, recurse on each of the four sub-tiles
let visibleChildren = []
.concat(getVisibleChildren(2 * x, 2 * y, z + 1)) // upper left
.concat(getVisibleChildren(2 * x + 1, 2 * y, z + 1)) // upper right
.concat(getVisibleChildren(2 * x, 2 * y + 1, z + 1)) // lower left
.concat(getVisibleChildren(2 * x + 1, 2 * y + 1, z + 1)) // lower right
return visibleChildren;
} else {
return [tile]; // this tile is visible and is of the desired zoom level
}
} else {
return []; // this tile is not visible
}
}

return getVisibleChildren(0, 0, 0);
}
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
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