vehicle-path2 1.0.11 → 1.0.13

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/README.md CHANGED
@@ -91,7 +91,6 @@ sim.clearVehicles()
91
91
  sim.goto({ id: 'v1', lineId: 'line2' }) // default position = 1.0 (ujung)
92
92
  sim.goto({ id: 'v1', lineId: 'line2', position: 0.5 }) // 0.5 = tengah line
93
93
  sim.goto({ id: 'v1', lineId: 'line2', position: 150, isPercentage: false }) // absolute
94
- sim.goto({ id: 'v1', lineId: 'line2', position: 0.5, wait: true }) // berhenti di tujuan
95
94
  sim.goto({ id: 'v1', lineId: 'line2', payload: { orderId: '123' } }) // dengan payload
96
95
  sim.clearQueue('v1')
97
96
  ```
@@ -128,6 +128,26 @@ export declare function updateAxlePosition(axleState: AxleState, axleExecution:
128
128
  execution: AxleExecutionState;
129
129
  completed: boolean;
130
130
  };
131
+ export interface MoveVehicleInput {
132
+ rear: AxleState;
133
+ front: AxleState;
134
+ rearExecution: AxleExecutionState;
135
+ frontExecution: AxleExecutionState;
136
+ }
137
+ export interface MoveVehicleResult {
138
+ rear: AxleState;
139
+ front: AxleState;
140
+ rearExecution: AxleExecutionState;
141
+ frontExecution: AxleExecutionState;
142
+ arrived: boolean;
143
+ }
144
+ /**
145
+ * Move a dual-axle vehicle along a path by a given distance.
146
+ *
147
+ * Coordinates rear and front axle updates, computes front maxOffset,
148
+ * detects arrival at target, and clamps both axles to preserve wheelbase.
149
+ */
150
+ export declare function moveVehicle(input: MoveVehicleInput, path: PathResult, distance: number, linesMap: Map<string, Line>, curveDataMap: Map<number, CurveData>, targetLineId: string, targetOffset: number, wheelbase: number): MoveVehicleResult;
131
151
  export interface PreparedPath {
132
152
  path: PathResult;
133
153
  curveDataMap: Map<number, CurveData>;
@@ -12,9 +12,9 @@
12
12
  */
13
13
  export type { Point, Line, BezierCurve, Curve } from './types/geometry';
14
14
  export type { VehicleState, VehicleStart, Vehicle, AxleState, GotoCommand, GotoCompletionInfo, GotoCompletionCallback } from './types/vehicle';
15
- export type { CurveData, PathExecutionState, VehicleMovementState, MovementConfig, SceneContext } from './types/movement';
15
+ export type { CurveData, PathExecutionState, AxleExecutionState, VehicleMovementState, MovementConfig, SceneContext } from './types/movement';
16
16
  export type { TangentMode } from './types/config';
17
17
  export type { CoordinateInput, SceneLineInput, SceneConnectionInput, SceneConfig, VehicleInput, VehicleUpdateInput, ConnectionUpdateInput, GotoCommandInput } from './types/api';
18
18
  export { buildGraph, findPath, calculateBezierArcLength, resolveFromLineOffset, resolveToLineOffset, type Graph, type GraphEdge, type PathSegment, type PathResult, type VehiclePosition } from './algorithms/pathFinding';
19
- export { initializeMovingVehicle, createInitialMovementState, initializeAllVehicles, calculateInitialFrontPosition, type InitializationResult, updateAxlePosition, calculatePositionOnLine, calculatePositionOnCurve, calculateFrontAxlePosition, getCumulativeArcLength, arcLengthToSegmentPosition, prepareCommandPath, type PreparedPath, handleArrival, type SegmentCompletionContext, type SegmentCompletionResult, type SegmentVehicleState, getPositionFromOffset, getLineLength } from './algorithms/vehicleMovement';
19
+ export { initializeMovingVehicle, createInitialMovementState, initializeAllVehicles, calculateInitialFrontPosition, type InitializationResult, updateAxlePosition, moveVehicle, type MoveVehicleInput, type MoveVehicleResult, calculatePositionOnLine, calculatePositionOnCurve, calculateFrontAxlePosition, getCumulativeArcLength, arcLengthToSegmentPosition, prepareCommandPath, type PreparedPath, handleArrival, type SegmentCompletionContext, type SegmentCompletionResult, type SegmentVehicleState, getPositionFromOffset, getLineLength } from './algorithms/vehicleMovement';
20
20
  export { distance, normalize, getPointOnLine, getPointOnLineByOffset, getPointOnBezier, createBezierCurve, buildArcLengthTable, distanceToT, getArcLength, calculateTangentLength, isPointNearPoint, type ArcLengthEntry, type CurveOffsetOptions } from './algorithms/math';
@@ -106,7 +106,6 @@ export interface ConnectionUpdateInput {
106
106
  * goto({ id: 'v1', lineId: 'line002' }) // position defaults to 1.0 (end)
107
107
  * goto({ id: 'v1', lineId: 'line002', position: 0.5 }) // 50% of line
108
108
  * goto({ id: 'v1', lineId: 'line002', position: 150, isPercentage: false }) // absolute 150
109
- * goto({ id: 'v1', lineId: 'line002', position: 0.5, wait: true }) // wait at destination
110
109
  * goto({ id: 'v1', lineId: 'line002', payload: { orderId: '123' } }) // with payload
111
110
  */
112
111
  export interface GotoInput {
@@ -114,7 +113,6 @@ export interface GotoInput {
114
113
  lineId: string;
115
114
  position?: number;
116
115
  isPercentage?: boolean;
117
- wait?: boolean;
118
116
  payload?: unknown;
119
117
  }
120
118
  /**
@@ -126,7 +124,6 @@ export interface GotoInput {
126
124
  * queueMovement('v1', {
127
125
  * targetLineId: 'line002',
128
126
  * targetPosition: 0.5,
129
- * wait: true,
130
127
  * payload: { orderId: '123' }
131
128
  * })
132
129
  * queueMovement('v1', { targetLineId: 'line002', targetPosition: 150, isPercentage: false })
@@ -135,7 +132,6 @@ export interface GotoCommandInput {
135
132
  targetLineId: string;
136
133
  targetPosition?: number;
137
134
  isPercentage?: boolean;
138
- wait?: boolean;
139
135
  payload?: unknown;
140
136
  }
141
137
  /**
@@ -151,7 +147,6 @@ export interface MovementCommandInput {
151
147
  targetLineId: string;
152
148
  targetPosition?: number;
153
149
  isPercentage?: boolean;
154
- wait?: boolean;
155
150
  payload?: unknown;
156
151
  }
157
152
  /**
@@ -43,7 +43,6 @@ export interface GotoCommand {
43
43
  targetLineId: string;
44
44
  targetOffset: number;
45
45
  isPercentage: boolean;
46
- awaitConfirmation?: boolean;
47
46
  payload?: unknown;
48
47
  }
49
48
  /**
package/dist/core.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function I(e,t){const s=t.x-e.x,n=t.y-e.y;return Math.sqrt(s*s+n*n)}function P(e,t){const s=t.x-e.x,n=t.y-e.y,o=Math.sqrt(s*s+n*n);return o===0?{x:0,y:0}:{x:s/o,y:n/o}}function q(e,t){return t*(e==="proportional-40"?.4:.5522)}function T(e,t,s,n=!1,o){const{wheelbase:c,tangentMode:i}=s;let r;o?.fromOffset!==void 0?r=S(e,o.fromOffset,o.fromIsPercentage??!1):r=e.end;let u;o?.toOffset!==void 0?u=S(t,o.toOffset,o.toIsPercentage??!1):u=t.start;const d=P(e.start,e.end),f=n?{x:r.x-d.x*c,y:r.y-d.y*c}:r,l=P(e.start,e.end),g=P(t.start,t.end),p=I(f,u),m=q(i,p),a=n?{x:f.x-l.x*m,y:f.y-l.y*m}:{x:f.x+l.x*m,y:f.y+l.y*m},v={x:u.x-g.x*m,y:u.y-g.y*m};return{p0:f,p1:a,p2:v,p3:u}}function F(e,t){return{x:e.start.x+(e.end.x-e.start.x)*t,y:e.start.y+(e.end.y-e.start.y)*t}}function S(e,t,s){const n=I(e.start,e.end);let o;return s?o=t:o=n>0?t/n:0,o=Math.max(0,Math.min(1,o)),F(e,o)}function w(e,t){const{p0:s,p1:n,p2:o,p3:c}=e,i=1-t,r=i*i,u=r*i,d=t*t,f=d*t;return{x:u*s.x+3*r*t*n.x+3*i*d*o.x+f*c.x,y:u*s.y+3*r*t*n.y+3*i*d*o.y+f*c.y}}function U(e,t,s=10){return I(e,t)<=s}function j(e,t=100){const s=[{t:0,distance:0}];let n=e.p0,o=0;for(let c=1;c<=t;c++){const i=c/t,r=w(e,i);o+=I(n,r),s.push({t:i,distance:o}),n=r}return s}function K(e,t){if(t<=0)return 0;const s=e[e.length-1].distance;if(t>=s)return 1;let n=0,o=e.length-1;for(;n<o-1;){const f=Math.floor((n+o)/2);e[f].distance<t?n=f:o=f}const c=e[n].distance,i=e[o].distance,r=e[n].t,u=e[o].t;if(i===c)return r;const d=(t-c)/(i-c);return r+d*(u-r)}function X(e){return e[e.length-1].distance}function N(e,t=100){let s=0,n=e.p0;for(let o=1;o<=t;o++){const c=o/t,i=w(e,c);s+=I(n,i),n=i}return s}function A(e,t,s,n,o){const c=I(e.start,e.end),i=c-o;if(i<=0)return c;let r;if(t===void 0)r=n;else if(s)r=t;else{const u=Math.max(0,Math.min(t,i));return o+u}return o+r*i}function b(e,t,s,n,o){const i=I(e.start,e.end)-o;if(i<=0)return 0;let r;if(t===void 0)r=n;else if(s)r=t;else return Math.max(0,Math.min(t,i));return r*i}function Y(e,t,s){const n=new Map,o=new Map,c=new Map;for(const i of e)o.set(i.id,i),c.set(i.id,I(i.start,i.end)),n.set(i.id,[]);for(let i=0;i<t.length;i++){const r=t[i],u=o.get(r.fromLineId),d=o.get(r.toLineId);if(!u||!d)continue;const f=A(u,r.fromOffset,r.fromIsPercentage,1,s.wheelbase),l=b(d,r.toOffset,r.toIsPercentage,0,s.wheelbase),g=T(u,d,s,!1,{fromOffset:f,fromIsPercentage:!1,toOffset:l,toIsPercentage:!1}),p=N(g),m={curveIndex:i,fromLineId:r.fromLineId,toLineId:r.toLineId,fromOffset:f,toOffset:l,curveLength:p};n.get(r.fromLineId).push(m)}return{adjacency:n,lines:o,lineLengths:c}}function B(e,t){return e.curveCount!==t.curveCount?e.curveCount-t.curveCount:e.totalDistance-t.totalDistance}function k(e,t,s,n,o=!1){const{adjacency:c,lines:i,lineLengths:r}=e;if(!i.get(s))return null;const d=r.get(s),f=o?n/100*d:n,l=[],g=new Map,p=(a,v)=>`${a}:${Math.round(v)}`;if(t.lineId===s&&f>=t.offset){const a=f-t.offset;return{segments:[{type:"line",lineId:t.lineId,startOffset:t.offset,endOffset:f,length:a}],totalDistance:a,curveCount:0}}const m=c.get(t.lineId)||[];for(const a of m){if(a.fromOffset<t.offset)continue;const v=a.fromOffset-t.offset,L=v+a.curveLength,O={type:"line",lineId:t.lineId,startOffset:t.offset,endOffset:a.fromOffset,length:v},h={type:"curve",curveIndex:a.curveIndex,startOffset:0,endOffset:a.curveLength,length:a.curveLength};l.push({lineId:a.toLineId,entryOffset:a.toOffset,totalDistance:L,curveCount:1,path:[O,h]})}for(l.sort(B);l.length>0;){const a=l.shift(),v=p(a.lineId,a.entryOffset),L=g.get(v);if(L!==void 0&&(L.curveCount<a.curveCount||L.curveCount===a.curveCount&&L.distance<=a.totalDistance))continue;if(g.set(v,{curveCount:a.curveCount,distance:a.totalDistance}),a.lineId===s){const h=Math.abs(f-a.entryOffset);if(f>=a.entryOffset){const x={type:"line",lineId:s,startOffset:a.entryOffset,endOffset:f,length:h};return{segments:[...a.path,x],totalDistance:a.totalDistance+h,curveCount:a.curveCount}}}const O=c.get(a.lineId)||[];for(const h of O){if(h.fromOffset<a.entryOffset)continue;const x=h.fromOffset-a.entryOffset,V=a.totalDistance+x+h.curveLength,D=a.curveCount+1,E=p(h.toLineId,h.toOffset),C=g.get(E);if(C!==void 0&&(C.curveCount<D||C.curveCount===D&&C.distance<=V))continue;const H={type:"line",lineId:a.lineId,startOffset:a.entryOffset,endOffset:h.fromOffset,length:x},J={type:"curve",curveIndex:h.curveIndex,startOffset:0,endOffset:h.curveLength,length:h.curveLength};l.push({lineId:h.toLineId,entryOffset:h.toOffset,totalDistance:V,curveCount:D,path:[...a.path,H,J]})}l.sort(B)}return null}function z(e,t){const s=Math.sqrt(Math.pow(e.end.x-e.start.x,2)+Math.pow(e.end.y-e.start.y,2)),n=s>0?t/s:0;return{x:e.start.x+(e.end.x-e.start.x)*Math.min(1,Math.max(0,n)),y:e.start.y+(e.end.y-e.start.y)*Math.min(1,Math.max(0,n))}}function G(e){return Math.sqrt(Math.pow(e.end.x-e.start.x,2)+Math.pow(e.end.y-e.start.y,2))}function $(e,t,s){let n=0;for(let o=0;o<t;o++)n+=e.segments[o].length;return n+=s,n}function Q(e,t){let s=0;for(let n=0;n<e.segments.length;n++){const o=e.segments[n],c=s+o.length;if(t<c)return{segmentIndex:n,segmentDistance:t-s};if(t===c)return n+1<e.segments.length?{segmentIndex:n+1,segmentDistance:0}:{segmentIndex:n,segmentDistance:o.length};s+=o.length}return null}function R(e,t,s,n){const c=$(e,t,s)+n;return Q(e,c)}function Z(e,t,s,n){const o=Math.sqrt(Math.pow(n.end.x-n.start.x,2)+Math.pow(n.end.y-n.start.y,2));let c=t+s;c=Math.min(c,o);const i=z(n,c);return{lineId:e,position:i,absoluteOffset:c}}function W(e,t){return{...e,state:"idle"}}function _(e){return{vehicle:e,execution:null}}function ee(e,t){const s=[],n=new Map;for(const o of e){if(!t.get(o.lineId))continue;const i=W(o);s.push(i);const r=_(i);n.set(o.id,r)}return{movingVehicles:s,stateMap:n}}function y(e,t){return{position:z(e,t),lineId:e.id,absoluteOffset:t}}function M(e,t){const s=K(e.arcLengthTable,t);return{position:w(e.bezier,s)}}function te(e,t,s,n,o,c,i){const r=s.segments[t.currentSegmentIndex],u=t.segmentDistance+n;if(u>=r.length){const f=u-r.length,l=t.currentSegmentIndex+1;if(l>=s.segments.length){if(i!==void 0&&r.type==="line"){const a=o.get(r.lineId),v=r.startOffset+u;if(v<=i){const O=y(a,v);return{axleState:{...e,...O},execution:{...t,segmentDistance:u},completed:!1}}const L=y(a,i);return{axleState:{...e,...L},execution:{...t,segmentDistance:i-r.startOffset},completed:!0}}const m=r.type==="line"?y(o.get(r.lineId),r.endOffset):M(c.get(r.curveIndex),r.length);return{axleState:{...e,...m},execution:{...t,segmentDistance:r.length},completed:!0}}const g=s.segments[l],p=g.type==="line"?y(o.get(g.lineId),g.startOffset+f):M(c.get(g.curveIndex),f);return{axleState:{...e,...p},execution:{currentSegmentIndex:l,segmentDistance:f},completed:!1}}const d=r.type==="line"?y(o.get(r.lineId),r.startOffset+u):M(c.get(r.curveIndex),u);return{axleState:{...e,...d},execution:{...t,segmentDistance:u},completed:!1}}function ne(e,t,s,n){const o=new Map;for(const c of e.segments)if(c.type==="curve"&&c.curveIndex!==void 0){const i=t[c.curveIndex];if(i){const r=s.get(i.fromLineId),u=s.get(i.toLineId);if(r&&u){const d=A(r,i.fromOffset,i.fromIsPercentage,1,n.wheelbase),f=b(u,i.toOffset,i.toIsPercentage,0,n.wheelbase),l=T(r,u,n,!1,{fromOffset:d,fromIsPercentage:!1,toOffset:f,toIsPercentage:!1}),g=j(l);o.set(c.curveIndex,{bezier:l,arcLengthTable:g})}}}return o}function oe(e,t,s){const{graph:n,linesMap:o,curves:c,config:i}=s,r=o.get(t.targetLineId);if(!r)return null;const d=G(r)-i.wheelbase;if(d<=0)return null;const f=t.isPercentage?t.targetOffset*d:Math.min(t.targetOffset,d),l=k(n,{lineId:e.rear.lineId,offset:e.rear.absoluteOffset},t.targetLineId,f,!1);if(!l)return null;const g=ne(l,c,o,i);return{path:l,curveDataMap:g}}function se(e,t){const s=e.execution,n=t.vehicleQueues.get(e.vehicle.id),o=n?.[s.currentCommandIndex];if(o&&t.onCommandComplete&&t.onCommandComplete({vehicleId:e.vehicle.id,command:o,finalPosition:{lineId:e.vehicle.rear.lineId,absoluteOffset:e.vehicle.rear.absoluteOffset,position:e.vehicle.rear.position},payload:o.payload}),o?.awaitConfirmation)return{handled:!0,vehicle:{...e.vehicle,state:"waiting"},newExecution:s,isWaiting:!0};const c=s.currentCommandIndex+1;if(n&&c<n.length){const r=n[c],u=t.graphRef.current;if(u){const d={graph:u,linesMap:t.linesMap,curves:t.curves,config:t.config},f=t.prepareCommandPath(e.vehicle,r,d);if(f){const l=R(f.path,0,0,t.config.wheelbase);t.onCommandStart&&t.onCommandStart({vehicleId:e.vehicle.id,command:r,commandIndex:c,startPosition:{lineId:e.vehicle.rear.lineId,absoluteOffset:e.vehicle.rear.absoluteOffset,position:e.vehicle.rear.position}});const g={path:f.path,curveDataMap:f.curveDataMap,currentCommandIndex:c,rear:{currentSegmentIndex:0,segmentDistance:0},front:l?{currentSegmentIndex:l.segmentIndex,segmentDistance:l.segmentDistance}:{currentSegmentIndex:0,segmentDistance:0}};return{handled:!0,vehicle:{...e.vehicle,state:"moving"},newExecution:g}}}}return{handled:!0,vehicle:{...e.vehicle,state:"idle"},newExecution:null}}exports.arcLengthToSegmentPosition=Q;exports.buildArcLengthTable=j;exports.buildGraph=Y;exports.calculateBezierArcLength=N;exports.calculateFrontAxlePosition=R;exports.calculateInitialFrontPosition=Z;exports.calculatePositionOnCurve=M;exports.calculatePositionOnLine=y;exports.calculateTangentLength=q;exports.createBezierCurve=T;exports.createInitialMovementState=_;exports.distance=I;exports.distanceToT=K;exports.findPath=k;exports.getArcLength=X;exports.getCumulativeArcLength=$;exports.getLineLength=G;exports.getPointOnBezier=w;exports.getPointOnLine=F;exports.getPointOnLineByOffset=S;exports.getPositionFromOffset=z;exports.handleArrival=se;exports.initializeAllVehicles=ee;exports.initializeMovingVehicle=W;exports.isPointNearPoint=U;exports.normalize=P;exports.prepareCommandPath=oe;exports.resolveFromLineOffset=A;exports.resolveToLineOffset=b;exports.updateAxlePosition=te;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function I(e,t){const r=t.x-e.x,n=t.y-e.y;return Math.sqrt(r*r+n*n)}function C(e,t){const r=t.x-e.x,n=t.y-e.y,o=Math.sqrt(r*r+n*n);return o===0?{x:0,y:0}:{x:r/o,y:n/o}}function B(e,t){return t*(e==="proportional-40"?.4:.5522)}function A(e,t,r,n=!1,o){const{wheelbase:c,tangentMode:s}=r;let i;o?.fromOffset!==void 0?i=T(e,o.fromOffset,o.fromIsPercentage??!1):i=e.end;let f;o?.toOffset!==void 0?f=T(t,o.toOffset,o.toIsPercentage??!1):f=t.start;const l=C(e.start,e.end),u=n?{x:i.x-l.x*c,y:i.y-l.y*c}:i,g=C(e.start,e.end),d=C(t.start,t.end),x=I(u,f),h=B(s,x),a=n?{x:u.x-g.x*h,y:u.y-g.y*h}:{x:u.x+g.x*h,y:u.y+g.y*h},v={x:f.x-d.x*h,y:f.y-d.y*h};return{p0:u,p1:a,p2:v,p3:f}}function j(e,t){return{x:e.start.x+(e.end.x-e.start.x)*t,y:e.start.y+(e.end.y-e.start.y)*t}}function T(e,t,r){const n=I(e.start,e.end);let o;return r?o=t:o=n>0?t/n:0,o=Math.max(0,Math.min(1,o)),j(e,o)}function M(e,t){const{p0:r,p1:n,p2:o,p3:c}=e,s=1-t,i=s*s,f=i*s,l=t*t,u=l*t;return{x:f*r.x+3*i*t*n.x+3*s*l*o.x+u*c.x,y:f*r.y+3*i*t*n.y+3*s*l*o.y+u*c.y}}function U(e,t,r=10){return I(e,t)<=r}function k(e,t=100){const r=[{t:0,distance:0}];let n=e.p0,o=0;for(let c=1;c<=t;c++){const s=c/t,i=M(e,s);o+=I(n,i),r.push({t:s,distance:o}),n=i}return r}function K(e,t){if(t<=0)return 0;const r=e[e.length-1].distance;if(t>=r)return 1;let n=0,o=e.length-1;for(;n<o-1;){const u=Math.floor((n+o)/2);e[u].distance<t?n=u:o=u}const c=e[n].distance,s=e[o].distance,i=e[n].t,f=e[o].t;if(s===c)return i;const l=(t-c)/(s-c);return i+l*(f-i)}function X(e){return e[e.length-1].distance}function N(e,t=100){let r=0,n=e.p0;for(let o=1;o<=t;o++){const c=o/t,s=M(e,c);r+=I(n,s),n=s}return r}function b(e,t,r,n,o){const c=I(e.start,e.end),s=c-o;if(s<=0)return c;let i;if(t===void 0)i=n;else if(r)i=t;else{const f=Math.max(0,Math.min(t,s));return o+f}return o+i*s}function z(e,t,r,n,o){const s=I(e.start,e.end)-o;if(s<=0)return 0;let i;if(t===void 0)i=n;else if(r)i=t;else return Math.max(0,Math.min(t,s));return i*s}function Y(e,t,r){const n=new Map,o=new Map,c=new Map;for(const s of e)o.set(s.id,s),c.set(s.id,I(s.start,s.end)),n.set(s.id,[]);for(let s=0;s<t.length;s++){const i=t[s],f=o.get(i.fromLineId),l=o.get(i.toLineId);if(!f||!l)continue;const u=b(f,i.fromOffset,i.fromIsPercentage,1,r.wheelbase),g=z(l,i.toOffset,i.toIsPercentage,0,r.wheelbase),d=A(f,l,r,!1,{fromOffset:u,fromIsPercentage:!1,toOffset:g,toIsPercentage:!1}),x=N(d),h={curveIndex:s,fromLineId:i.fromLineId,toLineId:i.toLineId,fromOffset:u,toOffset:g,curveLength:x};n.get(i.fromLineId).push(h)}return{adjacency:n,lines:o,lineLengths:c}}function q(e,t){return e.curveCount!==t.curveCount?e.curveCount-t.curveCount:e.totalDistance-t.totalDistance}function R(e,t,r,n,o=!1){const{adjacency:c,lines:s,lineLengths:i}=e;if(!s.get(r))return null;const l=i.get(r),u=o?n/100*l:n,g=[],d=new Map,x=(a,v)=>`${a}:${Math.round(v)}`;if(t.lineId===r&&u>=t.offset){const a=u-t.offset;return{segments:[{type:"line",lineId:t.lineId,startOffset:t.offset,endOffset:u,length:a}],totalDistance:a,curveCount:0}}const h=c.get(t.lineId)||[];for(const a of h){if(a.fromOffset<t.offset)continue;const v=a.fromOffset-t.offset,L=v+a.curveLength,p={type:"line",lineId:t.lineId,startOffset:t.offset,endOffset:a.fromOffset,length:v},m={type:"curve",curveIndex:a.curveIndex,startOffset:0,endOffset:a.curveLength,length:a.curveLength};g.push({lineId:a.toLineId,entryOffset:a.toOffset,totalDistance:L,curveCount:1,path:[p,m]})}for(g.sort(q);g.length>0;){const a=g.shift(),v=x(a.lineId,a.entryOffset),L=d.get(v);if(L!==void 0&&(L.curveCount<a.curveCount||L.curveCount===a.curveCount&&L.distance<=a.totalDistance))continue;if(d.set(v,{curveCount:a.curveCount,distance:a.totalDistance}),a.lineId===r){const m=Math.abs(u-a.entryOffset);if(u>=a.entryOffset){const O={type:"line",lineId:r,startOffset:a.entryOffset,endOffset:u,length:m};return{segments:[...a.path,O],totalDistance:a.totalDistance+m,curveCount:a.curveCount}}}const p=c.get(a.lineId)||[];for(const m of p){if(m.fromOffset<a.entryOffset)continue;const O=m.fromOffset-a.entryOffset,F=a.totalDistance+O+m.curveLength,S=a.curveCount+1,_=x(m.toLineId,m.toOffset),P=d.get(_);if(P!==void 0&&(P.curveCount<S||P.curveCount===S&&P.distance<=F))continue;const H={type:"line",lineId:a.lineId,startOffset:a.entryOffset,endOffset:m.fromOffset,length:O},J={type:"curve",curveIndex:m.curveIndex,startOffset:0,endOffset:m.curveLength,length:m.curveLength};g.push({lineId:m.toLineId,entryOffset:m.toOffset,totalDistance:F,curveCount:S,path:[...a.path,H,J]})}g.sort(q)}return null}function E(e,t){const r=Math.sqrt(Math.pow(e.end.x-e.start.x,2)+Math.pow(e.end.y-e.start.y,2)),n=r>0?t/r:0;return{x:e.start.x+(e.end.x-e.start.x)*Math.min(1,Math.max(0,n)),y:e.start.y+(e.end.y-e.start.y)*Math.min(1,Math.max(0,n))}}function V(e){return Math.sqrt(Math.pow(e.end.x-e.start.x,2)+Math.pow(e.end.y-e.start.y,2))}function G(e,t,r){let n=0;for(let o=0;o<t;o++)n+=e.segments[o].length;return n+=r,n}function $(e,t){let r=0;for(let n=0;n<e.segments.length;n++){const o=e.segments[n],c=r+o.length;if(t<c)return{segmentIndex:n,segmentDistance:t-r};if(t===c)return n+1<e.segments.length?{segmentIndex:n+1,segmentDistance:0}:{segmentIndex:n,segmentDistance:o.length};r+=o.length}return null}function Z(e,t,r,n){const c=G(e,t,r)+n;return $(e,c)}function ee(e,t,r,n){const o=Math.sqrt(Math.pow(n.end.x-n.start.x,2)+Math.pow(n.end.y-n.start.y,2));let c=t+r;c=Math.min(c,o);const s=E(n,c);return{lineId:e,position:s,absoluteOffset:c}}function Q(e,t){return{...e,state:"idle"}}function W(e){return{vehicle:e,execution:null}}function te(e,t){const r=[],n=new Map;for(const o of e){if(!t.get(o.lineId))continue;const s=Q(o);r.push(s);const i=W(s);n.set(o.id,i)}return{movingVehicles:r,stateMap:n}}function y(e,t){return{position:E(e,t),lineId:e.id,absoluteOffset:t}}function w(e,t){const r=K(e.arcLengthTable,t);return{position:M(e.bezier,r)}}function D(e,t,r,n,o,c,s){let i=t.currentSegmentIndex,f=t.segmentDistance,l=n;for(;l>0;){const d=r.segments[i],x=d.length-f;if(l<x){f+=l,l=0;break}l-=x;const h=i+1;if(h>=r.segments.length){if(s!==void 0&&d.type==="line"){const v=d.startOffset+d.length+l;if(v<=s){const m=o.get(d.lineId),O=y(m,v);return{axleState:{...e,...O},execution:{currentSegmentIndex:i,segmentDistance:d.length+l},completed:!1}}const L=o.get(d.lineId),p=y(L,s);return{axleState:{...e,...p},execution:{currentSegmentIndex:i,segmentDistance:s-d.startOffset},completed:!0}}const a=d.type==="line"?y(o.get(d.lineId),d.endOffset):w(c.get(d.curveIndex),d.length);return{axleState:{...e,...a},execution:{currentSegmentIndex:i,segmentDistance:d.length},completed:!0}}i=h,f=0}const u=r.segments[i],g=u.type==="line"?y(o.get(u.lineId),u.startOffset+f):w(c.get(u.curveIndex),f);return{axleState:{...e,...g},execution:{currentSegmentIndex:i,segmentDistance:f},completed:!1}}function ne(e,t,r,n,o,c,s,i){const f=D(e.rear,e.rearExecution,t,r,n,o);let l;const u=e.frontExecution.currentSegmentIndex;if(u<t.segments.length){const h=t.segments[u];if(h.type==="line"){const a=n.get(h.lineId);a&&(l=V(a))}}const g=D(e.front,e.frontExecution,t,r,n,o,l),d=s-i;if(f.axleState.lineId===c&&f.axleState.absoluteOffset>=d-.001){const h=n.get(c),a=y(h,d),v=y(h,s);return{rear:{...f.axleState,...a},front:{...g.axleState,...v},rearExecution:f.execution,frontExecution:g.execution,arrived:!0}}return{rear:f.axleState,front:g.axleState,rearExecution:f.execution,frontExecution:g.execution,arrived:!1}}function oe(e,t,r,n){const o=new Map;for(const c of e.segments)if(c.type==="curve"&&c.curveIndex!==void 0){const s=t[c.curveIndex];if(s){const i=r.get(s.fromLineId),f=r.get(s.toLineId);if(i&&f){const l=b(i,s.fromOffset,s.fromIsPercentage,1,n.wheelbase),u=z(f,s.toOffset,s.toIsPercentage,0,n.wheelbase),g=A(i,f,n,!1,{fromOffset:l,fromIsPercentage:!1,toOffset:u,toIsPercentage:!1}),d=k(g);o.set(c.curveIndex,{bezier:g,arcLengthTable:d})}}}return o}function re(e,t,r){const{graph:n,linesMap:o,curves:c,config:s}=r,i=o.get(t.targetLineId);if(!i)return null;const l=V(i)-s.wheelbase;if(l<=0)return null;const u=t.isPercentage?t.targetOffset*l:Math.min(t.targetOffset,l),g=R(n,{lineId:e.rear.lineId,offset:e.rear.absoluteOffset},t.targetLineId,u,!1);if(!g)return null;const d=oe(g,c,o,s);return{path:g,curveDataMap:d}}function se(e,t){const r=e.execution,o=t.vehicleQueues.get(e.vehicle.id)?.[r.currentCommandIndex];return o&&t.onCommandComplete&&t.onCommandComplete({vehicleId:e.vehicle.id,command:o,finalPosition:{lineId:e.vehicle.rear.lineId,absoluteOffset:e.vehicle.rear.absoluteOffset,position:e.vehicle.rear.position},payload:o.payload}),{handled:!0,vehicle:{...e.vehicle,state:"waiting"},newExecution:r,isWaiting:!0}}exports.arcLengthToSegmentPosition=$;exports.buildArcLengthTable=k;exports.buildGraph=Y;exports.calculateBezierArcLength=N;exports.calculateFrontAxlePosition=Z;exports.calculateInitialFrontPosition=ee;exports.calculatePositionOnCurve=w;exports.calculatePositionOnLine=y;exports.calculateTangentLength=B;exports.createBezierCurve=A;exports.createInitialMovementState=W;exports.distance=I;exports.distanceToT=K;exports.findPath=R;exports.getArcLength=X;exports.getCumulativeArcLength=G;exports.getLineLength=V;exports.getPointOnBezier=M;exports.getPointOnLine=j;exports.getPointOnLineByOffset=T;exports.getPositionFromOffset=E;exports.handleArrival=se;exports.initializeAllVehicles=te;exports.initializeMovingVehicle=Q;exports.isPointNearPoint=U;exports.moveVehicle=ne;exports.normalize=C;exports.prepareCommandPath=re;exports.resolveFromLineOffset=b;exports.resolveToLineOffset=z;exports.updateAxlePosition=D;