UNPKG

@deck.gl-community/layers

Version:

Add-on layers for deck.gl

123 lines (102 loc) 3.19 kB
// deck.gl-community // SPDX-License-Identifier: MIT // Copyright (c) vis.gl contributors import {Vector2} from '@math.gl/core'; /** GeoJSON style position coordinate vector */ export type Position = [number, number] | [number, number, number]; /** [red, green, blue, alpha] in premultiplied alpha format */ export type Color = [number, number, number, number]; export interface PathMarker { position: Position; angle: number; color: Color; object: unknown; } function getLineLength(vPoints) { // calculate total length let lineLength = 0; for (let i = 0; i < vPoints.length - 1; i++) { lineLength += vPoints[i].distance(vPoints[i + 1]); } return lineLength; } const DEFAULT_COLOR = [0, 0, 0, 255]; const DEFAULT_DIRECTION = {forward: true, backward: false}; export function createPathMarkers({ data, getPath = (x, context) => x.path, getDirection = (x) => x.direction, getColor = (x) => DEFAULT_COLOR, getMarkerPercentages = (x, info) => [0.5], projectFlat }): PathMarker[] { const markers: PathMarker[] = []; for (const object of data) { const path = getPath(object, null); const direction = getDirection(object) || DEFAULT_DIRECTION; const color = getColor(object); const vPoints = path.map((p) => new Vector2(p)); const vPointsReverse = vPoints.slice(0).reverse(); // calculate total length const lineLength = getLineLength(vPoints); // Ask for where to put markers const percentages = getMarkerPercentages(object, {lineLength}); // Create the markers for (const percentage of percentages) { if (direction.forward) { const marker = createMarkerAlongPath({ path: vPoints, percentage, lineLength, color, object, projectFlat }); markers.push(marker); } if (direction.backward) { const marker = createMarkerAlongPath({ path: vPointsReverse, percentage, lineLength, color, object, projectFlat }); markers.push(marker); } } } return markers; } function createMarkerAlongPath({ path, percentage, lineLength, color, object, projectFlat }): PathMarker { const distanceAlong = lineLength * percentage; let currentDistance = 0; let previousDistance = 0; let i = 0; for (i = 0; i < path.length - 1; i++) { currentDistance += path[i].distance(path[i + 1]); if (currentDistance > distanceAlong) { break; } previousDistance = currentDistance; } // If reached the end of the loop without exiting early, // undo the final increment to avoid a null-pointer exception if (i === path.length - 1) { i -= 1; } const vDirection = path[i + 1].clone().subtract(path[i]).normalize(); const along = distanceAlong - previousDistance; const vCenter = vDirection.clone().multiply(new Vector2(along, along)).add(path[i]); const vDirection2 = new Vector2(projectFlat(path[i + 1])).subtract(projectFlat(path[i])); const angle = (vDirection2.verticalAngle() * 180) / Math.PI; return {position: [vCenter.x, vCenter.y, 0], angle, color, object}; }