rendezvous-kit 0.0.0-development
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/LICENSE +21 -0
- package/README.md +184 -0
- package/dist/engines/graphhopper.d.ts +14 -0
- package/dist/engines/graphhopper.d.ts.map +1 -0
- package/dist/engines/graphhopper.js +72 -0
- package/dist/engines/graphhopper.js.map +1 -0
- package/dist/engines/openrouteservice.d.ts +14 -0
- package/dist/engines/openrouteservice.d.ts.map +1 -0
- package/dist/engines/openrouteservice.js +79 -0
- package/dist/engines/openrouteservice.js.map +1 -0
- package/dist/engines/osrm.d.ts +11 -0
- package/dist/engines/osrm.d.ts.map +1 -0
- package/dist/engines/osrm.js +48 -0
- package/dist/engines/osrm.js.map +1 -0
- package/dist/engines/valhalla.d.ts +11 -0
- package/dist/engines/valhalla.d.ts.map +1 -0
- package/dist/engines/valhalla.js +72 -0
- package/dist/engines/valhalla.js.map +1 -0
- package/dist/geo.d.ts +16 -0
- package/dist/geo.d.ts.map +1 -0
- package/dist/geo.js +142 -0
- package/dist/geo.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/rendezvous.d.ts +14 -0
- package/dist/rendezvous.d.ts.map +1 -0
- package/dist/rendezvous.js +72 -0
- package/dist/rendezvous.js.map +1 -0
- package/dist/types.d.ts +73 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/venues.d.ts +7 -0
- package/dist/venues.d.ts.map +1 -0
- package/dist/venues.js +74 -0
- package/dist/venues.js.map +1 -0
- package/llms-full.txt +481 -0
- package/llms.txt +86 -0
- package/package.json +76 -0
package/dist/geo.js
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
export function boundingBox(polygon) {
|
|
2
|
+
const ring = polygon.coordinates[0];
|
|
3
|
+
if (!ring || ring.length === 0) {
|
|
4
|
+
return { minLon: 0, minLat: 0, maxLon: 0, maxLat: 0 };
|
|
5
|
+
}
|
|
6
|
+
let minLon = Infinity, minLat = Infinity;
|
|
7
|
+
let maxLon = -Infinity, maxLat = -Infinity;
|
|
8
|
+
for (const [lon, lat] of ring) {
|
|
9
|
+
if (lon < minLon)
|
|
10
|
+
minLon = lon;
|
|
11
|
+
if (lon > maxLon)
|
|
12
|
+
maxLon = lon;
|
|
13
|
+
if (lat < minLat)
|
|
14
|
+
minLat = lat;
|
|
15
|
+
if (lat > maxLat)
|
|
16
|
+
maxLat = lat;
|
|
17
|
+
}
|
|
18
|
+
return { minLon, minLat, maxLon, maxLat };
|
|
19
|
+
}
|
|
20
|
+
export function centroid(polygon) {
|
|
21
|
+
const ring = polygon.coordinates[0];
|
|
22
|
+
if (!ring || ring.length < 2)
|
|
23
|
+
return { lat: 0, lon: 0 };
|
|
24
|
+
const n = ring.length - 1;
|
|
25
|
+
let sumLon = 0, sumLat = 0;
|
|
26
|
+
for (let i = 0; i < n; i++) {
|
|
27
|
+
sumLon += ring[i][0];
|
|
28
|
+
sumLat += ring[i][1];
|
|
29
|
+
}
|
|
30
|
+
return { lon: sumLon / n, lat: sumLat / n };
|
|
31
|
+
}
|
|
32
|
+
export function polygonArea(polygon) {
|
|
33
|
+
const ring = polygon.coordinates[0];
|
|
34
|
+
if (!ring || ring.length < 4)
|
|
35
|
+
return 0;
|
|
36
|
+
const c = centroid(polygon);
|
|
37
|
+
const cosLat = Math.cos((c.lat * Math.PI) / 180);
|
|
38
|
+
const mPerDegLat = 111_320;
|
|
39
|
+
const mPerDegLon = 111_320 * cosLat;
|
|
40
|
+
let area = 0;
|
|
41
|
+
const n = ring.length - 1;
|
|
42
|
+
for (let i = 0; i < n; i++) {
|
|
43
|
+
const j = (i + 1) % n;
|
|
44
|
+
const xi = ring[i][0] * mPerDegLon, yi = ring[i][1] * mPerDegLat;
|
|
45
|
+
const xj = ring[j][0] * mPerDegLon, yj = ring[j][1] * mPerDegLat;
|
|
46
|
+
area += xi * yj - xj * yi;
|
|
47
|
+
}
|
|
48
|
+
return Math.abs(area) / 2;
|
|
49
|
+
}
|
|
50
|
+
export function intersectPolygons(polygons) {
|
|
51
|
+
if (polygons.length === 0)
|
|
52
|
+
return null;
|
|
53
|
+
if (polygons.length === 1)
|
|
54
|
+
return polygons[0];
|
|
55
|
+
let current = polygonToRing(polygons[0]);
|
|
56
|
+
if (current.length === 0)
|
|
57
|
+
return null;
|
|
58
|
+
for (let i = 1; i < polygons.length; i++) {
|
|
59
|
+
const clip = polygonToRing(polygons[i]);
|
|
60
|
+
if (clip.length === 0)
|
|
61
|
+
return null;
|
|
62
|
+
if (!bboxOverlap(ringBBox(current), ringBBox(clip)))
|
|
63
|
+
return null;
|
|
64
|
+
current = sutherlandHodgman(current, clip);
|
|
65
|
+
if (current.length === 0)
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
return ringToPolygon(current);
|
|
69
|
+
}
|
|
70
|
+
function polygonToRing(p) {
|
|
71
|
+
const ring = p.coordinates[0];
|
|
72
|
+
if (!ring || ring.length < 4)
|
|
73
|
+
return [];
|
|
74
|
+
return ring.slice(0, -1);
|
|
75
|
+
}
|
|
76
|
+
function ringToPolygon(ring) {
|
|
77
|
+
const closed = [...ring, ring[0]];
|
|
78
|
+
return { type: 'Polygon', coordinates: [closed] };
|
|
79
|
+
}
|
|
80
|
+
function ringBBox(ring) {
|
|
81
|
+
let minLon = Infinity, minLat = Infinity;
|
|
82
|
+
let maxLon = -Infinity, maxLat = -Infinity;
|
|
83
|
+
for (const [lon, lat] of ring) {
|
|
84
|
+
if (lon < minLon)
|
|
85
|
+
minLon = lon;
|
|
86
|
+
if (lon > maxLon)
|
|
87
|
+
maxLon = lon;
|
|
88
|
+
if (lat < minLat)
|
|
89
|
+
minLat = lat;
|
|
90
|
+
if (lat > maxLat)
|
|
91
|
+
maxLat = lat;
|
|
92
|
+
}
|
|
93
|
+
return { minLon, minLat, maxLon, maxLat };
|
|
94
|
+
}
|
|
95
|
+
function bboxOverlap(a, b) {
|
|
96
|
+
return a.minLon <= b.maxLon && a.maxLon >= b.minLon &&
|
|
97
|
+
a.minLat <= b.maxLat && a.maxLat >= b.minLat;
|
|
98
|
+
}
|
|
99
|
+
function sutherlandHodgman(subject, clip) {
|
|
100
|
+
let output = subject;
|
|
101
|
+
for (let i = 0; i < clip.length; i++) {
|
|
102
|
+
if (output.length === 0)
|
|
103
|
+
return [];
|
|
104
|
+
const input = output;
|
|
105
|
+
output = [];
|
|
106
|
+
const edgeStart = clip[i];
|
|
107
|
+
const edgeEnd = clip[(i + 1) % clip.length];
|
|
108
|
+
for (let j = 0; j < input.length; j++) {
|
|
109
|
+
const current = input[j];
|
|
110
|
+
const previous = input[(j + input.length - 1) % input.length];
|
|
111
|
+
const currInside = isLeft(edgeStart, edgeEnd, current);
|
|
112
|
+
const prevInside = isLeft(edgeStart, edgeEnd, previous);
|
|
113
|
+
if (currInside) {
|
|
114
|
+
if (!prevInside) {
|
|
115
|
+
const inter = lineIntersection(previous, current, edgeStart, edgeEnd);
|
|
116
|
+
if (inter)
|
|
117
|
+
output.push(inter);
|
|
118
|
+
}
|
|
119
|
+
output.push(current);
|
|
120
|
+
}
|
|
121
|
+
else if (prevInside) {
|
|
122
|
+
const inter = lineIntersection(previous, current, edgeStart, edgeEnd);
|
|
123
|
+
if (inter)
|
|
124
|
+
output.push(inter);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return output;
|
|
129
|
+
}
|
|
130
|
+
function isLeft(a, b, p) {
|
|
131
|
+
return (b[0] - a[0]) * (p[1] - a[1]) - (b[1] - a[1]) * (p[0] - a[0]) >= 0;
|
|
132
|
+
}
|
|
133
|
+
function lineIntersection(a1, a2, b1, b2) {
|
|
134
|
+
const dx1 = a2[0] - a1[0], dy1 = a2[1] - a1[1];
|
|
135
|
+
const dx2 = b2[0] - b1[0], dy2 = b2[1] - b1[1];
|
|
136
|
+
const denom = dx1 * dy2 - dy1 * dx2;
|
|
137
|
+
if (Math.abs(denom) < 1e-12)
|
|
138
|
+
return null;
|
|
139
|
+
const t = ((b1[0] - a1[0]) * dy2 - (b1[1] - a1[1]) * dx2) / denom;
|
|
140
|
+
return [a1[0] + t * dx1, a1[1] + t * dy1];
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=geo.js.map
|
package/dist/geo.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geo.js","sourceRoot":"","sources":["../src/geo.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type { LatLon, GeoJSONPolygon, TransportMode, FairnessStrategy, VenueType, RoutingEngine, Isochrone, MatrixEntry, RouteMatrix, Venue, RendezvousOptions, RendezvousSuggestion, } from './types.js';
|
|
2
|
+
export { intersectPolygons, boundingBox, centroid, polygonArea, } from './geo.js';
|
|
3
|
+
export type { BBox, Coordinate } from './geo.js';
|
|
4
|
+
export { OpenRouteServiceEngine } from './engines/openrouteservice.js';
|
|
5
|
+
export { ValhallaEngine } from './engines/valhalla.js';
|
|
6
|
+
export { GraphHopperEngine } from './engines/graphhopper.js';
|
|
7
|
+
export { OsrmEngine } from './engines/osrm.js';
|
|
8
|
+
export { searchVenues } from './venues.js';
|
|
9
|
+
export { findRendezvous } from './rendezvous.js';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,MAAM,EACN,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,SAAS,EACT,aAAa,EACb,SAAS,EACT,WAAW,EACX,WAAW,EACX,KAAK,EACL,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,YAAY,CAAA;AAGnB,OAAO,EACL,iBAAiB,EACjB,WAAW,EACX,QAAQ,EACR,WAAW,GACZ,MAAM,UAAU,CAAA;AACjB,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAGhD,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAG9C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAG1C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Geometry
|
|
2
|
+
export { intersectPolygons, boundingBox, centroid, polygonArea, } from './geo.js';
|
|
3
|
+
// Engines
|
|
4
|
+
export { OpenRouteServiceEngine } from './engines/openrouteservice.js';
|
|
5
|
+
export { ValhallaEngine } from './engines/valhalla.js';
|
|
6
|
+
export { GraphHopperEngine } from './engines/graphhopper.js';
|
|
7
|
+
export { OsrmEngine } from './engines/osrm.js';
|
|
8
|
+
// Venues
|
|
9
|
+
export { searchVenues } from './venues.js';
|
|
10
|
+
// Rendezvous
|
|
11
|
+
export { findRendezvous } from './rendezvous.js';
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAgBA,WAAW;AACX,OAAO,EACL,iBAAiB,EACjB,WAAW,EACX,QAAQ,EACR,WAAW,GACZ,MAAM,UAAU,CAAA;AAGjB,UAAU;AACV,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,SAAS;AACT,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE1C,aAAa;AACb,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { RoutingEngine, RendezvousOptions, RendezvousSuggestion } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Find optimal meeting points for N participants using isochrone intersection.
|
|
4
|
+
*
|
|
5
|
+
* Algorithm:
|
|
6
|
+
* 1. Compute isochrones for each participant
|
|
7
|
+
* 2. Intersect isochrone polygons
|
|
8
|
+
* 3. Search for venues within the intersection
|
|
9
|
+
* 4. Compute route matrix from all participants to all candidate venues
|
|
10
|
+
* 5. Score venues by fairness strategy
|
|
11
|
+
* 6. Return ranked suggestions
|
|
12
|
+
*/
|
|
13
|
+
export declare function findRendezvous(engine: RoutingEngine, options: RendezvousOptions): Promise<RendezvousSuggestion[]>;
|
|
14
|
+
//# sourceMappingURL=rendezvous.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rendezvous.d.ts","sourceRoot":"","sources":["../src/rendezvous.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,oBAAoB,EAAU,MAAM,YAAY,CAAA;AAIhG;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAyDjC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { searchVenues } from './venues.js';
|
|
2
|
+
import { intersectPolygons, centroid } from './geo.js';
|
|
3
|
+
/**
|
|
4
|
+
* Find optimal meeting points for N participants using isochrone intersection.
|
|
5
|
+
*
|
|
6
|
+
* Algorithm:
|
|
7
|
+
* 1. Compute isochrones for each participant
|
|
8
|
+
* 2. Intersect isochrone polygons
|
|
9
|
+
* 3. Search for venues within the intersection
|
|
10
|
+
* 4. Compute route matrix from all participants to all candidate venues
|
|
11
|
+
* 5. Score venues by fairness strategy
|
|
12
|
+
* 6. Return ranked suggestions
|
|
13
|
+
*/
|
|
14
|
+
export async function findRendezvous(engine, options) {
|
|
15
|
+
const { participants, mode, maxTimeMinutes, venueTypes, fairness = 'min_max', limit = 5 } = options;
|
|
16
|
+
if (participants.length < 2) {
|
|
17
|
+
throw new RangeError('findRendezvous requires at least 2 participants');
|
|
18
|
+
}
|
|
19
|
+
// Step 1: Compute isochrones for each participant
|
|
20
|
+
const isochrones = await Promise.all(participants.map(p => engine.computeIsochrone(p, mode, maxTimeMinutes)));
|
|
21
|
+
// Step 2: Intersect isochrone polygons
|
|
22
|
+
const intersection = intersectPolygons(isochrones.map(iso => iso.polygon));
|
|
23
|
+
if (!intersection) {
|
|
24
|
+
return []; // No overlap — participants are too far apart
|
|
25
|
+
}
|
|
26
|
+
// Step 3: Search for venues within the intersection
|
|
27
|
+
let venues = await searchVenues(intersection, venueTypes);
|
|
28
|
+
if (venues.length === 0) {
|
|
29
|
+
const c = centroid(intersection);
|
|
30
|
+
venues = [{
|
|
31
|
+
name: 'Meeting point',
|
|
32
|
+
lat: c.lat,
|
|
33
|
+
lon: c.lon,
|
|
34
|
+
venueType: 'centroid',
|
|
35
|
+
}];
|
|
36
|
+
}
|
|
37
|
+
// Step 4: Compute route matrix from participants to candidate venues
|
|
38
|
+
const venuePoints = venues.map(v => ({ lat: v.lat, lon: v.lon }));
|
|
39
|
+
const matrix = await engine.computeRouteMatrix(participants, venuePoints, mode);
|
|
40
|
+
// Step 5: Score venues
|
|
41
|
+
const suggestions = venues.map((venue, vi) => {
|
|
42
|
+
const travelTimes = {};
|
|
43
|
+
const times = [];
|
|
44
|
+
for (let pi = 0; pi < participants.length; pi++) {
|
|
45
|
+
const entry = matrix.entries.find(e => e.originIndex === pi && e.destinationIndex === vi);
|
|
46
|
+
const duration = entry?.durationMinutes ?? Infinity;
|
|
47
|
+
const label = participants[pi].label ?? `participant_${pi}`;
|
|
48
|
+
travelTimes[label] = Math.round(duration * 10) / 10;
|
|
49
|
+
times.push(duration);
|
|
50
|
+
}
|
|
51
|
+
const fairnessScore = computeFairnessScore(times, fairness);
|
|
52
|
+
return { venue, travelTimes, fairnessScore };
|
|
53
|
+
});
|
|
54
|
+
// Step 6: Sort by fairness score and return top N
|
|
55
|
+
suggestions.sort((a, b) => a.fairnessScore - b.fairnessScore);
|
|
56
|
+
return suggestions.slice(0, limit);
|
|
57
|
+
}
|
|
58
|
+
function computeFairnessScore(times, strategy) {
|
|
59
|
+
switch (strategy) {
|
|
60
|
+
case 'min_max':
|
|
61
|
+
return Math.max(...times);
|
|
62
|
+
case 'min_total':
|
|
63
|
+
return times.reduce((sum, t) => sum + t, 0);
|
|
64
|
+
case 'min_variance': {
|
|
65
|
+
const mean = times.reduce((sum, t) => sum + t, 0) / times.length;
|
|
66
|
+
return Math.sqrt(times.reduce((sum, t) => sum + (t - mean) ** 2, 0) / times.length);
|
|
67
|
+
}
|
|
68
|
+
default:
|
|
69
|
+
return Math.max(...times);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=rendezvous.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rendezvous.js","sourceRoot":"","sources":["../src/rendezvous.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/** Transport mode for routing calculations. */
|
|
2
|
+
export type TransportMode = 'drive' | 'cycle' | 'walk' | 'public_transit';
|
|
3
|
+
/** Fairness strategy for rendezvous scoring. */
|
|
4
|
+
export type FairnessStrategy = 'min_max' | 'min_total' | 'min_variance';
|
|
5
|
+
/** A point with coordinates and optional label. */
|
|
6
|
+
export interface LatLon {
|
|
7
|
+
lat: number;
|
|
8
|
+
lon: number;
|
|
9
|
+
label?: string;
|
|
10
|
+
}
|
|
11
|
+
/** GeoJSON Polygon geometry. */
|
|
12
|
+
export interface GeoJSONPolygon {
|
|
13
|
+
type: 'Polygon';
|
|
14
|
+
coordinates: number[][][];
|
|
15
|
+
}
|
|
16
|
+
/** Result of an isochrone computation. */
|
|
17
|
+
export interface Isochrone {
|
|
18
|
+
origin: LatLon;
|
|
19
|
+
mode: TransportMode;
|
|
20
|
+
timeMinutes: number;
|
|
21
|
+
polygon: GeoJSONPolygon;
|
|
22
|
+
}
|
|
23
|
+
/** A single cell in a route matrix. */
|
|
24
|
+
export interface MatrixEntry {
|
|
25
|
+
originIndex: number;
|
|
26
|
+
destinationIndex: number;
|
|
27
|
+
durationMinutes: number;
|
|
28
|
+
distanceKm: number;
|
|
29
|
+
}
|
|
30
|
+
/** Result of a route matrix computation. */
|
|
31
|
+
export interface RouteMatrix {
|
|
32
|
+
origins: LatLon[];
|
|
33
|
+
destinations: LatLon[];
|
|
34
|
+
entries: MatrixEntry[];
|
|
35
|
+
}
|
|
36
|
+
/** Venue type for filtering. */
|
|
37
|
+
export type VenueType = 'park' | 'cafe' | 'restaurant' | 'service_station' | 'library' | 'pub' | 'playground' | 'community_centre' | string;
|
|
38
|
+
/** A venue found within the rendezvous zone. */
|
|
39
|
+
export interface Venue {
|
|
40
|
+
name: string;
|
|
41
|
+
lat: number;
|
|
42
|
+
lon: number;
|
|
43
|
+
venueType: VenueType;
|
|
44
|
+
osmId?: string;
|
|
45
|
+
}
|
|
46
|
+
/** Options for rendezvous calculation. */
|
|
47
|
+
export interface RendezvousOptions {
|
|
48
|
+
participants: LatLon[];
|
|
49
|
+
mode: TransportMode;
|
|
50
|
+
maxTimeMinutes: number;
|
|
51
|
+
venueTypes: VenueType[];
|
|
52
|
+
fairness?: FairnessStrategy;
|
|
53
|
+
limit?: number;
|
|
54
|
+
}
|
|
55
|
+
/** A ranked rendezvous suggestion. */
|
|
56
|
+
export interface RendezvousSuggestion {
|
|
57
|
+
venue: Venue;
|
|
58
|
+
travelTimes: Record<string, number>;
|
|
59
|
+
fairnessScore: number;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Engine-agnostic routing interface.
|
|
63
|
+
* Implementations wrap specific routing APIs (Valhalla, OpenRouteService, etc.).
|
|
64
|
+
*/
|
|
65
|
+
export interface RoutingEngine {
|
|
66
|
+
/** Human-readable engine name (e.g., "OpenRouteService", "Valhalla"). */
|
|
67
|
+
readonly name: string;
|
|
68
|
+
/** Compute an isochrone polygon from an origin. */
|
|
69
|
+
computeIsochrone(origin: LatLon, mode: TransportMode, timeMinutes: number): Promise<Isochrone>;
|
|
70
|
+
/** Compute a travel time/distance matrix between origins and destinations. */
|
|
71
|
+
computeRouteMatrix(origins: LatLon[], destinations: LatLon[], mode: TransportMode): Promise<RouteMatrix>;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,gBAAgB,CAAA;AAEzE,gDAAgD;AAChD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,WAAW,GAAG,cAAc,CAAA;AAEvE,mDAAmD;AACnD,MAAM,WAAW,MAAM;IACrB,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,gCAAgC;AAChC,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,SAAS,CAAA;IACf,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,CAAA;CAC1B;AAED,0CAA0C;AAC1C,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,aAAa,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,cAAc,CAAA;CACxB;AAED,uCAAuC;AACvC,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAA;IACnB,gBAAgB,EAAE,MAAM,CAAA;IACxB,eAAe,EAAE,MAAM,CAAA;IACvB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,4CAA4C;AAC5C,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,OAAO,EAAE,WAAW,EAAE,CAAA;CACvB;AAED,gCAAgC;AAChC,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,YAAY,GAAG,iBAAiB,GAAG,SAAS,GAAG,KAAK,GAAG,YAAY,GAAG,kBAAkB,GAAG,MAAM,CAAA;AAE3I,gDAAgD;AAChD,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,SAAS,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,0CAA0C;AAC1C,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,IAAI,EAAE,aAAa,CAAA;IACnB,cAAc,EAAE,MAAM,CAAA;IACtB,UAAU,EAAE,SAAS,EAAE,CAAA;IACvB,QAAQ,CAAC,EAAE,gBAAgB,CAAA;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,sCAAsC;AACtC,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,KAAK,CAAA;IACZ,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,aAAa,EAAE,MAAM,CAAA;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,yEAAyE;IACzE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IAErB,mDAAmD;IACnD,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAA;IAE9F,8EAA8E;IAC9E,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;CACzG"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/dist/venues.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { GeoJSONPolygon, Venue, VenueType } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Search for venues within a polygon using the Overpass API.
|
|
4
|
+
* Uses the bounding box of the polygon for the query.
|
|
5
|
+
*/
|
|
6
|
+
export declare function searchVenues(polygon: GeoJSONPolygon, venueTypes: VenueType[], overpassUrl?: string): Promise<Venue[]>;
|
|
7
|
+
//# sourceMappingURL=venues.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"venues.d.ts","sourceRoot":"","sources":["../src/venues.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AA4BlE;;;GAGG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,SAAS,EAAE,EACvB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,KAAK,EAAE,CAAC,CA4ClB"}
|
package/dist/venues.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
const OVERPASS_URL = 'https://overpass-api.de/api/interpreter';
|
|
2
|
+
/** Map VenueType to Overpass tag queries. */
|
|
3
|
+
const VENUE_TAG_MAP = {
|
|
4
|
+
park: 'leisure=park',
|
|
5
|
+
cafe: 'amenity=cafe',
|
|
6
|
+
restaurant: 'amenity=restaurant',
|
|
7
|
+
service_station: 'amenity=fuel',
|
|
8
|
+
library: 'amenity=library',
|
|
9
|
+
pub: 'amenity=pub',
|
|
10
|
+
playground: 'leisure=playground',
|
|
11
|
+
community_centre: 'amenity=community_centre',
|
|
12
|
+
};
|
|
13
|
+
function polygonBBox(polygon) {
|
|
14
|
+
const coords = polygon.coordinates[0];
|
|
15
|
+
let south = Infinity, west = Infinity, north = -Infinity, east = -Infinity;
|
|
16
|
+
for (const [lon, lat] of coords) {
|
|
17
|
+
if (lat < south)
|
|
18
|
+
south = lat;
|
|
19
|
+
if (lat > north)
|
|
20
|
+
north = lat;
|
|
21
|
+
if (lon < west)
|
|
22
|
+
west = lon;
|
|
23
|
+
if (lon > east)
|
|
24
|
+
east = lon;
|
|
25
|
+
}
|
|
26
|
+
return { south, west, north, east };
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Search for venues within a polygon using the Overpass API.
|
|
30
|
+
* Uses the bounding box of the polygon for the query.
|
|
31
|
+
*/
|
|
32
|
+
export async function searchVenues(polygon, venueTypes, overpassUrl) {
|
|
33
|
+
const bbox = polygonBBox(polygon);
|
|
34
|
+
const bboxStr = `${bbox.south},${bbox.west},${bbox.north},${bbox.east}`;
|
|
35
|
+
const tagQueries = venueTypes
|
|
36
|
+
.map(vt => VENUE_TAG_MAP[vt] ?? `amenity=${vt}`)
|
|
37
|
+
.map(tag => {
|
|
38
|
+
const [key, value] = tag.split('=');
|
|
39
|
+
return `node["${key}"="${value}"]["name"](${bboxStr});`;
|
|
40
|
+
})
|
|
41
|
+
.join('\n');
|
|
42
|
+
const query = `[out:json][timeout:25];(\n${tagQueries}\n);out body;`;
|
|
43
|
+
const response = await fetch(overpassUrl ?? OVERPASS_URL, {
|
|
44
|
+
method: 'POST',
|
|
45
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
46
|
+
body: `data=${encodeURIComponent(query)}`,
|
|
47
|
+
});
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
const text = await response.text();
|
|
50
|
+
throw new Error(`Overpass API error ${response.status}: ${text}`);
|
|
51
|
+
}
|
|
52
|
+
const data = await response.json();
|
|
53
|
+
return data.elements
|
|
54
|
+
.filter(el => el.tags?.name)
|
|
55
|
+
.map(el => ({
|
|
56
|
+
name: el.tags.name,
|
|
57
|
+
lat: el.lat,
|
|
58
|
+
lon: el.lon,
|
|
59
|
+
venueType: inferVenueType(el.tags, venueTypes),
|
|
60
|
+
osmId: `${el.type}/${el.id}`,
|
|
61
|
+
}));
|
|
62
|
+
}
|
|
63
|
+
function inferVenueType(tags, requested) {
|
|
64
|
+
for (const vt of requested) {
|
|
65
|
+
const mapping = VENUE_TAG_MAP[vt];
|
|
66
|
+
if (mapping) {
|
|
67
|
+
const [key, value] = mapping.split('=');
|
|
68
|
+
if (tags[key] === value)
|
|
69
|
+
return vt;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return requested[0] ?? 'unknown';
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=venues.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"venues.js","sourceRoot":"","sources":["../src/venues.ts"],"names":[],"mappings":"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"}
|