vehicle-path2 3.0.1 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/algorithms/math.d.ts +1 -1
- package/dist/core/algorithms/pathFinding.d.ts +2 -2
- package/dist/core/engine.d.ts +1 -2
- package/dist/core/types/movement.d.ts +0 -1
- package/dist/core/types/vehicle.d.ts +1 -1
- package/dist/core.cjs +1 -1
- package/dist/core.js +2 -2
- package/dist/index-DQbf63_R.cjs +1 -0
- package/dist/{index-C7pH7jZo.js → index-okJUn3WJ.js} +255 -274
- package/dist/vehicle-path.cjs +1 -1
- package/dist/vehicle-path.js +1 -1
- package/package.json +1 -1
- package/dist/index-C4FckUel.cjs +0 -1
|
@@ -10,7 +10,7 @@ export interface CurveOffsetOptions {
|
|
|
10
10
|
toOffset?: number;
|
|
11
11
|
toIsPercentage?: boolean;
|
|
12
12
|
}
|
|
13
|
-
export declare function createBezierCurve(line: Line, nextLine: Line, config: MovementConfig,
|
|
13
|
+
export declare function createBezierCurve(line: Line, nextLine: Line, config: MovementConfig, offsetOptions?: CurveOffsetOptions): BezierCurve;
|
|
14
14
|
export declare function getPointOnLine(line: Line, t: number): Point;
|
|
15
15
|
export declare function getPointOnLineByOffset(line: Line, offset: number, isPercentage: boolean): Point;
|
|
16
16
|
export declare function getPointOnBezier(bezier: BezierCurve, t: number): Point;
|
|
@@ -41,7 +41,7 @@ export declare function calculateBezierArcLength(bezier: BezierCurve, segments?:
|
|
|
41
41
|
* Untuk absolute offset: clamp ke [0, lineLength].
|
|
42
42
|
* Untuk percentage (0-1): map ke [0, lineLength].
|
|
43
43
|
*/
|
|
44
|
-
export declare function resolveFromLineOffset(line: Line, offset: number | undefined, isPercentage: boolean | undefined, defaultPercentage: number
|
|
44
|
+
export declare function resolveFromLineOffset(line: Line, offset: number | undefined, isPercentage: boolean | undefined, defaultPercentage: number): number;
|
|
45
45
|
/**
|
|
46
46
|
* Resolve offset untuk TO line (garis tujuan kurva).
|
|
47
47
|
* Kurva bisa ditempatkan di mana saja pada line: range [0, lineLength].
|
|
@@ -49,7 +49,7 @@ export declare function resolveFromLineOffset(line: Line, offset: number | undef
|
|
|
49
49
|
* Untuk absolute offset: clamp ke [0, lineLength].
|
|
50
50
|
* Untuk percentage (0-1): map ke [0, lineLength].
|
|
51
51
|
*/
|
|
52
|
-
export declare function resolveToLineOffset(line: Line, offset: number | undefined, isPercentage: boolean | undefined, defaultPercentage: number
|
|
52
|
+
export declare function resolveToLineOffset(line: Line, offset: number | undefined, isPercentage: boolean | undefined, defaultPercentage: number): number;
|
|
53
53
|
/**
|
|
54
54
|
* Membangun graph dari lines dan curves
|
|
55
55
|
*/
|
package/dist/core/engine.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* ```typescript
|
|
10
10
|
* import { PathEngine } from 'vehicle-path/core'
|
|
11
11
|
*
|
|
12
|
-
* const engine = new PathEngine({
|
|
12
|
+
* const engine = new PathEngine({ tangentMode: 'proportional-40' })
|
|
13
13
|
*
|
|
14
14
|
* engine.setScene(lines, curves)
|
|
15
15
|
*
|
|
@@ -31,7 +31,6 @@ import type { MovementConfig, CurveData } from './types/movement';
|
|
|
31
31
|
import type { PathResult } from './algorithms/pathFinding';
|
|
32
32
|
import type { TangentMode } from './types/config';
|
|
33
33
|
export interface PathEngineConfig {
|
|
34
|
-
maxWheelbase: number;
|
|
35
34
|
tangentMode: TangentMode;
|
|
36
35
|
}
|
|
37
36
|
/**
|
|
@@ -25,7 +25,7 @@ export interface VehicleStart {
|
|
|
25
25
|
lineId: string;
|
|
26
26
|
offset: number;
|
|
27
27
|
isPercentage: boolean;
|
|
28
|
-
/**
|
|
28
|
+
/** axleSpacings[i] = arc-length antara axles[i] dan axles[i+1]. Default: [] (1 axle) */
|
|
29
29
|
axleSpacings?: number[];
|
|
30
30
|
}
|
|
31
31
|
/**
|
package/dist/core.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./index-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./index-DQbf63_R.cjs");function P(n,e){const a={lines:n,curves:e.map(t=>({id:t.id,fromLineId:t.fromLineId,toLineId:t.toLineId,fromOffset:t.fromOffset,fromIsPercentage:t.fromIsPercentage??!1,toOffset:t.toOffset,toIsPercentage:t.toIsPercentage??!1}))};return JSON.stringify(a,null,2)}function O(n){let e;try{e=JSON.parse(n)}catch{throw new Error("deserializeScene: invalid JSON")}if(!e||typeof e!="object"||Array.isArray(e))throw new Error("deserializeScene: expected a JSON object");const a=e;if(!Array.isArray(a.lines))throw new Error('deserializeScene: missing "lines"');if(!Array.isArray(a.curves))throw new Error('deserializeScene: missing "curves"');return{lines:a.lines,curves:a.curves}}function h(n){const e=n.axleExecutions[n.axleExecutions.length-1],a=i.getCumulativeArcLength(n.path,e.segmentIndex,e.segmentDistance);return Math.max(0,n.path.totalDistance-a)}function d(n){const e=n.axleExecutions[0],a=i.getCumulativeArcLength(n.path,e.segmentIndex,e.segmentDistance);let t=0;for(let r=0;r<n.path.segments.length;r++){const o=n.path.segments[r];if(r>=e.segmentIndex&&o.type==="curve")return Math.max(0,t-a);t+=o.length}return null}function p(n,e,a){let t=a.maxSpeed;const r=Math.sqrt(2*a.deceleration*Math.max(0,n));if(t=Math.min(t,r),e!==null){const o=Math.sqrt(a.minCurveSpeed**2+2*a.deceleration*e);t=Math.min(t,o)}return Math.max(0,t)}function x(n,e,a,t,r){return n<e?Math.min(e,n+a*r):n>e?Math.max(e,n-t*r):n}function S(n,e,a,t,r,o){const c=h(e),l=d(e),f=p(c,l,t),g=x(a.currentSpeed,f,t.acceleration,t.deceleration,r),u=g*r,v=n.axles.map(s=>({lineId:s.lineId,position:s.position,absoluteOffset:s.offset})),L=e.axleExecutions.map(s=>({currentSegmentIndex:s.segmentIndex,segmentDistance:s.segmentDistance})),m=i.moveVehicle(v,L,e.path,u,o,e.curveDataMap);return{state:{axles:m.axles.map(s=>({lineId:s.lineId,offset:s.absoluteOffset,position:s.position})),axleSpacings:n.axleSpacings},execution:{...e,axleExecutions:m.axleExecutions.map(s=>({segmentIndex:s.currentSegmentIndex,segmentDistance:s.segmentDistance}))},accelState:{currentSpeed:g},arrived:m.arrived}}function A(n,e){const a=e.end.x-e.start.x,t=e.end.y-e.start.y,r=a*a+t*t;if(r===0)return{offset:0,distance:Math.sqrt((n.x-e.start.x)**2+(n.y-e.start.y)**2)};const o=Math.max(0,Math.min(1,((n.x-e.start.x)*a+(n.y-e.start.y)*t)/r)),c=e.start.x+o*a,l=e.start.y+o*t,f=Math.sqrt((n.x-c)**2+(n.y-l)**2);return{offset:o*Math.sqrt(r),distance:f}}function I(n,e){const a=i.getLineLength(n),t=e.reduce((o,c)=>o+c,0);return[0,Math.max(0,a-t)]}function M(n,e){let a=0;for(const t of e)t.fromLineId===n&&!t.fromIsPercentage&&t.fromOffset!==void 0&&(a=Math.max(a,t.fromOffset)),t.toLineId===n&&!t.toIsPercentage&&t.toOffset!==void 0&&(a=Math.max(a,t.toOffset));return a}exports.PathEngine=i.PathEngine;exports.arcLengthToSegmentPosition=i.arcLengthToSegmentPosition;exports.buildArcLengthTable=i.buildArcLengthTable;exports.buildGraph=i.buildGraph;exports.calculateBezierArcLength=i.calculateBezierArcLength;exports.calculateFrontAxlePosition=i.calculateFrontAxlePosition;exports.calculateInitialAxlePositions=i.calculateInitialAxlePositions;exports.calculatePositionOnCurve=i.calculatePositionOnCurve;exports.calculatePositionOnLine=i.calculatePositionOnLine;exports.calculateTangentLength=i.calculateTangentLength;exports.createBezierCurve=i.createBezierCurve;exports.createInitialMovementState=i.createInitialMovementState;exports.distance=i.distance;exports.distanceToT=i.distanceToT;exports.findPath=i.findPath;exports.getArcLength=i.getArcLength;exports.getCumulativeArcLength=i.getCumulativeArcLength;exports.getLineLength=i.getLineLength;exports.getPointOnBezier=i.getPointOnBezier;exports.getPointOnLine=i.getPointOnLine;exports.getPointOnLineByOffset=i.getPointOnLineByOffset;exports.getPositionFromOffset=i.getPositionFromOffset;exports.handleArrival=i.handleArrival;exports.initializeAllVehicles=i.initializeAllVehicles;exports.initializeMovingVehicle=i.initializeMovingVehicle;exports.isPointNearPoint=i.isPointNearPoint;exports.moveVehicle=i.moveVehicle;exports.normalize=i.normalize;exports.prepareCommandPath=i.prepareCommandPath;exports.resolveFromLineOffset=i.resolveFromLineOffset;exports.resolveToLineOffset=i.resolveToLineOffset;exports.updateAxlePosition=i.updateAxlePosition;exports.approachSpeed=x;exports.computeDistToNextCurve=d;exports.computeMinLineLength=M;exports.computeRemainingToArrival=h;exports.computeTargetSpeed=p;exports.deserializeScene=O;exports.getValidRearOffsetRange=I;exports.moveVehicleWithAcceleration=S;exports.projectPointOnLine=A;exports.serializeScene=P;
|
package/dist/core.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { g as u, m as x, a as p } from "./index-
|
|
2
|
-
import { P as T, b, c as j, d as q, e as C, f as N, h as B, i as V, j as J, k as F, l as R, n as k, o as G, p as W, q as X, r as Y, s as H, t as K, u as Q, v as U, w as Z, x as _, y as $, z as ee, A as te, B as ne, C as ae, D as se, E as re } from "./index-
|
|
1
|
+
import { g as u, m as x, a as p } from "./index-okJUn3WJ.js";
|
|
2
|
+
import { P as T, b, c as j, d as q, e as C, f as N, h as B, i as V, j as J, k as F, l as R, n as k, o as G, p as W, q as X, r as Y, s as H, t as K, u as Q, v as U, w as Z, x as _, y as $, z as ee, A as te, B as ne, C as ae, D as se, E as re } from "./index-okJUn3WJ.js";
|
|
3
3
|
function P(n, e) {
|
|
4
4
|
const a = {
|
|
5
5
|
lines: n,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";function L(t,e){const s=e.x-t.x,n=e.y-t.y;return Math.sqrt(s*s+n*n)}function T(t,e){const s=e.x-t.x,n=e.y-t.y,i=Math.sqrt(s*s+n*n);return i===0?{x:0,y:0}:{x:s/i,y:n/i}}function F(t,e){return e*(t==="proportional-40"?.4:.5522)}function z(t,e,s,n){const{tangentMode:i}=s;let c;n?.fromOffset!==void 0?c=V(t,n.fromOffset,n.fromIsPercentage??!1):c=t.end;let o;n?.toOffset!==void 0?o=V(e,n.toOffset,n.toIsPercentage??!1):o=e.start;const r=T(t.start,t.end),f=T(e.start,e.end),l=L(c,o),a=F(i,l),g={x:c.x+r.x*a,y:c.y+r.y*a},d={x:o.x-f.x*a,y:o.y-f.y*a};return{p0:c,p1:g,p2:d,p3:o}}function N(t,e){return{x:t.start.x+(t.end.x-t.start.x)*e,y:t.start.y+(t.end.y-t.start.y)*e}}function V(t,e,s){const n=L(t.start,t.end);let i;return s?i=e:i=n>0?e/n:0,i=Math.max(0,Math.min(1,i)),N(t,i)}function A(t,e){const{p0:s,p1:n,p2:i,p3:c}=t,o=1-e,r=o*o,f=r*o,l=e*e,a=l*e;return{x:f*s.x+3*r*e*n.x+3*o*l*i.x+a*c.x,y:f*s.y+3*r*e*n.y+3*o*l*i.y+a*c.y}}function ee(t,e,s=10){return L(t,e)<=s}function $(t,e=100){const s=[{t:0,distance:0}];let n=t.p0,i=0;for(let c=1;c<=e;c++){const o=c/e,r=A(t,o);i+=L(n,r),s.push({t:o,distance:i}),n=r}return s}function j(t,e){if(e<=0)return 0;const s=t[t.length-1].distance;if(e>=s)return 1;let n=0,i=t.length-1;for(;n<i-1;){const a=Math.floor((n+i)/2);t[a].distance<e?n=a:i=a}const c=t[n].distance,o=t[i].distance,r=t[n].t,f=t[i].t;if(o===c)return r;const l=(e-c)/(o-c);return r+l*(f-r)}function te(t){return t[t.length-1].distance}function K(t,e=100){let s=0,n=t.p0;for(let i=1;i<=e;i++){const c=i/e,o=A(t,c);s+=L(n,o),n=o}return s}function b(t,e,s,n){const i=L(t.start,t.end);return e===void 0?n*i:s?Math.max(0,Math.min(e,1))*i:Math.max(0,Math.min(e,i))}function B(t,e,s,n){const i=L(t.start,t.end);return e===void 0?n*i:s?Math.max(0,Math.min(e,1))*i:Math.max(0,Math.min(e,i))}function x(t,e,s){const n=new Map,i=new Map,c=new Map;for(const o of t)i.set(o.id,o),c.set(o.id,L(o.start,o.end)),n.set(o.id,[]);for(let o=0;o<e.length;o++){const r=e[o],f=i.get(r.fromLineId),l=i.get(r.toLineId);if(!f||!l)continue;const a=b(f,r.fromOffset,r.fromIsPercentage,1),g=B(l,r.toOffset,r.toIsPercentage,0),d=z(f,l,s,{fromOffset:a,fromIsPercentage:!1,toOffset:g,toIsPercentage:!1}),h=K(d),v={curveIndex:o,fromLineId:r.fromLineId,toLineId:r.toLineId,fromOffset:a,toOffset:g,curveLength:h};n.get(r.fromLineId).push(v)}return{adjacency:n,lines:i,lineLengths:c}}function q(t,e){return t.curveCount!==e.curveCount?t.curveCount-e.curveCount:t.totalDistance-e.totalDistance}function k(t,e,s,n,i=!1){const{adjacency:c,lines:o,lineLengths:r}=t;if(!o.get(s))return null;const l=r.get(s),a=i?n/100*l:n,g=[],d=new Map,h=(u,p)=>`${u}:${Math.round(p)}`;if(e.lineId===s&&a>=e.offset){const u=a-e.offset;return{segments:[{type:"line",lineId:e.lineId,startOffset:e.offset,endOffset:a,length:u}],totalDistance:u,curveCount:0}}const v=c.get(e.lineId)||[];for(const u of v){if(u.fromOffset<e.offset)continue;const p=u.fromOffset-e.offset,I=p+u.curveLength,O={type:"line",lineId:e.lineId,startOffset:e.offset,endOffset:u.fromOffset,length:p},m={type:"curve",curveIndex:u.curveIndex,startOffset:0,endOffset:u.curveLength,length:u.curveLength};g.push({lineId:u.toLineId,entryOffset:u.toOffset,totalDistance:I,curveCount:1,path:[O,m]})}for(g.sort(q);g.length>0;){const u=g.shift(),p=h(u.lineId,u.entryOffset),I=d.get(p);if(I!==void 0&&(I.curveCount<u.curveCount||I.curveCount===u.curveCount&&I.distance<=u.totalDistance))continue;if(d.set(p,{curveCount:u.curveCount,distance:u.totalDistance}),u.lineId===s){const m=Math.abs(a-u.entryOffset);if(a>=u.entryOffset){const C={type:"line",lineId:s,startOffset:u.entryOffset,endOffset:a,length:m};return{segments:[...u.path,C],totalDistance:u.totalDistance+m,curveCount:u.curveCount}}}const O=c.get(u.lineId)||[];for(const m of O){if(m.fromOffset<u.entryOffset)continue;const C=m.fromOffset-u.entryOffset,E=u.totalDistance+C+m.curveLength,w=u.curveCount+1,X=h(m.toLineId,m.toOffset),P=d.get(X);if(P!==void 0&&(P.curveCount<w||P.curveCount===w&&P.distance<=E))continue;const Y={type:"line",lineId:u.lineId,startOffset:u.entryOffset,endOffset:m.fromOffset,length:C},Z={type:"curve",curveIndex:m.curveIndex,startOffset:0,endOffset:m.curveLength,length:m.curveLength};g.push({lineId:m.toLineId,entryOffset:m.toOffset,totalDistance:E,curveCount:w,path:[...u.path,Y,Z]})}g.sort(q)}return null}function S(t,e){const s=Math.sqrt(Math.pow(t.end.x-t.start.x,2)+Math.pow(t.end.y-t.start.y,2)),n=s>0?e/s:0;return{x:t.start.x+(t.end.x-t.start.x)*Math.min(1,Math.max(0,n)),y:t.start.y+(t.end.y-t.start.y)*Math.min(1,Math.max(0,n))}}function M(t){return Math.sqrt(Math.pow(t.end.x-t.start.x,2)+Math.pow(t.end.y-t.start.y,2))}function G(t,e,s){let n=0;for(let i=0;i<e;i++)n+=t.segments[i].length;return n+=s,n}function Q(t,e){let s=0;for(let n=0;n<t.segments.length;n++){const i=t.segments[n],c=s+i.length;if(e<c)return{segmentIndex:n,segmentDistance:e-s};if(e===c)return n+1<t.segments.length?{segmentIndex:n+1,segmentDistance:0}:{segmentIndex:n,segmentDistance:i.length};s+=i.length}return null}function ne(t,e,s,n){const c=G(t,e,s)+n;return Q(t,c)}function R(t,e,s,n){const i=M(n),c=s.length+1,o=new Array(c);o[c-1]={lineId:t,absoluteOffset:e,position:S(n,e)};let r=e;for(let f=c-2;f>=0;f--)r=Math.min(r+s[f],i),o[f]={lineId:t,absoluteOffset:r,position:S(n,r)};return o}function W(t,e){return{...t,state:"idle"}}function _(t){return{vehicle:t,execution:null}}function se(t,e){const s=[],n=new Map;for(const i of t){if(!e.get(i.lineId))continue;const o=W(i);s.push(o);const r=_(o);n.set(i.id,r)}return{movingVehicles:s,stateMap:n}}function y(t,e){return{position:S(t,e),lineId:t.id,absoluteOffset:e}}function D(t,e){const s=j(t.arcLengthTable,e);return{position:A(t.bezier,s)}}function H(t,e,s,n,i,c,o){const r=s.segments[e.currentSegmentIndex],f=e.segmentDistance+n;if(f>=r.length){const a=f-r.length,g=e.currentSegmentIndex+1;if(g>=s.segments.length){if(o!==void 0&&r.type==="line"){const u=i.get(r.lineId),p=r.startOffset+f;if(p<=o){const O=y(u,p);return{axleState:{...t,...O},execution:{...e,segmentDistance:f},completed:!1}}const I=y(u,o);return{axleState:{...t,...I},execution:{...e,segmentDistance:o-r.startOffset},completed:!0}}const v=r.type==="line"?y(i.get(r.lineId),r.endOffset):D(c.get(r.curveIndex),r.length);return{axleState:{...t,...v},execution:{...e,segmentDistance:r.length},completed:!0}}const d=s.segments[g],h=d.type==="line"?y(i.get(d.lineId),d.startOffset+a):D(c.get(d.curveIndex),a);return{axleState:{...t,...h},execution:{currentSegmentIndex:g,segmentDistance:a},completed:!1}}const l=r.type==="line"?y(i.get(r.lineId),r.startOffset+f):D(c.get(r.curveIndex),f);return{axleState:{...t,...l},execution:{...e,segmentDistance:f},completed:!1}}function ie(t,e,s,n){const i=new Map;for(const c of t.segments)if(c.type==="curve"&&c.curveIndex!==void 0){const o=e[c.curveIndex];if(o){const r=s.get(o.fromLineId),f=s.get(o.toLineId);if(r&&f){const l=b(r,o.fromOffset,o.fromIsPercentage,1),a=B(f,o.toOffset,o.toIsPercentage,0),g=z(r,f,n,{fromOffset:l,fromIsPercentage:!1,toOffset:a,toIsPercentage:!1}),d=$(g);i.set(c.curveIndex,{bezier:g,arcLengthTable:d})}}}return i}function J(t,e,s){const{graph:n,linesMap:i,curves:c,config:o}=s,r=i.get(e.targetLineId);if(!r)return null;const f=t.axleSpacings.reduce((u,p)=>u+p,0),a=M(r)-f;if(a<=0)return null;const g=e.isPercentage?e.targetOffset*a:Math.min(e.targetOffset,a),d=t.axles[t.axles.length-1],h=k(n,{lineId:d.lineId,offset:d.absoluteOffset},e.targetLineId,g,!1);if(!h)return null;const v=ie(h,c,i,o);return{path:h,curveDataMap:v}}function re(t,e){const s=t.execution,i=e.vehicleQueues.get(t.vehicle.id)?.[s.currentCommandIndex];return i&&e.onCommandComplete&&e.onCommandComplete({vehicleId:t.vehicle.id,command:i,finalPosition:{lineId:t.vehicle.axles[t.vehicle.axles.length-1].lineId,absoluteOffset:t.vehicle.axles[t.vehicle.axles.length-1].absoluteOffset,position:t.vehicle.axles[t.vehicle.axles.length-1].position},payload:i.payload}),{handled:!0,vehicle:{...t.vehicle,state:"waiting"},newExecution:s,isWaiting:!0}}function U(t,e,s,n,i,c){let o;const r=e[0];if(r.currentSegmentIndex<s.segments.length){const l=s.segments[r.currentSegmentIndex];if(l.type==="line"){const a=i.get(l.lineId);a&&(o=M(a))}}const f=t.map((l,a)=>{const g=a===0?o:void 0;return H(l,e[a],s,n,i,c,g)});return{axles:f.map(l=>l.axleState),axleExecutions:f.map(l=>l.execution),arrived:f[f.length-1].completed}}class oe{graph=null;linesMap=new Map;curves=[];config;constructor(e){this.config={tangentMode:e.tangentMode}}get movementConfig(){return this.config}get lines(){return Array.from(this.linesMap.values())}getCurves(){return this.curves}setScene(e,s){this.linesMap.clear();for(const n of e)this.linesMap.set(n.id,n);this.curves=s,this.graph=x(e,s,this.config)}addLine(e){return this.linesMap.has(e.id)?!1:(this.linesMap.set(e.id,e),this.graph=x(Array.from(this.linesMap.values()),this.curves,this.config),!0)}updateLine(e,s){const n=this.linesMap.get(e);return n?(s.start&&(n.start=s.start),s.end&&(n.end=s.end),this.graph=x(Array.from(this.linesMap.values()),this.curves,this.config),!0):!1}updateLineEndpoint(e,s,n){return this.updateLine(e,{[s]:n})}renameLine(e,s){const n=s.trim();if(!n)return{success:!1,error:"Name cannot be empty"};if(n===e)return{success:!0};if(this.linesMap.has(n))return{success:!1,error:`"${n}" already exists`};const i=this.linesMap.get(e);if(!i)return{success:!1,error:`Line "${e}" not found`};i.id=n,this.linesMap.delete(e),this.linesMap.set(n,i);for(const c of this.curves)c.fromLineId===e&&(c.fromLineId=n),c.toLineId===e&&(c.toLineId=n);return this.graph=x(Array.from(this.linesMap.values()),this.curves,this.config),{success:!0}}removeLine(e){return this.linesMap.has(e)?(this.linesMap.delete(e),this.curves=this.curves.filter(s=>s.fromLineId!==e&&s.toLineId!==e),this.graph=x(Array.from(this.linesMap.values()),this.curves,this.config),!0):!1}addCurve(e){this.curves.push(e),this.graph=x(Array.from(this.linesMap.values()),this.curves,this.config)}updateCurve(e,s){return e<0||e>=this.curves.length?!1:(this.curves[e]={...this.curves[e],...s},this.graph=x(Array.from(this.linesMap.values()),this.curves,this.config),!0)}removeCurve(e){return e<0||e>=this.curves.length?!1:(this.curves.splice(e,1),this.graph=x(Array.from(this.linesMap.values()),this.curves,this.config),!0)}initializeVehicle(e,s,n){const i=this.linesMap.get(e);if(!i)return null;const{axleSpacings:c}=n;if(c.length===0)throw new Error("initializeVehicle: axleSpacings must have at least one entry (vehicle needs ≥2 axles)");const o=c.reduce((a,g)=>a+g,0),r=M(i),f=Math.min(s,r-o);return{axles:R(e,f,c,i).map(a=>({lineId:a.lineId,offset:a.absoluteOffset,position:a.position})),axleSpacings:c}}preparePath(e,s,n,i=!1){if(!this.graph)return null;const c=e.axleSpacings.reduce((h,v)=>h+v,0),o=e.axles[e.axles.length-1],r={lineId:o.lineId,offset:o.offset,axles:e.axles.map(h=>({lineId:h.lineId,position:h.position,absoluteOffset:h.offset})),axleSpacings:e.axleSpacings},f=J(r,{targetLineId:s,targetOffset:n,isPercentage:i},{graph:this.graph,linesMap:this.linesMap,curves:this.curves,config:this.config});if(!f)return null;let l=n;const a=this.linesMap.get(s);if(a){const h=Math.max(0,M(a)-c);l=i?n*h:Math.min(n,h)}let g=0;const d=[{segmentIndex:0,segmentDistance:c}];for(let h=0;h<e.axleSpacings.length;h++)g+=e.axleSpacings[h],d.push({segmentIndex:0,segmentDistance:c-g});return{path:f.path,curveDataMap:f.curveDataMap,axleExecutions:d,targetLineId:s,targetOffset:l}}moveVehicle(e,s,n){const i=e.axles.map(r=>({lineId:r.lineId,position:r.position,absoluteOffset:r.offset})),c=s.axleExecutions.map(r=>({currentSegmentIndex:r.segmentIndex,segmentDistance:r.segmentDistance})),o=U(i,c,s.path,n,this.linesMap,s.curveDataMap);return{state:{axles:o.axles.map(r=>({lineId:r.lineId,offset:r.absoluteOffset,position:r.position})),axleSpacings:e.axleSpacings},execution:{...s,axleExecutions:o.axleExecutions.map(r=>({segmentIndex:r.currentSegmentIndex,segmentDistance:r.segmentDistance}))},arrived:o.arrived}}}exports.PathEngine=oe;exports.arcLengthToSegmentPosition=Q;exports.buildArcLengthTable=$;exports.buildGraph=x;exports.calculateBezierArcLength=K;exports.calculateFrontAxlePosition=ne;exports.calculateInitialAxlePositions=R;exports.calculatePositionOnCurve=D;exports.calculatePositionOnLine=y;exports.calculateTangentLength=F;exports.createBezierCurve=z;exports.createInitialMovementState=_;exports.distance=L;exports.distanceToT=j;exports.findPath=k;exports.getArcLength=te;exports.getCumulativeArcLength=G;exports.getLineLength=M;exports.getPointOnBezier=A;exports.getPointOnLine=N;exports.getPointOnLineByOffset=V;exports.getPositionFromOffset=S;exports.handleArrival=re;exports.initializeAllVehicles=se;exports.initializeMovingVehicle=W;exports.isPointNearPoint=ee;exports.moveVehicle=U;exports.normalize=T;exports.prepareCommandPath=J;exports.resolveFromLineOffset=b;exports.resolveToLineOffset=B;exports.updateAxlePosition=H;
|
|
@@ -1,29 +1,22 @@
|
|
|
1
1
|
function y(t, e) {
|
|
2
|
-
const
|
|
3
|
-
return Math.sqrt(
|
|
2
|
+
const s = e.x - t.x, n = e.y - t.y;
|
|
3
|
+
return Math.sqrt(s * s + n * n);
|
|
4
4
|
}
|
|
5
|
-
function
|
|
6
|
-
const
|
|
7
|
-
return i === 0 ? { x: 0, y: 0 } : { x:
|
|
5
|
+
function V(t, e) {
|
|
6
|
+
const s = e.x - t.x, n = e.y - t.y, i = Math.sqrt(s * s + n * n);
|
|
7
|
+
return i === 0 ? { x: 0, y: 0 } : { x: s / i, y: n / i };
|
|
8
8
|
}
|
|
9
|
-
function
|
|
9
|
+
function F(t, e) {
|
|
10
10
|
return e * (t === "proportional-40" ? 0.4 : 0.5522);
|
|
11
11
|
}
|
|
12
|
-
function
|
|
13
|
-
const {
|
|
14
|
-
let
|
|
15
|
-
|
|
16
|
-
let
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
x: r.x - l.x * o,
|
|
21
|
-
y: r.y - l.y * o
|
|
22
|
-
} : r, g = S(t.start, t.end), d = S(e.start, e.end), h = y(c, f), p = k(a, h), u = s ? { x: c.x - g.x * p, y: c.y - g.y * p } : { x: c.x + g.x * p, y: c.y + g.y * p }, v = {
|
|
23
|
-
x: f.x - d.x * p,
|
|
24
|
-
y: f.y - d.y * p
|
|
25
|
-
};
|
|
26
|
-
return { p0: c, p1: u, p2: v, p3: f };
|
|
12
|
+
function q(t, e, s, n) {
|
|
13
|
+
const { tangentMode: i } = s;
|
|
14
|
+
let c;
|
|
15
|
+
n?.fromOffset !== void 0 ? c = z(t, n.fromOffset, n.fromIsPercentage ?? !1) : c = t.end;
|
|
16
|
+
let o;
|
|
17
|
+
n?.toOffset !== void 0 ? o = z(e, n.toOffset, n.toIsPercentage ?? !1) : o = e.start;
|
|
18
|
+
const r = V(t.start, t.end), f = V(e.start, e.end), l = y(c, o), a = F(i, l), g = { x: c.x + r.x * a, y: c.y + r.y * a }, d = { x: o.x - f.x * a, y: o.y - f.y * a };
|
|
19
|
+
return { p0: c, p1: g, p2: d, p3: o };
|
|
27
20
|
}
|
|
28
21
|
function K(t, e) {
|
|
29
22
|
return {
|
|
@@ -31,126 +24,122 @@ function K(t, e) {
|
|
|
31
24
|
y: t.start.y + (t.end.y - t.start.y) * e
|
|
32
25
|
};
|
|
33
26
|
}
|
|
34
|
-
function
|
|
35
|
-
const
|
|
27
|
+
function z(t, e, s) {
|
|
28
|
+
const n = y(t.start, t.end);
|
|
36
29
|
let i;
|
|
37
|
-
return
|
|
30
|
+
return s ? i = e : i = n > 0 ? e / n : 0, i = Math.max(0, Math.min(1, i)), K(t, i);
|
|
38
31
|
}
|
|
39
|
-
function
|
|
40
|
-
const { p0:
|
|
32
|
+
function A(t, e) {
|
|
33
|
+
const { p0: s, p1: n, p2: i, p3: c } = t, o = 1 - e, r = o * o, f = r * o, l = e * e, a = l * e;
|
|
41
34
|
return {
|
|
42
|
-
x: f *
|
|
43
|
-
y: f *
|
|
35
|
+
x: f * s.x + 3 * r * e * n.x + 3 * o * l * i.x + a * c.x,
|
|
36
|
+
y: f * s.y + 3 * r * e * n.y + 3 * o * l * i.y + a * c.y
|
|
44
37
|
};
|
|
45
38
|
}
|
|
46
|
-
function ne(t, e,
|
|
47
|
-
return y(t, e) <=
|
|
39
|
+
function ne(t, e, s = 10) {
|
|
40
|
+
return y(t, e) <= s;
|
|
48
41
|
}
|
|
49
42
|
function N(t, e = 100) {
|
|
50
|
-
const
|
|
51
|
-
let
|
|
52
|
-
for (let
|
|
53
|
-
const
|
|
54
|
-
i += y(
|
|
43
|
+
const s = [{ t: 0, distance: 0 }];
|
|
44
|
+
let n = t.p0, i = 0;
|
|
45
|
+
for (let c = 1; c <= e; c++) {
|
|
46
|
+
const o = c / e, r = A(t, o);
|
|
47
|
+
i += y(n, r), s.push({ t: o, distance: i }), n = r;
|
|
55
48
|
}
|
|
56
|
-
return
|
|
49
|
+
return s;
|
|
57
50
|
}
|
|
58
|
-
function
|
|
51
|
+
function G(t, e) {
|
|
59
52
|
if (e <= 0) return 0;
|
|
60
|
-
const
|
|
61
|
-
if (e >=
|
|
62
|
-
let
|
|
63
|
-
for (;
|
|
64
|
-
const
|
|
65
|
-
t[
|
|
53
|
+
const s = t[t.length - 1].distance;
|
|
54
|
+
if (e >= s) return 1;
|
|
55
|
+
let n = 0, i = t.length - 1;
|
|
56
|
+
for (; n < i - 1; ) {
|
|
57
|
+
const a = Math.floor((n + i) / 2);
|
|
58
|
+
t[a].distance < e ? n = a : i = a;
|
|
66
59
|
}
|
|
67
|
-
const
|
|
68
|
-
if (
|
|
69
|
-
const l = (e -
|
|
60
|
+
const c = t[n].distance, o = t[i].distance, r = t[n].t, f = t[i].t;
|
|
61
|
+
if (o === c) return r;
|
|
62
|
+
const l = (e - c) / (o - c);
|
|
70
63
|
return r + l * (f - r);
|
|
71
64
|
}
|
|
72
65
|
function se(t) {
|
|
73
66
|
return t[t.length - 1].distance;
|
|
74
67
|
}
|
|
75
|
-
function
|
|
76
|
-
let
|
|
68
|
+
function Q(t, e = 100) {
|
|
69
|
+
let s = 0, n = t.p0;
|
|
77
70
|
for (let i = 1; i <= e; i++) {
|
|
78
|
-
const
|
|
79
|
-
|
|
71
|
+
const c = i / e, o = A(t, c);
|
|
72
|
+
s += y(n, o), n = o;
|
|
80
73
|
}
|
|
81
|
-
return
|
|
82
|
-
}
|
|
83
|
-
function
|
|
84
|
-
const
|
|
85
|
-
return e === void 0 ?
|
|
86
|
-
}
|
|
87
|
-
function
|
|
88
|
-
const
|
|
89
|
-
return e === void 0 ?
|
|
90
|
-
}
|
|
91
|
-
function I(t, e,
|
|
92
|
-
const
|
|
93
|
-
for (const
|
|
94
|
-
i.set(
|
|
95
|
-
for (let
|
|
96
|
-
const r = e[
|
|
74
|
+
return s;
|
|
75
|
+
}
|
|
76
|
+
function E(t, e, s, n) {
|
|
77
|
+
const i = y(t.start, t.end);
|
|
78
|
+
return e === void 0 ? n * i : s ? Math.max(0, Math.min(e, 1)) * i : Math.max(0, Math.min(e, i));
|
|
79
|
+
}
|
|
80
|
+
function B(t, e, s, n) {
|
|
81
|
+
const i = y(t.start, t.end);
|
|
82
|
+
return e === void 0 ? n * i : s ? Math.max(0, Math.min(e, 1)) * i : Math.max(0, Math.min(e, i));
|
|
83
|
+
}
|
|
84
|
+
function I(t, e, s) {
|
|
85
|
+
const n = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map(), c = /* @__PURE__ */ new Map();
|
|
86
|
+
for (const o of t)
|
|
87
|
+
i.set(o.id, o), c.set(o.id, y(o.start, o.end)), n.set(o.id, []);
|
|
88
|
+
for (let o = 0; o < e.length; o++) {
|
|
89
|
+
const r = e[o], f = i.get(r.fromLineId), l = i.get(r.toLineId);
|
|
97
90
|
if (!f || !l) continue;
|
|
98
|
-
const
|
|
91
|
+
const a = E(f, r.fromOffset, r.fromIsPercentage, 1), g = B(l, r.toOffset, r.toIsPercentage, 0), d = q(
|
|
99
92
|
f,
|
|
100
93
|
l,
|
|
101
|
-
|
|
102
|
-
!1,
|
|
103
|
-
// willFlip is always false now
|
|
94
|
+
s,
|
|
104
95
|
{
|
|
105
|
-
fromOffset:
|
|
96
|
+
fromOffset: a,
|
|
106
97
|
fromIsPercentage: !1,
|
|
107
|
-
// Already resolved to absolute
|
|
108
98
|
toOffset: g,
|
|
109
99
|
toIsPercentage: !1
|
|
110
|
-
// Already resolved to absolute
|
|
111
100
|
}
|
|
112
|
-
), h =
|
|
113
|
-
curveIndex:
|
|
101
|
+
), h = Q(d), v = {
|
|
102
|
+
curveIndex: o,
|
|
114
103
|
fromLineId: r.fromLineId,
|
|
115
104
|
toLineId: r.toLineId,
|
|
116
|
-
fromOffset:
|
|
105
|
+
fromOffset: a,
|
|
117
106
|
toOffset: g,
|
|
118
107
|
curveLength: h
|
|
119
108
|
};
|
|
120
|
-
|
|
109
|
+
n.get(r.fromLineId).push(v);
|
|
121
110
|
}
|
|
122
|
-
return { adjacency:
|
|
111
|
+
return { adjacency: n, lines: i, lineLengths: c };
|
|
123
112
|
}
|
|
124
|
-
function
|
|
113
|
+
function b(t, e) {
|
|
125
114
|
return t.curveCount !== e.curveCount ? t.curveCount - e.curveCount : t.totalDistance - e.totalDistance;
|
|
126
115
|
}
|
|
127
|
-
function
|
|
128
|
-
const { adjacency:
|
|
129
|
-
if (!
|
|
130
|
-
const l = r.get(
|
|
131
|
-
if (e.lineId ===
|
|
132
|
-
const u =
|
|
116
|
+
function R(t, e, s, n, i = !1) {
|
|
117
|
+
const { adjacency: c, lines: o, lineLengths: r } = t;
|
|
118
|
+
if (!o.get(s)) return null;
|
|
119
|
+
const l = r.get(s), a = i ? n / 100 * l : n, g = [], d = /* @__PURE__ */ new Map(), h = (u, p) => `${u}:${Math.round(p)}`;
|
|
120
|
+
if (e.lineId === s && a >= e.offset) {
|
|
121
|
+
const u = a - e.offset;
|
|
133
122
|
return {
|
|
134
123
|
segments: [{
|
|
135
124
|
type: "line",
|
|
136
125
|
lineId: e.lineId,
|
|
137
126
|
startOffset: e.offset,
|
|
138
|
-
endOffset:
|
|
127
|
+
endOffset: a,
|
|
139
128
|
length: u
|
|
140
129
|
}],
|
|
141
130
|
totalDistance: u,
|
|
142
131
|
curveCount: 0
|
|
143
132
|
};
|
|
144
133
|
}
|
|
145
|
-
const
|
|
146
|
-
for (const u of
|
|
134
|
+
const v = c.get(e.lineId) || [];
|
|
135
|
+
for (const u of v) {
|
|
147
136
|
if (u.fromOffset < e.offset) continue;
|
|
148
|
-
const
|
|
137
|
+
const p = u.fromOffset - e.offset, x = p + u.curveLength, L = {
|
|
149
138
|
type: "line",
|
|
150
139
|
lineId: e.lineId,
|
|
151
140
|
startOffset: e.offset,
|
|
152
141
|
endOffset: u.fromOffset,
|
|
153
|
-
length:
|
|
142
|
+
length: p
|
|
154
143
|
}, m = {
|
|
155
144
|
type: "curve",
|
|
156
145
|
curveIndex: u.curveIndex,
|
|
@@ -166,18 +155,18 @@ function G(t, e, n, s, i = !1) {
|
|
|
166
155
|
path: [L, m]
|
|
167
156
|
});
|
|
168
157
|
}
|
|
169
|
-
for (g.sort(
|
|
170
|
-
const u = g.shift(),
|
|
158
|
+
for (g.sort(b); g.length > 0; ) {
|
|
159
|
+
const u = g.shift(), p = h(u.lineId, u.entryOffset), x = d.get(p);
|
|
171
160
|
if (x !== void 0 && (x.curveCount < u.curveCount || x.curveCount === u.curveCount && x.distance <= u.totalDistance))
|
|
172
161
|
continue;
|
|
173
|
-
if (d.set(
|
|
174
|
-
const m = Math.abs(
|
|
175
|
-
if (
|
|
162
|
+
if (d.set(p, { curveCount: u.curveCount, distance: u.totalDistance }), u.lineId === s) {
|
|
163
|
+
const m = Math.abs(a - u.entryOffset);
|
|
164
|
+
if (a >= u.entryOffset) {
|
|
176
165
|
const C = {
|
|
177
166
|
type: "line",
|
|
178
|
-
lineId:
|
|
167
|
+
lineId: s,
|
|
179
168
|
startOffset: u.entryOffset,
|
|
180
|
-
endOffset:
|
|
169
|
+
endOffset: a,
|
|
181
170
|
length: m
|
|
182
171
|
};
|
|
183
172
|
return {
|
|
@@ -187,19 +176,19 @@ function G(t, e, n, s, i = !1) {
|
|
|
187
176
|
};
|
|
188
177
|
}
|
|
189
178
|
}
|
|
190
|
-
const L =
|
|
179
|
+
const L = c.get(u.lineId) || [];
|
|
191
180
|
for (const m of L) {
|
|
192
181
|
if (m.fromOffset < u.entryOffset) continue;
|
|
193
|
-
const C = m.fromOffset - u.entryOffset, T = u.totalDistance + C + m.curveLength,
|
|
194
|
-
if (D !== void 0 && (D.curveCount <
|
|
182
|
+
const C = m.fromOffset - u.entryOffset, T = u.totalDistance + C + m.curveLength, S = u.curveCount + 1, j = h(m.toLineId, m.toOffset), D = d.get(j);
|
|
183
|
+
if (D !== void 0 && (D.curveCount < S || D.curveCount === S && D.distance <= T))
|
|
195
184
|
continue;
|
|
196
|
-
const
|
|
185
|
+
const $ = {
|
|
197
186
|
type: "line",
|
|
198
187
|
lineId: u.lineId,
|
|
199
188
|
startOffset: u.entryOffset,
|
|
200
189
|
endOffset: m.fromOffset,
|
|
201
190
|
length: C
|
|
202
|
-
},
|
|
191
|
+
}, k = {
|
|
203
192
|
type: "curve",
|
|
204
193
|
curveIndex: m.curveIndex,
|
|
205
194
|
startOffset: 0,
|
|
@@ -210,21 +199,21 @@ function G(t, e, n, s, i = !1) {
|
|
|
210
199
|
lineId: m.toLineId,
|
|
211
200
|
entryOffset: m.toOffset,
|
|
212
201
|
totalDistance: T,
|
|
213
|
-
curveCount:
|
|
214
|
-
path: [...u.path,
|
|
202
|
+
curveCount: S,
|
|
203
|
+
path: [...u.path, $, k]
|
|
215
204
|
});
|
|
216
205
|
}
|
|
217
|
-
g.sort(
|
|
206
|
+
g.sort(b);
|
|
218
207
|
}
|
|
219
208
|
return null;
|
|
220
209
|
}
|
|
221
|
-
function
|
|
222
|
-
const
|
|
210
|
+
function P(t, e) {
|
|
211
|
+
const s = Math.sqrt(
|
|
223
212
|
Math.pow(t.end.x - t.start.x, 2) + Math.pow(t.end.y - t.start.y, 2)
|
|
224
|
-
),
|
|
213
|
+
), n = s > 0 ? e / s : 0;
|
|
225
214
|
return {
|
|
226
|
-
x: t.start.x + (t.end.x - t.start.x) * Math.min(1, Math.max(0,
|
|
227
|
-
y: t.start.y + (t.end.y - t.start.y) * Math.min(1, Math.max(0,
|
|
215
|
+
x: t.start.x + (t.end.x - t.start.x) * Math.min(1, Math.max(0, n)),
|
|
216
|
+
y: t.start.y + (t.end.y - t.start.y) * Math.min(1, Math.max(0, n))
|
|
228
217
|
};
|
|
229
218
|
}
|
|
230
219
|
function O(t) {
|
|
@@ -232,56 +221,56 @@ function O(t) {
|
|
|
232
221
|
Math.pow(t.end.x - t.start.x, 2) + Math.pow(t.end.y - t.start.y, 2)
|
|
233
222
|
);
|
|
234
223
|
}
|
|
235
|
-
function
|
|
236
|
-
let
|
|
224
|
+
function W(t, e, s) {
|
|
225
|
+
let n = 0;
|
|
237
226
|
for (let i = 0; i < e; i++)
|
|
238
|
-
|
|
239
|
-
return
|
|
227
|
+
n += t.segments[i].length;
|
|
228
|
+
return n += s, n;
|
|
240
229
|
}
|
|
241
|
-
function
|
|
242
|
-
let
|
|
243
|
-
for (let
|
|
244
|
-
const i = t.segments[
|
|
245
|
-
if (e <
|
|
230
|
+
function _(t, e) {
|
|
231
|
+
let s = 0;
|
|
232
|
+
for (let n = 0; n < t.segments.length; n++) {
|
|
233
|
+
const i = t.segments[n], c = s + i.length;
|
|
234
|
+
if (e < c)
|
|
246
235
|
return {
|
|
247
|
-
segmentIndex:
|
|
248
|
-
segmentDistance: e -
|
|
236
|
+
segmentIndex: n,
|
|
237
|
+
segmentDistance: e - s
|
|
249
238
|
};
|
|
250
|
-
if (e ===
|
|
251
|
-
return
|
|
252
|
-
segmentIndex:
|
|
239
|
+
if (e === c)
|
|
240
|
+
return n + 1 < t.segments.length ? {
|
|
241
|
+
segmentIndex: n + 1,
|
|
253
242
|
segmentDistance: 0
|
|
254
243
|
} : {
|
|
255
|
-
segmentIndex:
|
|
244
|
+
segmentIndex: n,
|
|
256
245
|
segmentDistance: i.length
|
|
257
246
|
};
|
|
258
|
-
|
|
247
|
+
s += i.length;
|
|
259
248
|
}
|
|
260
249
|
return null;
|
|
261
250
|
}
|
|
262
|
-
function ie(t, e,
|
|
263
|
-
const
|
|
251
|
+
function ie(t, e, s, n) {
|
|
252
|
+
const c = W(
|
|
264
253
|
t,
|
|
265
254
|
e,
|
|
266
|
-
|
|
267
|
-
) +
|
|
268
|
-
return
|
|
255
|
+
s
|
|
256
|
+
) + n;
|
|
257
|
+
return _(t, c);
|
|
269
258
|
}
|
|
270
|
-
function H(t, e,
|
|
271
|
-
const i = O(
|
|
272
|
-
|
|
259
|
+
function H(t, e, s, n) {
|
|
260
|
+
const i = O(n), c = s.length + 1, o = new Array(c);
|
|
261
|
+
o[c - 1] = {
|
|
273
262
|
lineId: t,
|
|
274
263
|
absoluteOffset: e,
|
|
275
|
-
position:
|
|
264
|
+
position: P(n, e)
|
|
276
265
|
};
|
|
277
266
|
let r = e;
|
|
278
|
-
for (let f =
|
|
279
|
-
r = Math.min(r +
|
|
267
|
+
for (let f = c - 2; f >= 0; f--)
|
|
268
|
+
r = Math.min(r + s[f], i), o[f] = {
|
|
280
269
|
lineId: t,
|
|
281
270
|
absoluteOffset: r,
|
|
282
|
-
position:
|
|
271
|
+
position: P(n, r)
|
|
283
272
|
};
|
|
284
|
-
return
|
|
273
|
+
return o;
|
|
285
274
|
}
|
|
286
275
|
function J(t, e) {
|
|
287
276
|
return {
|
|
@@ -296,70 +285,70 @@ function U(t) {
|
|
|
296
285
|
};
|
|
297
286
|
}
|
|
298
287
|
function re(t, e) {
|
|
299
|
-
const
|
|
288
|
+
const s = [], n = /* @__PURE__ */ new Map();
|
|
300
289
|
for (const i of t) {
|
|
301
290
|
if (!e.get(i.lineId)) continue;
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
const r = U(
|
|
305
|
-
|
|
291
|
+
const o = J(i);
|
|
292
|
+
s.push(o);
|
|
293
|
+
const r = U(o);
|
|
294
|
+
n.set(i.id, r);
|
|
306
295
|
}
|
|
307
|
-
return { movingVehicles:
|
|
296
|
+
return { movingVehicles: s, stateMap: n };
|
|
308
297
|
}
|
|
309
298
|
function M(t, e) {
|
|
310
|
-
return { position:
|
|
299
|
+
return { position: P(t, e), lineId: t.id, absoluteOffset: e };
|
|
311
300
|
}
|
|
312
301
|
function w(t, e) {
|
|
313
|
-
const
|
|
314
|
-
return { position:
|
|
302
|
+
const s = G(t.arcLengthTable, e);
|
|
303
|
+
return { position: A(t.bezier, s) };
|
|
315
304
|
}
|
|
316
|
-
function X(t, e,
|
|
317
|
-
const r =
|
|
305
|
+
function X(t, e, s, n, i, c, o) {
|
|
306
|
+
const r = s.segments[e.currentSegmentIndex], f = e.segmentDistance + n;
|
|
318
307
|
if (f >= r.length) {
|
|
319
|
-
const
|
|
320
|
-
if (g >=
|
|
321
|
-
if (
|
|
322
|
-
const u = i.get(r.lineId),
|
|
323
|
-
if (
|
|
324
|
-
const L = M(u,
|
|
308
|
+
const a = f - r.length, g = e.currentSegmentIndex + 1;
|
|
309
|
+
if (g >= s.segments.length) {
|
|
310
|
+
if (o !== void 0 && r.type === "line") {
|
|
311
|
+
const u = i.get(r.lineId), p = r.startOffset + f;
|
|
312
|
+
if (p <= o) {
|
|
313
|
+
const L = M(u, p);
|
|
325
314
|
return {
|
|
326
315
|
axleState: { ...t, ...L },
|
|
327
316
|
execution: { ...e, segmentDistance: f },
|
|
328
317
|
completed: !1
|
|
329
318
|
};
|
|
330
319
|
}
|
|
331
|
-
const x = M(u,
|
|
320
|
+
const x = M(u, o);
|
|
332
321
|
return {
|
|
333
322
|
axleState: { ...t, ...x },
|
|
334
|
-
execution: { ...e, segmentDistance:
|
|
323
|
+
execution: { ...e, segmentDistance: o - r.startOffset },
|
|
335
324
|
completed: !0
|
|
336
325
|
};
|
|
337
326
|
}
|
|
338
|
-
const
|
|
327
|
+
const v = r.type === "line" ? M(
|
|
339
328
|
i.get(r.lineId),
|
|
340
329
|
r.endOffset
|
|
341
330
|
) : w(
|
|
342
|
-
|
|
331
|
+
c.get(r.curveIndex),
|
|
343
332
|
r.length
|
|
344
333
|
);
|
|
345
334
|
return {
|
|
346
|
-
axleState: { ...t, ...
|
|
335
|
+
axleState: { ...t, ...v },
|
|
347
336
|
execution: { ...e, segmentDistance: r.length },
|
|
348
337
|
completed: !0
|
|
349
338
|
};
|
|
350
339
|
}
|
|
351
|
-
const d =
|
|
340
|
+
const d = s.segments[g], h = d.type === "line" ? M(
|
|
352
341
|
i.get(d.lineId),
|
|
353
|
-
d.startOffset +
|
|
342
|
+
d.startOffset + a
|
|
354
343
|
) : w(
|
|
355
|
-
|
|
356
|
-
|
|
344
|
+
c.get(d.curveIndex),
|
|
345
|
+
a
|
|
357
346
|
);
|
|
358
347
|
return {
|
|
359
348
|
axleState: { ...t, ...h },
|
|
360
349
|
execution: {
|
|
361
350
|
currentSegmentIndex: g,
|
|
362
|
-
segmentDistance:
|
|
351
|
+
segmentDistance: a
|
|
363
352
|
},
|
|
364
353
|
completed: !1
|
|
365
354
|
};
|
|
@@ -368,7 +357,7 @@ function X(t, e, n, s, i, o, a) {
|
|
|
368
357
|
i.get(r.lineId),
|
|
369
358
|
r.startOffset + f
|
|
370
359
|
) : w(
|
|
371
|
-
|
|
360
|
+
c.get(r.curveIndex),
|
|
372
361
|
f
|
|
373
362
|
);
|
|
374
363
|
return {
|
|
@@ -377,66 +366,59 @@ function X(t, e, n, s, i, o, a) {
|
|
|
377
366
|
completed: !1
|
|
378
367
|
};
|
|
379
368
|
}
|
|
380
|
-
function Y(t, e,
|
|
369
|
+
function Y(t, e, s, n) {
|
|
381
370
|
const i = /* @__PURE__ */ new Map();
|
|
382
|
-
for (const
|
|
383
|
-
if (
|
|
384
|
-
const
|
|
385
|
-
if (
|
|
386
|
-
const r =
|
|
371
|
+
for (const c of t.segments)
|
|
372
|
+
if (c.type === "curve" && c.curveIndex !== void 0) {
|
|
373
|
+
const o = e[c.curveIndex];
|
|
374
|
+
if (o) {
|
|
375
|
+
const r = s.get(o.fromLineId), f = s.get(o.toLineId);
|
|
387
376
|
if (r && f) {
|
|
388
|
-
const l =
|
|
377
|
+
const l = E(
|
|
389
378
|
r,
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
1
|
|
393
|
-
|
|
394
|
-
s.maxWheelbase
|
|
395
|
-
), c = E(
|
|
379
|
+
o.fromOffset,
|
|
380
|
+
o.fromIsPercentage,
|
|
381
|
+
1
|
|
382
|
+
), a = B(
|
|
396
383
|
f,
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
0
|
|
400
|
-
|
|
401
|
-
), g = W(
|
|
384
|
+
o.toOffset,
|
|
385
|
+
o.toIsPercentage,
|
|
386
|
+
0
|
|
387
|
+
), g = q(
|
|
402
388
|
r,
|
|
403
389
|
f,
|
|
404
|
-
|
|
405
|
-
!1,
|
|
406
|
-
// willFlip is always false now
|
|
390
|
+
n,
|
|
407
391
|
{
|
|
408
392
|
fromOffset: l,
|
|
409
393
|
fromIsPercentage: !1,
|
|
410
|
-
|
|
411
|
-
toOffset: c,
|
|
394
|
+
toOffset: a,
|
|
412
395
|
toIsPercentage: !1
|
|
413
|
-
// Already resolved to absolute
|
|
414
396
|
}
|
|
415
397
|
), d = N(g);
|
|
416
|
-
i.set(
|
|
398
|
+
i.set(c.curveIndex, { bezier: g, arcLengthTable: d });
|
|
417
399
|
}
|
|
418
400
|
}
|
|
419
401
|
}
|
|
420
402
|
return i;
|
|
421
403
|
}
|
|
422
|
-
function Z(t, e,
|
|
423
|
-
const { graph:
|
|
404
|
+
function Z(t, e, s) {
|
|
405
|
+
const { graph: n, linesMap: i, curves: c, config: o } = s, r = i.get(e.targetLineId);
|
|
424
406
|
if (!r) return null;
|
|
425
|
-
const f = t.axleSpacings.reduce((u,
|
|
426
|
-
if (
|
|
427
|
-
const g = e.isPercentage ? e.targetOffset *
|
|
428
|
-
|
|
407
|
+
const f = t.axleSpacings.reduce((u, p) => u + p, 0), a = O(r) - f;
|
|
408
|
+
if (a <= 0) return null;
|
|
409
|
+
const g = e.isPercentage ? e.targetOffset * a : Math.min(e.targetOffset, a), d = t.axles[t.axles.length - 1], h = R(
|
|
410
|
+
n,
|
|
429
411
|
{ lineId: d.lineId, offset: d.absoluteOffset },
|
|
430
412
|
e.targetLineId,
|
|
431
413
|
g,
|
|
432
414
|
!1
|
|
433
415
|
);
|
|
434
416
|
if (!h) return null;
|
|
435
|
-
const
|
|
436
|
-
return { path: h, curveDataMap:
|
|
417
|
+
const v = Y(h, c, i, o);
|
|
418
|
+
return { path: h, curveDataMap: v };
|
|
437
419
|
}
|
|
438
420
|
function oe(t, e) {
|
|
439
|
-
const
|
|
421
|
+
const s = t.execution, i = e.vehicleQueues.get(t.vehicle.id)?.[s.currentCommandIndex];
|
|
440
422
|
return i && e.onCommandComplete && e.onCommandComplete({
|
|
441
423
|
vehicleId: t.vehicle.id,
|
|
442
424
|
command: i,
|
|
@@ -449,24 +431,24 @@ function oe(t, e) {
|
|
|
449
431
|
}), {
|
|
450
432
|
handled: !0,
|
|
451
433
|
vehicle: { ...t.vehicle, state: "waiting" },
|
|
452
|
-
newExecution:
|
|
434
|
+
newExecution: s,
|
|
453
435
|
// Keep execution state for resume
|
|
454
436
|
isWaiting: !0
|
|
455
437
|
};
|
|
456
438
|
}
|
|
457
|
-
function ee(t, e,
|
|
458
|
-
let
|
|
439
|
+
function ee(t, e, s, n, i, c) {
|
|
440
|
+
let o;
|
|
459
441
|
const r = e[0];
|
|
460
|
-
if (r.currentSegmentIndex <
|
|
461
|
-
const l =
|
|
442
|
+
if (r.currentSegmentIndex < s.segments.length) {
|
|
443
|
+
const l = s.segments[r.currentSegmentIndex];
|
|
462
444
|
if (l.type === "line") {
|
|
463
|
-
const
|
|
464
|
-
|
|
445
|
+
const a = i.get(l.lineId);
|
|
446
|
+
a && (o = O(a));
|
|
465
447
|
}
|
|
466
448
|
}
|
|
467
|
-
const f = t.map((l,
|
|
468
|
-
const g =
|
|
469
|
-
return X(l, e[
|
|
449
|
+
const f = t.map((l, a) => {
|
|
450
|
+
const g = a === 0 ? o : void 0;
|
|
451
|
+
return X(l, e[a], s, n, i, c, g);
|
|
470
452
|
});
|
|
471
453
|
return {
|
|
472
454
|
axles: f.map((l) => l.axleState),
|
|
@@ -475,14 +457,13 @@ function ee(t, e, n, s, i, o) {
|
|
|
475
457
|
// axles[N-1] = rearmost menentukan arrived
|
|
476
458
|
};
|
|
477
459
|
}
|
|
478
|
-
class
|
|
460
|
+
class ce {
|
|
479
461
|
graph = null;
|
|
480
462
|
linesMap = /* @__PURE__ */ new Map();
|
|
481
463
|
curves = [];
|
|
482
464
|
config;
|
|
483
465
|
constructor(e) {
|
|
484
466
|
this.config = {
|
|
485
|
-
maxWheelbase: e.maxWheelbase,
|
|
486
467
|
tangentMode: e.tangentMode
|
|
487
468
|
};
|
|
488
469
|
}
|
|
@@ -504,11 +485,11 @@ class ae {
|
|
|
504
485
|
/**
|
|
505
486
|
* Replace the entire scene and rebuild the graph.
|
|
506
487
|
*/
|
|
507
|
-
setScene(e,
|
|
488
|
+
setScene(e, s) {
|
|
508
489
|
this.linesMap.clear();
|
|
509
|
-
for (const
|
|
510
|
-
this.linesMap.set(
|
|
511
|
-
this.curves =
|
|
490
|
+
for (const n of e)
|
|
491
|
+
this.linesMap.set(n.id, n);
|
|
492
|
+
this.curves = s, this.graph = I(e, s, this.config);
|
|
512
493
|
}
|
|
513
494
|
/**
|
|
514
495
|
* Add a single line. Returns false if a line with the same ID already exists.
|
|
@@ -519,36 +500,36 @@ class ae {
|
|
|
519
500
|
/**
|
|
520
501
|
* Update start and/or end coordinates of an existing line.
|
|
521
502
|
*/
|
|
522
|
-
updateLine(e,
|
|
523
|
-
const
|
|
524
|
-
return
|
|
503
|
+
updateLine(e, s) {
|
|
504
|
+
const n = this.linesMap.get(e);
|
|
505
|
+
return n ? (s.start && (n.start = s.start), s.end && (n.end = s.end), this.graph = I(Array.from(this.linesMap.values()), this.curves, this.config), !0) : !1;
|
|
525
506
|
}
|
|
526
507
|
/**
|
|
527
508
|
* Update a single endpoint ('start' or 'end') of a line.
|
|
528
509
|
*/
|
|
529
|
-
updateLineEndpoint(e,
|
|
530
|
-
return this.updateLine(e, { [
|
|
510
|
+
updateLineEndpoint(e, s, n) {
|
|
511
|
+
return this.updateLine(e, { [s]: n });
|
|
531
512
|
}
|
|
532
513
|
/**
|
|
533
514
|
* Rename a line ID and cascade the change to all connected curves.
|
|
534
515
|
*/
|
|
535
|
-
renameLine(e,
|
|
536
|
-
const
|
|
537
|
-
if (!
|
|
538
|
-
if (
|
|
539
|
-
if (this.linesMap.has(
|
|
516
|
+
renameLine(e, s) {
|
|
517
|
+
const n = s.trim();
|
|
518
|
+
if (!n) return { success: !1, error: "Name cannot be empty" };
|
|
519
|
+
if (n === e) return { success: !0 };
|
|
520
|
+
if (this.linesMap.has(n)) return { success: !1, error: `"${n}" already exists` };
|
|
540
521
|
const i = this.linesMap.get(e);
|
|
541
522
|
if (!i) return { success: !1, error: `Line "${e}" not found` };
|
|
542
|
-
i.id =
|
|
543
|
-
for (const
|
|
544
|
-
|
|
523
|
+
i.id = n, this.linesMap.delete(e), this.linesMap.set(n, i);
|
|
524
|
+
for (const c of this.curves)
|
|
525
|
+
c.fromLineId === e && (c.fromLineId = n), c.toLineId === e && (c.toLineId = n);
|
|
545
526
|
return this.graph = I(Array.from(this.linesMap.values()), this.curves, this.config), { success: !0 };
|
|
546
527
|
}
|
|
547
528
|
/**
|
|
548
529
|
* Remove a line and all curves connected to it.
|
|
549
530
|
*/
|
|
550
531
|
removeLine(e) {
|
|
551
|
-
return this.linesMap.has(e) ? (this.linesMap.delete(e), this.curves = this.curves.filter((
|
|
532
|
+
return this.linesMap.has(e) ? (this.linesMap.delete(e), this.curves = this.curves.filter((s) => s.fromLineId !== e && s.toLineId !== e), this.graph = I(Array.from(this.linesMap.values()), this.curves, this.config), !0) : !1;
|
|
552
533
|
}
|
|
553
534
|
/**
|
|
554
535
|
* Add a directional curve (connection) from one line to another.
|
|
@@ -559,8 +540,8 @@ class ae {
|
|
|
559
540
|
/**
|
|
560
541
|
* Update a curve by index. Returns false if index is out of bounds.
|
|
561
542
|
*/
|
|
562
|
-
updateCurve(e,
|
|
563
|
-
return e < 0 || e >= this.curves.length ? !1 : (this.curves[e] = { ...this.curves[e], ...
|
|
543
|
+
updateCurve(e, s) {
|
|
544
|
+
return e < 0 || e >= this.curves.length ? !1 : (this.curves[e] = { ...this.curves[e], ...s }, this.graph = I(Array.from(this.linesMap.values()), this.curves, this.config), !0);
|
|
564
545
|
}
|
|
565
546
|
/**
|
|
566
547
|
* Remove a curve by index. Returns false if index is out of bounds.
|
|
@@ -580,16 +561,16 @@ class ae {
|
|
|
580
561
|
* @returns Initial VehiclePathState, or null if lineId does not exist
|
|
581
562
|
* @throws if axleSpacings is empty
|
|
582
563
|
*/
|
|
583
|
-
initializeVehicle(e,
|
|
564
|
+
initializeVehicle(e, s, n) {
|
|
584
565
|
const i = this.linesMap.get(e);
|
|
585
566
|
if (!i) return null;
|
|
586
|
-
const { axleSpacings:
|
|
587
|
-
if (
|
|
567
|
+
const { axleSpacings: c } = n;
|
|
568
|
+
if (c.length === 0)
|
|
588
569
|
throw new Error("initializeVehicle: axleSpacings must have at least one entry (vehicle needs ≥2 axles)");
|
|
589
|
-
const
|
|
570
|
+
const o = c.reduce((a, g) => a + g, 0), r = O(i), f = Math.min(s, r - o);
|
|
590
571
|
return {
|
|
591
|
-
axles: H(e, f,
|
|
592
|
-
axleSpacings:
|
|
572
|
+
axles: H(e, f, c, i).map((a) => ({ lineId: a.lineId, offset: a.absoluteOffset, position: a.position })),
|
|
573
|
+
axleSpacings: c
|
|
593
574
|
};
|
|
594
575
|
}
|
|
595
576
|
/**
|
|
@@ -602,11 +583,11 @@ class ae {
|
|
|
602
583
|
* @param targetOffset - Position on the target line
|
|
603
584
|
* @param isPercentage - If true, targetOffset is 0-1 fraction; if false, absolute distance
|
|
604
585
|
*/
|
|
605
|
-
preparePath(e,
|
|
586
|
+
preparePath(e, s, n, i = !1) {
|
|
606
587
|
if (!this.graph) return null;
|
|
607
|
-
const
|
|
608
|
-
lineId:
|
|
609
|
-
offset:
|
|
588
|
+
const c = e.axleSpacings.reduce((h, v) => h + v, 0), o = e.axles[e.axles.length - 1], r = {
|
|
589
|
+
lineId: o.lineId,
|
|
590
|
+
offset: o.offset,
|
|
610
591
|
axles: e.axles.map((h) => ({
|
|
611
592
|
lineId: h.lineId,
|
|
612
593
|
position: h.position,
|
|
@@ -614,8 +595,8 @@ class ae {
|
|
|
614
595
|
})),
|
|
615
596
|
axleSpacings: e.axleSpacings
|
|
616
597
|
}, f = Z(r, {
|
|
617
|
-
targetLineId:
|
|
618
|
-
targetOffset:
|
|
598
|
+
targetLineId: s,
|
|
599
|
+
targetOffset: n,
|
|
619
600
|
isPercentage: i
|
|
620
601
|
}, {
|
|
621
602
|
graph: this.graph,
|
|
@@ -624,24 +605,24 @@ class ae {
|
|
|
624
605
|
config: this.config
|
|
625
606
|
});
|
|
626
607
|
if (!f) return null;
|
|
627
|
-
let l =
|
|
628
|
-
const
|
|
629
|
-
if (
|
|
630
|
-
const h = Math.max(0, O(
|
|
631
|
-
l = i ?
|
|
608
|
+
let l = n;
|
|
609
|
+
const a = this.linesMap.get(s);
|
|
610
|
+
if (a) {
|
|
611
|
+
const h = Math.max(0, O(a) - c);
|
|
612
|
+
l = i ? n * h : Math.min(n, h);
|
|
632
613
|
}
|
|
633
614
|
let g = 0;
|
|
634
615
|
const d = [
|
|
635
|
-
{ segmentIndex: 0, segmentDistance:
|
|
616
|
+
{ segmentIndex: 0, segmentDistance: c }
|
|
636
617
|
// axles[0] = front
|
|
637
618
|
];
|
|
638
619
|
for (let h = 0; h < e.axleSpacings.length; h++)
|
|
639
|
-
g += e.axleSpacings[h], d.push({ segmentIndex: 0, segmentDistance:
|
|
620
|
+
g += e.axleSpacings[h], d.push({ segmentIndex: 0, segmentDistance: c - g });
|
|
640
621
|
return {
|
|
641
622
|
path: f.path,
|
|
642
623
|
curveDataMap: f.curveDataMap,
|
|
643
624
|
axleExecutions: d,
|
|
644
|
-
targetLineId:
|
|
625
|
+
targetLineId: s,
|
|
645
626
|
targetOffset: l
|
|
646
627
|
};
|
|
647
628
|
}
|
|
@@ -655,60 +636,60 @@ class ae {
|
|
|
655
636
|
* @param execution - Current path execution (from preparePath or previous tick)
|
|
656
637
|
* @param distance - Distance to advance this tick (speed × deltaTime)
|
|
657
638
|
*/
|
|
658
|
-
moveVehicle(e,
|
|
639
|
+
moveVehicle(e, s, n) {
|
|
659
640
|
const i = e.axles.map((r) => ({
|
|
660
641
|
lineId: r.lineId,
|
|
661
642
|
position: r.position,
|
|
662
643
|
absoluteOffset: r.offset
|
|
663
|
-
})),
|
|
644
|
+
})), c = s.axleExecutions.map((r) => ({
|
|
664
645
|
currentSegmentIndex: r.segmentIndex,
|
|
665
646
|
segmentDistance: r.segmentDistance
|
|
666
|
-
})),
|
|
647
|
+
})), o = ee(i, c, s.path, n, this.linesMap, s.curveDataMap);
|
|
667
648
|
return {
|
|
668
649
|
state: {
|
|
669
|
-
axles:
|
|
650
|
+
axles: o.axles.map((r) => ({ lineId: r.lineId, offset: r.absoluteOffset, position: r.position })),
|
|
670
651
|
axleSpacings: e.axleSpacings
|
|
671
652
|
},
|
|
672
653
|
execution: {
|
|
673
|
-
...
|
|
674
|
-
axleExecutions:
|
|
654
|
+
...s,
|
|
655
|
+
axleExecutions: o.axleExecutions.map((r) => ({
|
|
675
656
|
segmentIndex: r.currentSegmentIndex,
|
|
676
657
|
segmentDistance: r.segmentDistance
|
|
677
658
|
}))
|
|
678
659
|
},
|
|
679
|
-
arrived:
|
|
660
|
+
arrived: o.arrived
|
|
680
661
|
};
|
|
681
662
|
}
|
|
682
663
|
}
|
|
683
664
|
export {
|
|
684
|
-
|
|
665
|
+
V as A,
|
|
685
666
|
Z as B,
|
|
686
|
-
|
|
687
|
-
|
|
667
|
+
E as C,
|
|
668
|
+
B as D,
|
|
688
669
|
X as E,
|
|
689
|
-
|
|
670
|
+
ce as P,
|
|
690
671
|
O as a,
|
|
691
|
-
|
|
672
|
+
_ as b,
|
|
692
673
|
N as c,
|
|
693
674
|
I as d,
|
|
694
|
-
|
|
675
|
+
Q as e,
|
|
695
676
|
ie as f,
|
|
696
|
-
|
|
677
|
+
W as g,
|
|
697
678
|
H as h,
|
|
698
679
|
w as i,
|
|
699
680
|
M as j,
|
|
700
|
-
k,
|
|
701
|
-
|
|
681
|
+
F as k,
|
|
682
|
+
q as l,
|
|
702
683
|
ee as m,
|
|
703
684
|
U as n,
|
|
704
685
|
y as o,
|
|
705
|
-
|
|
706
|
-
|
|
686
|
+
G as p,
|
|
687
|
+
R as q,
|
|
707
688
|
se as r,
|
|
708
|
-
|
|
689
|
+
A as s,
|
|
709
690
|
K as t,
|
|
710
|
-
|
|
711
|
-
|
|
691
|
+
z as u,
|
|
692
|
+
P as v,
|
|
712
693
|
oe as w,
|
|
713
694
|
re as x,
|
|
714
695
|
J as y,
|
package/dist/vehicle-path.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-DQbf63_R.cjs");exports.PathEngine=e.PathEngine;exports.arcLengthToSegmentPosition=e.arcLengthToSegmentPosition;exports.buildArcLengthTable=e.buildArcLengthTable;exports.buildGraph=e.buildGraph;exports.calculateBezierArcLength=e.calculateBezierArcLength;exports.calculateFrontAxlePosition=e.calculateFrontAxlePosition;exports.calculateInitialAxlePositions=e.calculateInitialAxlePositions;exports.calculatePositionOnCurve=e.calculatePositionOnCurve;exports.calculatePositionOnLine=e.calculatePositionOnLine;exports.createBezierCurve=e.createBezierCurve;exports.createInitialMovementState=e.createInitialMovementState;exports.distance=e.distance;exports.distanceToT=e.distanceToT;exports.findPath=e.findPath;exports.getArcLength=e.getArcLength;exports.getCumulativeArcLength=e.getCumulativeArcLength;exports.getLineLength=e.getLineLength;exports.getPointOnBezier=e.getPointOnBezier;exports.getPointOnLine=e.getPointOnLine;exports.getPointOnLineByOffset=e.getPointOnLineByOffset;exports.getPositionFromOffset=e.getPositionFromOffset;exports.handleArrival=e.handleArrival;exports.initializeAllVehicles=e.initializeAllVehicles;exports.initializeMovingVehicle=e.initializeMovingVehicle;exports.moveVehicle=e.moveVehicle;exports.normalize=e.normalize;exports.prepareCommandPath=e.prepareCommandPath;exports.resolveFromLineOffset=e.resolveFromLineOffset;exports.resolveToLineOffset=e.resolveToLineOffset;exports.updateAxlePosition=e.updateAxlePosition;
|
package/dist/vehicle-path.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as i, b as t, c as s, d as n, e as o, f as l, h as r, i as c, j as g, l as h, n as P, o as u, p as L, q as f, r as m, g as v, a as A, s as d, t as O, u as p, v as z, w as x, x as B, y as C, m as T, A as b, B as F, C as V, D as y, E } from "./index-
|
|
1
|
+
import { P as i, b as t, c as s, d as n, e as o, f as l, h as r, i as c, j as g, l as h, n as P, o as u, p as L, q as f, r as m, g as v, a as A, s as d, t as O, u as p, v as z, w as x, x as B, y as C, m as T, A as b, B as F, C as V, D as y, E } from "./index-okJUn3WJ.js";
|
|
2
2
|
export {
|
|
3
3
|
i as PathEngine,
|
|
4
4
|
t as arcLengthToSegmentPosition,
|
package/package.json
CHANGED
package/dist/index-C4FckUel.cjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";function L(t,e){const n=e.x-t.x,s=e.y-t.y;return Math.sqrt(n*n+s*s)}function D(t,e){const n=e.x-t.x,s=e.y-t.y,i=Math.sqrt(n*n+s*s);return i===0?{x:0,y:0}:{x:n/i,y:s/i}}function q(t,e){return e*(t==="proportional-40"?.4:.5522)}function V(t,e,n,s=!1,i){const{maxWheelbase:o,tangentMode:c}=n;let r;i?.fromOffset!==void 0?r=b(t,i.fromOffset,i.fromIsPercentage??!1):r=t.end;let u;i?.toOffset!==void 0?u=b(e,i.toOffset,i.toIsPercentage??!1):u=e.start;const l=D(t.start,t.end),a=s?{x:r.x-l.x*o,y:r.y-l.y*o}:r,g=D(t.start,t.end),d=D(e.start,e.end),h=L(a,u),p=q(c,h),f=s?{x:a.x-g.x*p,y:a.y-g.y*p}:{x:a.x+g.x*p,y:a.y+g.y*p},v={x:u.x-d.x*p,y:u.y-d.y*p};return{p0:a,p1:f,p2:v,p3:u}}function F(t,e){return{x:t.start.x+(t.end.x-t.start.x)*e,y:t.start.y+(t.end.y-t.start.y)*e}}function b(t,e,n){const s=L(t.start,t.end);let i;return n?i=e:i=s>0?e/s:0,i=Math.max(0,Math.min(1,i)),F(t,i)}function w(t,e){const{p0:n,p1:s,p2:i,p3:o}=t,c=1-e,r=c*c,u=r*c,l=e*e,a=l*e;return{x:u*n.x+3*r*e*s.x+3*c*l*i.x+a*o.x,y:u*n.y+3*r*e*s.y+3*c*l*i.y+a*o.y}}function ee(t,e,n=10){return L(t,e)<=n}function N(t,e=100){const n=[{t:0,distance:0}];let s=t.p0,i=0;for(let o=1;o<=e;o++){const c=o/e,r=w(t,c);i+=L(s,r),n.push({t:c,distance:i}),s=r}return n}function $(t,e){if(e<=0)return 0;const n=t[t.length-1].distance;if(e>=n)return 1;let s=0,i=t.length-1;for(;s<i-1;){const a=Math.floor((s+i)/2);t[a].distance<e?s=a:i=a}const o=t[s].distance,c=t[i].distance,r=t[s].t,u=t[i].t;if(c===o)return r;const l=(e-o)/(c-o);return r+l*(u-r)}function te(t){return t[t.length-1].distance}function j(t,e=100){let n=0,s=t.p0;for(let i=1;i<=e;i++){const o=i/e,c=w(t,o);n+=L(s,c),s=c}return n}function z(t,e,n,s,i){const o=L(t.start,t.end);return e===void 0?s*o:n?Math.max(0,Math.min(e,1))*o:Math.max(0,Math.min(e,o))}function W(t,e,n,s,i){const o=L(t.start,t.end);return e===void 0?s*o:n?Math.max(0,Math.min(e,1))*o:Math.max(0,Math.min(e,o))}function x(t,e,n){const s=new Map,i=new Map,o=new Map;for(const c of t)i.set(c.id,c),o.set(c.id,L(c.start,c.end)),s.set(c.id,[]);for(let c=0;c<e.length;c++){const r=e[c],u=i.get(r.fromLineId),l=i.get(r.toLineId);if(!u||!l)continue;const a=z(u,r.fromOffset,r.fromIsPercentage,1,n.maxWheelbase),g=W(l,r.toOffset,r.toIsPercentage,0,n.maxWheelbase),d=V(u,l,n,!1,{fromOffset:a,fromIsPercentage:!1,toOffset:g,toIsPercentage:!1}),h=j(d),p={curveIndex:c,fromLineId:r.fromLineId,toLineId:r.toLineId,fromOffset:a,toOffset:g,curveLength:h};s.get(r.fromLineId).push(p)}return{adjacency:s,lines:i,lineLengths:o}}function E(t,e){return t.curveCount!==e.curveCount?t.curveCount-e.curveCount:t.totalDistance-e.totalDistance}function K(t,e,n,s,i=!1){const{adjacency:o,lines:c,lineLengths:r}=t;if(!c.get(n))return null;const l=r.get(n),a=i?s/100*l:s,g=[],d=new Map,h=(f,v)=>`${f}:${Math.round(v)}`;if(e.lineId===n&&a>=e.offset){const f=a-e.offset;return{segments:[{type:"line",lineId:e.lineId,startOffset:e.offset,endOffset:a,length:f}],totalDistance:f,curveCount:0}}const p=o.get(e.lineId)||[];for(const f of p){if(f.fromOffset<e.offset)continue;const v=f.fromOffset-e.offset,I=v+f.curveLength,O={type:"line",lineId:e.lineId,startOffset:e.offset,endOffset:f.fromOffset,length:v},m={type:"curve",curveIndex:f.curveIndex,startOffset:0,endOffset:f.curveLength,length:f.curveLength};g.push({lineId:f.toLineId,entryOffset:f.toOffset,totalDistance:I,curveCount:1,path:[O,m]})}for(g.sort(E);g.length>0;){const f=g.shift(),v=h(f.lineId,f.entryOffset),I=d.get(v);if(I!==void 0&&(I.curveCount<f.curveCount||I.curveCount===f.curveCount&&I.distance<=f.totalDistance))continue;if(d.set(v,{curveCount:f.curveCount,distance:f.totalDistance}),f.lineId===n){const m=Math.abs(a-f.entryOffset);if(a>=f.entryOffset){const P={type:"line",lineId:n,startOffset:f.entryOffset,endOffset:a,length:m};return{segments:[...f.path,P],totalDistance:f.totalDistance+m,curveCount:f.curveCount}}}const O=o.get(f.lineId)||[];for(const m of O){if(m.fromOffset<f.entryOffset)continue;const P=m.fromOffset-f.entryOffset,B=f.totalDistance+P+m.curveLength,T=f.curveCount+1,X=h(m.toLineId,m.toOffset),C=d.get(X);if(C!==void 0&&(C.curveCount<T||C.curveCount===T&&C.distance<=B))continue;const Y={type:"line",lineId:f.lineId,startOffset:f.entryOffset,endOffset:m.fromOffset,length:P},Z={type:"curve",curveIndex:m.curveIndex,startOffset:0,endOffset:m.curveLength,length:m.curveLength};g.push({lineId:m.toLineId,entryOffset:m.toOffset,totalDistance:B,curveCount:T,path:[...f.path,Y,Z]})}g.sort(E)}return null}function A(t,e){const n=Math.sqrt(Math.pow(t.end.x-t.start.x,2)+Math.pow(t.end.y-t.start.y,2)),s=n>0?e/n:0;return{x:t.start.x+(t.end.x-t.start.x)*Math.min(1,Math.max(0,s)),y:t.start.y+(t.end.y-t.start.y)*Math.min(1,Math.max(0,s))}}function M(t){return Math.sqrt(Math.pow(t.end.x-t.start.x,2)+Math.pow(t.end.y-t.start.y,2))}function _(t,e,n){let s=0;for(let i=0;i<e;i++)s+=t.segments[i].length;return s+=n,s}function k(t,e){let n=0;for(let s=0;s<t.segments.length;s++){const i=t.segments[s],o=n+i.length;if(e<o)return{segmentIndex:s,segmentDistance:e-n};if(e===o)return s+1<t.segments.length?{segmentIndex:s+1,segmentDistance:0}:{segmentIndex:s,segmentDistance:i.length};n+=i.length}return null}function ne(t,e,n,s){const o=_(t,e,n)+s;return k(t,o)}function G(t,e,n,s){const i=M(s),o=n.length+1,c=new Array(o);c[o-1]={lineId:t,absoluteOffset:e,position:A(s,e)};let r=e;for(let u=o-2;u>=0;u--)r=Math.min(r+n[u],i),c[u]={lineId:t,absoluteOffset:r,position:A(s,r)};return c}function Q(t,e){return{...t,state:"idle"}}function R(t){return{vehicle:t,execution:null}}function se(t,e){const n=[],s=new Map;for(const i of t){if(!e.get(i.lineId))continue;const c=Q(i);n.push(c);const r=R(c);s.set(i.id,r)}return{movingVehicles:n,stateMap:s}}function y(t,e){return{position:A(t,e),lineId:t.id,absoluteOffset:e}}function S(t,e){const n=$(t.arcLengthTable,e);return{position:w(t.bezier,n)}}function H(t,e,n,s,i,o,c){const r=n.segments[e.currentSegmentIndex],u=e.segmentDistance+s;if(u>=r.length){const a=u-r.length,g=e.currentSegmentIndex+1;if(g>=n.segments.length){if(c!==void 0&&r.type==="line"){const f=i.get(r.lineId),v=r.startOffset+u;if(v<=c){const O=y(f,v);return{axleState:{...t,...O},execution:{...e,segmentDistance:u},completed:!1}}const I=y(f,c);return{axleState:{...t,...I},execution:{...e,segmentDistance:c-r.startOffset},completed:!0}}const p=r.type==="line"?y(i.get(r.lineId),r.endOffset):S(o.get(r.curveIndex),r.length);return{axleState:{...t,...p},execution:{...e,segmentDistance:r.length},completed:!0}}const d=n.segments[g],h=d.type==="line"?y(i.get(d.lineId),d.startOffset+a):S(o.get(d.curveIndex),a);return{axleState:{...t,...h},execution:{currentSegmentIndex:g,segmentDistance:a},completed:!1}}const l=r.type==="line"?y(i.get(r.lineId),r.startOffset+u):S(o.get(r.curveIndex),u);return{axleState:{...t,...l},execution:{...e,segmentDistance:u},completed:!1}}function ie(t,e,n,s){const i=new Map;for(const o of t.segments)if(o.type==="curve"&&o.curveIndex!==void 0){const c=e[o.curveIndex];if(c){const r=n.get(c.fromLineId),u=n.get(c.toLineId);if(r&&u){const l=z(r,c.fromOffset,c.fromIsPercentage,1,s.maxWheelbase),a=W(u,c.toOffset,c.toIsPercentage,0,s.maxWheelbase),g=V(r,u,s,!1,{fromOffset:l,fromIsPercentage:!1,toOffset:a,toIsPercentage:!1}),d=N(g);i.set(o.curveIndex,{bezier:g,arcLengthTable:d})}}}return i}function J(t,e,n){const{graph:s,linesMap:i,curves:o,config:c}=n,r=i.get(e.targetLineId);if(!r)return null;const u=t.axleSpacings.reduce((f,v)=>f+v,0),a=M(r)-u;if(a<=0)return null;const g=e.isPercentage?e.targetOffset*a:Math.min(e.targetOffset,a),d=t.axles[t.axles.length-1],h=K(s,{lineId:d.lineId,offset:d.absoluteOffset},e.targetLineId,g,!1);if(!h)return null;const p=ie(h,o,i,c);return{path:h,curveDataMap:p}}function re(t,e){const n=t.execution,i=e.vehicleQueues.get(t.vehicle.id)?.[n.currentCommandIndex];return i&&e.onCommandComplete&&e.onCommandComplete({vehicleId:t.vehicle.id,command:i,finalPosition:{lineId:t.vehicle.axles[t.vehicle.axles.length-1].lineId,absoluteOffset:t.vehicle.axles[t.vehicle.axles.length-1].absoluteOffset,position:t.vehicle.axles[t.vehicle.axles.length-1].position},payload:i.payload}),{handled:!0,vehicle:{...t.vehicle,state:"waiting"},newExecution:n,isWaiting:!0}}function U(t,e,n,s,i,o){let c;const r=e[0];if(r.currentSegmentIndex<n.segments.length){const l=n.segments[r.currentSegmentIndex];if(l.type==="line"){const a=i.get(l.lineId);a&&(c=M(a))}}const u=t.map((l,a)=>{const g=a===0?c:void 0;return H(l,e[a],n,s,i,o,g)});return{axles:u.map(l=>l.axleState),axleExecutions:u.map(l=>l.execution),arrived:u[u.length-1].completed}}class oe{graph=null;linesMap=new Map;curves=[];config;constructor(e){this.config={maxWheelbase:e.maxWheelbase,tangentMode:e.tangentMode}}get movementConfig(){return this.config}get lines(){return Array.from(this.linesMap.values())}getCurves(){return this.curves}setScene(e,n){this.linesMap.clear();for(const s of e)this.linesMap.set(s.id,s);this.curves=n,this.graph=x(e,n,this.config)}addLine(e){return this.linesMap.has(e.id)?!1:(this.linesMap.set(e.id,e),this.graph=x(Array.from(this.linesMap.values()),this.curves,this.config),!0)}updateLine(e,n){const s=this.linesMap.get(e);return s?(n.start&&(s.start=n.start),n.end&&(s.end=n.end),this.graph=x(Array.from(this.linesMap.values()),this.curves,this.config),!0):!1}updateLineEndpoint(e,n,s){return this.updateLine(e,{[n]:s})}renameLine(e,n){const s=n.trim();if(!s)return{success:!1,error:"Name cannot be empty"};if(s===e)return{success:!0};if(this.linesMap.has(s))return{success:!1,error:`"${s}" already exists`};const i=this.linesMap.get(e);if(!i)return{success:!1,error:`Line "${e}" not found`};i.id=s,this.linesMap.delete(e),this.linesMap.set(s,i);for(const o of this.curves)o.fromLineId===e&&(o.fromLineId=s),o.toLineId===e&&(o.toLineId=s);return this.graph=x(Array.from(this.linesMap.values()),this.curves,this.config),{success:!0}}removeLine(e){return this.linesMap.has(e)?(this.linesMap.delete(e),this.curves=this.curves.filter(n=>n.fromLineId!==e&&n.toLineId!==e),this.graph=x(Array.from(this.linesMap.values()),this.curves,this.config),!0):!1}addCurve(e){this.curves.push(e),this.graph=x(Array.from(this.linesMap.values()),this.curves,this.config)}updateCurve(e,n){return e<0||e>=this.curves.length?!1:(this.curves[e]={...this.curves[e],...n},this.graph=x(Array.from(this.linesMap.values()),this.curves,this.config),!0)}removeCurve(e){return e<0||e>=this.curves.length?!1:(this.curves.splice(e,1),this.graph=x(Array.from(this.linesMap.values()),this.curves,this.config),!0)}initializeVehicle(e,n,s){const i=this.linesMap.get(e);if(!i)return null;const{axleSpacings:o}=s;if(o.length===0)throw new Error("initializeVehicle: axleSpacings must have at least one entry (vehicle needs ≥2 axles)");const c=o.reduce((a,g)=>a+g,0),r=M(i),u=Math.min(n,r-c);return{axles:G(e,u,o,i).map(a=>({lineId:a.lineId,offset:a.absoluteOffset,position:a.position})),axleSpacings:o}}preparePath(e,n,s,i=!1){if(!this.graph)return null;const o=e.axleSpacings.reduce((h,p)=>h+p,0),c=e.axles[e.axles.length-1],r={lineId:c.lineId,offset:c.offset,axles:e.axles.map(h=>({lineId:h.lineId,position:h.position,absoluteOffset:h.offset})),axleSpacings:e.axleSpacings},u=J(r,{targetLineId:n,targetOffset:s,isPercentage:i},{graph:this.graph,linesMap:this.linesMap,curves:this.curves,config:this.config});if(!u)return null;let l=s;const a=this.linesMap.get(n);if(a){const h=Math.max(0,M(a)-o);l=i?s*h:Math.min(s,h)}let g=0;const d=[{segmentIndex:0,segmentDistance:o}];for(let h=0;h<e.axleSpacings.length;h++)g+=e.axleSpacings[h],d.push({segmentIndex:0,segmentDistance:o-g});return{path:u.path,curveDataMap:u.curveDataMap,axleExecutions:d,targetLineId:n,targetOffset:l}}moveVehicle(e,n,s){const i=e.axles.map(r=>({lineId:r.lineId,position:r.position,absoluteOffset:r.offset})),o=n.axleExecutions.map(r=>({currentSegmentIndex:r.segmentIndex,segmentDistance:r.segmentDistance})),c=U(i,o,n.path,s,this.linesMap,n.curveDataMap);return{state:{axles:c.axles.map(r=>({lineId:r.lineId,offset:r.absoluteOffset,position:r.position})),axleSpacings:e.axleSpacings},execution:{...n,axleExecutions:c.axleExecutions.map(r=>({segmentIndex:r.currentSegmentIndex,segmentDistance:r.segmentDistance}))},arrived:c.arrived}}}exports.PathEngine=oe;exports.arcLengthToSegmentPosition=k;exports.buildArcLengthTable=N;exports.buildGraph=x;exports.calculateBezierArcLength=j;exports.calculateFrontAxlePosition=ne;exports.calculateInitialAxlePositions=G;exports.calculatePositionOnCurve=S;exports.calculatePositionOnLine=y;exports.calculateTangentLength=q;exports.createBezierCurve=V;exports.createInitialMovementState=R;exports.distance=L;exports.distanceToT=$;exports.findPath=K;exports.getArcLength=te;exports.getCumulativeArcLength=_;exports.getLineLength=M;exports.getPointOnBezier=w;exports.getPointOnLine=F;exports.getPointOnLineByOffset=b;exports.getPositionFromOffset=A;exports.handleArrival=re;exports.initializeAllVehicles=se;exports.initializeMovingVehicle=Q;exports.isPointNearPoint=ee;exports.moveVehicle=U;exports.normalize=D;exports.prepareCommandPath=J;exports.resolveFromLineOffset=z;exports.resolveToLineOffset=W;exports.updateAxlePosition=H;
|