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,
     ...