@fieldia/map 0.15.0 → 0.17.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.
- package/README.md +79 -11
- package/package.json +4 -4
- package/src/index.d.mts +2 -1
- package/src/index.d.ts +2 -1
- package/src/index.js +3 -1
- package/src/index.js.map +1 -1
- package/src/index.mjs +1 -0
- package/src/index.mjs.map +1 -1
- package/src/lib/answers.d.mts +17 -0
- package/src/lib/answers.d.ts +17 -0
- package/src/lib/answers.js +27 -0
- package/src/lib/answers.js.map +1 -0
- package/src/lib/answers.mjs +21 -0
- package/src/lib/answers.mjs.map +1 -0
- package/src/lib/area.js +2 -1
- package/src/lib/area.js.map +1 -1
- package/src/lib/area.mjs +3 -2
- package/src/lib/area.mjs.map +1 -1
- package/src/lib/card.d.mts +10 -2
- package/src/lib/card.d.ts +10 -2
- package/src/lib/card.js +13 -4
- package/src/lib/card.js.map +1 -1
- package/src/lib/card.mjs +13 -4
- package/src/lib/card.mjs.map +1 -1
- package/src/lib/form-map.d.mts +18 -0
- package/src/lib/form-map.d.ts +18 -0
- package/src/lib/form-map.js +586 -0
- package/src/lib/form-map.js.map +1 -0
- package/src/lib/form-map.mjs +583 -0
- package/src/lib/form-map.mjs.map +1 -0
- package/src/lib/heat.d.mts +25 -0
- package/src/lib/heat.d.ts +25 -0
- package/src/lib/heat.js +111 -0
- package/src/lib/heat.js.map +1 -0
- package/src/lib/heat.mjs +108 -0
- package/src/lib/heat.mjs.map +1 -0
- package/src/lib/labels.d.mts +33 -0
- package/src/lib/labels.d.ts +33 -0
- package/src/lib/labels.js +60 -1
- package/src/lib/labels.js.map +1 -1
- package/src/lib/labels.mjs +58 -0
- package/src/lib/labels.mjs.map +1 -1
- package/src/lib/list-view.js +168 -70
- package/src/lib/list-view.js.map +1 -1
- package/src/lib/list-view.mjs +162 -64
- package/src/lib/list-view.mjs.map +1 -1
- package/src/lib/map-core.d.mts +8 -0
- package/src/lib/map-core.d.ts +8 -0
- package/src/lib/map-core.js +57 -4
- package/src/lib/map-core.js.map +1 -1
- package/src/lib/map-core.mjs +56 -4
- package/src/lib/map-core.mjs.map +1 -1
- package/src/lib/marks.d.mts +34 -0
- package/src/lib/marks.d.ts +34 -0
- package/src/lib/marks.js +56 -0
- package/src/lib/marks.js.map +1 -0
- package/src/lib/marks.mjs +49 -0
- package/src/lib/marks.mjs.map +1 -0
- package/src/lib/measure.d.mts +15 -0
- package/src/lib/measure.d.ts +15 -0
- package/src/lib/measure.js +157 -0
- package/src/lib/measure.js.map +1 -0
- package/src/lib/measure.mjs +153 -0
- package/src/lib/measure.mjs.map +1 -0
- package/src/lib/pins.d.mts +2 -0
- package/src/lib/pins.d.ts +2 -0
- package/src/lib/pins.js +5 -1
- package/src/lib/pins.js.map +1 -1
- package/src/lib/pins.mjs +3 -1
- package/src/lib/pins.mjs.map +1 -1
- package/src/lib/place.js +3 -1
- package/src/lib/place.js.map +1 -1
- package/src/lib/place.mjs +4 -2
- package/src/lib/place.mjs.map +1 -1
- package/src/lib/providers.d.mts +43 -3
- package/src/lib/providers.d.ts +43 -3
- package/src/lib/providers.js +76 -67
- package/src/lib/providers.js.map +1 -1
- package/src/lib/providers.mjs +24 -15
- package/src/lib/providers.mjs.map +1 -1
- package/src/lib/reach.d.mts +25 -0
- package/src/lib/reach.d.ts +25 -0
- package/src/lib/reach.js +158 -0
- package/src/lib/reach.js.map +1 -0
- package/src/lib/reach.mjs +153 -0
- package/src/lib/reach.mjs.map +1 -0
- package/src/lib/regions.d.mts +137 -0
- package/src/lib/regions.d.ts +137 -0
- package/src/lib/regions.js +456 -0
- package/src/lib/regions.js.map +1 -0
- package/src/lib/regions.mjs +445 -0
- package/src/lib/regions.mjs.map +1 -0
- package/src/lib/route-line.d.mts +34 -0
- package/src/lib/route-line.d.ts +34 -0
- package/src/lib/route-line.js +53 -0
- package/src/lib/route-line.js.map +1 -0
- package/src/lib/route-line.mjs +47 -0
- package/src/lib/route-line.mjs.map +1 -0
- package/src/lib/routes.d.mts +40 -0
- package/src/lib/routes.d.ts +40 -0
- package/src/lib/routes.js +149 -0
- package/src/lib/routes.js.map +1 -0
- package/src/lib/routes.mjs +140 -0
- package/src/lib/routes.mjs.map +1 -0
- package/src/lib/settings.d.mts +13 -3
- package/src/lib/settings.d.ts +13 -3
- package/src/lib/styles.d.mts +10 -2
- package/src/lib/styles.d.ts +10 -2
- package/src/lib/styles.js +52 -3
- package/src/lib/styles.js.map +1 -1
- package/src/lib/styles.mjs +50 -2
- package/src/lib/styles.mjs.map +1 -1
- package/src/lib/tools.d.mts +27 -0
- package/src/lib/tools.d.ts +27 -0
- package/src/lib/tools.js +84 -0
- package/src/lib/tools.js.map +1 -0
- package/src/lib/tools.mjs +81 -0
- package/src/lib/tools.mjs.map +1 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { metresBetween } from './geo.mjs';
|
|
2
|
+
export function routeLine(line) {
|
|
3
|
+
const along = [0];
|
|
4
|
+
for (let i = 1; i < line.length; i++)
|
|
5
|
+
along.push(along[i - 1] + metresBetween(line[i - 1], line[i]));
|
|
6
|
+
return { line, along, metres: along[along.length - 1] ?? 0 };
|
|
7
|
+
}
|
|
8
|
+
/** The nearest point of the line to a place: each segment measured flat around the place, as a few hundred metres are. */
|
|
9
|
+
export function nearestOnLine(route, place) {
|
|
10
|
+
const { line, along } = route;
|
|
11
|
+
if (line.length === 1)
|
|
12
|
+
return { index: 0, at: line[0], along: 0, off: metresBetween(line[0], place) };
|
|
13
|
+
const scale = Math.cos((place.lat * Math.PI) / 180);
|
|
14
|
+
let best = { index: 0, at: line[0], along: 0, off: Infinity };
|
|
15
|
+
for (let i = 0; i < line.length - 1; i++) {
|
|
16
|
+
const a = line[i];
|
|
17
|
+
const b = line[i + 1];
|
|
18
|
+
const dx = (b.lng - a.lng) * scale;
|
|
19
|
+
const dy = b.lat - a.lat;
|
|
20
|
+
const length = dx * dx + dy * dy;
|
|
21
|
+
const t = length ? Math.max(0, Math.min(1, (((place.lng - a.lng) * scale) * dx + (place.lat - a.lat) * dy) / length)) : 0;
|
|
22
|
+
const at = { lat: a.lat + (b.lat - a.lat) * t, lng: a.lng + (b.lng - a.lng) * t };
|
|
23
|
+
const off = metresBetween(at, place);
|
|
24
|
+
if (off < best.off)
|
|
25
|
+
best = { index: i, at, along: along[i] + (along[i + 1] - along[i]) * t, off };
|
|
26
|
+
}
|
|
27
|
+
return best;
|
|
28
|
+
}
|
|
29
|
+
/** The line in two at a point on it: the part travelled, and the part left, each starting or ending there. */
|
|
30
|
+
export function splitLine(route, on) {
|
|
31
|
+
const { line } = route;
|
|
32
|
+
return { done: [...line.slice(0, on.index + 1), on.at], left: [on.at, ...line.slice(on.index + 1)] };
|
|
33
|
+
}
|
|
34
|
+
/** The point `metres` along the line, the ends where it runs past them. */
|
|
35
|
+
export function pointAlong(route, metres) {
|
|
36
|
+
const { line, along } = route;
|
|
37
|
+
if (metres <= 0)
|
|
38
|
+
return line[0];
|
|
39
|
+
if (metres >= route.metres)
|
|
40
|
+
return line[line.length - 1];
|
|
41
|
+
let i = 1;
|
|
42
|
+
while (along[i] < metres)
|
|
43
|
+
i++;
|
|
44
|
+
const t = (metres - along[i - 1]) / (along[i] - along[i - 1] || 1);
|
|
45
|
+
return { lat: line[i - 1].lat + (line[i].lat - line[i - 1].lat) * t, lng: line[i - 1].lng + (line[i].lng - line[i - 1].lng) * t };
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=route-line.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-line.mjs","sourceRoot":"","sources":["../../../../../libs/map/src/lib/route-line.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { LatLng } from './geo.mjs';
|
|
2
|
+
import { type Fetch } from './answers.mjs';
|
|
3
|
+
import type { ReachFound, ReachRequest, RouteFound, RouteRequest } from './providers.mjs';
|
|
4
|
+
/**
|
|
5
|
+
* The providers' routes along the roads and reachable areas, loaded the
|
|
6
|
+
* first time a map asks for one: a form with only a place or an area never
|
|
7
|
+
* carries them. Each reads its provider's answer into one line, its metres
|
|
8
|
+
* and its seconds; or an area's rings.
|
|
9
|
+
*/
|
|
10
|
+
/** Google's encoded polyline, as its Routes API sends a line: five decimals, each number a run of five-bit groups. */
|
|
11
|
+
export declare function decodePolyline(encoded: string): LatLng[];
|
|
12
|
+
/** OSRM's route: the points longitude first, by its profile. */
|
|
13
|
+
export declare function osrmRoute(fetchWith: Fetch, osrm: string, { points, mode, signal }: RouteRequest): Promise<RouteFound>;
|
|
14
|
+
/** Azure Maps' Route Directions of 2025: a GeoJSON of the points in order, its route path asked for; by car or on foot. */
|
|
15
|
+
export declare function azureRoute(ask: {
|
|
16
|
+
fetchWith: Fetch;
|
|
17
|
+
auth: string;
|
|
18
|
+
headers: () => Promise<Record<string, string>>;
|
|
19
|
+
}, { points, mode, signal }: RouteRequest): Promise<RouteFound>;
|
|
20
|
+
/** Google's Routes API: only the fields it reads, its line an encoded polyline, traffic for a car. */
|
|
21
|
+
export declare function googleRoute(ask: {
|
|
22
|
+
fetchWith: Fetch;
|
|
23
|
+
key: string;
|
|
24
|
+
}, { points, mode, signal }: RouteRequest): Promise<RouteFound>;
|
|
25
|
+
/** Mapbox Directions: by its profile, traffic for a car. */
|
|
26
|
+
export declare function mapboxRoute(ask: {
|
|
27
|
+
fetchWith: Fetch;
|
|
28
|
+
token: string;
|
|
29
|
+
}, { points, mode, signal }: RouteRequest): Promise<RouteFound>;
|
|
30
|
+
/** Azure Maps' Route Range of 2025: the area within a time from a point, by car (or truck) alone. */
|
|
31
|
+
export declare function azureReach(ask: {
|
|
32
|
+
fetchWith: Fetch;
|
|
33
|
+
auth: string;
|
|
34
|
+
headers: () => Promise<Record<string, string>>;
|
|
35
|
+
}, { at, minutes, mode, signal }: ReachRequest): Promise<ReachFound>;
|
|
36
|
+
/** Mapbox Isochrone: the area within some minutes, by its profile, as polygons. */
|
|
37
|
+
export declare function mapboxReach(ask: {
|
|
38
|
+
fetchWith: Fetch;
|
|
39
|
+
token: string;
|
|
40
|
+
}, { at, minutes, mode, signal }: ReachRequest): Promise<ReachFound>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { LatLng } from './geo';
|
|
2
|
+
import { type Fetch } from './answers';
|
|
3
|
+
import type { ReachFound, ReachRequest, RouteFound, RouteRequest } from './providers';
|
|
4
|
+
/**
|
|
5
|
+
* The providers' routes along the roads and reachable areas, loaded the
|
|
6
|
+
* first time a map asks for one: a form with only a place or an area never
|
|
7
|
+
* carries them. Each reads its provider's answer into one line, its metres
|
|
8
|
+
* and its seconds; or an area's rings.
|
|
9
|
+
*/
|
|
10
|
+
/** Google's encoded polyline, as its Routes API sends a line: five decimals, each number a run of five-bit groups. */
|
|
11
|
+
export declare function decodePolyline(encoded: string): LatLng[];
|
|
12
|
+
/** OSRM's route: the points longitude first, by its profile. */
|
|
13
|
+
export declare function osrmRoute(fetchWith: Fetch, osrm: string, { points, mode, signal }: RouteRequest): Promise<RouteFound>;
|
|
14
|
+
/** Azure Maps' Route Directions of 2025: a GeoJSON of the points in order, its route path asked for; by car or on foot. */
|
|
15
|
+
export declare function azureRoute(ask: {
|
|
16
|
+
fetchWith: Fetch;
|
|
17
|
+
auth: string;
|
|
18
|
+
headers: () => Promise<Record<string, string>>;
|
|
19
|
+
}, { points, mode, signal }: RouteRequest): Promise<RouteFound>;
|
|
20
|
+
/** Google's Routes API: only the fields it reads, its line an encoded polyline, traffic for a car. */
|
|
21
|
+
export declare function googleRoute(ask: {
|
|
22
|
+
fetchWith: Fetch;
|
|
23
|
+
key: string;
|
|
24
|
+
}, { points, mode, signal }: RouteRequest): Promise<RouteFound>;
|
|
25
|
+
/** Mapbox Directions: by its profile, traffic for a car. */
|
|
26
|
+
export declare function mapboxRoute(ask: {
|
|
27
|
+
fetchWith: Fetch;
|
|
28
|
+
token: string;
|
|
29
|
+
}, { points, mode, signal }: RouteRequest): Promise<RouteFound>;
|
|
30
|
+
/** Azure Maps' Route Range of 2025: the area within a time from a point, by car (or truck) alone. */
|
|
31
|
+
export declare function azureReach(ask: {
|
|
32
|
+
fetchWith: Fetch;
|
|
33
|
+
auth: string;
|
|
34
|
+
headers: () => Promise<Record<string, string>>;
|
|
35
|
+
}, { at, minutes, mode, signal }: ReachRequest): Promise<ReachFound>;
|
|
36
|
+
/** Mapbox Isochrone: the area within some minutes, by its profile, as polygons. */
|
|
37
|
+
export declare function mapboxReach(ask: {
|
|
38
|
+
fetchWith: Fetch;
|
|
39
|
+
token: string;
|
|
40
|
+
}, { at, minutes, mode, signal }: ReachRequest): Promise<ReachFound>;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.decodePolyline = decodePolyline;
|
|
4
|
+
exports.osrmRoute = osrmRoute;
|
|
5
|
+
exports.azureRoute = azureRoute;
|
|
6
|
+
exports.googleRoute = googleRoute;
|
|
7
|
+
exports.mapboxRoute = mapboxRoute;
|
|
8
|
+
exports.azureReach = azureReach;
|
|
9
|
+
exports.mapboxReach = mapboxReach;
|
|
10
|
+
const answers_1 = require("./answers");
|
|
11
|
+
/**
|
|
12
|
+
* The providers' routes along the roads and reachable areas, loaded the
|
|
13
|
+
* first time a map asks for one: a form with only a place or an area never
|
|
14
|
+
* carries them. Each reads its provider's answer into one line, its metres
|
|
15
|
+
* and its seconds; or an area's rings.
|
|
16
|
+
*/
|
|
17
|
+
/** Google's encoded polyline, as its Routes API sends a line: five decimals, each number a run of five-bit groups. */
|
|
18
|
+
function decodePolyline(encoded) {
|
|
19
|
+
const line = [];
|
|
20
|
+
let at = 0;
|
|
21
|
+
let lat = 0;
|
|
22
|
+
let lng = 0;
|
|
23
|
+
const next = () => {
|
|
24
|
+
let shift = 0;
|
|
25
|
+
let result = 0;
|
|
26
|
+
let byte;
|
|
27
|
+
do {
|
|
28
|
+
byte = encoded.charCodeAt(at++) - 63;
|
|
29
|
+
result |= (byte & 0x1f) << shift;
|
|
30
|
+
shift += 5;
|
|
31
|
+
} while (byte >= 0x20);
|
|
32
|
+
return result & 1 ? ~(result >> 1) : result >> 1;
|
|
33
|
+
};
|
|
34
|
+
while (at < encoded.length) {
|
|
35
|
+
lat += next();
|
|
36
|
+
lng += next();
|
|
37
|
+
line.push({ lat: lat / 1e5, lng: lng / 1e5 });
|
|
38
|
+
}
|
|
39
|
+
return line;
|
|
40
|
+
}
|
|
41
|
+
/** A route's line from GeoJSON coordinates, longitude first: a LineString's, or a MultiLineString's joined. */
|
|
42
|
+
function lineOf(coordinates, multi = false) {
|
|
43
|
+
const runs = multi ? coordinates : [coordinates];
|
|
44
|
+
if (!Array.isArray(runs))
|
|
45
|
+
return [];
|
|
46
|
+
return runs.flatMap((run) => Array.isArray(run) ? run.flatMap((pair) => (Array.isArray(pair) && typeof pair[0] === 'number' && typeof pair[1] === 'number' ? [{ lat: pair[1], lng: pair[0] }] : [])) : []);
|
|
47
|
+
}
|
|
48
|
+
/** A route that is no route: refused in words a developer can act on. */
|
|
49
|
+
function routed(found, provider) {
|
|
50
|
+
if (found.line.length < 2 || !Number.isFinite(found.metres) || !Number.isFinite(found.seconds))
|
|
51
|
+
throw new Error(`${provider} found no route`);
|
|
52
|
+
return found;
|
|
53
|
+
}
|
|
54
|
+
const OSRM_PROFILE = { car: 'driving', bike: 'cycling', foot: 'walking' };
|
|
55
|
+
/** OSRM's route: the points longitude first, by its profile. */
|
|
56
|
+
async function osrmRoute(fetchWith, osrm, { points, mode, signal }) {
|
|
57
|
+
const found = await (0, answers_1.getJson)(fetchWith, `${osrm}/route/v1/${OSRM_PROFILE[mode]}/${points.map((p) => `${p.lng},${p.lat}`).join(';')}?overview=full&geometries=geojson`, { signal });
|
|
58
|
+
const route = (0, answers_1.pathOf)(found, 'routes')?.[0];
|
|
59
|
+
return routed({ line: lineOf((0, answers_1.pathOf)(route, 'geometry', 'coordinates')), metres: Number((0, answers_1.pathOf)(route, 'distance')), seconds: Number((0, answers_1.pathOf)(route, 'duration')) }, 'OSRM');
|
|
60
|
+
}
|
|
61
|
+
/** Azure Maps' Route Directions of 2025: a GeoJSON of the points in order, its route path asked for; by car or on foot. */
|
|
62
|
+
async function azureRoute(ask, { points, mode, signal }) {
|
|
63
|
+
// Its route service drives and walks; it has no bicycles.
|
|
64
|
+
if (mode === 'bike')
|
|
65
|
+
throw new Error('Azure Maps finds routes by car or on foot, not by bike');
|
|
66
|
+
const found = await (0, answers_1.getJson)(ask.fetchWith, `https://atlas.microsoft.com/route/directions?api-version=2025-01-01${ask.auth}`, {
|
|
67
|
+
method: 'POST',
|
|
68
|
+
signal,
|
|
69
|
+
headers: { 'Content-Type': 'application/geo+json', ...(await ask.headers()) },
|
|
70
|
+
body: JSON.stringify({
|
|
71
|
+
type: 'FeatureCollection',
|
|
72
|
+
features: points.map((p, i) => ({
|
|
73
|
+
type: 'Feature',
|
|
74
|
+
geometry: { type: 'Point', coordinates: [p.lng, p.lat] },
|
|
75
|
+
// Its first and last are where it starts and ends; those between, passed through.
|
|
76
|
+
properties: { pointIndex: i, pointType: i === 0 || i === points.length - 1 ? 'waypoint' : 'viaWaypoint' },
|
|
77
|
+
})),
|
|
78
|
+
travelMode: mode === 'foot' ? 'walking' : 'driving',
|
|
79
|
+
routeOutputOptions: ['routePath'],
|
|
80
|
+
}),
|
|
81
|
+
});
|
|
82
|
+
const features = (0, answers_1.pathOf)(found, 'features');
|
|
83
|
+
const path = Array.isArray(features) ? features.find((f) => (0, answers_1.pathOf)(f, 'properties', 'type') === 'RoutePath') : undefined;
|
|
84
|
+
// The time with traffic, when it gives one.
|
|
85
|
+
const seconds = (0, answers_1.pathOf)(path, 'properties', 'durationTrafficInSeconds') ?? (0, answers_1.pathOf)(path, 'properties', 'durationInSeconds');
|
|
86
|
+
return routed({ line: lineOf((0, answers_1.pathOf)(path, 'geometry', 'coordinates'), true), metres: Number((0, answers_1.pathOf)(path, 'properties', 'distanceInMeters')), seconds: Number(seconds) }, 'Azure Maps');
|
|
87
|
+
}
|
|
88
|
+
/** Google's Routes API: only the fields it reads, its line an encoded polyline, traffic for a car. */
|
|
89
|
+
async function googleRoute(ask, { points, mode, signal }) {
|
|
90
|
+
const place = (p) => ({ location: { latLng: { latitude: p.lat, longitude: p.lng } } });
|
|
91
|
+
const answer = await (0, answers_1.getJson)(ask.fetchWith, 'https://routes.googleapis.com/directions/v2:computeRoutes', {
|
|
92
|
+
method: 'POST',
|
|
93
|
+
signal,
|
|
94
|
+
headers: { 'Content-Type': 'application/json', 'X-Goog-Api-Key': ask.key, 'X-Goog-FieldMask': 'routes.distanceMeters,routes.duration,routes.polyline.encodedPolyline' },
|
|
95
|
+
body: JSON.stringify({
|
|
96
|
+
origin: place(points[0]),
|
|
97
|
+
destination: place(points[points.length - 1]),
|
|
98
|
+
...(points.length > 2 ? { intermediates: points.slice(1, -1).map(place) } : {}),
|
|
99
|
+
travelMode: mode === 'bike' ? 'BICYCLE' : mode === 'foot' ? 'WALK' : 'DRIVE',
|
|
100
|
+
...(mode === 'car' ? { routingPreference: 'TRAFFIC_AWARE' } : {}),
|
|
101
|
+
}),
|
|
102
|
+
});
|
|
103
|
+
const route = (0, answers_1.pathOf)(answer, 'routes')?.[0];
|
|
104
|
+
const encoded = (0, answers_1.pathOf)(route, 'polyline', 'encodedPolyline');
|
|
105
|
+
// Its duration is words: "489s".
|
|
106
|
+
return routed({ line: typeof encoded === 'string' ? decodePolyline(encoded) : [], metres: Number((0, answers_1.pathOf)(route, 'distanceMeters')), seconds: parseFloat(String((0, answers_1.pathOf)(route, 'duration'))) }, "Google's Routes API");
|
|
107
|
+
}
|
|
108
|
+
/** Mapbox Directions: by its profile, traffic for a car. */
|
|
109
|
+
async function mapboxRoute(ask, { points, mode, signal }) {
|
|
110
|
+
const profile = mode === 'bike' ? 'cycling' : mode === 'foot' ? 'walking' : 'driving-traffic';
|
|
111
|
+
const found = await (0, answers_1.getJson)(ask.fetchWith, `https://api.mapbox.com/directions/v5/mapbox/${profile}/${points.map((p) => `${p.lng},${p.lat}`).join(';')}?geometries=geojson&overview=full&access_token=${ask.token}`, { signal });
|
|
112
|
+
const route = (0, answers_1.pathOf)(found, 'routes')?.[0];
|
|
113
|
+
return routed({ line: lineOf((0, answers_1.pathOf)(route, 'geometry', 'coordinates')), metres: Number((0, answers_1.pathOf)(route, 'distance')), seconds: Number((0, answers_1.pathOf)(route, 'duration')) }, 'Mapbox');
|
|
114
|
+
}
|
|
115
|
+
/** The outer rings of a GeoJSON Polygon's or MultiPolygon's, as places. */
|
|
116
|
+
function ringsOf(geometry) {
|
|
117
|
+
const type = (0, answers_1.pathOf)(geometry, 'type');
|
|
118
|
+
const coordinates = (0, answers_1.pathOf)(geometry, 'coordinates');
|
|
119
|
+
const polygons = type === 'Polygon' ? [coordinates] : type === 'MultiPolygon' && Array.isArray(coordinates) ? coordinates : [];
|
|
120
|
+
return polygons.flatMap((polygon) => (Array.isArray(polygon) ? [lineOf(polygon[0])] : [])).filter((ring) => ring.length > 2);
|
|
121
|
+
}
|
|
122
|
+
/** An area that is no area: refused in words a developer can act on. */
|
|
123
|
+
function reached(found, provider) {
|
|
124
|
+
if (!found.rings.length)
|
|
125
|
+
throw new Error(`${provider} found no reachable area`);
|
|
126
|
+
return found;
|
|
127
|
+
}
|
|
128
|
+
/** Azure Maps' Route Range of 2025: the area within a time from a point, by car (or truck) alone. */
|
|
129
|
+
async function azureReach(ask, { at, minutes, mode, signal }) {
|
|
130
|
+
if (mode !== 'car')
|
|
131
|
+
throw new Error('Azure Maps works out reachable areas by car, not by bike or on foot');
|
|
132
|
+
const found = await (0, answers_1.getJson)(ask.fetchWith, `https://atlas.microsoft.com/route/range?api-version=2025-01-01${ask.auth}`, {
|
|
133
|
+
method: 'POST',
|
|
134
|
+
signal,
|
|
135
|
+
headers: { 'Content-Type': 'application/geo+json', ...(await ask.headers()) },
|
|
136
|
+
body: JSON.stringify({ type: 'Feature', geometry: { type: 'Point', coordinates: [at.lng, at.lat] }, properties: { timeBudgetInSec: Math.round(minutes * 60), travelMode: 'driving' } }),
|
|
137
|
+
});
|
|
138
|
+
const features = (0, answers_1.pathOf)(found, 'features');
|
|
139
|
+
const boundary = Array.isArray(features) ? features.find((f) => (0, answers_1.pathOf)(f, 'properties', 'type') === 'boundary') : undefined;
|
|
140
|
+
return reached({ rings: ringsOf((0, answers_1.pathOf)(boundary, 'geometry')) }, 'Azure Maps');
|
|
141
|
+
}
|
|
142
|
+
/** Mapbox Isochrone: the area within some minutes, by its profile, as polygons. */
|
|
143
|
+
async function mapboxReach(ask, { at, minutes, mode, signal }) {
|
|
144
|
+
const profile = mode === 'bike' ? 'cycling' : mode === 'foot' ? 'walking' : 'driving';
|
|
145
|
+
const found = await (0, answers_1.getJson)(ask.fetchWith, `https://api.mapbox.com/isochrone/v1/mapbox/${profile}/${at.lng},${at.lat}?contours_minutes=${Math.round(minutes)}&polygons=true&access_token=${ask.token}`, { signal });
|
|
146
|
+
const features = (0, answers_1.pathOf)(found, 'features');
|
|
147
|
+
return reached({ rings: Array.isArray(features) ? features.flatMap((f) => ringsOf((0, answers_1.pathOf)(f, 'geometry'))) : [] }, 'Mapbox');
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../../../../libs/map/src/lib/routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { getJson, pathOf } from './answers.mjs';
|
|
2
|
+
/**
|
|
3
|
+
* The providers' routes along the roads and reachable areas, loaded the
|
|
4
|
+
* first time a map asks for one: a form with only a place or an area never
|
|
5
|
+
* carries them. Each reads its provider's answer into one line, its metres
|
|
6
|
+
* and its seconds; or an area's rings.
|
|
7
|
+
*/
|
|
8
|
+
/** Google's encoded polyline, as its Routes API sends a line: five decimals, each number a run of five-bit groups. */
|
|
9
|
+
export function decodePolyline(encoded) {
|
|
10
|
+
const line = [];
|
|
11
|
+
let at = 0;
|
|
12
|
+
let lat = 0;
|
|
13
|
+
let lng = 0;
|
|
14
|
+
const next = () => {
|
|
15
|
+
let shift = 0;
|
|
16
|
+
let result = 0;
|
|
17
|
+
let byte;
|
|
18
|
+
do {
|
|
19
|
+
byte = encoded.charCodeAt(at++) - 63;
|
|
20
|
+
result |= (byte & 0x1f) << shift;
|
|
21
|
+
shift += 5;
|
|
22
|
+
} while (byte >= 0x20);
|
|
23
|
+
return result & 1 ? ~(result >> 1) : result >> 1;
|
|
24
|
+
};
|
|
25
|
+
while (at < encoded.length) {
|
|
26
|
+
lat += next();
|
|
27
|
+
lng += next();
|
|
28
|
+
line.push({ lat: lat / 1e5, lng: lng / 1e5 });
|
|
29
|
+
}
|
|
30
|
+
return line;
|
|
31
|
+
}
|
|
32
|
+
/** A route's line from GeoJSON coordinates, longitude first: a LineString's, or a MultiLineString's joined. */
|
|
33
|
+
function lineOf(coordinates, multi = false) {
|
|
34
|
+
const runs = multi ? coordinates : [coordinates];
|
|
35
|
+
if (!Array.isArray(runs))
|
|
36
|
+
return [];
|
|
37
|
+
return runs.flatMap((run) => Array.isArray(run) ? run.flatMap((pair) => (Array.isArray(pair) && typeof pair[0] === 'number' && typeof pair[1] === 'number' ? [{ lat: pair[1], lng: pair[0] }] : [])) : []);
|
|
38
|
+
}
|
|
39
|
+
/** A route that is no route: refused in words a developer can act on. */
|
|
40
|
+
function routed(found, provider) {
|
|
41
|
+
if (found.line.length < 2 || !Number.isFinite(found.metres) || !Number.isFinite(found.seconds))
|
|
42
|
+
throw new Error(`${provider} found no route`);
|
|
43
|
+
return found;
|
|
44
|
+
}
|
|
45
|
+
const OSRM_PROFILE = { car: 'driving', bike: 'cycling', foot: 'walking' };
|
|
46
|
+
/** OSRM's route: the points longitude first, by its profile. */
|
|
47
|
+
export async function osrmRoute(fetchWith, osrm, { points, mode, signal }) {
|
|
48
|
+
const found = await getJson(fetchWith, `${osrm}/route/v1/${OSRM_PROFILE[mode]}/${points.map((p) => `${p.lng},${p.lat}`).join(';')}?overview=full&geometries=geojson`, { signal });
|
|
49
|
+
const route = pathOf(found, 'routes')?.[0];
|
|
50
|
+
return routed({ line: lineOf(pathOf(route, 'geometry', 'coordinates')), metres: Number(pathOf(route, 'distance')), seconds: Number(pathOf(route, 'duration')) }, 'OSRM');
|
|
51
|
+
}
|
|
52
|
+
/** Azure Maps' Route Directions of 2025: a GeoJSON of the points in order, its route path asked for; by car or on foot. */
|
|
53
|
+
export async function azureRoute(ask, { points, mode, signal }) {
|
|
54
|
+
// Its route service drives and walks; it has no bicycles.
|
|
55
|
+
if (mode === 'bike')
|
|
56
|
+
throw new Error('Azure Maps finds routes by car or on foot, not by bike');
|
|
57
|
+
const found = await getJson(ask.fetchWith, `https://atlas.microsoft.com/route/directions?api-version=2025-01-01${ask.auth}`, {
|
|
58
|
+
method: 'POST',
|
|
59
|
+
signal,
|
|
60
|
+
headers: { 'Content-Type': 'application/geo+json', ...(await ask.headers()) },
|
|
61
|
+
body: JSON.stringify({
|
|
62
|
+
type: 'FeatureCollection',
|
|
63
|
+
features: points.map((p, i) => ({
|
|
64
|
+
type: 'Feature',
|
|
65
|
+
geometry: { type: 'Point', coordinates: [p.lng, p.lat] },
|
|
66
|
+
// Its first and last are where it starts and ends; those between, passed through.
|
|
67
|
+
properties: { pointIndex: i, pointType: i === 0 || i === points.length - 1 ? 'waypoint' : 'viaWaypoint' },
|
|
68
|
+
})),
|
|
69
|
+
travelMode: mode === 'foot' ? 'walking' : 'driving',
|
|
70
|
+
routeOutputOptions: ['routePath'],
|
|
71
|
+
}),
|
|
72
|
+
});
|
|
73
|
+
const features = pathOf(found, 'features');
|
|
74
|
+
const path = Array.isArray(features) ? features.find((f) => pathOf(f, 'properties', 'type') === 'RoutePath') : undefined;
|
|
75
|
+
// The time with traffic, when it gives one.
|
|
76
|
+
const seconds = pathOf(path, 'properties', 'durationTrafficInSeconds') ?? pathOf(path, 'properties', 'durationInSeconds');
|
|
77
|
+
return routed({ line: lineOf(pathOf(path, 'geometry', 'coordinates'), true), metres: Number(pathOf(path, 'properties', 'distanceInMeters')), seconds: Number(seconds) }, 'Azure Maps');
|
|
78
|
+
}
|
|
79
|
+
/** Google's Routes API: only the fields it reads, its line an encoded polyline, traffic for a car. */
|
|
80
|
+
export async function googleRoute(ask, { points, mode, signal }) {
|
|
81
|
+
const place = (p) => ({ location: { latLng: { latitude: p.lat, longitude: p.lng } } });
|
|
82
|
+
const answer = await getJson(ask.fetchWith, 'https://routes.googleapis.com/directions/v2:computeRoutes', {
|
|
83
|
+
method: 'POST',
|
|
84
|
+
signal,
|
|
85
|
+
headers: { 'Content-Type': 'application/json', 'X-Goog-Api-Key': ask.key, 'X-Goog-FieldMask': 'routes.distanceMeters,routes.duration,routes.polyline.encodedPolyline' },
|
|
86
|
+
body: JSON.stringify({
|
|
87
|
+
origin: place(points[0]),
|
|
88
|
+
destination: place(points[points.length - 1]),
|
|
89
|
+
...(points.length > 2 ? { intermediates: points.slice(1, -1).map(place) } : {}),
|
|
90
|
+
travelMode: mode === 'bike' ? 'BICYCLE' : mode === 'foot' ? 'WALK' : 'DRIVE',
|
|
91
|
+
...(mode === 'car' ? { routingPreference: 'TRAFFIC_AWARE' } : {}),
|
|
92
|
+
}),
|
|
93
|
+
});
|
|
94
|
+
const route = pathOf(answer, 'routes')?.[0];
|
|
95
|
+
const encoded = pathOf(route, 'polyline', 'encodedPolyline');
|
|
96
|
+
// Its duration is words: "489s".
|
|
97
|
+
return routed({ line: typeof encoded === 'string' ? decodePolyline(encoded) : [], metres: Number(pathOf(route, 'distanceMeters')), seconds: parseFloat(String(pathOf(route, 'duration'))) }, "Google's Routes API");
|
|
98
|
+
}
|
|
99
|
+
/** Mapbox Directions: by its profile, traffic for a car. */
|
|
100
|
+
export async function mapboxRoute(ask, { points, mode, signal }) {
|
|
101
|
+
const profile = mode === 'bike' ? 'cycling' : mode === 'foot' ? 'walking' : 'driving-traffic';
|
|
102
|
+
const found = await getJson(ask.fetchWith, `https://api.mapbox.com/directions/v5/mapbox/${profile}/${points.map((p) => `${p.lng},${p.lat}`).join(';')}?geometries=geojson&overview=full&access_token=${ask.token}`, { signal });
|
|
103
|
+
const route = pathOf(found, 'routes')?.[0];
|
|
104
|
+
return routed({ line: lineOf(pathOf(route, 'geometry', 'coordinates')), metres: Number(pathOf(route, 'distance')), seconds: Number(pathOf(route, 'duration')) }, 'Mapbox');
|
|
105
|
+
}
|
|
106
|
+
/** The outer rings of a GeoJSON Polygon's or MultiPolygon's, as places. */
|
|
107
|
+
function ringsOf(geometry) {
|
|
108
|
+
const type = pathOf(geometry, 'type');
|
|
109
|
+
const coordinates = pathOf(geometry, 'coordinates');
|
|
110
|
+
const polygons = type === 'Polygon' ? [coordinates] : type === 'MultiPolygon' && Array.isArray(coordinates) ? coordinates : [];
|
|
111
|
+
return polygons.flatMap((polygon) => (Array.isArray(polygon) ? [lineOf(polygon[0])] : [])).filter((ring) => ring.length > 2);
|
|
112
|
+
}
|
|
113
|
+
/** An area that is no area: refused in words a developer can act on. */
|
|
114
|
+
function reached(found, provider) {
|
|
115
|
+
if (!found.rings.length)
|
|
116
|
+
throw new Error(`${provider} found no reachable area`);
|
|
117
|
+
return found;
|
|
118
|
+
}
|
|
119
|
+
/** Azure Maps' Route Range of 2025: the area within a time from a point, by car (or truck) alone. */
|
|
120
|
+
export async function azureReach(ask, { at, minutes, mode, signal }) {
|
|
121
|
+
if (mode !== 'car')
|
|
122
|
+
throw new Error('Azure Maps works out reachable areas by car, not by bike or on foot');
|
|
123
|
+
const found = await getJson(ask.fetchWith, `https://atlas.microsoft.com/route/range?api-version=2025-01-01${ask.auth}`, {
|
|
124
|
+
method: 'POST',
|
|
125
|
+
signal,
|
|
126
|
+
headers: { 'Content-Type': 'application/geo+json', ...(await ask.headers()) },
|
|
127
|
+
body: JSON.stringify({ type: 'Feature', geometry: { type: 'Point', coordinates: [at.lng, at.lat] }, properties: { timeBudgetInSec: Math.round(minutes * 60), travelMode: 'driving' } }),
|
|
128
|
+
});
|
|
129
|
+
const features = pathOf(found, 'features');
|
|
130
|
+
const boundary = Array.isArray(features) ? features.find((f) => pathOf(f, 'properties', 'type') === 'boundary') : undefined;
|
|
131
|
+
return reached({ rings: ringsOf(pathOf(boundary, 'geometry')) }, 'Azure Maps');
|
|
132
|
+
}
|
|
133
|
+
/** Mapbox Isochrone: the area within some minutes, by its profile, as polygons. */
|
|
134
|
+
export async function mapboxReach(ask, { at, minutes, mode, signal }) {
|
|
135
|
+
const profile = mode === 'bike' ? 'cycling' : mode === 'foot' ? 'walking' : 'driving';
|
|
136
|
+
const found = await getJson(ask.fetchWith, `https://api.mapbox.com/isochrone/v1/mapbox/${profile}/${at.lng},${at.lat}?contours_minutes=${Math.round(minutes)}&polygons=true&access_token=${ask.token}`, { signal });
|
|
137
|
+
const features = pathOf(found, 'features');
|
|
138
|
+
return reached({ rings: Array.isArray(features) ? features.flatMap((f) => ringsOf(pathOf(f, 'geometry'))) : [] }, 'Mapbox');
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=routes.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.mjs","sourceRoot":"","sources":["../../../../../libs/map/src/lib/routes.ts"],"names":[],"mappings":"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"}
|
package/src/lib/settings.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Locale } from '@fieldia/core';
|
|
2
2
|
import type { LatLng } from './geo.mjs';
|
|
3
|
-
import type { ListMapLabels, MapLabels } from './labels.mjs';
|
|
3
|
+
import type { FormMapLabels, ListMapLabels, MapLabels } from './labels.mjs';
|
|
4
4
|
import type { PinDrawer } from './pins.mjs';
|
|
5
|
-
import type { AddressSearch, MapProvider, ReverseSearch } from './providers.mjs';
|
|
5
|
+
import type { AddressSearch, MapProvider, ReachFinder, ReverseSearch, RouteFinder } from './providers.mjs';
|
|
6
6
|
/** What every map of an app shares: given once to `mapWidgets`. */
|
|
7
7
|
export interface MapSettings {
|
|
8
8
|
provider: MapProvider;
|
|
@@ -15,8 +15,18 @@ export interface MapSettings {
|
|
|
15
15
|
/** Where an empty map opens, and how close. */
|
|
16
16
|
center?: LatLng;
|
|
17
17
|
zoom?: number;
|
|
18
|
+
/** The app's own routes, instead of the provider's. */
|
|
19
|
+
route?: RouteFinder;
|
|
20
|
+
/** The app's own reachable areas, instead of the provider's. */
|
|
21
|
+
reach?: ReachFinder;
|
|
22
|
+
/**
|
|
23
|
+
* The app's sets of borders, by the name a page's `regions.from` gives: each
|
|
24
|
+
* a GeoJSON FeatureCollection of polygons, or a function that loads one
|
|
25
|
+
* (`() => fetch('/geo/districts.json').then((r) => r.json())`), asked once.
|
|
26
|
+
*/
|
|
27
|
+
regions?: Record<string, unknown | (() => unknown)>;
|
|
18
28
|
/** The app's own pins for a list's map, by the name a page's `pin.widget` gives. */
|
|
19
29
|
pins?: Record<string, PinDrawer>;
|
|
20
30
|
/** The app's own words over the maps', by language. */
|
|
21
|
-
labels?: Partial<Record<Locale, Partial<MapLabels & ListMapLabels>>>;
|
|
31
|
+
labels?: Partial<Record<Locale, Partial<MapLabels & ListMapLabels & FormMapLabels>>>;
|
|
22
32
|
}
|
package/src/lib/settings.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { Locale } from '@fieldia/core';
|
|
2
2
|
import type { LatLng } from './geo';
|
|
3
|
-
import type { ListMapLabels, MapLabels } from './labels';
|
|
3
|
+
import type { FormMapLabels, ListMapLabels, MapLabels } from './labels';
|
|
4
4
|
import type { PinDrawer } from './pins';
|
|
5
|
-
import type { AddressSearch, MapProvider, ReverseSearch } from './providers';
|
|
5
|
+
import type { AddressSearch, MapProvider, ReachFinder, ReverseSearch, RouteFinder } from './providers';
|
|
6
6
|
/** What every map of an app shares: given once to `mapWidgets`. */
|
|
7
7
|
export interface MapSettings {
|
|
8
8
|
provider: MapProvider;
|
|
@@ -15,8 +15,18 @@ export interface MapSettings {
|
|
|
15
15
|
/** Where an empty map opens, and how close. */
|
|
16
16
|
center?: LatLng;
|
|
17
17
|
zoom?: number;
|
|
18
|
+
/** The app's own routes, instead of the provider's. */
|
|
19
|
+
route?: RouteFinder;
|
|
20
|
+
/** The app's own reachable areas, instead of the provider's. */
|
|
21
|
+
reach?: ReachFinder;
|
|
22
|
+
/**
|
|
23
|
+
* The app's sets of borders, by the name a page's `regions.from` gives: each
|
|
24
|
+
* a GeoJSON FeatureCollection of polygons, or a function that loads one
|
|
25
|
+
* (`() => fetch('/geo/districts.json').then((r) => r.json())`), asked once.
|
|
26
|
+
*/
|
|
27
|
+
regions?: Record<string, unknown | (() => unknown)>;
|
|
18
28
|
/** The app's own pins for a list's map, by the name a page's `pin.widget` gives. */
|
|
19
29
|
pins?: Record<string, PinDrawer>;
|
|
20
30
|
/** The app's own words over the maps', by language. */
|
|
21
|
-
labels?: Partial<Record<Locale, Partial<MapLabels & ListMapLabels>>>;
|
|
31
|
+
labels?: Partial<Record<Locale, Partial<MapLabels & ListMapLabels & FormMapLabels>>>;
|
|
22
32
|
}
|