@@ -63,6 +63,15 @@ type VenueType =
6363 | 'pub'
6464 | 'playground'
6565 | 'community_centre'
66+ | 'bar'
67+ | 'fast_food'
68+ | 'garden'
69+ | 'theatre'
70+ | 'arts_centre'
71+ | 'fitness_centre'
72+ | 'sports_centre'
73+ | 'escape_game'
74+ | 'swimming_pool'
6675 | string
6776
6877/** Result of an isochrone computation. */
@@ -97,6 +106,43 @@ interface Venue {
97106 osmId?: string // e.g. 'node/123456'
98107}
99108
109+ /** GeoJSON LineString geometry. */
110+ interface GeoJSONLineString {
111+ type: 'LineString'
112+ coordinates: number[][]
113+ }
114+
115+ /** A single manoeuvre in a route. */
116+ interface RouteLeg {
117+ instruction: string
118+ distanceKm: number
119+ durationMinutes: number
120+ type?: number // Valhalla manoeuvre type (0-38)
121+ streetNames?: string[]
122+ beginStreetNames?: string[]
123+ verbalInstruction?: string
124+ toll?: boolean
125+ highway?: boolean
126+ ferry?: boolean
127+ rough?: boolean
128+ gate?: boolean
129+ bearingBefore?: number
130+ bearingAfter?: number
131+ beginShapeIndex?: number
132+ endShapeIndex?: number
133+ }
134+
135+ /** Result of a single route computation. */
136+ interface RouteGeometry {
137+ origin: LatLon
138+ destination: LatLon
139+ mode: TransportMode
140+ durationMinutes: number
141+ distanceKm: number
142+ geometry: GeoJSONLineString
143+ legs?: RouteLeg[]
144+ }
145+
100146/** Options for rendezvous calculation. */
101147interface RendezvousOptions {
102148 participants: LatLon[] // at least 2 required
@@ -105,20 +151,23 @@ interface RendezvousOptions {
105151 venueTypes: VenueType[]
106152 fairness?: FairnessStrategy // default: 'min_max'
107153 limit?: number // max suggestions to return, default: 5
154+ strategy?: 'auto' | 'hull' | 'isochrone' // pipeline strategy, default: 'auto'
108155}
109156
110157/** A ranked rendezvous suggestion. */
111158interface RendezvousSuggestion {
112159 venue: Venue
113160 travelTimes: Record<string, number> // keyed by participant label or 'participant_N'
114161 fairnessScore: number // lower is better
162+ metadata?: { strategy: 'hull' | 'isochrone' } // which pipeline was used
115163}
116164
117165/** Engine-agnostic routing interface. Implement this to add a custom engine. */
118166interface RoutingEngine {
119167 readonly name: string
120168 computeIsochrone(origin: LatLon, mode: TransportMode, timeMinutes: number): Promise<Isochrone>
121169 computeRouteMatrix(origins: LatLon[], destinations: LatLon[], mode: TransportMode): Promise<RouteMatrix>
170+ computeRoute(origin: LatLon, destination: LatLon, mode: TransportMode): Promise<RouteGeometry>
122171}
123172
124173/** Bounding box (from rendezvous-kit/geo). */
@@ -413,6 +462,15 @@ Built-in `VenueType` to Overpass tag mapping:
413462| `pub` | `amenity=pub` |
414463| `playground` | `leisure=playground` |
415464| `community_centre` | `amenity=community_centre` |
465+ | `bar` | `amenity=bar` |
466+ | `fast_food` | `amenity=fast_food` |
467+ | `garden` | `leisure=garden` |
468+ | `theatre` | `amenity=theatre` |
469+ | `arts_centre` | `amenity=arts_centre` |
470+ | `fitness_centre` | `leisure=fitness_centre` |
471+ | `sports_centre` | `leisure=sports_centre` |
472+ | `escape_game` | `leisure=escape_game` |
473+ | `swimming_pool` | `leisure=swimming_pool` |
416474
417475Unknown strings are passed through as `amenity=<value>`.
418476
@@ -421,7 +479,7 @@ Unknown strings are passed through as `amenity=<value>`.
421479## Implementing a Custom Engine
422480
423481```typescript
424- import type { RoutingEngine, LatLon, TransportMode, Isochrone, RouteMatrix } from 'rendezvous-kit'
482+ import type { RoutingEngine, LatLon, TransportMode, Isochrone, RouteMatrix, RouteGeometry } from 'rendezvous-kit'
425483
426484class MyRoutingEngine implements RoutingEngine {
427485 readonly name = 'MyEngine'
@@ -454,6 +512,27 @@ class MyRoutingEngine implements RoutingEngine {
454512 }
455513 return { origins, destinations, entries }
456514 }
515+
516+ async computeRoute(
517+ origin: LatLon,
518+ destination: LatLon,
519+ mode: TransportMode,
520+ ): Promise<RouteGeometry> {
521+ const raw = await myApi.getRoute(origin, destination, mode)
522+ return {
523+ origin,
524+ destination,
525+ mode,
526+ durationMinutes: raw.seconds / 60,
527+ distanceKm: raw.metres / 1000,
528+ geometry: { type: 'LineString', coordinates: raw.polyline },
529+ legs: raw.steps.map((s: any) => ({
530+ instruction: s.text,
531+ distanceKm: s.metres / 1000,
532+ durationMinutes: s.seconds / 60,
533+ })),
534+ }
535+ }
457536}
458537
459538// Use it with findRendezvous
@@ -464,12 +543,12 @@ const suggestions = await findRendezvous(new MyRoutingEngine(), options)
464543
465544## Engine Comparison
466545
467- | Engine | Isochrone | Matrix | Auth | Notes |
468- |--------|:---------:|:------:|------|-------|
469- | Valhalla | Yes | Yes | None | Best self-hosted option; supports public transit |
470- | OpenRouteService | Yes | Yes | API key | Free tier available; no public transit |
471- | GraphHopper | Yes | Yes | Optional | API key only for cloud; optional self-hosted |
472- | OSRM | No | Yes | None | Fastest matrix; no isochrone support |
546+ | Engine | Isochrone | Matrix | Route | Auth | Notes |
547+ |--------|:---------:|:------:|:-----:| ------|-------|
548+ | Valhalla | Yes | Yes | Yes | None | Best self-hosted option; supports public transit |
549+ | OpenRouteService | Yes | Yes | No | API key | Free tier available; no public transit |
550+ | GraphHopper | Yes | Yes | No | Optional | API key only for cloud; optional self-hosted |
551+ | OSRM | No | Yes | No | None | Fastest matrix; no isochrone support |
473552
474553---
475554
0 commit comments