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.
@@ -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, willFlip?: boolean, offsetOptions?: CurveOffsetOptions): BezierCurve;
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, _maxWheelbase: number): 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, _maxWheelbase: number): 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
  */
@@ -9,7 +9,7 @@
9
9
  * ```typescript
10
10
  * import { PathEngine } from 'vehicle-path/core'
11
11
  *
12
- * const engine = new PathEngine({ maxWheelbase: 100, tangentMode: 'proportional-40' })
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
  /**
@@ -40,7 +40,6 @@ export interface VehicleMovementState {
40
40
  * Configuration for vehicle movement
41
41
  */
42
42
  export interface MovementConfig {
43
- maxWheelbase: number;
44
43
  tangentMode: TangentMode;
45
44
  }
46
45
  /**
@@ -25,7 +25,7 @@ export interface VehicleStart {
25
25
  lineId: string;
26
26
  offset: number;
27
27
  isPercentage: boolean;
28
- /** Optional: defaults to [maxWheelbase] jika tidak disediakan */
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-C4FckUel.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;
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-C7pH7jZo.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-C7pH7jZo.js";
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 n = e.x - t.x, s = e.y - t.y;
3
- return Math.sqrt(n * n + s * s);
2
+ const s = e.x - t.x, n = e.y - t.y;
3
+ return Math.sqrt(s * s + n * n);
4
4
  }
5
- function S(t, e) {
6
- const n = e.x - t.x, s = e.y - t.y, i = Math.sqrt(n * n + s * s);
7
- return i === 0 ? { x: 0, y: 0 } : { x: n / i, y: s / i };
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 k(t, e) {
9
+ function F(t, e) {
10
10
  return e * (t === "proportional-40" ? 0.4 : 0.5522);
11
11
  }
12
- function W(t, e, n, s = !1, i) {
13
- const { maxWheelbase: o, tangentMode: a } = n;
14
- let r;
15
- i?.fromOffset !== void 0 ? r = V(t, i.fromOffset, i.fromIsPercentage ?? !1) : r = t.end;
16
- let f;
17
- i?.toOffset !== void 0 ? f = V(e, i.toOffset, i.toIsPercentage ?? !1) : f = e.start;
18
- const l = S(t.start, t.end), c = s ? {
19
- // Transition with flip: kurva dimulai dari P (baseP0 - wheelbase in line direction)
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 V(t, e, n) {
35
- const s = y(t.start, t.end);
27
+ function z(t, e, s) {
28
+ const n = y(t.start, t.end);
36
29
  let i;
37
- return n ? i = e : i = s > 0 ? e / s : 0, i = Math.max(0, Math.min(1, i)), K(t, i);
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 b(t, e) {
40
- const { p0: n, p1: s, p2: i, p3: o } = t, a = 1 - e, r = a * a, f = r * a, l = e * e, c = l * e;
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 * n.x + 3 * r * e * s.x + 3 * a * l * i.x + c * o.x,
43
- y: f * n.y + 3 * r * e * s.y + 3 * a * l * i.y + c * o.y
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, n = 10) {
47
- return y(t, e) <= n;
39
+ function ne(t, e, s = 10) {
40
+ return y(t, e) <= s;
48
41
  }
49
42
  function N(t, e = 100) {
50
- const n = [{ t: 0, distance: 0 }];
51
- let s = t.p0, i = 0;
52
- for (let o = 1; o <= e; o++) {
53
- const a = o / e, r = b(t, a);
54
- i += y(s, r), n.push({ t: a, distance: i }), s = r;
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 n;
49
+ return s;
57
50
  }
58
- function _(t, e) {
51
+ function G(t, e) {
59
52
  if (e <= 0) return 0;
60
- const n = t[t.length - 1].distance;
61
- if (e >= n) return 1;
62
- let s = 0, i = t.length - 1;
63
- for (; s < i - 1; ) {
64
- const c = Math.floor((s + i) / 2);
65
- t[c].distance < e ? s = c : i = c;
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 o = t[s].distance, a = t[i].distance, r = t[s].t, f = t[i].t;
68
- if (a === o) return r;
69
- const l = (e - o) / (a - o);
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 F(t, e = 100) {
76
- let n = 0, s = t.p0;
68
+ function Q(t, e = 100) {
69
+ let s = 0, n = t.p0;
77
70
  for (let i = 1; i <= e; i++) {
78
- const o = i / e, a = b(t, o);
79
- n += y(s, a), s = a;
71
+ const c = i / e, o = A(t, c);
72
+ s += y(n, o), n = o;
80
73
  }
81
- return n;
82
- }
83
- function q(t, e, n, s, i) {
84
- const o = y(t.start, t.end);
85
- return e === void 0 ? s * o : n ? Math.max(0, Math.min(e, 1)) * o : Math.max(0, Math.min(e, o));
86
- }
87
- function E(t, e, n, s, i) {
88
- const o = y(t.start, t.end);
89
- return e === void 0 ? s * o : n ? Math.max(0, Math.min(e, 1)) * o : Math.max(0, Math.min(e, o));
90
- }
91
- function I(t, e, n) {
92
- const s = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Map();
93
- for (const a of t)
94
- i.set(a.id, a), o.set(a.id, y(a.start, a.end)), s.set(a.id, []);
95
- for (let a = 0; a < e.length; a++) {
96
- const r = e[a], f = i.get(r.fromLineId), l = i.get(r.toLineId);
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 c = q(f, r.fromOffset, r.fromIsPercentage, 1, n.maxWheelbase), g = E(l, r.toOffset, r.toIsPercentage, 0, n.maxWheelbase), d = W(
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
- n,
102
- !1,
103
- // willFlip is always false now
94
+ s,
104
95
  {
105
- fromOffset: c,
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 = F(d), p = {
113
- curveIndex: a,
101
+ ), h = Q(d), v = {
102
+ curveIndex: o,
114
103
  fromLineId: r.fromLineId,
115
104
  toLineId: r.toLineId,
116
- fromOffset: c,
105
+ fromOffset: a,
117
106
  toOffset: g,
118
107
  curveLength: h
119
108
  };
120
- s.get(r.fromLineId).push(p);
109
+ n.get(r.fromLineId).push(v);
121
110
  }
122
- return { adjacency: s, lines: i, lineLengths: o };
111
+ return { adjacency: n, lines: i, lineLengths: c };
123
112
  }
124
- function z(t, e) {
113
+ function b(t, e) {
125
114
  return t.curveCount !== e.curveCount ? t.curveCount - e.curveCount : t.totalDistance - e.totalDistance;
126
115
  }
127
- function G(t, e, n, s, i = !1) {
128
- const { adjacency: o, lines: a, lineLengths: r } = t;
129
- if (!a.get(n)) return null;
130
- const l = r.get(n), c = i ? s / 100 * l : s, g = [], d = /* @__PURE__ */ new Map(), h = (u, v) => `${u}:${Math.round(v)}`;
131
- if (e.lineId === n && c >= e.offset) {
132
- const u = c - e.offset;
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: c,
127
+ endOffset: a,
139
128
  length: u
140
129
  }],
141
130
  totalDistance: u,
142
131
  curveCount: 0
143
132
  };
144
133
  }
145
- const p = o.get(e.lineId) || [];
146
- for (const u of p) {
134
+ const v = c.get(e.lineId) || [];
135
+ for (const u of v) {
147
136
  if (u.fromOffset < e.offset) continue;
148
- const v = u.fromOffset - e.offset, x = v + u.curveLength, L = {
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: v
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(z); g.length > 0; ) {
170
- const u = g.shift(), v = h(u.lineId, u.entryOffset), x = d.get(v);
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(v, { curveCount: u.curveCount, distance: u.totalDistance }), u.lineId === n) {
174
- const m = Math.abs(c - u.entryOffset);
175
- if (c >= u.entryOffset) {
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: n,
167
+ lineId: s,
179
168
  startOffset: u.entryOffset,
180
- endOffset: c,
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 = o.get(u.lineId) || [];
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, P = u.curveCount + 1, B = h(m.toLineId, m.toOffset), D = d.get(B);
194
- if (D !== void 0 && (D.curveCount < P || D.curveCount === P && D.distance <= T))
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 j = {
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: P,
214
- path: [...u.path, j, $]
202
+ curveCount: S,
203
+ path: [...u.path, $, k]
215
204
  });
216
205
  }
217
- g.sort(z);
206
+ g.sort(b);
218
207
  }
219
208
  return null;
220
209
  }
221
- function A(t, e) {
222
- const n = Math.sqrt(
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
- ), s = n > 0 ? e / n : 0;
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, s)),
227
- y: t.start.y + (t.end.y - t.start.y) * Math.min(1, Math.max(0, s))
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 Q(t, e, n) {
236
- let s = 0;
224
+ function W(t, e, s) {
225
+ let n = 0;
237
226
  for (let i = 0; i < e; i++)
238
- s += t.segments[i].length;
239
- return s += n, s;
227
+ n += t.segments[i].length;
228
+ return n += s, n;
240
229
  }
241
- function R(t, e) {
242
- let n = 0;
243
- for (let s = 0; s < t.segments.length; s++) {
244
- const i = t.segments[s], o = n + i.length;
245
- if (e < o)
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: s,
248
- segmentDistance: e - n
236
+ segmentIndex: n,
237
+ segmentDistance: e - s
249
238
  };
250
- if (e === o)
251
- return s + 1 < t.segments.length ? {
252
- segmentIndex: s + 1,
239
+ if (e === c)
240
+ return n + 1 < t.segments.length ? {
241
+ segmentIndex: n + 1,
253
242
  segmentDistance: 0
254
243
  } : {
255
- segmentIndex: s,
244
+ segmentIndex: n,
256
245
  segmentDistance: i.length
257
246
  };
258
- n += i.length;
247
+ s += i.length;
259
248
  }
260
249
  return null;
261
250
  }
262
- function ie(t, e, n, s) {
263
- const o = Q(
251
+ function ie(t, e, s, n) {
252
+ const c = W(
264
253
  t,
265
254
  e,
266
- n
267
- ) + s;
268
- return R(t, o);
255
+ s
256
+ ) + n;
257
+ return _(t, c);
269
258
  }
270
- function H(t, e, n, s) {
271
- const i = O(s), o = n.length + 1, a = new Array(o);
272
- a[o - 1] = {
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: A(s, e)
264
+ position: P(n, e)
276
265
  };
277
266
  let r = e;
278
- for (let f = o - 2; f >= 0; f--)
279
- r = Math.min(r + n[f], i), a[f] = {
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: A(s, r)
271
+ position: P(n, r)
283
272
  };
284
- return a;
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 n = [], s = /* @__PURE__ */ new Map();
288
+ const s = [], n = /* @__PURE__ */ new Map();
300
289
  for (const i of t) {
301
290
  if (!e.get(i.lineId)) continue;
302
- const a = J(i);
303
- n.push(a);
304
- const r = U(a);
305
- s.set(i.id, r);
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: n, stateMap: s };
296
+ return { movingVehicles: s, stateMap: n };
308
297
  }
309
298
  function M(t, e) {
310
- return { position: A(t, e), lineId: t.id, absoluteOffset: e };
299
+ return { position: P(t, e), lineId: t.id, absoluteOffset: e };
311
300
  }
312
301
  function w(t, e) {
313
- const n = _(t.arcLengthTable, e);
314
- return { position: b(t.bezier, n) };
302
+ const s = G(t.arcLengthTable, e);
303
+ return { position: A(t.bezier, s) };
315
304
  }
316
- function X(t, e, n, s, i, o, a) {
317
- const r = n.segments[e.currentSegmentIndex], f = e.segmentDistance + s;
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 c = f - r.length, g = e.currentSegmentIndex + 1;
320
- if (g >= n.segments.length) {
321
- if (a !== void 0 && r.type === "line") {
322
- const u = i.get(r.lineId), v = r.startOffset + f;
323
- if (v <= a) {
324
- const L = M(u, v);
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, a);
320
+ const x = M(u, o);
332
321
  return {
333
322
  axleState: { ...t, ...x },
334
- execution: { ...e, segmentDistance: a - r.startOffset },
323
+ execution: { ...e, segmentDistance: o - r.startOffset },
335
324
  completed: !0
336
325
  };
337
326
  }
338
- const p = r.type === "line" ? M(
327
+ const v = r.type === "line" ? M(
339
328
  i.get(r.lineId),
340
329
  r.endOffset
341
330
  ) : w(
342
- o.get(r.curveIndex),
331
+ c.get(r.curveIndex),
343
332
  r.length
344
333
  );
345
334
  return {
346
- axleState: { ...t, ...p },
335
+ axleState: { ...t, ...v },
347
336
  execution: { ...e, segmentDistance: r.length },
348
337
  completed: !0
349
338
  };
350
339
  }
351
- const d = n.segments[g], h = d.type === "line" ? M(
340
+ const d = s.segments[g], h = d.type === "line" ? M(
352
341
  i.get(d.lineId),
353
- d.startOffset + c
342
+ d.startOffset + a
354
343
  ) : w(
355
- o.get(d.curveIndex),
356
- c
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: c
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
- o.get(r.curveIndex),
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, n, s) {
369
+ function Y(t, e, s, n) {
381
370
  const i = /* @__PURE__ */ new Map();
382
- for (const o of t.segments)
383
- if (o.type === "curve" && o.curveIndex !== void 0) {
384
- const a = e[o.curveIndex];
385
- if (a) {
386
- const r = n.get(a.fromLineId), f = n.get(a.toLineId);
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 = q(
377
+ const l = E(
389
378
  r,
390
- a.fromOffset,
391
- a.fromIsPercentage,
392
- 1,
393
- // Default: 100% = 1.0
394
- s.maxWheelbase
395
- ), c = E(
379
+ o.fromOffset,
380
+ o.fromIsPercentage,
381
+ 1
382
+ ), a = B(
396
383
  f,
397
- a.toOffset,
398
- a.toIsPercentage,
399
- 0,
400
- s.maxWheelbase
401
- ), g = W(
384
+ o.toOffset,
385
+ o.toIsPercentage,
386
+ 0
387
+ ), g = q(
402
388
  r,
403
389
  f,
404
- s,
405
- !1,
406
- // willFlip is always false now
390
+ n,
407
391
  {
408
392
  fromOffset: l,
409
393
  fromIsPercentage: !1,
410
- // Already resolved to absolute
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(o.curveIndex, { bezier: g, arcLengthTable: d });
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, n) {
423
- const { graph: s, linesMap: i, curves: o, config: a } = n, r = i.get(e.targetLineId);
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, v) => u + v, 0), c = O(r) - f;
426
- if (c <= 0) return null;
427
- const g = e.isPercentage ? e.targetOffset * c : Math.min(e.targetOffset, c), d = t.axles[t.axles.length - 1], h = G(
428
- s,
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 p = Y(h, o, i, a);
436
- return { path: h, curveDataMap: p };
417
+ const v = Y(h, c, i, o);
418
+ return { path: h, curveDataMap: v };
437
419
  }
438
420
  function oe(t, e) {
439
- const n = t.execution, i = e.vehicleQueues.get(t.vehicle.id)?.[n.currentCommandIndex];
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: n,
434
+ newExecution: s,
453
435
  // Keep execution state for resume
454
436
  isWaiting: !0
455
437
  };
456
438
  }
457
- function ee(t, e, n, s, i, o) {
458
- let a;
439
+ function ee(t, e, s, n, i, c) {
440
+ let o;
459
441
  const r = e[0];
460
- if (r.currentSegmentIndex < n.segments.length) {
461
- const l = n.segments[r.currentSegmentIndex];
442
+ if (r.currentSegmentIndex < s.segments.length) {
443
+ const l = s.segments[r.currentSegmentIndex];
462
444
  if (l.type === "line") {
463
- const c = i.get(l.lineId);
464
- c && (a = O(c));
445
+ const a = i.get(l.lineId);
446
+ a && (o = O(a));
465
447
  }
466
448
  }
467
- const f = t.map((l, c) => {
468
- const g = c === 0 ? a : void 0;
469
- return X(l, e[c], n, s, i, o, g);
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 ae {
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, n) {
488
+ setScene(e, s) {
508
489
  this.linesMap.clear();
509
- for (const s of e)
510
- this.linesMap.set(s.id, s);
511
- this.curves = n, this.graph = I(e, n, this.config);
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, n) {
523
- const s = this.linesMap.get(e);
524
- return s ? (n.start && (s.start = n.start), n.end && (s.end = n.end), this.graph = I(Array.from(this.linesMap.values()), this.curves, this.config), !0) : !1;
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, n, s) {
530
- return this.updateLine(e, { [n]: s });
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, n) {
536
- const s = n.trim();
537
- if (!s) return { success: !1, error: "Name cannot be empty" };
538
- if (s === e) return { success: !0 };
539
- if (this.linesMap.has(s)) return { success: !1, error: `"${s}" already exists` };
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 = s, this.linesMap.delete(e), this.linesMap.set(s, i);
543
- for (const o of this.curves)
544
- o.fromLineId === e && (o.fromLineId = s), o.toLineId === e && (o.toLineId = s);
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((n) => n.fromLineId !== e && n.toLineId !== e), this.graph = I(Array.from(this.linesMap.values()), this.curves, this.config), !0) : !1;
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, n) {
563
- return e < 0 || e >= this.curves.length ? !1 : (this.curves[e] = { ...this.curves[e], ...n }, this.graph = I(Array.from(this.linesMap.values()), this.curves, this.config), !0);
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, n, s) {
564
+ initializeVehicle(e, s, n) {
584
565
  const i = this.linesMap.get(e);
585
566
  if (!i) return null;
586
- const { axleSpacings: o } = s;
587
- if (o.length === 0)
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 a = o.reduce((c, g) => c + g, 0), r = O(i), f = Math.min(n, r - a);
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, o, i).map((c) => ({ lineId: c.lineId, offset: c.absoluteOffset, position: c.position })),
592
- axleSpacings: o
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, n, s, i = !1) {
586
+ preparePath(e, s, n, i = !1) {
606
587
  if (!this.graph) return null;
607
- const o = e.axleSpacings.reduce((h, p) => h + p, 0), a = e.axles[e.axles.length - 1], r = {
608
- lineId: a.lineId,
609
- offset: a.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: n,
618
- targetOffset: s,
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 = s;
628
- const c = this.linesMap.get(n);
629
- if (c) {
630
- const h = Math.max(0, O(c) - o);
631
- l = i ? s * h : Math.min(s, h);
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: o }
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: o - g });
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: n,
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, n, s) {
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
- })), o = n.axleExecutions.map((r) => ({
644
+ })), c = s.axleExecutions.map((r) => ({
664
645
  currentSegmentIndex: r.segmentIndex,
665
646
  segmentDistance: r.segmentDistance
666
- })), a = ee(i, o, n.path, s, this.linesMap, n.curveDataMap);
647
+ })), o = ee(i, c, s.path, n, this.linesMap, s.curveDataMap);
667
648
  return {
668
649
  state: {
669
- axles: a.axles.map((r) => ({ lineId: r.lineId, offset: r.absoluteOffset, position: r.position })),
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
- ...n,
674
- axleExecutions: a.axleExecutions.map((r) => ({
654
+ ...s,
655
+ axleExecutions: o.axleExecutions.map((r) => ({
675
656
  segmentIndex: r.currentSegmentIndex,
676
657
  segmentDistance: r.segmentDistance
677
658
  }))
678
659
  },
679
- arrived: a.arrived
660
+ arrived: o.arrived
680
661
  };
681
662
  }
682
663
  }
683
664
  export {
684
- S as A,
665
+ V as A,
685
666
  Z as B,
686
- q as C,
687
- E as D,
667
+ E as C,
668
+ B as D,
688
669
  X as E,
689
- ae as P,
670
+ ce as P,
690
671
  O as a,
691
- R as b,
672
+ _ as b,
692
673
  N as c,
693
674
  I as d,
694
- F as e,
675
+ Q as e,
695
676
  ie as f,
696
- Q as g,
677
+ W as g,
697
678
  H as h,
698
679
  w as i,
699
680
  M as j,
700
- k,
701
- W as l,
681
+ F as k,
682
+ q as l,
702
683
  ee as m,
703
684
  U as n,
704
685
  y as o,
705
- _ as p,
706
- G as q,
686
+ G as p,
687
+ R as q,
707
688
  se as r,
708
- b as s,
689
+ A as s,
709
690
  K as t,
710
- V as u,
711
- A as v,
691
+ z as u,
692
+ P as v,
712
693
  oe as w,
713
694
  re as x,
714
695
  J as y,
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-C4FckUel.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;
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;
@@ -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-C7pH7jZo.js";
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vehicle-path2",
3
- "version": "3.0.1",
3
+ "version": "4.0.0",
4
4
  "description": "Vehicle motion simulator library for dual-axle vehicle movement along paths composed of lines and Bezier curves",
5
5
  "type": "module",
6
6
  "main": "./dist/vehicle-path.cjs",
@@ -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;