@osm-editor-kit/osm-way-chain 0.1.0-alpha.0 → 0.1.0-alpha.2
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 +26 -12
- package/dist/highway-filter.d.ts +22 -16
- package/dist/index.d.ts +2 -1
- package/dist/index.js +129 -13
- package/dist/way-selection-policy.d.ts +64 -0
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
# `@osm-editor-kit/osm-way-chain`
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> [!NOTE]
|
|
4
|
+
> This package is an **alpha** release and still under active development. APIs may change; install with the npm `alpha` dist-tag.
|
|
4
5
|
|
|
5
6
|
## What it does
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
- Walk connected highway ways left and right from a center segment
|
|
9
|
+
- Rank neighbor candidates (same road kind, name, ref)
|
|
10
|
+
- Flag junctions where more than one neighbor is equally good
|
|
11
|
+
- Flip geometry and directional tags when a way is digitized the “wrong” way
|
|
12
|
+
- Compile and match **app-owned** way-selection policies (Overpass + in-memory tags)
|
|
13
|
+
- Adapter for in-memory session data from `@osm-editor-kit/osm-data`
|
|
10
14
|
|
|
11
15
|
## Usage
|
|
12
16
|
|
|
@@ -14,11 +18,21 @@ Includes `mirrorTags` for flipping digitization direction (left/right, forward/b
|
|
|
14
18
|
import type { ParsedOsmData } from '@osm-editor-kit/osm-data'
|
|
15
19
|
import {
|
|
16
20
|
buildChain,
|
|
21
|
+
buildWaysOverpassQuery,
|
|
17
22
|
createSessionGraphAdapter,
|
|
18
|
-
|
|
19
|
-
|
|
23
|
+
matchesOsmWaySelectionSegment,
|
|
24
|
+
tag,
|
|
25
|
+
type OsmWaySelectionPolicy,
|
|
20
26
|
} from '@osm-editor-kit/osm-way-chain'
|
|
21
27
|
|
|
28
|
+
/** App-owned contract — which ways to download / chain. Not package defaults. */
|
|
29
|
+
const wayPolicy: OsmWaySelectionPolicy = {
|
|
30
|
+
include: [
|
|
31
|
+
{ all: [tag.oneOf('highway', ['residential', 'cycleway', 'path', 'footway', 'steps'])] },
|
|
32
|
+
],
|
|
33
|
+
globalAll: [tag.neq('access', 'private'), tag.neq('access', 'no')],
|
|
34
|
+
}
|
|
35
|
+
|
|
22
36
|
const graph: ParsedOsmData = /* loaded viewport data */
|
|
23
37
|
const adapter = createSessionGraphAdapter(graph)
|
|
24
38
|
|
|
@@ -26,14 +40,14 @@ const { chain, pendingJunctions } = await buildChain(adapter, {
|
|
|
26
40
|
centerWayId: 123456,
|
|
27
41
|
maxPerSide: 5,
|
|
28
42
|
candidateFilter: (candidate, from) =>
|
|
29
|
-
|
|
43
|
+
matchesOsmWaySelectionSegment(candidate, wayPolicy) &&
|
|
44
|
+
matchesOsmWaySelectionSegment(from, wayPolicy),
|
|
30
45
|
})
|
|
31
46
|
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
// Overpass fragment for lane-mode downloads:
|
|
36
|
-
overpassRoadLikeSelector('public')
|
|
47
|
+
// Overpass download for the same policy:
|
|
48
|
+
buildWaysOverpassQuery(wayPolicy, '52.5,13.4,52.51,13.41')
|
|
37
49
|
```
|
|
38
50
|
|
|
39
51
|
Implement `OsmDataAdapter` (`getWay`, `getWaysForNode`) for other data sources. Use `extendChainAtJunction` and `recenterChain` to continue after resolving a junction choice.
|
|
52
|
+
|
|
53
|
+
Legacy `overpassRoadLikeSelector` / `HighwayInclusionStyle` helpers remain as deprecated shims for street-space-editor.
|
package/dist/highway-filter.d.ts
CHANGED
|
@@ -1,30 +1,36 @@
|
|
|
1
1
|
import type { OsmTags } from '@osm-editor-kit/osm-data';
|
|
2
2
|
import type { Segment } from './domain/types';
|
|
3
|
+
import { type OsmWaySelectionPolicy } from './way-selection-policy';
|
|
3
4
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*/
|
|
7
|
-
export declare const ROAD_LIKE_HIGHWAY_BASE_REGEX: RegExp;
|
|
8
|
-
/**
|
|
9
|
-
* How broadly the editor includes low-priority access roads in the map.
|
|
10
|
-
*
|
|
11
|
-
* - `public` (default): skip private access, driveways, emergency access, and parking aisles
|
|
12
|
-
* - `inclusive`: include those ways (previous editor behavior)
|
|
5
|
+
* @deprecated App-owned concept. Prefer {@link OsmWaySelectionPolicy} defined in the app.
|
|
6
|
+
* Kept temporarily for street-space-editor call sites.
|
|
13
7
|
*/
|
|
14
8
|
export type HighwayInclusionStyle = 'public' | 'inclusive';
|
|
9
|
+
/** @deprecated Prefer app-owned policies. */
|
|
15
10
|
export declare const DEFAULT_HIGHWAY_INCLUSION_STYLE: HighwayInclusionStyle;
|
|
11
|
+
/**
|
|
12
|
+
* @deprecated Prefer app-owned {@link OsmWaySelectionPolicy}.
|
|
13
|
+
* Legacy lane-mode car/road selection (incl. `*_link` and `busway`).
|
|
14
|
+
*/
|
|
15
|
+
export declare function createLegacyStreetRoadWayPolicy(style?: HighwayInclusionStyle): OsmWaySelectionPolicy;
|
|
16
|
+
/** @deprecated Prefer matching against an app policy. */
|
|
17
|
+
export declare const ROAD_LIKE_HIGHWAY_BASE_REGEX: RegExp;
|
|
18
|
+
/** @deprecated Prefer policy `globalAll`. */
|
|
16
19
|
export declare const OVERPASS_PUBLIC_ROAD_FILTERS = "[service!=emergency_access][service!=parking_aisle][service!=driveway][access!=private]";
|
|
17
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* @deprecated Prefer {@link compileOverpassWaySelector} with an app policy.
|
|
22
|
+
* Returns the legacy fragment expected by `way[${tag}]` callers (no leading `[`).
|
|
23
|
+
*/
|
|
18
24
|
export declare function overpassRoadLikeSelector(style?: HighwayInclusionStyle): string;
|
|
19
|
-
/**
|
|
25
|
+
/** @deprecated Prefer app policy + {@link matchesOsmWaySelection}. */
|
|
20
26
|
export declare function isClutterAccessWay(tags: OsmTags): boolean;
|
|
21
|
-
/**
|
|
27
|
+
/** @deprecated Prefer app policy + {@link matchesOsmWaySelection}. */
|
|
22
28
|
export declare function matchesHighwayInclusionStyle(tags: OsmTags, style?: HighwayInclusionStyle): boolean;
|
|
23
|
-
/**
|
|
29
|
+
/** @deprecated Prefer app policy + {@link matchesOsmWaySelection}. */
|
|
24
30
|
export declare function isRoadLikeHighway(tags: OsmTags): boolean;
|
|
25
|
-
/**
|
|
31
|
+
/** @deprecated Prefer app policy + {@link matchesOsmWaySelection}. */
|
|
26
32
|
export declare function isEditableRoadLikeHighway(tags: OsmTags, style?: HighwayInclusionStyle): boolean;
|
|
27
|
-
/**
|
|
33
|
+
/** @deprecated Prefer app policy + {@link matchesOsmWaySelectionSegment}. */
|
|
28
34
|
export declare function isRoadLikeSegment(segment: Segment): boolean;
|
|
29
|
-
/**
|
|
35
|
+
/** @deprecated Prefer app policy + {@link matchesOsmWaySelectionSegment}. */
|
|
30
36
|
export declare function isEditableRoadLikeSegment(segment: Segment, style?: HighwayInclusionStyle): boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export type { JunctionChoice, NeighborDirection, OsmTags, Segment, SegmentChain, } from './domain/types';
|
|
2
|
-
export { DEFAULT_HIGHWAY_INCLUSION_STYLE, isClutterAccessWay, isEditableRoadLikeHighway, isEditableRoadLikeSegment, isRoadLikeHighway, isRoadLikeSegment, matchesHighwayInclusionStyle, overpassRoadLikeSelector, ROAD_LIKE_HIGHWAY_BASE_REGEX, OVERPASS_PUBLIC_ROAD_FILTERS, type HighwayInclusionStyle, } from './highway-filter';
|
|
2
|
+
export { createLegacyStreetRoadWayPolicy, DEFAULT_HIGHWAY_INCLUSION_STYLE, isClutterAccessWay, isEditableRoadLikeHighway, isEditableRoadLikeSegment, isRoadLikeHighway, isRoadLikeSegment, matchesHighwayInclusionStyle, overpassRoadLikeSelector, ROAD_LIKE_HIGHWAY_BASE_REGEX, OVERPASS_PUBLIC_ROAD_FILTERS, type HighwayInclusionStyle, } from './highway-filter';
|
|
3
|
+
export { buildWaysOverpassQuery, compileOverpassWaySelector, compileOverpassWaySelectors, matchesOsmWaySelection, matchesOsmWaySelectionSegment, tag, type OsmTagPredicate, type OsmWayFilterClause, type OsmWaySelectionPolicy, } from './way-selection-policy';
|
|
3
4
|
export type { OsmDataAdapter } from './ports/OsmDataAdapter';
|
|
4
5
|
export { createSessionGraphAdapter, osmWayToSegment } from './session-graph-adapter';
|
|
5
6
|
export { buildChain, extendChainAtJunction, getOtherEndpointNodeId, getSharedNodeBetween, recenterChain, type BuildChainOptions, type BuildChainResult, } from './traversal/buildChain';
|
package/dist/index.js
CHANGED
|
@@ -1,31 +1,147 @@
|
|
|
1
|
+
// src/way-selection-policy.ts
|
|
2
|
+
var tag = {
|
|
3
|
+
eq: (key, value) => ({ key, op: "eq", value }),
|
|
4
|
+
neq: (key, value) => ({ key, op: "neq", value }),
|
|
5
|
+
oneOf: (key, values) => ({
|
|
6
|
+
key,
|
|
7
|
+
op: "in",
|
|
8
|
+
values
|
|
9
|
+
}),
|
|
10
|
+
noneOf: (key, values) => ({
|
|
11
|
+
key,
|
|
12
|
+
op: "nin",
|
|
13
|
+
values
|
|
14
|
+
}),
|
|
15
|
+
regex: (key, pattern) => ({ key, op: "regex", pattern }),
|
|
16
|
+
nregex: (key, pattern) => ({ key, op: "nregex", pattern }),
|
|
17
|
+
present: (key) => ({ key, op: "present" }),
|
|
18
|
+
absent: (key) => ({ key, op: "absent" })
|
|
19
|
+
};
|
|
20
|
+
function escapeRegexAlternation(values) {
|
|
21
|
+
return values.map((value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
|
|
22
|
+
}
|
|
23
|
+
function quoteOverpassValue(value) {
|
|
24
|
+
if (/^[A-Za-z0-9_:-]+$/.test(value)) return value;
|
|
25
|
+
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
26
|
+
}
|
|
27
|
+
function escapeOverpassRegex(pattern) {
|
|
28
|
+
return pattern.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
29
|
+
}
|
|
30
|
+
function compileTagPredicate(predicate) {
|
|
31
|
+
switch (predicate.op) {
|
|
32
|
+
case "eq":
|
|
33
|
+
return `[${predicate.key}=${quoteOverpassValue(predicate.value)}]`;
|
|
34
|
+
case "neq":
|
|
35
|
+
return `[${predicate.key}!=${quoteOverpassValue(predicate.value)}]`;
|
|
36
|
+
case "in":
|
|
37
|
+
return `[${predicate.key}~"^(${escapeRegexAlternation(predicate.values)})$"]`;
|
|
38
|
+
case "nin":
|
|
39
|
+
return `[${predicate.key}!~"^(${escapeRegexAlternation(predicate.values)})$"]`;
|
|
40
|
+
case "regex":
|
|
41
|
+
return `[${predicate.key}~"${escapeOverpassRegex(predicate.pattern)}"]`;
|
|
42
|
+
case "nregex":
|
|
43
|
+
return `[${predicate.key}!~"${escapeOverpassRegex(predicate.pattern)}"]`;
|
|
44
|
+
case "present":
|
|
45
|
+
return `[${predicate.key}]`;
|
|
46
|
+
case "absent":
|
|
47
|
+
return `[!${predicate.key}]`;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function clausePredicates(policy, clause) {
|
|
51
|
+
return [...clause.all, ...policy.globalAll ?? []];
|
|
52
|
+
}
|
|
53
|
+
function compileOverpassWaySelectors(policy) {
|
|
54
|
+
if (policy.include.length === 0) {
|
|
55
|
+
throw new Error("OsmWaySelectionPolicy.include must contain at least one clause");
|
|
56
|
+
}
|
|
57
|
+
return policy.include.map(
|
|
58
|
+
(clause) => clausePredicates(policy, clause).map(compileTagPredicate).join("")
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
function compileOverpassWaySelector(policy) {
|
|
62
|
+
const selectors = compileOverpassWaySelectors(policy);
|
|
63
|
+
if (selectors.length !== 1) {
|
|
64
|
+
throw new Error(
|
|
65
|
+
`compileOverpassWaySelector expects exactly one include clause, got ${selectors.length}`
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
return selectors[0];
|
|
69
|
+
}
|
|
70
|
+
function matchesTagPredicate(tags, predicate) {
|
|
71
|
+
const raw = tags[predicate.key];
|
|
72
|
+
switch (predicate.op) {
|
|
73
|
+
case "eq":
|
|
74
|
+
return raw === predicate.value;
|
|
75
|
+
case "neq":
|
|
76
|
+
return raw !== predicate.value;
|
|
77
|
+
case "in":
|
|
78
|
+
return raw != null && predicate.values.includes(raw);
|
|
79
|
+
case "nin":
|
|
80
|
+
return raw == null || !predicate.values.includes(raw);
|
|
81
|
+
case "regex":
|
|
82
|
+
return raw != null && new RegExp(predicate.pattern).test(raw);
|
|
83
|
+
case "nregex":
|
|
84
|
+
return raw == null || !new RegExp(predicate.pattern).test(raw);
|
|
85
|
+
case "present":
|
|
86
|
+
return raw != null && raw !== "";
|
|
87
|
+
case "absent":
|
|
88
|
+
return raw == null || raw === "";
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function matchesClause(tags, predicates) {
|
|
92
|
+
return predicates.every((predicate) => matchesTagPredicate(tags, predicate));
|
|
93
|
+
}
|
|
94
|
+
function matchesOsmWaySelection(tags, policy) {
|
|
95
|
+
return policy.include.some((clause) => matchesClause(tags, clausePredicates(policy, clause)));
|
|
96
|
+
}
|
|
97
|
+
function matchesOsmWaySelectionSegment(segment, policy) {
|
|
98
|
+
return matchesOsmWaySelection(segment.tags, policy);
|
|
99
|
+
}
|
|
100
|
+
function buildWaysOverpassQuery(policy, bbox, options) {
|
|
101
|
+
const selectors = compileOverpassWaySelectors(policy);
|
|
102
|
+
const timeout = options?.timeoutSeconds ?? 60;
|
|
103
|
+
const out = options?.out ?? "meta";
|
|
104
|
+
const union = selectors.map((selector) => `way${selector}(${bbox});`).join("");
|
|
105
|
+
return `[out:xml][timeout:${timeout}];(${union});(._;>;);out ${out};`;
|
|
106
|
+
}
|
|
107
|
+
|
|
1
108
|
// src/highway-filter.ts
|
|
2
|
-
var ROAD_LIKE_HIGHWAY_BASE_REGEX = /^motorway|trunk|primary|secondary|tertiary|unclassified|residential|living_street|service/;
|
|
3
109
|
var DEFAULT_HIGHWAY_INCLUSION_STYLE = "public";
|
|
4
|
-
|
|
110
|
+
function createLegacyStreetRoadWayPolicy(style = DEFAULT_HIGHWAY_INCLUSION_STYLE) {
|
|
111
|
+
const highway = tag.regex(
|
|
112
|
+
"highway",
|
|
113
|
+
"^(motorway|trunk|primary|secondary|tertiary|unclassified|residential|living_street|service)(_link)?$|^busway$"
|
|
114
|
+
);
|
|
115
|
+
if (style === "inclusive") {
|
|
116
|
+
return { include: [{ all: [highway] }] };
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
include: [{ all: [highway] }],
|
|
120
|
+
globalAll: [
|
|
121
|
+
tag.neq("access", "private"),
|
|
122
|
+
tag.noneOf("service", ["emergency_access", "parking_aisle", "driveway"])
|
|
123
|
+
]
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
var ROAD_LIKE_HIGHWAY_BASE_REGEX = /^motorway|trunk|primary|secondary|tertiary|unclassified|residential|living_street|service/;
|
|
5
127
|
var OVERPASS_PUBLIC_ROAD_FILTERS = "[service!=emergency_access][service!=parking_aisle][service!=driveway][access!=private]";
|
|
6
128
|
function overpassRoadLikeSelector(style = DEFAULT_HIGHWAY_INCLUSION_STYLE) {
|
|
7
|
-
|
|
8
|
-
if (style === "inclusive") return base;
|
|
9
|
-
return base + OVERPASS_PUBLIC_ROAD_FILTERS;
|
|
129
|
+
return compileOverpassWaySelector(createLegacyStreetRoadWayPolicy(style)).slice(1);
|
|
10
130
|
}
|
|
11
131
|
function isClutterAccessWay(tags) {
|
|
12
132
|
if (tags.access === "private") return true;
|
|
13
133
|
const service = tags.service;
|
|
14
|
-
return service
|
|
134
|
+
return service === "driveway" || service === "emergency_access" || service === "parking_aisle";
|
|
15
135
|
}
|
|
16
136
|
function matchesHighwayInclusionStyle(tags, style = DEFAULT_HIGHWAY_INCLUSION_STYLE) {
|
|
17
137
|
if (style === "inclusive") return true;
|
|
18
138
|
return !isClutterAccessWay(tags);
|
|
19
139
|
}
|
|
20
140
|
function isRoadLikeHighway(tags) {
|
|
21
|
-
|
|
22
|
-
if (!highway) return false;
|
|
23
|
-
if (highway === "busway") return true;
|
|
24
|
-
const base = highway.endsWith("_link") ? highway.slice(0, -"_link".length) : highway;
|
|
25
|
-
return ROAD_LIKE_HIGHWAY_BASE_REGEX.test(base);
|
|
141
|
+
return matchesOsmWaySelection(tags, createLegacyStreetRoadWayPolicy("inclusive"));
|
|
26
142
|
}
|
|
27
143
|
function isEditableRoadLikeHighway(tags, style = DEFAULT_HIGHWAY_INCLUSION_STYLE) {
|
|
28
|
-
return
|
|
144
|
+
return matchesOsmWaySelection(tags, createLegacyStreetRoadWayPolicy(style));
|
|
29
145
|
}
|
|
30
146
|
function isRoadLikeSegment(segment) {
|
|
31
147
|
return isRoadLikeHighway(segment.tags);
|
|
@@ -396,4 +512,4 @@ function getSharedNodeBetween(a, b) {
|
|
|
396
512
|
return void 0;
|
|
397
513
|
}
|
|
398
514
|
|
|
399
|
-
export { DEFAULT_HIGHWAY_INCLUSION_STYLE, OVERPASS_PUBLIC_ROAD_FILTERS, ROAD_LIKE_HIGHWAY_BASE_REGEX, buildChain, createSessionGraphAdapter, extendChainAtJunction, filterNeighborCandidates, getEndpointNodeId, getKindKey, getOtherEndpointNodeId, getSharedNodeBetween, isClutterAccessWay, isEditableRoadLikeHighway, isEditableRoadLikeSegment, isReversedAtNode, isRoadLikeHighway, isRoadLikeSegment, matchesHighwayInclusionStyle, mirrorTags, normalizeTagsForDirection, orientNeighbor, osmWayToSegment, overpassRoadLikeSelector, pickBestNeighbor, recenterChain, sameKind, scoreNeighborCandidate, swapLeftRightKey };
|
|
515
|
+
export { DEFAULT_HIGHWAY_INCLUSION_STYLE, OVERPASS_PUBLIC_ROAD_FILTERS, ROAD_LIKE_HIGHWAY_BASE_REGEX, buildChain, buildWaysOverpassQuery, compileOverpassWaySelector, compileOverpassWaySelectors, createLegacyStreetRoadWayPolicy, createSessionGraphAdapter, extendChainAtJunction, filterNeighborCandidates, getEndpointNodeId, getKindKey, getOtherEndpointNodeId, getSharedNodeBetween, isClutterAccessWay, isEditableRoadLikeHighway, isEditableRoadLikeSegment, isReversedAtNode, isRoadLikeHighway, isRoadLikeSegment, matchesHighwayInclusionStyle, matchesOsmWaySelection, matchesOsmWaySelectionSegment, mirrorTags, normalizeTagsForDirection, orientNeighbor, osmWayToSegment, overpassRoadLikeSelector, pickBestNeighbor, recenterChain, sameKind, scoreNeighborCandidate, swapLeftRightKey, tag };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { OsmTags } from '@osm-editor-kit/osm-data';
|
|
2
|
+
import type { Segment } from './domain/types';
|
|
3
|
+
/**
|
|
4
|
+
* Atomic tag predicate. Compiles 1:1 to Overpass filter syntax and the same
|
|
5
|
+
* semantics when matching in-memory `OsmTags` (missing tag matches `neq` / `nin`
|
|
6
|
+
* / `absent`, same as Overpass).
|
|
7
|
+
*/
|
|
8
|
+
export type OsmTagPredicate = {
|
|
9
|
+
readonly key: string;
|
|
10
|
+
readonly op: 'eq' | 'neq';
|
|
11
|
+
readonly value: string;
|
|
12
|
+
} | {
|
|
13
|
+
readonly key: string;
|
|
14
|
+
readonly op: 'in' | 'nin';
|
|
15
|
+
readonly values: readonly string[];
|
|
16
|
+
} | {
|
|
17
|
+
readonly key: string;
|
|
18
|
+
readonly op: 'regex' | 'nregex';
|
|
19
|
+
readonly pattern: string;
|
|
20
|
+
} | {
|
|
21
|
+
readonly key: string;
|
|
22
|
+
readonly op: 'present' | 'absent';
|
|
23
|
+
};
|
|
24
|
+
/** One AND-group of tag predicates — one `way[...]` branch in Overpass. */
|
|
25
|
+
export type OsmWayFilterClause = {
|
|
26
|
+
readonly all: readonly OsmTagPredicate[];
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Declarative way-selection policy (app-owned contract).
|
|
30
|
+
*
|
|
31
|
+
* - `include`: OR — union of Overpass `way[...](bbox)` statements
|
|
32
|
+
* - `globalAll`: AND — appended to every include clause (e.g. access exclusions)
|
|
33
|
+
*/
|
|
34
|
+
export type OsmWaySelectionPolicy = {
|
|
35
|
+
readonly include: readonly OsmWayFilterClause[];
|
|
36
|
+
readonly globalAll?: readonly OsmTagPredicate[];
|
|
37
|
+
};
|
|
38
|
+
/** Ergonomic constructors for {@link OsmTagPredicate}. */
|
|
39
|
+
export declare const tag: {
|
|
40
|
+
readonly eq: (key: string, value: string) => OsmTagPredicate;
|
|
41
|
+
readonly neq: (key: string, value: string) => OsmTagPredicate;
|
|
42
|
+
readonly oneOf: (key: string, values: readonly string[]) => OsmTagPredicate;
|
|
43
|
+
readonly noneOf: (key: string, values: readonly string[]) => OsmTagPredicate;
|
|
44
|
+
readonly regex: (key: string, pattern: string) => OsmTagPredicate;
|
|
45
|
+
readonly nregex: (key: string, pattern: string) => OsmTagPredicate;
|
|
46
|
+
readonly present: (key: string) => OsmTagPredicate;
|
|
47
|
+
readonly absent: (key: string) => OsmTagPredicate;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Compiles each include clause to an Overpass way-filter suffix, e.g.
|
|
51
|
+
* `[highway=cycleway][access!=private]`.
|
|
52
|
+
* Callers wrap these in `way…(bbox)` union statements.
|
|
53
|
+
*/
|
|
54
|
+
export declare function compileOverpassWaySelectors(policy: OsmWaySelectionPolicy): string[];
|
|
55
|
+
/** Single selector when the policy has exactly one include clause; otherwise throws. */
|
|
56
|
+
export declare function compileOverpassWaySelector(policy: OsmWaySelectionPolicy): string;
|
|
57
|
+
/** Whether OSM tags match the policy (OR of include clauses, each with globalAll). */
|
|
58
|
+
export declare function matchesOsmWaySelection(tags: OsmTags, policy: OsmWaySelectionPolicy): boolean;
|
|
59
|
+
export declare function matchesOsmWaySelectionSegment(segment: Segment, policy: OsmWaySelectionPolicy): boolean;
|
|
60
|
+
/** Builds Overpass QL that downloads matching ways (+ their nodes) for a bbox string. */
|
|
61
|
+
export declare function buildWaysOverpassQuery(policy: OsmWaySelectionPolicy, bbox: string, options?: {
|
|
62
|
+
readonly timeoutSeconds?: number;
|
|
63
|
+
readonly out?: 'meta' | 'body';
|
|
64
|
+
}): string;
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@osm-editor-kit/osm-way-chain",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.2",
|
|
4
4
|
"description": "Traverse and orient connected OSM highway ways for multi-segment editing sessions.",
|
|
5
|
+
"homepage": "https://github.com/osmberlin/street-space-editor/tree/main/packages/osm-way-chain",
|
|
5
6
|
"license": "MIT",
|
|
6
7
|
"author": "Tobias Jordans",
|
|
7
8
|
"repository": {
|
|
@@ -9,11 +10,11 @@
|
|
|
9
10
|
"url": "git+https://github.com/osmberlin/street-space-editor.git",
|
|
10
11
|
"directory": "packages/osm-way-chain"
|
|
11
12
|
},
|
|
12
|
-
"type": "module",
|
|
13
|
-
"sideEffects": false,
|
|
14
13
|
"files": [
|
|
15
14
|
"dist"
|
|
16
15
|
],
|
|
16
|
+
"type": "module",
|
|
17
|
+
"sideEffects": false,
|
|
17
18
|
"exports": {
|
|
18
19
|
".": {
|
|
19
20
|
"types": "./dist/index.d.ts",
|