vehicle-path 1.0.4 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hooks/useCanvasInteraction.d.ts +31 -0
- package/dist/hooks/useInitialMovement.d.ts +16 -0
- package/dist/hooks/useMovementSequence.d.ts +17 -0
- package/dist/hooks/useSceneDefinition.d.ts +12 -0
- package/dist/hooks/useVehicleEvents.d.ts +31 -0
- package/dist/hooks/useVehicleMovement.d.ts +24 -0
- package/dist/index.d.ts +28 -0
- package/dist/types/core.d.ts +26 -0
- package/dist/types/index.d.ts +12 -0
- package/dist/types/movement.d.ts +64 -0
- package/dist/types/ui.d.ts +13 -0
- package/dist/types/vehicle.d.ts +65 -0
- package/dist/utils/VehicleEventEmitter.d.ts +94 -0
- package/dist/utils/canvasHelpers.d.ts +9 -0
- package/dist/utils/canvasRenderer.d.ts +13 -0
- package/dist/utils/math.d.ts +35 -0
- package/dist/utils/pathFinding.d.ts +75 -0
- package/dist/utils/textParser.d.ts +22 -0
- package/dist/utils/vehicleHelpers.d.ts +14 -0
- package/dist/utils/vehicleMovement/arcLengthTracking.d.ts +40 -0
- package/dist/utils/vehicleMovement/index.d.ts +8 -0
- package/dist/utils/vehicleMovement/initialize.d.ts +37 -0
- package/dist/utils/vehicleMovement/pathPreparation.d.ts +18 -0
- package/dist/utils/vehicleMovement/positionUpdate.d.ts +44 -0
- package/dist/utils/vehicleMovement/segmentTransition.d.ts +42 -0
- package/dist/utils/vehicleMovement/shared.d.ts +10 -0
- package/dist/vehicle-path.cjs +14 -14
- package/dist/vehicle-path.js +708 -722
- package/package.json +1 -1
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Point, Line, Curve } from '../types/core';
|
|
2
|
+
import type { DrawMode } from '../types/ui';
|
|
3
|
+
interface UseCanvasInteractionProps {
|
|
4
|
+
canvasRef: React.RefObject<HTMLCanvasElement | null>;
|
|
5
|
+
containerRef: React.RefObject<HTMLDivElement | null>;
|
|
6
|
+
drawMode: DrawMode;
|
|
7
|
+
lines: Line[];
|
|
8
|
+
curves: Curve[];
|
|
9
|
+
setLines: (lines: Line[]) => void;
|
|
10
|
+
setCurves: (curves: Curve[]) => void;
|
|
11
|
+
lineCounterRef: React.MutableRefObject<number>;
|
|
12
|
+
}
|
|
13
|
+
export declare function useCanvasInteraction({ canvasRef, containerRef, drawMode, lines, curves, setLines, setCurves, lineCounterRef }: UseCanvasInteractionProps): {
|
|
14
|
+
handleMouseDown: (e: React.MouseEvent<HTMLCanvasElement>) => void;
|
|
15
|
+
handleMouseMove: (e: React.MouseEvent<HTMLCanvasElement>) => void;
|
|
16
|
+
handleMouseUp: () => void;
|
|
17
|
+
tempLine: {
|
|
18
|
+
start: Point;
|
|
19
|
+
current: Point;
|
|
20
|
+
} | null;
|
|
21
|
+
hoveredEndpoint: {
|
|
22
|
+
lineId: string;
|
|
23
|
+
endpoint: "start" | "end";
|
|
24
|
+
} | null;
|
|
25
|
+
curveStart: {
|
|
26
|
+
lineId: string;
|
|
27
|
+
endpoint: "start" | "end";
|
|
28
|
+
} | null;
|
|
29
|
+
mousePos: Point;
|
|
30
|
+
};
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Line } from '../types/core';
|
|
2
|
+
import type { Vehicle } from '../types/vehicle';
|
|
3
|
+
interface UseInitialMovementProps {
|
|
4
|
+
lines: Line[];
|
|
5
|
+
wheelbase: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function useInitialMovement({ lines, wheelbase }: UseInitialMovementProps): {
|
|
8
|
+
vehicles: Vehicle[];
|
|
9
|
+
initialMovementText: string;
|
|
10
|
+
movementError: string | null;
|
|
11
|
+
isDebouncing: boolean;
|
|
12
|
+
debounceKey: number;
|
|
13
|
+
setInitialMovementText: import("react").Dispatch<import("react").SetStateAction<string>>;
|
|
14
|
+
handleAddStartCommand: () => void;
|
|
15
|
+
};
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Line } from '../types/core';
|
|
2
|
+
import type { Vehicle, GotoCommand } from '../types/vehicle';
|
|
3
|
+
interface UseMovementSequenceProps {
|
|
4
|
+
lines: Line[];
|
|
5
|
+
vehicles: Vehicle[];
|
|
6
|
+
}
|
|
7
|
+
export declare function useMovementSequence({ lines, vehicles }: UseMovementSequenceProps): {
|
|
8
|
+
movementSequenceText: string;
|
|
9
|
+
gotoCommands: GotoCommand[];
|
|
10
|
+
vehicleQueues: Map<string, GotoCommand[]>;
|
|
11
|
+
sequenceError: string | null;
|
|
12
|
+
isDebouncing: boolean;
|
|
13
|
+
debounceKey: number;
|
|
14
|
+
setMovementSequenceText: import("react").Dispatch<import("react").SetStateAction<string>>;
|
|
15
|
+
handleAddGotoCommand: () => void;
|
|
16
|
+
};
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Line, Curve } from '../types/core';
|
|
2
|
+
export declare function useSceneDefinition(): {
|
|
3
|
+
lines: Line[];
|
|
4
|
+
curves: Curve[];
|
|
5
|
+
sceneDefinitionText: string;
|
|
6
|
+
sceneError: string | null;
|
|
7
|
+
isDebouncing: boolean;
|
|
8
|
+
debounceKey: number;
|
|
9
|
+
setLines: import("react").Dispatch<import("react").SetStateAction<Line[]>>;
|
|
10
|
+
setCurves: import("react").Dispatch<import("react").SetStateAction<Curve[]>>;
|
|
11
|
+
setSceneDefinitionText: import("react").Dispatch<import("react").SetStateAction<string>>;
|
|
12
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { VehicleEventEmitter, type VehicleEventType, type VehicleEventCallback, type VehicleEventMap, type VehiclePositionUpdate } from '../utils/VehicleEventEmitter';
|
|
2
|
+
/**
|
|
3
|
+
* React context for VehicleEventEmitter
|
|
4
|
+
*/
|
|
5
|
+
export declare const VehicleEventContext: import("react").Context<VehicleEventEmitter | null>;
|
|
6
|
+
/**
|
|
7
|
+
* Hook to access the VehicleEventEmitter instance from context
|
|
8
|
+
* @returns VehicleEventEmitter instance
|
|
9
|
+
* @throws Error if used outside of VehicleEventProvider
|
|
10
|
+
*/
|
|
11
|
+
export declare function useVehicleEventEmitter(): VehicleEventEmitter;
|
|
12
|
+
/**
|
|
13
|
+
* Hook to create a new VehicleEventEmitter instance (for provider)
|
|
14
|
+
* @returns VehicleEventEmitter instance (stable reference)
|
|
15
|
+
*/
|
|
16
|
+
export declare function useCreateVehicleEventEmitter(): VehicleEventEmitter;
|
|
17
|
+
/**
|
|
18
|
+
* Hook to subscribe to a vehicle event with automatic cleanup
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* useVehicleEvent('commandComplete', (info) => {
|
|
23
|
+
* console.log(`Vehicle ${info.vehicleId} arrived!`)
|
|
24
|
+
* if (info.payload) {
|
|
25
|
+
* // Handle payload
|
|
26
|
+
* }
|
|
27
|
+
* })
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare function useVehicleEvent<K extends VehicleEventType>(event: K, callback: VehicleEventCallback<K>, deps?: React.DependencyList): void;
|
|
31
|
+
export type { VehicleEventEmitter, VehicleEventType, VehicleEventCallback, VehicleEventMap, VehiclePositionUpdate };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Line } from '../types/core';
|
|
2
|
+
import type { Vehicle, GotoCommand } from '../types/vehicle';
|
|
3
|
+
import type { TangentMode } from '../types/ui';
|
|
4
|
+
import type { VehicleEventEmitter } from '../utils/VehicleEventEmitter';
|
|
5
|
+
interface UseVehicleMovementProps {
|
|
6
|
+
vehicles: Vehicle[];
|
|
7
|
+
lines: Line[];
|
|
8
|
+
vehicleQueues: Map<string, GotoCommand[]>;
|
|
9
|
+
velocity: number;
|
|
10
|
+
wheelbase: number;
|
|
11
|
+
tangentMode: TangentMode;
|
|
12
|
+
curves: import('../types/core').Curve[];
|
|
13
|
+
eventEmitter?: VehicleEventEmitter;
|
|
14
|
+
}
|
|
15
|
+
type PlaybackState = 'stopped' | 'running' | 'paused';
|
|
16
|
+
export declare function useVehicleMovement({ vehicles, lines, vehicleQueues, velocity, wheelbase, tangentMode, curves, eventEmitter }: UseVehicleMovementProps): {
|
|
17
|
+
movingVehicles: Vehicle[];
|
|
18
|
+
playbackState: PlaybackState;
|
|
19
|
+
handleRun: () => void;
|
|
20
|
+
handlePause: () => void;
|
|
21
|
+
handleReset: () => void;
|
|
22
|
+
continueVehicle: (vehicleId: string) => boolean;
|
|
23
|
+
};
|
|
24
|
+
export {};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VehiclePath - Vehicle motion simulator library
|
|
3
|
+
*
|
|
4
|
+
* A library for simulating dual-axle vehicle movement along paths
|
|
5
|
+
* composed of lines and Bezier curves.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import {
|
|
10
|
+
* useVehicleMovement,
|
|
11
|
+
* VehicleEventEmitter,
|
|
12
|
+
* parseSceneDefinition
|
|
13
|
+
* } from 'vehicle-path'
|
|
14
|
+
* import type { Point, Line, Vehicle } from 'vehicle-path'
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export type { Point, Line, BezierCurve, Curve, VehicleState, VehicleStart, Vehicle, AxleState, GotoCommand, GotoCompletionInfo, GotoCompletionCallback, CurveData, PathExecutionState, VehicleMovementState, MovementConfig, SceneDefinition, SceneContext, DrawMode, TangentMode } from './types';
|
|
18
|
+
export { useVehicleMovement } from './hooks/useVehicleMovement';
|
|
19
|
+
export { useVehicleEventEmitter, useCreateVehicleEventEmitter, useVehicleEvent, VehicleEventContext } from './hooks/useVehicleEvents';
|
|
20
|
+
export { useSceneDefinition } from './hooks/useSceneDefinition';
|
|
21
|
+
export { useInitialMovement } from './hooks/useInitialMovement';
|
|
22
|
+
export { useMovementSequence } from './hooks/useMovementSequence';
|
|
23
|
+
export { useCanvasInteraction } from './hooks/useCanvasInteraction';
|
|
24
|
+
export { VehicleEventEmitter, type VehicleEventMap, type VehicleEventType, type VehicleEventCallback, type VehiclePositionUpdate, type Unsubscribe } from './utils/VehicleEventEmitter';
|
|
25
|
+
export { parseSceneDefinition, generateSceneDefinition, parseVehicleStarts, generateVehicleStarts, parseGotoCommands, generateGotoCommands } from './utils/textParser';
|
|
26
|
+
export { buildGraph, findPath, canReachTarget, getReachableCurves, calculateBezierArcLength, resolveOffset, resolveFromLineOffset, resolveToLineOffset, type Graph, type GraphEdge, type PathSegment, type PathResult, type VehiclePosition } from './utils/pathFinding';
|
|
27
|
+
export { initializeMovingVehicle, createInitialMovementState, initializeAllVehicles, calculateInitialFrontPosition, type InitializationResult, updateAxlePosition, calculatePositionOnLine, calculatePositionOnCurve, calculateFrontAxlePosition, getCumulativeArcLength, arcLengthToSegmentPosition, prepareCommandPath, type PreparedPath, checkRearCompletion, handleArrival, type SegmentCompletionContext, type SegmentCompletionResult, type SegmentVehicleState, getPositionFromOffset, getLineLength } from './utils/vehicleMovement';
|
|
28
|
+
export { distance, normalize, getPointOnLine, getPointOnLineByOffset, getPointOnBezier, createBezierCurve, buildArcLengthTable, distanceToT, getArcLength, type ArcLengthEntry, type CurveOffsetOptions } from './utils/math';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core geometry types for the bezier-path system
|
|
3
|
+
*/
|
|
4
|
+
export interface Point {
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
}
|
|
8
|
+
export interface Line {
|
|
9
|
+
id: string;
|
|
10
|
+
start: Point;
|
|
11
|
+
end: Point;
|
|
12
|
+
}
|
|
13
|
+
export interface BezierCurve {
|
|
14
|
+
p0: Point;
|
|
15
|
+
p1: Point;
|
|
16
|
+
p2: Point;
|
|
17
|
+
p3: Point;
|
|
18
|
+
}
|
|
19
|
+
export interface Curve {
|
|
20
|
+
fromLineId: string;
|
|
21
|
+
toLineId: string;
|
|
22
|
+
fromOffset?: number;
|
|
23
|
+
fromIsPercentage?: boolean;
|
|
24
|
+
toOffset?: number;
|
|
25
|
+
toIsPercentage?: boolean;
|
|
26
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-export all types from a single entry point
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* import type { Point, Line, Vehicle } from '../types'
|
|
6
|
+
* // or
|
|
7
|
+
* import type { Point } from '../types/core'
|
|
8
|
+
*/
|
|
9
|
+
export type { Point, Line, BezierCurve, Curve } from './core';
|
|
10
|
+
export type { VehicleState, VehicleStart, Vehicle, AxleState, GotoCommand, GotoCompletionInfo, GotoCompletionCallback } from './vehicle';
|
|
11
|
+
export type { CurveData, PathExecutionState, VehicleMovementState, MovementConfig, SceneDefinition, SceneContext } from './movement';
|
|
12
|
+
export type { DrawMode, TangentMode } from './ui';
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Movement and animation state types
|
|
3
|
+
*/
|
|
4
|
+
import type { Line, Curve, BezierCurve } from './core';
|
|
5
|
+
import type { Vehicle, VehicleStart } from './vehicle';
|
|
6
|
+
import type { TangentMode } from './ui';
|
|
7
|
+
export type { PathResult } from '../utils/pathFinding';
|
|
8
|
+
export type { ArcLengthEntry } from '../utils/math';
|
|
9
|
+
/**
|
|
10
|
+
* Bezier curve data with arc-length lookup table for animation
|
|
11
|
+
*/
|
|
12
|
+
export interface CurveData {
|
|
13
|
+
bezier: BezierCurve;
|
|
14
|
+
arcLengthTable: import('../utils/math').ArcLengthEntry[];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Execution state for a single axle (Front or Rear)
|
|
18
|
+
*/
|
|
19
|
+
export interface AxleExecutionState {
|
|
20
|
+
currentSegmentIndex: number;
|
|
21
|
+
segmentDistance: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* State for path execution during animation
|
|
25
|
+
*/
|
|
26
|
+
export interface PathExecutionState {
|
|
27
|
+
path: import('../utils/pathFinding').PathResult;
|
|
28
|
+
curveDataMap: Map<number, CurveData>;
|
|
29
|
+
currentCommandIndex: number;
|
|
30
|
+
rear: AxleExecutionState;
|
|
31
|
+
front: AxleExecutionState;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Movement state container for a vehicle
|
|
35
|
+
*/
|
|
36
|
+
export interface VehicleMovementState {
|
|
37
|
+
vehicle: Vehicle;
|
|
38
|
+
execution: PathExecutionState | null;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Configuration for vehicle movement
|
|
42
|
+
*/
|
|
43
|
+
export interface MovementConfig {
|
|
44
|
+
wheelbase: number;
|
|
45
|
+
tangentMode: TangentMode;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Scene definition (parsed from text input)
|
|
49
|
+
*/
|
|
50
|
+
export interface SceneDefinition {
|
|
51
|
+
lines: Line[];
|
|
52
|
+
curves: Curve[];
|
|
53
|
+
vehicles: VehicleStart[];
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Scene context for path preparation and movement calculations
|
|
57
|
+
* Bundles commonly-passed together dependencies
|
|
58
|
+
*/
|
|
59
|
+
export interface SceneContext {
|
|
60
|
+
config: MovementConfig;
|
|
61
|
+
graph: import('../utils/pathFinding').Graph;
|
|
62
|
+
linesMap: Map<string, Line>;
|
|
63
|
+
curves: Curve[];
|
|
64
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UI-related types for canvas and controls
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Drawing mode for canvas interaction
|
|
6
|
+
*/
|
|
7
|
+
export type DrawMode = 'line' | 'curve' | 'drag';
|
|
8
|
+
/**
|
|
9
|
+
* Tangent calculation mode for bezier curves
|
|
10
|
+
* - proportional-40: 40% of distance for tangent length
|
|
11
|
+
* - magic-55: 55.22% of distance (approximates circular arc)
|
|
12
|
+
*/
|
|
13
|
+
export type TangentMode = 'proportional-40' | 'magic-55';
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vehicle-related types
|
|
3
|
+
*/
|
|
4
|
+
import type { Point } from './core';
|
|
5
|
+
/**
|
|
6
|
+
* Animation state for a vehicle
|
|
7
|
+
*/
|
|
8
|
+
export type VehicleState = 'idle' | 'moving' | 'waiting';
|
|
9
|
+
/**
|
|
10
|
+
* Vehicle start position (input from text parsing)
|
|
11
|
+
*/
|
|
12
|
+
export interface VehicleStart {
|
|
13
|
+
vehicleId: string;
|
|
14
|
+
lineId: string;
|
|
15
|
+
offset: number;
|
|
16
|
+
isPercentage: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* State for a single axle (Front or Rear)
|
|
20
|
+
*/
|
|
21
|
+
export interface AxleState {
|
|
22
|
+
lineId: string;
|
|
23
|
+
position: Point;
|
|
24
|
+
absoluteOffset: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Vehicle with runtime state (used during animation)
|
|
28
|
+
*/
|
|
29
|
+
export interface Vehicle {
|
|
30
|
+
id: string;
|
|
31
|
+
lineId: string;
|
|
32
|
+
offset: number;
|
|
33
|
+
isPercentage: boolean;
|
|
34
|
+
state: VehicleState;
|
|
35
|
+
rear: AxleState;
|
|
36
|
+
front: AxleState;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Command to move a vehicle to a target position
|
|
40
|
+
*/
|
|
41
|
+
export interface GotoCommand {
|
|
42
|
+
vehicleId: string;
|
|
43
|
+
targetLineId: string;
|
|
44
|
+
targetOffset: number;
|
|
45
|
+
isPercentage: boolean;
|
|
46
|
+
awaitConfirmation?: boolean;
|
|
47
|
+
payload?: unknown;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Information provided when a goto command completes
|
|
51
|
+
*/
|
|
52
|
+
export interface GotoCompletionInfo {
|
|
53
|
+
vehicleId: string;
|
|
54
|
+
command: GotoCommand;
|
|
55
|
+
finalPosition: {
|
|
56
|
+
lineId: string;
|
|
57
|
+
absoluteOffset: number;
|
|
58
|
+
position: Point;
|
|
59
|
+
};
|
|
60
|
+
payload?: unknown;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Callback type for goto command completion
|
|
64
|
+
*/
|
|
65
|
+
export type GotoCompletionCallback = (info: GotoCompletionInfo) => void;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { GotoCompletionInfo, GotoCommand, VehicleState } from '../types/vehicle';
|
|
2
|
+
import type { Point } from '../types/core';
|
|
3
|
+
/**
|
|
4
|
+
* Info when a command starts execution
|
|
5
|
+
*/
|
|
6
|
+
export interface CommandStartInfo {
|
|
7
|
+
vehicleId: string;
|
|
8
|
+
command: GotoCommand;
|
|
9
|
+
commandIndex: number;
|
|
10
|
+
startPosition: {
|
|
11
|
+
lineId: string;
|
|
12
|
+
absoluteOffset: number;
|
|
13
|
+
position: Point;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Position update data for a vehicle
|
|
18
|
+
*/
|
|
19
|
+
export interface VehiclePositionUpdate {
|
|
20
|
+
vehicleId: string;
|
|
21
|
+
/** Rear axle position */
|
|
22
|
+
rear: Point;
|
|
23
|
+
/** Front axle position */
|
|
24
|
+
front: Point;
|
|
25
|
+
/** Center point between rear and front axles */
|
|
26
|
+
center: Point;
|
|
27
|
+
/** Angle in radians from rear to front (heading direction) */
|
|
28
|
+
angle: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Event map for vehicle-related events
|
|
32
|
+
*/
|
|
33
|
+
export interface VehicleEventMap {
|
|
34
|
+
/** Fired when a goto command starts execution */
|
|
35
|
+
commandStart: CommandStartInfo;
|
|
36
|
+
/** Fired when a goto command completes (vehicle arrives at destination) */
|
|
37
|
+
commandComplete: GotoCompletionInfo;
|
|
38
|
+
/** Fired when vehicle state changes */
|
|
39
|
+
stateChange: {
|
|
40
|
+
vehicleId: string;
|
|
41
|
+
from: VehicleState;
|
|
42
|
+
to: VehicleState;
|
|
43
|
+
};
|
|
44
|
+
/** Fired on each frame when vehicle position updates */
|
|
45
|
+
positionUpdate: VehiclePositionUpdate;
|
|
46
|
+
}
|
|
47
|
+
export type VehicleEventType = keyof VehicleEventMap;
|
|
48
|
+
export type VehicleEventCallback<K extends VehicleEventType> = (data: VehicleEventMap[K]) => void;
|
|
49
|
+
export type Unsubscribe = () => void;
|
|
50
|
+
/**
|
|
51
|
+
* Event emitter for vehicle movement events.
|
|
52
|
+
* Allows multiple subscribers to listen for events like command completion,
|
|
53
|
+
* state changes, etc.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* const emitter = new VehicleEventEmitter()
|
|
58
|
+
*
|
|
59
|
+
* // Subscribe to events
|
|
60
|
+
* const unsubscribe = emitter.on('commandComplete', (info) => {
|
|
61
|
+
* console.log(`Vehicle ${info.vehicleId} arrived with payload:`, info.payload)
|
|
62
|
+
* })
|
|
63
|
+
*
|
|
64
|
+
* // Later, unsubscribe
|
|
65
|
+
* unsubscribe()
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export declare class VehicleEventEmitter {
|
|
69
|
+
private listeners;
|
|
70
|
+
/**
|
|
71
|
+
* Subscribe to an event
|
|
72
|
+
* @param event - The event type to listen for
|
|
73
|
+
* @param callback - Function to call when event is emitted
|
|
74
|
+
* @returns Unsubscribe function
|
|
75
|
+
*/
|
|
76
|
+
on<K extends VehicleEventType>(event: K, callback: VehicleEventCallback<K>): Unsubscribe;
|
|
77
|
+
/**
|
|
78
|
+
* Emit an event to all subscribers
|
|
79
|
+
* @param event - The event type to emit
|
|
80
|
+
* @param data - The event data
|
|
81
|
+
*/
|
|
82
|
+
emit<K extends VehicleEventType>(event: K, data: VehicleEventMap[K]): void;
|
|
83
|
+
/**
|
|
84
|
+
* Remove all listeners for a specific event, or all events if no event specified
|
|
85
|
+
* @param event - Optional event type to clear listeners for
|
|
86
|
+
*/
|
|
87
|
+
off(event?: VehicleEventType): void;
|
|
88
|
+
/**
|
|
89
|
+
* Get the number of listeners for a specific event
|
|
90
|
+
* @param event - The event type
|
|
91
|
+
* @returns Number of listeners
|
|
92
|
+
*/
|
|
93
|
+
listenerCount(event: VehicleEventType): number;
|
|
94
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Point, Line } from '../types/core';
|
|
2
|
+
import type { TangentMode } from '../types/ui';
|
|
3
|
+
export declare function setupCanvas(canvas: HTMLCanvasElement, container: HTMLDivElement): void;
|
|
4
|
+
export declare function getMousePos(e: React.MouseEvent<HTMLCanvasElement>, canvas: HTMLCanvasElement | null, container: HTMLDivElement | null): Point;
|
|
5
|
+
export declare function findEndpointAtPoint(pos: Point, lines: Line[], threshold?: number): {
|
|
6
|
+
lineId: string;
|
|
7
|
+
endpoint: 'start' | 'end';
|
|
8
|
+
} | null;
|
|
9
|
+
export declare function parseTangentMode(smoothness: string): TangentMode;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Point, Line, BezierCurve } from '../types/core';
|
|
2
|
+
import type { TangentMode } from '../types/ui';
|
|
3
|
+
import type { Vehicle } from '../types/vehicle';
|
|
4
|
+
import { type CurveOffsetOptions } from './math';
|
|
5
|
+
export declare function drawLine(ctx: CanvasRenderingContext2D, line: Line, hoveredEndpoint: {
|
|
6
|
+
lineId: string;
|
|
7
|
+
endpoint: 'start' | 'end';
|
|
8
|
+
} | null): void;
|
|
9
|
+
export declare function drawTempLine(ctx: CanvasRenderingContext2D, start: Point, end: Point): void;
|
|
10
|
+
export declare function drawCurve(ctx: CanvasRenderingContext2D, fromLine: Line, toLine: Line, wheelbase: number, tangentMode: TangentMode, offsetOptions?: CurveOffsetOptions): void;
|
|
11
|
+
export declare function drawBezierCurve(ctx: CanvasRenderingContext2D, bezier: BezierCurve): void;
|
|
12
|
+
export declare function drawTempCurveLine(ctx: CanvasRenderingContext2D, start: Point, end: Point): void;
|
|
13
|
+
export declare function drawVehicle(ctx: CanvasRenderingContext2D, vehicle: Vehicle): void;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Point, Line, BezierCurve } from '../types/core';
|
|
2
|
+
import type { TangentMode } from '../types/ui';
|
|
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,75 @@
|
|
|
1
|
+
import type { Line, Curve, BezierCurve } from '../types/core';
|
|
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
|
+
* Menghitung absolute offset dari offset yang mungkin percentage
|
|
38
|
+
* (Legacy function - use resolveFromLineOffset/resolveToLineOffset for curve offsets)
|
|
39
|
+
*/
|
|
40
|
+
export declare function resolveOffset(line: Line, offset: number | undefined, isPercentage: boolean | undefined, defaultPercentage: number): number;
|
|
41
|
+
/**
|
|
42
|
+
* Resolve offset untuk FROM line (garis asal kurva)
|
|
43
|
+
* - 0% → wheelbase (bukan 0, untuk memberi ruang vehicle)
|
|
44
|
+
* - 100% → lineLength (ujung garis)
|
|
45
|
+
*
|
|
46
|
+
* Effective range: [wheelbase, lineLength]
|
|
47
|
+
*/
|
|
48
|
+
export declare function resolveFromLineOffset(line: Line, offset: number | undefined, isPercentage: boolean | undefined, defaultPercentage: number, wheelbase: number): number;
|
|
49
|
+
/**
|
|
50
|
+
* Resolve offset untuk TO line (garis tujuan kurva)
|
|
51
|
+
* - 0% → 0 (awal garis)
|
|
52
|
+
* - 100% → lineLength - wheelbase (untuk memberi ruang vehicle)
|
|
53
|
+
*
|
|
54
|
+
* Effective range: [0, lineLength - wheelbase]
|
|
55
|
+
*/
|
|
56
|
+
export declare function resolveToLineOffset(line: Line, offset: number | undefined, isPercentage: boolean | undefined, defaultPercentage: number, wheelbase: number): number;
|
|
57
|
+
/**
|
|
58
|
+
* Membangun graph dari lines dan curves
|
|
59
|
+
*/
|
|
60
|
+
export declare function buildGraph(lines: Line[], curves: Curve[], config: MovementConfig): Graph;
|
|
61
|
+
/**
|
|
62
|
+
* Mencari path terpendek dari posisi vehicle ke target
|
|
63
|
+
*
|
|
64
|
+
* @returns PathResult jika path ditemukan, null jika tidak ada path valid
|
|
65
|
+
*/
|
|
66
|
+
export declare function findPath(graph: Graph, vehiclePos: VehiclePosition, targetLineId: string, targetOffset: number, // Absolute offset
|
|
67
|
+
targetIsPercentage?: boolean): PathResult | null;
|
|
68
|
+
/**
|
|
69
|
+
* Mengecek apakah path valid dari posisi vehicle ke target
|
|
70
|
+
*/
|
|
71
|
+
export declare function canReachTarget(graph: Graph, vehiclePos: VehiclePosition, targetLineId: string, targetOffset: number, targetIsPercentage?: boolean): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Mendapatkan semua kurva yang bisa diambil dari posisi tertentu pada line
|
|
74
|
+
*/
|
|
75
|
+
export declare function getReachableCurves(graph: Graph, lineId: string, currentOffset: number): GraphEdge[];
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { VehicleStart, GotoCommand } from '../types/vehicle';
|
|
2
|
+
import type { SceneDefinition } from '../types/movement';
|
|
3
|
+
export declare function parseSceneDefinition(text: string): SceneDefinition;
|
|
4
|
+
export declare function generateSceneDefinition(scene: SceneDefinition): string;
|
|
5
|
+
/**
|
|
6
|
+
* Parse vehicle start positions from initial movement text
|
|
7
|
+
* Format: v1 start line001 10 or v2 start line002 20%
|
|
8
|
+
*/
|
|
9
|
+
export declare function parseVehicleStarts(text: string): VehicleStart[];
|
|
10
|
+
/**
|
|
11
|
+
* Generate initial movement text from vehicle starts
|
|
12
|
+
*/
|
|
13
|
+
export declare function generateVehicleStarts(vehicles: VehicleStart[]): string;
|
|
14
|
+
/**
|
|
15
|
+
* Parse goto commands from movement sequence text
|
|
16
|
+
* Format: v1 goto line001 100% [--wait] [--payload {...}]
|
|
17
|
+
*/
|
|
18
|
+
export declare function parseGotoCommands(text: string): GotoCommand[];
|
|
19
|
+
/**
|
|
20
|
+
* Generate movement sequence text from goto commands
|
|
21
|
+
*/
|
|
22
|
+
export declare function generateGotoCommands(commands: GotoCommand[]): string;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Line } from '../types/core';
|
|
2
|
+
import type { Vehicle, VehicleStart, GotoCommand } from '../types/vehicle';
|
|
3
|
+
export declare function validateAndCreateVehicles(vehicleStarts: VehicleStart[], lines: Line[], wheelbase?: number): {
|
|
4
|
+
vehicles: Vehicle[];
|
|
5
|
+
errors: string[];
|
|
6
|
+
};
|
|
7
|
+
export declare function getNextStartVehicleId(existingVehicles: VehicleStart[]): string;
|
|
8
|
+
export interface GotoValidationResult {
|
|
9
|
+
commands: GotoCommand[];
|
|
10
|
+
errors: string[];
|
|
11
|
+
vehicleQueues: Map<string, GotoCommand[]>;
|
|
12
|
+
}
|
|
13
|
+
export declare function validateGotoCommands(commands: GotoCommand[], vehicles: Vehicle[], lines: Line[]): GotoValidationResult;
|
|
14
|
+
export declare function getNextGotoVehicleId(existingCommands: GotoCommand[], vehicles: Vehicle[]): string | null;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Arc-length tracking utilities for dual-axle vehicle movement
|
|
3
|
+
*
|
|
4
|
+
* Enables calculating front axle position from rear axle position
|
|
5
|
+
* by maintaining wheelbase distance in arc-length terms.
|
|
6
|
+
*/
|
|
7
|
+
import type { PathResult } from '../pathFinding';
|
|
8
|
+
/**
|
|
9
|
+
* Calculate cumulative arc-length from start of path
|
|
10
|
+
*
|
|
11
|
+
* @param path - The path being followed
|
|
12
|
+
* @param segmentIndex - Current segment index
|
|
13
|
+
* @param segmentDistance - Distance along current segment
|
|
14
|
+
* @returns Total arc-length from path start
|
|
15
|
+
*/
|
|
16
|
+
export declare function getCumulativeArcLength(path: PathResult, segmentIndex: number, segmentDistance: number): number;
|
|
17
|
+
/**
|
|
18
|
+
* Convert arc-length to segment position
|
|
19
|
+
*
|
|
20
|
+
* @param path - The path being followed
|
|
21
|
+
* @param targetArcLength - Target cumulative arc-length
|
|
22
|
+
* @returns Segment position or null if exceeds path length
|
|
23
|
+
*/
|
|
24
|
+
export declare function arcLengthToSegmentPosition(path: PathResult, targetArcLength: number): {
|
|
25
|
+
segmentIndex: number;
|
|
26
|
+
segmentDistance: number;
|
|
27
|
+
} | null;
|
|
28
|
+
/**
|
|
29
|
+
* Calculate front axle position from rear position + wheelbase
|
|
30
|
+
*
|
|
31
|
+
* @param path - The path being followed
|
|
32
|
+
* @param rearSegmentIndex - Rear axle segment index
|
|
33
|
+
* @param rearSegmentDistance - Rear axle distance in segment
|
|
34
|
+
* @param wheelbase - Distance between front and rear axles
|
|
35
|
+
* @returns Front axle position or null if exceeds path
|
|
36
|
+
*/
|
|
37
|
+
export declare function calculateFrontAxlePosition(path: PathResult, rearSegmentIndex: number, rearSegmentDistance: number, wheelbase: number): {
|
|
38
|
+
segmentIndex: number;
|
|
39
|
+
segmentDistance: number;
|
|
40
|
+
} | null;
|