H3 levels (padding)
by felixp
HTML
<!DOCTYPE html>
<html>
<head>
<title>H3 levels</title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Turf.js/6.5.0/turf.min.js"></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://unpkg.com/[email protected]"></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" class="info">Hexagons</div>
<div id="textfield2" class="info">Edges</div>
<div id="textfield3" class="info">Culled</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%;
}
.info {
position: absolute;
left: 10px;
top: 10px;
background: snow;
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3);
padding: 10px;
}
#textfield2 {
top: 50px;
}
#textfield3 {
top: 90px;
}
/* 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 = 2;
// 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));
}
// Support h3 v3/v4 (https://h3geo.org/docs/library/migration-3.x/functions)
const kRing = h3.kRing || h3.gridDisk;
const geoToH3 = h3.geoToH3 || h3.latLngToCell;
const getH3UnidirectionalEdgesFromHexagon = h3.getH3UnidirectionalEdgesFromHexagon || h3.originToDirectedEdges;
const exactEdgeLength = h3.exactEdgeLength || h3.edgeLength;
const h3ToGeoBoundary = h3.h3ToGeoBoundary || h3.cellToBoundary;
const polyfill = h3.polyfill || h3.polygonToCells;
const getRes0Indexes = h3.getRes0Indexes;
// Style
const GREEN = [128, 189, 164];
const PINK = [245, 41, 95];
// Visualization
function createHexagonLayers(viewState) {
const viewport = new deck.WebMercatorViewport(viewState);
let polygon = [
viewport.unproject([0, 0]),
viewport.unproject([viewport.width, 0]),
viewport.unproject([viewport.width, viewport.height]),
viewport.unproject([0, viewport.height])
];
polygon.push(polygon[0]);
polygon = turf.polygon([polygon]);
const resolution = getHexagonResolution(viewState);
const r = Math.floor(resolution);
const hexagons = getHexagonsInView(viewState, r);
// Stats display
const totalHex = 122 * Math.pow(7, r); // estimate
const el = document.getElementById('textfield');
el.innerHTML = `Hexagons: ${hexagons.length}/${totalHex}, resolution: ${r}`;
return [new deck.H3HexagonLayer({
id: 'hex',
data: hexagons,
getHexagon: d => d,
getLineColor: GREEN,
...