@ingissa/navcore-core 1.0.2 → 1.0.4
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 +136 -279
- package/dist/{NavCore-Bjl5fTea.d.mts → NavCore-DzTPBxIc.d.mts} +44 -23
- package/dist/{NavCore-Bjl5fTea.d.ts → NavCore-DzTPBxIc.d.ts} +44 -23
- package/dist/core.d.mts +22 -2
- package/dist/core.d.ts +22 -2
- package/dist/core.js +2 -2
- package/dist/core.mjs +2 -2
- package/dist/index.d.mts +65 -2
- package/dist/index.d.ts +65 -2
- package/dist/index.js +3 -3
- package/dist/index.mjs +3 -3
- package/dist/pro.d.mts +39 -70
- package/dist/pro.d.ts +39 -70
- package/dist/pro.js +1 -1
- package/dist/pro.mjs +1 -1
- package/package.json +9 -9
|
@@ -151,8 +151,12 @@ declare class OffRouteFSM {
|
|
|
151
151
|
/**
|
|
152
152
|
* Feature flag constants for SDK consumers.
|
|
153
153
|
*
|
|
154
|
-
* CORE features: available to all users
|
|
155
|
-
*
|
|
154
|
+
* CORE features: available to all users without a license key.
|
|
155
|
+
* - GPS smoothing, basic snapping, route building, directions providers,
|
|
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.
|
|
156
160
|
*/
|
|
157
161
|
declare const FEATURES: {
|
|
158
162
|
/**
|
|
@@ -161,43 +165,45 @@ declare const FEATURES: {
|
|
|
161
165
|
*/
|
|
162
166
|
readonly GPS_SMOOTHING: "gps_smoothing";
|
|
163
167
|
/**
|
|
164
|
-
* Basic route snapping (nearest-point projection)
|
|
165
|
-
*
|
|
168
|
+
* Basic route snapping (nearest-point projection) with bearing and inertia
|
|
169
|
+
* penalties to prevent U-turn snaps and oscillation.
|
|
170
|
+
* Both basic and advanced snapping quality are available in the free tier.
|
|
166
171
|
*/
|
|
167
172
|
readonly BASIC_SNAPPING: "basic_snapping";
|
|
168
173
|
/**
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
|
|
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.
|
|
174
|
+
* Progress anti-regression: prevents route index from jumping backward.
|
|
175
|
+
* Essential for circuit routes and motorway slip roads.
|
|
176
|
+
* Used unconditionally inside NavCore — available in the free tier.
|
|
176
177
|
*/
|
|
177
|
-
readonly
|
|
178
|
+
readonly PROGRESS_TRACKING: "progress_tracking";
|
|
178
179
|
/**
|
|
179
180
|
* Smooth route offset predictor for jitter-free map rendering.
|
|
180
181
|
* Advances render position at frame rate between GPS fixes.
|
|
182
|
+
* Used unconditionally inside NavCore — available in the free tier.
|
|
181
183
|
*/
|
|
182
184
|
readonly ROUTE_OFFSET: "route_offset";
|
|
183
185
|
/**
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
+
* Dead reckoning: continues navigation during GPS signal loss.
|
|
187
|
+
* Predicts position based on last known speed and bearing.
|
|
188
|
+
* DeadReckoningEngine.predict() is a no-op without a Pro license.
|
|
186
189
|
*/
|
|
187
|
-
readonly
|
|
190
|
+
readonly DEAD_RECKONING: "dead_reckoning";
|
|
188
191
|
/**
|
|
189
192
|
* Advanced bearing engine with look-ahead and speed-adaptive alpha.
|
|
190
193
|
* Produces stable heading for smooth map camera rotation.
|
|
194
|
+
* Gated inside NavCore.update() via this.has(FEATURES.ADVANCED_BEARING).
|
|
191
195
|
*/
|
|
192
196
|
readonly ADVANCED_BEARING: "advanced_bearing";
|
|
193
197
|
/**
|
|
194
198
|
* Compound deviation detection: combines distance, bearing, and speed signals.
|
|
195
199
|
* Eliminates false off-route triggers in tunnels and urban canyons.
|
|
200
|
+
* DeviationDetector.evaluate() returns a neutral signal without a Pro license.
|
|
196
201
|
*/
|
|
197
202
|
readonly COMPOUND_DEVIATION: "compound_deviation";
|
|
198
203
|
/**
|
|
199
204
|
* Parallel road disambiguation + U-turn snap protection.
|
|
200
205
|
* Prevents snapping to the wrong carriageway when bearing mismatches route direction.
|
|
206
|
+
* ParallelRoadResolver falls back to pure distance sorting without a Pro license.
|
|
201
207
|
*/
|
|
202
208
|
readonly PARALLEL_ROAD_RESOLUTION: "parallel_road_resolution";
|
|
203
209
|
/**
|
|
@@ -207,14 +213,17 @@ declare const FEATURES: {
|
|
|
207
213
|
readonly U_TURN_PROTECTION: "u_turn_protection";
|
|
208
214
|
/**
|
|
209
215
|
* Timed voice instruction cues with deduplication and priority levels.
|
|
216
|
+
* VoiceTriggerEngine.update() returns null without a Pro license.
|
|
210
217
|
*/
|
|
211
218
|
readonly VOICE_TRIGGERS: "voice_triggers";
|
|
212
219
|
/**
|
|
213
220
|
* Local ETA computation using rolling speed average — zero API calls.
|
|
221
|
+
* ETAEngine.update() returns isReliable=false without a Pro license.
|
|
214
222
|
*/
|
|
215
223
|
readonly ETA: "eta";
|
|
216
224
|
/**
|
|
217
225
|
* Circular and polygon geofencing with enter/exit/dwell events.
|
|
226
|
+
* GeofencingEngine.update() returns [] without a Pro license.
|
|
218
227
|
*/
|
|
219
228
|
readonly GEOFENCING: "geofencing";
|
|
220
229
|
/**
|
|
@@ -247,9 +256,25 @@ declare class LicenseManager {
|
|
|
247
256
|
private payload;
|
|
248
257
|
private enabledFeatures;
|
|
249
258
|
private warnedFeatures;
|
|
250
|
-
private
|
|
259
|
+
private static activeManager;
|
|
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;
|
|
251
275
|
private static PUBLIC_KEY_SPKI;
|
|
252
|
-
constructor(licenseKey?: string
|
|
276
|
+
constructor(licenseKey?: string);
|
|
277
|
+
private tryValidateSync;
|
|
253
278
|
validate(key: string): Promise<LicenseStatus>;
|
|
254
279
|
private extractFeatures;
|
|
255
280
|
hasFeature(feature: FeatureKey): boolean;
|
|
@@ -286,7 +311,6 @@ interface NavGpsUpdate {
|
|
|
286
311
|
}
|
|
287
312
|
interface NavCoreOptions {
|
|
288
313
|
licenseKey?: string;
|
|
289
|
-
isDev?: boolean;
|
|
290
314
|
isCircuit?: boolean;
|
|
291
315
|
kalmanQ?: number;
|
|
292
316
|
kalmanRBase?: number;
|
|
@@ -347,11 +371,8 @@ declare class NavCore {
|
|
|
347
371
|
private readonly options;
|
|
348
372
|
private listeners;
|
|
349
373
|
constructor(options?: NavCoreOptions);
|
|
350
|
-
/**
|
|
351
|
-
|
|
352
|
-
* Emits a one-time console warning when a Pro feature is blocked.
|
|
353
|
-
*/
|
|
354
|
-
private has;
|
|
374
|
+
/** Internal license check for automatic fallbacks that should not warn Core users every tick. */
|
|
375
|
+
private canUse;
|
|
355
376
|
/** Load route geometry and instructions */
|
|
356
377
|
setRoute(route: Coordinate[], instructions?: NavInstruction[]): void;
|
|
357
378
|
/** 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-DzTPBxIc.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-DzTPBxIc.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Bearing and angular math utilities.
|
|
@@ -281,6 +281,10 @@ 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;
|
|
284
288
|
}
|
|
285
289
|
declare class OSRMDirectionsProvider implements DirectionsProvider {
|
|
286
290
|
private readonly config;
|
|
@@ -288,6 +292,7 @@ declare class OSRMDirectionsProvider implements DirectionsProvider {
|
|
|
288
292
|
getRoute(waypoints: Coordinate[], options?: DirectionsOptions): Promise<DirectionsResult>;
|
|
289
293
|
private fetchRoute;
|
|
290
294
|
private fetchChunked;
|
|
295
|
+
private fetchWithTimeout;
|
|
291
296
|
}
|
|
292
297
|
|
|
293
298
|
/**
|
|
@@ -310,6 +315,10 @@ interface ValhallaConfig {
|
|
|
310
315
|
apiKey?: string;
|
|
311
316
|
/** Max waypoints per chunk (default: 50) */
|
|
312
317
|
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;
|
|
313
322
|
}
|
|
314
323
|
declare class ValhallaDirectionsProvider implements DirectionsProvider {
|
|
315
324
|
private readonly config;
|
|
@@ -319,7 +328,11 @@ declare class ValhallaDirectionsProvider implements DirectionsProvider {
|
|
|
319
328
|
private fetchRoute;
|
|
320
329
|
/** Decode Valhalla's encoded polyline6 format */
|
|
321
330
|
private decodePolyline;
|
|
331
|
+
private stitchGeometry;
|
|
332
|
+
private sameCoordinate;
|
|
333
|
+
private shapeIndex;
|
|
322
334
|
private fetchChunked;
|
|
335
|
+
private fetchWithTimeout;
|
|
323
336
|
}
|
|
324
337
|
|
|
325
338
|
/**
|
|
@@ -341,6 +354,10 @@ interface ORSConfig {
|
|
|
341
354
|
baseUrl?: string;
|
|
342
355
|
/** Max waypoints per request (ORS limit: 50) */
|
|
343
356
|
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;
|
|
344
361
|
}
|
|
345
362
|
declare class OpenRouteServiceProvider implements DirectionsProvider {
|
|
346
363
|
private readonly config;
|
|
@@ -349,6 +366,9 @@ declare class OpenRouteServiceProvider implements DirectionsProvider {
|
|
|
349
366
|
private profileFromOptions;
|
|
350
367
|
private fetchRoute;
|
|
351
368
|
private fetchChunked;
|
|
369
|
+
private stepRange;
|
|
370
|
+
private bearingFromGeometry;
|
|
371
|
+
private fetchWithTimeout;
|
|
352
372
|
}
|
|
353
373
|
|
|
354
374
|
/**
|
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-DzTPBxIc.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-DzTPBxIc.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Bearing and angular math utilities.
|
|
@@ -281,6 +281,10 @@ 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;
|
|
284
288
|
}
|
|
285
289
|
declare class OSRMDirectionsProvider implements DirectionsProvider {
|
|
286
290
|
private readonly config;
|
|
@@ -288,6 +292,7 @@ declare class OSRMDirectionsProvider implements DirectionsProvider {
|
|
|
288
292
|
getRoute(waypoints: Coordinate[], options?: DirectionsOptions): Promise<DirectionsResult>;
|
|
289
293
|
private fetchRoute;
|
|
290
294
|
private fetchChunked;
|
|
295
|
+
private fetchWithTimeout;
|
|
291
296
|
}
|
|
292
297
|
|
|
293
298
|
/**
|
|
@@ -310,6 +315,10 @@ interface ValhallaConfig {
|
|
|
310
315
|
apiKey?: string;
|
|
311
316
|
/** Max waypoints per chunk (default: 50) */
|
|
312
317
|
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;
|
|
313
322
|
}
|
|
314
323
|
declare class ValhallaDirectionsProvider implements DirectionsProvider {
|
|
315
324
|
private readonly config;
|
|
@@ -319,7 +328,11 @@ declare class ValhallaDirectionsProvider implements DirectionsProvider {
|
|
|
319
328
|
private fetchRoute;
|
|
320
329
|
/** Decode Valhalla's encoded polyline6 format */
|
|
321
330
|
private decodePolyline;
|
|
331
|
+
private stitchGeometry;
|
|
332
|
+
private sameCoordinate;
|
|
333
|
+
private shapeIndex;
|
|
322
334
|
private fetchChunked;
|
|
335
|
+
private fetchWithTimeout;
|
|
323
336
|
}
|
|
324
337
|
|
|
325
338
|
/**
|
|
@@ -341,6 +354,10 @@ interface ORSConfig {
|
|
|
341
354
|
baseUrl?: string;
|
|
342
355
|
/** Max waypoints per request (ORS limit: 50) */
|
|
343
356
|
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;
|
|
344
361
|
}
|
|
345
362
|
declare class OpenRouteServiceProvider implements DirectionsProvider {
|
|
346
363
|
private readonly config;
|
|
@@ -349,6 +366,9 @@ declare class OpenRouteServiceProvider implements DirectionsProvider {
|
|
|
349
366
|
private profileFromOptions;
|
|
350
367
|
private fetchRoute;
|
|
351
368
|
private fetchChunked;
|
|
369
|
+
private stepRange;
|
|
370
|
+
private bearingFromGeometry;
|
|
371
|
+
private fetchWithTimeout;
|
|
352
372
|
}
|
|
353
373
|
|
|
354
374
|
/**
|
package/dist/core.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
'use strict';var H=Object.defineProperty;var $=(i,t)=>{for(var e in t)H(i,e,{get:t[e],enumerable:true});};function f(i,t,e,n){let r=(e-i)*(Math.PI/180),s=(n-t)*(Math.PI/180),l=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(l),Math.sqrt(1-l)))}function X(i,t,e,n){let r=n/6371e3,s=e*(Math.PI/180),l=i*(Math.PI/180),p=t*(Math.PI/180),a=Math.asin(Math.sin(l)*Math.cos(r)+Math.cos(l)*Math.sin(r)*Math.cos(s));return [((p+Math.atan2(Math.sin(s)*Math.sin(r)*Math.cos(l),Math.cos(r)-Math.sin(l)*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),l=Math.sin(s-n)*Math.cos(r),p=Math.cos(e)*Math.sin(r)-Math.sin(e)*Math.cos(r)*Math.cos(s-n),a=Math.atan2(l,p)*(180/Math.PI);return a=(a+360)%360,a}function P(i){let t=i%360;return t>180?t-360:t<-180?t+360:t}function x(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),l=Math.sin(s-n)*Math.cos(r),p=Math.cos(e)*Math.sin(r)-Math.sin(e)*Math.cos(r)*Math.cos(s-n);return (Math.atan2(l,p)*180/Math.PI+360)%360}function q(i,t,e){let n=(r,s,l)=>r+(s-r)*l;return [n(i[0],t[0],e),n(i[1],t[1],e)]}function A(i,t,e){let[n,r]=i,[s,l]=t,[p,a]=e,d=p-s,u=a-l,o=d*d+u*u;if(o===0)return t;let c=((n-s)*d+(r-l)*u)/o;return c=Math.max(0,Math.min(1,c)),[s+c*d,l+c*u]}function z(i){let t=new Float64Array(i.length);for(let e=1;e<i.length;e++)t[e]=t[e-1]+f(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]+f(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,l=5e-5){i.x+=i.vx*r,i.y+=i.vy*r,i.P+=s;let p=l*Math.max(1,n/5),a=i.P/(i.P+p),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 S=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 W={};$(W,{ARRIVAL_THRESHOLD_METERS:()=>Ct,BASE_CORRIDOR_METERS:()=>J,BEARING_ALIGNMENT_THRESHOLD:()=>rt,BEARING_MIN_SPEED_MPS:()=>ot,BEARING_MISMATCH_PENALTY:()=>U,BEARING_MISMATCH_THRESHOLD:()=>k,BEARING_SMOOTHING_ALPHA:()=>nt,BETA_CORRECTION:()=>mt,DETOUR_COMMIT_MS:()=>lt,DR_MAX_AGE_MS:()=>it,GPS_ACCURACY_FACTOR:()=>tt,GPS_AGE_CAP_SECONDS:()=>dt,GPS_STALE_MS:()=>ut,INERTIA_PENALTY:()=>B,INERTIA_SEGMENT_DIST:()=>K,LOOK_AHEAD_SECONDS:()=>ft,MANEUVER_TRIGGER_DIST:()=>ht,MAX_CORRIDOR_METERS:()=>Q,MAX_LOOK_AHEAD_METERS:()=>gt,MAX_SNAP_DISTANCE:()=>F,MIN_LOOK_AHEAD_METERS:()=>yt,OFF_ROUTE_CONFIRM_MS:()=>st,REJOIN_CONFIRM_MS:()=>at,REJOIN_COOLDOWN_MS:()=>ct,SNAP_WINDOW_SIZE:()=>et,SPEED_CORRIDOR_FACTOR:()=>Z,STARTUP_GRACE_MS:()=>pt});var J=25,Q=60,Z=1.2,tt=.5,F=80,k=90,U=500,B=200,K=5,et=25,nt=.3,ot=1.5,rt=55,it=5e3,st=2e3,at=1500,ct=12e3,pt=3e3,lt=4e3,ut=3e3,dt=10,ht=25,mt=.15,ft=3,yt=20,gt=100,Ct=30;var Rt={useBearingPenalty:true,useInertiaPenalty:true,maxSnapDistance:80},E=class{constructor(t){this.options={...Rt,...t};}snap(t,e,n,r,s,l,p,a=null,d=null){let u=e.length,o=p,c=1/0,h=1/0,T=e[p]??[0,0];for(let C=0;C<=r;C++){let m=n+C;if(m>u-2)if(s&&l>u*.7)m=m%(u-1);else break;if(m<0||m>=u-1)continue;let w=e[m],N=e[m+1],R=A(t,w,N),b=f(t[1],t[0],R[1],R[0]);if(b>this.options.maxSnapDistance*2)continue;let y=b;if(this.options.useBearingPenalty&&a!==null){let G=x(w,N);Math.abs(P(a-G))>90&&(y+=500);}this.options.useInertiaPenalty&&d!==null&&Math.abs(m-d)>=5&&(y+=200),y<c&&(c=y,h=b,o=m,T=R);}return {idx:o,dist:h,proj:T}}};var D=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",l=`${this.config.baseUrl}/route/v1/${e}/${r}?overview=full&geometries=geojson&steps=${s}&annotations=false`,p=await fetch(l);if(!p.ok)throw new Error(`[OSRM] HTTP ${p.status}: ${p.statusText}`);let a=await p.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 c=t.slice(o,o+r);if(c.length<2||(s.push(c),o+r>=t.length))break}let l=await Promise.all(s.map(o=>this.fetchRoute(o,e,n))),p=[],a=0,d=0,u=[];for(let o=0;o<l.length;o++){let c=l[o];p.push(...o===0?c.geometry:c.geometry.slice(1)),a+=c.distance,d+=c.duration,u.push(...c.legs);}return {geometry:p,distance:a,duration:d,legs:u,raw:l.map(o=>o.raw)}}};var _=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(c=>({lon:c[0],lat:c[1],type:"break"})),s=JSON.stringify({locations:r,costing:e,directions_options:{units:"kilometers"}}),l={"Content-Type":"application/json"};this.config.apiKey&&(l.api_key=this.config.apiKey);let p=await fetch(`${this.config.baseUrl}/route`,{method:"POST",headers:l,body:s});if(!p.ok){let c=await p.text();throw new Error(`[Valhalla] HTTP ${p.status}: ${c}`)}let a=await p.json(),d=this.decodePolyline(a.trip?.legs?.[0]?.shape??""),u=a.trip?.summary??{},o=(a.trip?.legs??[]).map(c=>({distance:(c.summary?.length??0)*1e3,duration:c.summary?.time??0,steps:(c.maneuvers??[]).map(h=>({distance:(h.length??0)*1e3,duration:h.time??0,geometry:[],maneuver:{type:h.type?.toString()??"unknown",modifier:void 0,location:t[0],bearingBefore:h.begin_heading??0,bearingAfter:h.end_heading??0,instruction:h.instruction},name:h.street_names?.[0]}))}));return {geometry:d,distance:(u.length??0)*1e3,duration:u.time??0,legs:o,raw:a}}decodePolyline(t,e=6){let n=Math.pow(10,e),r=[],s=0,l=0,p=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;l+=o,a=0,d=0;do u=t.charCodeAt(s++)-63,d|=(u&31)<<a,a+=5;while(u>=32);let c=(d&1)!==0?~(d>>1):d>>1;p+=c,r.push([p/n,l/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 c=t.slice(o,o+r);if(c.length<2||(s.push(c),o+r>=t.length))break}let l=await Promise.all(s.map(o=>this.fetchRoute(o,e,n))),p=[],a=0,d=0,u=[];for(let o=0;o<l.length;o++){let c=l[o];p.push(...o===0?c.geometry:c.geometry.slice(1)),a+=c.distance,d+=c.duration,u.push(...c.legs);}return {geometry:p,distance:a,duration:d,legs:u,raw:l.map(o=>o.raw)}}};var bt="https://api.openrouteservice.org/v2/directions";var M=class{constructor(t){this.config={apiKey:t.apiKey,profile:t.profile??"driving-car",baseUrl:t.baseUrl??bt,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 l=await s.json(),p=l.features?.[0];if(!p)throw new Error("[ORS] No route returned");let a=p.properties?.summary??{},u=(p.properties?.segments??[]).map(o=>({distance:o.distance??0,duration:o.duration??0,steps:(o.steps??[]).map(c=>({distance:c.distance??0,duration:c.duration??0,geometry:[],maneuver:{type:c.type?.toString()??"unknown",modifier:void 0,location:t[0],bearingBefore:0,bearingAfter:0,instruction:c.instruction},name:c.name}))}));return {geometry:p.geometry?.coordinates??[],distance:a.distance??0,duration:a.duration??0,legs:u,raw:l}}async fetchChunked(t,e,n){let r=this.config.maxWaypointsPerChunk,s=[];for(let o=0;o<t.length;o+=r-1){let c=t.slice(o,o+r);if(c.length<2||(s.push(c),o+r>=t.length))break}let l=await Promise.all(s.map(o=>this.fetchRoute(o,e,n))),p=[],a=0,d=0,u=[];for(let o=0;o<l.length;o++){let c=l[o];p.push(...o===0?c.geometry:c.geometry.slice(1)),a+=c.distance,d+=c.duration,u.push(...c.legs);}return {geometry:p,distance:a,duration:d,legs:u,raw:l.map(o=>o.raw)}}};var Pt=0;function V(){return `wp_${Date.now()}_${++Pt}`}var v=class{constructor(){this.waypoints=[];}addWaypoint(t,e){let n=V();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=V();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(p=>p.coord);if(n.length<=e)return [n];let s=e-(t==="OVERLAP_2"?2:1),l=[];for(let p=0;p<n.length;p+=s){let a=n.slice(p,p+e);if(l.push(a),p+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 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"?>
|
|
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"?>
|
|
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 o of n)this.addWaypoint(o);}}}toGeoJSON(){let t=this.waypoints.map((n,o)=>({type:"Feature",geometry:{type:"Point",coordinates:n.coord},properties:{id:n.id,order:o,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 F={GPS_SMOOTHING:"gps_smoothing",BASIC_SNAPPING:"basic_snapping",PROGRESS_TRACKING:"progress_tracking",ROUTE_OFFSET:"route_offset",DEAD_RECKONING:"dead_reckoning",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 C=class C{constructor(t){this.status="MISSING";this.payload=null;this.enabledFeatures=new Set;this.warnedFeatures=new Set;t&&(this.tryValidateSync(t)||this.validate(t)),this.promoteToActive();}static getActive(){return C.activeManager}static clearActive(){C.activeManager=null;}promoteToActive(){let t=C.activeManager;(t===null||t.status!=="VALID"||this.status==="VALID")&&(C.activeManager=this);}tryValidateSync(t){return t==="eyJ0IjoicHJvIiwiZXhwIjo0OTMyNzAzMTU2MDAwLCJiaWQiOiJkZXYuYnlwYXNzIiwiZiI6WyIqIl19.MEQCIH4E4QNu9PuVsXHSnYmcqpCLk4QitiIH9hhY0Zm+YO5gAiAE7X3c47YQLUj7WPSGKw9Y7W2kBUR5GCnOMBwdBsYGgg=="?typeof __DEV__<"u"&&__DEV__||typeof window<"u"&&(window.location?.hostname==="localhost"||window.location?.hostname==="127.0.0.1"||window.location?.hostname?.startsWith("192.168.")||window.location?.hostname?.endsWith(".local"))||typeof process<"u"&&(process.env?.NODE_ENV==="development"||process.env?.NODE_ENV==="test"||process.env?.VITEST==="true"||process.env?.JEST_WORKER_ID!==void 0)?(this.status="VALID",this.payload={t:"pro",exp:4932703156e3,bid:"dev.bypass",f:["*"]},this.extractFeatures(),console.log("\u{1F511} [NavCore] Development bypass key validated synchronously. Plan: pro"),true):(console.warn("[NavCore] Development bypass key is restricted to local development environments."),this.status="INVALID",this.payload=null,true):false}async validate(t){if(this.tryValidateSync(t))return this.status;try{let[e,n]=t.split(".");if(!e||!n)return this.status="INVALID",this.status;let o=atob(e);if(this.payload=JSON.parse(o),!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;if(this.payload?.bid==="dev.bypass"&&!(typeof __DEV__<"u"&&__DEV__||typeof window<"u"&&(window.location?.hostname==="localhost"||window.location?.hostname==="127.0.0.1"||window.location?.hostname?.startsWith("192.168.")||window.location?.hostname?.endsWith(".local"))||typeof process<"u"&&(process.env?.NODE_ENV==="development"||process.env?.NODE_ENV==="test"||process.env?.VITEST==="true"||process.env?.JEST_WORKER_ID!==void 0)))return console.warn("[NavCore] Development bypass key is restricted to local development environments."),this.status="INVALID",this.payload=null,this.status;this.status="VALID",this.extractFeatures(),this.promoteToActive(),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.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(F.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 o=new TextEncoder().encode(t),i=Uint8Array.from(atob(e),c=>c.charCodeAt(0)),l=Uint8Array.from(atob(C.PUBLIC_KEY_SPKI),c=>c.charCodeAt(0)),a=await crypto.subtle.importKey("spki",l,{name:"ECDSA",namedCurve:"P-256"},!0,["verify"]);return await crypto.subtle.verify({name:"ECDSA",hash:{name:"SHA-256"}},a,i,o)}catch{return false}}};C.activeManager=null,C.PUBLIC_KEY_SPKI="MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEk6onJmJkWtRFusiSS69dcdONX4xL2Snm4AZO+dYjSynfJiL4x7trEy80MImLftknBWT/qI0z7ox4Q7VNL3te6A==";var N=C;exports.Constants=K;exports.CustomRouteBuilder=T;exports.FEATURES=F;exports.KalmanFilter2D=P;exports.LicenseManager=N;exports.OSRMDirectionsProvider=O;exports.OpenRouteServiceProvider=w;exports.RouteSnapper=D;exports.ValhallaDirectionsProvider=I;exports.buildForwardCumulativeDistances=J;exports.buildReverseCumulativeDistances=z;exports.destinationPoint=X;exports.geoGetBearing=j;exports.getBearingBetweenPoints=x;exports.haversineDistance=R;exports.interpolatePoint=Y;exports.kalmanUpdate2D=k;exports.normalizeAngle=v;exports.projectPointOnSegment=_;
|
package/dist/core.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
var H=Object.defineProperty;var $=(i,t)=>{for(var e in t)H(i,e,{get:t[e],enumerable:true});};function f(i,t,e,n){let r=(e-i)*(Math.PI/180),s=(n-t)*(Math.PI/180),l=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(l),Math.sqrt(1-l)))}function X(i,t,e,n){let r=n/6371e3,s=e*(Math.PI/180),l=i*(Math.PI/180),p=t*(Math.PI/180),a=Math.asin(Math.sin(l)*Math.cos(r)+Math.cos(l)*Math.sin(r)*Math.cos(s));return [((p+Math.atan2(Math.sin(s)*Math.sin(r)*Math.cos(l),Math.cos(r)-Math.sin(l)*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),l=Math.sin(s-n)*Math.cos(r),p=Math.cos(e)*Math.sin(r)-Math.sin(e)*Math.cos(r)*Math.cos(s-n),a=Math.atan2(l,p)*(180/Math.PI);return a=(a+360)%360,a}function P(i){let t=i%360;return t>180?t-360:t<-180?t+360:t}function x(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),l=Math.sin(s-n)*Math.cos(r),p=Math.cos(e)*Math.sin(r)-Math.sin(e)*Math.cos(r)*Math.cos(s-n);return (Math.atan2(l,p)*180/Math.PI+360)%360}function q(i,t,e){let n=(r,s,l)=>r+(s-r)*l;return [n(i[0],t[0],e),n(i[1],t[1],e)]}function A(i,t,e){let[n,r]=i,[s,l]=t,[p,a]=e,d=p-s,u=a-l,o=d*d+u*u;if(o===0)return t;let c=((n-s)*d+(r-l)*u)/o;return c=Math.max(0,Math.min(1,c)),[s+c*d,l+c*u]}function z(i){let t=new Float64Array(i.length);for(let e=1;e<i.length;e++)t[e]=t[e-1]+f(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]+f(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,l=5e-5){i.x+=i.vx*r,i.y+=i.vy*r,i.P+=s;let p=l*Math.max(1,n/5),a=i.P/(i.P+p),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 S=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 W={};$(W,{ARRIVAL_THRESHOLD_METERS:()=>Ct,BASE_CORRIDOR_METERS:()=>J,BEARING_ALIGNMENT_THRESHOLD:()=>rt,BEARING_MIN_SPEED_MPS:()=>ot,BEARING_MISMATCH_PENALTY:()=>U,BEARING_MISMATCH_THRESHOLD:()=>k,BEARING_SMOOTHING_ALPHA:()=>nt,BETA_CORRECTION:()=>mt,DETOUR_COMMIT_MS:()=>lt,DR_MAX_AGE_MS:()=>it,GPS_ACCURACY_FACTOR:()=>tt,GPS_AGE_CAP_SECONDS:()=>dt,GPS_STALE_MS:()=>ut,INERTIA_PENALTY:()=>B,INERTIA_SEGMENT_DIST:()=>K,LOOK_AHEAD_SECONDS:()=>ft,MANEUVER_TRIGGER_DIST:()=>ht,MAX_CORRIDOR_METERS:()=>Q,MAX_LOOK_AHEAD_METERS:()=>gt,MAX_SNAP_DISTANCE:()=>F,MIN_LOOK_AHEAD_METERS:()=>yt,OFF_ROUTE_CONFIRM_MS:()=>st,REJOIN_CONFIRM_MS:()=>at,REJOIN_COOLDOWN_MS:()=>ct,SNAP_WINDOW_SIZE:()=>et,SPEED_CORRIDOR_FACTOR:()=>Z,STARTUP_GRACE_MS:()=>pt});var J=25,Q=60,Z=1.2,tt=.5,F=80,k=90,U=500,B=200,K=5,et=25,nt=.3,ot=1.5,rt=55,it=5e3,st=2e3,at=1500,ct=12e3,pt=3e3,lt=4e3,ut=3e3,dt=10,ht=25,mt=.15,ft=3,yt=20,gt=100,Ct=30;var Rt={useBearingPenalty:true,useInertiaPenalty:true,maxSnapDistance:80},E=class{constructor(t){this.options={...Rt,...t};}snap(t,e,n,r,s,l,p,a=null,d=null){let u=e.length,o=p,c=1/0,h=1/0,T=e[p]??[0,0];for(let C=0;C<=r;C++){let m=n+C;if(m>u-2)if(s&&l>u*.7)m=m%(u-1);else break;if(m<0||m>=u-1)continue;let w=e[m],N=e[m+1],R=A(t,w,N),b=f(t[1],t[0],R[1],R[0]);if(b>this.options.maxSnapDistance*2)continue;let y=b;if(this.options.useBearingPenalty&&a!==null){let G=x(w,N);Math.abs(P(a-G))>90&&(y+=500);}this.options.useInertiaPenalty&&d!==null&&Math.abs(m-d)>=5&&(y+=200),y<c&&(c=y,h=b,o=m,T=R);}return {idx:o,dist:h,proj:T}}};var D=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",l=`${this.config.baseUrl}/route/v1/${e}/${r}?overview=full&geometries=geojson&steps=${s}&annotations=false`,p=await fetch(l);if(!p.ok)throw new Error(`[OSRM] HTTP ${p.status}: ${p.statusText}`);let a=await p.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 c=t.slice(o,o+r);if(c.length<2||(s.push(c),o+r>=t.length))break}let l=await Promise.all(s.map(o=>this.fetchRoute(o,e,n))),p=[],a=0,d=0,u=[];for(let o=0;o<l.length;o++){let c=l[o];p.push(...o===0?c.geometry:c.geometry.slice(1)),a+=c.distance,d+=c.duration,u.push(...c.legs);}return {geometry:p,distance:a,duration:d,legs:u,raw:l.map(o=>o.raw)}}};var _=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(c=>({lon:c[0],lat:c[1],type:"break"})),s=JSON.stringify({locations:r,costing:e,directions_options:{units:"kilometers"}}),l={"Content-Type":"application/json"};this.config.apiKey&&(l.api_key=this.config.apiKey);let p=await fetch(`${this.config.baseUrl}/route`,{method:"POST",headers:l,body:s});if(!p.ok){let c=await p.text();throw new Error(`[Valhalla] HTTP ${p.status}: ${c}`)}let a=await p.json(),d=this.decodePolyline(a.trip?.legs?.[0]?.shape??""),u=a.trip?.summary??{},o=(a.trip?.legs??[]).map(c=>({distance:(c.summary?.length??0)*1e3,duration:c.summary?.time??0,steps:(c.maneuvers??[]).map(h=>({distance:(h.length??0)*1e3,duration:h.time??0,geometry:[],maneuver:{type:h.type?.toString()??"unknown",modifier:void 0,location:t[0],bearingBefore:h.begin_heading??0,bearingAfter:h.end_heading??0,instruction:h.instruction},name:h.street_names?.[0]}))}));return {geometry:d,distance:(u.length??0)*1e3,duration:u.time??0,legs:o,raw:a}}decodePolyline(t,e=6){let n=Math.pow(10,e),r=[],s=0,l=0,p=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;l+=o,a=0,d=0;do u=t.charCodeAt(s++)-63,d|=(u&31)<<a,a+=5;while(u>=32);let c=(d&1)!==0?~(d>>1):d>>1;p+=c,r.push([p/n,l/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 c=t.slice(o,o+r);if(c.length<2||(s.push(c),o+r>=t.length))break}let l=await Promise.all(s.map(o=>this.fetchRoute(o,e,n))),p=[],a=0,d=0,u=[];for(let o=0;o<l.length;o++){let c=l[o];p.push(...o===0?c.geometry:c.geometry.slice(1)),a+=c.distance,d+=c.duration,u.push(...c.legs);}return {geometry:p,distance:a,duration:d,legs:u,raw:l.map(o=>o.raw)}}};var bt="https://api.openrouteservice.org/v2/directions";var M=class{constructor(t){this.config={apiKey:t.apiKey,profile:t.profile??"driving-car",baseUrl:t.baseUrl??bt,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 l=await s.json(),p=l.features?.[0];if(!p)throw new Error("[ORS] No route returned");let a=p.properties?.summary??{},u=(p.properties?.segments??[]).map(o=>({distance:o.distance??0,duration:o.duration??0,steps:(o.steps??[]).map(c=>({distance:c.distance??0,duration:c.duration??0,geometry:[],maneuver:{type:c.type?.toString()??"unknown",modifier:void 0,location:t[0],bearingBefore:0,bearingAfter:0,instruction:c.instruction},name:c.name}))}));return {geometry:p.geometry?.coordinates??[],distance:a.distance??0,duration:a.duration??0,legs:u,raw:l}}async fetchChunked(t,e,n){let r=this.config.maxWaypointsPerChunk,s=[];for(let o=0;o<t.length;o+=r-1){let c=t.slice(o,o+r);if(c.length<2||(s.push(c),o+r>=t.length))break}let l=await Promise.all(s.map(o=>this.fetchRoute(o,e,n))),p=[],a=0,d=0,u=[];for(let o=0;o<l.length;o++){let c=l[o];p.push(...o===0?c.geometry:c.geometry.slice(1)),a+=c.distance,d+=c.duration,u.push(...c.legs);}return {geometry:p,distance:a,duration:d,legs:u,raw:l.map(o=>o.raw)}}};var Pt=0;function V(){return `wp_${Date.now()}_${++Pt}`}var v=class{constructor(){this.waypoints=[];}addWaypoint(t,e){let n=V();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=V();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(p=>p.coord);if(n.length<=e)return [n];let s=e-(t==="OVERLAP_2"?2:1),l=[];for(let p=0;p<n.length;p+=s){let a=n.slice(p,p+e);if(l.push(a),p+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 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"?>
|
|
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"?>
|
|
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 o of n)this.addWaypoint(o);}}}toGeoJSON(){let t=this.waypoints.map((n,o)=>({type:"Feature",geometry:{type:"Point",coordinates:n.coord},properties:{id:n.id,order:o,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 F={GPS_SMOOTHING:"gps_smoothing",BASIC_SNAPPING:"basic_snapping",PROGRESS_TRACKING:"progress_tracking",ROUTE_OFFSET:"route_offset",DEAD_RECKONING:"dead_reckoning",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 C=class C{constructor(t){this.status="MISSING";this.payload=null;this.enabledFeatures=new Set;this.warnedFeatures=new Set;t&&(this.tryValidateSync(t)||this.validate(t)),this.promoteToActive();}static getActive(){return C.activeManager}static clearActive(){C.activeManager=null;}promoteToActive(){let t=C.activeManager;(t===null||t.status!=="VALID"||this.status==="VALID")&&(C.activeManager=this);}tryValidateSync(t){return t==="eyJ0IjoicHJvIiwiZXhwIjo0OTMyNzAzMTU2MDAwLCJiaWQiOiJkZXYuYnlwYXNzIiwiZiI6WyIqIl19.MEQCIH4E4QNu9PuVsXHSnYmcqpCLk4QitiIH9hhY0Zm+YO5gAiAE7X3c47YQLUj7WPSGKw9Y7W2kBUR5GCnOMBwdBsYGgg=="?typeof __DEV__<"u"&&__DEV__||typeof window<"u"&&(window.location?.hostname==="localhost"||window.location?.hostname==="127.0.0.1"||window.location?.hostname?.startsWith("192.168.")||window.location?.hostname?.endsWith(".local"))||typeof process<"u"&&(process.env?.NODE_ENV==="development"||process.env?.NODE_ENV==="test"||process.env?.VITEST==="true"||process.env?.JEST_WORKER_ID!==void 0)?(this.status="VALID",this.payload={t:"pro",exp:4932703156e3,bid:"dev.bypass",f:["*"]},this.extractFeatures(),console.log("\u{1F511} [NavCore] Development bypass key validated synchronously. Plan: pro"),true):(console.warn("[NavCore] Development bypass key is restricted to local development environments."),this.status="INVALID",this.payload=null,true):false}async validate(t){if(this.tryValidateSync(t))return this.status;try{let[e,n]=t.split(".");if(!e||!n)return this.status="INVALID",this.status;let o=atob(e);if(this.payload=JSON.parse(o),!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;if(this.payload?.bid==="dev.bypass"&&!(typeof __DEV__<"u"&&__DEV__||typeof window<"u"&&(window.location?.hostname==="localhost"||window.location?.hostname==="127.0.0.1"||window.location?.hostname?.startsWith("192.168.")||window.location?.hostname?.endsWith(".local"))||typeof process<"u"&&(process.env?.NODE_ENV==="development"||process.env?.NODE_ENV==="test"||process.env?.VITEST==="true"||process.env?.JEST_WORKER_ID!==void 0)))return console.warn("[NavCore] Development bypass key is restricted to local development environments."),this.status="INVALID",this.payload=null,this.status;this.status="VALID",this.extractFeatures(),this.promoteToActive(),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.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(F.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 o=new TextEncoder().encode(t),i=Uint8Array.from(atob(e),c=>c.charCodeAt(0)),l=Uint8Array.from(atob(C.PUBLIC_KEY_SPKI),c=>c.charCodeAt(0)),a=await crypto.subtle.importKey("spki",l,{name:"ECDSA",namedCurve:"P-256"},!0,["verify"]);return await crypto.subtle.verify({name:"ECDSA",hash:{name:"SHA-256"}},a,i,o)}catch{return false}}};C.activeManager=null,C.PUBLIC_KEY_SPKI="MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEk6onJmJkWtRFusiSS69dcdONX4xL2Snm4AZO+dYjSynfJiL4x7trEy80MImLftknBWT/qI0z7ox4Q7VNL3te6A==";var N=C;export{K as Constants,T as CustomRouteBuilder,F as FEATURES,P as KalmanFilter2D,N as LicenseManager,O as OSRMDirectionsProvider,w as OpenRouteServiceProvider,D as RouteSnapper,I as ValhallaDirectionsProvider,J as buildForwardCumulativeDistances,z as buildReverseCumulativeDistances,X as destinationPoint,j as geoGetBearing,x as getBearingBetweenPoints,R as haversineDistance,Y as interpolatePoint,k as kalmanUpdate2D,v as normalizeAngle,_ as projectPointOnSegment};
|
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,66 @@
|
|
|
1
|
-
|
|
1
|
+
import { C as Coordinate } from './NavCore-DzTPBxIc.mjs';
|
|
2
|
+
export { F as FEATURES, a as FeatureKey, L as LicenseManager, b as LicensePayload, c as LicenseStatus, d as LifecycleContext, e as LifecycleEvent, N as NavCore, f as NavCoreOptions, g as NavCoreState, h as NavGpsUpdate, i as NavInstruction, j as NavLifecycleState, k as NavigationFSM, O as OffRouteContext, l as OffRouteEvent, m as OffRouteFSM, n as OffRouteState, R as RejoinTarget, T as TempRoute, o as destinationPoint, p as geoGetBearing, q as haversineDistance, r as resolveNextInstruction } from './NavCore-DzTPBxIc.mjs';
|
|
2
3
|
export { BuildOptions, CameraOptions, Constants, CustomRouteBuilder, CustomWaypoint, DirectionsLeg, DirectionsManeuver, DirectionsOptions, DirectionsProvider, DirectionsResult, DirectionsStep, Kalman2DState, KalmanFilter2D, MapRendererAdapter, ORSConfig, ORSProfile, OSRMConfig, OSRMDirectionsProvider, OpenRouteServiceProvider, RouteSnapper, RouteStyle, SnapResult, SnapperOptions, ValhallaConfig, ValhallaCostingModel, ValhallaDirectionsProvider, VehicleStyle, WaypointOptions, buildForwardCumulativeDistances, buildReverseCumulativeDistances, getBearingBetweenPoints, interpolatePoint, kalmanUpdate2D, normalizeAngle, projectPointOnSegment } from './core.mjs';
|
|
3
|
-
export { DeadReckoningEngine, DeviationDetector, ETAEngine, ETAOptions, ETAResult, GeofenceEvent, GeofenceEventType, GeofenceType, GeofencingEngine, GeofencingOptions, InstructionEditor, InstructionType, ParallelRoadResolver, ParallelRoadResolverOptions, ResolvedCandidate, RichInstruction, SnapCandidate, VoiceCue, VoicePriority, VoiceTriggerEngine, VoiceTriggerOptions,
|
|
4
|
+
export { DeadReckoningEngine, DeviationDetector, ETAEngine, ETAOptions, ETAResult, GeofenceEvent, GeofenceEventType, GeofenceType, GeofencingEngine, GeofencingOptions, InstructionEditor, InstructionType, ParallelRoadResolver, ParallelRoadResolverOptions, ResolvedCandidate, RichInstruction, SnapCandidate, VoiceCue, VoicePriority, VoiceTriggerEngine, VoiceTriggerOptions, ZoneDefinition, calculateDynamicCorridor, computeDeadReckoningOnRoute } from './pro.mjs';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Module 5: BearingEngine
|
|
8
|
+
* Speed-adaptive IIR bearing smoothing.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Calculate speed-adaptive smoothing factor.
|
|
13
|
+
* Higher speed → less smoothing (alpha closer to 1).
|
|
14
|
+
* Lower speed → more smoothing (alpha closer to base value).
|
|
15
|
+
*/
|
|
16
|
+
declare function getSpeedAdaptiveAlpha(speedMps: number, baseAlpha?: number): number;
|
|
17
|
+
/**
|
|
18
|
+
* Compute bearing from the route geometry at the current segment.
|
|
19
|
+
*/
|
|
20
|
+
declare function calculateRobustBearing(route: Coordinate[], currentIdx: number, lookAhead?: number): number;
|
|
21
|
+
/**
|
|
22
|
+
* Blend two bearings using the shortest angular path.
|
|
23
|
+
*/
|
|
24
|
+
declare function blendBearing(current: number, target: number, alpha: number): number;
|
|
25
|
+
/**
|
|
26
|
+
* Full bearing smoothing pipeline: route bearing → IIR blend → output.
|
|
27
|
+
*/
|
|
28
|
+
declare function applyBearingSmoothing(currentBearing: number, route: Coordinate[], routeIdx: number, speedMps: number, gpsBearing: number | null, baseAlpha?: number): number;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Module 6: ProgressTracker
|
|
32
|
+
* Monotonic route progress tracking with anti-jitter.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Validate a progress update: ensures monotonic forward progress with jitter tolerance.
|
|
37
|
+
*
|
|
38
|
+
* @returns The new progress index (may be the same as current if update is rejected)
|
|
39
|
+
*/
|
|
40
|
+
declare function validateProgressUpdate(currentIdx: number, candidateIdx: number, route: Coordinate[], distToRoute: number, maxSnapDistance: number): number;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Module 8: RouteOffsetPredictor
|
|
44
|
+
* Linear distance-based position predictor for smooth rendering between GPS fixes.
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Advance the predictor's offset by speed * dt.
|
|
49
|
+
*/
|
|
50
|
+
declare function advancePredictor(currentOffset: number, speedMps: number, dtSec: number): number;
|
|
51
|
+
/**
|
|
52
|
+
* Correct the predictor when a new GPS fix arrives.
|
|
53
|
+
* Blend towards the actual measured offset using betaCorrection.
|
|
54
|
+
*/
|
|
55
|
+
declare function applyGpsCorrection(predictedOffset: number, measuredOffset: number, betaCorrection?: number): number;
|
|
56
|
+
/**
|
|
57
|
+
* Given a linear offset (metres from route start), find the [lng, lat] on the route.
|
|
58
|
+
*
|
|
59
|
+
* @param offset Linear distance from route start in metres
|
|
60
|
+
* @param cumulativeDistances Forward cumulative distance array
|
|
61
|
+
* @param route Route coordinates
|
|
62
|
+
* @returns Interpolated coordinate on the route
|
|
63
|
+
*/
|
|
64
|
+
declare function pointAtOffset(offset: number, cumulativeDistances: Float64Array, route: Coordinate[]): Coordinate;
|
|
65
|
+
|
|
66
|
+
export { Coordinate, advancePredictor, applyBearingSmoothing, applyGpsCorrection, blendBearing, calculateRobustBearing, getSpeedAdaptiveAlpha, pointAtOffset, validateProgressUpdate };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,66 @@
|
|
|
1
|
-
|
|
1
|
+
import { C as Coordinate } from './NavCore-DzTPBxIc.js';
|
|
2
|
+
export { F as FEATURES, a as FeatureKey, L as LicenseManager, b as LicensePayload, c as LicenseStatus, d as LifecycleContext, e as LifecycleEvent, N as NavCore, f as NavCoreOptions, g as NavCoreState, h as NavGpsUpdate, i as NavInstruction, j as NavLifecycleState, k as NavigationFSM, O as OffRouteContext, l as OffRouteEvent, m as OffRouteFSM, n as OffRouteState, R as RejoinTarget, T as TempRoute, o as destinationPoint, p as geoGetBearing, q as haversineDistance, r as resolveNextInstruction } from './NavCore-DzTPBxIc.js';
|
|
2
3
|
export { BuildOptions, CameraOptions, Constants, CustomRouteBuilder, CustomWaypoint, DirectionsLeg, DirectionsManeuver, DirectionsOptions, DirectionsProvider, DirectionsResult, DirectionsStep, Kalman2DState, KalmanFilter2D, MapRendererAdapter, ORSConfig, ORSProfile, OSRMConfig, OSRMDirectionsProvider, OpenRouteServiceProvider, RouteSnapper, RouteStyle, SnapResult, SnapperOptions, ValhallaConfig, ValhallaCostingModel, ValhallaDirectionsProvider, VehicleStyle, WaypointOptions, buildForwardCumulativeDistances, buildReverseCumulativeDistances, getBearingBetweenPoints, interpolatePoint, kalmanUpdate2D, normalizeAngle, projectPointOnSegment } from './core.js';
|
|
3
|
-
export { DeadReckoningEngine, DeviationDetector, ETAEngine, ETAOptions, ETAResult, GeofenceEvent, GeofenceEventType, GeofenceType, GeofencingEngine, GeofencingOptions, InstructionEditor, InstructionType, ParallelRoadResolver, ParallelRoadResolverOptions, ResolvedCandidate, RichInstruction, SnapCandidate, VoiceCue, VoicePriority, VoiceTriggerEngine, VoiceTriggerOptions,
|
|
4
|
+
export { DeadReckoningEngine, DeviationDetector, ETAEngine, ETAOptions, ETAResult, GeofenceEvent, GeofenceEventType, GeofenceType, GeofencingEngine, GeofencingOptions, InstructionEditor, InstructionType, ParallelRoadResolver, ParallelRoadResolverOptions, ResolvedCandidate, RichInstruction, SnapCandidate, VoiceCue, VoicePriority, VoiceTriggerEngine, VoiceTriggerOptions, ZoneDefinition, calculateDynamicCorridor, computeDeadReckoningOnRoute } from './pro.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Module 5: BearingEngine
|
|
8
|
+
* Speed-adaptive IIR bearing smoothing.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Calculate speed-adaptive smoothing factor.
|
|
13
|
+
* Higher speed → less smoothing (alpha closer to 1).
|
|
14
|
+
* Lower speed → more smoothing (alpha closer to base value).
|
|
15
|
+
*/
|
|
16
|
+
declare function getSpeedAdaptiveAlpha(speedMps: number, baseAlpha?: number): number;
|
|
17
|
+
/**
|
|
18
|
+
* Compute bearing from the route geometry at the current segment.
|
|
19
|
+
*/
|
|
20
|
+
declare function calculateRobustBearing(route: Coordinate[], currentIdx: number, lookAhead?: number): number;
|
|
21
|
+
/**
|
|
22
|
+
* Blend two bearings using the shortest angular path.
|
|
23
|
+
*/
|
|
24
|
+
declare function blendBearing(current: number, target: number, alpha: number): number;
|
|
25
|
+
/**
|
|
26
|
+
* Full bearing smoothing pipeline: route bearing → IIR blend → output.
|
|
27
|
+
*/
|
|
28
|
+
declare function applyBearingSmoothing(currentBearing: number, route: Coordinate[], routeIdx: number, speedMps: number, gpsBearing: number | null, baseAlpha?: number): number;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Module 6: ProgressTracker
|
|
32
|
+
* Monotonic route progress tracking with anti-jitter.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Validate a progress update: ensures monotonic forward progress with jitter tolerance.
|
|
37
|
+
*
|
|
38
|
+
* @returns The new progress index (may be the same as current if update is rejected)
|
|
39
|
+
*/
|
|
40
|
+
declare function validateProgressUpdate(currentIdx: number, candidateIdx: number, route: Coordinate[], distToRoute: number, maxSnapDistance: number): number;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Module 8: RouteOffsetPredictor
|
|
44
|
+
* Linear distance-based position predictor for smooth rendering between GPS fixes.
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Advance the predictor's offset by speed * dt.
|
|
49
|
+
*/
|
|
50
|
+
declare function advancePredictor(currentOffset: number, speedMps: number, dtSec: number): number;
|
|
51
|
+
/**
|
|
52
|
+
* Correct the predictor when a new GPS fix arrives.
|
|
53
|
+
* Blend towards the actual measured offset using betaCorrection.
|
|
54
|
+
*/
|
|
55
|
+
declare function applyGpsCorrection(predictedOffset: number, measuredOffset: number, betaCorrection?: number): number;
|
|
56
|
+
/**
|
|
57
|
+
* Given a linear offset (metres from route start), find the [lng, lat] on the route.
|
|
58
|
+
*
|
|
59
|
+
* @param offset Linear distance from route start in metres
|
|
60
|
+
* @param cumulativeDistances Forward cumulative distance array
|
|
61
|
+
* @param route Route coordinates
|
|
62
|
+
* @returns Interpolated coordinate on the route
|
|
63
|
+
*/
|
|
64
|
+
declare function pointAtOffset(offset: number, cumulativeDistances: Float64Array, route: Coordinate[]): Coordinate;
|
|
65
|
+
|
|
66
|
+
export { Coordinate, advancePredictor, applyBearingSmoothing, applyGpsCorrection, blendBearing, calculateRobustBearing, getSpeedAdaptiveAlpha, pointAtOffset, validateProgressUpdate };
|