UNPKG

@nebula.gl/layers

Version:

A suite of 3D-enabled data editing layers, suitable for deck.gl

100 lines (83 loc) 2.72 kB
import { Vector2 } from 'math.gl'; 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 default function createPathMarkers({ data, getPath = (x) => x.path, getDirection = (x) => x.direction, getColor = (x) => DEFAULT_COLOR, getMarkerPercentages = (x, info) => [0.5], projectFlat, }) { const markers = []; for (const object of data) { const path = getPath(object); 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 // @ts-ignore 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 }) { 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 }; }