vehicle-path2 1.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.
Files changed (42) hide show
  1. package/README.md +160 -0
  2. package/dist/animation-loop-bZEm2pMN.js +37 -0
  3. package/dist/animation-loop-fC2LjxCd.cjs +1 -0
  4. package/dist/core/algorithms/math.d.ts +35 -0
  5. package/dist/core/algorithms/pathFinding.d.ts +62 -0
  6. package/dist/core/algorithms/vehicleMovement.d.ts +174 -0
  7. package/dist/core/index.d.ts +20 -0
  8. package/dist/core/types/api.d.ts +185 -0
  9. package/dist/core/types/config.d.ts +9 -0
  10. package/dist/core/types/geometry.d.ts +26 -0
  11. package/dist/core/types/movement.d.ts +56 -0
  12. package/dist/core/types/vehicle.d.ts +65 -0
  13. package/dist/core.cjs +1 -0
  14. package/dist/core.js +551 -0
  15. package/dist/index.d.ts +45 -0
  16. package/dist/react/dsl-hooks/useInitialMovement.d.ts +24 -0
  17. package/dist/react/dsl-hooks/useMovementSequence.d.ts +27 -0
  18. package/dist/react/dsl-hooks/useSceneDefinition.d.ts +22 -0
  19. package/dist/react/hooks/useAnimation.d.ts +43 -0
  20. package/dist/react/hooks/useMovementQueue.d.ts +52 -0
  21. package/dist/react/hooks/useScene.d.ts +78 -0
  22. package/dist/react/hooks/useVehicleSimulation.d.ts +126 -0
  23. package/dist/react/hooks/useVehicles.d.ts +55 -0
  24. package/dist/react/index.d.ts +48 -0
  25. package/dist/react/providers/useVehicleEvents.d.ts +78 -0
  26. package/dist/react.cjs +1 -0
  27. package/dist/react.js +18 -0
  28. package/dist/useVehicleEvents-B2JQFNjc.js +923 -0
  29. package/dist/useVehicleEvents-CBymulau.cjs +3 -0
  30. package/dist/utils/animation-loop.d.ts +105 -0
  31. package/dist/utils/dsl-parser.d.ts +152 -0
  32. package/dist/utils/event-emitter.d.ts +94 -0
  33. package/dist/utils/index.d.ts +15 -0
  34. package/dist/utils/type-converters.d.ts +38 -0
  35. package/dist/utils/vehicle-helpers.d.ts +8 -0
  36. package/dist/utils.cjs +1 -0
  37. package/dist/utils.js +17 -0
  38. package/dist/vehicle-helpers-DIcksrtO.cjs +7 -0
  39. package/dist/vehicle-helpers-_72KxCqO.js +276 -0
  40. package/dist/vehicle-path.cjs +1 -0
  41. package/dist/vehicle-path.js +62 -0
  42. package/package.json +103 -0
package/README.md ADDED
@@ -0,0 +1,160 @@
1
+ # vehicle-path2
2
+
3
+ Library untuk simulasi pergerakan kendaraan dual-axle sepanjang jalur.
4
+
5
+ ## Instalasi
6
+
7
+ ```bash
8
+ npm install vehicle-path2
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```tsx
14
+ import { useVehicleSimulation } from 'vehicle-path2/react'
15
+
16
+ function App() {
17
+ const sim = useVehicleSimulation({ wheelbase: 30 })
18
+
19
+ // Buat jalur
20
+ sim.addLine({ id: 'line1', start: [0, 0], end: [400, 0] })
21
+ sim.addLine({ id: 'line2', start: [400, 0], end: [400, 300] })
22
+ sim.connect('line1', 'line2')
23
+
24
+ // Tambah kendaraan
25
+ sim.addVehicles({ id: 'v1', lineId: 'line1', position: 0 })
26
+
27
+ // Gerakkan ke tujuan
28
+ sim.goto({ id: 'v1', lineId: 'line2', position: 1.0 })
29
+
30
+ // Jalankan animasi
31
+ sim.prepare()
32
+ sim.tick(5) // panggil di animation loop
33
+ }
34
+ ```
35
+
36
+ ## API
37
+
38
+ ### Setup
39
+
40
+ ```ts
41
+ const sim = useVehicleSimulation({
42
+ wheelbase: 30, // jarak antar roda
43
+ tangentMode: 'proportional-40' // mode kurva (opsional)
44
+ })
45
+ ```
46
+
47
+ ### Scene
48
+
49
+ ```ts
50
+ sim.addLine({ id: 'line1', start: [0, 0], end: [400, 0] })
51
+ sim.updateLine('line1', { end: [500, 100] })
52
+ sim.removeLine('line1')
53
+ sim.clearScene()
54
+ ```
55
+
56
+ ### Koneksi
57
+
58
+ ```ts
59
+ sim.connect('line1', 'line2')
60
+ sim.connect('line1', 'line2', { fromOffset: 0.8, toOffset: 0.2 })
61
+ sim.connect('line1', 'line2', { fromOffset: 150, fromIsPercentage: false, toOffset: 50, toIsPercentage: false })
62
+ sim.updateConnection('line1', 'line2', { fromOffset: 0.5 }) // update offset
63
+ sim.updateConnection('line1', 'line2', { toOffset: 100, toIsPercentage: false }) // absolute
64
+ sim.disconnect('line1', 'line2')
65
+ ```
66
+
67
+ ### Kendaraan
68
+
69
+ ```ts
70
+ sim.addVehicles({ id: 'v1', lineId: 'line1', position: 0 })
71
+ sim.addVehicles({ id: 'v2', lineId: 'line1', position: 150, isPercentage: false }) // absolute
72
+ sim.updateVehicle('v1', { position: 0.5 }) // pindah ke 50%
73
+ sim.updateVehicle('v1', { lineId: 'line2' }) // pindah ke line lain
74
+ sim.updateVehicle('v1', { lineId: 'line2', position: 0.8 }) // pindah ke 80% di line2
75
+ sim.removeVehicle('v1')
76
+ sim.clearVehicles()
77
+ ```
78
+
79
+ ### Pergerakan
80
+
81
+ ```ts
82
+ sim.goto({ id: 'v1', lineId: 'line2' }) // default position = 1.0 (ujung)
83
+ sim.goto({ id: 'v1', lineId: 'line2', position: 0.5 }) // 0.5 = tengah line
84
+ sim.goto({ id: 'v1', lineId: 'line2', position: 150, isPercentage: false }) // absolute
85
+ sim.goto({ id: 'v1', lineId: 'line2', position: 0.5, wait: true }) // berhenti di tujuan
86
+ sim.goto({ id: 'v1', lineId: 'line2', payload: { orderId: '123' } }) // dengan payload
87
+ sim.clearQueue('v1')
88
+ ```
89
+
90
+ ### Animasi
91
+
92
+ ```ts
93
+ sim.prepare() // siapkan sebelum animasi
94
+ sim.tick(5) // gerakkan 5 pixel per tick
95
+ sim.reset() // kembali ke posisi awal
96
+ sim.isMoving() // cek ada yang bergerak
97
+ sim.continueVehicle('v1') // lanjutkan vehicle yang wait
98
+ ```
99
+
100
+ ### Load dari DSL
101
+
102
+ ```ts
103
+ sim.loadFromDSL(`
104
+ line1 : (0, 0) -> (400, 0)
105
+ line2 : (400, 0) -> (400, 300)
106
+ line1 -> line2
107
+ `)
108
+ ```
109
+
110
+ ### State
111
+
112
+ ```ts
113
+ sim.lines // semua line
114
+ sim.curves // semua koneksi
115
+ sim.vehicles // kendaraan (posisi awal)
116
+ sim.movingVehicles // kendaraan (posisi saat animasi)
117
+ ```
118
+
119
+ ## Contoh Lengkap
120
+
121
+ ```tsx
122
+ import { useVehicleSimulation } from 'vehicle-path2/react'
123
+ import { useEffect } from 'react'
124
+
125
+ function AnimatedVehicle() {
126
+ const sim = useVehicleSimulation({ wheelbase: 30 })
127
+
128
+ useEffect(() => {
129
+ sim.addLine({ id: 'line1', start: [100, 100], end: [500, 100] })
130
+ sim.addVehicles({ id: 'v1', lineId: 'line1', position: 0 })
131
+ sim.goto({ id: 'v1', lineId: 'line1', position: 1.0 })
132
+ sim.prepare()
133
+
134
+ const animate = () => {
135
+ if (sim.tick(3)) {
136
+ requestAnimationFrame(animate)
137
+ }
138
+ }
139
+ requestAnimationFrame(animate)
140
+ }, [])
141
+
142
+ return (
143
+ <svg width={600} height={200}>
144
+ {sim.movingVehicles.map(v => (
145
+ <circle
146
+ key={v.id}
147
+ cx={v.rear.position.x}
148
+ cy={v.rear.position.y}
149
+ r={10}
150
+ fill="blue"
151
+ />
152
+ ))}
153
+ </svg>
154
+ )
155
+ }
156
+ ```
157
+
158
+ ## License
159
+
160
+ MIT
@@ -0,0 +1,37 @@
1
+ import { useRef as p, useEffect as d } from "react";
2
+ function A(o) {
3
+ const { onTick: t, onComplete: a, onStart: i, onPause: c, onStop: f } = o;
4
+ let n = null, u = null, e = !1, l = !1;
5
+ const s = (r) => {
6
+ if (!e) return;
7
+ const m = u !== null ? r - u : 0;
8
+ if (u = r, t(m) === !1) {
9
+ e = !1, n = null, u = null, a?.();
10
+ return;
11
+ }
12
+ n = requestAnimationFrame(s);
13
+ };
14
+ return {
15
+ start: () => {
16
+ e || (e = !0, l = !1, u = null, i?.(), n = requestAnimationFrame(s));
17
+ },
18
+ pause: () => {
19
+ !e || l || (e = !1, l = !0, n !== null && (cancelAnimationFrame(n), n = null), c?.());
20
+ },
21
+ stop: () => {
22
+ e = !1, l = !1, u = null, n !== null && (cancelAnimationFrame(n), n = null), f?.();
23
+ },
24
+ isRunning: () => e,
25
+ isPaused: () => l
26
+ };
27
+ }
28
+ function q(o) {
29
+ const t = p(null);
30
+ return t.current || (t.current = A(o)), d(() => () => {
31
+ t.current?.stop();
32
+ }, []), t.current;
33
+ }
34
+ export {
35
+ A as c,
36
+ q as u
37
+ };
@@ -0,0 +1 @@
1
+ "use strict";const i=require("react");function a(s){const{onTick:t,onComplete:c,onStart:f,onPause:m,onStop:p}=s;let n=null,o=null,e=!1,u=!1;const l=r=>{if(!e)return;const A=o!==null?r-o:0;if(o=r,t(A)===!1){e=!1,n=null,o=null,c?.();return}n=requestAnimationFrame(l)};return{start:()=>{e||(e=!0,u=!1,o=null,f?.(),n=requestAnimationFrame(l))},pause:()=>{!e||u||(e=!1,u=!0,n!==null&&(cancelAnimationFrame(n),n=null),m?.())},stop:()=>{e=!1,u=!1,o=null,n!==null&&(cancelAnimationFrame(n),n=null),p?.()},isRunning:()=>e,isPaused:()=>u}}function d(s){const t=i.useRef(null);return t.current||(t.current=a(s)),i.useEffect(()=>()=>{t.current?.stop()},[]),t.current}exports.createAnimationLoop=a;exports.useAnimationLoop=d;
@@ -0,0 +1,35 @@
1
+ import type { Point, Line, BezierCurve } from '../types/geometry';
2
+ import type { TangentMode } from '../types/config';
3
+ import type { MovementConfig } from '../types/movement';
4
+ export declare function distance(p1: Point, p2: Point): number;
5
+ export declare function normalize(p1: Point, p2: Point): Point;
6
+ export declare function calculateTangentLength(mode: TangentMode, distance: number): number;
7
+ export interface CurveOffsetOptions {
8
+ fromOffset?: number;
9
+ fromIsPercentage?: boolean;
10
+ toOffset?: number;
11
+ toIsPercentage?: boolean;
12
+ }
13
+ export declare function createBezierCurve(line: Line, nextLine: Line, config: MovementConfig, willFlip?: boolean, offsetOptions?: CurveOffsetOptions): BezierCurve;
14
+ export declare function getPointOnLine(line: Line, t: number): Point;
15
+ export declare function getPointOnLineByOffset(line: Line, offset: number, isPercentage: boolean): Point;
16
+ export declare function getPointOnBezier(bezier: BezierCurve, t: number): Point;
17
+ export declare function isPointNearPoint(p1: Point, p2: Point, threshold?: number): boolean;
18
+ export interface ArcLengthEntry {
19
+ t: number;
20
+ distance: number;
21
+ }
22
+ /**
23
+ * Build a lookup table for arc-length parameterization.
24
+ * Maps t values to cumulative distances along the curve.
25
+ */
26
+ export declare function buildArcLengthTable(bezier: BezierCurve, samples?: number): ArcLengthEntry[];
27
+ /**
28
+ * Convert a distance along the curve to the corresponding t parameter.
29
+ * Uses linear interpolation between table entries for smooth results.
30
+ */
31
+ export declare function distanceToT(table: ArcLengthEntry[], targetDistance: number): number;
32
+ /**
33
+ * Get the total arc length from a pre-built table
34
+ */
35
+ export declare function getArcLength(table: ArcLengthEntry[]): number;
@@ -0,0 +1,62 @@
1
+ import type { Line, Curve, BezierCurve } from '../types/geometry';
2
+ import type { MovementConfig } from '../types/movement';
3
+ export interface GraphEdge {
4
+ curveIndex: number;
5
+ fromLineId: string;
6
+ toLineId: string;
7
+ fromOffset: number;
8
+ toOffset: number;
9
+ curveLength: number;
10
+ }
11
+ export interface Graph {
12
+ adjacency: Map<string, GraphEdge[]>;
13
+ lines: Map<string, Line>;
14
+ lineLengths: Map<string, number>;
15
+ }
16
+ export interface PathSegment {
17
+ type: 'line' | 'curve';
18
+ lineId?: string;
19
+ curveIndex?: number;
20
+ startOffset: number;
21
+ endOffset: number;
22
+ length: number;
23
+ }
24
+ export interface PathResult {
25
+ segments: PathSegment[];
26
+ totalDistance: number;
27
+ }
28
+ export interface VehiclePosition {
29
+ lineId: string;
30
+ offset: number;
31
+ }
32
+ /**
33
+ * Menghitung arc length dari bezier curve menggunakan numerical integration
34
+ */
35
+ export declare function calculateBezierArcLength(bezier: BezierCurve, segments?: number): number;
36
+ /**
37
+ * Resolve offset untuk FROM line (garis asal kurva)
38
+ * - 0% → wheelbase (bukan 0, untuk memberi ruang vehicle)
39
+ * - 100% → lineLength (ujung garis)
40
+ *
41
+ * Effective range: [wheelbase, lineLength]
42
+ */
43
+ export declare function resolveFromLineOffset(line: Line, offset: number | undefined, isPercentage: boolean | undefined, defaultPercentage: number, wheelbase: number): number;
44
+ /**
45
+ * Resolve offset untuk TO line (garis tujuan kurva)
46
+ * - 0% → 0 (awal garis)
47
+ * - 100% → lineLength - wheelbase (untuk memberi ruang vehicle)
48
+ *
49
+ * Effective range: [0, lineLength - wheelbase]
50
+ */
51
+ export declare function resolveToLineOffset(line: Line, offset: number | undefined, isPercentage: boolean | undefined, defaultPercentage: number, wheelbase: number): number;
52
+ /**
53
+ * Membangun graph dari lines dan curves
54
+ */
55
+ export declare function buildGraph(lines: Line[], curves: Curve[], config: MovementConfig): Graph;
56
+ /**
57
+ * Mencari path terpendek dari posisi vehicle ke target
58
+ *
59
+ * @returns PathResult jika path ditemukan, null jika tidak ada path valid
60
+ */
61
+ export declare function findPath(graph: Graph, vehiclePos: VehiclePosition, targetLineId: string, targetOffset: number, // Absolute offset
62
+ targetIsPercentage?: boolean): PathResult | null;
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Vehicle Movement Module
3
+ *
4
+ * Handles dual-axle vehicle movement including:
5
+ * - Position calculations (line and curve)
6
+ * - Arc-length tracking for wheelbase
7
+ * - Path preparation and execution
8
+ * - Segment transitions
9
+ */
10
+ import type { Line, Point, Curve } from '../types/geometry';
11
+ import type { Vehicle, AxleState, GotoCommand, GotoCompletionCallback } from '../types/vehicle';
12
+ import type { VehicleMovementState, PathExecutionState, AxleExecutionState, CurveData, SceneContext, MovementConfig } from '../types/movement';
13
+ import type { PathResult } from './pathFinding';
14
+ import type { CommandStartInfo } from '../../utils/event-emitter';
15
+ export type { CurveData, PathExecutionState, VehicleMovementState } from '../types/movement';
16
+ /**
17
+ * Get position on line from absolute offset
18
+ * This is a pure function that converts absolute offset to Point coordinates
19
+ */
20
+ export declare function getPositionFromOffset(line: Line, absoluteOffset: number): Point;
21
+ /**
22
+ * Calculate line length
23
+ */
24
+ export declare function getLineLength(line: Line): number;
25
+ /**
26
+ * Calculate cumulative arc-length from start of path
27
+ *
28
+ * @param path - The path being followed
29
+ * @param segmentIndex - Current segment index
30
+ * @param segmentDistance - Distance along current segment
31
+ * @returns Total arc-length from path start
32
+ */
33
+ export declare function getCumulativeArcLength(path: PathResult, segmentIndex: number, segmentDistance: number): number;
34
+ /**
35
+ * Convert arc-length to segment position
36
+ *
37
+ * @param path - The path being followed
38
+ * @param targetArcLength - Target cumulative arc-length
39
+ * @returns Segment position or null if exceeds path length
40
+ */
41
+ export declare function arcLengthToSegmentPosition(path: PathResult, targetArcLength: number): {
42
+ segmentIndex: number;
43
+ segmentDistance: number;
44
+ } | null;
45
+ /**
46
+ * Calculate front axle position from rear position + wheelbase
47
+ *
48
+ * @param path - The path being followed
49
+ * @param rearSegmentIndex - Rear axle segment index
50
+ * @param rearSegmentDistance - Rear axle distance in segment
51
+ * @param wheelbase - Distance between front and rear axles
52
+ * @returns Front axle position or null if exceeds path
53
+ */
54
+ export declare function calculateFrontAxlePosition(path: PathResult, rearSegmentIndex: number, rearSegmentDistance: number, wheelbase: number): {
55
+ segmentIndex: number;
56
+ segmentDistance: number;
57
+ } | null;
58
+ /**
59
+ * Calculate initial front axle position from rear position
60
+ *
61
+ * @param rLineId - Rear axle line ID
62
+ * @param rAbsoluteOffset - Rear axle absolute offset on line
63
+ * @param wheelbase - Distance between front and rear axles
64
+ * @param line - The line the vehicle is on
65
+ * @returns Front axle state
66
+ */
67
+ export declare function calculateInitialFrontPosition(rLineId: string, rAbsoluteOffset: number, wheelbase: number, line: Line): AxleState;
68
+ /**
69
+ * Initialize Vehicle with runtime state for dual-axle
70
+ *
71
+ * @param vehicle - Vehicle to initialize (must have rear and front already populated)
72
+ * @param _line - The line (kept for compatibility)
73
+ * @returns Vehicle with state set to idle
74
+ */
75
+ export declare function initializeMovingVehicle(vehicle: Vehicle, _line: Line): Vehicle;
76
+ /**
77
+ * Create initial movement state for a vehicle
78
+ */
79
+ export declare function createInitialMovementState(vehicle: Vehicle): VehicleMovementState;
80
+ export interface InitializationResult {
81
+ movingVehicles: Vehicle[];
82
+ stateMap: Map<string, VehicleMovementState>;
83
+ }
84
+ /**
85
+ * Initialize all vehicles and their movement states
86
+ *
87
+ * @param vehicles - Array of vehicles to initialize
88
+ * @param linesMap - Map of line IDs to Line objects
89
+ * @returns InitializationResult with moving vehicles and state map
90
+ */
91
+ export declare function initializeAllVehicles(vehicles: Vehicle[], linesMap: Map<string, Line>): InitializationResult;
92
+ /**
93
+ * Calculate position on line (pure function)
94
+ *
95
+ * @param line - The line to calculate position on
96
+ * @param absoluteOffset - The offset along the line
97
+ * @returns Position data
98
+ */
99
+ export declare function calculatePositionOnLine(line: Line, absoluteOffset: number): {
100
+ position: Point;
101
+ lineId: string;
102
+ absoluteOffset: number;
103
+ };
104
+ /**
105
+ * Calculate position on curve (pure function)
106
+ *
107
+ * @param curveData - The curve data with arc-length table
108
+ * @param segmentDistance - Distance along the curve
109
+ * @returns Position data
110
+ */
111
+ export declare function calculatePositionOnCurve(curveData: CurveData, segmentDistance: number): {
112
+ position: Point;
113
+ };
114
+ /**
115
+ * Update single axle position and handle segment transitions
116
+ *
117
+ * @param axleState - Current axle state
118
+ * @param axleExecution - Current execution state for this axle
119
+ * @param path - The path being followed
120
+ * @param velocity - Distance to move this frame
121
+ * @param linesMap - Map of line IDs to Line objects
122
+ * @param curveDataMap - Map of curve indices to curve data
123
+ * @param maxOffset - Optional max offset for extending beyond path (for front axle)
124
+ * @returns Updated axle state, execution state, and completion flag
125
+ */
126
+ export declare function updateAxlePosition(axleState: AxleState, axleExecution: AxleExecutionState, path: PathResult, velocity: number, linesMap: Map<string, Line>, curveDataMap: Map<number, CurveData>, maxOffset?: number): {
127
+ axleState: AxleState;
128
+ execution: AxleExecutionState;
129
+ completed: boolean;
130
+ };
131
+ export interface PreparedPath {
132
+ path: PathResult;
133
+ curveDataMap: Map<number, CurveData>;
134
+ }
135
+ /**
136
+ * Prepare path and curve data for a goto command
137
+ * Returns null if no path found
138
+ *
139
+ * @param vehicle - The vehicle to move
140
+ * @param command - The goto command with target
141
+ * @param ctx - Scene context with graph, linesMap, curves, and config
142
+ * @returns PreparedPath with path and curve data, or null if no path found
143
+ */
144
+ export declare function prepareCommandPath(vehicle: Vehicle, command: GotoCommand, ctx: SceneContext): PreparedPath | null;
145
+ type CommandStartCallback = (info: CommandStartInfo) => void;
146
+ export interface SegmentCompletionContext {
147
+ linesMap: Map<string, Line>;
148
+ config: MovementConfig;
149
+ vehicleQueues: Map<string, GotoCommand[]>;
150
+ curves: Curve[];
151
+ graphRef: {
152
+ current: ReturnType<typeof import('./pathFinding').buildGraph> | null;
153
+ };
154
+ prepareCommandPath: (vehicle: Vehicle, command: GotoCommand, ctx: SceneContext) => {
155
+ path: PathResult;
156
+ curveDataMap: Map<number, CurveData>;
157
+ } | null;
158
+ onCommandComplete?: GotoCompletionCallback;
159
+ onCommandStart?: CommandStartCallback;
160
+ }
161
+ export interface SegmentCompletionResult {
162
+ handled: boolean;
163
+ vehicle: Vehicle;
164
+ /** New execution state (null if completed or unchanged) */
165
+ newExecution?: PathExecutionState | null;
166
+ /** True if vehicle is waiting for confirmation to continue */
167
+ isWaiting?: boolean;
168
+ }
169
+ /**
170
+ * Handle arrival at destination - all segments completed (pure function)
171
+ * Checks for next command in queue and starts it, or marks vehicle as arrived
172
+ */
173
+ export declare function handleArrival(state: VehicleMovementState, ctx: SegmentCompletionContext): SegmentCompletionResult;
174
+ export type { VehicleMovementState as SegmentVehicleState };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Core Layer - Pure algorithms and types
3
+ *
4
+ * This layer contains the essential logic without any framework dependencies.
5
+ * Use this if you want to implement your own animation loop or React integration.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { buildGraph, findPath, distance } from 'vehicle-path/core'
10
+ * import type { Point, Line, Vehicle } from 'vehicle-path/core'
11
+ * ```
12
+ */
13
+ export type { Point, Line, BezierCurve, Curve } from './types/geometry';
14
+ export type { VehicleState, VehicleStart, Vehicle, AxleState, GotoCommand, GotoCompletionInfo, GotoCompletionCallback } from './types/vehicle';
15
+ export type { CurveData, PathExecutionState, VehicleMovementState, MovementConfig, SceneContext } from './types/movement';
16
+ export type { TangentMode } from './types/config';
17
+ export type { CoordinateInput, SceneLineInput, SceneConnectionInput, SceneConfig, VehicleInput, VehicleUpdateInput, ConnectionUpdateInput, GotoCommandInput } from './types/api';
18
+ export { buildGraph, findPath, calculateBezierArcLength, resolveFromLineOffset, resolveToLineOffset, type Graph, type GraphEdge, type PathSegment, type PathResult, type VehiclePosition } from './algorithms/pathFinding';
19
+ export { initializeMovingVehicle, createInitialMovementState, initializeAllVehicles, calculateInitialFrontPosition, type InitializationResult, updateAxlePosition, calculatePositionOnLine, calculatePositionOnCurve, calculateFrontAxlePosition, getCumulativeArcLength, arcLengthToSegmentPosition, prepareCommandPath, type PreparedPath, handleArrival, type SegmentCompletionContext, type SegmentCompletionResult, type SegmentVehicleState, getPositionFromOffset, getLineLength } from './algorithms/vehicleMovement';
20
+ export { distance, normalize, getPointOnLine, getPointOnLineByOffset, getPointOnBezier, createBezierCurve, buildArcLengthTable, distanceToT, getArcLength, calculateTangentLength, isPointNearPoint, type ArcLengthEntry, type CurveOffsetOptions } from './algorithms/math';
@@ -0,0 +1,185 @@
1
+ /**
2
+ * API Input Types
3
+ *
4
+ * These types define the simplified input format for the programmatic API.
5
+ * They are designed to be more ergonomic than the internal types.
6
+ */
7
+ /**
8
+ * Simple coordinate input - can be [x, y] tuple or {x, y} object
9
+ */
10
+ export type CoordinateInput = [number, number] | {
11
+ x: number;
12
+ y: number;
13
+ };
14
+ /**
15
+ * Line definition for Scene API
16
+ *
17
+ * @example
18
+ * { id: 'line001', start: [100, 100], end: [500, 100] }
19
+ * { id: 'line002', start: { x: 500, y: 100 }, end: { x: 500, y: 400 } }
20
+ */
21
+ export interface SceneLineInput {
22
+ id: string;
23
+ start: CoordinateInput;
24
+ end: CoordinateInput;
25
+ }
26
+ /**
27
+ * Connection (curve) definition for Scene API
28
+ *
29
+ * @example
30
+ * { from: 'line001', to: 'line002' }
31
+ * { from: 'line001', fromPosition: 0.8, to: 'line002', toPosition: 0.2 }
32
+ * { from: 'line001', fromPosition: 150, fromIsPercentage: false, to: 'line002', toPosition: 50, toIsPercentage: false }
33
+ */
34
+ export interface SceneConnectionInput {
35
+ from: string;
36
+ fromPosition?: number;
37
+ fromIsPercentage?: boolean;
38
+ to: string;
39
+ toPosition?: number;
40
+ toIsPercentage?: boolean;
41
+ }
42
+ /**
43
+ * Full scene configuration for setScene()
44
+ *
45
+ * @example
46
+ * setScene({
47
+ * lines: [
48
+ * { id: 'line001', start: [100, 100], end: [500, 100] },
49
+ * { id: 'line002', start: [500, 100], end: [500, 400] }
50
+ * ],
51
+ * connections: [
52
+ * { from: 'line001', to: 'line002' }
53
+ * ]
54
+ * })
55
+ */
56
+ export interface SceneConfig {
57
+ lines: SceneLineInput[];
58
+ connections?: SceneConnectionInput[];
59
+ }
60
+ /**
61
+ * Vehicle creation input for addVehicle()
62
+ *
63
+ * @example
64
+ * addVehicle({ id: 'v1', lineId: 'line001' }) // position defaults to 0 (start)
65
+ * addVehicle({ id: 'v2', lineId: 'line002', position: 0.5 }) // 50% of line
66
+ * addVehicle({ id: 'v3', lineId: 'line003', position: 150, isPercentage: false }) // absolute 150
67
+ */
68
+ export interface VehicleInput {
69
+ id: string;
70
+ lineId: string;
71
+ position?: number;
72
+ isPercentage?: boolean;
73
+ }
74
+ /**
75
+ * Vehicle update input for updateVehicle()
76
+ *
77
+ * @example
78
+ * updateVehicle('v1', { lineId: 'line002' }) // move to different line (keeps position 0)
79
+ * updateVehicle('v1', { position: 0.5 }) // move to 50% on current line
80
+ * updateVehicle('v1', { lineId: 'line002', position: 0.8 }) // move to 80% on line002
81
+ * updateVehicle('v1', { position: 150, isPercentage: false }) // move to absolute 150
82
+ */
83
+ export interface VehicleUpdateInput {
84
+ lineId?: string;
85
+ position?: number;
86
+ isPercentage?: boolean;
87
+ }
88
+ /**
89
+ * Connection update input for updateConnection()
90
+ *
91
+ * @example
92
+ * updateConnection('line001', 'line002', { fromOffset: 0.8 }) // change from offset to 80%
93
+ * updateConnection('line001', 'line002', { toOffset: 0.2 }) // change to offset to 20%
94
+ * updateConnection('line001', 'line002', { fromOffset: 150, fromIsPercentage: false }) // absolute offset
95
+ */
96
+ export interface ConnectionUpdateInput {
97
+ fromOffset?: number;
98
+ fromIsPercentage?: boolean;
99
+ toOffset?: number;
100
+ toIsPercentage?: boolean;
101
+ }
102
+ /**
103
+ * Simplified goto input for useVehicleSimulation.goto()
104
+ *
105
+ * @example
106
+ * goto({ id: 'v1', lineId: 'line002' }) // position defaults to 1.0 (end)
107
+ * goto({ id: 'v1', lineId: 'line002', position: 0.5 }) // 50% of line
108
+ * goto({ id: 'v1', lineId: 'line002', position: 150, isPercentage: false }) // absolute 150
109
+ * goto({ id: 'v1', lineId: 'line002', position: 0.5, wait: true }) // wait at destination
110
+ * goto({ id: 'v1', lineId: 'line002', payload: { orderId: '123' } }) // with payload
111
+ */
112
+ export interface GotoInput {
113
+ id: string;
114
+ lineId: string;
115
+ position?: number;
116
+ isPercentage?: boolean;
117
+ wait?: boolean;
118
+ payload?: unknown;
119
+ }
120
+ /**
121
+ * Input for goto/queueMovement commands (API-friendly version of GotoCommand)
122
+ *
123
+ * @example
124
+ * queueMovement('v1', { targetLineId: 'line002' }) // targetPosition defaults to 1.0 (end)
125
+ * queueMovement('v1', { targetLineId: 'line002', targetPosition: 0.5 }) // 50% of line
126
+ * queueMovement('v1', {
127
+ * targetLineId: 'line002',
128
+ * targetPosition: 0.5,
129
+ * wait: true,
130
+ * payload: { orderId: '123' }
131
+ * })
132
+ * queueMovement('v1', { targetLineId: 'line002', targetPosition: 150, isPercentage: false })
133
+ */
134
+ export interface GotoCommandInput {
135
+ targetLineId: string;
136
+ targetPosition?: number;
137
+ isPercentage?: boolean;
138
+ wait?: boolean;
139
+ payload?: unknown;
140
+ }
141
+ /**
142
+ * Movement command input for SimulationConfig
143
+ *
144
+ * @example
145
+ * { vehicleId: 'v1', targetLineId: 'line002' } // position defaults to 1.0 (end)
146
+ * { vehicleId: 'v1', targetLineId: 'line002', targetPosition: 0.5 } // 50% of line
147
+ * { vehicleId: 'v1', targetLineId: 'line002', targetPosition: 150, isPercentage: false }
148
+ */
149
+ export interface MovementCommandInput {
150
+ vehicleId: string;
151
+ targetLineId: string;
152
+ targetPosition?: number;
153
+ isPercentage?: boolean;
154
+ wait?: boolean;
155
+ payload?: unknown;
156
+ }
157
+ /**
158
+ * Full simulation configuration for loadFromJSON()
159
+ *
160
+ * Allows loading an entire simulation state from a JSON object,
161
+ * including lines, connections, vehicles, and movement commands.
162
+ *
163
+ * @example
164
+ * loadFromJSON({
165
+ * lines: [
166
+ * { id: 'line001', start: [100, 100], end: [500, 100] },
167
+ * { id: 'line002', start: [500, 100], end: [500, 400] }
168
+ * ],
169
+ * connections: [
170
+ * { from: 'line001', to: 'line002' }
171
+ * ],
172
+ * vehicles: [
173
+ * { id: 'v1', lineId: 'line001', position: 0 }
174
+ * ],
175
+ * movements: [
176
+ * { vehicleId: 'v1', targetLineId: 'line002', targetPosition: 1.0 }
177
+ * ]
178
+ * })
179
+ */
180
+ export interface SimulationConfig {
181
+ lines: SceneLineInput[];
182
+ connections?: SceneConnectionInput[];
183
+ vehicles?: VehicleInput[];
184
+ movements?: MovementCommandInput[];
185
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Configuration types for algorithm behavior
3
+ */
4
+ /**
5
+ * Tangent calculation mode for bezier curves
6
+ * - proportional-40: 40% of distance for tangent length
7
+ * - magic-55: 55.22% of distance (approximates circular arc)
8
+ */
9
+ export type TangentMode = 'proportional-40' | 'magic-55';