geo-relative-position 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,604 @@
1
+ /**
2
+ * Basic geographic coordinates
3
+ */
4
+ interface Coordinates {
5
+ /** Latitude in degrees (-90 to 90) */
6
+ latitude: number;
7
+ /** Longitude in degrees (-180 to 180) */
8
+ longitude: number;
9
+ }
10
+ /**
11
+ * User's current position with optional motion data
12
+ */
13
+ interface UserPosition extends Coordinates {
14
+ /** User's direction of travel in degrees (0-360, 0 = North, 90 = East) */
15
+ bearing?: number;
16
+ /** User's speed in meters per second */
17
+ speedMps?: number;
18
+ /** GPS accuracy radius in meters */
19
+ accuracy?: number;
20
+ /** Altitude in meters (for future 3D calculations) */
21
+ altitude?: number;
22
+ }
23
+ /**
24
+ * Point of Interest with optional boundary radius
25
+ */
26
+ interface POI extends Coordinates {
27
+ /** Unique identifier for the POI */
28
+ id?: string | number;
29
+ /** Display name of the POI */
30
+ name?: string;
31
+ /** Radius in meters defining POI boundary (for large POIs like parks) */
32
+ radiusMeters?: number;
33
+ /** Optional metadata */
34
+ metadata?: Record<string, unknown>;
35
+ }
36
+ /**
37
+ * Simple 4-direction orientation
38
+ */
39
+ type SimpleOrientation = 'ahead' | 'behind' | 'left' | 'right';
40
+ /**
41
+ * Granular 8-direction orientation (compass points)
42
+ */
43
+ type CompassOrientation = 'north' | 'northeast' | 'east' | 'southeast' | 'south' | 'southwest' | 'west' | 'northwest';
44
+ /**
45
+ * Detailed relative orientation with angular precision
46
+ */
47
+ type DetailedOrientation = 'directly_ahead' | 'ahead_left' | 'ahead_right' | 'left' | 'right' | 'behind_left' | 'behind_right' | 'directly_behind';
48
+ /**
49
+ * Approach status indicating if user is moving toward or away from POI
50
+ */
51
+ type ApproachStatus = 'approaching' | 'receding' | 'stationary' | 'unknown';
52
+ /**
53
+ * Complete relative position result
54
+ */
55
+ interface RelativePosition {
56
+ /** Distance from user to POI center in meters */
57
+ distanceMeters: number;
58
+ /** Distance from user to POI center in kilometers */
59
+ distanceKm: number;
60
+ /** Distance from user to POI edge (considering radius) in meters */
61
+ distanceToEdgeMeters: number;
62
+ /** Absolute bearing from user to POI (0-360, 0 = North) */
63
+ absoluteBearing: number;
64
+ /** Relative bearing from user's heading to POI (-180 to 180) */
65
+ relativeBearing: number;
66
+ /** Simple orientation (4-way) */
67
+ simpleOrientation: SimpleOrientation;
68
+ /** Compass orientation (8-way) */
69
+ compassOrientation: CompassOrientation;
70
+ /** Detailed orientation */
71
+ detailedOrientation: DetailedOrientation;
72
+ /** Whether user is currently within POI boundary */
73
+ isWithinPOI: boolean;
74
+ /** Whether user is approaching or receding from POI */
75
+ approachStatus: ApproachStatus;
76
+ }
77
+ /**
78
+ * Estimated Time of Arrival result
79
+ */
80
+ interface ETAResult {
81
+ /** Estimated time to reach POI center in seconds */
82
+ etaSeconds: number;
83
+ /** Estimated time to reach POI edge in seconds (if POI has radius) */
84
+ etaToEdgeSeconds: number;
85
+ /** Formatted time string (e.g., "2 min 30 sec", "1 hr 15 min") */
86
+ formatted: string;
87
+ /** Formatted short time string (e.g., "2m", "1h 15m") */
88
+ formattedShort: string;
89
+ /** Whether ETA is valid (user moving toward POI) */
90
+ isValid: boolean;
91
+ /** Reason if ETA is invalid */
92
+ invalidReason?: 'stationary' | 'moving_away' | 'no_speed_data' | 'at_destination';
93
+ }
94
+ /**
95
+ * Closest point calculation result (for POIs with radius)
96
+ */
97
+ interface ClosestPointResult {
98
+ /** Coordinates of closest point on POI boundary */
99
+ closestPoint: Coordinates;
100
+ /** Distance to closest point in meters */
101
+ distanceMeters: number;
102
+ /** Bearing to closest point */
103
+ bearing: number;
104
+ /** Whether user is inside the POI boundary */
105
+ isInside: boolean;
106
+ }
107
+ /**
108
+ * POI with calculated relative position data
109
+ */
110
+ interface POIWithRelativePosition extends POI {
111
+ /** Calculated relative position data */
112
+ relativePosition: RelativePosition;
113
+ /** Optional ETA data (if user speed provided) */
114
+ eta?: ETAResult;
115
+ }
116
+ /**
117
+ * Cone filter configuration (for route-ahead queries)
118
+ */
119
+ interface ConeFilter {
120
+ /** Center angle of cone in degrees (typically user's bearing) */
121
+ centerAngle: number;
122
+ /** Half-width of cone in degrees (e.g., 30 = 60 degree total cone) */
123
+ halfAngle: number;
124
+ /** Maximum distance in meters */
125
+ maxDistanceMeters: number;
126
+ /** Minimum distance in meters (optional, for excluding nearby POIs) */
127
+ minDistanceMeters?: number;
128
+ }
129
+ /**
130
+ * Proximity filter configuration
131
+ */
132
+ interface ProximityFilter {
133
+ /** Maximum distance in meters */
134
+ maxDistanceMeters: number;
135
+ /** Minimum distance in meters (optional) */
136
+ minDistanceMeters?: number;
137
+ /** Only include POIs user is approaching */
138
+ approachingOnly?: boolean;
139
+ }
140
+ /**
141
+ * Sort configuration for batch operations
142
+ */
143
+ interface SortConfig {
144
+ /** Sort field */
145
+ by: 'distance' | 'eta' | 'relativeBearing';
146
+ /** Sort direction */
147
+ direction: 'asc' | 'desc';
148
+ }
149
+ /**
150
+ * Speed unit for conversion utilities
151
+ */
152
+ type SpeedUnit = 'mps' | 'kmh' | 'mph';
153
+
154
+ /**
155
+ * Earth's mean radius in meters (WGS84 approximation)
156
+ */
157
+ declare const EARTH_RADIUS_METERS = 6371000;
158
+ /**
159
+ * Threshold below which a user is considered stationary (m/s)
160
+ * Approximately 1.8 km/h or 1.1 mph
161
+ */
162
+ declare const STATIONARY_SPEED_THRESHOLD = 0.5;
163
+ /**
164
+ * Orientation angle thresholds (in degrees)
165
+ */
166
+ declare const ORIENTATION_THRESHOLDS: {
167
+ /** Threshold for "directly ahead" (+/- degrees from 0) */
168
+ readonly DIRECTLY_AHEAD: 10;
169
+ /** Threshold for "ahead" region (within +/- degrees from 0) */
170
+ readonly AHEAD: 45;
171
+ /** Threshold for "behind" region (beyond +/- degrees from 0) */
172
+ readonly BEHIND: 135;
173
+ /** Threshold for "directly behind" (+/- degrees from 180) */
174
+ readonly DIRECTLY_BEHIND: 170;
175
+ };
176
+ /**
177
+ * Compass orientation boundaries (in degrees, clockwise from North)
178
+ */
179
+ declare const COMPASS_BOUNDARIES: {
180
+ readonly NORTH_END: 22.5;
181
+ readonly NORTHEAST_END: 67.5;
182
+ readonly EAST_END: 112.5;
183
+ readonly SOUTHEAST_END: 157.5;
184
+ readonly SOUTH_END: 202.5;
185
+ readonly SOUTHWEST_END: 247.5;
186
+ readonly WEST_END: 292.5;
187
+ readonly NORTHWEST_END: 337.5;
188
+ };
189
+
190
+ /**
191
+ * Calculate the great-circle distance between two points using the Haversine formula.
192
+ * This is the shortest distance over the earth's surface.
193
+ *
194
+ * @param from - Starting coordinates
195
+ * @param to - Ending coordinates
196
+ * @returns Distance in meters
197
+ *
198
+ * @example
199
+ * const distance = getDistance(
200
+ * { latitude: 37.7749, longitude: -122.4194 }, // San Francisco
201
+ * { latitude: 34.0522, longitude: -118.2437 } // Los Angeles
202
+ * );
203
+ * // Returns: approximately 559120 meters (~559 km)
204
+ */
205
+ declare function getDistance(from: Coordinates, to: Coordinates): number;
206
+ /**
207
+ * Calculate distance in kilometers
208
+ *
209
+ * @param from - Starting coordinates
210
+ * @param to - Ending coordinates
211
+ * @returns Distance in kilometers
212
+ */
213
+ declare function getDistanceKm(from: Coordinates, to: Coordinates): number;
214
+
215
+ /**
216
+ * Calculate the initial bearing (forward azimuth) from one point to another.
217
+ * Uses the spherical law of sines/cosines for accurate bearing calculation.
218
+ *
219
+ * @param from - Starting coordinates
220
+ * @param to - Ending coordinates
221
+ * @returns Bearing in degrees (0-360, where 0 = North, 90 = East)
222
+ *
223
+ * @example
224
+ * const bearing = getBearing(
225
+ * { latitude: 37.7749, longitude: -122.4194 }, // San Francisco
226
+ * { latitude: 34.0522, longitude: -118.2437 } // Los Angeles
227
+ * );
228
+ * // Returns: approximately 136 (southeast)
229
+ */
230
+ declare function getBearing(from: Coordinates, to: Coordinates): number;
231
+ /**
232
+ * Calculate the relative bearing from user's heading to a target.
233
+ * Positive values indicate target is to the right, negative to the left.
234
+ *
235
+ * @param userBearing - User's current heading (0-360)
236
+ * @param targetBearing - Absolute bearing to target (0-360)
237
+ * @returns Relative bearing (-180 to 180, positive = right, negative = left)
238
+ *
239
+ * @example
240
+ * // User heading north (0), target is to the east (90)
241
+ * getRelativeBearing(0, 90); // Returns: 90 (target is to the right)
242
+ *
243
+ * // User heading east (90), target is to the north (0)
244
+ * getRelativeBearing(90, 0); // Returns: -90 (target is to the left)
245
+ *
246
+ * // User heading south (180), target is to the north (0)
247
+ * getRelativeBearing(180, 0); // Returns: 180 or -180 (target is behind)
248
+ */
249
+ declare function getRelativeBearing(userBearing: number, targetBearing: number): number;
250
+ /**
251
+ * Calculate the final bearing (reverse azimuth) at the destination point.
252
+ * This is the direction you'd be facing when arriving at the destination.
253
+ *
254
+ * @param from - Starting coordinates
255
+ * @param to - Ending coordinates
256
+ * @returns Final bearing in degrees (0-360)
257
+ */
258
+ declare function getFinalBearing(from: Coordinates, to: Coordinates): number;
259
+
260
+ /**
261
+ * Get simple 4-way orientation from relative bearing
262
+ *
263
+ * @param relativeBearing - Relative bearing (-180 to 180)
264
+ * @returns Simple orientation: 'ahead', 'behind', 'left', or 'right'
265
+ *
266
+ * @example
267
+ * getSimpleOrientation(0); // 'ahead'
268
+ * getSimpleOrientation(45); // 'ahead' (within 45 degrees)
269
+ * getSimpleOrientation(90); // 'right'
270
+ * getSimpleOrientation(-90); // 'left'
271
+ * getSimpleOrientation(180); // 'behind'
272
+ */
273
+ declare function getSimpleOrientation(relativeBearing: number): SimpleOrientation;
274
+ /**
275
+ * Get compass 8-way orientation from absolute bearing
276
+ *
277
+ * @param absoluteBearing - Absolute bearing (0-360, 0 = North)
278
+ * @returns Compass orientation: 'north', 'northeast', 'east', etc.
279
+ *
280
+ * @example
281
+ * getCompassOrientation(0); // 'north'
282
+ * getCompassOrientation(45); // 'northeast'
283
+ * getCompassOrientation(90); // 'east'
284
+ * getCompassOrientation(180); // 'south'
285
+ */
286
+ declare function getCompassOrientation(absoluteBearing: number): CompassOrientation;
287
+ /**
288
+ * Get detailed 8-way orientation with nuance from relative bearing
289
+ *
290
+ * @param relativeBearing - Relative bearing (-180 to 180)
291
+ * @returns Detailed orientation with directional nuance
292
+ *
293
+ * @example
294
+ * getDetailedOrientation(0); // 'directly_ahead'
295
+ * getDetailedOrientation(5); // 'directly_ahead' (within 10 degrees)
296
+ * getDetailedOrientation(30); // 'ahead_right'
297
+ * getDetailedOrientation(90); // 'right'
298
+ * getDetailedOrientation(150); // 'behind_right'
299
+ * getDetailedOrientation(175); // 'directly_behind'
300
+ */
301
+ declare function getDetailedOrientation(relativeBearing: number): DetailedOrientation;
302
+ /**
303
+ * Get human-readable description of orientation
304
+ *
305
+ * @param orientation - Any orientation type
306
+ * @returns Human-readable string
307
+ */
308
+ declare function getOrientationDescription(orientation: SimpleOrientation | CompassOrientation | DetailedOrientation): string;
309
+
310
+ /**
311
+ * Calculate the closest point on a POI's boundary to the user.
312
+ * For POIs with radius (large areas like parks), finds the edge point.
313
+ * For point POIs (no radius), returns the POI coordinates.
314
+ *
315
+ * @param user - User's coordinates
316
+ * @param poi - POI with optional radius
317
+ * @returns Closest point result with distance and bearing
318
+ *
319
+ * @example
320
+ * const closest = getClosestPoint(
321
+ * { latitude: 37.7749, longitude: -122.4194 },
322
+ * { latitude: 37.7700, longitude: -122.4200, radiusMeters: 500, name: 'Large Park' }
323
+ * );
324
+ */
325
+ declare function getClosestPoint(user: Coordinates, poi: POI): ClosestPointResult;
326
+ /**
327
+ * Calculate destination point given start, bearing, and distance.
328
+ * Uses the direct geodesic formula (inverse Haversine).
329
+ *
330
+ * @param start - Starting coordinates
331
+ * @param bearing - Bearing in degrees (0-360)
332
+ * @param distanceMeters - Distance in meters
333
+ * @returns Destination coordinates
334
+ *
335
+ * @example
336
+ * // Starting from San Francisco, travel 10km northeast
337
+ * const dest = destinationPoint(
338
+ * { latitude: 37.7749, longitude: -122.4194 },
339
+ * 45, // northeast bearing
340
+ * 10000 // 10 km
341
+ * );
342
+ */
343
+ declare function destinationPoint(start: Coordinates, bearing: number, distanceMeters: number): Coordinates;
344
+ /**
345
+ * Calculate the distance to the edge of a POI (considering its radius)
346
+ *
347
+ * @param user - User's coordinates
348
+ * @param poi - POI with optional radius
349
+ * @returns Distance to edge in meters (0 if inside, negative values not returned)
350
+ */
351
+ declare function getDistanceToEdge(user: Coordinates, poi: POI): number;
352
+ /**
353
+ * Check if a point is within a POI's boundary
354
+ *
355
+ * @param point - Coordinates to check
356
+ * @param poi - POI with optional radius
357
+ * @returns True if point is within the POI boundary
358
+ */
359
+ declare function isWithinPOI(point: Coordinates, poi: POI): boolean;
360
+
361
+ /**
362
+ * Calculate estimated time of arrival to a POI.
363
+ * Considers user's speed, bearing relative to POI, and POI radius.
364
+ *
365
+ * @param user - User position with speed data
366
+ * @param poi - Target POI
367
+ * @param relativePosition - Pre-calculated relative position (optional, for efficiency)
368
+ * @returns ETA result with validity check
369
+ *
370
+ * @example
371
+ * const eta = getETA(
372
+ * { latitude: 37.7749, longitude: -122.4194, bearing: 45, speedMps: 13.4 }, // ~30 mph
373
+ * { latitude: 37.7849, longitude: -122.4094, radiusMeters: 100 }
374
+ * );
375
+ * // Returns: { etaSeconds: 120, formatted: "2 min", isValid: true }
376
+ */
377
+ declare function getETA(user: UserPosition, poi: POI, relativePosition?: Partial<RelativePosition>): ETAResult;
378
+ /**
379
+ * Calculate simple ETA without considering approach angle
380
+ * Useful when user bearing is unknown or irrelevant
381
+ *
382
+ * @param distanceMeters - Distance to target in meters
383
+ * @param speedMps - Speed in meters per second
384
+ * @returns ETA in seconds, or Infinity if invalid
385
+ */
386
+ declare function getSimpleETA(distanceMeters: number, speedMps: number): number;
387
+
388
+ /**
389
+ * Calculate complete relative position between user and POI.
390
+ * This is the primary function combining distance, bearing, and orientation.
391
+ *
392
+ * @param user - User's current position with optional bearing and speed
393
+ * @param poi - Target POI with optional radius
394
+ * @returns Complete relative position data
395
+ */
396
+ declare function getRelativePosition(user: UserPosition, poi: POI): RelativePosition;
397
+
398
+ /**
399
+ * Calculate relative positions for multiple POIs and sort them.
400
+ * Efficient batch operation that calculates positions once and sorts.
401
+ *
402
+ * @param user - User position
403
+ * @param pois - Array of POIs
404
+ * @param config - Sort configuration (default: sort by distance ascending)
405
+ * @returns Sorted array of POIs with relative positions
406
+ *
407
+ * @example
408
+ * const sorted = sortByDistance(user, allPOIs);
409
+ * // Returns POIs sorted by distance, nearest first
410
+ *
411
+ * @example
412
+ * const sorted = sortByDistance(user, allPOIs, { by: 'eta', direction: 'asc' });
413
+ * // Returns POIs sorted by estimated arrival time
414
+ */
415
+ declare function sortByDistance(user: UserPosition, pois: POI[], config?: SortConfig): POIWithRelativePosition[];
416
+ /**
417
+ * Get the N nearest POIs to the user
418
+ *
419
+ * @param user - User position
420
+ * @param pois - Array of POIs
421
+ * @param count - Number of POIs to return
422
+ * @returns Array of nearest POIs with relative positions
423
+ */
424
+ declare function getNearestPOIs(user: UserPosition, pois: POI[], count: number): POIWithRelativePosition[];
425
+ /**
426
+ * Get the POIs with shortest ETA
427
+ *
428
+ * @param user - User position (must include speedMps)
429
+ * @param pois - Array of POIs
430
+ * @param count - Number of POIs to return
431
+ * @returns Array of POIs with shortest ETA
432
+ */
433
+ declare function getNextArrivals(user: UserPosition, pois: POI[], count: number): POIWithRelativePosition[];
434
+
435
+ /**
436
+ * Filter POIs by proximity and optionally by approach status.
437
+ *
438
+ * @param user - User position
439
+ * @param pois - Array of POIs
440
+ * @param filter - Proximity filter configuration
441
+ * @returns Filtered array of POIs with relative positions, sorted by distance
442
+ *
443
+ * @example
444
+ * // Get all POIs within 1km that user is approaching
445
+ * const nearby = filterByProximity(user, allPOIs, {
446
+ * maxDistanceMeters: 1000,
447
+ * approachingOnly: true
448
+ * });
449
+ */
450
+ declare function filterByProximity(user: UserPosition, pois: POI[], filter: ProximityFilter): POIWithRelativePosition[];
451
+ /**
452
+ * Filter POIs within a directional cone (for route-ahead queries).
453
+ * Useful for finding POIs along user's path of travel.
454
+ *
455
+ * @param user - User position with bearing
456
+ * @param pois - Array of POIs
457
+ * @param cone - Cone filter configuration
458
+ * @returns Filtered array of POIs within the cone, sorted by distance
459
+ *
460
+ * @example
461
+ * // Get POIs ahead within 30 degrees of heading, up to 5km
462
+ * const upcoming = filterByCone(user, allPOIs, {
463
+ * centerAngle: user.bearing,
464
+ * halfAngle: 30,
465
+ * maxDistanceMeters: 5000
466
+ * });
467
+ */
468
+ declare function filterByCone(user: UserPosition, pois: POI[], cone: ConeFilter): POIWithRelativePosition[];
469
+ /**
470
+ * Filter POIs that the user is currently inside of (based on POI radius)
471
+ *
472
+ * @param user - User position
473
+ * @param pois - Array of POIs (should have radiusMeters set)
474
+ * @returns Array of POIs the user is currently within
475
+ */
476
+ declare function filterInsidePOIs(user: UserPosition, pois: POI[]): POIWithRelativePosition[];
477
+ /**
478
+ * Filter POIs by orientation (e.g., only POIs ahead or to the left)
479
+ *
480
+ * @param user - User position with bearing
481
+ * @param pois - Array of POIs
482
+ * @param orientations - Array of orientations to include
483
+ * @returns Filtered array of POIs
484
+ */
485
+ declare function filterByOrientation(user: UserPosition, pois: POI[], orientations: Array<'ahead' | 'behind' | 'left' | 'right'>): POIWithRelativePosition[];
486
+
487
+ /**
488
+ * Convert degrees to radians
489
+ * @param degrees - Angle in degrees
490
+ * @returns Angle in radians
491
+ */
492
+ declare function toRadians(degrees: number): number;
493
+ /**
494
+ * Convert radians to degrees
495
+ * @param radians - Angle in radians
496
+ * @returns Angle in degrees
497
+ */
498
+ declare function toDegrees(radians: number): number;
499
+ /**
500
+ * Normalize angle to 0-360 range
501
+ * @param degrees - Angle in degrees (can be any value)
502
+ * @returns Normalized angle between 0 and 360
503
+ */
504
+ declare function normalizeAngle(degrees: number): number;
505
+ /**
506
+ * Normalize longitude to -180 to 180 range
507
+ * Handles international date line wraparound
508
+ * @param longitude - Longitude in degrees
509
+ * @returns Normalized longitude between -180 and 180
510
+ */
511
+ declare function normalizeLongitude(longitude: number): number;
512
+ /**
513
+ * Clamp a value between min and max
514
+ * @param value - Value to clamp
515
+ * @param min - Minimum value
516
+ * @param max - Maximum value
517
+ * @returns Clamped value
518
+ */
519
+ declare function clamp(value: number, min: number, max: number): number;
520
+ /**
521
+ * Round a number to specified decimal places
522
+ * @param value - Value to round
523
+ * @param decimals - Number of decimal places
524
+ * @returns Rounded value
525
+ */
526
+ declare function roundTo(value: number, decimals: number): number;
527
+
528
+ /**
529
+ * Format duration in seconds to human-readable string
530
+ * @param seconds - Duration in seconds
531
+ * @returns Formatted string (e.g., "2 min 30 sec", "1 hr 15 min")
532
+ */
533
+ declare function formatDuration(seconds: number): string;
534
+ /**
535
+ * Format duration in seconds to short human-readable string
536
+ * @param seconds - Duration in seconds
537
+ * @returns Short formatted string (e.g., "2m", "1h 15m")
538
+ */
539
+ declare function formatDurationShort(seconds: number): string;
540
+ /**
541
+ * Format distance in meters to human-readable string
542
+ * @param meters - Distance in meters
543
+ * @returns Formatted string (e.g., "500 m", "2.5 km")
544
+ */
545
+ declare function formatDistance(meters: number): string;
546
+
547
+ /**
548
+ * Check if coordinates are valid
549
+ * @param coords - Coordinates to validate
550
+ * @returns True if coordinates are valid
551
+ */
552
+ declare function isValidCoordinates(coords: Coordinates): boolean;
553
+ /**
554
+ * Check if a bearing value is valid
555
+ * @param bearing - Bearing in degrees
556
+ * @returns True if bearing is valid (0-360 or undefined)
557
+ */
558
+ declare function isValidBearing(bearing: number | undefined): boolean;
559
+ /**
560
+ * Check if a speed value is valid
561
+ * @param speed - Speed in meters per second
562
+ * @returns True if speed is valid (non-negative or undefined)
563
+ */
564
+ declare function isValidSpeed(speed: number | undefined): boolean;
565
+ /**
566
+ * Check if a radius value is valid
567
+ * @param radius - Radius in meters
568
+ * @returns True if radius is valid (non-negative or undefined)
569
+ */
570
+ declare function isValidRadius(radius: number | undefined): boolean;
571
+ /**
572
+ * Validate a UserPosition object
573
+ * @param user - User position to validate
574
+ * @returns Object with isValid flag and optional error message
575
+ */
576
+ declare function validateUserPosition(user: UserPosition): {
577
+ isValid: boolean;
578
+ error?: string;
579
+ };
580
+ /**
581
+ * Validate a POI object
582
+ * @param poi - POI to validate
583
+ * @returns Object with isValid flag and optional error message
584
+ */
585
+ declare function validatePOI(poi: POI): {
586
+ isValid: boolean;
587
+ error?: string;
588
+ };
589
+
590
+ /**
591
+ * Convert speed between units
592
+ *
593
+ * @param value - Speed value to convert
594
+ * @param from - Source unit
595
+ * @param to - Target unit
596
+ * @returns Converted speed value
597
+ *
598
+ * @example
599
+ * convertSpeed(60, 'kmh', 'mps'); // Returns: 16.67 (approx)
600
+ * convertSpeed(10, 'mps', 'mph'); // Returns: 22.37 (approx)
601
+ */
602
+ declare function convertSpeed(value: number, from: 'mps' | 'kmh' | 'mph', to: 'mps' | 'kmh' | 'mph'): number;
603
+
604
+ export { type ApproachStatus, COMPASS_BOUNDARIES, type ClosestPointResult, type CompassOrientation, type ConeFilter, type Coordinates, type DetailedOrientation, EARTH_RADIUS_METERS, type ETAResult, ORIENTATION_THRESHOLDS, type POI, type POIWithRelativePosition, type ProximityFilter, type RelativePosition, STATIONARY_SPEED_THRESHOLD, type SimpleOrientation, type SortConfig, type SpeedUnit, type UserPosition, clamp, convertSpeed, destinationPoint, filterByCone, filterByOrientation, filterByProximity, filterInsidePOIs, formatDistance, formatDuration, formatDurationShort, getBearing, getClosestPoint, getCompassOrientation, getDetailedOrientation, getDistance, getDistanceKm, getDistanceToEdge, getETA, getFinalBearing, getNearestPOIs, getNextArrivals, getOrientationDescription, getRelativeBearing, getRelativePosition, getSimpleETA, getSimpleOrientation, isValidBearing, isValidCoordinates, isValidRadius, isValidSpeed, isWithinPOI, normalizeAngle, normalizeLongitude, roundTo, sortByDistance, toDegrees, toRadians, validatePOI, validateUserPosition };