vehicle-path2 2.4.0 → 3.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.
@@ -9,11 +9,11 @@
9
9
  * ```typescript
10
10
  * import { PathEngine } from 'vehicle-path/core'
11
11
  *
12
- * const engine = new PathEngine({ wheelbase: 30, tangentMode: 'proportional-40' })
12
+ * const engine = new PathEngine({ maxWheelbase: 100, tangentMode: 'proportional-40' })
13
13
  *
14
14
  * engine.setScene(lines, curves)
15
15
  *
16
- * const state = engine.initializeVehicle('line-1', 0)
16
+ * const state = engine.initializeVehicle('line-1', 0, { axleSpacings: [40] })
17
17
  * const execution = engine.preparePath(state, 'line-3', 1.0, true)
18
18
  *
19
19
  * // In your animation/game loop:
@@ -26,6 +26,7 @@
26
26
  * ```
27
27
  */
28
28
  import type { Line, Curve, Point } from './types/geometry';
29
+ import type { VehicleDefinition } from './types/vehicle';
29
30
  import type { MovementConfig, CurveData } from './types/movement';
30
31
  import type { PathResult } from './algorithms/pathFinding';
31
32
  import type { TangentMode } from './types/config';
@@ -37,14 +38,12 @@ export interface PathEngineConfig {
37
38
  * Multi-axle position state for use with PathEngine.
38
39
  * axles[0] = terdepan, axles[N-1] = paling belakang.
39
40
  */
40
- export interface VehiclePathState {
41
+ export interface VehiclePathState extends VehicleDefinition {
41
42
  axles: Array<{
42
43
  lineId: string;
43
44
  offset: number;
44
45
  position: Point;
45
46
  }>;
46
- /** N-1 jarak arc-length antar axle berurutan */
47
- axleSpacings: number[];
48
47
  }
49
48
  /**
50
49
  * Active path execution state for a vehicle in motion.
@@ -127,10 +126,11 @@ export declare class PathEngine {
127
126
  *
128
127
  * @param lineId - The line to place the vehicle on
129
128
  * @param rearOffset - Absolute distance offset untuk axle paling belakang
130
- * @param axleSpacings - Jarak antar axle berurutan (N-1 nilai untuk N axle)
129
+ * @param vehicle - VehicleDefinition (or any object extending it with axleSpacings)
131
130
  * @returns Initial VehiclePathState, or null if lineId does not exist
131
+ * @throws if axleSpacings is empty
132
132
  */
133
- initializeVehicle(lineId: string, rearOffset: number, axleSpacings: number[]): VehiclePathState | null;
133
+ initializeVehicle(lineId: string, rearOffset: number, vehicle: VehicleDefinition): VehiclePathState | null;
134
134
  /**
135
135
  * Prepare a path from the vehicle's current position to a target.
136
136
  *
@@ -11,7 +11,7 @@
11
11
  * ```
12
12
  */
13
13
  export type { Point, Line, BezierCurve, Curve } from './types/geometry';
14
- export type { VehicleState, VehicleStart, Vehicle, AxleState, GotoCommand, GotoCompletionInfo, GotoCompletionCallback } from './types/vehicle';
14
+ export type { VehicleDefinition, VehicleState, VehicleStart, Vehicle, AxleState, GotoCommand, GotoCompletionInfo, GotoCompletionCallback } from './types/vehicle';
15
15
  export type { CurveData, AxleExecutionState, PathExecutionState, 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';
@@ -10,24 +10,10 @@ export interface SceneSnapshot {
10
10
  toOffset: number;
11
11
  toIsPercentage: boolean;
12
12
  }>;
13
- vehicles: Array<{
14
- id: string;
15
- lineId: string;
16
- axles: Array<{
17
- offset: number;
18
- }>;
19
- axleSpacings: number[];
20
- isPercentage: boolean;
21
- }>;
22
13
  }
23
14
  /**
24
- * Serialize scene state to a JSON string suitable for clipboard or storage.
25
- * Strips derived fields (bezier curves, axle positions) only source-of-truth
26
- * data is included.
27
- *
28
- * Note: lineId is per-vehicle (not per-axle) because this snapshot captures
29
- * static placement where all axles share the same line. For mid-movement state,
30
- * use AxleState directly.
15
+ * Serialize scene state (lines + curves) to a JSON string.
16
+ * Vehicles are NOT included vehicle persistence is the client's responsibility.
31
17
  */
32
18
  export declare function serializeScene(lines: Line[], curves: Array<{
33
19
  id: string;
@@ -37,18 +23,10 @@ export declare function serializeScene(lines: Line[], curves: Array<{
37
23
  fromIsPercentage?: boolean;
38
24
  toOffset: number;
39
25
  toIsPercentage?: boolean;
40
- }>, vehicles: Array<{
41
- id: string;
42
- axles: Array<{
43
- lineId: string;
44
- offset: number;
45
- [key: string]: unknown;
46
- }>;
47
- axleSpacings: number[];
48
- isPercentage?: boolean;
49
26
  }>): string;
50
27
  /**
51
28
  * Deserialize a JSON string back into a SceneSnapshot.
52
- * Throws if the string is not valid JSON or missing required fields.
29
+ * Throws if the string is not valid JSON or missing required fields (lines, curves).
30
+ * Extra fields in the JSON (e.g. legacy "vehicles") are silently ignored.
53
31
  */
54
32
  export declare function deserializeScene(json: string): SceneSnapshot;
@@ -2,6 +2,17 @@
2
2
  * Vehicle-related types
3
3
  */
4
4
  import type { Point } from './geometry';
5
+ /**
6
+ * Base definition of a vehicle's physical structure.
7
+ * Client code is free to extend this with additional fields (id, name, color, etc).
8
+ *
9
+ * @example
10
+ * interface MyVehicle extends VehicleDefinition { id: string; name: string }
11
+ */
12
+ export interface VehicleDefinition {
13
+ /** N-1 arc-length spacings between consecutive axles. axleSpacings[i] = distance from axles[i] to axles[i+1]. */
14
+ axleSpacings: number[];
15
+ }
5
16
  /**
6
17
  * Animation state for a vehicle
7
18
  */
@@ -28,14 +39,13 @@ export interface AxleState {
28
39
  /**
29
40
  * Vehicle with runtime state (used during animation)
30
41
  */
31
- export interface Vehicle {
42
+ export interface Vehicle extends VehicleDefinition {
32
43
  id: string;
33
44
  lineId: string;
34
45
  offset: number;
35
46
  isPercentage: boolean;
36
47
  state: VehicleState;
37
48
  axles: AxleState[];
38
- axleSpacings: number[];
39
49
  }
40
50
  /**
41
51
  * Command to move a vehicle to a target position
package/dist/core.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-BUYdltrL.cjs");function f(a,t,i){const r={lines:a,curves:t.map(n=>({id:n.id,fromLineId:n.fromLineId,toLineId:n.toLineId,fromOffset:n.fromOffset,fromIsPercentage:n.fromIsPercentage??!1,toOffset:n.toOffset,toIsPercentage:n.toIsPercentage??!1})),vehicles:i.map(n=>({id:n.id,lineId:n.axles[0].lineId,axles:n.axles.map(o=>({offset:o.offset})),axleSpacings:n.axleSpacings,isPercentage:n.isPercentage??!1}))};return JSON.stringify(r,null,2)}function g(a){let t;try{t=JSON.parse(a)}catch{throw new Error("deserializeScene: invalid JSON")}if(!t||typeof t!="object"||Array.isArray(t))throw new Error("deserializeScene: expected a JSON object");const i=t;if(!Array.isArray(i.lines))throw new Error('deserializeScene: missing "lines"');if(!Array.isArray(i.curves))throw new Error('deserializeScene: missing "curves"');if(!Array.isArray(i.vehicles))throw new Error('deserializeScene: missing "vehicles"');return{lines:i.lines,curves:i.curves,vehicles:i.vehicles}}function h(a,t){const i=t.end.x-t.start.x,r=t.end.y-t.start.y,n=i*i+r*r;if(n===0)return{offset:0,distance:Math.sqrt((a.x-t.start.x)**2+(a.y-t.start.y)**2)};const o=Math.max(0,Math.min(1,((a.x-t.start.x)*i+(a.y-t.start.y)*r)/n)),s=t.start.x+o*i,c=t.start.y+o*r,l=Math.sqrt((a.x-s)**2+(a.y-c)**2);return{offset:o*Math.sqrt(n),distance:l}}function d(a,t){const i=e.getLineLength(a),r=t.reduce((o,s)=>o+s,0);return[0,Math.max(0,i-r)]}function u(a,t){let i=0;for(const r of t)r.fromLineId===a&&!r.fromIsPercentage&&r.fromOffset!==void 0&&(i=Math.max(i,r.fromOffset)),r.toLineId===a&&!r.toIsPercentage&&r.toOffset!==void 0&&(i=Math.max(i,r.toOffset));return i}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.calculateTangentLength=e.calculateTangentLength;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.isPointNearPoint=e.isPointNearPoint;exports.moveVehicle=e.moveVehicle;exports.normalize=e.normalize;exports.prepareCommandPath=e.prepareCommandPath;exports.resolveFromLineOffset=e.resolveFromLineOffset;exports.resolveToLineOffset=e.resolveToLineOffset;exports.updateAxlePosition=e.updateAxlePosition;exports.computeMinLineLength=u;exports.deserializeScene=g;exports.getValidRearOffsetRange=d;exports.projectPointOnLine=h;exports.serializeScene=f;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-C4FckUel.cjs");function f(r,n){const i={lines:r,curves:n.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(i,null,2)}function g(r){let n;try{n=JSON.parse(r)}catch{throw new Error("deserializeScene: invalid JSON")}if(!n||typeof n!="object"||Array.isArray(n))throw new Error("deserializeScene: expected a JSON object");const i=n;if(!Array.isArray(i.lines))throw new Error('deserializeScene: missing "lines"');if(!Array.isArray(i.curves))throw new Error('deserializeScene: missing "curves"');return{lines:i.lines,curves:i.curves}}function u(r,n){const i=n.end.x-n.start.x,t=n.end.y-n.start.y,o=i*i+t*t;if(o===0)return{offset:0,distance:Math.sqrt((r.x-n.start.x)**2+(r.y-n.start.y)**2)};const a=Math.max(0,Math.min(1,((r.x-n.start.x)*i+(r.y-n.start.y)*t)/o)),s=n.start.x+a*i,c=n.start.y+a*t,l=Math.sqrt((r.x-s)**2+(r.y-c)**2);return{offset:a*Math.sqrt(o),distance:l}}function h(r,n){const i=e.getLineLength(r),t=n.reduce((a,s)=>a+s,0);return[0,Math.max(0,i-t)]}function d(r,n){let i=0;for(const t of n)t.fromLineId===r&&!t.fromIsPercentage&&t.fromOffset!==void 0&&(i=Math.max(i,t.fromOffset)),t.toLineId===r&&!t.toIsPercentage&&t.toOffset!==void 0&&(i=Math.max(i,t.toOffset));return i}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.calculateTangentLength=e.calculateTangentLength;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.isPointNearPoint=e.isPointNearPoint;exports.moveVehicle=e.moveVehicle;exports.normalize=e.normalize;exports.prepareCommandPath=e.prepareCommandPath;exports.resolveFromLineOffset=e.resolveFromLineOffset;exports.resolveToLineOffset=e.resolveToLineOffset;exports.updateAxlePosition=e.updateAxlePosition;exports.computeMinLineLength=d;exports.deserializeScene=g;exports.getValidRearOffsetRange=h;exports.projectPointOnLine=u;exports.serializeScene=f;
package/dist/core.js CHANGED
@@ -1,86 +1,77 @@
1
- import { g as f } from "./index-wjEuFiRl.js";
2
- import { P as y, a as v, b as A, c as p, d as S, e as I, f as z, h as w, i as M, j as b, k as j, l as E, m as T, n as q, o as B, p as C, q as N, r as J, s as V, t as F, u as R, v as k, w as D, x as G, y as X, z as Y, A as H, B as K, C as Q, D as U, E as W } from "./index-wjEuFiRl.js";
3
- function h(r, e, t) {
4
- const a = {
5
- lines: r,
6
- curves: e.map((s) => ({
7
- id: s.id,
8
- fromLineId: s.fromLineId,
9
- toLineId: s.toLineId,
10
- fromOffset: s.fromOffset,
11
- fromIsPercentage: s.fromIsPercentage ?? !1,
12
- toOffset: s.toOffset,
13
- toIsPercentage: s.toIsPercentage ?? !1
14
- })),
15
- vehicles: t.map((s) => ({
16
- id: s.id,
17
- lineId: s.axles[0].lineId,
18
- axles: s.axles.map((n) => ({ offset: n.offset })),
19
- axleSpacings: s.axleSpacings,
20
- isPercentage: s.isPercentage ?? !1
1
+ import { g as f } from "./index-BV93143R.js";
2
+ import { P as y, a as v, b as A, c as S, d as p, e as z, f as I, h as M, i as w, j as b, k as j, l as E, m as T, n as q, o as B, p as C, q as N, r as J, s as V, t as F, u as R, v as k, w as D, x as G, y as X, z as Y, A as H, B as K, C as Q, D as U, E as W } from "./index-BV93143R.js";
3
+ function u(a, t) {
4
+ const s = {
5
+ lines: a,
6
+ curves: t.map((e) => ({
7
+ id: e.id,
8
+ fromLineId: e.fromLineId,
9
+ toLineId: e.toLineId,
10
+ fromOffset: e.fromOffset,
11
+ fromIsPercentage: e.fromIsPercentage ?? !1,
12
+ toOffset: e.toOffset,
13
+ toIsPercentage: e.toIsPercentage ?? !1
21
14
  }))
22
15
  };
23
- return JSON.stringify(a, null, 2);
16
+ return JSON.stringify(s, null, 2);
24
17
  }
25
- function m(r) {
26
- let e;
18
+ function g(a) {
19
+ let t;
27
20
  try {
28
- e = JSON.parse(r);
21
+ t = JSON.parse(a);
29
22
  } catch {
30
23
  throw new Error("deserializeScene: invalid JSON");
31
24
  }
32
- if (!e || typeof e != "object" || Array.isArray(e))
25
+ if (!t || typeof t != "object" || Array.isArray(t))
33
26
  throw new Error("deserializeScene: expected a JSON object");
34
- const t = e;
35
- if (!Array.isArray(t.lines)) throw new Error('deserializeScene: missing "lines"');
36
- if (!Array.isArray(t.curves)) throw new Error('deserializeScene: missing "curves"');
37
- if (!Array.isArray(t.vehicles)) throw new Error('deserializeScene: missing "vehicles"');
27
+ const s = t;
28
+ if (!Array.isArray(s.lines)) throw new Error('deserializeScene: missing "lines"');
29
+ if (!Array.isArray(s.curves)) throw new Error('deserializeScene: missing "curves"');
38
30
  return {
39
- lines: t.lines,
40
- curves: t.curves,
41
- vehicles: t.vehicles
31
+ lines: s.lines,
32
+ curves: s.curves
42
33
  };
43
34
  }
44
- function u(r, e) {
45
- const t = e.end.x - e.start.x, a = e.end.y - e.start.y, s = t * t + a * a;
46
- if (s === 0)
35
+ function h(a, t) {
36
+ const s = t.end.x - t.start.x, e = t.end.y - t.start.y, n = s * s + e * e;
37
+ if (n === 0)
47
38
  return { offset: 0, distance: Math.sqrt(
48
- (r.x - e.start.x) ** 2 + (r.y - e.start.y) ** 2
39
+ (a.x - t.start.x) ** 2 + (a.y - t.start.y) ** 2
49
40
  ) };
50
- const n = Math.max(
41
+ const r = Math.max(
51
42
  0,
52
43
  Math.min(
53
44
  1,
54
- ((r.x - e.start.x) * t + (r.y - e.start.y) * a) / s
45
+ ((a.x - t.start.x) * s + (a.y - t.start.y) * e) / n
55
46
  )
56
- ), i = e.start.x + n * t, o = e.start.y + n * a, c = Math.sqrt((r.x - i) ** 2 + (r.y - o) ** 2);
57
- return { offset: n * Math.sqrt(s), distance: c };
47
+ ), i = t.start.x + r * s, o = t.start.y + r * e, c = Math.sqrt((a.x - i) ** 2 + (a.y - o) ** 2);
48
+ return { offset: r * Math.sqrt(n), distance: c };
58
49
  }
59
- function x(r, e) {
60
- const t = f(r), a = e.reduce((n, i) => n + i, 0);
61
- return [0, Math.max(0, t - a)];
50
+ function L(a, t) {
51
+ const s = f(a), e = t.reduce((r, i) => r + i, 0);
52
+ return [0, Math.max(0, s - e)];
62
53
  }
63
- function P(r, e) {
64
- let t = 0;
65
- for (const a of e)
66
- a.fromLineId === r && !a.fromIsPercentage && a.fromOffset !== void 0 && (t = Math.max(t, a.fromOffset)), a.toLineId === r && !a.toIsPercentage && a.toOffset !== void 0 && (t = Math.max(t, a.toOffset));
67
- return t;
54
+ function O(a, t) {
55
+ let s = 0;
56
+ for (const e of t)
57
+ e.fromLineId === a && !e.fromIsPercentage && e.fromOffset !== void 0 && (s = Math.max(s, e.fromOffset)), e.toLineId === a && !e.toIsPercentage && e.toOffset !== void 0 && (s = Math.max(s, e.toOffset));
58
+ return s;
68
59
  }
69
60
  export {
70
61
  y as PathEngine,
71
62
  v as arcLengthToSegmentPosition,
72
63
  A as buildArcLengthTable,
73
- p as buildGraph,
74
- S as calculateBezierArcLength,
75
- I as calculateFrontAxlePosition,
76
- z as calculateInitialAxlePositions,
77
- w as calculatePositionOnCurve,
78
- M as calculatePositionOnLine,
64
+ S as buildGraph,
65
+ p as calculateBezierArcLength,
66
+ z as calculateFrontAxlePosition,
67
+ I as calculateInitialAxlePositions,
68
+ M as calculatePositionOnCurve,
69
+ w as calculatePositionOnLine,
79
70
  b as calculateTangentLength,
80
- P as computeMinLineLength,
71
+ O as computeMinLineLength,
81
72
  j as createBezierCurve,
82
73
  E as createInitialMovementState,
83
- m as deserializeScene,
74
+ g as deserializeScene,
84
75
  T as distance,
85
76
  q as distanceToT,
86
77
  B as findPath,
@@ -91,7 +82,7 @@ export {
91
82
  V as getPointOnLine,
92
83
  F as getPointOnLineByOffset,
93
84
  R as getPositionFromOffset,
94
- x as getValidRearOffsetRange,
85
+ L as getValidRearOffsetRange,
95
86
  k as handleArrival,
96
87
  D as initializeAllVehicles,
97
88
  G as initializeMovingVehicle,
@@ -99,9 +90,9 @@ export {
99
90
  Y as moveVehicle,
100
91
  H as normalize,
101
92
  K as prepareCommandPath,
102
- u as projectPointOnLine,
93
+ h as projectPointOnLine,
103
94
  Q as resolveFromLineOffset,
104
95
  U as resolveToLineOffset,
105
- h as serializeScene,
96
+ u as serializeScene,
106
97
  W as updateAxlePosition
107
98
  };
@@ -1,29 +1,29 @@
1
1
  function y(t, e) {
2
- const s = e.x - t.x, n = e.y - t.y;
3
- return Math.sqrt(s * s + n * n);
2
+ const n = e.x - t.x, s = e.y - t.y;
3
+ return Math.sqrt(n * n + s * s);
4
4
  }
5
- function w(t, e) {
6
- const s = e.x - t.x, n = e.y - t.y, r = Math.sqrt(s * s + n * n);
7
- return r === 0 ? { x: 0, y: 0 } : { x: s / r, y: n / r };
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 };
8
8
  }
9
9
  function k(t, e) {
10
10
  return e * (t === "proportional-40" ? 0.4 : 0.5522);
11
11
  }
12
- function z(t, e, s, n = !1, r) {
13
- const { maxWheelbase: o, tangentMode: a } = s;
14
- let i;
15
- r?.fromOffset !== void 0 ? i = V(t, r.fromOffset, r.fromIsPercentage ?? !1) : i = t.end;
16
- let c;
17
- r?.toOffset !== void 0 ? c = V(e, r.toOffset, r.toIsPercentage ?? !1) : c = e.start;
18
- const l = w(t.start, t.end), f = n ? {
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
19
  // Transition with flip: kurva dimulai dari P (baseP0 - wheelbase in line direction)
20
- x: i.x - l.x * o,
21
- y: i.y - l.y * o
22
- } : i, g = w(t.start, t.end), d = w(e.start, e.end), h = y(f, c), p = k(a, h), u = n ? { x: f.x - g.x * p, y: f.y - g.y * p } : { x: f.x + g.x * p, y: f.y + g.y * p }, v = {
23
- x: c.x - d.x * p,
24
- y: c.y - d.y * p
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
25
  };
26
- return { p0: f, p1: u, p2: v, p3: c };
26
+ return { p0: c, p1: u, p2: v, p3: f };
27
27
  }
28
28
  function K(t, e) {
29
29
  return {
@@ -31,78 +31,78 @@ function K(t, e) {
31
31
  y: t.start.y + (t.end.y - t.start.y) * e
32
32
  };
33
33
  }
34
- function V(t, e, s) {
35
- const n = y(t.start, t.end);
36
- let r;
37
- return s ? r = e : r = n > 0 ? e / n : 0, r = Math.max(0, Math.min(1, r)), K(t, r);
34
+ function V(t, e, n) {
35
+ const s = y(t.start, t.end);
36
+ let i;
37
+ return n ? i = e : i = s > 0 ? e / s : 0, i = Math.max(0, Math.min(1, i)), K(t, i);
38
38
  }
39
39
  function b(t, e) {
40
- const { p0: s, p1: n, p2: r, p3: o } = t, a = 1 - e, i = a * a, c = i * a, l = e * e, f = l * 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;
41
41
  return {
42
- x: c * s.x + 3 * i * e * n.x + 3 * a * l * r.x + f * o.x,
43
- y: c * s.y + 3 * i * e * n.y + 3 * a * l * r.y + f * o.y
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
44
44
  };
45
45
  }
46
- function ne(t, e, s = 10) {
47
- return y(t, e) <= s;
46
+ function ne(t, e, n = 10) {
47
+ return y(t, e) <= n;
48
48
  }
49
49
  function N(t, e = 100) {
50
- const s = [{ t: 0, distance: 0 }];
51
- let n = t.p0, r = 0;
50
+ const n = [{ t: 0, distance: 0 }];
51
+ let s = t.p0, i = 0;
52
52
  for (let o = 1; o <= e; o++) {
53
- const a = o / e, i = b(t, a);
54
- r += y(n, i), s.push({ t: a, distance: r }), n = i;
53
+ const a = o / e, r = b(t, a);
54
+ i += y(s, r), n.push({ t: a, distance: i }), s = r;
55
55
  }
56
- return s;
56
+ return n;
57
57
  }
58
58
  function _(t, e) {
59
59
  if (e <= 0) return 0;
60
- const s = t[t.length - 1].distance;
61
- if (e >= s) return 1;
62
- let n = 0, r = t.length - 1;
63
- for (; n < r - 1; ) {
64
- const f = Math.floor((n + r) / 2);
65
- t[f].distance < e ? n = f : r = f;
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;
66
66
  }
67
- const o = t[n].distance, a = t[r].distance, i = t[n].t, c = t[r].t;
68
- if (a === o) return i;
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
69
  const l = (e - o) / (a - o);
70
- return i + l * (c - i);
70
+ return r + l * (f - r);
71
71
  }
72
72
  function se(t) {
73
73
  return t[t.length - 1].distance;
74
74
  }
75
75
  function F(t, e = 100) {
76
- let s = 0, n = t.p0;
77
- for (let r = 1; r <= e; r++) {
78
- const o = r / e, a = b(t, o);
79
- s += y(n, a), n = a;
76
+ let n = 0, s = t.p0;
77
+ for (let i = 1; i <= e; i++) {
78
+ const o = i / e, a = b(t, o);
79
+ n += y(s, a), s = a;
80
80
  }
81
- return s;
81
+ return n;
82
82
  }
83
- function q(t, e, s, n, r) {
83
+ function q(t, e, n, s, i) {
84
84
  const o = y(t.start, t.end);
85
- return e === void 0 ? n * o : s ? Math.max(0, Math.min(e, 1)) * o : Math.max(0, Math.min(e, o));
85
+ return e === void 0 ? s * o : n ? Math.max(0, Math.min(e, 1)) * o : Math.max(0, Math.min(e, o));
86
86
  }
87
- function E(t, e, s, n, r) {
87
+ function E(t, e, n, s, i) {
88
88
  const o = y(t.start, t.end);
89
- return e === void 0 ? n * o : s ? Math.max(0, Math.min(e, 1)) * o : Math.max(0, Math.min(e, o));
89
+ return e === void 0 ? s * o : n ? Math.max(0, Math.min(e, 1)) * o : Math.max(0, Math.min(e, o));
90
90
  }
91
- function I(t, e, s) {
92
- const n = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Map();
91
+ function I(t, e, n) {
92
+ const s = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Map();
93
93
  for (const a of t)
94
- r.set(a.id, a), o.set(a.id, y(a.start, a.end)), n.set(a.id, []);
94
+ i.set(a.id, a), o.set(a.id, y(a.start, a.end)), s.set(a.id, []);
95
95
  for (let a = 0; a < e.length; a++) {
96
- const i = e[a], c = r.get(i.fromLineId), l = r.get(i.toLineId);
97
- if (!c || !l) continue;
98
- const f = q(c, i.fromOffset, i.fromIsPercentage, 1, s.maxWheelbase), g = E(l, i.toOffset, i.toIsPercentage, 0, s.maxWheelbase), d = z(
99
- c,
96
+ const r = e[a], f = i.get(r.fromLineId), l = i.get(r.toLineId);
97
+ 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(
99
+ f,
100
100
  l,
101
- s,
101
+ n,
102
102
  !1,
103
103
  // willFlip is always false now
104
104
  {
105
- fromOffset: f,
105
+ fromOffset: c,
106
106
  fromIsPercentage: !1,
107
107
  // Already resolved to absolute
108
108
  toOffset: g,
@@ -111,31 +111,31 @@ function I(t, e, s) {
111
111
  }
112
112
  ), h = F(d), p = {
113
113
  curveIndex: a,
114
- fromLineId: i.fromLineId,
115
- toLineId: i.toLineId,
116
- fromOffset: f,
114
+ fromLineId: r.fromLineId,
115
+ toLineId: r.toLineId,
116
+ fromOffset: c,
117
117
  toOffset: g,
118
118
  curveLength: h
119
119
  };
120
- n.get(i.fromLineId).push(p);
120
+ s.get(r.fromLineId).push(p);
121
121
  }
122
- return { adjacency: n, lines: r, lineLengths: o };
122
+ return { adjacency: s, lines: i, lineLengths: o };
123
123
  }
124
- function W(t, e) {
124
+ function z(t, e) {
125
125
  return t.curveCount !== e.curveCount ? t.curveCount - e.curveCount : t.totalDistance - e.totalDistance;
126
126
  }
127
- function G(t, e, s, n, r = !1) {
128
- const { adjacency: o, lines: a, lineLengths: i } = t;
129
- if (!a.get(s)) return null;
130
- const l = i.get(s), f = r ? n / 100 * l : n, g = [], d = /* @__PURE__ */ new Map(), h = (u, v) => `${u}:${Math.round(v)}`;
131
- if (e.lineId === s && f >= e.offset) {
132
- const u = f - e.offset;
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;
133
133
  return {
134
134
  segments: [{
135
135
  type: "line",
136
136
  lineId: e.lineId,
137
137
  startOffset: e.offset,
138
- endOffset: f,
138
+ endOffset: c,
139
139
  length: u
140
140
  }],
141
141
  totalDistance: u,
@@ -166,18 +166,18 @@ function G(t, e, s, n, r = !1) {
166
166
  path: [L, m]
167
167
  });
168
168
  }
169
- for (g.sort(W); g.length > 0; ) {
169
+ for (g.sort(z); g.length > 0; ) {
170
170
  const u = g.shift(), v = h(u.lineId, u.entryOffset), x = d.get(v);
171
171
  if (x !== void 0 && (x.curveCount < u.curveCount || x.curveCount === u.curveCount && x.distance <= u.totalDistance))
172
172
  continue;
173
- if (d.set(v, { curveCount: u.curveCount, distance: u.totalDistance }), u.lineId === s) {
174
- const m = Math.abs(f - u.entryOffset);
175
- if (f >= u.entryOffset) {
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) {
176
176
  const C = {
177
177
  type: "line",
178
- lineId: s,
178
+ lineId: n,
179
179
  startOffset: u.entryOffset,
180
- endOffset: f,
180
+ endOffset: c,
181
181
  length: m
182
182
  };
183
183
  return {
@@ -214,17 +214,17 @@ function G(t, e, s, n, r = !1) {
214
214
  path: [...u.path, j, $]
215
215
  });
216
216
  }
217
- g.sort(W);
217
+ g.sort(z);
218
218
  }
219
219
  return null;
220
220
  }
221
221
  function A(t, e) {
222
- const s = Math.sqrt(
222
+ const n = Math.sqrt(
223
223
  Math.pow(t.end.x - t.start.x, 2) + Math.pow(t.end.y - t.start.y, 2)
224
- ), n = s > 0 ? e / s : 0;
224
+ ), s = n > 0 ? e / n : 0;
225
225
  return {
226
- x: t.start.x + (t.end.x - t.start.x) * Math.min(1, Math.max(0, n)),
227
- y: t.start.y + (t.end.y - t.start.y) * Math.min(1, Math.max(0, n))
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))
228
228
  };
229
229
  }
230
230
  function O(t) {
@@ -232,54 +232,54 @@ function O(t) {
232
232
  Math.pow(t.end.x - t.start.x, 2) + Math.pow(t.end.y - t.start.y, 2)
233
233
  );
234
234
  }
235
- function Q(t, e, s) {
236
- let n = 0;
237
- for (let r = 0; r < e; r++)
238
- n += t.segments[r].length;
239
- return n += s, n;
235
+ function Q(t, e, n) {
236
+ let s = 0;
237
+ for (let i = 0; i < e; i++)
238
+ s += t.segments[i].length;
239
+ return s += n, s;
240
240
  }
241
241
  function R(t, e) {
242
- let s = 0;
243
- for (let n = 0; n < t.segments.length; n++) {
244
- const r = t.segments[n], o = s + r.length;
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
245
  if (e < o)
246
246
  return {
247
- segmentIndex: n,
248
- segmentDistance: e - s
247
+ segmentIndex: s,
248
+ segmentDistance: e - n
249
249
  };
250
250
  if (e === o)
251
- return n + 1 < t.segments.length ? {
252
- segmentIndex: n + 1,
251
+ return s + 1 < t.segments.length ? {
252
+ segmentIndex: s + 1,
253
253
  segmentDistance: 0
254
254
  } : {
255
- segmentIndex: n,
256
- segmentDistance: r.length
255
+ segmentIndex: s,
256
+ segmentDistance: i.length
257
257
  };
258
- s += r.length;
258
+ n += i.length;
259
259
  }
260
260
  return null;
261
261
  }
262
- function re(t, e, s, n) {
262
+ function ie(t, e, n, s) {
263
263
  const o = Q(
264
264
  t,
265
265
  e,
266
- s
267
- ) + n;
266
+ n
267
+ ) + s;
268
268
  return R(t, o);
269
269
  }
270
- function H(t, e, s, n) {
271
- const r = O(n), o = s.length + 1, a = new Array(o);
270
+ function H(t, e, n, s) {
271
+ const i = O(s), o = n.length + 1, a = new Array(o);
272
272
  a[o - 1] = {
273
273
  lineId: t,
274
274
  absoluteOffset: e,
275
- position: A(n, e)
275
+ position: A(s, e)
276
276
  };
277
- let i = e;
278
- for (let c = o - 2; c >= 0; c--)
279
- i = Math.min(i + s[c], r), a[c] = {
277
+ let r = e;
278
+ for (let f = o - 2; f >= 0; f--)
279
+ r = Math.min(r + n[f], i), a[f] = {
280
280
  lineId: t,
281
- absoluteOffset: i,
282
- position: A(n, i)
281
+ absoluteOffset: r,
282
+ position: A(s, r)
283
283
  };
284
284
  return a;
285
285
  }
@@ -295,183 +295,183 @@ function U(t) {
295
295
  execution: null
296
296
  };
297
297
  }
298
- function ie(t, e) {
299
- const s = [], n = /* @__PURE__ */ new Map();
300
- for (const r of t) {
301
- if (!e.get(r.lineId)) continue;
302
- const a = J(r);
303
- s.push(a);
304
- const i = U(a);
305
- n.set(r.id, i);
298
+ function re(t, e) {
299
+ const n = [], s = /* @__PURE__ */ new Map();
300
+ for (const i of t) {
301
+ 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);
306
306
  }
307
- return { movingVehicles: s, stateMap: n };
307
+ return { movingVehicles: n, stateMap: s };
308
308
  }
309
309
  function M(t, e) {
310
310
  return { position: A(t, e), lineId: t.id, absoluteOffset: e };
311
311
  }
312
- function S(t, e) {
313
- const s = _(t.arcLengthTable, e);
314
- return { position: b(t.bezier, s) };
315
- }
316
- function X(t, e, s, n, r, o, a) {
317
- const i = s.segments[e.currentSegmentIndex], c = e.segmentDistance + n;
318
- if (c >= i.length) {
319
- const f = c - i.length, g = e.currentSegmentIndex + 1;
320
- if (g >= s.segments.length) {
321
- if (a !== void 0 && i.type === "line") {
322
- const u = r.get(i.lineId), v = i.startOffset + c;
312
+ function w(t, e) {
313
+ const n = _(t.arcLengthTable, e);
314
+ return { position: b(t.bezier, n) };
315
+ }
316
+ function X(t, e, n, s, i, o, a) {
317
+ const r = n.segments[e.currentSegmentIndex], f = e.segmentDistance + s;
318
+ 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
323
  if (v <= a) {
324
324
  const L = M(u, v);
325
325
  return {
326
326
  axleState: { ...t, ...L },
327
- execution: { ...e, segmentDistance: c },
327
+ execution: { ...e, segmentDistance: f },
328
328
  completed: !1
329
329
  };
330
330
  }
331
331
  const x = M(u, a);
332
332
  return {
333
333
  axleState: { ...t, ...x },
334
- execution: { ...e, segmentDistance: a - i.startOffset },
334
+ execution: { ...e, segmentDistance: a - r.startOffset },
335
335
  completed: !0
336
336
  };
337
337
  }
338
- const p = i.type === "line" ? M(
339
- r.get(i.lineId),
340
- i.endOffset
341
- ) : S(
342
- o.get(i.curveIndex),
343
- i.length
338
+ const p = r.type === "line" ? M(
339
+ i.get(r.lineId),
340
+ r.endOffset
341
+ ) : w(
342
+ o.get(r.curveIndex),
343
+ r.length
344
344
  );
345
345
  return {
346
346
  axleState: { ...t, ...p },
347
- execution: { ...e, segmentDistance: i.length },
347
+ execution: { ...e, segmentDistance: r.length },
348
348
  completed: !0
349
349
  };
350
350
  }
351
- const d = s.segments[g], h = d.type === "line" ? M(
352
- r.get(d.lineId),
353
- d.startOffset + f
354
- ) : S(
351
+ const d = n.segments[g], h = d.type === "line" ? M(
352
+ i.get(d.lineId),
353
+ d.startOffset + c
354
+ ) : w(
355
355
  o.get(d.curveIndex),
356
- f
356
+ c
357
357
  );
358
358
  return {
359
359
  axleState: { ...t, ...h },
360
360
  execution: {
361
361
  currentSegmentIndex: g,
362
- segmentDistance: f
362
+ segmentDistance: c
363
363
  },
364
364
  completed: !1
365
365
  };
366
366
  }
367
- const l = i.type === "line" ? M(
368
- r.get(i.lineId),
369
- i.startOffset + c
370
- ) : S(
371
- o.get(i.curveIndex),
372
- c
367
+ const l = r.type === "line" ? M(
368
+ i.get(r.lineId),
369
+ r.startOffset + f
370
+ ) : w(
371
+ o.get(r.curveIndex),
372
+ f
373
373
  );
374
374
  return {
375
375
  axleState: { ...t, ...l },
376
- execution: { ...e, segmentDistance: c },
376
+ execution: { ...e, segmentDistance: f },
377
377
  completed: !1
378
378
  };
379
379
  }
380
- function Y(t, e, s, n) {
381
- const r = /* @__PURE__ */ new Map();
380
+ function Y(t, e, n, s) {
381
+ const i = /* @__PURE__ */ new Map();
382
382
  for (const o of t.segments)
383
383
  if (o.type === "curve" && o.curveIndex !== void 0) {
384
384
  const a = e[o.curveIndex];
385
385
  if (a) {
386
- const i = s.get(a.fromLineId), c = s.get(a.toLineId);
387
- if (i && c) {
386
+ const r = n.get(a.fromLineId), f = n.get(a.toLineId);
387
+ if (r && f) {
388
388
  const l = q(
389
- i,
389
+ r,
390
390
  a.fromOffset,
391
391
  a.fromIsPercentage,
392
392
  1,
393
393
  // Default: 100% = 1.0
394
- n.maxWheelbase
395
- ), f = E(
396
- c,
394
+ s.maxWheelbase
395
+ ), c = E(
396
+ f,
397
397
  a.toOffset,
398
398
  a.toIsPercentage,
399
399
  0,
400
- n.maxWheelbase
401
- ), g = z(
402
- i,
403
- c,
404
- n,
400
+ s.maxWheelbase
401
+ ), g = W(
402
+ r,
403
+ f,
404
+ s,
405
405
  !1,
406
406
  // willFlip is always false now
407
407
  {
408
408
  fromOffset: l,
409
409
  fromIsPercentage: !1,
410
410
  // Already resolved to absolute
411
- toOffset: f,
411
+ toOffset: c,
412
412
  toIsPercentage: !1
413
413
  // Already resolved to absolute
414
414
  }
415
415
  ), d = N(g);
416
- r.set(o.curveIndex, { bezier: g, arcLengthTable: d });
416
+ i.set(o.curveIndex, { bezier: g, arcLengthTable: d });
417
417
  }
418
418
  }
419
419
  }
420
- return r;
421
- }
422
- function Z(t, e, s) {
423
- const { graph: n, linesMap: r, curves: o, config: a } = s, i = r.get(e.targetLineId);
424
- if (!i) return null;
425
- const c = t.axleSpacings.reduce((u, v) => u + v, 0), f = O(i) - c;
426
- if (f <= 0) return null;
427
- const g = e.isPercentage ? e.targetOffset * f : Math.min(e.targetOffset, f), d = t.axles[t.axles.length - 1], h = G(
428
- n,
420
+ return i;
421
+ }
422
+ function Z(t, e, n) {
423
+ const { graph: s, linesMap: i, curves: o, config: a } = n, r = i.get(e.targetLineId);
424
+ 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,
429
429
  { lineId: d.lineId, offset: d.absoluteOffset },
430
430
  e.targetLineId,
431
431
  g,
432
432
  !1
433
433
  );
434
434
  if (!h) return null;
435
- const p = Y(h, o, r, a);
435
+ const p = Y(h, o, i, a);
436
436
  return { path: h, curveDataMap: p };
437
437
  }
438
438
  function oe(t, e) {
439
- const s = t.execution, r = e.vehicleQueues.get(t.vehicle.id)?.[s.currentCommandIndex];
440
- return r && e.onCommandComplete && e.onCommandComplete({
439
+ const n = t.execution, i = e.vehicleQueues.get(t.vehicle.id)?.[n.currentCommandIndex];
440
+ return i && e.onCommandComplete && e.onCommandComplete({
441
441
  vehicleId: t.vehicle.id,
442
- command: r,
442
+ command: i,
443
443
  finalPosition: {
444
444
  lineId: t.vehicle.axles[t.vehicle.axles.length - 1].lineId,
445
445
  absoluteOffset: t.vehicle.axles[t.vehicle.axles.length - 1].absoluteOffset,
446
446
  position: t.vehicle.axles[t.vehicle.axles.length - 1].position
447
447
  },
448
- payload: r.payload
448
+ payload: i.payload
449
449
  }), {
450
450
  handled: !0,
451
451
  vehicle: { ...t.vehicle, state: "waiting" },
452
- newExecution: s,
452
+ newExecution: n,
453
453
  // Keep execution state for resume
454
454
  isWaiting: !0
455
455
  };
456
456
  }
457
- function ee(t, e, s, n, r, o) {
457
+ function ee(t, e, n, s, i, o) {
458
458
  let a;
459
- const i = e[0];
460
- if (i.currentSegmentIndex < s.segments.length) {
461
- const l = s.segments[i.currentSegmentIndex];
459
+ const r = e[0];
460
+ if (r.currentSegmentIndex < n.segments.length) {
461
+ const l = n.segments[r.currentSegmentIndex];
462
462
  if (l.type === "line") {
463
- const f = r.get(l.lineId);
464
- f && (a = O(f));
463
+ const c = i.get(l.lineId);
464
+ c && (a = O(c));
465
465
  }
466
466
  }
467
- const c = t.map((l, f) => {
468
- const g = f === 0 ? a : void 0;
469
- return X(l, e[f], s, n, r, o, g);
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);
470
470
  });
471
471
  return {
472
- axles: c.map((l) => l.axleState),
473
- axleExecutions: c.map((l) => l.execution),
474
- arrived: c[c.length - 1].completed
472
+ axles: f.map((l) => l.axleState),
473
+ axleExecutions: f.map((l) => l.execution),
474
+ arrived: f[f.length - 1].completed
475
475
  // axles[N-1] = rearmost menentukan arrived
476
476
  };
477
477
  }
@@ -504,11 +504,11 @@ class ae {
504
504
  /**
505
505
  * Replace the entire scene and rebuild the graph.
506
506
  */
507
- setScene(e, s) {
507
+ setScene(e, n) {
508
508
  this.linesMap.clear();
509
- for (const n of e)
510
- this.linesMap.set(n.id, n);
511
- this.curves = s, this.graph = I(e, s, this.config);
509
+ for (const s of e)
510
+ this.linesMap.set(s.id, s);
511
+ this.curves = n, this.graph = I(e, n, this.config);
512
512
  }
513
513
  /**
514
514
  * Add a single line. Returns false if a line with the same ID already exists.
@@ -519,36 +519,36 @@ class ae {
519
519
  /**
520
520
  * Update start and/or end coordinates of an existing line.
521
521
  */
522
- updateLine(e, s) {
523
- const n = this.linesMap.get(e);
524
- 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;
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;
525
525
  }
526
526
  /**
527
527
  * Update a single endpoint ('start' or 'end') of a line.
528
528
  */
529
- updateLineEndpoint(e, s, n) {
530
- return this.updateLine(e, { [s]: n });
529
+ updateLineEndpoint(e, n, s) {
530
+ return this.updateLine(e, { [n]: s });
531
531
  }
532
532
  /**
533
533
  * Rename a line ID and cascade the change to all connected curves.
534
534
  */
535
- renameLine(e, s) {
536
- const n = s.trim();
537
- if (!n) return { success: !1, error: "Name cannot be empty" };
538
- if (n === e) return { success: !0 };
539
- if (this.linesMap.has(n)) return { success: !1, error: `"${n}" already exists` };
540
- const r = this.linesMap.get(e);
541
- if (!r) return { success: !1, error: `Line "${e}" not found` };
542
- r.id = n, this.linesMap.delete(e), this.linesMap.set(n, r);
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` };
540
+ const i = this.linesMap.get(e);
541
+ if (!i) return { success: !1, error: `Line "${e}" not found` };
542
+ i.id = s, this.linesMap.delete(e), this.linesMap.set(s, i);
543
543
  for (const o of this.curves)
544
- o.fromLineId === e && (o.fromLineId = n), o.toLineId === e && (o.toLineId = n);
544
+ o.fromLineId === e && (o.fromLineId = s), o.toLineId === e && (o.toLineId = s);
545
545
  return this.graph = I(Array.from(this.linesMap.values()), this.curves, this.config), { success: !0 };
546
546
  }
547
547
  /**
548
548
  * Remove a line and all curves connected to it.
549
549
  */
550
550
  removeLine(e) {
551
- 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;
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;
552
552
  }
553
553
  /**
554
554
  * Add a directional curve (connection) from one line to another.
@@ -559,8 +559,8 @@ class ae {
559
559
  /**
560
560
  * Update a curve by index. Returns false if index is out of bounds.
561
561
  */
562
- updateCurve(e, s) {
563
- 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);
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);
564
564
  }
565
565
  /**
566
566
  * Remove a curve by index. Returns false if index is out of bounds.
@@ -576,16 +576,20 @@ class ae {
576
576
  *
577
577
  * @param lineId - The line to place the vehicle on
578
578
  * @param rearOffset - Absolute distance offset untuk axle paling belakang
579
- * @param axleSpacings - Jarak antar axle berurutan (N-1 nilai untuk N axle)
579
+ * @param vehicle - VehicleDefinition (or any object extending it with axleSpacings)
580
580
  * @returns Initial VehiclePathState, or null if lineId does not exist
581
+ * @throws if axleSpacings is empty
581
582
  */
582
- initializeVehicle(e, s, n) {
583
- const r = this.linesMap.get(e);
584
- if (!r) return null;
585
- const o = n.reduce((l, f) => l + f, 0), a = O(r), i = Math.min(s, a - o);
583
+ initializeVehicle(e, n, s) {
584
+ const i = this.linesMap.get(e);
585
+ if (!i) return null;
586
+ const { axleSpacings: o } = s;
587
+ if (o.length === 0)
588
+ 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);
586
590
  return {
587
- axles: H(e, i, n, r).map((l) => ({ lineId: l.lineId, offset: l.absoluteOffset, position: l.position })),
588
- axleSpacings: n
591
+ axles: H(e, f, o, i).map((c) => ({ lineId: c.lineId, offset: c.absoluteOffset, position: c.position })),
592
+ axleSpacings: o
589
593
  };
590
594
  }
591
595
  /**
@@ -598,9 +602,9 @@ class ae {
598
602
  * @param targetOffset - Position on the target line
599
603
  * @param isPercentage - If true, targetOffset is 0-1 fraction; if false, absolute distance
600
604
  */
601
- preparePath(e, s, n, r = !1) {
605
+ preparePath(e, n, s, i = !1) {
602
606
  if (!this.graph) return null;
603
- const o = e.axleSpacings.reduce((h, p) => h + p, 0), a = e.axles[e.axles.length - 1], i = {
607
+ const o = e.axleSpacings.reduce((h, p) => h + p, 0), a = e.axles[e.axles.length - 1], r = {
604
608
  lineId: a.lineId,
605
609
  offset: a.offset,
606
610
  axles: e.axles.map((h) => ({
@@ -609,22 +613,22 @@ class ae {
609
613
  absoluteOffset: h.offset
610
614
  })),
611
615
  axleSpacings: e.axleSpacings
612
- }, c = Z(i, {
613
- targetLineId: s,
614
- targetOffset: n,
615
- isPercentage: r
616
+ }, f = Z(r, {
617
+ targetLineId: n,
618
+ targetOffset: s,
619
+ isPercentage: i
616
620
  }, {
617
621
  graph: this.graph,
618
622
  linesMap: this.linesMap,
619
623
  curves: this.curves,
620
624
  config: this.config
621
625
  });
622
- if (!c) return null;
623
- let l = n;
624
- const f = this.linesMap.get(s);
625
- if (f) {
626
- const h = Math.max(0, O(f) - o);
627
- l = r ? n * h : Math.min(n, h);
626
+ 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);
628
632
  }
629
633
  let g = 0;
630
634
  const d = [
@@ -634,10 +638,10 @@ class ae {
634
638
  for (let h = 0; h < e.axleSpacings.length; h++)
635
639
  g += e.axleSpacings[h], d.push({ segmentIndex: 0, segmentDistance: o - g });
636
640
  return {
637
- path: c.path,
638
- curveDataMap: c.curveDataMap,
641
+ path: f.path,
642
+ curveDataMap: f.curveDataMap,
639
643
  axleExecutions: d,
640
- targetLineId: s,
644
+ targetLineId: n,
641
645
  targetOffset: l
642
646
  };
643
647
  }
@@ -651,25 +655,25 @@ class ae {
651
655
  * @param execution - Current path execution (from preparePath or previous tick)
652
656
  * @param distance - Distance to advance this tick (speed × deltaTime)
653
657
  */
654
- moveVehicle(e, s, n) {
655
- const r = e.axles.map((i) => ({
656
- lineId: i.lineId,
657
- position: i.position,
658
- absoluteOffset: i.offset
659
- })), o = s.axleExecutions.map((i) => ({
660
- currentSegmentIndex: i.segmentIndex,
661
- segmentDistance: i.segmentDistance
662
- })), a = ee(r, o, s.path, n, this.linesMap, s.curveDataMap);
658
+ moveVehicle(e, n, s) {
659
+ const i = e.axles.map((r) => ({
660
+ lineId: r.lineId,
661
+ position: r.position,
662
+ absoluteOffset: r.offset
663
+ })), o = n.axleExecutions.map((r) => ({
664
+ currentSegmentIndex: r.segmentIndex,
665
+ segmentDistance: r.segmentDistance
666
+ })), a = ee(i, o, n.path, s, this.linesMap, n.curveDataMap);
663
667
  return {
664
668
  state: {
665
- axles: a.axles.map((i) => ({ lineId: i.lineId, offset: i.absoluteOffset, position: i.position })),
669
+ axles: a.axles.map((r) => ({ lineId: r.lineId, offset: r.absoluteOffset, position: r.position })),
666
670
  axleSpacings: e.axleSpacings
667
671
  },
668
672
  execution: {
669
- ...s,
670
- axleExecutions: a.axleExecutions.map((i) => ({
671
- segmentIndex: i.currentSegmentIndex,
672
- segmentDistance: i.segmentDistance
673
+ ...n,
674
+ axleExecutions: a.axleExecutions.map((r) => ({
675
+ segmentIndex: r.currentSegmentIndex,
676
+ segmentDistance: r.segmentDistance
673
677
  }))
674
678
  },
675
679
  arrived: a.arrived
@@ -677,7 +681,7 @@ class ae {
677
681
  }
678
682
  }
679
683
  export {
680
- w as A,
684
+ S as A,
681
685
  Z as B,
682
686
  q as C,
683
687
  E as D,
@@ -687,13 +691,13 @@ export {
687
691
  N as b,
688
692
  I as c,
689
693
  F as d,
690
- re as e,
694
+ ie as e,
691
695
  H as f,
692
696
  O as g,
693
- S as h,
697
+ w as h,
694
698
  M as i,
695
699
  k as j,
696
- z as k,
700
+ W as k,
697
701
  U as l,
698
702
  y as m,
699
703
  _ as n,
@@ -705,7 +709,7 @@ export {
705
709
  V as t,
706
710
  A as u,
707
711
  oe as v,
708
- ie as w,
712
+ re as w,
709
713
  J as x,
710
714
  ne as y,
711
715
  ee as z
@@ -0,0 +1 @@
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;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-BUYdltrL.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-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,4 +1,4 @@
1
- import { P as i, a as t, b as s, c as n, d as o, e as l, f as r, h as c, i as g, k as h, l as P, m as u, n as L, o as f, p as m, q as v, g as A, r as d, s as O, t as z, u as p, v as x, w as B, x as C, z as T, A as b, B as F, C as V, D as E, E as I } from "./index-wjEuFiRl.js";
1
+ import { P as i, a as t, b as s, c as n, d as o, e as l, f as r, h as c, i as g, k as h, l as P, m as u, n as L, o as f, p as m, q as v, g as A, r as d, s as O, t as z, u as p, v as x, w as B, x as C, z as T, A as b, B as F, C as V, D as E, E as I } from "./index-BV93143R.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": "2.4.0",
3
+ "version": "3.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 s=e.x-t.x,n=e.y-t.y;return Math.sqrt(s*s+n*n)}function D(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 E(t,e){return e*(t==="proportional-40"?.4:.5522)}function V(t,e,s,n=!1,i){const{maxWheelbase:o,tangentMode:c}=s;let r;i?.fromOffset!==void 0?r=b(t,i.fromOffset,i.fromIsPercentage??!1):r=t.end;let a;i?.toOffset!==void 0?a=b(e,i.toOffset,i.toIsPercentage??!1):a=e.start;const l=D(t.start,t.end),u=n?{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(u,a),p=E(c,h),f=n?{x:u.x-g.x*p,y:u.y-g.y*p}:{x:u.x+g.x*p,y:u.y+g.y*p},v={x:a.x-d.x*p,y:a.y-d.y*p};return{p0:u,p1:f,p2:v,p3:a}}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,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)),F(t,i)}function T(t,e){const{p0:s,p1:n,p2:i,p3:o}=t,c=1-e,r=c*c,a=r*c,l=e*e,u=l*e;return{x:a*s.x+3*r*e*n.x+3*c*l*i.x+u*o.x,y:a*s.y+3*r*e*n.y+3*c*l*i.y+u*o.y}}function ee(t,e,s=10){return L(t,e)<=s}function N(t,e=100){const s=[{t:0,distance:0}];let n=t.p0,i=0;for(let o=1;o<=e;o++){const c=o/e,r=T(t,c);i+=L(n,r),s.push({t:c,distance:i}),n=r}return s}function $(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 u=Math.floor((n+i)/2);t[u].distance<e?n=u:i=u}const o=t[n].distance,c=t[i].distance,r=t[n].t,a=t[i].t;if(c===o)return r;const l=(e-o)/(c-o);return r+l*(a-r)}function te(t){return t[t.length-1].distance}function j(t,e=100){let s=0,n=t.p0;for(let i=1;i<=e;i++){const o=i/e,c=T(t,o);s+=L(n,c),n=c}return s}function z(t,e,s,n,i){const o=L(t.start,t.end);return e===void 0?n*o:s?Math.max(0,Math.min(e,1))*o:Math.max(0,Math.min(e,o))}function W(t,e,s,n,i){const o=L(t.start,t.end);return e===void 0?n*o:s?Math.max(0,Math.min(e,1))*o:Math.max(0,Math.min(e,o))}function x(t,e,s){const n=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)),n.set(c.id,[]);for(let c=0;c<e.length;c++){const r=e[c],a=i.get(r.fromLineId),l=i.get(r.toLineId);if(!a||!l)continue;const u=z(a,r.fromOffset,r.fromIsPercentage,1,s.maxWheelbase),g=W(l,r.toOffset,r.toIsPercentage,0,s.maxWheelbase),d=V(a,l,s,!1,{fromOffset:u,fromIsPercentage:!1,toOffset:g,toIsPercentage:!1}),h=j(d),p={curveIndex:c,fromLineId:r.fromLineId,toLineId:r.toLineId,fromOffset:u,toOffset:g,curveLength:h};n.get(r.fromLineId).push(p)}return{adjacency:n,lines:i,lineLengths:o}}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:o,lines:c,lineLengths:r}=t;if(!c.get(s))return null;const l=r.get(s),u=i?n/100*l:n,g=[],d=new Map,h=(f,v)=>`${f}:${Math.round(v)}`;if(e.lineId===s&&u>=e.offset){const f=u-e.offset;return{segments:[{type:"line",lineId:e.lineId,startOffset:e.offset,endOffset:u,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(q);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===s){const m=Math.abs(u-f.entryOffset);if(u>=f.entryOffset){const P={type:"line",lineId:s,startOffset:f.entryOffset,endOffset:u,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,w=f.curveCount+1,X=h(m.toLineId,m.toOffset),C=d.get(X);if(C!==void 0&&(C.curveCount<w||C.curveCount===w&&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:w,path:[...f.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 _(t,e,s){let n=0;for(let i=0;i<e;i++)n+=t.segments[i].length;return n+=s,n}function k(t,e){let s=0;for(let n=0;n<t.segments.length;n++){const i=t.segments[n],o=s+i.length;if(e<o)return{segmentIndex:n,segmentDistance:e-s};if(e===o)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 o=_(t,e,s)+n;return k(t,o)}function G(t,e,s,n){const i=M(n),o=s.length+1,c=new Array(o);c[o-1]={lineId:t,absoluteOffset:e,position:S(n,e)};let r=e;for(let a=o-2;a>=0;a--)r=Math.min(r+s[a],i),c[a]={lineId:t,absoluteOffset:r,position:S(n,r)};return c}function Q(t,e){return{...t,state:"idle"}}function R(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 c=Q(i);s.push(c);const r=R(c);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 A(t,e){const s=$(t.arcLengthTable,e);return{position:T(t.bezier,s)}}function H(t,e,s,n,i,o,c){const r=s.segments[e.currentSegmentIndex],a=e.segmentDistance+n;if(a>=r.length){const u=a-r.length,g=e.currentSegmentIndex+1;if(g>=s.segments.length){if(c!==void 0&&r.type==="line"){const f=i.get(r.lineId),v=r.startOffset+a;if(v<=c){const O=y(f,v);return{axleState:{...t,...O},execution:{...e,segmentDistance:a},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):A(o.get(r.curveIndex),r.length);return{axleState:{...t,...p},execution:{...e,segmentDistance:r.length},completed:!0}}const d=s.segments[g],h=d.type==="line"?y(i.get(d.lineId),d.startOffset+u):A(o.get(d.curveIndex),u);return{axleState:{...t,...h},execution:{currentSegmentIndex:g,segmentDistance:u},completed:!1}}const l=r.type==="line"?y(i.get(r.lineId),r.startOffset+a):A(o.get(r.curveIndex),a);return{axleState:{...t,...l},execution:{...e,segmentDistance:a},completed:!1}}function ie(t,e,s,n){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=s.get(c.fromLineId),a=s.get(c.toLineId);if(r&&a){const l=z(r,c.fromOffset,c.fromIsPercentage,1,n.maxWheelbase),u=W(a,c.toOffset,c.toIsPercentage,0,n.maxWheelbase),g=V(r,a,n,!1,{fromOffset:l,fromIsPercentage:!1,toOffset:u,toIsPercentage:!1}),d=N(g);i.set(o.curveIndex,{bezier:g,arcLengthTable:d})}}}return i}function J(t,e,s){const{graph:n,linesMap:i,curves:o,config:c}=s,r=i.get(e.targetLineId);if(!r)return null;const a=t.axleSpacings.reduce((f,v)=>f+v,0),u=M(r)-a;if(u<=0)return null;const g=e.isPercentage?e.targetOffset*u:Math.min(e.targetOffset,u),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 p=ie(h,o,i,c);return{path:h,curveDataMap:p}}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,o){let c;const r=e[0];if(r.currentSegmentIndex<s.segments.length){const l=s.segments[r.currentSegmentIndex];if(l.type==="line"){const u=i.get(l.lineId);u&&(c=M(u))}}const a=t.map((l,u)=>{const g=u===0?c:void 0;return H(l,e[u],s,n,i,o,g)});return{axles:a.map(l=>l.axleState),axleExecutions:a.map(l=>l.execution),arrived:a[a.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,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 o of this.curves)o.fromLineId===e&&(o.fromLineId=n),o.toLineId===e&&(o.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 o=n.reduce((l,u)=>l+u,0),c=M(i),r=Math.min(s,c-o);return{axles:G(e,r,n,i).map(l=>({lineId:l.lineId,offset:l.absoluteOffset,position:l.position})),axleSpacings:n}}preparePath(e,s,n,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},a=J(r,{targetLineId:s,targetOffset:n,isPercentage:i},{graph:this.graph,linesMap:this.linesMap,curves:this.curves,config:this.config});if(!a)return null;let l=n;const u=this.linesMap.get(s);if(u){const h=Math.max(0,M(u)-o);l=i?n*h:Math.min(n,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:a.path,curveDataMap:a.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})),o=s.axleExecutions.map(r=>({currentSegmentIndex:r.segmentIndex,segmentDistance:r.segmentDistance})),c=U(i,o,s.path,n,this.linesMap,s.curveDataMap);return{state:{axles:c.axles.map(r=>({lineId:r.lineId,offset:r.absoluteOffset,position:r.position})),axleSpacings:e.axleSpacings},execution:{...s,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=A;exports.calculatePositionOnLine=y;exports.calculateTangentLength=E;exports.createBezierCurve=V;exports.createInitialMovementState=R;exports.distance=L;exports.distanceToT=$;exports.findPath=K;exports.getArcLength=te;exports.getCumulativeArcLength=_;exports.getLineLength=M;exports.getPointOnBezier=T;exports.getPointOnLine=F;exports.getPointOnLineByOffset=b;exports.getPositionFromOffset=S;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;