@ingissa/navcore-core 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/README.md +279 -136
- package/dist/{NavCore-DzTPBxIc.d.mts → NavCore-qf5_0qsR.d.mts} +50 -47
- package/dist/{NavCore-DzTPBxIc.d.ts → NavCore-qf5_0qsR.d.ts} +50 -47
- package/dist/core.d.mts +7 -23
- package/dist/core.d.ts +7 -23
- package/dist/core.js +2 -2
- package/dist/core.mjs +2 -2
- package/dist/index.d.mts +2 -65
- package/dist/index.d.ts +2 -65
- package/dist/index.js +3 -3
- package/dist/index.mjs +3 -3
- package/dist/index.pro-C5J1xlzt.d.ts +535 -0
- package/dist/index.pro-Cg6394f_.d.mts +535 -0
- package/dist/pro.d.mts +2 -488
- package/dist/pro.d.ts +2 -488
- package/dist/pro.js +1 -1
- package/dist/pro.mjs +1 -1
- package/package.json +5 -5
|
@@ -34,7 +34,7 @@ interface InstructionResult {
|
|
|
34
34
|
/**
|
|
35
35
|
* Resolve which instruction is next and whether it should trigger now.
|
|
36
36
|
*/
|
|
37
|
-
declare function resolveNextInstruction(currentGeometryIdx: number, instructions: NavInstruction[], currentInstrIdx: number, route: Coordinate[], currentCoord: Coordinate, vehicleBearing: number | null, vehicleDistance: number, speed?: number): InstructionResult;
|
|
37
|
+
declare function resolveNextInstruction(currentGeometryIdx: number, instructions: NavInstruction[], currentInstrIdx: number, route: Coordinate[], currentCoord: Coordinate, vehicleBearing: number | null, vehicleDistance: number, speed?: number, isCircuit?: boolean): InstructionResult;
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
40
|
* Module 9a: NavigationFSM
|
|
@@ -151,12 +151,8 @@ declare class OffRouteFSM {
|
|
|
151
151
|
/**
|
|
152
152
|
* Feature flag constants for SDK consumers.
|
|
153
153
|
*
|
|
154
|
-
* CORE features: available to all users
|
|
155
|
-
*
|
|
156
|
-
* progress tracking, and route offset prediction are all free.
|
|
157
|
-
*
|
|
158
|
-
* PRO features: require a valid commercial license key.
|
|
159
|
-
* Each PRO engine checks the license at runtime and gracefully degrades.
|
|
154
|
+
* CORE features: available to all users (MIT license).
|
|
155
|
+
* PRO features: require a valid commercial license key.
|
|
160
156
|
*/
|
|
161
157
|
declare const FEATURES: {
|
|
162
158
|
/**
|
|
@@ -165,45 +161,43 @@ declare const FEATURES: {
|
|
|
165
161
|
*/
|
|
166
162
|
readonly GPS_SMOOTHING: "gps_smoothing";
|
|
167
163
|
/**
|
|
168
|
-
* Basic route snapping (nearest-point projection)
|
|
169
|
-
*
|
|
170
|
-
* Both basic and advanced snapping quality are available in the free tier.
|
|
164
|
+
* Basic route snapping (nearest-point projection).
|
|
165
|
+
* Snaps GPS position to the closest route segment.
|
|
171
166
|
*/
|
|
172
167
|
readonly BASIC_SNAPPING: "basic_snapping";
|
|
173
168
|
/**
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
* Used unconditionally inside NavCore — available in the free tier.
|
|
169
|
+
* Advanced route snapping with bearing penalty + inertia.
|
|
170
|
+
* Prevents incorrect snaps on parallel roads and U-turns.
|
|
177
171
|
*/
|
|
178
|
-
readonly
|
|
172
|
+
readonly ADVANCED_SNAPPING: "advanced_snapping";
|
|
173
|
+
/**
|
|
174
|
+
* Dead reckoning: continues navigation during GPS signal loss.
|
|
175
|
+
* Predicts position based on last known speed and bearing.
|
|
176
|
+
*/
|
|
177
|
+
readonly DEAD_RECKONING: "dead_reckoning";
|
|
179
178
|
/**
|
|
180
179
|
* Smooth route offset predictor for jitter-free map rendering.
|
|
181
180
|
* Advances render position at frame rate between GPS fixes.
|
|
182
|
-
* Used unconditionally inside NavCore — available in the free tier.
|
|
183
181
|
*/
|
|
184
182
|
readonly ROUTE_OFFSET: "route_offset";
|
|
185
183
|
/**
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
* DeadReckoningEngine.predict() is a no-op without a Pro license.
|
|
184
|
+
* Progress anti-regression: prevents route index from jumping backward.
|
|
185
|
+
* Essential for circuit routes and motorway slip roads.
|
|
189
186
|
*/
|
|
190
|
-
readonly
|
|
187
|
+
readonly PROGRESS_TRACKING: "progress_tracking";
|
|
191
188
|
/**
|
|
192
189
|
* Advanced bearing engine with look-ahead and speed-adaptive alpha.
|
|
193
190
|
* Produces stable heading for smooth map camera rotation.
|
|
194
|
-
* Gated inside NavCore.update() via this.has(FEATURES.ADVANCED_BEARING).
|
|
195
191
|
*/
|
|
196
192
|
readonly ADVANCED_BEARING: "advanced_bearing";
|
|
197
193
|
/**
|
|
198
194
|
* Compound deviation detection: combines distance, bearing, and speed signals.
|
|
199
195
|
* Eliminates false off-route triggers in tunnels and urban canyons.
|
|
200
|
-
* DeviationDetector.evaluate() returns a neutral signal without a Pro license.
|
|
201
196
|
*/
|
|
202
197
|
readonly COMPOUND_DEVIATION: "compound_deviation";
|
|
203
198
|
/**
|
|
204
199
|
* Parallel road disambiguation + U-turn snap protection.
|
|
205
200
|
* Prevents snapping to the wrong carriageway when bearing mismatches route direction.
|
|
206
|
-
* ParallelRoadResolver falls back to pure distance sorting without a Pro license.
|
|
207
201
|
*/
|
|
208
202
|
readonly PARALLEL_ROAD_RESOLUTION: "parallel_road_resolution";
|
|
209
203
|
/**
|
|
@@ -213,17 +207,14 @@ declare const FEATURES: {
|
|
|
213
207
|
readonly U_TURN_PROTECTION: "u_turn_protection";
|
|
214
208
|
/**
|
|
215
209
|
* Timed voice instruction cues with deduplication and priority levels.
|
|
216
|
-
* VoiceTriggerEngine.update() returns null without a Pro license.
|
|
217
210
|
*/
|
|
218
211
|
readonly VOICE_TRIGGERS: "voice_triggers";
|
|
219
212
|
/**
|
|
220
213
|
* Local ETA computation using rolling speed average — zero API calls.
|
|
221
|
-
* ETAEngine.update() returns isReliable=false without a Pro license.
|
|
222
214
|
*/
|
|
223
215
|
readonly ETA: "eta";
|
|
224
216
|
/**
|
|
225
217
|
* Circular and polygon geofencing with enter/exit/dwell events.
|
|
226
|
-
* GeofencingEngine.update() returns [] without a Pro license.
|
|
227
218
|
*/
|
|
228
219
|
readonly GEOFENCING: "geofencing";
|
|
229
220
|
/**
|
|
@@ -256,25 +247,9 @@ declare class LicenseManager {
|
|
|
256
247
|
private payload;
|
|
257
248
|
private enabledFeatures;
|
|
258
249
|
private warnedFeatures;
|
|
259
|
-
private
|
|
260
|
-
static getActive(): LicenseManager | null;
|
|
261
|
-
/**
|
|
262
|
-
* Clear the active manager reference.
|
|
263
|
-
* Intended for test teardown only — not for production use.
|
|
264
|
-
*/
|
|
265
|
-
static clearActive(): void;
|
|
266
|
-
/**
|
|
267
|
-
* Promote this instance to the global active manager.
|
|
268
|
-
*
|
|
269
|
-
* Security rule: A VALID license context cannot be overwritten by an
|
|
270
|
-
* INVALID / MISSING / EXPIRED one. Once a valid license is registered,
|
|
271
|
-
* it holds the slot until explicitly cleared or replaced by another
|
|
272
|
-
* valid license.
|
|
273
|
-
*/
|
|
274
|
-
private promoteToActive;
|
|
250
|
+
private isDev;
|
|
275
251
|
private static PUBLIC_KEY_SPKI;
|
|
276
|
-
constructor(licenseKey?: string);
|
|
277
|
-
private tryValidateSync;
|
|
252
|
+
constructor(licenseKey?: string, isDev?: boolean);
|
|
278
253
|
validate(key: string): Promise<LicenseStatus>;
|
|
279
254
|
private extractFeatures;
|
|
280
255
|
hasFeature(feature: FeatureKey): boolean;
|
|
@@ -311,6 +286,7 @@ interface NavGpsUpdate {
|
|
|
311
286
|
}
|
|
312
287
|
interface NavCoreOptions {
|
|
313
288
|
licenseKey?: string;
|
|
289
|
+
isDev?: boolean;
|
|
314
290
|
isCircuit?: boolean;
|
|
315
291
|
kalmanQ?: number;
|
|
316
292
|
kalmanRBase?: number;
|
|
@@ -321,24 +297,47 @@ interface NavCoreOptions {
|
|
|
321
297
|
}
|
|
322
298
|
interface NavCoreState {
|
|
323
299
|
snappedCoord: Coordinate | null;
|
|
300
|
+
ghostCoord: Coordinate | null;
|
|
324
301
|
rawGpsCoord: Coordinate | null;
|
|
325
302
|
bearing: number;
|
|
326
303
|
rawGpsBearing: number | null;
|
|
327
304
|
routeIndex: number;
|
|
305
|
+
anchorRouteIndex: number | null;
|
|
328
306
|
distanceToRoute: number;
|
|
329
307
|
corridor: number;
|
|
308
|
+
confidence: number;
|
|
330
309
|
isOffRoute: boolean;
|
|
310
|
+
navFsmState: string;
|
|
331
311
|
progressIndex: number;
|
|
332
312
|
hasArrived: boolean;
|
|
333
|
-
|
|
334
|
-
|
|
313
|
+
rejoinCandidate: {
|
|
314
|
+
coord: Coordinate;
|
|
315
|
+
index: number;
|
|
316
|
+
} | null;
|
|
317
|
+
confidenceCone: {
|
|
318
|
+
center: Coordinate;
|
|
319
|
+
bearing: number;
|
|
320
|
+
angle: number;
|
|
321
|
+
length: number;
|
|
322
|
+
} | null;
|
|
323
|
+
alertState: 'NONE' | 'DEVIATING' | 'RECALCULATING' | 'REJOINING' | 'REJOINED';
|
|
324
|
+
detourMode: 'NONE' | 'FREE' | 'COMMITTED';
|
|
325
|
+
detourCommitProgress: number;
|
|
335
326
|
distanceToDestination: number | null;
|
|
336
327
|
distanceToNextInstruction: number | null;
|
|
328
|
+
nextInstrIdx: number | null;
|
|
337
329
|
nextInstructionIndex: number | null;
|
|
338
330
|
currentSpeed: number;
|
|
339
331
|
isGpsStale: boolean;
|
|
340
332
|
gpsAgeMs: number;
|
|
341
333
|
licenseStatus: string;
|
|
334
|
+
offRouteState: string;
|
|
335
|
+
lifecycleState: string;
|
|
336
|
+
stability?: {
|
|
337
|
+
oscillation: number;
|
|
338
|
+
drift: number;
|
|
339
|
+
jump: number;
|
|
340
|
+
};
|
|
342
341
|
}
|
|
343
342
|
type EventHandler = (...args: unknown[]) => void;
|
|
344
343
|
declare class NavCore {
|
|
@@ -354,6 +353,7 @@ declare class NavCore {
|
|
|
354
353
|
private forwardCum;
|
|
355
354
|
private reverseCum;
|
|
356
355
|
private snappedCoord;
|
|
356
|
+
private ghostCoord;
|
|
357
357
|
private rawGpsCoord;
|
|
358
358
|
private bearing;
|
|
359
359
|
private rawGpsBearing;
|
|
@@ -371,8 +371,11 @@ declare class NavCore {
|
|
|
371
371
|
private readonly options;
|
|
372
372
|
private listeners;
|
|
373
373
|
constructor(options?: NavCoreOptions);
|
|
374
|
-
/**
|
|
375
|
-
|
|
374
|
+
/**
|
|
375
|
+
* Returns true if the feature is unlocked (dev mode OR valid license).
|
|
376
|
+
* Emits a one-time console warning when a Pro feature is blocked.
|
|
377
|
+
*/
|
|
378
|
+
private has;
|
|
376
379
|
/** Load route geometry and instructions */
|
|
377
380
|
setRoute(route: Coordinate[], instructions?: NavInstruction[]): void;
|
|
378
381
|
/** Start navigation */
|
package/dist/core.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as Coordinate, g as NavCoreState } from './NavCore-
|
|
2
|
-
export { F as FEATURES, a as FeatureKey, L as LicenseManager, b as LicensePayload, c as LicenseStatus, o as destinationPoint, p as geoGetBearing, q as haversineDistance } from './NavCore-
|
|
1
|
+
import { C as Coordinate, g as NavCoreState } from './NavCore-qf5_0qsR.mjs';
|
|
2
|
+
export { F as FEATURES, a as FeatureKey, L as LicenseManager, b as LicensePayload, c as LicenseStatus, o as destinationPoint, p as geoGetBearing, q as haversineDistance } from './NavCore-qf5_0qsR.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Bearing and angular math utilities.
|
|
@@ -281,10 +281,6 @@ interface OSRMConfig {
|
|
|
281
281
|
profile?: 'driving' | 'cycling' | 'walking';
|
|
282
282
|
/** Max waypoints per API request (OSRM supports unlimited, but chunking keeps requests fast) */
|
|
283
283
|
maxWaypointsPerChunk?: number;
|
|
284
|
-
/** Optional fetch implementation for tests, React Native, or custom runtimes */
|
|
285
|
-
fetchFn?: typeof fetch;
|
|
286
|
-
/** Request timeout in milliseconds. Set to 0 to disable. */
|
|
287
|
-
timeoutMs?: number;
|
|
288
284
|
}
|
|
289
285
|
declare class OSRMDirectionsProvider implements DirectionsProvider {
|
|
290
286
|
private readonly config;
|
|
@@ -292,7 +288,6 @@ declare class OSRMDirectionsProvider implements DirectionsProvider {
|
|
|
292
288
|
getRoute(waypoints: Coordinate[], options?: DirectionsOptions): Promise<DirectionsResult>;
|
|
293
289
|
private fetchRoute;
|
|
294
290
|
private fetchChunked;
|
|
295
|
-
private fetchWithTimeout;
|
|
296
291
|
}
|
|
297
292
|
|
|
298
293
|
/**
|
|
@@ -315,10 +310,6 @@ interface ValhallaConfig {
|
|
|
315
310
|
apiKey?: string;
|
|
316
311
|
/** Max waypoints per chunk (default: 50) */
|
|
317
312
|
maxWaypointsPerChunk?: number;
|
|
318
|
-
/** Optional fetch implementation for tests, React Native, or custom runtimes */
|
|
319
|
-
fetchFn?: typeof fetch;
|
|
320
|
-
/** Request timeout in milliseconds. Set to 0 to disable. */
|
|
321
|
-
timeoutMs?: number;
|
|
322
313
|
}
|
|
323
314
|
declare class ValhallaDirectionsProvider implements DirectionsProvider {
|
|
324
315
|
private readonly config;
|
|
@@ -328,11 +319,7 @@ declare class ValhallaDirectionsProvider implements DirectionsProvider {
|
|
|
328
319
|
private fetchRoute;
|
|
329
320
|
/** Decode Valhalla's encoded polyline6 format */
|
|
330
321
|
private decodePolyline;
|
|
331
|
-
private stitchGeometry;
|
|
332
|
-
private sameCoordinate;
|
|
333
|
-
private shapeIndex;
|
|
334
322
|
private fetchChunked;
|
|
335
|
-
private fetchWithTimeout;
|
|
336
323
|
}
|
|
337
324
|
|
|
338
325
|
/**
|
|
@@ -354,10 +341,6 @@ interface ORSConfig {
|
|
|
354
341
|
baseUrl?: string;
|
|
355
342
|
/** Max waypoints per request (ORS limit: 50) */
|
|
356
343
|
maxWaypointsPerChunk?: number;
|
|
357
|
-
/** Optional fetch implementation for tests, React Native, or custom runtimes */
|
|
358
|
-
fetchFn?: typeof fetch;
|
|
359
|
-
/** Request timeout in milliseconds. Set to 0 to disable. */
|
|
360
|
-
timeoutMs?: number;
|
|
361
344
|
}
|
|
362
345
|
declare class OpenRouteServiceProvider implements DirectionsProvider {
|
|
363
346
|
private readonly config;
|
|
@@ -366,9 +349,6 @@ declare class OpenRouteServiceProvider implements DirectionsProvider {
|
|
|
366
349
|
private profileFromOptions;
|
|
367
350
|
private fetchRoute;
|
|
368
351
|
private fetchChunked;
|
|
369
|
-
private stepRange;
|
|
370
|
-
private bearingFromGeometry;
|
|
371
|
-
private fetchWithTimeout;
|
|
372
352
|
}
|
|
373
353
|
|
|
374
354
|
/**
|
|
@@ -450,6 +430,8 @@ declare const BASE_CORRIDOR_METERS = 25;
|
|
|
450
430
|
declare const MAX_CORRIDOR_METERS = 60;
|
|
451
431
|
declare const SPEED_CORRIDOR_FACTOR = 1.2;
|
|
452
432
|
declare const GPS_ACCURACY_FACTOR = 0.5;
|
|
433
|
+
declare const TURN_LOOKAHEAD_DISTANCE_METERS = 40;
|
|
434
|
+
declare const TURN_CORRIDOR_MULTIPLIER = 1.4;
|
|
453
435
|
declare const MAX_SNAP_DISTANCE = 80;
|
|
454
436
|
declare const BEARING_MISMATCH_THRESHOLD = 90;
|
|
455
437
|
declare const BEARING_MISMATCH_PENALTY = 500;
|
|
@@ -501,8 +483,10 @@ declare const constants_REJOIN_COOLDOWN_MS: typeof REJOIN_COOLDOWN_MS;
|
|
|
501
483
|
declare const constants_SNAP_WINDOW_SIZE: typeof SNAP_WINDOW_SIZE;
|
|
502
484
|
declare const constants_SPEED_CORRIDOR_FACTOR: typeof SPEED_CORRIDOR_FACTOR;
|
|
503
485
|
declare const constants_STARTUP_GRACE_MS: typeof STARTUP_GRACE_MS;
|
|
486
|
+
declare const constants_TURN_CORRIDOR_MULTIPLIER: typeof TURN_CORRIDOR_MULTIPLIER;
|
|
487
|
+
declare const constants_TURN_LOOKAHEAD_DISTANCE_METERS: typeof TURN_LOOKAHEAD_DISTANCE_METERS;
|
|
504
488
|
declare namespace constants {
|
|
505
|
-
export { constants_ARRIVAL_THRESHOLD_METERS as ARRIVAL_THRESHOLD_METERS, constants_BASE_CORRIDOR_METERS as BASE_CORRIDOR_METERS, constants_BEARING_ALIGNMENT_THRESHOLD as BEARING_ALIGNMENT_THRESHOLD, constants_BEARING_MIN_SPEED_MPS as BEARING_MIN_SPEED_MPS, constants_BEARING_MISMATCH_PENALTY as BEARING_MISMATCH_PENALTY, constants_BEARING_MISMATCH_THRESHOLD as BEARING_MISMATCH_THRESHOLD, constants_BEARING_SMOOTHING_ALPHA as BEARING_SMOOTHING_ALPHA, constants_BETA_CORRECTION as BETA_CORRECTION, constants_DETOUR_COMMIT_MS as DETOUR_COMMIT_MS, constants_DR_MAX_AGE_MS as DR_MAX_AGE_MS, constants_GPS_ACCURACY_FACTOR as GPS_ACCURACY_FACTOR, constants_GPS_AGE_CAP_SECONDS as GPS_AGE_CAP_SECONDS, constants_GPS_STALE_MS as GPS_STALE_MS, constants_INERTIA_PENALTY as INERTIA_PENALTY, constants_INERTIA_SEGMENT_DIST as INERTIA_SEGMENT_DIST, constants_LOOK_AHEAD_SECONDS as LOOK_AHEAD_SECONDS, constants_MANEUVER_TRIGGER_DIST as MANEUVER_TRIGGER_DIST, constants_MAX_CORRIDOR_METERS as MAX_CORRIDOR_METERS, constants_MAX_LOOK_AHEAD_METERS as MAX_LOOK_AHEAD_METERS, constants_MAX_SNAP_DISTANCE as MAX_SNAP_DISTANCE, constants_MIN_LOOK_AHEAD_METERS as MIN_LOOK_AHEAD_METERS, constants_OFF_ROUTE_CONFIRM_MS as OFF_ROUTE_CONFIRM_MS, constants_REJOIN_CONFIRM_MS as REJOIN_CONFIRM_MS, constants_REJOIN_COOLDOWN_MS as REJOIN_COOLDOWN_MS, constants_SNAP_WINDOW_SIZE as SNAP_WINDOW_SIZE, constants_SPEED_CORRIDOR_FACTOR as SPEED_CORRIDOR_FACTOR, constants_STARTUP_GRACE_MS as STARTUP_GRACE_MS };
|
|
489
|
+
export { constants_ARRIVAL_THRESHOLD_METERS as ARRIVAL_THRESHOLD_METERS, constants_BASE_CORRIDOR_METERS as BASE_CORRIDOR_METERS, constants_BEARING_ALIGNMENT_THRESHOLD as BEARING_ALIGNMENT_THRESHOLD, constants_BEARING_MIN_SPEED_MPS as BEARING_MIN_SPEED_MPS, constants_BEARING_MISMATCH_PENALTY as BEARING_MISMATCH_PENALTY, constants_BEARING_MISMATCH_THRESHOLD as BEARING_MISMATCH_THRESHOLD, constants_BEARING_SMOOTHING_ALPHA as BEARING_SMOOTHING_ALPHA, constants_BETA_CORRECTION as BETA_CORRECTION, constants_DETOUR_COMMIT_MS as DETOUR_COMMIT_MS, constants_DR_MAX_AGE_MS as DR_MAX_AGE_MS, constants_GPS_ACCURACY_FACTOR as GPS_ACCURACY_FACTOR, constants_GPS_AGE_CAP_SECONDS as GPS_AGE_CAP_SECONDS, constants_GPS_STALE_MS as GPS_STALE_MS, constants_INERTIA_PENALTY as INERTIA_PENALTY, constants_INERTIA_SEGMENT_DIST as INERTIA_SEGMENT_DIST, constants_LOOK_AHEAD_SECONDS as LOOK_AHEAD_SECONDS, constants_MANEUVER_TRIGGER_DIST as MANEUVER_TRIGGER_DIST, constants_MAX_CORRIDOR_METERS as MAX_CORRIDOR_METERS, constants_MAX_LOOK_AHEAD_METERS as MAX_LOOK_AHEAD_METERS, constants_MAX_SNAP_DISTANCE as MAX_SNAP_DISTANCE, constants_MIN_LOOK_AHEAD_METERS as MIN_LOOK_AHEAD_METERS, constants_OFF_ROUTE_CONFIRM_MS as OFF_ROUTE_CONFIRM_MS, constants_REJOIN_CONFIRM_MS as REJOIN_CONFIRM_MS, constants_REJOIN_COOLDOWN_MS as REJOIN_COOLDOWN_MS, constants_SNAP_WINDOW_SIZE as SNAP_WINDOW_SIZE, constants_SPEED_CORRIDOR_FACTOR as SPEED_CORRIDOR_FACTOR, constants_STARTUP_GRACE_MS as STARTUP_GRACE_MS, constants_TURN_CORRIDOR_MULTIPLIER as TURN_CORRIDOR_MULTIPLIER, constants_TURN_LOOKAHEAD_DISTANCE_METERS as TURN_LOOKAHEAD_DISTANCE_METERS };
|
|
506
490
|
}
|
|
507
491
|
|
|
508
492
|
export { type BuildOptions, type CameraOptions, constants as Constants, Coordinate, CustomRouteBuilder, type CustomWaypoint, type DirectionsLeg, type DirectionsManeuver, type DirectionsOptions, type DirectionsProvider, type DirectionsResult, type DirectionsStep, type Kalman2DState, KalmanFilter2D, type MapRendererAdapter, type ORSConfig, type ORSProfile, type OSRMConfig, OSRMDirectionsProvider, OpenRouteServiceProvider, RouteSnapper, type RouteStyle, type SnapResult, type SnapperOptions, type ValhallaConfig, type ValhallaCostingModel, ValhallaDirectionsProvider, type VehicleStyle, type WaypointOptions, buildForwardCumulativeDistances, buildReverseCumulativeDistances, getBearingBetweenPoints, interpolatePoint, kalmanUpdate2D, normalizeAngle, projectPointOnSegment };
|
package/dist/core.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as Coordinate, g as NavCoreState } from './NavCore-
|
|
2
|
-
export { F as FEATURES, a as FeatureKey, L as LicenseManager, b as LicensePayload, c as LicenseStatus, o as destinationPoint, p as geoGetBearing, q as haversineDistance } from './NavCore-
|
|
1
|
+
import { C as Coordinate, g as NavCoreState } from './NavCore-qf5_0qsR.js';
|
|
2
|
+
export { F as FEATURES, a as FeatureKey, L as LicenseManager, b as LicensePayload, c as LicenseStatus, o as destinationPoint, p as geoGetBearing, q as haversineDistance } from './NavCore-qf5_0qsR.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Bearing and angular math utilities.
|
|
@@ -281,10 +281,6 @@ interface OSRMConfig {
|
|
|
281
281
|
profile?: 'driving' | 'cycling' | 'walking';
|
|
282
282
|
/** Max waypoints per API request (OSRM supports unlimited, but chunking keeps requests fast) */
|
|
283
283
|
maxWaypointsPerChunk?: number;
|
|
284
|
-
/** Optional fetch implementation for tests, React Native, or custom runtimes */
|
|
285
|
-
fetchFn?: typeof fetch;
|
|
286
|
-
/** Request timeout in milliseconds. Set to 0 to disable. */
|
|
287
|
-
timeoutMs?: number;
|
|
288
284
|
}
|
|
289
285
|
declare class OSRMDirectionsProvider implements DirectionsProvider {
|
|
290
286
|
private readonly config;
|
|
@@ -292,7 +288,6 @@ declare class OSRMDirectionsProvider implements DirectionsProvider {
|
|
|
292
288
|
getRoute(waypoints: Coordinate[], options?: DirectionsOptions): Promise<DirectionsResult>;
|
|
293
289
|
private fetchRoute;
|
|
294
290
|
private fetchChunked;
|
|
295
|
-
private fetchWithTimeout;
|
|
296
291
|
}
|
|
297
292
|
|
|
298
293
|
/**
|
|
@@ -315,10 +310,6 @@ interface ValhallaConfig {
|
|
|
315
310
|
apiKey?: string;
|
|
316
311
|
/** Max waypoints per chunk (default: 50) */
|
|
317
312
|
maxWaypointsPerChunk?: number;
|
|
318
|
-
/** Optional fetch implementation for tests, React Native, or custom runtimes */
|
|
319
|
-
fetchFn?: typeof fetch;
|
|
320
|
-
/** Request timeout in milliseconds. Set to 0 to disable. */
|
|
321
|
-
timeoutMs?: number;
|
|
322
313
|
}
|
|
323
314
|
declare class ValhallaDirectionsProvider implements DirectionsProvider {
|
|
324
315
|
private readonly config;
|
|
@@ -328,11 +319,7 @@ declare class ValhallaDirectionsProvider implements DirectionsProvider {
|
|
|
328
319
|
private fetchRoute;
|
|
329
320
|
/** Decode Valhalla's encoded polyline6 format */
|
|
330
321
|
private decodePolyline;
|
|
331
|
-
private stitchGeometry;
|
|
332
|
-
private sameCoordinate;
|
|
333
|
-
private shapeIndex;
|
|
334
322
|
private fetchChunked;
|
|
335
|
-
private fetchWithTimeout;
|
|
336
323
|
}
|
|
337
324
|
|
|
338
325
|
/**
|
|
@@ -354,10 +341,6 @@ interface ORSConfig {
|
|
|
354
341
|
baseUrl?: string;
|
|
355
342
|
/** Max waypoints per request (ORS limit: 50) */
|
|
356
343
|
maxWaypointsPerChunk?: number;
|
|
357
|
-
/** Optional fetch implementation for tests, React Native, or custom runtimes */
|
|
358
|
-
fetchFn?: typeof fetch;
|
|
359
|
-
/** Request timeout in milliseconds. Set to 0 to disable. */
|
|
360
|
-
timeoutMs?: number;
|
|
361
344
|
}
|
|
362
345
|
declare class OpenRouteServiceProvider implements DirectionsProvider {
|
|
363
346
|
private readonly config;
|
|
@@ -366,9 +349,6 @@ declare class OpenRouteServiceProvider implements DirectionsProvider {
|
|
|
366
349
|
private profileFromOptions;
|
|
367
350
|
private fetchRoute;
|
|
368
351
|
private fetchChunked;
|
|
369
|
-
private stepRange;
|
|
370
|
-
private bearingFromGeometry;
|
|
371
|
-
private fetchWithTimeout;
|
|
372
352
|
}
|
|
373
353
|
|
|
374
354
|
/**
|
|
@@ -450,6 +430,8 @@ declare const BASE_CORRIDOR_METERS = 25;
|
|
|
450
430
|
declare const MAX_CORRIDOR_METERS = 60;
|
|
451
431
|
declare const SPEED_CORRIDOR_FACTOR = 1.2;
|
|
452
432
|
declare const GPS_ACCURACY_FACTOR = 0.5;
|
|
433
|
+
declare const TURN_LOOKAHEAD_DISTANCE_METERS = 40;
|
|
434
|
+
declare const TURN_CORRIDOR_MULTIPLIER = 1.4;
|
|
453
435
|
declare const MAX_SNAP_DISTANCE = 80;
|
|
454
436
|
declare const BEARING_MISMATCH_THRESHOLD = 90;
|
|
455
437
|
declare const BEARING_MISMATCH_PENALTY = 500;
|
|
@@ -501,8 +483,10 @@ declare const constants_REJOIN_COOLDOWN_MS: typeof REJOIN_COOLDOWN_MS;
|
|
|
501
483
|
declare const constants_SNAP_WINDOW_SIZE: typeof SNAP_WINDOW_SIZE;
|
|
502
484
|
declare const constants_SPEED_CORRIDOR_FACTOR: typeof SPEED_CORRIDOR_FACTOR;
|
|
503
485
|
declare const constants_STARTUP_GRACE_MS: typeof STARTUP_GRACE_MS;
|
|
486
|
+
declare const constants_TURN_CORRIDOR_MULTIPLIER: typeof TURN_CORRIDOR_MULTIPLIER;
|
|
487
|
+
declare const constants_TURN_LOOKAHEAD_DISTANCE_METERS: typeof TURN_LOOKAHEAD_DISTANCE_METERS;
|
|
504
488
|
declare namespace constants {
|
|
505
|
-
export { constants_ARRIVAL_THRESHOLD_METERS as ARRIVAL_THRESHOLD_METERS, constants_BASE_CORRIDOR_METERS as BASE_CORRIDOR_METERS, constants_BEARING_ALIGNMENT_THRESHOLD as BEARING_ALIGNMENT_THRESHOLD, constants_BEARING_MIN_SPEED_MPS as BEARING_MIN_SPEED_MPS, constants_BEARING_MISMATCH_PENALTY as BEARING_MISMATCH_PENALTY, constants_BEARING_MISMATCH_THRESHOLD as BEARING_MISMATCH_THRESHOLD, constants_BEARING_SMOOTHING_ALPHA as BEARING_SMOOTHING_ALPHA, constants_BETA_CORRECTION as BETA_CORRECTION, constants_DETOUR_COMMIT_MS as DETOUR_COMMIT_MS, constants_DR_MAX_AGE_MS as DR_MAX_AGE_MS, constants_GPS_ACCURACY_FACTOR as GPS_ACCURACY_FACTOR, constants_GPS_AGE_CAP_SECONDS as GPS_AGE_CAP_SECONDS, constants_GPS_STALE_MS as GPS_STALE_MS, constants_INERTIA_PENALTY as INERTIA_PENALTY, constants_INERTIA_SEGMENT_DIST as INERTIA_SEGMENT_DIST, constants_LOOK_AHEAD_SECONDS as LOOK_AHEAD_SECONDS, constants_MANEUVER_TRIGGER_DIST as MANEUVER_TRIGGER_DIST, constants_MAX_CORRIDOR_METERS as MAX_CORRIDOR_METERS, constants_MAX_LOOK_AHEAD_METERS as MAX_LOOK_AHEAD_METERS, constants_MAX_SNAP_DISTANCE as MAX_SNAP_DISTANCE, constants_MIN_LOOK_AHEAD_METERS as MIN_LOOK_AHEAD_METERS, constants_OFF_ROUTE_CONFIRM_MS as OFF_ROUTE_CONFIRM_MS, constants_REJOIN_CONFIRM_MS as REJOIN_CONFIRM_MS, constants_REJOIN_COOLDOWN_MS as REJOIN_COOLDOWN_MS, constants_SNAP_WINDOW_SIZE as SNAP_WINDOW_SIZE, constants_SPEED_CORRIDOR_FACTOR as SPEED_CORRIDOR_FACTOR, constants_STARTUP_GRACE_MS as STARTUP_GRACE_MS };
|
|
489
|
+
export { constants_ARRIVAL_THRESHOLD_METERS as ARRIVAL_THRESHOLD_METERS, constants_BASE_CORRIDOR_METERS as BASE_CORRIDOR_METERS, constants_BEARING_ALIGNMENT_THRESHOLD as BEARING_ALIGNMENT_THRESHOLD, constants_BEARING_MIN_SPEED_MPS as BEARING_MIN_SPEED_MPS, constants_BEARING_MISMATCH_PENALTY as BEARING_MISMATCH_PENALTY, constants_BEARING_MISMATCH_THRESHOLD as BEARING_MISMATCH_THRESHOLD, constants_BEARING_SMOOTHING_ALPHA as BEARING_SMOOTHING_ALPHA, constants_BETA_CORRECTION as BETA_CORRECTION, constants_DETOUR_COMMIT_MS as DETOUR_COMMIT_MS, constants_DR_MAX_AGE_MS as DR_MAX_AGE_MS, constants_GPS_ACCURACY_FACTOR as GPS_ACCURACY_FACTOR, constants_GPS_AGE_CAP_SECONDS as GPS_AGE_CAP_SECONDS, constants_GPS_STALE_MS as GPS_STALE_MS, constants_INERTIA_PENALTY as INERTIA_PENALTY, constants_INERTIA_SEGMENT_DIST as INERTIA_SEGMENT_DIST, constants_LOOK_AHEAD_SECONDS as LOOK_AHEAD_SECONDS, constants_MANEUVER_TRIGGER_DIST as MANEUVER_TRIGGER_DIST, constants_MAX_CORRIDOR_METERS as MAX_CORRIDOR_METERS, constants_MAX_LOOK_AHEAD_METERS as MAX_LOOK_AHEAD_METERS, constants_MAX_SNAP_DISTANCE as MAX_SNAP_DISTANCE, constants_MIN_LOOK_AHEAD_METERS as MIN_LOOK_AHEAD_METERS, constants_OFF_ROUTE_CONFIRM_MS as OFF_ROUTE_CONFIRM_MS, constants_REJOIN_CONFIRM_MS as REJOIN_CONFIRM_MS, constants_REJOIN_COOLDOWN_MS as REJOIN_COOLDOWN_MS, constants_SNAP_WINDOW_SIZE as SNAP_WINDOW_SIZE, constants_SPEED_CORRIDOR_FACTOR as SPEED_CORRIDOR_FACTOR, constants_STARTUP_GRACE_MS as STARTUP_GRACE_MS, constants_TURN_CORRIDOR_MULTIPLIER as TURN_CORRIDOR_MULTIPLIER, constants_TURN_LOOKAHEAD_DISTANCE_METERS as TURN_LOOKAHEAD_DISTANCE_METERS };
|
|
506
490
|
}
|
|
507
491
|
|
|
508
492
|
export { type BuildOptions, type CameraOptions, constants as Constants, Coordinate, CustomRouteBuilder, type CustomWaypoint, type DirectionsLeg, type DirectionsManeuver, type DirectionsOptions, type DirectionsProvider, type DirectionsResult, type DirectionsStep, type Kalman2DState, KalmanFilter2D, type MapRendererAdapter, type ORSConfig, type ORSProfile, type OSRMConfig, OSRMDirectionsProvider, OpenRouteServiceProvider, RouteSnapper, type RouteStyle, type SnapResult, type SnapperOptions, type ValhallaConfig, type ValhallaCostingModel, ValhallaDirectionsProvider, type VehicleStyle, type WaypointOptions, buildForwardCumulativeDistances, buildReverseCumulativeDistances, getBearingBetweenPoints, interpolatePoint, kalmanUpdate2D, normalizeAngle, projectPointOnSegment };
|
package/dist/core.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
'use strict';var $=Object.defineProperty;var q=(s,t)=>{for(var e in t)$(s,e,{get:t[e],enumerable:true});};function R(s,t,e,n){let o=(e-s)*(Math.PI/180),i=(n-t)*(Math.PI/180),l=Math.sin(o/2)*Math.sin(o/2)+Math.cos(s*(Math.PI/180))*Math.cos(e*(Math.PI/180))*Math.sin(i/2)*Math.sin(i/2);return 6371e3*(2*Math.atan2(Math.sqrt(l),Math.sqrt(1-l)))}function X(s,t,e,n){let o=n/6371e3,i=e*(Math.PI/180),l=s*(Math.PI/180),a=t*(Math.PI/180),c=Math.asin(Math.sin(l)*Math.cos(o)+Math.cos(l)*Math.sin(o)*Math.cos(i));return [((a+Math.atan2(Math.sin(i)*Math.sin(o)*Math.cos(l),Math.cos(o)-Math.sin(l)*Math.sin(c)))*180/Math.PI+540)%360-180,c*180/Math.PI]}function j(s,t){let e=s[1]*(Math.PI/180),n=s[0]*(Math.PI/180),o=t[1]*(Math.PI/180),i=t[0]*(Math.PI/180),l=Math.sin(i-n)*Math.cos(o),a=Math.cos(e)*Math.sin(o)-Math.sin(e)*Math.cos(o)*Math.cos(i-n),c=Math.atan2(l,a)*(180/Math.PI);return c=(c+360)%360,c}function v(s){let t=s%360;return t>180?t-360:t<-180?t+360:t}function x(s,t){let e=s[1]*(Math.PI/180),n=s[0]*(Math.PI/180),o=t[1]*(Math.PI/180),i=t[0]*(Math.PI/180),l=Math.sin(i-n)*Math.cos(o),a=Math.cos(e)*Math.sin(o)-Math.sin(e)*Math.cos(o)*Math.cos(i-n);return (Math.atan2(l,a)*180/Math.PI+360)%360}function Y(s,t,e){let n=(o,i,l)=>o+(i-o)*l;return [n(s[0],t[0],e),n(s[1],t[1],e)]}function _(s,t,e){let[n,o]=s,[i,l]=t,[a,c]=e,h=a-i,u=c-l,r=h*h+u*u;if(r===0)return t;let p=((n-i)*h+(o-l)*u)/r;return p=Math.max(0,Math.min(1,p)),[i+p*h,l+p*u]}function J(s){let t=new Float64Array(s.length);for(let e=1;e<s.length;e++)t[e]=t[e-1]+R(s[e-1][1],s[e-1][0],s[e][1],s[e][0]);return t}function z(s){let t=new Float64Array(s.length);for(let e=s.length-2;e>=0;e--)t[e]=t[e+1]+R(s[e][1],s[e][0],s[e+1][1],s[e+1][0]);return t}function k(s,t,e,n,o,i=1e-5,l=5e-5){s.x+=s.vx*o,s.y+=s.vy*o,s.P+=i;let a=l*Math.max(1,n/5),c=s.P/(s.P+a),h=t-s.x,u=e-s.y;return s.x+=c*h,s.y+=c*u,o>0&&(s.vx=h/o*c,s.vy=u/o*c),s.P=(1-c)*s.P,s}var P=class{constructor(t=1e-5,e=5e-5){this.lastTimestamp=0;this.Q=t,this.rBase=e,this.state={x:0,y:0,vx:0,vy:0,P:1};}init(t,e,n){this.state={x:t,y:e,vx:0,vy:0,P:1},this.lastTimestamp=n;}update(t,e,n,o){if(this.lastTimestamp===0)return this.init(t,e,o),[t,e];let i=Math.max(.001,(o-this.lastTimestamp)/1e3);return this.lastTimestamp=o,k(this.state,t,e,n,i,this.Q,this.rBase),[this.state.x,this.state.y]}getPosition(){return [this.state.x,this.state.y]}getState(){return {...this.state}}reset(){this.state={x:0,y:0,vx:0,vy:0,P:1},this.lastTimestamp=0;}};var K={};q(K,{ARRIVAL_THRESHOLD_METERS:()=>Ct,BASE_CORRIDOR_METERS:()=>Q,BEARING_ALIGNMENT_THRESHOLD:()=>it,BEARING_MIN_SPEED_MPS:()=>rt,BEARING_MISMATCH_PENALTY:()=>W,BEARING_MISMATCH_THRESHOLD:()=>V,BEARING_SMOOTHING_ALPHA:()=>ot,BETA_CORRECTION:()=>ft,DETOUR_COMMIT_MS:()=>pt,DR_MAX_AGE_MS:()=>st,GPS_ACCURACY_FACTOR:()=>et,GPS_AGE_CAP_SECONDS:()=>dt,GPS_STALE_MS:()=>ht,INERTIA_PENALTY:()=>G,INERTIA_SEGMENT_DIST:()=>B,LOOK_AHEAD_SECONDS:()=>yt,MANEUVER_TRIGGER_DIST:()=>mt,MAX_CORRIDOR_METERS:()=>Z,MAX_LOOK_AHEAD_METERS:()=>bt,MAX_SNAP_DISTANCE:()=>U,MIN_LOOK_AHEAD_METERS:()=>gt,OFF_ROUTE_CONFIRM_MS:()=>at,REJOIN_CONFIRM_MS:()=>ct,REJOIN_COOLDOWN_MS:()=>lt,SNAP_WINDOW_SIZE:()=>nt,SPEED_CORRIDOR_FACTOR:()=>tt,STARTUP_GRACE_MS:()=>ut});var Q=25,Z=60,tt=1.2,et=.5,U=80,V=90,W=500,G=200,B=5,nt=25,ot=.3,rt=1.5,it=55,st=5e3,at=2e3,ct=1500,lt=12e3,ut=3e3,pt=4e3,ht=3e3,dt=10,mt=25,ft=.15,yt=3,gt=20,bt=100,Ct=30;var Mt={useBearingPenalty:true,useInertiaPenalty:true,maxSnapDistance:80},D=class{constructor(t){this.options={...Mt,...t};}snap(t,e,n,o,i,l,a,c=null,h=null){let u=e.length,r=a,p=1/0,g=1/0,f=e[a]??[0,0];for(let d=0;d<=o;d++){let y=n+d;if(y>u-2)if(i&&l>u*.7)y=y%(u-1);else break;if(y<0||y>=u-1)continue;let m=e[y],M=e[y+1],b=_(t,m,M),E=R(t[1],t[0],b[1],b[0]);if(E>this.options.maxSnapDistance*2)continue;let A=E;if(this.options.useBearingPenalty&&c!==null){let S=x(m,M);Math.abs(v(c-S))>90&&(A+=500);}this.options.useInertiaPenalty&&h!==null&&Math.abs(y-h)>=5&&(A+=200),A<p&&(p=A,g=E,r=y,f=b);}if(!Number.isFinite(g)){let d=Math.min(Math.max(a,0),Math.max(0,u-2)),y=e[d],m=e[d+1];y&&m?(f=_(t,y,m),g=R(t[1],t[0],f[1],f[0]),r=d):(f=e[Math.min(Math.max(a,0),u-1)]??t,g=R(t[1],t[0],f[1],f[0]),r=0);}return {idx:r,dist:g,proj:f}}};var O=class{constructor(t){let e=t.fetchFn??globalThis.fetch?.bind(globalThis);if(!e)throw new Error("[OSRM] fetch is not available. Pass config.fetchFn in this runtime.");this.config={baseUrl:t.baseUrl.replace(/\/$/,""),profile:t.profile??"driving",maxWaypointsPerChunk:t.maxWaypointsPerChunk??100,fetchFn:e,timeoutMs:t.timeoutMs??15e3};}async getRoute(t,e){if(t.length<2)throw new Error("[OSRM] At least 2 waypoints required");let n=e?.profile??this.config.profile;return t.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(t,n,e):this.fetchChunked(t,n,e)}async fetchRoute(t,e,n){let o=t.map(u=>`${u[0]},${u[1]}`).join(";"),i=n?.steps!==false?"true":"false",l=`${this.config.baseUrl}/route/v1/${e}/${o}?overview=full&geometries=geojson&steps=${i}&annotations=false`,a=await this.fetchWithTimeout(l);if(!a.ok)throw new Error(`[OSRM] HTTP ${a.status}: ${a.statusText}`);let c=await a.json();if(c.code!=="Ok"||!c.routes?.length)throw new Error(`[OSRM] No route found: ${c.code}`);let h=c.routes[0];return {geometry:h.geometry.coordinates,distance:h.distance,duration:h.duration,legs:(h.legs??[]).map(u=>({distance:u.distance,duration:u.duration,steps:(u.steps??[]).map(r=>({distance:r.distance,duration:r.duration,geometry:r.geometry?.coordinates??[],maneuver:{type:r.maneuver?.type??"unknown",modifier:r.maneuver?.modifier,location:r.maneuver?.location??[0,0],bearingBefore:r.maneuver?.bearing_before??0,bearingAfter:r.maneuver?.bearing_after??0,instruction:r.name??void 0},name:r.name}))})),raw:c}}async fetchChunked(t,e,n){let o=this.config.maxWaypointsPerChunk,i=[];for(let r=0;r<t.length;r+=o-1){let p=t.slice(r,r+o);if(p.length<2||(i.push(p),r+o>=t.length))break}let l=await Promise.all(i.map(r=>this.fetchRoute(r,e,n))),a=[],c=0,h=0,u=[];for(let r=0;r<l.length;r++){let p=l[r];a.push(...r===0?p.geometry:p.geometry.slice(1)),c+=p.distance,h+=p.duration,u.push(...p.legs);}return {geometry:a,distance:c,duration:h,legs:u,raw:l.map(r=>r.raw)}}async fetchWithTimeout(t,e){if(this.config.timeoutMs<=0||typeof AbortController>"u")return this.config.fetchFn(t,e);let n=new AbortController,o=setTimeout(()=>n.abort(),this.config.timeoutMs);try{return await this.config.fetchFn(t,{...e,signal:n.signal})}catch(i){throw i.name==="AbortError"?new Error(`[OSRM] Request timed out after ${this.config.timeoutMs}ms`):i}finally{clearTimeout(o);}}};var I=class{constructor(t){let e=t.fetchFn??globalThis.fetch?.bind(globalThis);if(!e)throw new Error("[Valhalla] fetch is not available. Pass config.fetchFn in this runtime.");this.config={baseUrl:t.baseUrl.replace(/\/$/,""),costing:t.costing??"auto",apiKey:t.apiKey??"",maxWaypointsPerChunk:t.maxWaypointsPerChunk??50,fetchFn:e,timeoutMs:t.timeoutMs??15e3};}async getRoute(t,e){if(t.length<2)throw new Error("[Valhalla] At least 2 waypoints required");let n=this.profileToCosting(e?.profile);return t.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(t,n,e):this.fetchChunked(t,n,e)}profileToCosting(t){switch(t){case "cycling":return "bicycle";case "walking":return "pedestrian";default:return this.config.costing}}async fetchRoute(t,e,n){let o=t.map(d=>({lon:d[0],lat:d[1],type:"break"})),i=JSON.stringify({locations:o,costing:e,directions_options:{units:"kilometers"}}),l={"Content-Type":"application/json","User-Agent":"NavCoreSDK/1.0.0 (React Native; Expo; bab-bou-jeloud-demo)"};this.config.apiKey&&(l.api_key=this.config.apiKey);let a=await this.fetchWithTimeout(`${this.config.baseUrl}/route`,{method:"POST",headers:l,body:i});if(!a.ok){let d=await a.text();throw new Error(`[Valhalla] HTTP ${a.status}: ${d}`)}let c=await a.json(),h=c.trip?.legs??[],u=h.map(d=>this.decodePolyline(d.shape??"")),r=this.stitchGeometry(u),p=r.length>0?r:t,g=c.trip?.summary??{},f=h.map((d,y)=>({distance:(d.summary?.length??0)*1e3,duration:d.summary?.time??0,steps:(d.maneuvers??[]).map(m=>{let M=u[y]??[],b=this.shapeIndex(m.begin_shape_index,0),E=this.shapeIndex(m.end_shape_index,b),A=M.length>0?M.slice(b,Math.max(b,E)+1):[],S=t[Math.min(y,t.length-1)],L=A[0]??M[b]??S;return {distance:(m.length??0)*1e3,duration:m.time??0,geometry:A,maneuver:{type:m.type?.toString()??"unknown",modifier:void 0,location:L,bearingBefore:m.begin_heading??0,bearingAfter:m.end_heading??0,instruction:m.instruction},name:m.street_names?.[0]}})}));return {geometry:p,distance:(g.length??0)*1e3,duration:g.time??0,legs:f,raw:c}}decodePolyline(t,e=6){let n=Math.pow(10,e),o=[],i=0,l=0,a=0;for(;i<t.length;){let c=0,h=0,u;do u=t.charCodeAt(i++)-63,h|=(u&31)<<c,c+=5;while(u>=32);let r=(h&1)!==0?~(h>>1):h>>1;l+=r,c=0,h=0;do u=t.charCodeAt(i++)-63,h|=(u&31)<<c,c+=5;while(u>=32);let p=(h&1)!==0?~(h>>1):h>>1;a+=p,o.push([a/n,l/n]);}return o}stitchGeometry(t){let e=[];for(let n of t){if(n.length===0)continue;let o=n[0],i=e[e.length-1];i&&this.sameCoordinate(i,o)?e.push(...n.slice(1)):e.push(...n);}return e}sameCoordinate(t,e){return Math.abs(t[0]-e[0])<1e-9&&Math.abs(t[1]-e[1])<1e-9}shapeIndex(t,e){return typeof t=="number"&&Number.isFinite(t)&&t>=0?Math.floor(t):e}async fetchChunked(t,e,n){let o=this.config.maxWaypointsPerChunk,i=[];for(let r=0;r<t.length;r+=o-1){let p=t.slice(r,r+o);if(p.length<2||(i.push(p),r+o>=t.length))break}let l=await Promise.all(i.map(r=>this.fetchRoute(r,e,n))),a=[],c=0,h=0,u=[];for(let r=0;r<l.length;r++){let p=l[r];a.push(...r===0?p.geometry:p.geometry.slice(1)),c+=p.distance,h+=p.duration,u.push(...p.legs);}return {geometry:a,distance:c,duration:h,legs:u,raw:l.map(r=>r.raw)}}async fetchWithTimeout(t,e){if(this.config.timeoutMs<=0||typeof AbortController>"u")return this.config.fetchFn(t,e);let n=new AbortController,o=setTimeout(()=>n.abort(),this.config.timeoutMs);try{return await this.config.fetchFn(t,{...e,signal:n.signal})}catch(i){throw i.name==="AbortError"?new Error(`[Valhalla] Request timed out after ${this.config.timeoutMs}ms`):i}finally{clearTimeout(o);}}};var Rt="https://api.openrouteservice.org/v2/directions",At=50,Et=15e3,w=class{constructor(t){let e=t.fetchFn??globalThis.fetch?.bind(globalThis);if(!e)throw new Error("[ORS] fetch is not available. Pass config.fetchFn in this runtime.");this.config={apiKey:t.apiKey,profile:t.profile??"driving-car",baseUrl:t.baseUrl??Rt,maxWaypointsPerChunk:t.maxWaypointsPerChunk??At,fetchFn:e,timeoutMs:t.timeoutMs??Et};}async getRoute(t,e){if(t.length<2)throw new Error("[ORS] At least 2 waypoints required");let n=this.profileFromOptions(e);return t.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(t,n,e):this.fetchChunked(t,n,e)}profileFromOptions(t){switch(t?.profile){case "cycling":return "cycling-regular";case "walking":return "foot-walking";default:return this.config.profile}}async fetchRoute(t,e,n){let o=JSON.stringify({coordinates:t,instructions:n?.steps!==false,language:n?.language??"en"}),i=await this.fetchWithTimeout(`${this.config.baseUrl}/${e}/geojson`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.config.apiKey},body:o});if(!i.ok){let p=await i.text();throw new Error(`[ORS] HTTP ${i.status}: ${p}`)}let l=await i.json(),a=l.features?.[0];if(!a)throw new Error("[ORS] No route returned");let c=a.properties?.summary??{},h=a.properties?.segments??[],u=a.geometry?.coordinates??[],r=h.map((p,g)=>({distance:p.distance??0,duration:p.duration??0,steps:(p.steps??[]).map(f=>{let[d,y]=this.stepRange(f.way_points),m=u.slice(d,Math.max(d,y)+1),M=t[Math.min(g,t.length-1)],b=m[0]??u[d]??M;return {distance:f.distance??0,duration:f.duration??0,geometry:m,maneuver:{type:f.type?.toString()??"unknown",modifier:void 0,location:b,bearingBefore:this.bearingFromGeometry(m,false),bearingAfter:this.bearingFromGeometry(m,true),instruction:f.instruction},name:f.name}})}));return {geometry:u,distance:c.distance??0,duration:c.duration??0,legs:r,raw:l}}async fetchChunked(t,e,n){let o=this.config.maxWaypointsPerChunk,i=[];for(let r=0;r<t.length;r+=o-1){let p=t.slice(r,r+o);if(p.length<2||(i.push(p),r+o>=t.length))break}let l=await Promise.all(i.map(r=>this.fetchRoute(r,e,n))),a=[],c=0,h=0,u=[];for(let r=0;r<l.length;r++){let p=l[r];a.push(...r===0?p.geometry:p.geometry.slice(1)),c+=p.distance,h+=p.duration,u.push(...p.legs);}return {geometry:a,distance:c,duration:h,legs:u,raw:l.map(r=>r.raw)}}stepRange(t){if(!Array.isArray(t))return [0,0];let e=typeof t[0]=="number"&&Number.isFinite(t[0])?Math.max(0,Math.floor(t[0])):0,n=typeof t[1]=="number"&&Number.isFinite(t[1])?Math.max(e,Math.floor(t[1])):e;return [e,n]}bearingFromGeometry(t,e){if(t.length<2)return 0;let n=e?t[t.length-2]:t[0],o=e?t[t.length-1]:t[1];return !n||!o?0:x(n,o)}async fetchWithTimeout(t,e){if(this.config.timeoutMs<=0||typeof AbortController>"u")return this.config.fetchFn(t,e);let n=new AbortController,o=setTimeout(()=>n.abort(),this.config.timeoutMs);try{return await this.config.fetchFn(t,{...e,signal:n.signal})}catch(i){throw i.name==="AbortError"?new Error(`[ORS] Request timed out after ${this.config.timeoutMs}ms`):i}finally{clearTimeout(o);}}};var xt=0;function H(){return `wp_${Date.now()}_${++xt}`}var T=class{constructor(){this.waypoints=[];}addWaypoint(t,e){let n=H();return this.waypoints.push({id:n,coord:t,options:e}),n}insertWaypoint(t,e){let n=this.waypoints.findIndex(i=>i.id===e);if(n===-1)throw new Error(`Waypoint ${e} not found`);let o=H();return this.waypoints.splice(n+1,0,{id:o,coord:t,options:void 0}),o}removeWaypoint(t){let e=this.waypoints.findIndex(n=>n.id===t);if(e===-1)throw new Error(`Waypoint ${t} not found`);this.waypoints.splice(e,1);}moveWaypoint(t,e){let n=this.waypoints.find(o=>o.id===t);if(!n)throw new Error(`Waypoint ${t} not found`);n.coord=e;}getWaypoints(){return this.waypoints}get size(){return this.waypoints.length}chunk(t="OVERLAP_1",e=25){let n=this.waypoints.map(a=>a.coord);if(n.length<=e)return [n];let i=e-(t==="OVERLAP_2"?2:1),l=[];for(let a=0;a<n.length;a+=i){let c=n.slice(a,a+e);if(l.push(c),a+e>=n.length)break}return l}buildStraightLine(){return {geometry:this.waypoints.map(t=>t.coord),waypoints:[...this.waypoints]}}fromGPX(t){this.waypoints=[];let e=/<(?:trkpt|wpt|rtept)\s+lat="([^"]+)"\s+lon="([^"]+)"/g,n;for(;(n=e.exec(t))!==null;){let o=parseFloat(n[1]),i=parseFloat(n[2]);isFinite(o)&&isFinite(i)&&this.addWaypoint([i,o]);}}toGPX(){return `<?xml version="1.0" encoding="UTF-8"?>
|
|
1
|
+
'use strict';var H=Object.defineProperty;var $=(i,t)=>{for(var e in t)H(i,e,{get:t[e],enumerable:true});};function g(i,t,e,n){let r=(e-i)*(Math.PI/180),s=(n-t)*(Math.PI/180),p=Math.sin(r/2)*Math.sin(r/2)+Math.cos(i*(Math.PI/180))*Math.cos(e*(Math.PI/180))*Math.sin(s/2)*Math.sin(s/2);return 6371e3*(2*Math.atan2(Math.sqrt(p),Math.sqrt(1-p)))}function X(i,t,e,n){let r=n/6371e3,s=e*(Math.PI/180),p=i*(Math.PI/180),c=t*(Math.PI/180),a=Math.asin(Math.sin(p)*Math.cos(r)+Math.cos(p)*Math.sin(r)*Math.cos(s));return [((c+Math.atan2(Math.sin(s)*Math.sin(r)*Math.cos(p),Math.cos(r)-Math.sin(p)*Math.sin(a)))*180/Math.PI+540)%360-180,a*180/Math.PI]}function j(i,t){let e=i[1]*(Math.PI/180),n=i[0]*(Math.PI/180),r=t[1]*(Math.PI/180),s=t[0]*(Math.PI/180),p=Math.sin(s-n)*Math.cos(r),c=Math.cos(e)*Math.sin(r)-Math.sin(e)*Math.cos(r)*Math.cos(s-n),a=Math.atan2(p,c)*(180/Math.PI);return a=(a+360)%360,a}function S(i){let t=i%360;return t>180?t-360:t<-180?t+360:t}function _(i,t){let e=i[1]*(Math.PI/180),n=i[0]*(Math.PI/180),r=t[1]*(Math.PI/180),s=t[0]*(Math.PI/180),p=Math.sin(s-n)*Math.cos(r),c=Math.cos(e)*Math.sin(r)-Math.sin(e)*Math.cos(r)*Math.cos(s-n);return (Math.atan2(p,c)*180/Math.PI+360)%360}function q(i,t,e){let n=(r,s,p)=>r+(s-r)*p;return [n(i[0],t[0],e),n(i[1],t[1],e)]}function E(i,t,e){let[n,r]=i,[s,p]=t,[c,a]=e,d=c-s,u=a-p,o=d*d+u*u;if(o===0)return t;let l=((n-s)*d+(r-p)*u)/o;return l=Math.max(0,Math.min(1,l)),[s+l*d,p+l*u]}function z(i){let t=new Float64Array(i.length);for(let e=1;e<i.length;e++)t[e]=t[e-1]+g(i[e-1][1],i[e-1][0],i[e][1],i[e][0]);return t}function Y(i){let t=new Float64Array(i.length);for(let e=i.length-2;e>=0;e--)t[e]=t[e+1]+g(i[e][1],i[e][0],i[e+1][1],i[e+1][0]);return t}function L(i,t,e,n,r,s=1e-5,p=5e-5){i.x+=i.vx*r,i.y+=i.vy*r,i.P+=s;let c=p*Math.max(1,n/5),a=i.P/(i.P+c),d=t-i.x,u=e-i.y;return i.x+=a*d,i.y+=a*u,r>0&&(i.vx=d/r*a,i.vy=u/r*a),i.P=(1-a)*i.P,i}var D=class{constructor(t=1e-5,e=5e-5){this.lastTimestamp=0;this.Q=t,this.rBase=e,this.state={x:0,y:0,vx:0,vy:0,P:1};}init(t,e,n){this.state={x:t,y:e,vx:0,vy:0,P:1},this.lastTimestamp=n;}update(t,e,n,r){if(this.lastTimestamp===0)return this.init(t,e,r),[t,e];let s=Math.max(.001,(r-this.lastTimestamp)/1e3);return this.lastTimestamp=r,L(this.state,t,e,n,s,this.Q,this.rBase),[this.state.x,this.state.y]}getPosition(){return [this.state.x,this.state.y]}getState(){return {...this.state}}reset(){this.state={x:0,y:0,vx:0,vy:0,P:1},this.lastTimestamp=0;}};var G={};$(G,{ARRIVAL_THRESHOLD_METERS:()=>bt,BASE_CORRIDOR_METERS:()=>J,BEARING_ALIGNMENT_THRESHOLD:()=>st,BEARING_MIN_SPEED_MPS:()=>it,BEARING_MISMATCH_PENALTY:()=>U,BEARING_MISMATCH_THRESHOLD:()=>k,BEARING_SMOOTHING_ALPHA:()=>rt,BETA_CORRECTION:()=>yt,DETOUR_COMMIT_MS:()=>dt,DR_MAX_AGE_MS:()=>at,GPS_ACCURACY_FACTOR:()=>tt,GPS_AGE_CAP_SECONDS:()=>mt,GPS_STALE_MS:()=>ht,INERTIA_PENALTY:()=>K,INERTIA_SEGMENT_DIST:()=>B,LOOK_AHEAD_SECONDS:()=>gt,MANEUVER_TRIGGER_DIST:()=>ft,MAX_CORRIDOR_METERS:()=>Q,MAX_LOOK_AHEAD_METERS:()=>Rt,MAX_SNAP_DISTANCE:()=>F,MIN_LOOK_AHEAD_METERS:()=>Ct,OFF_ROUTE_CONFIRM_MS:()=>ct,REJOIN_CONFIRM_MS:()=>pt,REJOIN_COOLDOWN_MS:()=>lt,SNAP_WINDOW_SIZE:()=>ot,SPEED_CORRIDOR_FACTOR:()=>Z,STARTUP_GRACE_MS:()=>ut,TURN_CORRIDOR_MULTIPLIER:()=>nt,TURN_LOOKAHEAD_DISTANCE_METERS:()=>et});var J=25,Q=60,Z=1.2,tt=.5,et=40,nt=1.4,F=80,k=90,U=500,K=200,B=5,ot=25,rt=.3,it=1.5,st=55,at=5e3,ct=2e3,pt=1500,lt=12e3,ut=3e3,dt=4e3,ht=3e3,mt=10,ft=25,yt=.15,gt=3,Ct=20,Rt=100,bt=30;var xt={useBearingPenalty:true,useInertiaPenalty:true,maxSnapDistance:80},M=class{constructor(t){this.options={...xt,...t};}snap(t,e,n,r,s,p,c,a=null,d=null){let u=e.length,o=c,l=1/0,m=1/0,b=e[c]??[0,0];for(let f=0;f<=r;f++){let h=n+f;if(h>u-2)if(s&&p>u*.7)h=h%(u-1);else break;if(h<0||h>=u-1)continue;let y=e[h],x=e[h+1],C=E(t,y,x),R=g(t[1],t[0],C[1],C[0]);if(R>this.options.maxSnapDistance*2)continue;let P=R;if(this.options.useBearingPenalty&&a!==null){let V=_(y,x);Math.abs(S(a-V))>90&&(P+=500);}this.options.useInertiaPenalty&&d!==null&&Math.abs(h-d)>=5&&(P+=200),P<l&&(l=P,m=R,o=h,b=C);}return {idx:o,dist:m,proj:b}}};var O=class{constructor(t){this.config={baseUrl:t.baseUrl.replace(/\/$/,""),profile:t.profile??"driving",maxWaypointsPerChunk:t.maxWaypointsPerChunk??100};}async getRoute(t,e){if(t.length<2)throw new Error("[OSRM] At least 2 waypoints required");let n=e?.profile??this.config.profile;return t.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(t,n,e):this.fetchChunked(t,n,e)}async fetchRoute(t,e,n){let r=t.map(u=>`${u[0]},${u[1]}`).join(";"),s=n?.steps!==false?"true":"false",p=`${this.config.baseUrl}/route/v1/${e}/${r}?overview=full&geometries=geojson&steps=${s}&annotations=false`,c=await fetch(p);if(!c.ok)throw new Error(`[OSRM] HTTP ${c.status}: ${c.statusText}`);let a=await c.json();if(a.code!=="Ok"||!a.routes?.length)throw new Error(`[OSRM] No route found: ${a.code}`);let d=a.routes[0];return {geometry:d.geometry.coordinates,distance:d.distance,duration:d.duration,legs:(d.legs??[]).map(u=>({distance:u.distance,duration:u.duration,steps:(u.steps??[]).map(o=>({distance:o.distance,duration:o.duration,geometry:o.geometry?.coordinates??[],maneuver:{type:o.maneuver?.type??"unknown",modifier:o.maneuver?.modifier,location:o.maneuver?.location??[0,0],bearingBefore:o.maneuver?.bearing_before??0,bearingAfter:o.maneuver?.bearing_after??0,instruction:o.name??void 0},name:o.name}))})),raw:a}}async fetchChunked(t,e,n){let r=this.config.maxWaypointsPerChunk,s=[];for(let o=0;o<t.length;o+=r-1){let l=t.slice(o,o+r);if(l.length<2||(s.push(l),o+r>=t.length))break}let p=await Promise.all(s.map(o=>this.fetchRoute(o,e,n))),c=[],a=0,d=0,u=[];for(let o=0;o<p.length;o++){let l=p[o];c.push(...o===0?l.geometry:l.geometry.slice(1)),a+=l.distance,d+=l.duration,u.push(...l.legs);}return {geometry:c,distance:a,duration:d,legs:u,raw:p.map(o=>o.raw)}}};var v=class{constructor(t){this.config={baseUrl:t.baseUrl.replace(/\/$/,""),costing:t.costing??"auto",apiKey:t.apiKey??"",maxWaypointsPerChunk:t.maxWaypointsPerChunk??50};}async getRoute(t,e){if(t.length<2)throw new Error("[Valhalla] At least 2 waypoints required");let n=this.profileToCosting(e?.profile);return t.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(t,n,e):this.fetchChunked(t,n,e)}profileToCosting(t){switch(t){case "cycling":return "bicycle";case "walking":return "pedestrian";default:return this.config.costing}}async fetchRoute(t,e,n){let r=t.map(m=>({lon:m[0],lat:m[1],type:"break"})),s=JSON.stringify({locations:r,costing:e,directions_options:{units:"kilometers"}}),p={"Content-Type":"application/json"};this.config.apiKey&&(p.api_key=this.config.apiKey);let c=await fetch(`${this.config.baseUrl}/route`,{method:"POST",headers:p,body:s});if(!c.ok){let m=await c.text();throw new Error(`[Valhalla] HTTP ${c.status}: ${m}`)}let a=await c.json(),d=a.trip?.summary??{},u=[],o=(a.trip?.legs??[]).map((m,b)=>{let f=this.decodePolyline(m.shape??"");return b===0?u.push(...f):f.length>0&&u.push(...f.slice(1)),{distance:(m.summary?.length??0)*1e3,duration:m.summary?.time??0,steps:(m.maneuvers??[]).map(h=>{let y=typeof h.begin_shape_index=="number"?h.begin_shape_index:0,x=typeof h.end_shape_index=="number"?h.end_shape_index:y,C=f.slice(y,x+1),R=f[y]??t[0];return {distance:(h.length??0)*1e3,duration:h.time??0,geometry:C,maneuver:{type:h.type?.toString()??"unknown",modifier:void 0,location:R,bearingBefore:h.begin_heading??0,bearingAfter:h.end_heading??0,instruction:h.instruction},name:h.street_names?.[0]}})}});return {geometry:u.length>0?u:this.decodePolyline(a.trip?.legs?.[0]?.shape??""),distance:(d.length??0)*1e3,duration:d.time??0,legs:o,raw:a}}decodePolyline(t,e=6){let n=Math.pow(10,e),r=[],s=0,p=0,c=0;for(;s<t.length;){let a=0,d=0,u;do u=t.charCodeAt(s++)-63,d|=(u&31)<<a,a+=5;while(u>=32);let o=(d&1)!==0?~(d>>1):d>>1;p+=o,a=0,d=0;do u=t.charCodeAt(s++)-63,d|=(u&31)<<a,a+=5;while(u>=32);let l=(d&1)!==0?~(d>>1):d>>1;c+=l,r.push([c/n,p/n]);}return r}async fetchChunked(t,e,n){let r=this.config.maxWaypointsPerChunk,s=[];for(let o=0;o<t.length;o+=r-1){let l=t.slice(o,o+r);if(l.length<2||(s.push(l),o+r>=t.length))break}let p=await Promise.all(s.map(o=>this.fetchRoute(o,e,n))),c=[],a=0,d=0,u=[];for(let o=0;o<p.length;o++){let l=p[o];c.push(...o===0?l.geometry:l.geometry.slice(1)),a+=l.distance,d+=l.duration,u.push(...l.legs);}return {geometry:c,distance:a,duration:d,legs:u,raw:p.map(o=>o.raw)}}};var Pt="https://api.openrouteservice.org/v2/directions";var I=class{constructor(t){this.config={apiKey:t.apiKey,profile:t.profile??"driving-car",baseUrl:t.baseUrl??Pt,maxWaypointsPerChunk:t.maxWaypointsPerChunk??50};}async getRoute(t,e){if(t.length<2)throw new Error("[ORS] At least 2 waypoints required");let n=this.profileFromOptions(e);return t.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(t,n,e):this.fetchChunked(t,n,e)}profileFromOptions(t){switch(t?.profile){case "cycling":return "cycling-regular";case "walking":return "foot-walking";default:return this.config.profile}}async fetchRoute(t,e,n){let r=JSON.stringify({coordinates:t,instructions:n?.steps!==false,language:n?.language??"en"}),s=await fetch(`${this.config.baseUrl}/${e}/geojson`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.config.apiKey},body:r});if(!s.ok){let o=await s.text();throw new Error(`[ORS] HTTP ${s.status}: ${o}`)}let p=await s.json(),c=p.features?.[0];if(!c)throw new Error("[ORS] No route returned");let a=c.properties?.summary??{},u=(c.properties?.segments??[]).map(o=>({distance:o.distance??0,duration:o.duration??0,steps:(o.steps??[]).map(l=>({distance:l.distance??0,duration:l.duration??0,geometry:[],maneuver:{type:l.type?.toString()??"unknown",modifier:void 0,location:t[0],bearingBefore:0,bearingAfter:0,instruction:l.instruction},name:l.name}))}));return {geometry:c.geometry?.coordinates??[],distance:a.distance??0,duration:a.duration??0,legs:u,raw:p}}async fetchChunked(t,e,n){let r=this.config.maxWaypointsPerChunk,s=[];for(let o=0;o<t.length;o+=r-1){let l=t.slice(o,o+r);if(l.length<2||(s.push(l),o+r>=t.length))break}let p=await Promise.all(s.map(o=>this.fetchRoute(o,e,n))),c=[],a=0,d=0,u=[];for(let o=0;o<p.length;o++){let l=p[o];c.push(...o===0?l.geometry:l.geometry.slice(1)),a+=l.distance,d+=l.duration,u.push(...l.legs);}return {geometry:c,distance:a,duration:d,legs:u,raw:p.map(o=>o.raw)}}};var At=0;function W(){return `wp_${Date.now()}_${++At}`}var T=class{constructor(){this.waypoints=[];}addWaypoint(t,e){let n=W();return this.waypoints.push({id:n,coord:t,options:e}),n}insertWaypoint(t,e){let n=this.waypoints.findIndex(s=>s.id===e);if(n===-1)throw new Error(`Waypoint ${e} not found`);let r=W();return this.waypoints.splice(n+1,0,{id:r,coord:t,options:void 0}),r}removeWaypoint(t){let e=this.waypoints.findIndex(n=>n.id===t);if(e===-1)throw new Error(`Waypoint ${t} not found`);this.waypoints.splice(e,1);}moveWaypoint(t,e){let n=this.waypoints.find(r=>r.id===t);if(!n)throw new Error(`Waypoint ${t} not found`);n.coord=e;}getWaypoints(){return this.waypoints}get size(){return this.waypoints.length}chunk(t="OVERLAP_1",e=25){let n=this.waypoints.map(c=>c.coord);if(n.length<=e)return [n];let s=e-(t==="OVERLAP_2"?2:1),p=[];for(let c=0;c<n.length;c+=s){let a=n.slice(c,c+e);if(p.push(a),c+e>=n.length)break}return p}buildStraightLine(){return {geometry:this.waypoints.map(t=>t.coord),waypoints:[...this.waypoints]}}fromGPX(t){this.waypoints=[];let e=/<(?:trkpt|wpt|rtept)\s+lat="([^"]+)"\s+lon="([^"]+)"/g,n;for(;(n=e.exec(t))!==null;){let r=parseFloat(n[1]),s=parseFloat(n[2]);isFinite(r)&&isFinite(s)&&this.addWaypoint([s,r]);}}toGPX(){return `<?xml version="1.0" encoding="UTF-8"?>
|
|
2
2
|
<gpx version="1.1" creator="NavCore SDK">
|
|
3
3
|
${this.waypoints.map(e=>` <wpt lat="${e.coord[1]}" lon="${e.coord[0]}">`+(e.options?.name?`
|
|
4
4
|
<name>${e.options.name}</name>`:"")+`
|
|
5
5
|
</wpt>`).join(`
|
|
6
6
|
`)}
|
|
7
|
-
</gpx>`}fromGeoJSON(t){if(this.waypoints=[],t.type==="FeatureCollection"&&t.features){for(let e of t.features)if(e.geometry.type==="Point"){let n=e.geometry.coordinates;this.addWaypoint(n);}else if(e.geometry.type==="LineString"){let n=e.geometry.coordinates;for(let
|
|
7
|
+
</gpx>`}fromGeoJSON(t){if(this.waypoints=[],t.type==="FeatureCollection"&&t.features){for(let e of t.features)if(e.geometry.type==="Point"){let n=e.geometry.coordinates;this.addWaypoint(n);}else if(e.geometry.type==="LineString"){let n=e.geometry.coordinates;for(let r of n)this.addWaypoint(r);}}}toGeoJSON(){let t=this.waypoints.map((n,r)=>({type:"Feature",geometry:{type:"Point",coordinates:n.coord},properties:{id:n.id,order:r,name:n.options?.name??null,silent:n.options?.silent??false}})),e={type:"Feature",geometry:{type:"LineString",coordinates:this.waypoints.map(n=>n.coord)},properties:{type:"route"}};return {type:"FeatureCollection",features:[...t,e]}}clear(){this.waypoints=[];}};var w={GPS_SMOOTHING:"gps_smoothing",BASIC_SNAPPING:"basic_snapping",ADVANCED_SNAPPING:"advanced_snapping",DEAD_RECKONING:"dead_reckoning",ROUTE_OFFSET:"route_offset",PROGRESS_TRACKING:"progress_tracking",ADVANCED_BEARING:"advanced_bearing",COMPOUND_DEVIATION:"compound_deviation",PARALLEL_ROAD_RESOLUTION:"parallel_road_resolution",U_TURN_PROTECTION:"u_turn_protection",VOICE_TRIGGERS:"voice_triggers",ETA:"eta",GEOFENCING:"geofencing",NAV_AI:"nav_ai"};var A=class A{constructor(t,e){this.status="MISSING";this.payload=null;this.enabledFeatures=new Set;this.warnedFeatures=new Set;this.isDev=false;this.isDev=e??false,t&&this.validate(t);}async validate(t){try{if(this.status==="VALID"&&this.payload?.bid==="dev.bypass")return "VALID";let[e,n]=t.split(".");if(!e||!n)return this.status="INVALID",this.status;let r=atob(e);if(this.payload=JSON.parse(r),!this.payload||this.payload.exp<Date.now())return this.status="EXPIRED",this.status;if(!await this.verifySignature(e,n))return this.status="INVALID",this.status;this.status="VALID",this.extractFeatures(),console.log(`\u{1F511} [NavCore] License validation complete. Plan: ${this.isProEnabled()?"pro":"core"}`);}catch{this.status="INVALID";}return this.status}extractFeatures(){if(this.enabledFeatures.clear(),!!this.payload){if(Array.isArray(this.payload.f))for(let t of this.payload.f)this.enabledFeatures.add(t);this.payload.t==="pro"&&this.enabledFeatures.add("*");}}hasFeature(t){return this.isDev?true:this.status!=="VALID"?false:this.enabledFeatures.has("*")?true:this.enabledFeatures.has(t)}warnOnce(t){this.warnedFeatures.has(t)||(console.warn(`[NavCore] Feature '${t}' requires a Pro license`),this.warnedFeatures.add(t));}isProEnabled(){return this.hasFeature("*")}isAIEnabled(){return this.hasFeature(w.NAV_AI)}getStatus(){return this.status}getPayload(){return this.payload}getEnabledFeatures(){return Array.from(this.enabledFeatures)}async verifySignature(t,e){try{if(typeof crypto>"u"||!crypto.subtle)return !1;let r=new TextEncoder().encode(t),s=Uint8Array.from(atob(e),a=>a.charCodeAt(0)),p=Uint8Array.from(atob(A.PUBLIC_KEY_SPKI),a=>a.charCodeAt(0)),c=await crypto.subtle.importKey("spki",p,{name:"ECDSA",namedCurve:"P-256"},!0,["verify"]);return await crypto.subtle.verify({name:"ECDSA",hash:{name:"SHA-256"}},c,s,r)}catch{return false}}};A.PUBLIC_KEY_SPKI="MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEk6onJmJkWtRFusiSS69dcdONX4xL2Snm4AZO+dYjSynfJiL4x7trEy80MImLftknBWT/qI0z7ox4Q7VNL3te6A==";var N=A;exports.Constants=G;exports.CustomRouteBuilder=T;exports.FEATURES=w;exports.KalmanFilter2D=D;exports.LicenseManager=N;exports.OSRMDirectionsProvider=O;exports.OpenRouteServiceProvider=I;exports.RouteSnapper=M;exports.ValhallaDirectionsProvider=v;exports.buildForwardCumulativeDistances=z;exports.buildReverseCumulativeDistances=Y;exports.destinationPoint=X;exports.geoGetBearing=j;exports.getBearingBetweenPoints=_;exports.haversineDistance=g;exports.interpolatePoint=q;exports.kalmanUpdate2D=L;exports.normalizeAngle=S;exports.projectPointOnSegment=E;
|
package/dist/core.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
var $=Object.defineProperty;var q=(s,t)=>{for(var e in t)$(s,e,{get:t[e],enumerable:true});};function R(s,t,e,n){let o=(e-s)*(Math.PI/180),i=(n-t)*(Math.PI/180),l=Math.sin(o/2)*Math.sin(o/2)+Math.cos(s*(Math.PI/180))*Math.cos(e*(Math.PI/180))*Math.sin(i/2)*Math.sin(i/2);return 6371e3*(2*Math.atan2(Math.sqrt(l),Math.sqrt(1-l)))}function X(s,t,e,n){let o=n/6371e3,i=e*(Math.PI/180),l=s*(Math.PI/180),a=t*(Math.PI/180),c=Math.asin(Math.sin(l)*Math.cos(o)+Math.cos(l)*Math.sin(o)*Math.cos(i));return [((a+Math.atan2(Math.sin(i)*Math.sin(o)*Math.cos(l),Math.cos(o)-Math.sin(l)*Math.sin(c)))*180/Math.PI+540)%360-180,c*180/Math.PI]}function j(s,t){let e=s[1]*(Math.PI/180),n=s[0]*(Math.PI/180),o=t[1]*(Math.PI/180),i=t[0]*(Math.PI/180),l=Math.sin(i-n)*Math.cos(o),a=Math.cos(e)*Math.sin(o)-Math.sin(e)*Math.cos(o)*Math.cos(i-n),c=Math.atan2(l,a)*(180/Math.PI);return c=(c+360)%360,c}function v(s){let t=s%360;return t>180?t-360:t<-180?t+360:t}function x(s,t){let e=s[1]*(Math.PI/180),n=s[0]*(Math.PI/180),o=t[1]*(Math.PI/180),i=t[0]*(Math.PI/180),l=Math.sin(i-n)*Math.cos(o),a=Math.cos(e)*Math.sin(o)-Math.sin(e)*Math.cos(o)*Math.cos(i-n);return (Math.atan2(l,a)*180/Math.PI+360)%360}function Y(s,t,e){let n=(o,i,l)=>o+(i-o)*l;return [n(s[0],t[0],e),n(s[1],t[1],e)]}function _(s,t,e){let[n,o]=s,[i,l]=t,[a,c]=e,h=a-i,u=c-l,r=h*h+u*u;if(r===0)return t;let p=((n-i)*h+(o-l)*u)/r;return p=Math.max(0,Math.min(1,p)),[i+p*h,l+p*u]}function J(s){let t=new Float64Array(s.length);for(let e=1;e<s.length;e++)t[e]=t[e-1]+R(s[e-1][1],s[e-1][0],s[e][1],s[e][0]);return t}function z(s){let t=new Float64Array(s.length);for(let e=s.length-2;e>=0;e--)t[e]=t[e+1]+R(s[e][1],s[e][0],s[e+1][1],s[e+1][0]);return t}function k(s,t,e,n,o,i=1e-5,l=5e-5){s.x+=s.vx*o,s.y+=s.vy*o,s.P+=i;let a=l*Math.max(1,n/5),c=s.P/(s.P+a),h=t-s.x,u=e-s.y;return s.x+=c*h,s.y+=c*u,o>0&&(s.vx=h/o*c,s.vy=u/o*c),s.P=(1-c)*s.P,s}var P=class{constructor(t=1e-5,e=5e-5){this.lastTimestamp=0;this.Q=t,this.rBase=e,this.state={x:0,y:0,vx:0,vy:0,P:1};}init(t,e,n){this.state={x:t,y:e,vx:0,vy:0,P:1},this.lastTimestamp=n;}update(t,e,n,o){if(this.lastTimestamp===0)return this.init(t,e,o),[t,e];let i=Math.max(.001,(o-this.lastTimestamp)/1e3);return this.lastTimestamp=o,k(this.state,t,e,n,i,this.Q,this.rBase),[this.state.x,this.state.y]}getPosition(){return [this.state.x,this.state.y]}getState(){return {...this.state}}reset(){this.state={x:0,y:0,vx:0,vy:0,P:1},this.lastTimestamp=0;}};var K={};q(K,{ARRIVAL_THRESHOLD_METERS:()=>Ct,BASE_CORRIDOR_METERS:()=>Q,BEARING_ALIGNMENT_THRESHOLD:()=>it,BEARING_MIN_SPEED_MPS:()=>rt,BEARING_MISMATCH_PENALTY:()=>W,BEARING_MISMATCH_THRESHOLD:()=>V,BEARING_SMOOTHING_ALPHA:()=>ot,BETA_CORRECTION:()=>ft,DETOUR_COMMIT_MS:()=>pt,DR_MAX_AGE_MS:()=>st,GPS_ACCURACY_FACTOR:()=>et,GPS_AGE_CAP_SECONDS:()=>dt,GPS_STALE_MS:()=>ht,INERTIA_PENALTY:()=>G,INERTIA_SEGMENT_DIST:()=>B,LOOK_AHEAD_SECONDS:()=>yt,MANEUVER_TRIGGER_DIST:()=>mt,MAX_CORRIDOR_METERS:()=>Z,MAX_LOOK_AHEAD_METERS:()=>bt,MAX_SNAP_DISTANCE:()=>U,MIN_LOOK_AHEAD_METERS:()=>gt,OFF_ROUTE_CONFIRM_MS:()=>at,REJOIN_CONFIRM_MS:()=>ct,REJOIN_COOLDOWN_MS:()=>lt,SNAP_WINDOW_SIZE:()=>nt,SPEED_CORRIDOR_FACTOR:()=>tt,STARTUP_GRACE_MS:()=>ut});var Q=25,Z=60,tt=1.2,et=.5,U=80,V=90,W=500,G=200,B=5,nt=25,ot=.3,rt=1.5,it=55,st=5e3,at=2e3,ct=1500,lt=12e3,ut=3e3,pt=4e3,ht=3e3,dt=10,mt=25,ft=.15,yt=3,gt=20,bt=100,Ct=30;var Mt={useBearingPenalty:true,useInertiaPenalty:true,maxSnapDistance:80},D=class{constructor(t){this.options={...Mt,...t};}snap(t,e,n,o,i,l,a,c=null,h=null){let u=e.length,r=a,p=1/0,g=1/0,f=e[a]??[0,0];for(let d=0;d<=o;d++){let y=n+d;if(y>u-2)if(i&&l>u*.7)y=y%(u-1);else break;if(y<0||y>=u-1)continue;let m=e[y],M=e[y+1],b=_(t,m,M),E=R(t[1],t[0],b[1],b[0]);if(E>this.options.maxSnapDistance*2)continue;let A=E;if(this.options.useBearingPenalty&&c!==null){let S=x(m,M);Math.abs(v(c-S))>90&&(A+=500);}this.options.useInertiaPenalty&&h!==null&&Math.abs(y-h)>=5&&(A+=200),A<p&&(p=A,g=E,r=y,f=b);}if(!Number.isFinite(g)){let d=Math.min(Math.max(a,0),Math.max(0,u-2)),y=e[d],m=e[d+1];y&&m?(f=_(t,y,m),g=R(t[1],t[0],f[1],f[0]),r=d):(f=e[Math.min(Math.max(a,0),u-1)]??t,g=R(t[1],t[0],f[1],f[0]),r=0);}return {idx:r,dist:g,proj:f}}};var O=class{constructor(t){let e=t.fetchFn??globalThis.fetch?.bind(globalThis);if(!e)throw new Error("[OSRM] fetch is not available. Pass config.fetchFn in this runtime.");this.config={baseUrl:t.baseUrl.replace(/\/$/,""),profile:t.profile??"driving",maxWaypointsPerChunk:t.maxWaypointsPerChunk??100,fetchFn:e,timeoutMs:t.timeoutMs??15e3};}async getRoute(t,e){if(t.length<2)throw new Error("[OSRM] At least 2 waypoints required");let n=e?.profile??this.config.profile;return t.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(t,n,e):this.fetchChunked(t,n,e)}async fetchRoute(t,e,n){let o=t.map(u=>`${u[0]},${u[1]}`).join(";"),i=n?.steps!==false?"true":"false",l=`${this.config.baseUrl}/route/v1/${e}/${o}?overview=full&geometries=geojson&steps=${i}&annotations=false`,a=await this.fetchWithTimeout(l);if(!a.ok)throw new Error(`[OSRM] HTTP ${a.status}: ${a.statusText}`);let c=await a.json();if(c.code!=="Ok"||!c.routes?.length)throw new Error(`[OSRM] No route found: ${c.code}`);let h=c.routes[0];return {geometry:h.geometry.coordinates,distance:h.distance,duration:h.duration,legs:(h.legs??[]).map(u=>({distance:u.distance,duration:u.duration,steps:(u.steps??[]).map(r=>({distance:r.distance,duration:r.duration,geometry:r.geometry?.coordinates??[],maneuver:{type:r.maneuver?.type??"unknown",modifier:r.maneuver?.modifier,location:r.maneuver?.location??[0,0],bearingBefore:r.maneuver?.bearing_before??0,bearingAfter:r.maneuver?.bearing_after??0,instruction:r.name??void 0},name:r.name}))})),raw:c}}async fetchChunked(t,e,n){let o=this.config.maxWaypointsPerChunk,i=[];for(let r=0;r<t.length;r+=o-1){let p=t.slice(r,r+o);if(p.length<2||(i.push(p),r+o>=t.length))break}let l=await Promise.all(i.map(r=>this.fetchRoute(r,e,n))),a=[],c=0,h=0,u=[];for(let r=0;r<l.length;r++){let p=l[r];a.push(...r===0?p.geometry:p.geometry.slice(1)),c+=p.distance,h+=p.duration,u.push(...p.legs);}return {geometry:a,distance:c,duration:h,legs:u,raw:l.map(r=>r.raw)}}async fetchWithTimeout(t,e){if(this.config.timeoutMs<=0||typeof AbortController>"u")return this.config.fetchFn(t,e);let n=new AbortController,o=setTimeout(()=>n.abort(),this.config.timeoutMs);try{return await this.config.fetchFn(t,{...e,signal:n.signal})}catch(i){throw i.name==="AbortError"?new Error(`[OSRM] Request timed out after ${this.config.timeoutMs}ms`):i}finally{clearTimeout(o);}}};var I=class{constructor(t){let e=t.fetchFn??globalThis.fetch?.bind(globalThis);if(!e)throw new Error("[Valhalla] fetch is not available. Pass config.fetchFn in this runtime.");this.config={baseUrl:t.baseUrl.replace(/\/$/,""),costing:t.costing??"auto",apiKey:t.apiKey??"",maxWaypointsPerChunk:t.maxWaypointsPerChunk??50,fetchFn:e,timeoutMs:t.timeoutMs??15e3};}async getRoute(t,e){if(t.length<2)throw new Error("[Valhalla] At least 2 waypoints required");let n=this.profileToCosting(e?.profile);return t.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(t,n,e):this.fetchChunked(t,n,e)}profileToCosting(t){switch(t){case "cycling":return "bicycle";case "walking":return "pedestrian";default:return this.config.costing}}async fetchRoute(t,e,n){let o=t.map(d=>({lon:d[0],lat:d[1],type:"break"})),i=JSON.stringify({locations:o,costing:e,directions_options:{units:"kilometers"}}),l={"Content-Type":"application/json","User-Agent":"NavCoreSDK/1.0.0 (React Native; Expo; bab-bou-jeloud-demo)"};this.config.apiKey&&(l.api_key=this.config.apiKey);let a=await this.fetchWithTimeout(`${this.config.baseUrl}/route`,{method:"POST",headers:l,body:i});if(!a.ok){let d=await a.text();throw new Error(`[Valhalla] HTTP ${a.status}: ${d}`)}let c=await a.json(),h=c.trip?.legs??[],u=h.map(d=>this.decodePolyline(d.shape??"")),r=this.stitchGeometry(u),p=r.length>0?r:t,g=c.trip?.summary??{},f=h.map((d,y)=>({distance:(d.summary?.length??0)*1e3,duration:d.summary?.time??0,steps:(d.maneuvers??[]).map(m=>{let M=u[y]??[],b=this.shapeIndex(m.begin_shape_index,0),E=this.shapeIndex(m.end_shape_index,b),A=M.length>0?M.slice(b,Math.max(b,E)+1):[],S=t[Math.min(y,t.length-1)],L=A[0]??M[b]??S;return {distance:(m.length??0)*1e3,duration:m.time??0,geometry:A,maneuver:{type:m.type?.toString()??"unknown",modifier:void 0,location:L,bearingBefore:m.begin_heading??0,bearingAfter:m.end_heading??0,instruction:m.instruction},name:m.street_names?.[0]}})}));return {geometry:p,distance:(g.length??0)*1e3,duration:g.time??0,legs:f,raw:c}}decodePolyline(t,e=6){let n=Math.pow(10,e),o=[],i=0,l=0,a=0;for(;i<t.length;){let c=0,h=0,u;do u=t.charCodeAt(i++)-63,h|=(u&31)<<c,c+=5;while(u>=32);let r=(h&1)!==0?~(h>>1):h>>1;l+=r,c=0,h=0;do u=t.charCodeAt(i++)-63,h|=(u&31)<<c,c+=5;while(u>=32);let p=(h&1)!==0?~(h>>1):h>>1;a+=p,o.push([a/n,l/n]);}return o}stitchGeometry(t){let e=[];for(let n of t){if(n.length===0)continue;let o=n[0],i=e[e.length-1];i&&this.sameCoordinate(i,o)?e.push(...n.slice(1)):e.push(...n);}return e}sameCoordinate(t,e){return Math.abs(t[0]-e[0])<1e-9&&Math.abs(t[1]-e[1])<1e-9}shapeIndex(t,e){return typeof t=="number"&&Number.isFinite(t)&&t>=0?Math.floor(t):e}async fetchChunked(t,e,n){let o=this.config.maxWaypointsPerChunk,i=[];for(let r=0;r<t.length;r+=o-1){let p=t.slice(r,r+o);if(p.length<2||(i.push(p),r+o>=t.length))break}let l=await Promise.all(i.map(r=>this.fetchRoute(r,e,n))),a=[],c=0,h=0,u=[];for(let r=0;r<l.length;r++){let p=l[r];a.push(...r===0?p.geometry:p.geometry.slice(1)),c+=p.distance,h+=p.duration,u.push(...p.legs);}return {geometry:a,distance:c,duration:h,legs:u,raw:l.map(r=>r.raw)}}async fetchWithTimeout(t,e){if(this.config.timeoutMs<=0||typeof AbortController>"u")return this.config.fetchFn(t,e);let n=new AbortController,o=setTimeout(()=>n.abort(),this.config.timeoutMs);try{return await this.config.fetchFn(t,{...e,signal:n.signal})}catch(i){throw i.name==="AbortError"?new Error(`[Valhalla] Request timed out after ${this.config.timeoutMs}ms`):i}finally{clearTimeout(o);}}};var Rt="https://api.openrouteservice.org/v2/directions",At=50,Et=15e3,w=class{constructor(t){let e=t.fetchFn??globalThis.fetch?.bind(globalThis);if(!e)throw new Error("[ORS] fetch is not available. Pass config.fetchFn in this runtime.");this.config={apiKey:t.apiKey,profile:t.profile??"driving-car",baseUrl:t.baseUrl??Rt,maxWaypointsPerChunk:t.maxWaypointsPerChunk??At,fetchFn:e,timeoutMs:t.timeoutMs??Et};}async getRoute(t,e){if(t.length<2)throw new Error("[ORS] At least 2 waypoints required");let n=this.profileFromOptions(e);return t.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(t,n,e):this.fetchChunked(t,n,e)}profileFromOptions(t){switch(t?.profile){case "cycling":return "cycling-regular";case "walking":return "foot-walking";default:return this.config.profile}}async fetchRoute(t,e,n){let o=JSON.stringify({coordinates:t,instructions:n?.steps!==false,language:n?.language??"en"}),i=await this.fetchWithTimeout(`${this.config.baseUrl}/${e}/geojson`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.config.apiKey},body:o});if(!i.ok){let p=await i.text();throw new Error(`[ORS] HTTP ${i.status}: ${p}`)}let l=await i.json(),a=l.features?.[0];if(!a)throw new Error("[ORS] No route returned");let c=a.properties?.summary??{},h=a.properties?.segments??[],u=a.geometry?.coordinates??[],r=h.map((p,g)=>({distance:p.distance??0,duration:p.duration??0,steps:(p.steps??[]).map(f=>{let[d,y]=this.stepRange(f.way_points),m=u.slice(d,Math.max(d,y)+1),M=t[Math.min(g,t.length-1)],b=m[0]??u[d]??M;return {distance:f.distance??0,duration:f.duration??0,geometry:m,maneuver:{type:f.type?.toString()??"unknown",modifier:void 0,location:b,bearingBefore:this.bearingFromGeometry(m,false),bearingAfter:this.bearingFromGeometry(m,true),instruction:f.instruction},name:f.name}})}));return {geometry:u,distance:c.distance??0,duration:c.duration??0,legs:r,raw:l}}async fetchChunked(t,e,n){let o=this.config.maxWaypointsPerChunk,i=[];for(let r=0;r<t.length;r+=o-1){let p=t.slice(r,r+o);if(p.length<2||(i.push(p),r+o>=t.length))break}let l=await Promise.all(i.map(r=>this.fetchRoute(r,e,n))),a=[],c=0,h=0,u=[];for(let r=0;r<l.length;r++){let p=l[r];a.push(...r===0?p.geometry:p.geometry.slice(1)),c+=p.distance,h+=p.duration,u.push(...p.legs);}return {geometry:a,distance:c,duration:h,legs:u,raw:l.map(r=>r.raw)}}stepRange(t){if(!Array.isArray(t))return [0,0];let e=typeof t[0]=="number"&&Number.isFinite(t[0])?Math.max(0,Math.floor(t[0])):0,n=typeof t[1]=="number"&&Number.isFinite(t[1])?Math.max(e,Math.floor(t[1])):e;return [e,n]}bearingFromGeometry(t,e){if(t.length<2)return 0;let n=e?t[t.length-2]:t[0],o=e?t[t.length-1]:t[1];return !n||!o?0:x(n,o)}async fetchWithTimeout(t,e){if(this.config.timeoutMs<=0||typeof AbortController>"u")return this.config.fetchFn(t,e);let n=new AbortController,o=setTimeout(()=>n.abort(),this.config.timeoutMs);try{return await this.config.fetchFn(t,{...e,signal:n.signal})}catch(i){throw i.name==="AbortError"?new Error(`[ORS] Request timed out after ${this.config.timeoutMs}ms`):i}finally{clearTimeout(o);}}};var xt=0;function H(){return `wp_${Date.now()}_${++xt}`}var T=class{constructor(){this.waypoints=[];}addWaypoint(t,e){let n=H();return this.waypoints.push({id:n,coord:t,options:e}),n}insertWaypoint(t,e){let n=this.waypoints.findIndex(i=>i.id===e);if(n===-1)throw new Error(`Waypoint ${e} not found`);let o=H();return this.waypoints.splice(n+1,0,{id:o,coord:t,options:void 0}),o}removeWaypoint(t){let e=this.waypoints.findIndex(n=>n.id===t);if(e===-1)throw new Error(`Waypoint ${t} not found`);this.waypoints.splice(e,1);}moveWaypoint(t,e){let n=this.waypoints.find(o=>o.id===t);if(!n)throw new Error(`Waypoint ${t} not found`);n.coord=e;}getWaypoints(){return this.waypoints}get size(){return this.waypoints.length}chunk(t="OVERLAP_1",e=25){let n=this.waypoints.map(a=>a.coord);if(n.length<=e)return [n];let i=e-(t==="OVERLAP_2"?2:1),l=[];for(let a=0;a<n.length;a+=i){let c=n.slice(a,a+e);if(l.push(c),a+e>=n.length)break}return l}buildStraightLine(){return {geometry:this.waypoints.map(t=>t.coord),waypoints:[...this.waypoints]}}fromGPX(t){this.waypoints=[];let e=/<(?:trkpt|wpt|rtept)\s+lat="([^"]+)"\s+lon="([^"]+)"/g,n;for(;(n=e.exec(t))!==null;){let o=parseFloat(n[1]),i=parseFloat(n[2]);isFinite(o)&&isFinite(i)&&this.addWaypoint([i,o]);}}toGPX(){return `<?xml version="1.0" encoding="UTF-8"?>
|
|
1
|
+
var H=Object.defineProperty;var $=(i,t)=>{for(var e in t)H(i,e,{get:t[e],enumerable:true});};function g(i,t,e,n){let r=(e-i)*(Math.PI/180),s=(n-t)*(Math.PI/180),p=Math.sin(r/2)*Math.sin(r/2)+Math.cos(i*(Math.PI/180))*Math.cos(e*(Math.PI/180))*Math.sin(s/2)*Math.sin(s/2);return 6371e3*(2*Math.atan2(Math.sqrt(p),Math.sqrt(1-p)))}function X(i,t,e,n){let r=n/6371e3,s=e*(Math.PI/180),p=i*(Math.PI/180),c=t*(Math.PI/180),a=Math.asin(Math.sin(p)*Math.cos(r)+Math.cos(p)*Math.sin(r)*Math.cos(s));return [((c+Math.atan2(Math.sin(s)*Math.sin(r)*Math.cos(p),Math.cos(r)-Math.sin(p)*Math.sin(a)))*180/Math.PI+540)%360-180,a*180/Math.PI]}function j(i,t){let e=i[1]*(Math.PI/180),n=i[0]*(Math.PI/180),r=t[1]*(Math.PI/180),s=t[0]*(Math.PI/180),p=Math.sin(s-n)*Math.cos(r),c=Math.cos(e)*Math.sin(r)-Math.sin(e)*Math.cos(r)*Math.cos(s-n),a=Math.atan2(p,c)*(180/Math.PI);return a=(a+360)%360,a}function S(i){let t=i%360;return t>180?t-360:t<-180?t+360:t}function _(i,t){let e=i[1]*(Math.PI/180),n=i[0]*(Math.PI/180),r=t[1]*(Math.PI/180),s=t[0]*(Math.PI/180),p=Math.sin(s-n)*Math.cos(r),c=Math.cos(e)*Math.sin(r)-Math.sin(e)*Math.cos(r)*Math.cos(s-n);return (Math.atan2(p,c)*180/Math.PI+360)%360}function q(i,t,e){let n=(r,s,p)=>r+(s-r)*p;return [n(i[0],t[0],e),n(i[1],t[1],e)]}function E(i,t,e){let[n,r]=i,[s,p]=t,[c,a]=e,d=c-s,u=a-p,o=d*d+u*u;if(o===0)return t;let l=((n-s)*d+(r-p)*u)/o;return l=Math.max(0,Math.min(1,l)),[s+l*d,p+l*u]}function z(i){let t=new Float64Array(i.length);for(let e=1;e<i.length;e++)t[e]=t[e-1]+g(i[e-1][1],i[e-1][0],i[e][1],i[e][0]);return t}function Y(i){let t=new Float64Array(i.length);for(let e=i.length-2;e>=0;e--)t[e]=t[e+1]+g(i[e][1],i[e][0],i[e+1][1],i[e+1][0]);return t}function L(i,t,e,n,r,s=1e-5,p=5e-5){i.x+=i.vx*r,i.y+=i.vy*r,i.P+=s;let c=p*Math.max(1,n/5),a=i.P/(i.P+c),d=t-i.x,u=e-i.y;return i.x+=a*d,i.y+=a*u,r>0&&(i.vx=d/r*a,i.vy=u/r*a),i.P=(1-a)*i.P,i}var D=class{constructor(t=1e-5,e=5e-5){this.lastTimestamp=0;this.Q=t,this.rBase=e,this.state={x:0,y:0,vx:0,vy:0,P:1};}init(t,e,n){this.state={x:t,y:e,vx:0,vy:0,P:1},this.lastTimestamp=n;}update(t,e,n,r){if(this.lastTimestamp===0)return this.init(t,e,r),[t,e];let s=Math.max(.001,(r-this.lastTimestamp)/1e3);return this.lastTimestamp=r,L(this.state,t,e,n,s,this.Q,this.rBase),[this.state.x,this.state.y]}getPosition(){return [this.state.x,this.state.y]}getState(){return {...this.state}}reset(){this.state={x:0,y:0,vx:0,vy:0,P:1},this.lastTimestamp=0;}};var G={};$(G,{ARRIVAL_THRESHOLD_METERS:()=>bt,BASE_CORRIDOR_METERS:()=>J,BEARING_ALIGNMENT_THRESHOLD:()=>st,BEARING_MIN_SPEED_MPS:()=>it,BEARING_MISMATCH_PENALTY:()=>U,BEARING_MISMATCH_THRESHOLD:()=>k,BEARING_SMOOTHING_ALPHA:()=>rt,BETA_CORRECTION:()=>yt,DETOUR_COMMIT_MS:()=>dt,DR_MAX_AGE_MS:()=>at,GPS_ACCURACY_FACTOR:()=>tt,GPS_AGE_CAP_SECONDS:()=>mt,GPS_STALE_MS:()=>ht,INERTIA_PENALTY:()=>K,INERTIA_SEGMENT_DIST:()=>B,LOOK_AHEAD_SECONDS:()=>gt,MANEUVER_TRIGGER_DIST:()=>ft,MAX_CORRIDOR_METERS:()=>Q,MAX_LOOK_AHEAD_METERS:()=>Rt,MAX_SNAP_DISTANCE:()=>F,MIN_LOOK_AHEAD_METERS:()=>Ct,OFF_ROUTE_CONFIRM_MS:()=>ct,REJOIN_CONFIRM_MS:()=>pt,REJOIN_COOLDOWN_MS:()=>lt,SNAP_WINDOW_SIZE:()=>ot,SPEED_CORRIDOR_FACTOR:()=>Z,STARTUP_GRACE_MS:()=>ut,TURN_CORRIDOR_MULTIPLIER:()=>nt,TURN_LOOKAHEAD_DISTANCE_METERS:()=>et});var J=25,Q=60,Z=1.2,tt=.5,et=40,nt=1.4,F=80,k=90,U=500,K=200,B=5,ot=25,rt=.3,it=1.5,st=55,at=5e3,ct=2e3,pt=1500,lt=12e3,ut=3e3,dt=4e3,ht=3e3,mt=10,ft=25,yt=.15,gt=3,Ct=20,Rt=100,bt=30;var xt={useBearingPenalty:true,useInertiaPenalty:true,maxSnapDistance:80},M=class{constructor(t){this.options={...xt,...t};}snap(t,e,n,r,s,p,c,a=null,d=null){let u=e.length,o=c,l=1/0,m=1/0,b=e[c]??[0,0];for(let f=0;f<=r;f++){let h=n+f;if(h>u-2)if(s&&p>u*.7)h=h%(u-1);else break;if(h<0||h>=u-1)continue;let y=e[h],x=e[h+1],C=E(t,y,x),R=g(t[1],t[0],C[1],C[0]);if(R>this.options.maxSnapDistance*2)continue;let P=R;if(this.options.useBearingPenalty&&a!==null){let V=_(y,x);Math.abs(S(a-V))>90&&(P+=500);}this.options.useInertiaPenalty&&d!==null&&Math.abs(h-d)>=5&&(P+=200),P<l&&(l=P,m=R,o=h,b=C);}return {idx:o,dist:m,proj:b}}};var O=class{constructor(t){this.config={baseUrl:t.baseUrl.replace(/\/$/,""),profile:t.profile??"driving",maxWaypointsPerChunk:t.maxWaypointsPerChunk??100};}async getRoute(t,e){if(t.length<2)throw new Error("[OSRM] At least 2 waypoints required");let n=e?.profile??this.config.profile;return t.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(t,n,e):this.fetchChunked(t,n,e)}async fetchRoute(t,e,n){let r=t.map(u=>`${u[0]},${u[1]}`).join(";"),s=n?.steps!==false?"true":"false",p=`${this.config.baseUrl}/route/v1/${e}/${r}?overview=full&geometries=geojson&steps=${s}&annotations=false`,c=await fetch(p);if(!c.ok)throw new Error(`[OSRM] HTTP ${c.status}: ${c.statusText}`);let a=await c.json();if(a.code!=="Ok"||!a.routes?.length)throw new Error(`[OSRM] No route found: ${a.code}`);let d=a.routes[0];return {geometry:d.geometry.coordinates,distance:d.distance,duration:d.duration,legs:(d.legs??[]).map(u=>({distance:u.distance,duration:u.duration,steps:(u.steps??[]).map(o=>({distance:o.distance,duration:o.duration,geometry:o.geometry?.coordinates??[],maneuver:{type:o.maneuver?.type??"unknown",modifier:o.maneuver?.modifier,location:o.maneuver?.location??[0,0],bearingBefore:o.maneuver?.bearing_before??0,bearingAfter:o.maneuver?.bearing_after??0,instruction:o.name??void 0},name:o.name}))})),raw:a}}async fetchChunked(t,e,n){let r=this.config.maxWaypointsPerChunk,s=[];for(let o=0;o<t.length;o+=r-1){let l=t.slice(o,o+r);if(l.length<2||(s.push(l),o+r>=t.length))break}let p=await Promise.all(s.map(o=>this.fetchRoute(o,e,n))),c=[],a=0,d=0,u=[];for(let o=0;o<p.length;o++){let l=p[o];c.push(...o===0?l.geometry:l.geometry.slice(1)),a+=l.distance,d+=l.duration,u.push(...l.legs);}return {geometry:c,distance:a,duration:d,legs:u,raw:p.map(o=>o.raw)}}};var v=class{constructor(t){this.config={baseUrl:t.baseUrl.replace(/\/$/,""),costing:t.costing??"auto",apiKey:t.apiKey??"",maxWaypointsPerChunk:t.maxWaypointsPerChunk??50};}async getRoute(t,e){if(t.length<2)throw new Error("[Valhalla] At least 2 waypoints required");let n=this.profileToCosting(e?.profile);return t.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(t,n,e):this.fetchChunked(t,n,e)}profileToCosting(t){switch(t){case "cycling":return "bicycle";case "walking":return "pedestrian";default:return this.config.costing}}async fetchRoute(t,e,n){let r=t.map(m=>({lon:m[0],lat:m[1],type:"break"})),s=JSON.stringify({locations:r,costing:e,directions_options:{units:"kilometers"}}),p={"Content-Type":"application/json"};this.config.apiKey&&(p.api_key=this.config.apiKey);let c=await fetch(`${this.config.baseUrl}/route`,{method:"POST",headers:p,body:s});if(!c.ok){let m=await c.text();throw new Error(`[Valhalla] HTTP ${c.status}: ${m}`)}let a=await c.json(),d=a.trip?.summary??{},u=[],o=(a.trip?.legs??[]).map((m,b)=>{let f=this.decodePolyline(m.shape??"");return b===0?u.push(...f):f.length>0&&u.push(...f.slice(1)),{distance:(m.summary?.length??0)*1e3,duration:m.summary?.time??0,steps:(m.maneuvers??[]).map(h=>{let y=typeof h.begin_shape_index=="number"?h.begin_shape_index:0,x=typeof h.end_shape_index=="number"?h.end_shape_index:y,C=f.slice(y,x+1),R=f[y]??t[0];return {distance:(h.length??0)*1e3,duration:h.time??0,geometry:C,maneuver:{type:h.type?.toString()??"unknown",modifier:void 0,location:R,bearingBefore:h.begin_heading??0,bearingAfter:h.end_heading??0,instruction:h.instruction},name:h.street_names?.[0]}})}});return {geometry:u.length>0?u:this.decodePolyline(a.trip?.legs?.[0]?.shape??""),distance:(d.length??0)*1e3,duration:d.time??0,legs:o,raw:a}}decodePolyline(t,e=6){let n=Math.pow(10,e),r=[],s=0,p=0,c=0;for(;s<t.length;){let a=0,d=0,u;do u=t.charCodeAt(s++)-63,d|=(u&31)<<a,a+=5;while(u>=32);let o=(d&1)!==0?~(d>>1):d>>1;p+=o,a=0,d=0;do u=t.charCodeAt(s++)-63,d|=(u&31)<<a,a+=5;while(u>=32);let l=(d&1)!==0?~(d>>1):d>>1;c+=l,r.push([c/n,p/n]);}return r}async fetchChunked(t,e,n){let r=this.config.maxWaypointsPerChunk,s=[];for(let o=0;o<t.length;o+=r-1){let l=t.slice(o,o+r);if(l.length<2||(s.push(l),o+r>=t.length))break}let p=await Promise.all(s.map(o=>this.fetchRoute(o,e,n))),c=[],a=0,d=0,u=[];for(let o=0;o<p.length;o++){let l=p[o];c.push(...o===0?l.geometry:l.geometry.slice(1)),a+=l.distance,d+=l.duration,u.push(...l.legs);}return {geometry:c,distance:a,duration:d,legs:u,raw:p.map(o=>o.raw)}}};var Pt="https://api.openrouteservice.org/v2/directions";var I=class{constructor(t){this.config={apiKey:t.apiKey,profile:t.profile??"driving-car",baseUrl:t.baseUrl??Pt,maxWaypointsPerChunk:t.maxWaypointsPerChunk??50};}async getRoute(t,e){if(t.length<2)throw new Error("[ORS] At least 2 waypoints required");let n=this.profileFromOptions(e);return t.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(t,n,e):this.fetchChunked(t,n,e)}profileFromOptions(t){switch(t?.profile){case "cycling":return "cycling-regular";case "walking":return "foot-walking";default:return this.config.profile}}async fetchRoute(t,e,n){let r=JSON.stringify({coordinates:t,instructions:n?.steps!==false,language:n?.language??"en"}),s=await fetch(`${this.config.baseUrl}/${e}/geojson`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.config.apiKey},body:r});if(!s.ok){let o=await s.text();throw new Error(`[ORS] HTTP ${s.status}: ${o}`)}let p=await s.json(),c=p.features?.[0];if(!c)throw new Error("[ORS] No route returned");let a=c.properties?.summary??{},u=(c.properties?.segments??[]).map(o=>({distance:o.distance??0,duration:o.duration??0,steps:(o.steps??[]).map(l=>({distance:l.distance??0,duration:l.duration??0,geometry:[],maneuver:{type:l.type?.toString()??"unknown",modifier:void 0,location:t[0],bearingBefore:0,bearingAfter:0,instruction:l.instruction},name:l.name}))}));return {geometry:c.geometry?.coordinates??[],distance:a.distance??0,duration:a.duration??0,legs:u,raw:p}}async fetchChunked(t,e,n){let r=this.config.maxWaypointsPerChunk,s=[];for(let o=0;o<t.length;o+=r-1){let l=t.slice(o,o+r);if(l.length<2||(s.push(l),o+r>=t.length))break}let p=await Promise.all(s.map(o=>this.fetchRoute(o,e,n))),c=[],a=0,d=0,u=[];for(let o=0;o<p.length;o++){let l=p[o];c.push(...o===0?l.geometry:l.geometry.slice(1)),a+=l.distance,d+=l.duration,u.push(...l.legs);}return {geometry:c,distance:a,duration:d,legs:u,raw:p.map(o=>o.raw)}}};var At=0;function W(){return `wp_${Date.now()}_${++At}`}var T=class{constructor(){this.waypoints=[];}addWaypoint(t,e){let n=W();return this.waypoints.push({id:n,coord:t,options:e}),n}insertWaypoint(t,e){let n=this.waypoints.findIndex(s=>s.id===e);if(n===-1)throw new Error(`Waypoint ${e} not found`);let r=W();return this.waypoints.splice(n+1,0,{id:r,coord:t,options:void 0}),r}removeWaypoint(t){let e=this.waypoints.findIndex(n=>n.id===t);if(e===-1)throw new Error(`Waypoint ${t} not found`);this.waypoints.splice(e,1);}moveWaypoint(t,e){let n=this.waypoints.find(r=>r.id===t);if(!n)throw new Error(`Waypoint ${t} not found`);n.coord=e;}getWaypoints(){return this.waypoints}get size(){return this.waypoints.length}chunk(t="OVERLAP_1",e=25){let n=this.waypoints.map(c=>c.coord);if(n.length<=e)return [n];let s=e-(t==="OVERLAP_2"?2:1),p=[];for(let c=0;c<n.length;c+=s){let a=n.slice(c,c+e);if(p.push(a),c+e>=n.length)break}return p}buildStraightLine(){return {geometry:this.waypoints.map(t=>t.coord),waypoints:[...this.waypoints]}}fromGPX(t){this.waypoints=[];let e=/<(?:trkpt|wpt|rtept)\s+lat="([^"]+)"\s+lon="([^"]+)"/g,n;for(;(n=e.exec(t))!==null;){let r=parseFloat(n[1]),s=parseFloat(n[2]);isFinite(r)&&isFinite(s)&&this.addWaypoint([s,r]);}}toGPX(){return `<?xml version="1.0" encoding="UTF-8"?>
|
|
2
2
|
<gpx version="1.1" creator="NavCore SDK">
|
|
3
3
|
${this.waypoints.map(e=>` <wpt lat="${e.coord[1]}" lon="${e.coord[0]}">`+(e.options?.name?`
|
|
4
4
|
<name>${e.options.name}</name>`:"")+`
|
|
5
5
|
</wpt>`).join(`
|
|
6
6
|
`)}
|
|
7
|
-
</gpx>`}fromGeoJSON(t){if(this.waypoints=[],t.type==="FeatureCollection"&&t.features){for(let e of t.features)if(e.geometry.type==="Point"){let n=e.geometry.coordinates;this.addWaypoint(n);}else if(e.geometry.type==="LineString"){let n=e.geometry.coordinates;for(let
|
|
7
|
+
</gpx>`}fromGeoJSON(t){if(this.waypoints=[],t.type==="FeatureCollection"&&t.features){for(let e of t.features)if(e.geometry.type==="Point"){let n=e.geometry.coordinates;this.addWaypoint(n);}else if(e.geometry.type==="LineString"){let n=e.geometry.coordinates;for(let r of n)this.addWaypoint(r);}}}toGeoJSON(){let t=this.waypoints.map((n,r)=>({type:"Feature",geometry:{type:"Point",coordinates:n.coord},properties:{id:n.id,order:r,name:n.options?.name??null,silent:n.options?.silent??false}})),e={type:"Feature",geometry:{type:"LineString",coordinates:this.waypoints.map(n=>n.coord)},properties:{type:"route"}};return {type:"FeatureCollection",features:[...t,e]}}clear(){this.waypoints=[];}};var w={GPS_SMOOTHING:"gps_smoothing",BASIC_SNAPPING:"basic_snapping",ADVANCED_SNAPPING:"advanced_snapping",DEAD_RECKONING:"dead_reckoning",ROUTE_OFFSET:"route_offset",PROGRESS_TRACKING:"progress_tracking",ADVANCED_BEARING:"advanced_bearing",COMPOUND_DEVIATION:"compound_deviation",PARALLEL_ROAD_RESOLUTION:"parallel_road_resolution",U_TURN_PROTECTION:"u_turn_protection",VOICE_TRIGGERS:"voice_triggers",ETA:"eta",GEOFENCING:"geofencing",NAV_AI:"nav_ai"};var A=class A{constructor(t,e){this.status="MISSING";this.payload=null;this.enabledFeatures=new Set;this.warnedFeatures=new Set;this.isDev=false;this.isDev=e??false,t&&this.validate(t);}async validate(t){try{if(this.status==="VALID"&&this.payload?.bid==="dev.bypass")return "VALID";let[e,n]=t.split(".");if(!e||!n)return this.status="INVALID",this.status;let r=atob(e);if(this.payload=JSON.parse(r),!this.payload||this.payload.exp<Date.now())return this.status="EXPIRED",this.status;if(!await this.verifySignature(e,n))return this.status="INVALID",this.status;this.status="VALID",this.extractFeatures(),console.log(`\u{1F511} [NavCore] License validation complete. Plan: ${this.isProEnabled()?"pro":"core"}`);}catch{this.status="INVALID";}return this.status}extractFeatures(){if(this.enabledFeatures.clear(),!!this.payload){if(Array.isArray(this.payload.f))for(let t of this.payload.f)this.enabledFeatures.add(t);this.payload.t==="pro"&&this.enabledFeatures.add("*");}}hasFeature(t){return this.isDev?true:this.status!=="VALID"?false:this.enabledFeatures.has("*")?true:this.enabledFeatures.has(t)}warnOnce(t){this.warnedFeatures.has(t)||(console.warn(`[NavCore] Feature '${t}' requires a Pro license`),this.warnedFeatures.add(t));}isProEnabled(){return this.hasFeature("*")}isAIEnabled(){return this.hasFeature(w.NAV_AI)}getStatus(){return this.status}getPayload(){return this.payload}getEnabledFeatures(){return Array.from(this.enabledFeatures)}async verifySignature(t,e){try{if(typeof crypto>"u"||!crypto.subtle)return !1;let r=new TextEncoder().encode(t),s=Uint8Array.from(atob(e),a=>a.charCodeAt(0)),p=Uint8Array.from(atob(A.PUBLIC_KEY_SPKI),a=>a.charCodeAt(0)),c=await crypto.subtle.importKey("spki",p,{name:"ECDSA",namedCurve:"P-256"},!0,["verify"]);return await crypto.subtle.verify({name:"ECDSA",hash:{name:"SHA-256"}},c,s,r)}catch{return false}}};A.PUBLIC_KEY_SPKI="MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEk6onJmJkWtRFusiSS69dcdONX4xL2Snm4AZO+dYjSynfJiL4x7trEy80MImLftknBWT/qI0z7ox4Q7VNL3te6A==";var N=A;export{G as Constants,T as CustomRouteBuilder,w as FEATURES,D as KalmanFilter2D,N as LicenseManager,O as OSRMDirectionsProvider,I as OpenRouteServiceProvider,M as RouteSnapper,v as ValhallaDirectionsProvider,z as buildForwardCumulativeDistances,Y as buildReverseCumulativeDistances,X as destinationPoint,j as geoGetBearing,_ as getBearingBetweenPoints,g as haversineDistance,q as interpolatePoint,L as kalmanUpdate2D,S as normalizeAngle,E as projectPointOnSegment};
|