@drawtonomy/sdk 0.5.0 → 0.7.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.
@@ -0,0 +1,247 @@
1
+ // Lanelet2 OSM (.osm XML) parser.
2
+ //
3
+ // The Lanelet2 format reuses OpenStreetMap's `<node>` / `<way>` / `<relation>`
4
+ // tag structure but with traffic-domain semantics:
5
+ // - <node> : a 2D point in lat/lon (optionally with `ele` tag for height)
6
+ // - <way> : an ordered list of node refs forming a polyline
7
+ // (used for lane boundaries, stop lines, etc.)
8
+ // - <relation> : a typed grouping of ways/nodes
9
+ // (`type=lanelet` joins a left + right way as a lane;
10
+ // `type=regulatory_element` etc. are kept untouched)
11
+ //
12
+ // drawtonomy-emitted files additionally embed `drawtonomy_origin_lat` and
13
+ // `drawtonomy_origin_lon` attributes on the root `<osm>` element so that the
14
+ // canvas page coordinates can be reconstructed exactly on round-trip. Standard
15
+ // OSM consumers ignore unknown attributes, keeping the file compatible.
16
+ //
17
+ // The parser is intentionally hand-written so it works in a plain Node runtime
18
+ // without a DOM. When a global `DOMParser` is available (e.g. in a browser or
19
+ // when jsdom is installed), it is used for robustness; otherwise a regex-based
20
+ // fallback parses the same subset of OSM XML used by Lanelet2.
21
+ function getDomParser() {
22
+ const g = globalThis;
23
+ return typeof g.DOMParser === 'function' ? g.DOMParser : null;
24
+ }
25
+ function parseOsmXmlWithDom(xmlString, DOMParserImpl) {
26
+ const parser = new DOMParserImpl();
27
+ const doc = parser.parseFromString(xmlString, 'text/xml');
28
+ const nodes = new Map();
29
+ const ways = new Map();
30
+ const relations = [];
31
+ let drawtonomyOrigin;
32
+ const osmEl = doc.querySelector('osm');
33
+ if (osmEl) {
34
+ const oLat = parseFloat(osmEl.getAttribute('drawtonomy_origin_lat') || '');
35
+ const oLon = parseFloat(osmEl.getAttribute('drawtonomy_origin_lon') || '');
36
+ if (Number.isFinite(oLat) && Number.isFinite(oLon)) {
37
+ drawtonomyOrigin = { lat: oLat, lon: oLon };
38
+ }
39
+ }
40
+ const collectTags = (el) => {
41
+ const tags = {};
42
+ el.querySelectorAll(':scope > tag').forEach(tagEl => {
43
+ const k = tagEl.getAttribute('k') || '';
44
+ const v = tagEl.getAttribute('v') || '';
45
+ if (k)
46
+ tags[k] = v;
47
+ });
48
+ return tags;
49
+ };
50
+ doc.querySelectorAll('node').forEach(nodeEl => {
51
+ const id = nodeEl.getAttribute('id') || '';
52
+ const lat = parseFloat(nodeEl.getAttribute('lat') || '0');
53
+ const lon = parseFloat(nodeEl.getAttribute('lon') || '0');
54
+ const tags = collectTags(nodeEl);
55
+ nodes.set(id, {
56
+ id,
57
+ lat,
58
+ lon,
59
+ ele: tags.ele !== undefined ? parseFloat(tags.ele) : undefined,
60
+ tags,
61
+ });
62
+ });
63
+ doc.querySelectorAll('way').forEach(wayEl => {
64
+ const id = wayEl.getAttribute('id') || '';
65
+ const nodeRefs = [];
66
+ wayEl.querySelectorAll(':scope > nd').forEach(ndEl => {
67
+ const ref = ndEl.getAttribute('ref') || '';
68
+ if (ref)
69
+ nodeRefs.push(ref);
70
+ });
71
+ ways.set(id, { id, nodeRefs, tags: collectTags(wayEl) });
72
+ });
73
+ doc.querySelectorAll('relation').forEach(relEl => {
74
+ const id = relEl.getAttribute('id') || '';
75
+ const members = [];
76
+ relEl.querySelectorAll(':scope > member').forEach(memEl => {
77
+ members.push({
78
+ type: memEl.getAttribute('type') || '',
79
+ ref: memEl.getAttribute('ref') || '',
80
+ role: memEl.getAttribute('role') || '',
81
+ });
82
+ });
83
+ // Keep all relations (regulatory_element etc.) so they survive a
84
+ // round-trip; consumers can filter by tag type.
85
+ relations.push({ id, members, tags: collectTags(relEl) });
86
+ });
87
+ return { nodes, ways, relations, drawtonomyOrigin };
88
+ }
89
+ // ---------- Hand-rolled fallback parser (no DOM dependency) ----------
90
+ const ATTR_RE = /([a-zA-Z_][\w:.-]*)\s*=\s*(?:"([^"]*)"|'([^']*)')/g;
91
+ function parseAttributes(attrString) {
92
+ const attrs = {};
93
+ ATTR_RE.lastIndex = 0;
94
+ let m;
95
+ while ((m = ATTR_RE.exec(attrString)) !== null) {
96
+ const value = m[2] !== undefined ? m[2] : m[3];
97
+ attrs[m[1]] = decodeXmlEntities(value);
98
+ }
99
+ return attrs;
100
+ }
101
+ function decodeXmlEntities(s) {
102
+ return s
103
+ .replace(/&lt;/g, '<')
104
+ .replace(/&gt;/g, '>')
105
+ .replace(/&quot;/g, '"')
106
+ .replace(/&apos;/g, "'")
107
+ .replace(/&#(\d+);/g, (_, code) => String.fromCharCode(parseInt(code, 10)))
108
+ .replace(/&#x([0-9a-fA-F]+);/g, (_, code) => String.fromCharCode(parseInt(code, 16)))
109
+ .replace(/&amp;/g, '&');
110
+ }
111
+ /**
112
+ * Minimal XML parser supporting the subset used by Lanelet2 OSM files:
113
+ * elements, attributes, self-closing tags, and nested elements. XML comments
114
+ * and CDATA blocks are stripped first. Sufficient for `<node>`/`<way>`/
115
+ * `<relation>`/`<tag>`/`<nd>`/`<member>`.
116
+ */
117
+ function parseXmlSubset(xml) {
118
+ // Strip XML declaration, comments, processing instructions, and CDATA.
119
+ let src = xml
120
+ .replace(/<\?[\s\S]*?\?>/g, '')
121
+ .replace(/<!--[\s\S]*?-->/g, '')
122
+ .replace(/<!\[CDATA\[[\s\S]*?\]\]>/g, '')
123
+ .replace(/<!DOCTYPE[\s\S]*?>/g, '');
124
+ const tagRe = /<\/?\s*([a-zA-Z_][\w:.-]*)((?:[^<>"']|"[^"]*"|'[^']*')*)\/?\s*>/g;
125
+ const stack = [];
126
+ let root = null;
127
+ let m;
128
+ while ((m = tagRe.exec(src)) !== null) {
129
+ const fullTag = m[0];
130
+ const name = m[1];
131
+ const rest = m[2];
132
+ const isClosing = fullTag.startsWith('</');
133
+ const isSelfClosing = fullTag.endsWith('/>');
134
+ if (isClosing) {
135
+ // Pop matching element.
136
+ const top = stack.pop();
137
+ if (!top || top.name !== name) {
138
+ // Tolerate slight mismatches by ignoring stray closers.
139
+ continue;
140
+ }
141
+ }
142
+ else {
143
+ const el = { name, attrs: parseAttributes(rest), children: [] };
144
+ const parent = stack[stack.length - 1];
145
+ if (parent)
146
+ parent.children.push(el);
147
+ else
148
+ root = el;
149
+ if (!isSelfClosing)
150
+ stack.push(el);
151
+ }
152
+ }
153
+ return root;
154
+ }
155
+ function findChildren(el, name) {
156
+ return el.children.filter(c => c.name === name);
157
+ }
158
+ function collectTagsFromChildren(el) {
159
+ const tags = {};
160
+ for (const c of findChildren(el, 'tag')) {
161
+ const k = c.attrs.k;
162
+ const v = c.attrs.v ?? '';
163
+ if (k)
164
+ tags[k] = v;
165
+ }
166
+ return tags;
167
+ }
168
+ function parseOsmXmlFallback(xmlString) {
169
+ const root = parseXmlSubset(xmlString);
170
+ const nodes = new Map();
171
+ const ways = new Map();
172
+ const relations = [];
173
+ let drawtonomyOrigin;
174
+ if (!root)
175
+ return { nodes, ways, relations };
176
+ const osmRoot = root.name === 'osm' ? root : findChildren(root, 'osm')[0];
177
+ if (!osmRoot)
178
+ return { nodes, ways, relations };
179
+ const oLat = parseFloat(osmRoot.attrs.drawtonomy_origin_lat ?? '');
180
+ const oLon = parseFloat(osmRoot.attrs.drawtonomy_origin_lon ?? '');
181
+ if (Number.isFinite(oLat) && Number.isFinite(oLon)) {
182
+ drawtonomyOrigin = { lat: oLat, lon: oLon };
183
+ }
184
+ for (const child of osmRoot.children) {
185
+ if (child.name === 'node') {
186
+ const id = child.attrs.id ?? '';
187
+ const lat = parseFloat(child.attrs.lat ?? '0');
188
+ const lon = parseFloat(child.attrs.lon ?? '0');
189
+ const tags = collectTagsFromChildren(child);
190
+ nodes.set(id, {
191
+ id,
192
+ lat,
193
+ lon,
194
+ ele: tags.ele !== undefined ? parseFloat(tags.ele) : undefined,
195
+ tags,
196
+ });
197
+ }
198
+ else if (child.name === 'way') {
199
+ const id = child.attrs.id ?? '';
200
+ const nodeRefs = findChildren(child, 'nd').map(c => c.attrs.ref ?? '').filter(r => r.length > 0);
201
+ ways.set(id, { id, nodeRefs, tags: collectTagsFromChildren(child) });
202
+ }
203
+ else if (child.name === 'relation') {
204
+ const id = child.attrs.id ?? '';
205
+ const members = findChildren(child, 'member').map(c => ({
206
+ type: c.attrs.type ?? '',
207
+ ref: c.attrs.ref ?? '',
208
+ role: c.attrs.role ?? '',
209
+ }));
210
+ relations.push({ id, members, tags: collectTagsFromChildren(child) });
211
+ }
212
+ }
213
+ return { nodes, ways, relations, drawtonomyOrigin };
214
+ }
215
+ /** Parse a Lanelet2 OSM XML string into structured data. */
216
+ export function parseOsmXml(xmlString) {
217
+ const DOMParserImpl = getDomParser();
218
+ if (DOMParserImpl) {
219
+ try {
220
+ return parseOsmXmlWithDom(xmlString, DOMParserImpl);
221
+ }
222
+ catch {
223
+ // Fall through to the hand-rolled parser.
224
+ }
225
+ }
226
+ return parseOsmXmlFallback(xmlString);
227
+ }
228
+ /**
229
+ * Project lat/lon onto canvas (page) coordinates using a simple
230
+ * equirectangular projection centered at (centerLat, centerLon).
231
+ *
232
+ * The default scale matches drawtonomy's visual sizing convention: a 3 m wide
233
+ * lane renders as 50 px (16.67 px/m), so `scale = 16.67 * 111320 ≈ 1,855,000`.
234
+ */
235
+ export function latLonToCanvas(lat, lon, centerLat, centerLon, scale = 1855000) {
236
+ const x = (lon - centerLon) * scale * Math.cos((centerLat * Math.PI) / 180);
237
+ // Page Y axis points down, latitude grows northward (= up), so flip.
238
+ const y = -(lat - centerLat) * scale;
239
+ return { x, y };
240
+ }
241
+ /** Inverse of `latLonToCanvas`: page coordinates back to lat/lon. */
242
+ export function canvasToLatLon(x, y, centerLat, centerLon, scale = 1855000) {
243
+ const lat = centerLat - y / scale;
244
+ const lon = centerLon + x / (scale * Math.cos((centerLat * Math.PI) / 180));
245
+ return { lat, lon };
246
+ }
247
+ //# sourceMappingURL=osmParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"osmParser.js","sourceRoot":"","sources":["../../src/exporter/osmParser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,107 @@
1
+ import type { ShapeId } from '../types';
2
+ import { type OsmData } from './osmParser';
3
+ /**
4
+ * ID allocator interface. The default implementation produces predictable
5
+ * `shape:<kind>_<n>` ids starting from 0; callers (e.g. the editor) can pass
6
+ * a custom allocator to coordinate IDs with their own counters.
7
+ */
8
+ export interface ShapeIdAllocator {
9
+ next(kind: 'point' | 'linestring' | 'lane'): ShapeId;
10
+ }
11
+ /** Default allocator: monotonic counter per shape kind. */
12
+ export declare function createShapeIdAllocator(): ShapeIdAllocator;
13
+ export interface ImportedPoint {
14
+ id: ShapeId;
15
+ x: number;
16
+ y: number;
17
+ osmId: string;
18
+ }
19
+ export interface ImportedLinestring {
20
+ id: ShapeId;
21
+ x: number;
22
+ y: number;
23
+ pointIds: string[];
24
+ osmId: string;
25
+ attributes: Record<string, string>;
26
+ }
27
+ export interface ImportedLane {
28
+ id: ShapeId;
29
+ x: number;
30
+ y: number;
31
+ leftBoundaryId: string;
32
+ rightBoundaryId: string;
33
+ /**
34
+ * Whether the boundary's node order should be reversed when interpreted by
35
+ * the editor. Lanelet2 encodes lane direction via the left boundary's node
36
+ * order, but a sibling lane in the opposite direction may share the same
37
+ * boundary read backwards.
38
+ */
39
+ invertLeft: boolean;
40
+ invertRight: boolean;
41
+ osmId: string;
42
+ attributes: Record<string, string>;
43
+ next: string[];
44
+ prev: string[];
45
+ }
46
+ export interface ImportBounds {
47
+ minX: number;
48
+ maxX: number;
49
+ minY: number;
50
+ maxY: number;
51
+ centerX: number;
52
+ centerY: number;
53
+ width: number;
54
+ height: number;
55
+ }
56
+ export interface ImportedShapes {
57
+ points: ImportedPoint[];
58
+ linestrings: ImportedLinestring[];
59
+ lanes: ImportedLane[];
60
+ bounds: ImportBounds;
61
+ /**
62
+ * Geographic center used as the canvas origin during projection. The host
63
+ * app should call `setMapOrigin(originLatLon)` so that the map background
64
+ * lines up with the imported lanes at page (0, 0).
65
+ */
66
+ originLatLon?: {
67
+ lat: number;
68
+ lon: number;
69
+ };
70
+ }
71
+ export interface OsmToShapesOptions {
72
+ /** Custom id allocator. A fresh `createShapeIdAllocator()` is used when omitted. */
73
+ idAllocator?: ShapeIdAllocator;
74
+ /**
75
+ * Restrict conversion to the given lanelet relation IDs. When omitted, all
76
+ * `type=lanelet` relations are converted (regulatory_element etc. are
77
+ * always skipped here; they are preserved separately via the OSM sidecar).
78
+ */
79
+ selectedLaneIds?: readonly string[];
80
+ }
81
+ interface Point2d {
82
+ x: number;
83
+ y: number;
84
+ }
85
+ /**
86
+ * Decide whether to reverse the left and/or right boundary so the lane is
87
+ * interpreted consistently by the editor.
88
+ *
89
+ * In Lanelet2, the way's node order defines the lane direction (the left
90
+ * boundary's direction is the lane's direction). This routine preserves that
91
+ * direction whenever possible, only flipping a boundary when needed to keep
92
+ * the right-of-left invariant.
93
+ */
94
+ export declare function alignBoundaries(leftPoints: Point2d[], rightPoints: Point2d[]): {
95
+ invertLeft: boolean;
96
+ invertRight: boolean;
97
+ };
98
+ /**
99
+ * Convert parsed OSM data into editor-ready point/linestring/lane records.
100
+ *
101
+ * Pass `selectedLaneIds` to restrict to a subset of lanelet relations
102
+ * (selective import); leave it `undefined` to import every `type=lanelet`
103
+ * relation.
104
+ */
105
+ export declare function osmToShapes(osmData: OsmData, options?: OsmToShapesOptions): ImportedShapes;
106
+ export {};
107
+ //# sourceMappingURL=osmToShapes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"osmToShapes.d.ts","sourceRoot":"","sources":["../../src/exporter/osmToShapes.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,EAAkB,KAAK,OAAO,EAAE,MAAM,aAAa,CAAA;AAE1D;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,YAAY,GAAG,MAAM,GAAG,OAAO,CAAA;CACrD;AAED,2DAA2D;AAC3D,wBAAgB,sBAAsB,IAAI,gBAAgB,CASzD;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,CAAA;IACX,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,OAAO,CAAA;IACX,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACnC;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAA;IACX,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,cAAc,EAAE,MAAM,CAAA;IACtB,eAAe,EAAE,MAAM,CAAA;IACvB;;;;;OAKG;IACH,UAAU,EAAE,OAAO,CAAA;IACnB,WAAW,EAAE,OAAO,CAAA;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAClC,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,IAAI,EAAE,MAAM,EAAE,CAAA;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,aAAa,EAAE,CAAA;IACvB,WAAW,EAAE,kBAAkB,EAAE,CAAA;IACjC,KAAK,EAAE,YAAY,EAAE,CAAA;IACrB,MAAM,EAAE,YAAY,CAAA;IACpB;;;;OAIG;IACH,YAAY,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;CAC5C;AAED,MAAM,WAAW,kBAAkB;IACjC,oFAAoF;IACpF,WAAW,CAAC,EAAE,gBAAgB,CAAA;IAC9B;;;;OAIG;IACH,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CACpC;AAED,UAAU,OAAO;IACf,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV;AAcD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,OAAO,EAAE,EACrB,WAAW,EAAE,OAAO,EAAE,GACrB;IAAE,UAAU,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,CA4E/C;AAmFD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,GAAE,kBAAuB,GAAG,cAAc,CAmM9F"}