Frontline
This commit is contained in:
38
Arrow.js
38
Arrow.js
@@ -2,12 +2,20 @@ export const ARROW_BODY_STYLE_CONSTANT = 1;
|
||||
export const ARROW_BODY_STYLE_LINEAR = 2;
|
||||
export const ARROW_BODY_STYLE_EXPONENTIAL = 3;
|
||||
|
||||
|
||||
export const METERS = 'meters';
|
||||
|
||||
import * as turf from "@turf/turf";
|
||||
|
||||
//ARROW
|
||||
// Cubic interpolation source from https://www.paulinternet.nl/?page=bicubic
|
||||
function cubicInterpolate(p, x) {
|
||||
return p[1] + 0.5 * x * (p[2] - p[0] + x * (2.0 * p[0] - 5.0 * p[1] + 4.0 * p[2] - p[3] + x * (3.0 * (p[1] - p[2]) + p[3] - p[0])));
|
||||
/**
|
||||
* @param {number[]} points - An array of 4 values [p0, p1, p2, p3] representing control points.
|
||||
* @param {number} t - The relative position between p1 and p2 (range typically from 0 to 1).
|
||||
* @returns {number} The interpolated value.
|
||||
*/
|
||||
export function cubicInterpolate(p, t) {
|
||||
return p[1] + 0.5 * t * (p[2] - p[0] + t * (2.0 * p[0] - 5.0 * p[1] + 4.0 * p[2] - p[3] + t * (3.0 * (p[1] - p[2]) + p[3] - p[0])));
|
||||
}
|
||||
|
||||
function exponentialWidthCurve(normalizedPosition, range = 5, minValue = 0.1) {
|
||||
@@ -37,12 +45,18 @@ function linearWidthCurve(normalizedPosition, range = 1, minValue = 0.1) {
|
||||
* @returns {GeoJSON.Feature<GeoJSON.Polygon>} - An array of points representing the arrow polygon.
|
||||
*/
|
||||
export function getArrowPolygon(arrowData, style, arrowHeadData) {
|
||||
if (!style)
|
||||
if (!arrowData || !(arrowData.points) || arrowData.points.length === 0) {
|
||||
console.warn("getArrowPolygon: Invalid arrowData or empty points array.");
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!style) {
|
||||
style = {
|
||||
calculation: ARROW_BODY_STYLE_CONSTANT,
|
||||
range: 0,
|
||||
minValue: 0
|
||||
};
|
||||
}
|
||||
|
||||
const splinePoints = computeSplinePoints(arrowData.points, arrowData.splineStep);
|
||||
const { leftSidePoints, rightSidePoints } = computeSideOffsets(splinePoints, arrowData.offsetDistance, style);
|
||||
@@ -69,8 +83,7 @@ function averageBearing(points, count = 3) {
|
||||
const bearings = [];
|
||||
for (let i = points.length - count; i < points.length -1; i++) {
|
||||
if (i >= 0) {
|
||||
const b = turf.bearing(turf.point(points[i]), turf.point(points[i + 1]));
|
||||
bearings.push(b);
|
||||
bearings.push(turf.bearing(turf.point(points[i]), turf.point(points[i + 1])));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +103,7 @@ function computeSplinePoints(points, splineStep = 10) {
|
||||
const p3 = points[i + 2] || p2;
|
||||
for (let j = 0; j < splineStep; j++) {
|
||||
const t = j / splineStep;
|
||||
const lon = cubicInterpolate([p0[0], p1[0], p2[0], p3[0]], t);
|
||||
const lon = cubicInterpolate([p0[0], p1[0], p2[0], p3[0]], t);
|
||||
const lat = cubicInterpolate([p0[1], p1[1], p2[1], p3[1]], t);
|
||||
result.push([lon, lat]);
|
||||
}
|
||||
@@ -112,7 +125,7 @@ function computeSideOffsets(points, offsetMeters, style) {
|
||||
const normalizedPosition = i / total;
|
||||
|
||||
let localOffsetDistance;
|
||||
switch (style.calculation) {
|
||||
switch (style.calculation) {
|
||||
case ARROW_BODY_STYLE_LINEAR:
|
||||
localOffsetDistance = offsetMeters * linearWidthCurve(normalizedPosition, style.range, style.minValue);
|
||||
break;
|
||||
@@ -124,8 +137,8 @@ function computeSideOffsets(points, offsetMeters, style) {
|
||||
localOffsetDistance = offsetMeters;
|
||||
}
|
||||
|
||||
leftSidePoints.push(turf.destination(turf.point(currentPoint), localOffsetDistance, bearing - 90, { units: 'meters' }).geometry.coordinates);
|
||||
rightSidePoints.push(turf.destination(turf.point(currentPoint), localOffsetDistance, bearing + 90, { units: 'meters' }).geometry.coordinates);
|
||||
leftSidePoints.push(turf.destination(turf.point(currentPoint), localOffsetDistance, bearing - 90, { units: METERS }).geometry.coordinates);
|
||||
rightSidePoints.push(turf.destination(turf.point(currentPoint), localOffsetDistance, bearing + 90, { units: METERS }).geometry.coordinates);
|
||||
}
|
||||
|
||||
return { leftSidePoints, rightSidePoints };
|
||||
@@ -133,9 +146,9 @@ function computeSideOffsets(points, offsetMeters, style) {
|
||||
|
||||
function createIsoscelesTriangleCoords(center, baseLengthMeters, heightMeters, bearing = 0) {
|
||||
const halfBase = baseLengthMeters / 2;
|
||||
const left = turf.destination(center, halfBase, bearing - 90, { units: 'meters' }).geometry.coordinates;
|
||||
const right = turf.destination(center, halfBase, bearing + 90, { units: 'meters' }).geometry.coordinates;
|
||||
const tip = turf.destination(center, heightMeters, bearing, { units: 'meters' }).geometry.coordinates;
|
||||
const left = turf.destination(center, halfBase, bearing - 90, { units: METERS }).geometry.coordinates;
|
||||
const right = turf.destination(center, halfBase, bearing + 90, { units: METERS }).geometry.coordinates;
|
||||
const tip = turf.destination(center, heightMeters, bearing, { units: METERS }).geometry.coordinates;
|
||||
return [left, tip, right];
|
||||
}
|
||||
//GEOJSON
|
||||
@@ -162,7 +175,6 @@ export function getArrowPolygonEuclidean(
|
||||
arrowData,
|
||||
style= undefined,
|
||||
arrowHeadData = undefined) {
|
||||
|
||||
if (!style)
|
||||
style = {
|
||||
calculation: ARROW_BODY_STYLE_CONSTANT,
|
||||
|
||||
Reference in New Issue
Block a user