Quadkey levels
by felixp
HTML
<!DOCTYPE html>
<html>
<head>
<title>Quadkey levels</title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<script src="https://unpkg.com/h3-js"></script>
<script src="https://unpkg.com/[email protected]/dist.min.js"></script>
<script src="https://unpkg.com/@deck.gl/[email protected]/dist.min.js"></script>
<script src="https://libs.cartocdn.com/mapbox-gl/v1.13.0/mapbox-gl.js"></script>
<link href="https://libs.cartocdn.com/mapbox-gl/v1.13.0/mapbox-gl.css" rel="stylesheet" />
<!-- jsFiddle will insert css and js -->
</head>
<body>
<div id="map"></div>
<div id="textfield">Hexagons</div>
</body>
</html>
CSS
/* Always set the map height explicitly to define the size of the div element that contains the map. */
#map {
height: 100%;
}
#textfield {
position: absolute;
left: 10px;
top: 10px;
background: snow;
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3);
padding: 10px;
}
/* Optional: Makes the sample page fill the window. */
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
JavaScript
// Relative scale factor (0 = no biasing, 2 = a few hexagons cover view)
const bias = 1;
const limX = 179;
const limY = -85.05112877980662;
//const limY = -75;
const bounds = [
[-limX, -limY],
[limX, -limY],
[limX, limY],
[-limX, limY],
[-limX, -limY]
];
const hexList = h3.polyfill(bounds, 4, false);
console.log(hexList.length, 122 * Math.pow(7, 4));
// Resolution conversion function. Takes a WebMercatorViewport and returns
// a H3 resolution such that the screen space size of the hexagons is
// similar
function getHexagonResolution(viewport) {
const hexagonScaleFactor = (2 / 3) * viewport.zoom;
const latitudeScaleFactor = Math.log(1 / Math.cos(Math.PI * viewport.latitude / 180));
// Clip and bias
const r = hexagonScaleFactor + latitudeScaleFactor - bias;
return Math.max(0, Math.min(15, r));
}
// Style
const GREEN = [128, 189, 164];
const PURPLE = [45, 41, 95];
// Visualization
function createHexagonLayers(viewState) {
const resolution = getHexagonResolution(viewState);
const r0 = Math.floor(resolution);
const r1 = r0 + 1;
const rRef = Math.round(resolution);
const hexagons = getHexagonsInView(viewState, rRef);
// Stats display
const totalHex = 122 * Math.pow(7, rRef); // estimate
const el = document.getElementById('textfield');
el.innerHTML = `Hexagons: ${hexagons.length}/${totalHex}, resolution: ${rRef}`;
return [r0, r1].map(r => {
const alpha = Math.pow(1 - Math.abs(r - resolution), 3);
const color = Math.floor(r) % 2 ? GREEN : PURPLE;
return new deck.H3HexagonLayer({
id: `hex-${r}`,
data: getHexagonsInView(viewState, r),
getHexagon: d => d,
getLineColor: [...color, 255 * alpha],
extruded: false,
filled: false,
stroked: true,
getLineWidth: 3,
lineWidthUnits: 'pixels',
});
});
}
const initialViewState = {
latitude: 40.4948,
longitude: -3.3746,
zoom: 5,
maxZoom: 30
}
const d = new...