vehicle-path2 2.3.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.
- package/dist/core/algorithms/geometry.d.ts +31 -0
- package/dist/core/engine.d.ts +7 -7
- package/dist/core/index.d.ts +2 -1
- package/dist/core/snapshot.d.ts +4 -26
- package/dist/core/types/vehicle.d.ts +12 -2
- package/dist/core.cjs +1 -1
- package/dist/core.js +78 -58
- package/dist/{index-D-HctiIv.js → index-BV93143R.js} +268 -264
- package/dist/index-C4FckUel.cjs +1 -0
- package/dist/vehicle-path.cjs +1 -1
- package/dist/vehicle-path.js +3 -3
- package/package.json +1 -1
- package/dist/index-BUYdltrL.cjs +0 -1
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Point, Line, Curve } from '../types/geometry';
|
|
2
|
+
/**
|
|
3
|
+
* Project a point onto a line segment.
|
|
4
|
+
*
|
|
5
|
+
* Returns:
|
|
6
|
+
* - offset: absolute distance from line.start along the line (clamped to [0, lineLength])
|
|
7
|
+
* - distance: perpendicular distance from point to the nearest point on the line
|
|
8
|
+
*/
|
|
9
|
+
export declare function projectPointOnLine(point: Point, line: Line): {
|
|
10
|
+
offset: number;
|
|
11
|
+
distance: number;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Compute the valid [min, max] offset range for placing the rear axle of a
|
|
15
|
+
* multi-axle vehicle on a line.
|
|
16
|
+
*
|
|
17
|
+
* - min is always 0 (rear axle at line start)
|
|
18
|
+
* - max is lineLength - totalAxleSpacing (so all axles fit on the line)
|
|
19
|
+
* - If the vehicle is too long for the line, returns [0, 0]
|
|
20
|
+
*/
|
|
21
|
+
export declare function getValidRearOffsetRange(line: Line, axleSpacings: number[]): [number, number];
|
|
22
|
+
/**
|
|
23
|
+
* Compute the minimum length a line must have so that all attached curve
|
|
24
|
+
* offsets (fromOffset / toOffset) remain within valid bounds.
|
|
25
|
+
*
|
|
26
|
+
* Only absolute offsets contribute to the minimum — percentage-based offsets
|
|
27
|
+
* scale with the line and therefore impose no hard minimum.
|
|
28
|
+
*
|
|
29
|
+
* Returns 0 if no curves are attached or all offsets are percentage-based.
|
|
30
|
+
*/
|
|
31
|
+
export declare function computeMinLineLength(lineId: string, curves: Curve[]): number;
|
package/dist/core/engine.d.ts
CHANGED
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
* ```typescript
|
|
10
10
|
* import { PathEngine } from 'vehicle-path/core'
|
|
11
11
|
*
|
|
12
|
-
* const engine = new PathEngine({
|
|
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
|
|
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,
|
|
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
|
*
|
package/dist/core/index.d.ts
CHANGED
|
@@ -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';
|
|
@@ -20,3 +20,4 @@ export { initializeMovingVehicle, createInitialMovementState, initializeAllVehic
|
|
|
20
20
|
export { PathEngine, type PathEngineConfig, type VehiclePathState, type PathExecution } from './engine';
|
|
21
21
|
export { distance, normalize, getPointOnLine, getPointOnLineByOffset, getPointOnBezier, createBezierCurve, buildArcLengthTable, distanceToT, getArcLength, calculateTangentLength, isPointNearPoint, type ArcLengthEntry, type CurveOffsetOptions } from './algorithms/math';
|
|
22
22
|
export { serializeScene, deserializeScene, type SceneSnapshot } from './snapshot';
|
|
23
|
+
export { projectPointOnLine, getValidRearOffsetRange, computeMinLineLength } from './algorithms/geometry';
|
package/dist/core/snapshot.d.ts
CHANGED
|
@@ -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
|
|
25
|
-
*
|
|
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-
|
|
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,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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) => ({
|
|
6
7
|
id: e.id,
|
|
7
8
|
fromLineId: e.fromLineId,
|
|
8
9
|
toLineId: e.toLineId,
|
|
@@ -10,69 +11,88 @@ function n(s, a, i) {
|
|
|
10
11
|
fromIsPercentage: e.fromIsPercentage ?? !1,
|
|
11
12
|
toOffset: e.toOffset,
|
|
12
13
|
toIsPercentage: e.toIsPercentage ?? !1
|
|
13
|
-
})),
|
|
14
|
-
vehicles: i.map((e) => ({
|
|
15
|
-
id: e.id,
|
|
16
|
-
lineId: e.axles[0].lineId,
|
|
17
|
-
axles: e.axles.map((t) => ({ offset: t.offset })),
|
|
18
|
-
axleSpacings: e.axleSpacings,
|
|
19
|
-
isPercentage: e.isPercentage ?? !1
|
|
20
14
|
}))
|
|
21
15
|
};
|
|
22
|
-
return JSON.stringify(
|
|
16
|
+
return JSON.stringify(s, null, 2);
|
|
23
17
|
}
|
|
24
|
-
function
|
|
25
|
-
let
|
|
18
|
+
function g(a) {
|
|
19
|
+
let t;
|
|
26
20
|
try {
|
|
27
|
-
|
|
21
|
+
t = JSON.parse(a);
|
|
28
22
|
} catch {
|
|
29
23
|
throw new Error("deserializeScene: invalid JSON");
|
|
30
24
|
}
|
|
31
|
-
if (!
|
|
25
|
+
if (!t || typeof t != "object" || Array.isArray(t))
|
|
32
26
|
throw new Error("deserializeScene: expected a JSON object");
|
|
33
|
-
const
|
|
34
|
-
if (!Array.isArray(
|
|
35
|
-
if (!Array.isArray(
|
|
36
|
-
if (!Array.isArray(i.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"');
|
|
37
30
|
return {
|
|
38
|
-
lines:
|
|
39
|
-
curves:
|
|
40
|
-
vehicles: i.vehicles
|
|
31
|
+
lines: s.lines,
|
|
32
|
+
curves: s.curves
|
|
41
33
|
};
|
|
42
34
|
}
|
|
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)
|
|
38
|
+
return { offset: 0, distance: Math.sqrt(
|
|
39
|
+
(a.x - t.start.x) ** 2 + (a.y - t.start.y) ** 2
|
|
40
|
+
) };
|
|
41
|
+
const r = Math.max(
|
|
42
|
+
0,
|
|
43
|
+
Math.min(
|
|
44
|
+
1,
|
|
45
|
+
((a.x - t.start.x) * s + (a.y - t.start.y) * e) / n
|
|
46
|
+
)
|
|
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 };
|
|
49
|
+
}
|
|
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)];
|
|
53
|
+
}
|
|
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;
|
|
59
|
+
}
|
|
43
60
|
export {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
O as
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
61
|
+
y as PathEngine,
|
|
62
|
+
v as arcLengthToSegmentPosition,
|
|
63
|
+
A as buildArcLengthTable,
|
|
64
|
+
S as buildGraph,
|
|
65
|
+
p as calculateBezierArcLength,
|
|
66
|
+
z as calculateFrontAxlePosition,
|
|
67
|
+
I as calculateInitialAxlePositions,
|
|
68
|
+
M as calculatePositionOnCurve,
|
|
69
|
+
w as calculatePositionOnLine,
|
|
70
|
+
b as calculateTangentLength,
|
|
71
|
+
O as computeMinLineLength,
|
|
72
|
+
j as createBezierCurve,
|
|
73
|
+
E as createInitialMovementState,
|
|
74
|
+
g as deserializeScene,
|
|
75
|
+
T as distance,
|
|
76
|
+
q as distanceToT,
|
|
77
|
+
B as findPath,
|
|
78
|
+
C as getArcLength,
|
|
79
|
+
N as getCumulativeArcLength,
|
|
80
|
+
f as getLineLength,
|
|
81
|
+
J as getPointOnBezier,
|
|
82
|
+
V as getPointOnLine,
|
|
83
|
+
F as getPointOnLineByOffset,
|
|
84
|
+
R as getPositionFromOffset,
|
|
85
|
+
L as getValidRearOffsetRange,
|
|
86
|
+
k as handleArrival,
|
|
87
|
+
D as initializeAllVehicles,
|
|
88
|
+
G as initializeMovingVehicle,
|
|
89
|
+
X as isPointNearPoint,
|
|
90
|
+
Y as moveVehicle,
|
|
91
|
+
H as normalize,
|
|
92
|
+
K as prepareCommandPath,
|
|
93
|
+
h as projectPointOnLine,
|
|
94
|
+
Q as resolveFromLineOffset,
|
|
95
|
+
U as resolveToLineOffset,
|
|
96
|
+
u as serializeScene,
|
|
97
|
+
W as updateAxlePosition
|
|
78
98
|
};
|