roadgraph-router-v2 0.2.0 → 0.3.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/CHANGELOG.md +217 -2
- package/README.md +408 -24
- package/dist/{chunk-PXL65P3L.js → chunk-QSIKDM4A.js} +942 -316
- package/dist/index.d.ts +480 -66
- package/dist/index.js +201 -14
- package/dist/worker.js +2 -2
- package/package.json +1 -1
- package/scripts/roadgraph-compile.mjs +30 -7
package/dist/index.d.ts
CHANGED
|
@@ -62,6 +62,8 @@ interface RoadGraph {
|
|
|
62
62
|
* for a profile whose routes depend on the vehicle's size. See `./limits`.
|
|
63
63
|
*/
|
|
64
64
|
edgeLimits?: EdgeLimits;
|
|
65
|
+
/** Conditional restrictions for the edges that carry one; absent when none do. */
|
|
66
|
+
edgeConditions?: EdgeConditions;
|
|
65
67
|
/**
|
|
66
68
|
* One bit per turn restriction, saying whether this vehicle obeys it. The
|
|
67
69
|
* pairs come first, then the sequences. Absent means all of them apply.
|
|
@@ -100,6 +102,14 @@ interface RouteSnap {
|
|
|
100
102
|
point: Coordinate;
|
|
101
103
|
/** How far the requested coordinate was from that road. */
|
|
102
104
|
distanceMeters: number;
|
|
105
|
+
/**
|
|
106
|
+
* How far the route actually travels along that road, for an end that
|
|
107
|
+
* begins or finishes part-way along one. Zero where the end sits on a
|
|
108
|
+
* junction, and zero at the destination of a route that never leaves a
|
|
109
|
+
* single road, whose whole length is reported at the origin instead so
|
|
110
|
+
* that adding the two up gives the route and not twice the route.
|
|
111
|
+
*/
|
|
112
|
+
travelledMeters?: number;
|
|
103
113
|
}
|
|
104
114
|
interface RouteResult {
|
|
105
115
|
geometry: GeoJsonLineString;
|
|
@@ -139,6 +149,26 @@ interface EdgeLimits {
|
|
|
139
149
|
/** Half-tonnes. */
|
|
140
150
|
weightHalfTonnes: Uint8Array;
|
|
141
151
|
}
|
|
152
|
+
/**
|
|
153
|
+
* Conditional restrictions for the few edges carrying one: the raw
|
|
154
|
+
* `value @ condition` text, kept as written and parsed when a bundle opens.
|
|
155
|
+
*
|
|
156
|
+
* A side table for the same reason the limits are one — a country has a few
|
|
157
|
+
* thousand of these among millions of edges. The text is deduplicated into
|
|
158
|
+
* `values`, because the same working-hours ban is repeated along every segment
|
|
159
|
+
* of the street it applies to. One edge may have several rows: a lorry ban and
|
|
160
|
+
* a night speed limit are both conditional and both apply.
|
|
161
|
+
*/
|
|
162
|
+
interface EdgeConditions {
|
|
163
|
+
/** Sorted by edge, then by kind; an edge may appear more than once. */
|
|
164
|
+
edges: Uint32Array;
|
|
165
|
+
/** What the value means: 0 is access, 1 is a speed limit in km/h. */
|
|
166
|
+
kinds: Uint8Array;
|
|
167
|
+
/** Index into `values`. */
|
|
168
|
+
rules: Uint16Array;
|
|
169
|
+
/** The deduplicated conditional values, as tagged. */
|
|
170
|
+
values: string[];
|
|
171
|
+
}
|
|
142
172
|
/**
|
|
143
173
|
* A tile's vehicle-independent half: everything a v7 `shared` chunk holds.
|
|
144
174
|
* It is not routable on its own — a profile supplies the durations.
|
|
@@ -154,6 +184,8 @@ interface ProfileChunk {
|
|
|
154
184
|
edgeAccess?: Uint8Array;
|
|
155
185
|
/** Signed limits for the few edges that state any; absent for vehicles whose size does not matter. */
|
|
156
186
|
edgeLimits?: EdgeLimits;
|
|
187
|
+
/** Conditional restrictions for the edges that carry one; absent when none do. */
|
|
188
|
+
edgeConditions?: EdgeConditions;
|
|
157
189
|
/**
|
|
158
190
|
* One bit per turn restriction the shared chunk holds, saying whether this
|
|
159
191
|
* vehicle obeys it. `except=hgv` lifts a restriction for lorries and not for
|
|
@@ -318,15 +350,76 @@ declare function componentsFor(graph: RoadGraph): Int32Array;
|
|
|
318
350
|
/** How many nodes carry each label, so the smaller piece can be recognised. */
|
|
319
351
|
declare function componentSizes(labels: Int32Array): Map<number, number>;
|
|
320
352
|
|
|
353
|
+
/**
|
|
354
|
+
* Roads the caller knows are shut.
|
|
355
|
+
*
|
|
356
|
+
* A compiled bundle is as current as the extract it came from: roadworks, a
|
|
357
|
+
* burst main, a festival closing the square are all things that happened
|
|
358
|
+
* after it was built, and nothing inside it can know about them. What it can
|
|
359
|
+
* do is let whoever does know say so at the time of asking.
|
|
360
|
+
*
|
|
361
|
+
* An area rather than a road, because a caller reading an incident feed has a
|
|
362
|
+
* place and a radius, not an edge number. Anything the circle touches is
|
|
363
|
+
* closed to the search and to snapping, exactly as a tagged restriction would
|
|
364
|
+
* be, so a route neither drives through a closure nor starts in the middle of
|
|
365
|
+
* one.
|
|
366
|
+
*/
|
|
367
|
+
|
|
368
|
+
/** A circle of road that cannot be driven, whatever the map says. */
|
|
369
|
+
type AvoidArea = {
|
|
370
|
+
lat: number;
|
|
371
|
+
lng: number;
|
|
372
|
+
/** How far the closure reaches from that point. */
|
|
373
|
+
radiusMeters: number;
|
|
374
|
+
};
|
|
375
|
+
/**
|
|
376
|
+
* Whether any part of this edge lies inside the circle.
|
|
377
|
+
*
|
|
378
|
+
* The whole of each segment counts, not only its ends: a motorway crossing a
|
|
379
|
+
* closed junction may have no shape point anywhere near it, and testing the
|
|
380
|
+
* ends alone would drive a route straight through.
|
|
381
|
+
*/
|
|
382
|
+
declare function touchesArea(graph: RoadGraph, edge: number, area: AvoidArea, centre?: Coordinate): boolean;
|
|
383
|
+
/**
|
|
384
|
+
* The access mask with every road the caller has closed cleared as well.
|
|
385
|
+
*
|
|
386
|
+
* Only the roads near each circle are looked at, so closing a junction costs
|
|
387
|
+
* the same whether the graph holds a town or a country.
|
|
388
|
+
*/
|
|
389
|
+
declare function accessAvoiding(graph: RoadGraph, areas: AvoidArea[] | undefined, base?: Uint8Array): Uint8Array | undefined;
|
|
390
|
+
/** How many roads these closures take away, for reporting rather than routing. */
|
|
391
|
+
declare function countAvoided(graph: RoadGraph, areas: AvoidArea[] | undefined): number;
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Reading a speed off an OSM tag.
|
|
395
|
+
*
|
|
396
|
+
* It lives on its own because both the profiles and the conditional
|
|
397
|
+
* restrictions need it, and a conditional limit is written in the same units
|
|
398
|
+
* as a plain one: `maxspeed:conditional = 30 mph @ (Mo-Fr 07:00-19:00)` means
|
|
399
|
+
* 30 mph, not 30 km/h.
|
|
400
|
+
*/
|
|
401
|
+
/** Kilometres per hour, or null when the value is not a speed this reads. */
|
|
402
|
+
declare function parseMaxSpeedKph(value: string | undefined): number | null;
|
|
403
|
+
|
|
321
404
|
/**
|
|
322
405
|
* Routing profiles turn raw OSM tags into routable facts: may a vehicle use
|
|
323
406
|
* this way, in which directions, and how fast. Keeping the rules behind one
|
|
324
407
|
* interface lets the compiler stay generic — it never inspects a tag itself —
|
|
325
408
|
* and lets the rules be unit-tested without a PBF file.
|
|
326
409
|
*/
|
|
410
|
+
|
|
327
411
|
type OsmTags = Record<string, string | undefined>;
|
|
328
412
|
/** How a profile may traverse one OSM way. */
|
|
329
413
|
type WayTraversal = {
|
|
414
|
+
/**
|
|
415
|
+
* Conditional restrictions tagged on the way, kept as written for the
|
|
416
|
+
* router to evaluate against a departure time. They apply to both
|
|
417
|
+
* directions: OSM states these per vehicle class, not per direction.
|
|
418
|
+
*/
|
|
419
|
+
conditions?: {
|
|
420
|
+
kind: number;
|
|
421
|
+
value: string;
|
|
422
|
+
}[];
|
|
330
423
|
/** Travel from the first node reference towards the last is allowed. */
|
|
331
424
|
forward: boolean;
|
|
332
425
|
/** Travel from the last node reference towards the first is allowed. */
|
|
@@ -398,13 +491,6 @@ interface RoutingProfile {
|
|
|
398
491
|
*/
|
|
399
492
|
evaluateBarrier?(tags: OsmTags): boolean;
|
|
400
493
|
}
|
|
401
|
-
/**
|
|
402
|
-
* Reads a `maxspeed`-style value. Returns null for every value that is not a
|
|
403
|
-
* plain number with an optional unit — country codes such as `PT:urban`,
|
|
404
|
-
* `none`, `signals` and `variable` included — so the caller can fall back to a
|
|
405
|
-
* class default instead of inventing a country-specific table.
|
|
406
|
-
*/
|
|
407
|
-
declare function parseMaxSpeedKph(value: string | undefined): number | null;
|
|
408
494
|
/**
|
|
409
495
|
* Reads a `maxheight`-style value in metres. Feet and inches are accepted
|
|
410
496
|
* because they are how the limit is written wherever it is signed that way;
|
|
@@ -535,6 +621,188 @@ declare function accessForVehicle(graph: RoadGraph, vehicle: VehicleDimensions |
|
|
|
535
621
|
/** How many edges this vehicle may not use, for reporting rather than routing. */
|
|
536
622
|
declare function countBlocked(graph: RoadGraph, vehicle: VehicleDimensions): number;
|
|
537
623
|
|
|
624
|
+
/**
|
|
625
|
+
* Conditional restrictions: `hgv:conditional = no @ (Mo-Fr 07:00-19:00)`.
|
|
626
|
+
*
|
|
627
|
+
* A road can be closed overnight, a square pedestrianised on Sundays, a bridge
|
|
628
|
+
* limited to 7.5 tonnes only for vehicles over a certain length. Until now
|
|
629
|
+
* every one of those read as permanently open, which is the limitation most
|
|
630
|
+
* likely to make a route wrong rather than merely longer.
|
|
631
|
+
*
|
|
632
|
+
* The value is a list of `value @ condition` pairs separated by semicolons,
|
|
633
|
+
* and where several match, OpenStreetMap says the **last** one wins — the
|
|
634
|
+
* convention being to write the general rule first and the specific one last.
|
|
635
|
+
*
|
|
636
|
+
* Not every condition can be answered. Weather, a driver's occupation and a
|
|
637
|
+
* stay duration are not things a compiled graph knows, and a rule resting on
|
|
638
|
+
* one is kept but marked, so a caller can count what was not understood
|
|
639
|
+
* instead of being told silently that a road is open.
|
|
640
|
+
*/
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* How many distinct conditional values one table can hold. The stored index
|
|
644
|
+
* is sixteen bits wide, so the values are numbered 0 to 65535.
|
|
645
|
+
*/
|
|
646
|
+
declare const MAX_STORED_VALUES = 65536;
|
|
647
|
+
/** When a journey passes, in the local time of the road it passes on. */
|
|
648
|
+
type TravelTime = {
|
|
649
|
+
/** 0 is Monday, 6 is Sunday. */
|
|
650
|
+
weekday: number;
|
|
651
|
+
/** Minutes since midnight, 0 to 1439. */
|
|
652
|
+
minutes: number;
|
|
653
|
+
/** 1 to 12, for a seasonal rule. */
|
|
654
|
+
month: number;
|
|
655
|
+
/**
|
|
656
|
+
* The day of the month, 1 to 31. Only a span running past midnight needs
|
|
657
|
+
* it, to know whether the morning it ends on began in the month before.
|
|
658
|
+
* Leaving it out treats such a morning as belonging to the current month,
|
|
659
|
+
* which is right on every day but the first.
|
|
660
|
+
*/
|
|
661
|
+
dayOfMonth?: number;
|
|
662
|
+
/** Whether it is a public holiday there, which only a caller can know. */
|
|
663
|
+
publicHoliday?: boolean;
|
|
664
|
+
};
|
|
665
|
+
/** A span of minutes within a day, which may run past midnight. */
|
|
666
|
+
type MinuteSpan = {
|
|
667
|
+
from: number;
|
|
668
|
+
to: number;
|
|
669
|
+
};
|
|
670
|
+
/** An inclusive range of weekdays, months, or anything else counted in order. */
|
|
671
|
+
type Range = {
|
|
672
|
+
from: number;
|
|
673
|
+
to: number;
|
|
674
|
+
};
|
|
675
|
+
/** A measurement of the vehicle compared against a number, as `weight>7.5`. */
|
|
676
|
+
type VehicleComparison = {
|
|
677
|
+
property: "weight" | "height" | "width" | "length";
|
|
678
|
+
operator: "<" | "<=" | ">" | ">=" | "=";
|
|
679
|
+
amount: number;
|
|
680
|
+
};
|
|
681
|
+
/** One `(...)` group: every part present must hold for the group to match. */
|
|
682
|
+
type Condition = {
|
|
683
|
+
days?: Range[];
|
|
684
|
+
times?: MinuteSpan[];
|
|
685
|
+
months?: Range[];
|
|
686
|
+
publicHoliday?: boolean;
|
|
687
|
+
vehicle?: VehicleComparison[];
|
|
688
|
+
/**
|
|
689
|
+
* Circumstances this library cannot know by itself: the weather, who is
|
|
690
|
+
* driving, what for. They are read from the tag and answered only by a
|
|
691
|
+
* caller who says so; unanswered, the condition does not hold.
|
|
692
|
+
*/
|
|
693
|
+
circumstances?: string[];
|
|
694
|
+
/**
|
|
695
|
+
* The part of the condition this parser could not read at all — a stay
|
|
696
|
+
* duration, a form of words nobody has taught it. A condition carrying one
|
|
697
|
+
* is never matched, and is counted so it can be reported rather than
|
|
698
|
+
* quietly ignored.
|
|
699
|
+
*/
|
|
700
|
+
unreadable?: string;
|
|
701
|
+
};
|
|
702
|
+
/**
|
|
703
|
+
* What the caller knows that the map does not: whether it is raining, who is
|
|
704
|
+
* at the wheel, what the journey is for. A conditional rule resting on one of
|
|
705
|
+
* these is ignored unless the answer is given here.
|
|
706
|
+
*/
|
|
707
|
+
type Circumstances = {
|
|
708
|
+
/** Named states of the road or sky, such as `wet`, `snow`, `ice`. */
|
|
709
|
+
conditions?: string[];
|
|
710
|
+
/** Who is driving, such as `disabled`, `resident`, `emergency`. */
|
|
711
|
+
userGroups?: string[];
|
|
712
|
+
/** Why, such as `delivery`, `destination`, `agricultural`. */
|
|
713
|
+
purposes?: string[];
|
|
714
|
+
};
|
|
715
|
+
type ConditionalRule = {
|
|
716
|
+
/** What applies when the condition holds: `no`, `destination`, `30`, `7.5`. */
|
|
717
|
+
value: string;
|
|
718
|
+
/** Any of these matching makes the rule apply, as `Mo-Fr 07:00-19:00, Sa 08:00-12:00`. */
|
|
719
|
+
conditions: Condition[];
|
|
720
|
+
};
|
|
721
|
+
/**
|
|
722
|
+
* Reads a `*:conditional` value into its rules. An empty list means the value
|
|
723
|
+
* was not a conditional expression at all.
|
|
724
|
+
*/
|
|
725
|
+
declare function parseConditional(value: string | undefined): ConditionalRule[];
|
|
726
|
+
/** Whether one condition group holds at this moment, for this vehicle. */
|
|
727
|
+
declare function conditionHolds(condition: Condition, when: TravelTime, vehicle?: VehicleDimensions, circumstances?: Circumstances): boolean;
|
|
728
|
+
/**
|
|
729
|
+
* What a conditional value comes to at this moment, or null when none of its
|
|
730
|
+
* rules applies. Where several match, the last wins, which is what
|
|
731
|
+
* OpenStreetMap says and why the convention is general first, specific last.
|
|
732
|
+
*/
|
|
733
|
+
declare function conditionalValue(rules: ConditionalRule[], when: TravelTime, vehicle?: VehicleDimensions, circumstances?: Circumstances): string | null;
|
|
734
|
+
/**
|
|
735
|
+
* How many of these rules rest on something this parser cannot read at all.
|
|
736
|
+
* A rule resting on the weather or on who is driving is readable and is not
|
|
737
|
+
* counted here; it simply needs a caller to answer it.
|
|
738
|
+
*/
|
|
739
|
+
declare function unreadableConditions(rules: ConditionalRule[]): number;
|
|
740
|
+
/**
|
|
741
|
+
* The moment a journey is travelled.
|
|
742
|
+
*
|
|
743
|
+
* Without a time zone the date is read as the machine reads it, which is
|
|
744
|
+
* right when the roads and the reader are in the same place and wrong by
|
|
745
|
+
* however many hours when they are not. Naming the zone the roads are in —
|
|
746
|
+
* `"Europe/Lisbon"` — reads the date there instead, which is what a
|
|
747
|
+
* restriction written in local time means.
|
|
748
|
+
*
|
|
749
|
+
* The zone names are the IANA ones the platform already knows; nothing is
|
|
750
|
+
* bundled for this.
|
|
751
|
+
*/
|
|
752
|
+
declare function travelTimeFrom(date: Date, publicHoliday?: boolean, timeZone?: string): TravelTime;
|
|
753
|
+
/** What a stored conditional row says: an access rule or a speed limit. */
|
|
754
|
+
declare const ConditionKind: {
|
|
755
|
+
readonly access: 0;
|
|
756
|
+
readonly maxspeed: 1;
|
|
757
|
+
};
|
|
758
|
+
/** Collects what a compiler found into the stored side table. */
|
|
759
|
+
declare function packEdgeConditions(entries: {
|
|
760
|
+
edge: number;
|
|
761
|
+
kind: number;
|
|
762
|
+
value: string;
|
|
763
|
+
}[]): EdgeConditions | undefined;
|
|
764
|
+
/** A bundle's conditional values parsed once, rather than per edge per search. */
|
|
765
|
+
type ParsedConditions = {
|
|
766
|
+
table: EdgeConditions;
|
|
767
|
+
parsed: ConditionalRule[][];
|
|
768
|
+
};
|
|
769
|
+
declare function parseEdgeConditions(table: EdgeConditions | undefined): ParsedConditions | undefined;
|
|
770
|
+
/**
|
|
771
|
+
* What the conditional rules say about one edge at one moment: whether it is
|
|
772
|
+
* closed, and any speed limit that applies.
|
|
773
|
+
*
|
|
774
|
+
* `destination` and the permit-style values count as closed because this
|
|
775
|
+
* library has no notion of a journey's purpose, and treating "only if you live
|
|
776
|
+
* here" as open would route strangers down a residents' street.
|
|
777
|
+
*/
|
|
778
|
+
declare function conditionsOnEdge(conditions: ParsedConditions, edge: number, when: TravelTime, vehicle?: VehicleDimensions, circumstances?: Circumstances): {
|
|
779
|
+
closed: boolean;
|
|
780
|
+
speedKph: number | undefined;
|
|
781
|
+
};
|
|
782
|
+
/**
|
|
783
|
+
* The access mask for a departure time: the graph's own with the roads shut at
|
|
784
|
+
* that moment cleared as well.
|
|
785
|
+
*
|
|
786
|
+
* Only closures are applied. A road whose plain tags already forbid it stays
|
|
787
|
+
* forbidden even where a conditional value would open it, because the stored
|
|
788
|
+
* mask has already dropped it and reopening one would need the compiler to
|
|
789
|
+
* keep roads it currently discards. That errs towards refusing a road that is
|
|
790
|
+
* in fact usable, which is the direction this library errs in everywhere else.
|
|
791
|
+
*/
|
|
792
|
+
declare function accessAtTime(graph: Pick<RoadGraph, "edgeTargets" | "edgeAccess">, conditions: ParsedConditions | undefined, when: TravelTime | undefined, vehicle?: VehicleDimensions, base?: Uint8Array, circumstances?: Circumstances): Uint8Array | undefined;
|
|
793
|
+
/** How many edges this moment closes, for reporting rather than routing. */
|
|
794
|
+
declare function countClosedAt(graph: Pick<RoadGraph, "edgeTargets" | "edgeAccess">, conditions: ParsedConditions | undefined, when: TravelTime, vehicle?: VehicleDimensions): number;
|
|
795
|
+
declare function conditionsOf(graph: Pick<RoadGraph, "edgeConditions">): ParsedConditions | undefined;
|
|
796
|
+
/**
|
|
797
|
+
* The edges a conditional speed limit slows at this moment, as whole seconds.
|
|
798
|
+
*
|
|
799
|
+
* A conditional limit may only slow an edge, never speed it up. A faster
|
|
800
|
+
* stored duration is left alone, because the A* bound is built from the
|
|
801
|
+
* profile's ceiling and an edge quicker than the graph says would break the
|
|
802
|
+
* guarantee that the route found is the best one.
|
|
803
|
+
*/
|
|
804
|
+
declare function conditionalDurations(graph: Pick<RoadGraph, "edgeTargets" | "edgeDistancesMeters" | "edgeDistanceScale" | "edgeDurationsSeconds" | "edgeDurationScale">, conditions: ParsedConditions | undefined, when: TravelTime, vehicle?: VehicleDimensions, circumstances?: Circumstances): Map<number, number> | undefined;
|
|
805
|
+
|
|
538
806
|
/**
|
|
539
807
|
* The nearest routing node to a coordinate. After topology simplification a
|
|
540
808
|
* node is a junction rather than an arbitrary point on a road, so on a long
|
|
@@ -555,74 +823,130 @@ type RouteOptions = {
|
|
|
555
823
|
* is too large or too heavy for are closed to the search and to snapping.
|
|
556
824
|
*/
|
|
557
825
|
vehicle?: VehicleDimensions;
|
|
826
|
+
/**
|
|
827
|
+
* When the journey starts, in the local time of the roads being travelled.
|
|
828
|
+
*
|
|
829
|
+
* Leaving it out ignores every conditional restriction, which is what this
|
|
830
|
+
* library did before it could read them: a road closed only at certain hours
|
|
831
|
+
* counts as open. Supplying it closes the roads shut at that moment and
|
|
832
|
+
* slows the ones a conditional speed limit slows.
|
|
833
|
+
*
|
|
834
|
+
* One moment is used for the whole route rather than an arrival time per
|
|
835
|
+
* edge. A route crossing a boundary as a restriction begins is therefore
|
|
836
|
+
* judged by where it set out, which is the honest limit of a departure time.
|
|
837
|
+
*/
|
|
838
|
+
departAt?: Date | TravelTime;
|
|
839
|
+
/** Whether that day is a public holiday, which only a caller can know. */
|
|
840
|
+
publicHoliday?: boolean;
|
|
841
|
+
/**
|
|
842
|
+
* The time zone the roads are in, as an IANA name such as
|
|
843
|
+
* `"Europe/Lisbon"`. A restriction is written in the local time of the road
|
|
844
|
+
* it is on, so a caller routing somewhere other than where it is running
|
|
845
|
+
* should say where. Left out, a `Date` is read as this machine reads it.
|
|
846
|
+
*/
|
|
847
|
+
timeZone?: string;
|
|
848
|
+
/**
|
|
849
|
+
* What the map cannot know: whether it is raining, who is driving, what the
|
|
850
|
+
* journey is for. A conditional rule resting on one of these is ignored
|
|
851
|
+
* unless it is answered here, so a road shut `@ (wet)` stays open until a
|
|
852
|
+
* caller says it is wet.
|
|
853
|
+
*/
|
|
854
|
+
circumstances?: Circumstances;
|
|
855
|
+
/**
|
|
856
|
+
* Roads the caller knows are shut — roadworks, an incident, an event. A
|
|
857
|
+
* compiled bundle cannot know about any of them; whoever is reading a feed
|
|
858
|
+
* of them can say so here, and the search will neither drive through a
|
|
859
|
+
* closure nor begin in the middle of one.
|
|
860
|
+
*/
|
|
861
|
+
avoid?: AvoidArea[];
|
|
862
|
+
/**
|
|
863
|
+
* Multipliers making certain edges dearer to the search than they really
|
|
864
|
+
* are, used to push a search away from a route already found. The route
|
|
865
|
+
* reported back is always priced at the graph's own cost, so a penalty
|
|
866
|
+
* changes which roads are chosen and never what they are said to cost.
|
|
867
|
+
*/
|
|
868
|
+
costPenalties?: ReadonlyMap<number, number>;
|
|
869
|
+
/**
|
|
870
|
+
* Whether a route that cannot reach the road nearest its destination may
|
|
871
|
+
* finish on one a little further away. On by default, because the nearest
|
|
872
|
+
* road is sometimes one the network cannot legally enter — a pocket of
|
|
873
|
+
* one-way streets behind banned turns, an island of service roads — and
|
|
874
|
+
* refusing to route at all is a worse answer than finishing nearby.
|
|
875
|
+
*
|
|
876
|
+
* Turn it off to be told plainly that the point asked for cannot be
|
|
877
|
+
* reached. `RouteResult.destinationSnap.distanceMeters` reports how far
|
|
878
|
+
* short a route finished either way.
|
|
879
|
+
*/
|
|
880
|
+
finishOnANearbyRoad?: boolean;
|
|
558
881
|
};
|
|
559
882
|
declare function route(graph: RoadGraph, from: Coordinate, to: Coordinate, preference?: RoutePreference, options?: RouteOptions): RouteResult;
|
|
560
883
|
|
|
561
|
-
/** Where a coordinate lands on one directed edge. */
|
|
562
|
-
type EdgeProjection = {
|
|
563
|
-
edge: number;
|
|
564
|
-
source: number;
|
|
565
|
-
target: number;
|
|
566
|
-
/** How far along the edge the projection sits, 0 at the source and 1 at the target. */
|
|
567
|
-
fraction: number;
|
|
568
|
-
/** The point on the road itself. */
|
|
569
|
-
point: Coordinate;
|
|
570
|
-
/** Distance from the queried coordinate to that point. */
|
|
571
|
-
distanceMeters: number;
|
|
572
|
-
/** Index of the polyline vertex the projection follows, for slicing geometry. */
|
|
573
|
-
vertexIndex: number;
|
|
574
|
-
polyline: Coordinate[];
|
|
575
|
-
};
|
|
576
884
|
/**
|
|
577
|
-
*
|
|
578
|
-
*
|
|
579
|
-
*
|
|
580
|
-
*
|
|
885
|
+
* Several ways to get there, not just the best one.
|
|
886
|
+
*
|
|
887
|
+
* A second route is only worth offering if it is genuinely different and not
|
|
888
|
+
* much worse. The method here is the simple one: find the best route, make the
|
|
889
|
+
* roads it used dearer to the search than they really are, and search again.
|
|
890
|
+
* A road that is the only sensible way through survives the penalty and is
|
|
891
|
+
* used again; one that was merely convenient gives way to its neighbour.
|
|
892
|
+
*
|
|
893
|
+
* The penalty never reaches the answer. A route is always reported at the
|
|
894
|
+
* graph's own cost, so an alternative's distance and duration are what it
|
|
895
|
+
* would really take, not what the search was told to believe.
|
|
896
|
+
*
|
|
897
|
+
* Candidates are then filtered rather than trusted: one that reuses most of a
|
|
898
|
+
* route already offered, or that is far worse than the best, is not an
|
|
899
|
+
* alternative anybody wants. What comes back is in order, best first.
|
|
581
900
|
*/
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
901
|
+
|
|
902
|
+
type AlternativeRoutesOptions = Omit<RouteOptions, "costPenalties" | "costBound"> & {
|
|
903
|
+
/** How many routes to return at most, the best one included. Default 3. */
|
|
904
|
+
count?: number;
|
|
905
|
+
/**
|
|
906
|
+
* How much worse than the best route an alternative may be. 1.4 allows one
|
|
907
|
+
* taking 40% longer; raising it offers more routes and worse ones.
|
|
908
|
+
*/
|
|
909
|
+
maxStretch?: number;
|
|
910
|
+
/**
|
|
911
|
+
* How much of the routes already offered an alternative may reuse, measured
|
|
912
|
+
* by distance. 0.75 rejects one that is three-quarters the same road.
|
|
913
|
+
*/
|
|
914
|
+
maxSharing?: number;
|
|
915
|
+
/**
|
|
916
|
+
* How much dearer a road already used is made to look. Too small and the
|
|
917
|
+
* search returns the same route again; too large and it flees onto
|
|
918
|
+
* absurdities. Default 2.
|
|
919
|
+
*/
|
|
920
|
+
penaltyFactor?: number;
|
|
921
|
+
/**
|
|
922
|
+
* Whether to download the wider corridor an alternative might lie in.
|
|
923
|
+
*
|
|
924
|
+
* On by default, because an alternative is allowed to be worse than the
|
|
925
|
+
* best by `maxStretch` and the tiles holding one therefore reach further
|
|
926
|
+
* than the tiles that proved the best route. On a long journey that is
|
|
927
|
+
* about three megabytes more map. Turning it off keeps the download to
|
|
928
|
+
* what one route needed and offers only the alternatives already inside
|
|
929
|
+
* it, which on a dense network is usually most of them.
|
|
930
|
+
*/
|
|
931
|
+
searchWiderCorridor?: boolean;
|
|
592
932
|
};
|
|
593
933
|
/**
|
|
594
|
-
*
|
|
595
|
-
*
|
|
596
|
-
*
|
|
934
|
+
* Rejects options that would make the search unbounded or meaningless.
|
|
935
|
+
*
|
|
936
|
+
* Exported so the public entry point can refuse them before it downloads
|
|
937
|
+
* anything: a caller who passed `count: NaN` should be told so, not billed
|
|
938
|
+
* for a corridor first.
|
|
597
939
|
*/
|
|
598
|
-
declare function
|
|
599
|
-
|
|
940
|
+
declare function checkAlternativeOptions(options: AlternativeRoutesOptions): void;
|
|
600
941
|
/**
|
|
601
|
-
*
|
|
602
|
-
*
|
|
603
|
-
* for a kilometre without a node, so a node-only index cannot answer "which
|
|
604
|
-
* road am I standing on".
|
|
942
|
+
* Routes from one point to another, best first, with up to `count - 1`
|
|
943
|
+
* genuinely different alternatives after it.
|
|
605
944
|
*
|
|
606
|
-
*
|
|
607
|
-
*
|
|
945
|
+
* Returns at least the best route; fewer than `count` means the graph held
|
|
946
|
+
* nothing else worth offering, which is the usual answer on a road network
|
|
947
|
+
* with one obvious way through.
|
|
608
948
|
*/
|
|
609
|
-
|
|
610
|
-
cellSizeDegrees: number;
|
|
611
|
-
cells: Map<string, Uint32Array>;
|
|
612
|
-
/** Edges whose extent covers too many cells to list individually. */
|
|
613
|
-
oversized: Uint32Array;
|
|
614
|
-
};
|
|
615
|
-
/** Recovers an edge's source node from the CSR offsets. */
|
|
616
|
-
declare function edgeSource(graph: RoadGraph, edge: number): number;
|
|
617
|
-
/** The full vertex list of a directed edge: source node, shape points, target node. */
|
|
618
|
-
declare function edgePolyline(graph: RoadGraph, edge: number, source?: number): Coordinate[];
|
|
619
|
-
declare function createEdgeSpatialIndex(graph: RoadGraph, cellSizeDegrees?: number): EdgeSpatialIndex;
|
|
620
|
-
declare function edgeSpatialIndexFor(graph: RoadGraph, cellSizeDegrees?: number): EdgeSpatialIndex;
|
|
621
|
-
declare function nearbyEdgeIds(index: EdgeSpatialIndex, coordinate: Coordinate, maxDistanceMeters: number): Set<number>;
|
|
622
|
-
|
|
623
|
-
/** Builds a uniform-grid index. It can be created after decoding without changing the graph format. */
|
|
624
|
-
declare function createSpatialIndex(graph: RoadGraph, cellSizeDegrees?: number): NodeSpatialIndex;
|
|
625
|
-
declare function withSpatialIndex(graph: RoadGraph, cellSizeDegrees?: number): RoadGraph;
|
|
949
|
+
declare function routeAlternatives(graph: RoadGraph, from: Coordinate, to: Coordinate, preference?: RoutePreference, options?: AlternativeRoutesOptions): RouteResult[];
|
|
626
950
|
|
|
627
951
|
type FetchLike$2 = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
|
628
952
|
/**
|
|
@@ -653,6 +977,8 @@ type RoadRouterOptions = {
|
|
|
653
977
|
* High-level route entry point. `open()` accepts an EFRB bundle, an EFRT
|
|
654
978
|
* manifest, or an already-decoded graph.
|
|
655
979
|
*/
|
|
980
|
+
/** When a journey starts, for the conditional restrictions that depend on it. */
|
|
981
|
+
type DepartureOptions = Pick<RouteOptions, "departAt" | "publicHoliday" | "timeZone" | "circumstances" | "avoid">;
|
|
656
982
|
declare class RoadRouter {
|
|
657
983
|
private readonly graph?;
|
|
658
984
|
private readonly loader?;
|
|
@@ -685,7 +1011,12 @@ declare class RoadRouter {
|
|
|
685
1011
|
* network once: switching vehicle costs only the small per-vehicle chunks.
|
|
686
1012
|
*/
|
|
687
1013
|
withProfile(name: string): RoadRouter;
|
|
688
|
-
|
|
1014
|
+
/**
|
|
1015
|
+
* `when` says when the journey starts, so conditional restrictions apply.
|
|
1016
|
+
* Leaving it out ignores them, which is how this library behaved before it
|
|
1017
|
+
* could read them.
|
|
1018
|
+
*/
|
|
1019
|
+
route(from: Coordinate, to: Coordinate, preference?: RoutePreference, when?: DepartureOptions): Promise<RouteResult>;
|
|
689
1020
|
/**
|
|
690
1021
|
* Downloads a corridor, routes, then asks whether any tile left out could
|
|
691
1022
|
* still hold something better. A route through a tile costs at least the
|
|
@@ -695,10 +1026,93 @@ declare class RoadRouter {
|
|
|
695
1026
|
* graph contains. Because the test measures ground distance rather than
|
|
696
1027
|
* counting neighbours, the answer does not depend on the tile size.
|
|
697
1028
|
*/
|
|
1029
|
+
/**
|
|
1030
|
+
* Several ways there, best first, with up to `count - 1` alternatives after
|
|
1031
|
+
* it. Fewer than asked for means the network held nothing else worth
|
|
1032
|
+
* offering, which is the usual answer where there is one obvious way.
|
|
1033
|
+
*
|
|
1034
|
+
* Over a bundle this downloads a wider corridor than a single route needs:
|
|
1035
|
+
* an alternative may be worse than the best by as much as `maxStretch`, and
|
|
1036
|
+
* the tiles holding it lie outside the corridor that proved the best route.
|
|
1037
|
+
*/
|
|
1038
|
+
routeAlternatives(from: Coordinate, to: Coordinate, preference?: RoutePreference, options?: AlternativeRoutesOptions): Promise<RouteResult[]>;
|
|
698
1039
|
private routeOverBundle;
|
|
1040
|
+
/**
|
|
1041
|
+
* The same corridor walk, stopping with the graph it settled on as well as
|
|
1042
|
+
* the route. Alternatives need the graph, and need to be able to widen it
|
|
1043
|
+
* once more: a second route may be worse than the best by more than the
|
|
1044
|
+
* corridor was ever sized to hold.
|
|
1045
|
+
*/
|
|
1046
|
+
private bestOverBundle;
|
|
699
1047
|
private routeOverLoader;
|
|
700
1048
|
}
|
|
701
1049
|
|
|
1050
|
+
/** Where a coordinate lands on one directed edge. */
|
|
1051
|
+
type EdgeProjection = {
|
|
1052
|
+
edge: number;
|
|
1053
|
+
source: number;
|
|
1054
|
+
target: number;
|
|
1055
|
+
/** How far along the edge the projection sits, 0 at the source and 1 at the target. */
|
|
1056
|
+
fraction: number;
|
|
1057
|
+
/** The point on the road itself. */
|
|
1058
|
+
point: Coordinate;
|
|
1059
|
+
/** Distance from the queried coordinate to that point. */
|
|
1060
|
+
distanceMeters: number;
|
|
1061
|
+
/** Index of the polyline vertex the projection follows, for slicing geometry. */
|
|
1062
|
+
vertexIndex: number;
|
|
1063
|
+
polyline: Coordinate[];
|
|
1064
|
+
};
|
|
1065
|
+
/**
|
|
1066
|
+
* Snapping a coordinate onto the graph. A `node` snap behaves exactly as this
|
|
1067
|
+
* package always has; an `edge` snap carries one projection per directed edge
|
|
1068
|
+
* covering the same stretch of road, so a two-way road offers both directions
|
|
1069
|
+
* and a one-way road offers only the legal one.
|
|
1070
|
+
*/
|
|
1071
|
+
type GraphSnap = {
|
|
1072
|
+
kind: "node";
|
|
1073
|
+
node: number;
|
|
1074
|
+
point: Coordinate;
|
|
1075
|
+
distanceMeters: number;
|
|
1076
|
+
} | {
|
|
1077
|
+
kind: "edge";
|
|
1078
|
+
projections: EdgeProjection[];
|
|
1079
|
+
point: Coordinate;
|
|
1080
|
+
distanceMeters: number;
|
|
1081
|
+
};
|
|
1082
|
+
/**
|
|
1083
|
+
* Finds the road nearest to a coordinate. Returns null when nothing routable
|
|
1084
|
+
* lies within `maxDistanceMeters` of the coordinate — measured to the road
|
|
1085
|
+
* surface, not to the nearest junction.
|
|
1086
|
+
*/
|
|
1087
|
+
declare function snapToGraph(graph: RoadGraph, coordinate: Coordinate, maxDistanceMeters?: number, access?: Uint8Array | undefined, accept?: (node: number) => boolean, everyNearbyRoad?: boolean): GraphSnap | null;
|
|
1088
|
+
|
|
1089
|
+
/**
|
|
1090
|
+
* A uniform-grid index over directed edges. Snapping needs the nearest *road*,
|
|
1091
|
+
* not the nearest junction: after topology simplification a rural edge can run
|
|
1092
|
+
* for a kilometre without a node, so a node-only index cannot answer "which
|
|
1093
|
+
* road am I standing on".
|
|
1094
|
+
*
|
|
1095
|
+
* Each edge is registered in every cell its bounding box touches, which keeps
|
|
1096
|
+
* construction linear and lookups to a handful of cells.
|
|
1097
|
+
*/
|
|
1098
|
+
type EdgeSpatialIndex = {
|
|
1099
|
+
cellSizeDegrees: number;
|
|
1100
|
+
cells: Map<string, Uint32Array>;
|
|
1101
|
+
/** Edges whose extent covers too many cells to list individually. */
|
|
1102
|
+
oversized: Uint32Array;
|
|
1103
|
+
};
|
|
1104
|
+
/** Recovers an edge's source node from the CSR offsets. */
|
|
1105
|
+
declare function edgeSource(graph: RoadGraph, edge: number): number;
|
|
1106
|
+
/** The full vertex list of a directed edge: source node, shape points, target node. */
|
|
1107
|
+
declare function edgePolyline(graph: RoadGraph, edge: number, source?: number): Coordinate[];
|
|
1108
|
+
declare function createEdgeSpatialIndex(graph: RoadGraph, cellSizeDegrees?: number): EdgeSpatialIndex;
|
|
1109
|
+
declare function edgeSpatialIndexFor(graph: RoadGraph, cellSizeDegrees?: number): EdgeSpatialIndex;
|
|
1110
|
+
declare function nearbyEdgeIds(index: EdgeSpatialIndex, coordinate: Coordinate, maxDistanceMeters: number): Set<number>;
|
|
1111
|
+
|
|
1112
|
+
/** Builds a uniform-grid index. It can be created after decoding without changing the graph format. */
|
|
1113
|
+
declare function createSpatialIndex(graph: RoadGraph, cellSizeDegrees?: number): NodeSpatialIndex;
|
|
1114
|
+
declare function withSpatialIndex(graph: RoadGraph, cellSizeDegrees?: number): RoadGraph;
|
|
1115
|
+
|
|
702
1116
|
declare const BundleCompression: {
|
|
703
1117
|
readonly none: 0;
|
|
704
1118
|
readonly gzip: 1;
|
|
@@ -938,4 +1352,4 @@ type GuardedJunctions = {
|
|
|
938
1352
|
};
|
|
939
1353
|
declare function guardedJunctionsFor(graph: RoadGraph, restrictions: TurnRestrictionIndex | null, sequences: TurnSequenceIndex | null): GuardedJunctions;
|
|
940
1354
|
|
|
941
|
-
export { type BundleBounds, type BundleChunkRef, BundleCompression, type BundleEncodeOptions, type BundleGraphTile, type BundleOpenOptions, type BundleProfiledTile, type BundleTile, type CompactEncodeOptions, type CompactGraphOptions, type Coordinate, type CoordinateStorage, DEFAULT_VEHICLE_PRESET, type EdgeLimits, type EdgeProjection, type EdgeSpatialIndex, type EdgeWeightStorage, type GeoJsonLineString, type GeoJsonPosition, type GraphBounds, type GraphSnap, type GraphTile, type GuardedJunctions, type NodeSpatialIndex, type OsmTags, type ParsedTurnRestriction, type ProfileChunk, ProfileId, type RoadGraph, type RoadGraphBundle, RoadRouter, type RoadRouterOptions, type RouteGraphLoader, type RouteGraphManifest, type RouteOptions, type RoutePreference, type RouteResult, type RouteSnap, RouterError, type RouterErrorCode, type RoutingProfile, type SearchBounds, type SharedRoadGraph, type TurnRestrictionIndex, type TurnRestrictionKind, type TurnSequenceIndex, VEHICLE_PRESETS, VarintReader, VarintWriter, type VehicleDimensions, type VehicleInput, type VehicleLimits, VehiclePresetId, type WayTraversal, accessForVehicle, accessMaskFor, allowsEverything, buildTurnRestrictionIndex, buildTurnSequenceIndex, carRoutingProfile, combineProfiledGraph, compactGraph, componentSizes, componentsFor, countBlocked, createEdgeSpatialIndex, createRouteGraphLoader, createSpatialIndex, decodeGraph, decodeProfileChunk, decodeSharedGraph, distanceToBounds, edgeAllowed, edgePolyline, edgeSource, edgeSpatialIndexFor, encodeCompactGraph, encodeCompressedRoadGraphBundle, encodeGraph, encodeProfileChunk, encodeProfiledRoadGraphBundle, encodeRoadGraphBundle, encodeSharedGraph, findNearestNode, fromDecimetres, fromHalfTonnes, getRoutingProfile, getRoutingProfileById, guardedJunctionsFor, isTurnBanned, maxSpeedMpsFor, mergeRoadGraphs, motorcycleRoutingProfile, nearbyEdgeIds, openRoadGraphBundle, packEdgeLimits, packTurnRestrictions, packTurnSequences, parseLengthMeters, parseMaxSpeedKph, parseWeightTonnes, profileOf, resolveVehicle, route, routingProfiles, searchBoundsFor, snapToGraph, straightLineAtMost, toDecimetres, toHalfTonnes, truckRoutingProfile, unzigzag, vehiclePreset, vehiclePresetName, withSpatialIndex, zigzag };
|
|
1355
|
+
export { type AlternativeRoutesOptions, type AvoidArea, type BundleBounds, type BundleChunkRef, BundleCompression, type BundleEncodeOptions, type BundleGraphTile, type BundleOpenOptions, type BundleProfiledTile, type BundleTile, type Circumstances, type CompactEncodeOptions, type CompactGraphOptions, type Condition, ConditionKind, type ConditionalRule, type Coordinate, type CoordinateStorage, DEFAULT_VEHICLE_PRESET, type DepartureOptions, type EdgeConditions, type EdgeLimits, type EdgeProjection, type EdgeSpatialIndex, type EdgeWeightStorage, type GeoJsonLineString, type GeoJsonPosition, type GraphBounds, type GraphSnap, type GraphTile, type GuardedJunctions, MAX_STORED_VALUES, type MinuteSpan, type NodeSpatialIndex, type OsmTags, type ParsedConditions, type ParsedTurnRestriction, type ProfileChunk, ProfileId, type RoadGraph, type RoadGraphBundle, RoadRouter, type RoadRouterOptions, type RouteGraphLoader, type RouteGraphManifest, type RouteOptions, type RoutePreference, type RouteResult, type RouteSnap, RouterError, type RouterErrorCode, type RoutingProfile, type SearchBounds, type SharedRoadGraph, type TravelTime, type TurnRestrictionIndex, type TurnRestrictionKind, type TurnSequenceIndex, VEHICLE_PRESETS, VarintReader, VarintWriter, type VehicleComparison, type VehicleDimensions, type VehicleInput, type VehicleLimits, VehiclePresetId, type WayTraversal, accessAtTime, accessAvoiding, accessForVehicle, accessMaskFor, allowsEverything, buildTurnRestrictionIndex, buildTurnSequenceIndex, carRoutingProfile, checkAlternativeOptions, combineProfiledGraph, compactGraph, componentSizes, componentsFor, conditionHolds, conditionalDurations, conditionalValue, conditionsOf, conditionsOnEdge, countAvoided, countBlocked, countClosedAt, createEdgeSpatialIndex, createRouteGraphLoader, createSpatialIndex, decodeGraph, decodeProfileChunk, decodeSharedGraph, distanceToBounds, edgeAllowed, edgePolyline, edgeSource, edgeSpatialIndexFor, encodeCompactGraph, encodeCompressedRoadGraphBundle, encodeGraph, encodeProfileChunk, encodeProfiledRoadGraphBundle, encodeRoadGraphBundle, encodeSharedGraph, findNearestNode, fromDecimetres, fromHalfTonnes, getRoutingProfile, getRoutingProfileById, guardedJunctionsFor, isTurnBanned, maxSpeedMpsFor, mergeRoadGraphs, motorcycleRoutingProfile, nearbyEdgeIds, openRoadGraphBundle, packEdgeConditions, packEdgeLimits, packTurnRestrictions, packTurnSequences, parseConditional, parseEdgeConditions, parseLengthMeters, parseMaxSpeedKph, parseWeightTonnes, profileOf, resolveVehicle, route, routeAlternatives, routingProfiles, searchBoundsFor, snapToGraph, straightLineAtMost, toDecimetres, toHalfTonnes, touchesArea, travelTimeFrom, truckRoutingProfile, unreadableConditions, unzigzag, vehiclePreset, vehiclePresetName, withSpatialIndex, zigzag };
|