Skip to content

Commit

Permalink
[visgl#9165] H3HexagonLayer / Elevation of hexagons above the ground
Browse files Browse the repository at this point in the history
  • Loading branch information
birdofpreyru committed Sep 20, 2024
1 parent 95ee077 commit 83bc853
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 15 deletions.
4 changes: 2 additions & 2 deletions docs/api-reference/geo-layers/h3-hexagon-layer.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,11 @@ Hexagon radius multiplier, between 0 - 1. When `coverage` = 1, hexagon is render

### Data Accessors

#### `getHexagon` ([Accessor<string>](../../developer-guide/using-layers.md#accessors), optional) {#gethexagon}
#### `getHexagon` ([Accessor<string | [string, number]>](../../developer-guide/using-layers.md#accessors), optional) {#gethexagon}

* Default: `object => object.hexagon`

Method called to retrieve the [H3](https://h3geo.org/) hexagon index of each object. Note that all hexagons within one `H3HexagonLayer` must use the same [resolution](https://h3geo.org/docs/core-library/restable).
Method called to retrieve the [H3](https://h3geo.org/) hexagon index of each object. Optionally, it may return `[string, number]` tuple, where the first element is the hexagon index, and the second one is the hexagon base elevation over the ground. Note that all hexagons within one `H3HexagonLayer` must use the same [resolution](https://h3geo.org/docs/core-library/restable).


## Sub Layers
Expand Down
23 changes: 15 additions & 8 deletions modules/geo-layers/src/h3-layers/h3-hexagon-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import {
getHexagonEdgeLengthAvg,
H3Index
} from 'h3-js';

import {
AccessorFunction,
CompositeLayer,
createIterable,
Layer,
Expand All @@ -17,8 +17,16 @@ import {
WebMercatorViewport,
DefaultProps
} from '@deck.gl/core';

import {ColumnLayer, PolygonLayer, PolygonLayerProps} from '@deck.gl/layers';
import {flattenPolygon, getHexagonCentroid, h3ToPolygon} from './h3-utils';

import {
type HexagonAccessor,
flattenPolygon,
getHexagonCentroid,
getIndexAndBaseElevation,
h3ToPolygon
} from './h3-utils';

// There is a cost to updating the instanced geometries when using highPrecision: false
// This constant defines the distance between two hexagons that leads to "significant
Expand Down Expand Up @@ -71,7 +79,7 @@ type _H3HexagonLayerProps<DataT> = {
*
* By default, it reads `hexagon` property of data object.
*/
getHexagon?: AccessorFunction<DataT, string>;
getHexagon?: HexagonAccessor<DataT>;
/**
* Whether to extrude polygons.
* @default true
Expand Down Expand Up @@ -136,7 +144,7 @@ export default class H3HexagonLayer<
const {iterable, objectInfo} = createIterable(this.props.data);
for (const object of iterable) {
objectInfo.index++;
const hexId = this.props.getHexagon(object, objectInfo);
const [hexId] = getIndexAndBaseElevation(this.props.getHexagon, object, objectInfo);
// Take the resolution of the first hex
const hexResolution = getResolution(hexId);
if (resolution < 0) {
Expand Down Expand Up @@ -292,10 +300,9 @@ export default class H3HexagonLayer<
data,
_normalize: false,
_windingOrder: 'CCW',
positionFormat: 'XY',
getPolygon: (object, objectInfo) => {
const hexagonId = getHexagon(object, objectInfo);
return flattenPolygon(h3ToPolygon(hexagonId, coverage));
const hexagon = getHexagon(object, objectInfo);
return flattenPolygon(h3ToPolygon(hexagon, coverage));
}
}
);
Expand All @@ -320,7 +327,7 @@ export default class H3HexagonLayer<
diskResolution: 6, // generate an extruded hexagon as the base geometry
radius: 1,
vertices: this.state.vertices,
getPosition: getHexagonCentroid.bind(null, getHexagon)
getPosition: getHexagonCentroid.bind(null, getHexagon as any)
}
);
}
Expand Down
34 changes: 29 additions & 5 deletions modules/geo-layers/src/h3-layers/h3-utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import {CoordPair, H3IndexInput, cellToBoundary, cellToLatLng} from 'h3-js';
import {lerp} from '@math.gl/core';
import type {AccessorFunction} from '@deck.gl/core';

export type HexagonAccessor<DataT> = AccessorFunction<DataT, string | [string, number]>;

// normalize longitudes w.r.t center (refLng), when not provided first vertex
export function normalizeLongitudes(vertices: CoordPair[], refLng?: number): void {
Expand Down Expand Up @@ -31,14 +34,32 @@ export function scalePolygon(hexId: H3IndexInput, vertices: CoordPair[], factor:
}
}

// gets hexagon id
export function getIndexAndBaseElevation<DataT>(
getHexagon: HexagonAccessor<DataT>,
object,
objectInfo
): [string, number] {
const hexagon = getHexagon(object, objectInfo);
return typeof hexagon === 'string' ? [hexagon, 0] : hexagon;
}

// gets hexagon centroid
export function getHexagonCentroid(getHexagon, object, objectInfo) {
const hexagonId = getHexagon(object, objectInfo);
export function getHexagonCentroid<DataT>(getHexagon: HexagonAccessor<DataT>, object, objectInfo) {
const [hexagonId, baseElevation] = getIndexAndBaseElevation(getHexagon, object, objectInfo);
const [lat, lng] = cellToLatLng(hexagonId);
return [lng, lat];
return [lng, lat, baseElevation];
}

export function h3ToPolygon(hexId: H3IndexInput, coverage: number = 1): number[][] {
export function h3ToPolygon(hex: string | [string, number], coverage: number = 1): number[][] {
let baseElevation: number;
let hexId: string;

if (typeof hex === 'string') {
baseElevation = 0;
hexId = hex;
} else [hexId, baseElevation] = hex;

const vertices = cellToBoundary(hexId, true);

if (coverage !== 1) {
Expand All @@ -49,15 +70,18 @@ export function h3ToPolygon(hexId: H3IndexInput, coverage: number = 1): number[]
normalizeLongitudes(vertices);
}

for (const vtx of vertices) vtx.push(baseElevation);

return vertices;
}

export function flattenPolygon(vertices: number[][]): Float64Array {
const positions = new Float64Array(vertices.length * 2);
const positions = new Float64Array(vertices.length * 3);
let i = 0;
for (const pt of vertices) {
positions[i++] = pt[0];
positions[i++] = pt[1];
positions[i++] = pt[2];
}
return positions;
}

0 comments on commit 83bc853

Please sign in to comment.