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.
- package/README.md +160 -0
- package/dist/animation-loop-bZEm2pMN.js +37 -0
- package/dist/animation-loop-fC2LjxCd.cjs +1 -0
- package/dist/core/algorithms/math.d.ts +35 -0
- package/dist/core/algorithms/pathFinding.d.ts +62 -0
- package/dist/core/algorithms/vehicleMovement.d.ts +174 -0
- package/dist/core/index.d.ts +20 -0
- package/dist/core/types/api.d.ts +185 -0
- package/dist/core/types/config.d.ts +9 -0
- package/dist/core/types/geometry.d.ts +26 -0
- package/dist/core/types/movement.d.ts +56 -0
- package/dist/core/types/vehicle.d.ts +65 -0
- package/dist/core.cjs +1 -0
- package/dist/core.js +551 -0
- package/dist/index.d.ts +45 -0
- package/dist/react/dsl-hooks/useInitialMovement.d.ts +24 -0
- package/dist/react/dsl-hooks/useMovementSequence.d.ts +27 -0
- package/dist/react/dsl-hooks/useSceneDefinition.d.ts +22 -0
- package/dist/react/hooks/useAnimation.d.ts +43 -0
- package/dist/react/hooks/useMovementQueue.d.ts +52 -0
- package/dist/react/hooks/useScene.d.ts +78 -0
- package/dist/react/hooks/useVehicleSimulation.d.ts +126 -0
- package/dist/react/hooks/useVehicles.d.ts +55 -0
- package/dist/react/index.d.ts +48 -0
- package/dist/react/providers/useVehicleEvents.d.ts +78 -0
- package/dist/react.cjs +1 -0
- package/dist/react.js +18 -0
- package/dist/useVehicleEvents-B2JQFNjc.js +923 -0
- package/dist/useVehicleEvents-CBymulau.cjs +3 -0
- package/dist/utils/animation-loop.d.ts +105 -0
- package/dist/utils/dsl-parser.d.ts +152 -0
- package/dist/utils/event-emitter.d.ts +94 -0
- package/dist/utils/index.d.ts +15 -0
- package/dist/utils/type-converters.d.ts +38 -0
- package/dist/utils/vehicle-helpers.d.ts +8 -0
- package/dist/utils.cjs +1 -0
- package/dist/utils.js +17 -0
- package/dist/vehicle-helpers-DIcksrtO.cjs +7 -0
- package/dist/vehicle-helpers-_72KxCqO.js +276 -0
- package/dist/vehicle-path.cjs +1 -0
- package/dist/vehicle-path.js +62 -0
- package/package.json +103 -0
|
@@ -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,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Movement and animation state types
|
|
3
|
+
*/
|
|
4
|
+
import type { Line, Curve, BezierCurve } from './geometry';
|
|
5
|
+
import type { Vehicle } from './vehicle';
|
|
6
|
+
import type { TangentMode } from './config';
|
|
7
|
+
export type { PathResult } from '../algorithms/pathFinding';
|
|
8
|
+
export type { ArcLengthEntry } from '../algorithms/math';
|
|
9
|
+
/**
|
|
10
|
+
* Bezier curve data with arc-length lookup table for animation
|
|
11
|
+
*/
|
|
12
|
+
export interface CurveData {
|
|
13
|
+
bezier: BezierCurve;
|
|
14
|
+
arcLengthTable: import('../algorithms/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('../algorithms/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 context for path preparation and movement calculations
|
|
49
|
+
* Bundles commonly-passed together dependencies
|
|
50
|
+
*/
|
|
51
|
+
export interface SceneContext {
|
|
52
|
+
config: MovementConfig;
|
|
53
|
+
graph: import('../algorithms/pathFinding').Graph;
|
|
54
|
+
linesMap: Map<string, Line>;
|
|
55
|
+
curves: Curve[];
|
|
56
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vehicle-related types
|
|
3
|
+
*/
|
|
4
|
+
import type { Point } from './geometry';
|
|
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;
|
package/dist/core.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function p(e,t){const s=t.x-e.x,n=t.y-e.y;return Math.sqrt(s*s+n*n)}function P(e,t){const s=t.x-e.x,n=t.y-e.y,o=Math.sqrt(s*s+n*n);return o===0?{x:0,y:0}:{x:s/o,y:n/o}}function V(e,t){return t*(e==="proportional-40"?.4:.5522)}function C(e,t,s,n=!1,o){const{wheelbase:c,tangentMode:r}=s;let i;o?.fromOffset!==void 0?i=D(e,o.fromOffset,o.fromIsPercentage??!1):i=e.end;let l;o?.toOffset!==void 0?l=D(t,o.toOffset,o.toIsPercentage??!1):l=t.start;const d=P(e.start,e.end),f=n?{x:i.x-d.x*c,y:i.y-d.y*c}:i,u=P(e.start,e.end),g=P(t.start,t.end),I=p(f,l),v=V(r,I),a=n?{x:f.x-u.x*v,y:f.y-u.y*v}:{x:f.x+u.x*v,y:f.y+u.y*v},m={x:l.x-g.x*v,y:l.y-g.y*v};return{p0:f,p1:a,p2:m,p3:l}}function B(e,t){return{x:e.start.x+(e.end.x-e.start.x)*t,y:e.start.y+(e.end.y-e.start.y)*t}}function D(e,t,s){const n=p(e.start,e.end);let o;return s?o=t/100:o=n>0?t/n:0,o=Math.max(0,Math.min(1,o)),B(e,o)}function w(e,t){const{p0:s,p1:n,p2:o,p3:c}=e,r=1-t,i=r*r,l=i*r,d=t*t,f=d*t;return{x:l*s.x+3*i*t*n.x+3*r*d*o.x+f*c.x,y:l*s.y+3*i*t*n.y+3*r*d*o.y+f*c.y}}function H(e,t,s=10){return p(e,t)<=s}function q(e,t=100){const s=[{t:0,distance:0}];let n=e.p0,o=0;for(let c=1;c<=t;c++){const r=c/t,i=w(e,r);o+=p(n,i),s.push({t:r,distance:o}),n=i}return s}function F(e,t){if(t<=0)return 0;const s=e[e.length-1].distance;if(t>=s)return 1;let n=0,o=e.length-1;for(;n<o-1;){const f=Math.floor((n+o)/2);e[f].distance<t?n=f:o=f}const c=e[n].distance,r=e[o].distance,i=e[n].t,l=e[o].t;if(r===c)return i;const d=(t-c)/(r-c);return i+d*(l-i)}function J(e){return e[e.length-1].distance}function j(e,t=100){let s=0,n=e.p0;for(let o=1;o<=t;o++){const c=o/t,r=w(e,c);s+=p(n,r),n=r}return s}function S(e,t,s,n,o){const c=p(e.start,e.end),r=c-o;if(r<=0)return c;let i;if(t===void 0)i=n;else if(s)i=t;else return Math.max(o,Math.min(t,c));return o+i/100*r}function T(e,t,s,n,o){const r=p(e.start,e.end)-o;if(r<=0)return 0;let i;if(t===void 0)i=n;else if(s)i=t;else return Math.max(0,Math.min(t,r));return i/100*r}function U(e,t,s){const n=new Map,o=new Map,c=new Map;for(const r of e)o.set(r.id,r),c.set(r.id,p(r.start,r.end)),n.set(r.id,[]);for(let r=0;r<t.length;r++){const i=t[r],l=o.get(i.fromLineId),d=o.get(i.toLineId);if(!l||!d)continue;const f=S(l,i.fromOffset,i.fromIsPercentage,100,s.wheelbase),u=T(d,i.toOffset,i.toIsPercentage,0,s.wheelbase),g=C(l,d,s,!1,{fromOffset:f,fromIsPercentage:!1,toOffset:u,toIsPercentage:!1}),I=j(g),v={curveIndex:r,fromLineId:i.fromLineId,toLineId:i.toLineId,fromOffset:f,toOffset:u,curveLength:I};n.get(i.fromLineId).push(v)}return{adjacency:n,lines:o,lineLengths:c}}function K(e,t,s,n,o=!1){const{adjacency:c,lines:r,lineLengths:i}=e;if(!r.get(s))return null;const d=i.get(s),f=o?n/100*d:n,u=[],g=new Map,I=(a,m)=>`${a}:${Math.round(m)}`;if(t.lineId===s&&f>=t.offset){const a=f-t.offset;return{segments:[{type:"line",lineId:t.lineId,startOffset:t.offset,endOffset:f,length:a}],totalDistance:a}}const v=c.get(t.lineId)||[];for(const a of v){if(a.fromOffset<t.offset)continue;const m=a.fromOffset-t.offset,L=m+a.curveLength,x={type:"line",lineId:t.lineId,startOffset:t.offset,endOffset:a.fromOffset,length:m},h={type:"curve",curveIndex:a.curveIndex,startOffset:0,endOffset:a.curveLength,length:a.curveLength};u.push({lineId:a.toLineId,entryOffset:a.toOffset,totalDistance:L,path:[x,h]})}for(u.sort((a,m)=>a.totalDistance-m.totalDistance);u.length>0;){const a=u.shift(),m=I(a.lineId,a.entryOffset),L=g.get(m);if(L!==void 0&&L<=a.totalDistance)continue;if(g.set(m,a.totalDistance),a.lineId===s){const h=Math.abs(f-a.entryOffset);if(f>=a.entryOffset){const y={type:"line",lineId:s,startOffset:a.entryOffset,endOffset:f,length:h};return{segments:[...a.path,y],totalDistance:a.totalDistance+h}}}const x=c.get(a.lineId)||[];for(const h of x){if(h.fromOffset<a.entryOffset)continue;const y=h.fromOffset-a.entryOffset,A=a.totalDistance+y+h.curveLength,W=I(h.toLineId,h.toOffset),z=g.get(W);if(z!==void 0&&z<=A)continue;const _={type:"line",lineId:a.lineId,startOffset:a.entryOffset,endOffset:h.fromOffset,length:y},E={type:"curve",curveIndex:h.curveIndex,startOffset:0,endOffset:h.curveLength,length:h.curveLength};u.push({lineId:h.toLineId,entryOffset:h.toOffset,totalDistance:A,path:[...a.path,_,E]})}u.sort((h,y)=>h.totalDistance-y.totalDistance)}return null}function b(e,t){const s=Math.sqrt(Math.pow(e.end.x-e.start.x,2)+Math.pow(e.end.y-e.start.y,2)),n=s>0?t/s:0;return{x:e.start.x+(e.end.x-e.start.x)*Math.min(1,Math.max(0,n)),y:e.start.y+(e.end.y-e.start.y)*Math.min(1,Math.max(0,n))}}function G(e){return Math.sqrt(Math.pow(e.end.x-e.start.x,2)+Math.pow(e.end.y-e.start.y,2))}function N(e,t,s){let n=0;for(let o=0;o<t;o++)n+=e.segments[o].length;return n+=s,n}function $(e,t){let s=0;for(let n=0;n<e.segments.length;n++){const o=e.segments[n],c=s+o.length;if(t<c)return{segmentIndex:n,segmentDistance:t-s};if(t===c)return n+1<e.segments.length?{segmentIndex:n+1,segmentDistance:0}:{segmentIndex:n,segmentDistance:o.length};s+=o.length}return null}function k(e,t,s,n){const c=N(e,t,s)+n;return $(e,c)}function X(e,t,s,n){const o=Math.sqrt(Math.pow(n.end.x-n.start.x,2)+Math.pow(n.end.y-n.start.y,2));let c=t+s;c=Math.min(c,o);const r=b(n,c);return{lineId:e,position:r,absoluteOffset:c}}function Q(e,t){return{...e,state:"idle"}}function R(e){return{vehicle:e,execution:null}}function Y(e,t){const s=[],n=new Map;for(const o of e){if(!t.get(o.lineId))continue;const r=Q(o);s.push(r);const i=R(r);n.set(o.id,i)}return{movingVehicles:s,stateMap:n}}function O(e,t){return{position:b(e,t),lineId:e.id,absoluteOffset:t}}function M(e,t){const s=F(e.arcLengthTable,t);return{position:w(e.bezier,s)}}function Z(e,t,s,n,o,c,r){const i=s.segments[t.currentSegmentIndex],l=t.segmentDistance+n;if(l>=i.length){const f=l-i.length,u=t.currentSegmentIndex+1;if(u>=s.segments.length){if(r!==void 0&&i.type==="line"){const a=o.get(i.lineId),m=i.startOffset+l;if(m<=r){const x=O(a,m);return{axleState:{...e,...x},execution:{...t,segmentDistance:l},completed:!1}}const L=O(a,r);return{axleState:{...e,...L},execution:{...t,segmentDistance:r-i.startOffset},completed:!0}}const v=i.type==="line"?O(o.get(i.lineId),i.endOffset):M(c.get(i.curveIndex),i.length);return{axleState:{...e,...v},execution:{...t,segmentDistance:i.length},completed:!0}}const g=s.segments[u],I=g.type==="line"?O(o.get(g.lineId),g.startOffset+f):M(c.get(g.curveIndex),f);return{axleState:{...e,...I},execution:{currentSegmentIndex:u,segmentDistance:f},completed:!1}}const d=i.type==="line"?O(o.get(i.lineId),i.startOffset+l):M(c.get(i.curveIndex),l);return{axleState:{...e,...d},execution:{...t,segmentDistance:l},completed:!1}}function ee(e,t,s,n){const o=new Map;for(const c of e.segments)if(c.type==="curve"&&c.curveIndex!==void 0){const r=t[c.curveIndex];if(r){const i=s.get(r.fromLineId),l=s.get(r.toLineId);if(i&&l){const d=S(i,r.fromOffset,r.fromIsPercentage,100,n.wheelbase),f=T(l,r.toOffset,r.toIsPercentage,0,n.wheelbase),u=C(i,l,n,!1,{fromOffset:d,fromIsPercentage:!1,toOffset:f,toIsPercentage:!1}),g=q(u);o.set(c.curveIndex,{bezier:u,arcLengthTable:g})}}}return o}function te(e,t,s){const{graph:n,linesMap:o,curves:c,config:r}=s,i=o.get(t.targetLineId);if(!i)return null;const d=G(i)-r.wheelbase;if(d<=0)return null;const f=t.isPercentage?t.targetOffset/100*d:Math.min(t.targetOffset,d),u=K(n,{lineId:e.rear.lineId,offset:e.rear.absoluteOffset},t.targetLineId,f,!1);if(!u)return null;const g=ee(u,c,o,r);return{path:u,curveDataMap:g}}function ne(e,t){const s=e.execution,n=t.vehicleQueues.get(e.vehicle.id),o=n?.[s.currentCommandIndex];if(o&&t.onCommandComplete&&t.onCommandComplete({vehicleId:e.vehicle.id,command:o,finalPosition:{lineId:e.vehicle.rear.lineId,absoluteOffset:e.vehicle.rear.absoluteOffset,position:e.vehicle.rear.position},payload:o.payload}),o?.awaitConfirmation)return{handled:!0,vehicle:{...e.vehicle,state:"waiting"},newExecution:s,isWaiting:!0};const c=s.currentCommandIndex+1;if(n&&c<n.length){const i=n[c],l=t.graphRef.current;if(l){const d={graph:l,linesMap:t.linesMap,curves:t.curves,config:t.config},f=t.prepareCommandPath(e.vehicle,i,d);if(f){const u=k(f.path,0,0,t.config.wheelbase);t.onCommandStart&&t.onCommandStart({vehicleId:e.vehicle.id,command:i,commandIndex:c,startPosition:{lineId:e.vehicle.rear.lineId,absoluteOffset:e.vehicle.rear.absoluteOffset,position:e.vehicle.rear.position}});const g={path:f.path,curveDataMap:f.curveDataMap,currentCommandIndex:c,rear:{currentSegmentIndex:0,segmentDistance:0},front:u?{currentSegmentIndex:u.segmentIndex,segmentDistance:u.segmentDistance}:{currentSegmentIndex:0,segmentDistance:0}};return{handled:!0,vehicle:{...e.vehicle,state:"moving"},newExecution:g}}}}return{handled:!0,vehicle:{...e.vehicle,state:"idle"},newExecution:null}}exports.arcLengthToSegmentPosition=$;exports.buildArcLengthTable=q;exports.buildGraph=U;exports.calculateBezierArcLength=j;exports.calculateFrontAxlePosition=k;exports.calculateInitialFrontPosition=X;exports.calculatePositionOnCurve=M;exports.calculatePositionOnLine=O;exports.calculateTangentLength=V;exports.createBezierCurve=C;exports.createInitialMovementState=R;exports.distance=p;exports.distanceToT=F;exports.findPath=K;exports.getArcLength=J;exports.getCumulativeArcLength=N;exports.getLineLength=G;exports.getPointOnBezier=w;exports.getPointOnLine=B;exports.getPointOnLineByOffset=D;exports.getPositionFromOffset=b;exports.handleArrival=ne;exports.initializeAllVehicles=Y;exports.initializeMovingVehicle=Q;exports.isPointNearPoint=H;exports.normalize=P;exports.prepareCommandPath=te;exports.resolveFromLineOffset=S;exports.resolveToLineOffset=T;exports.updateAxlePosition=Z;
|