osm2geojson-lite 1.0.2 → 1.1.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 CHANGED
@@ -1,18 +1,15 @@
1
1
  osm2geojson-lite
2
2
  ============
3
3
 
4
+ [![NPM Version](https://img.shields.io/npm/v/osm2geojson-lite)](https://www.npmjs.com/package/osm2geojson-lite) [![Codecov](https://img.shields.io/codecov/c/github/tibetty/osm2geojson-lite/master.svg)](https://codecov.io/gh/tibetty/osm2geojson-lite/)
5
+
6
+
4
7
  A lightweight (not as lightweight as xml2geojson though) yet faster convertor for [OSM](http://openstreetmap.org) [data](http://wiki.openstreetmap.org/wiki/OSM_XML) whatever in XML or JSON formats to [GeoJSON](http://www.geojson.org/) - much faster (the more complex the data source is, the more performance advantages it posesses) than osmtogeojson in most situations - implemented in pure JavaScript without any 3rd party dependency.
5
8
 
6
9
  History
7
10
  -----
8
11
  An internal function inside [query-geo-boundary](https://www.npmjs.com/package/query-geo-boundary) → stripped out to handle OSM XML only [xml2geojson-lite](https://www.npmjs.com/package/xml2geojson-lite) → this library that supports both OSM XML and OSM/Overpass JSON
9
12
 
10
- Changelog:
11
- -----
12
- * Late 2018: this repository was created and the initial version was pushed to github - almost around specific usages for myself.
13
- * 2019-2025: quite a few contributors had fixed quite a few bugs and also contributed some good ideas - thanks for their efforts!
14
- * 2025-03-03: fixed a few bugs around non-*Polygon features processing and convert it to a pure TypeScript project (codes published to [NPM](https://npmjs.org/) have become TSC compiled from now on).
15
-
16
13
  Usage
17
14
  -----
18
15
 
@@ -25,7 +22,7 @@ Installation:
25
22
  Usage:
26
23
 
27
24
  ```js
28
- const osm2geojson = require('osm2geojson-lite');
25
+ import osm2geojson from 'osm2geojson-lite';
29
26
  let geojson = osm2geojson(osm, opts);
30
27
  ```
31
28
 
@@ -46,9 +43,9 @@ Converts OSM data (XML/JSON) to GeoJSON.
46
43
 
47
44
  * `osm`: the OSM XML data in String, or OSM/Overpass JSON as object or in String
48
45
  * `opts?`: optional, the options object, right now supports below properties/fields:
49
- - `completeFeature/allFeatures`: the default value is `false`. When it's set to `true`, the returned geojson will include all elements that meet the specified conditions in `FeatureCollection` format; otherwise, only the bare geometry of the first `relation` element will be returned.
50
- - `renderTagged`: the default value is `false`. When it's set to `true`, the returned geojson will include all elements with tags (i.e., tagged) until `suppressWay` changes its behavior a bit; otherwise only the unreferenced ones get returned.
51
- - `suppressWay/excludeWay`: the default value is `true`. When it's set to `true`, the returned `FeatureCollection` will exclude all referenced `way`s even though they are tagged; otherwise the features of those `way`s will be included in the resulted result as well.
46
+ - `completeFeature`: the default value is `false`. When it's set to `true`, the returned geojson will include all elements that meet the specified conditions in `FeatureCollection` format; otherwise, only the bare geometry of the first `relation` element will be returned.
47
+ - `renderTagged`: the default value is `false`. When it's set to `true`, the returned geojson will include all elements with tags (i.e., tagged) until `excludeWay` changes its behavior a bit; otherwise only the unreferenced ones get returned.
48
+ - `excludeWay`: the default value is `true`. When it's set to `true`, the returned `FeatureCollection` will exclude all referenced `way`s even though they are tagged; otherwise the features of those `way`s will be included in the resulted result as well.
52
49
 
53
50
 
54
51
  Performance
@@ -58,9 +55,8 @@ Performance
58
55
  3. For each script, run as many as times seperately and then calculate the average cost time (ACT for short)
59
56
  4. The # listed in the table below are coarse lowest values of dividing the ACT of `osmtogeojson` by the one of this library
60
57
  ```
61
- $ cd bench
62
- $ node o2gl-bench.js
63
- $ node otg-bench.js
58
+ $ cd test
59
+ $ npm run bench
64
60
  ```
65
61
  1. XML
66
62
 
@@ -79,7 +75,7 @@ Correctness
79
75
  ---
80
76
  You can copy the converted results to [geojsonlint](http://geojsonlint.com) for the correctness validation. Up until now, `osm2geojson-lite` behaves pretty well with all the samples (also quite representative) in the `data` subfolers under `test` and `bench` directories, which also outperforms `osmtogeojson`.
81
77
 
82
- The client side example shipped along with this package, `test/index.html` ~~will automatically call `geojsonlint` validation service directly after each conversion, you can wait for a while to see the validation result after click the conversion button.~~ - because the CORS limitation, the direct post to geojsonlint was blocked, so I added a "copy to clipboard" button for you to ease the validation.
78
+ The client side example shipped along with this package, `test/index.html` - due to CORS limitation, the direct post to geojsonlint is blocked, so there's a "copy to clipboard" button for you to ease the validation.
83
79
 
84
80
  Node.JS version
85
81
  ---
@@ -91,10 +87,10 @@ Dependencies
91
87
 
92
88
  License
93
89
  ---
94
- Copyleft
90
+ MIT
95
91
 
96
92
  Collaborators
97
93
  ---
98
- * tibetty
99
- * HarelM
94
+ * [tibetty](https://github.com/tibetty/)
95
+ * [HarelM](https://github.com/HarelM)
100
96
 
package/package.json CHANGED
@@ -25,7 +25,7 @@
25
25
  "bugs": {
26
26
  "url": "https://github.com/tibetty/osm2geojson-lite/issues"
27
27
  },
28
- "bundleDependencies": false,
28
+ "bundleDependencies": [],
29
29
  "deprecated": false,
30
30
  "description": "a lightweight yet faster osm (either in xml or in json formats) to geojson convertor - 4x faster than xmldom + osmtogeojson in most situations - implemented in pure JavaScript without any 3rd party dependency",
31
31
  "homepage": "https://github.com/tibetty/osm2geojson-lite#readme",
@@ -53,23 +53,29 @@
53
53
  "url": "git+https://github.com/tibetty/osm2geojson-lite.git"
54
54
  },
55
55
  "scripts": {
56
- "build": "npm install && make",
57
- "test": "make test"
56
+ "build-node": "tsc --declaration && cp src/polytags.json dist/node",
57
+ "build-web": "mkdir -p dist/web && browserify -s osm2geojson dist/node/index.js | uglifyjs -c -m -o dist/web/osm2geojson-lite.js",
58
+ "build": "npm run build-node && npm run build-web",
59
+ "test": "vitest test/e2e.test.ts --coverage"
58
60
  },
59
61
  "optionalDependencies": {
60
62
  "@types/geojson": "^7946.0.16"
61
63
  },
62
- "version": "1.0.2",
64
+ "version": "1.1.0",
63
65
  "directories": {
64
66
  "lib": "lib",
65
67
  "test": "test"
66
68
  },
67
69
  "devDependencies": {
70
+ "@vitest/coverage-v8": "^3.1.3",
68
71
  "browserify": "^17.0.1",
69
- "uglify-js": "^3.19.3"
72
+ "typescript": "^5.8.3",
73
+ "uglify-js": "^3.19.3",
74
+ "vitest": "^3.1.3"
70
75
  },
71
76
  "files": [
72
77
  "dist/**/*.js",
78
+ "dist/**/*.ts",
73
79
  "dist/**/*.json"
74
80
  ]
75
81
  }
@@ -1,199 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- const osmobjs_1 = require("./osmobjs");
6
- const utils_1 = require("./utils");
7
- const xmlparser_1 = __importDefault(require("./xmlparser"));
8
- function osm2geojson(osm, opts) {
9
- let completeFeature = false;
10
- let renderTagged = false;
11
- let excludeWay = true;
12
- const parseOpts = (os) => {
13
- if (os) {
14
- completeFeature = os.completeFeature || os.allFeatures ? true : false;
15
- renderTagged = os.renderTagged ? true : false;
16
- const wayOpt = os.suppressWay || os.excludeWay;
17
- if (wayOpt !== undefined && !wayOpt) {
18
- excludeWay = false;
19
- }
20
- }
21
- };
22
- if (opts) {
23
- parseOpts(opts);
24
- }
25
- const detectFormat = (o) => {
26
- if (o.elements) {
27
- return 'json';
28
- }
29
- if (o.indexOf('<osm') >= 0) {
30
- return 'xml';
31
- }
32
- if (o.trim().startsWith('{')) {
33
- return 'json-raw';
34
- }
35
- return 'invalid';
36
- };
37
- let format = detectFormat(osm);
38
- const refElements = new utils_1.RefElements();
39
- let featureArray = [];
40
- const analyzeFeaturesFromJson = (o) => {
41
- for (const elem of osm.elements) {
42
- switch (elem.type) {
43
- case 'node':
44
- const node = new osmobjs_1.Node(elem.id, refElements);
45
- if (elem.tags) {
46
- node.addTags(elem.tags);
47
- }
48
- node.addProps((0, utils_1.purgeProps)(elem, ['id', 'type', 'tags', 'lat', 'lon']));
49
- node.setLatLng(elem);
50
- break;
51
- case 'way':
52
- const way = new osmobjs_1.Way(elem.id, refElements);
53
- if (elem.tags) {
54
- way.addTags(elem.tags);
55
- }
56
- way.addProps((0, utils_1.purgeProps)(elem, ['id', 'type', 'tags', 'nodes', 'geometry']));
57
- if (elem.geometry) {
58
- way.setLatLngArray(elem.geometry);
59
- }
60
- else if (elem.nodes) {
61
- for (const n of elem.nodes) {
62
- way.addNodeRef(n);
63
- }
64
- }
65
- break;
66
- case 'relation':
67
- const relation = new osmobjs_1.Relation(elem.id, refElements);
68
- if (elem.bounds) {
69
- relation.setBounds([parseFloat(elem.bounds.minlon), parseFloat(elem.bounds.minlat), parseFloat(elem.bounds.maxlon), parseFloat(elem.bounds.maxlat)]);
70
- }
71
- if (elem.tags) {
72
- relation.addTags(elem.tags);
73
- }
74
- relation.addProps((0, utils_1.purgeProps)(elem, ['id', 'type', 'tags', 'bounds', 'members']));
75
- if (elem.members) {
76
- for (const member of elem.members) {
77
- relation.addMember(member);
78
- }
79
- }
80
- default:
81
- break;
82
- }
83
- }
84
- };
85
- const analyzeFeaturesFromXml = (o) => {
86
- const xmlParser = new xmlparser_1.default({ progressive: true });
87
- xmlParser.on('</osm.node>', (node) => {
88
- const nd = new osmobjs_1.Node(node.id, refElements);
89
- for (const [k, v] of Object.entries(node)) {
90
- if (!k.startsWith('$') && ['id', 'lon', 'lat'].indexOf(k) < 0) {
91
- nd.addProp(k, v);
92
- }
93
- }
94
- nd.setLatLng(node);
95
- if (node.$innerNodes) {
96
- for (const ind of node.$innerNodes) {
97
- if (ind.$tag === 'tag') {
98
- nd.addTag(ind.k, ind.v);
99
- }
100
- }
101
- }
102
- });
103
- xmlParser.on('</osm.way>', (node) => {
104
- const way = new osmobjs_1.Way(node.id, refElements);
105
- for (const [k, v] of Object.entries(node)) {
106
- if (!k.startsWith('$') && ['id'].indexOf(k) < 0) {
107
- way.addProp(k, v);
108
- }
109
- }
110
- if (node.$innerNodes) {
111
- for (const ind of node.$innerNodes) {
112
- if (ind.$tag === 'nd') {
113
- if (ind.lon && ind.lat) {
114
- way.addLatLng(ind);
115
- }
116
- else if (ind.ref) {
117
- way.addNodeRef(ind.ref);
118
- }
119
- }
120
- else if (ind.$tag === 'tag') {
121
- way.addTag(ind.k, ind.v);
122
- }
123
- }
124
- }
125
- });
126
- xmlParser.on('<osm.relation>', (node) => new osmobjs_1.Relation(node.id, refElements));
127
- xmlParser.on('</osm.relation.member>', (node, parent) => {
128
- const relation = refElements.get(`relation/${parent === null || parent === void 0 ? void 0 : parent.id}`);
129
- const member = {
130
- type: node.type,
131
- role: node.role ? node.role : '',
132
- ref: node.ref,
133
- };
134
- if (node.lat && node.lon) {
135
- member.lat = node.lat, member.lon = node.lon, member.tags = {};
136
- for (const [k, v] of Object.entries(node)) {
137
- if (!k.startsWith('$') && ['type', 'lat', 'lon'].indexOf(k) < 0) {
138
- member[k] = v;
139
- }
140
- }
141
- }
142
- if (node.$innerNodes) {
143
- const geometry = [];
144
- const nodes = [];
145
- for (const ind of node.$innerNodes) {
146
- if (ind.lat && ind.lon) {
147
- geometry.push(ind);
148
- }
149
- else if (ind.ref) {
150
- nodes.push(ind.ref);
151
- }
152
- }
153
- if (geometry.length > 0) {
154
- member.geometry = geometry;
155
- }
156
- else if (nodes.length > 0) {
157
- member.nodes = nodes;
158
- }
159
- }
160
- relation.addMember(member);
161
- });
162
- xmlParser.on('</osm.relation.bounds>', (node, parent) => {
163
- refElements.get(`relation/${parent === null || parent === void 0 ? void 0 : parent.id}`).setBounds([parseFloat(node.minlon), parseFloat(node.minlat), parseFloat(node.maxlon), parseFloat(node.maxlat)]);
164
- });
165
- xmlParser.on('</osm.relation.tag>', (node, parent) => {
166
- refElements.get(`relation/${parent === null || parent === void 0 ? void 0 : parent.id}`).addTag(node.k, node.v);
167
- });
168
- xmlParser.parse(o);
169
- };
170
- if (format === 'json-raw') {
171
- osm = JSON.parse(osm);
172
- if (osm.elements) {
173
- format = 'json';
174
- }
175
- else {
176
- format = 'invalid';
177
- }
178
- }
179
- if (format === 'json') {
180
- analyzeFeaturesFromJson(osm);
181
- }
182
- else if (format === 'xml') {
183
- analyzeFeaturesFromXml(osm);
184
- }
185
- refElements.bindAll();
186
- for (const v of refElements.values()) {
187
- if (v.refCount <= 0 || (v.hasTag && renderTagged && !(v instanceof osmobjs_1.Way && excludeWay))) {
188
- const features = v.toFeatureArray();
189
- // return the first geometry of the first relation element
190
- if (v instanceof osmobjs_1.Relation && !completeFeature && features.length > 0) {
191
- return features[0].geometry;
192
- }
193
- featureArray = featureArray.concat(features);
194
- }
195
- }
196
- return { type: 'FeatureCollection', features: featureArray };
197
- }
198
- ;
199
- module.exports = osm2geojson;
@@ -1,377 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.Relation = exports.Way = exports.Node = void 0;
7
- const utils_1 = require("./utils");
8
- const utils_2 = require("./utils");
9
- const polytags_json_1 = __importDefault(require("./polytags.json"));
10
- class OsmObject {
11
- constructor(type, id, refElems) {
12
- this.type = type;
13
- this.id = id;
14
- this.refElems = refElems;
15
- this.tags = {};
16
- this.props = { id: this.getCompositeId() };
17
- this.refCount = 0;
18
- this.hasTag = false;
19
- if (refElems) {
20
- refElems.add(this.getCompositeId(), this);
21
- }
22
- }
23
- addTags(tags) {
24
- this.tags = Object.assign(this.tags, tags);
25
- this.hasTag = tags ? true : false;
26
- }
27
- addTag(k, v) {
28
- this.tags[k] = v;
29
- this.hasTag = k ? true : false;
30
- }
31
- addProp(k, v) {
32
- this.props[k] = v;
33
- }
34
- addProps(props) {
35
- this.props = Object.assign(this.props, props);
36
- }
37
- getCompositeId() {
38
- return `${this.type}/${this.id}`;
39
- }
40
- getProps() {
41
- return Object.assign(this.props, this.tags);
42
- }
43
- toFeatureArray() {
44
- return [];
45
- }
46
- }
47
- class Node extends OsmObject {
48
- constructor(id, refElems) {
49
- super('node', id, refElems);
50
- this.latLng = null;
51
- }
52
- setLatLng(latLng) {
53
- this.latLng = latLng;
54
- }
55
- toFeatureArray() {
56
- if (this.latLng) {
57
- return [{
58
- type: 'Feature',
59
- id: this.getCompositeId(),
60
- properties: this.getProps(),
61
- geometry: {
62
- type: 'Point',
63
- coordinates: (0, utils_1.strToFloat)([this.latLng.lon, this.latLng.lat]),
64
- },
65
- }];
66
- }
67
- return [];
68
- }
69
- getLatLng() {
70
- return this.latLng;
71
- }
72
- }
73
- exports.Node = Node;
74
- class Way extends OsmObject {
75
- constructor(id, refElems) {
76
- super('way', id, refElems);
77
- this.latLngArray = [];
78
- this.isPolygon = false;
79
- }
80
- addLatLng(latLng) {
81
- this.latLngArray.push(latLng);
82
- }
83
- setLatLngArray(latLngArray) {
84
- this.latLngArray = latLngArray;
85
- }
86
- addNodeRef(ref) {
87
- const binder = new utils_2.LateBinder(this.latLngArray, (id) => {
88
- const node = this.refElems.get(`node/${id}`);
89
- if (node) {
90
- node.refCount++;
91
- return node.getLatLng();
92
- }
93
- }, this, [ref]);
94
- this.latLngArray.push(binder);
95
- this.refElems.addBinder(binder);
96
- }
97
- addTags(tags) {
98
- super.addTags(tags);
99
- for (const [k, v] of Object.entries(tags)) {
100
- this.analyzeTag(k, v);
101
- }
102
- }
103
- addTag(k, v) {
104
- super.addTag(k, v);
105
- this.analyzeTag(k, v);
106
- }
107
- toCoordsArray() {
108
- return this.latLngArray.map((latLng) => [latLng.lon, latLng.lat]);
109
- }
110
- toFeatureArray() {
111
- let coordsArray = this.toCoordsArray();
112
- if (coordsArray.length > 1) {
113
- coordsArray = (0, utils_1.strToFloat)(coordsArray);
114
- const feature = {
115
- type: 'Feature',
116
- id: this.getCompositeId(),
117
- properties: this.getProps(),
118
- geometry: {
119
- type: 'LineString',
120
- coordinates: coordsArray,
121
- },
122
- };
123
- if (this.isPolygon && (0, utils_1.isRing)(coordsArray)) {
124
- if ((0, utils_1.ringDirection)(coordsArray) !== 'counterclockwise') {
125
- coordsArray.reverse();
126
- }
127
- feature.geometry = {
128
- type: 'Polygon',
129
- coordinates: [coordsArray],
130
- };
131
- return [feature];
132
- }
133
- return [feature];
134
- }
135
- return [];
136
- }
137
- analyzeTag(k, v) {
138
- const o = polytags_json_1.default[k];
139
- if (o) {
140
- this.isPolygon = true;
141
- if (o.whitelist) {
142
- this.isPolygon = o.whitelist.indexOf(v) >= 0 ? true : false;
143
- }
144
- else if (o.blacklist) {
145
- this.isPolygon = o.blacklist.indexOf(v) >= 0 ? false : true;
146
- }
147
- }
148
- }
149
- }
150
- exports.Way = Way;
151
- class Relation extends OsmObject {
152
- constructor(id, refElems) {
153
- super('relation', id, refElems);
154
- this.relations = [];
155
- this.nodes = [];
156
- this.bounds = undefined;
157
- }
158
- setBounds(bounds) {
159
- this.bounds = bounds;
160
- }
161
- addMember(member) {
162
- switch (member.type) {
163
- // super relation, need to do combination
164
- case 'relation':
165
- let binder = new utils_2.LateBinder(this.relations, (id) => {
166
- const relation = this.refElems.get(`relation/${id}`);
167
- if (relation) {
168
- relation.refCount++;
169
- return relation;
170
- }
171
- }, this, [member.ref]);
172
- this.relations.push(binder);
173
- this.refElems.addBinder(binder);
174
- break;
175
- case 'way':
176
- if (!member.role) {
177
- member.role = '';
178
- }
179
- let ways = this[member.role];
180
- if (!ways) {
181
- ways = this[member.role] = [];
182
- }
183
- if (member.geometry) {
184
- const way = new Way(member.ref, this.refElems);
185
- way.setLatLngArray(member.geometry);
186
- way.refCount++;
187
- ways.push(way);
188
- }
189
- else if (member.nodes) {
190
- const way = new Way(member.ref, this.refElems);
191
- for (const nid of member.nodes) {
192
- way.addNodeRef(nid);
193
- }
194
- way.refCount++;
195
- ways.push(way);
196
- }
197
- else {
198
- let binder = new utils_2.LateBinder(ways, (nid) => {
199
- const way = this.refElems.get(`way/${nid}`);
200
- if (way) {
201
- way.refCount++;
202
- return way;
203
- }
204
- }, this, [member.ref]);
205
- ways.push(binder);
206
- this.refElems.addBinder(binder);
207
- }
208
- break;
209
- case 'node':
210
- let node = null;
211
- if (member.lat && member.lon) {
212
- node = new Node(member.ref, this.refElems);
213
- node.setLatLng({ lon: member.lon, lat: member.lat });
214
- if (member.tags) {
215
- node.addTags(member.tags);
216
- }
217
- for (const [k, v] of Object.entries(member)) {
218
- if (['id', 'type', 'lat', 'lon'].indexOf(k) < 0) {
219
- node.addProp(k, v);
220
- }
221
- }
222
- node.refCount++;
223
- this.nodes.push(node);
224
- }
225
- else {
226
- let binder = new utils_2.LateBinder(this.nodes, (id) => {
227
- const nn = this.refElems.get(`node/${id}`);
228
- if (nn) {
229
- nn.refCount++;
230
- return nn;
231
- }
232
- }, this, [member.ref]);
233
- this.nodes.push(binder);
234
- this.refElems.addBinder(binder);
235
- }
236
- default:
237
- break;
238
- }
239
- }
240
- toFeatureArray() {
241
- function constructStringGeometry(ws) {
242
- const strings = ws ? ws.toStrings() : [];
243
- if (strings.length > 0) {
244
- if (strings.length === 1) {
245
- return {
246
- type: 'LineString',
247
- coordinates: strings[0],
248
- };
249
- }
250
- return {
251
- type: 'MultiLineString',
252
- coordinates: strings,
253
- };
254
- }
255
- return null;
256
- }
257
- function constructPolygonGeometry(ows, iws) {
258
- const outerRings = ows ? ows.toRings('counterclockwise') : [];
259
- const innerRings = iws ? iws.toRings('clockwise') : [];
260
- if (outerRings.length > 0) {
261
- const compositPolyons = [];
262
- let ring;
263
- for (ring of outerRings) {
264
- compositPolyons.push([ring]);
265
- }
266
- // link inner polygons to outer containers
267
- ring = innerRings.shift();
268
- while (ring) {
269
- for (const idx in outerRings) {
270
- if ((0, utils_1.ptInsidePolygon)((0, utils_1.first)(ring), outerRings[idx])) {
271
- compositPolyons[idx].push(ring);
272
- break;
273
- }
274
- }
275
- ring = innerRings.shift();
276
- }
277
- // construct the Polygon/MultiPolygon geometry
278
- if (compositPolyons.length === 1) {
279
- return {
280
- type: 'Polygon',
281
- coordinates: compositPolyons[0],
282
- };
283
- }
284
- return {
285
- type: 'MultiPolygon',
286
- coordinates: compositPolyons,
287
- };
288
- }
289
- return null;
290
- }
291
- const polygonFeatures = [];
292
- const stringFeatures = [];
293
- let pointFeatures = [];
294
- // need to do combination when there're nested relations
295
- const notWayFields = ['type', 'id', 'refElems', 'tags', 'props', 'refCount', 'hasTag', 'relations', 'nodes', 'bounds'];
296
- for (const relation of this.relations) {
297
- if (relation) {
298
- let waysFieldNames = Object.keys(relation).filter(fieldName => notWayFields.indexOf(fieldName) < 0);
299
- for (const fieldName of waysFieldNames) {
300
- const ways = relation[fieldName];
301
- if (ways) {
302
- const thisWays = this[fieldName];
303
- if (thisWays) {
304
- thisWays.push(...ways);
305
- }
306
- else {
307
- this[fieldName] = ways;
308
- }
309
- }
310
- }
311
- }
312
- }
313
- let waysFieldNames = Object.keys(this).filter(fieldName => notWayFields.indexOf(fieldName) < 0);
314
- for (const fieldName of waysFieldNames) {
315
- const ways = this[fieldName];
316
- if (ways) {
317
- this[fieldName] = new utils_2.WayCollection();
318
- for (const way of ways) {
319
- this[fieldName].addWay(way);
320
- }
321
- }
322
- }
323
- let geometry = null;
324
- let templateFeature = {
325
- type: 'Feature',
326
- id: this.getCompositeId(),
327
- bbox: this.bounds,
328
- properties: this.getProps(),
329
- geometry: null
330
- };
331
- if (!this.bounds) {
332
- delete templateFeature.bbox;
333
- }
334
- if (this.outer) {
335
- let feature = Object.assign({}, templateFeature);
336
- let geometry = constructPolygonGeometry(this.outer, this.inner);
337
- if (geometry) {
338
- feature.geometry = geometry;
339
- polygonFeatures.push(feature);
340
- }
341
- }
342
- else {
343
- let multiLineGeometry = {
344
- type: 'MultiLineString',
345
- coordinates: []
346
- };
347
- for (let way of waysFieldNames) {
348
- if (way != null && way !== 'inner') {
349
- let ws = this[way];
350
- if (ws) {
351
- let geometry = constructStringGeometry(ws);
352
- if (geometry) {
353
- if (geometry.type === 'LineString') {
354
- multiLineGeometry.coordinates.push(geometry.coordinates);
355
- }
356
- else if (geometry.type === 'MultiLineString') {
357
- let feature = Object.assign({}, templateFeature);
358
- feature.geometry = geometry;
359
- stringFeatures.push(feature);
360
- }
361
- }
362
- }
363
- }
364
- }
365
- if (multiLineGeometry.coordinates.length > 0) {
366
- let feature = Object.assign({}, templateFeature);
367
- feature.geometry = multiLineGeometry;
368
- stringFeatures.push(feature);
369
- }
370
- }
371
- for (let node of this.nodes) {
372
- pointFeatures = pointFeatures.concat(node.toFeatureArray());
373
- }
374
- return [...polygonFeatures, ...stringFeatures, ...pointFeatures];
375
- }
376
- }
377
- exports.Relation = Relation;
@@ -1,84 +0,0 @@
1
- {
2
- "building": {},
3
- "highway": {
4
- "whitelist": [
5
- "services",
6
- "rest_area",
7
- "escape",
8
- "elevator"
9
- ]
10
- },
11
- "natural": {
12
- "blacklist": [
13
- "coastline",
14
- "cliff",
15
- "ridge",
16
- "arete",
17
- "tree_row"
18
- ]
19
- },
20
- "landuse": {},
21
- "waterway": {
22
- "whitelist": [
23
- "riverbank",
24
- "dock",
25
- "boatyard",
26
- "dam"
27
- ]
28
- },
29
- "amenity": {},
30
- "leisure": {},
31
- "barrier": {
32
- "whitelist": [
33
- "city_wall",
34
- "ditch",
35
- "hedge",
36
- "retaining_wall",
37
- "wall",
38
- "spikes"
39
- ]
40
- },
41
- "railway": {
42
- "whitelist": [
43
- "station",
44
- "turntable",
45
- "roundhouse",
46
- "platform"
47
- ]
48
- },
49
- "area": {},
50
- "boundary": {},
51
- "man_made": {
52
- "blacklist": [
53
- "cutline",
54
- "embankment",
55
- "pipeline"
56
- ]
57
- },
58
- "power": {
59
- "whitelist": [
60
- "plant",
61
- "substation",
62
- "generator",
63
- "transformer"
64
- ]
65
- },
66
- "place": {},
67
- "shop": {},
68
- "aeroway": {
69
- "blacklist": [
70
- "taxiway"
71
- ]
72
- },
73
- "tourism": {},
74
- "historic": {},
75
- "public_transport": {},
76
- "office": {},
77
- "building:part": {},
78
- "military": {},
79
- "ruins": {},
80
- "area:highway": {},
81
- "craft": {},
82
- "golf": {},
83
- "indoor": {}
84
- }
@@ -1,222 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.WayCollection = exports.RefElements = exports.LateBinder = exports.strToFloat = exports.ptInsidePolygon = exports.ringDirection = exports.isRing = exports.coordsToKey = exports.last = exports.first = void 0;
4
- exports.purgeProps = purgeProps;
5
- exports.mergeProps = mergeProps;
6
- exports.addPropToFeature = addPropToFeature;
7
- exports.addPropToFeatures = addPropToFeatures;
8
- exports.addToMap = addToMap;
9
- exports.removeFromMap = removeFromMap;
10
- exports.getFirstFromMap = getFirstFromMap;
11
- function purgeProps(obj, blacklist) {
12
- if (obj) {
13
- const rs = Object.assign({}, obj);
14
- if (blacklist) {
15
- for (const prop of blacklist) {
16
- delete rs[prop];
17
- }
18
- }
19
- return rs;
20
- }
21
- return {};
22
- }
23
- function mergeProps(obj1, obj2) {
24
- obj1 = obj1 ? obj1 : {};
25
- obj2 = obj2 ? obj2 : {};
26
- return Object.assign(obj1, obj2);
27
- }
28
- function addPropToFeature(f, k, v) {
29
- if (f.properties && k && v) {
30
- f.properties[k] = v;
31
- }
32
- }
33
- function addPropToFeatures(fs, k, v) {
34
- for (const f of fs) {
35
- addPropToFeature(f, k, v);
36
- }
37
- }
38
- const first = (a) => a[0];
39
- exports.first = first;
40
- const last = (a) => a[a.length - 1];
41
- exports.last = last;
42
- const coordsToKey = (a) => a.join(',');
43
- exports.coordsToKey = coordsToKey;
44
- function addToMap(m, k, v) {
45
- const a = m[k];
46
- if (a) {
47
- a.push(v);
48
- }
49
- else {
50
- m[k] = [v];
51
- }
52
- }
53
- function removeFromMap(m, k, v) {
54
- const a = m[k];
55
- let idx = -1;
56
- if (a) {
57
- idx = a.indexOf(v);
58
- }
59
- if (idx >= 0) {
60
- a.splice(idx, 1);
61
- }
62
- }
63
- function getFirstFromMap(m, k) {
64
- const a = m[k];
65
- if (a && a.length > 0) {
66
- return a[0];
67
- }
68
- return null;
69
- }
70
- // need 3+ different points to form a ring, here using > 3 is 'coz a the first and the last points are actually the same
71
- const isRing = (a) => a.length > 3 && (0, exports.coordsToKey)((0, exports.first)(a)) === (0, exports.coordsToKey)((0, exports.last)(a));
72
- exports.isRing = isRing;
73
- const ringDirection = (a, xIdx, yIdx) => {
74
- xIdx = xIdx || 0, yIdx = yIdx || 1;
75
- // get the index of the point which has the maximum x value
76
- const m = a.reduce((maxxIdx, v, idx) => a[maxxIdx][xIdx || 0] > v[xIdx || 0] ? maxxIdx : idx, 0);
77
- // 'coz the first point is virtually the same one as the last point,
78
- // we need to skip a.length - 1 for left when m = 0,
79
- // and skip 0 for right when m = a.length - 1;
80
- const l = m <= 0 ? a.length - 2 : m - 1;
81
- const r = m >= a.length - 1 ? 1 : m + 1;
82
- const xa = a[l][xIdx];
83
- const xb = a[m][xIdx];
84
- const xc = a[r][xIdx];
85
- const ya = a[l][yIdx];
86
- const yb = a[m][yIdx];
87
- const yc = a[r][yIdx];
88
- const det = (xb - xa) * (yc - ya) - (xc - xa) * (yb - ya);
89
- return det < 0 ? 'clockwise' : 'counterclockwise';
90
- };
91
- exports.ringDirection = ringDirection;
92
- const ptInsidePolygon = (pt, polygon, xIdx, yIdx) => {
93
- xIdx = xIdx || 0, yIdx = yIdx || 1;
94
- let result = false;
95
- for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
96
- if ((polygon[i][xIdx] <= pt[xIdx] && pt[xIdx] < polygon[j][xIdx] ||
97
- polygon[j][xIdx] <= pt[xIdx] && pt[xIdx] < polygon[i][xIdx]) &&
98
- pt[yIdx] < (polygon[j][yIdx] - polygon[i][yIdx]) * (pt[xIdx] - polygon[i][xIdx]) / (polygon[j][xIdx] - polygon[i][xIdx]) + polygon[i][yIdx]) {
99
- result = !result;
100
- }
101
- }
102
- return result;
103
- };
104
- exports.ptInsidePolygon = ptInsidePolygon;
105
- const strToFloat = (el) => el instanceof Array ? el.map(exports.strToFloat) : parseFloat(el);
106
- exports.strToFloat = strToFloat;
107
- class LateBinder {
108
- constructor(container, valueFunc, ctx, args) {
109
- this.container = container;
110
- this.valueFunc = valueFunc;
111
- this.ctx = ctx;
112
- this.args = args;
113
- }
114
- bind() {
115
- const v = this.valueFunc.apply(this.ctx, this.args);
116
- if (this.container instanceof Array) {
117
- const idx = this.container.indexOf(this);
118
- if (idx >= 0) {
119
- const args = [idx, 1];
120
- if (v) {
121
- args.push(v);
122
- }
123
- Array.prototype.splice.apply(this.container, args);
124
- }
125
- }
126
- else if (typeof this.container === 'object' && !Array.isArray(this.container)) {
127
- const container = this.container;
128
- const k = Object.keys(container).find((nv) => container[nv] === this);
129
- if (k) {
130
- if (v) {
131
- container[k] = v;
132
- }
133
- else {
134
- delete container[k];
135
- }
136
- }
137
- }
138
- }
139
- }
140
- exports.LateBinder = LateBinder;
141
- class RefElements extends Map {
142
- constructor() {
143
- super();
144
- this.binders = [];
145
- }
146
- add(k, v) {
147
- this.set(k, v);
148
- }
149
- addBinder(binder) {
150
- this.binders.push(binder);
151
- }
152
- bindAll() {
153
- this.binders.forEach((binder) => binder.bind());
154
- }
155
- }
156
- exports.RefElements = RefElements;
157
- class WayCollection extends Array {
158
- constructor() {
159
- super();
160
- this.firstMap = {};
161
- this.lastMap = {};
162
- }
163
- addWay(way) {
164
- const w = way.toCoordsArray();
165
- if (w.length > 0) {
166
- this.push(w);
167
- addToMap(this.firstMap, (0, exports.coordsToKey)((0, exports.first)(w)), w);
168
- addToMap(this.lastMap, (0, exports.coordsToKey)((0, exports.last)(w)), w);
169
- }
170
- }
171
- toStrings() {
172
- const strings = [];
173
- let way = this.shift();
174
- while (way) {
175
- removeFromMap(this.firstMap, (0, exports.coordsToKey)((0, exports.first)(way)), way);
176
- removeFromMap(this.lastMap, (0, exports.coordsToKey)((0, exports.last)(way)), way);
177
- let current = way;
178
- let next;
179
- do {
180
- const key = (0, exports.coordsToKey)((0, exports.last)(current));
181
- let shouldReverse = false;
182
- next = getFirstFromMap(this.firstMap, key);
183
- if (!next) {
184
- next = getFirstFromMap(this.lastMap, key);
185
- shouldReverse = true;
186
- }
187
- if (next) {
188
- this.splice(this.indexOf(next), 1);
189
- removeFromMap(this.firstMap, (0, exports.coordsToKey)((0, exports.first)(next)), next);
190
- removeFromMap(this.lastMap, (0, exports.coordsToKey)((0, exports.last)(next)), next);
191
- if (shouldReverse) {
192
- // always reverse shorter one to save time
193
- if (next.length > current.length) {
194
- [current, next] = [next, current];
195
- }
196
- next.reverse();
197
- }
198
- current = current.concat(next.slice(1));
199
- }
200
- } while (next);
201
- strings.push((0, exports.strToFloat)(current));
202
- way = this.shift();
203
- }
204
- return strings;
205
- }
206
- toRings(direction) {
207
- const strings = this.toStrings();
208
- const rings = [];
209
- let str = strings.shift();
210
- while (str) {
211
- if ((0, exports.isRing)(str)) {
212
- if ((0, exports.ringDirection)(str) !== direction) {
213
- str.reverse();
214
- }
215
- rings.push(str);
216
- }
217
- str = strings.shift();
218
- }
219
- return rings;
220
- }
221
- }
222
- exports.WayCollection = WayCollection;
@@ -1,160 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- function conditioned(evt) {
4
- return evt.match(/^(.+?)\[(.+?)\]>$/g) !== null;
5
- }
6
- function parseEvent(evt) {
7
- const match = /^(.+?)\[(.+?)\]>$/g.exec(evt);
8
- if (match) {
9
- return { evt: match[1] + '>', exp: match[2] };
10
- }
11
- return { evt };
12
- }
13
- function genConditionFunc(cond) {
14
- const body = 'return ' + cond.replace(/(\$.+?)(?=[=!.])/g, 'node.$&') + ';';
15
- return new Function('node', body);
16
- }
17
- class default_1 {
18
- constructor(opts) {
19
- this.queryParent = false;
20
- this.progressive = false;
21
- this.parentMap = new WeakMap();
22
- if (opts) {
23
- this.queryParent = opts.queryParent ? true : false;
24
- this.progressive = opts.progressive;
25
- if (this.queryParent) {
26
- this.parentMap = new WeakMap();
27
- }
28
- }
29
- this.evtListeners = {};
30
- }
31
- parse(xml, parent, dir) {
32
- dir = dir ? dir + '.' : '';
33
- const nodeRegEx = /<([^ >\/]+)(.*?)>/mg;
34
- const nodes = [];
35
- let nodeMatch = nodeRegEx.exec(xml);
36
- while (nodeMatch) {
37
- const tag = nodeMatch[1];
38
- const node = { $tag: tag };
39
- const fullTag = dir + tag;
40
- const attrText = nodeMatch[2].trim();
41
- let closed = false;
42
- if (attrText.endsWith('/') || tag.startsWith('?') || tag.startsWith('!')) {
43
- closed = true;
44
- }
45
- const attRegEx1 = /([^ ]+?)="(.+?)"/g;
46
- const attRegEx2 = /([^ ]+?)='(.+?)'/g;
47
- let attMatch = attRegEx1.exec(attrText);
48
- let hasAttrs = false;
49
- while (attMatch) {
50
- hasAttrs = true;
51
- node[attMatch[1]] = attMatch[2];
52
- attMatch = attRegEx1.exec(attrText);
53
- }
54
- if (!hasAttrs) {
55
- attMatch = attRegEx2.exec(attrText);
56
- while (attMatch) {
57
- hasAttrs = true;
58
- node[attMatch[1]] = attMatch[2];
59
- attMatch = attRegEx2.exec(attrText);
60
- }
61
- }
62
- if (!hasAttrs && attrText !== '') {
63
- node.text = attrText;
64
- }
65
- if (this.progressive) {
66
- this.emit(`<${fullTag}>`, node, parent);
67
- }
68
- if (!closed) {
69
- const innerRegEx = new RegExp(`([^]+?)<\/${tag}>`, 'g');
70
- innerRegEx.lastIndex = nodeRegEx.lastIndex;
71
- const innerMatch = innerRegEx.exec(xml);
72
- if (innerMatch && innerMatch[1]) {
73
- nodeRegEx.lastIndex = innerRegEx.lastIndex;
74
- const innerNodes = this.parse(innerMatch[1], node, fullTag);
75
- if (innerNodes.length > 0) {
76
- node.$innerNodes = innerNodes;
77
- }
78
- else {
79
- node.$innerText = innerMatch[1];
80
- }
81
- }
82
- }
83
- if (this.queryParent && parent) {
84
- this.parentMap.set(node, parent);
85
- }
86
- if (this.progressive) {
87
- this.emit(`</${fullTag}>`, node, parent);
88
- }
89
- nodes.push(node);
90
- nodeMatch = nodeRegEx.exec(xml);
91
- }
92
- return nodes;
93
- }
94
- getParent(node) {
95
- if (this.queryParent) {
96
- return this.parentMap.get(node);
97
- }
98
- return null;
99
- }
100
- // support javascript condition for the last tag
101
- addListener(evt, func) {
102
- if (conditioned(evt)) {
103
- // func.prototype = evt;
104
- const ev = parseEvent(evt);
105
- if (ev.exp) {
106
- func.condition = genConditionFunc(ev.exp);
107
- }
108
- evt = ev.evt;
109
- }
110
- this.$addListener(evt, func);
111
- }
112
- removeListener(evt, func) {
113
- if (conditioned(evt)) {
114
- const ev = parseEvent(evt);
115
- evt = ev.evt;
116
- }
117
- this.$removeListener(evt, func);
118
- }
119
- on(evt, func) {
120
- this.addListener(evt, func);
121
- }
122
- off(evt, func) {
123
- this.removeListener(evt, func);
124
- }
125
- $addListener(evt, func) {
126
- const funcs = this.evtListeners[evt];
127
- if (funcs) {
128
- funcs.push(func);
129
- }
130
- else {
131
- this.evtListeners[evt] = [func];
132
- }
133
- }
134
- $removeListener(evt, func) {
135
- const funcs = this.evtListeners[evt];
136
- let idx = -1;
137
- if (funcs) {
138
- idx = funcs.indexOf(func);
139
- }
140
- if (idx >= 0) {
141
- funcs.splice(idx, 1);
142
- }
143
- }
144
- emit(evt, ...args) {
145
- const funcs = this.evtListeners[evt];
146
- if (funcs) {
147
- for (const func of funcs) {
148
- if (func.condition) {
149
- if (func.condition.apply(null, args) === true) {
150
- func.apply(null, args);
151
- }
152
- }
153
- else {
154
- func.apply(null, args);
155
- }
156
- }
157
- }
158
- }
159
- }
160
- exports.default = default_1;
@@ -1 +0,0 @@
1
- !function(e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).osm2geojson=e()}(function(){return function s(i,o,n){function a(t,e){if(!o[t]){if(!i[t]){var r="function"==typeof require&&require;if(!e&&r)return r(t,!0);if(l)return l(t,!0);throw(e=new Error("Cannot find module '"+t+"'")).code="MODULE_NOT_FOUND",e}r=o[t]={exports:{}},i[t][0].call(r.exports,function(e){return a(i[t][1][e]||e)},r,r.exports,s,i,o,n)}return o[t].exports}for(var l="function"==typeof require&&require,e=0;e<n.length;e++)a(n[e]);return a}({1:[function(e,t,r){let s=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}},f=e("./osmobjs"),u=e("./utils"),p=s(e("./xmlparser"));t.exports=function(n,e){let t=!1,r=!1,s=!0,i=(e&&(e=e)&&(t=!(!e.completeFeature&&!e.allFeatures),r=!!e.renderTagged,void 0===(e=e.suppressWay||e.excludeWay)||e||(s=!1)),(e=n).elements?"json":0<=e.indexOf("<osm")?"xml":e.trim().startsWith("{")?"json-raw":"invalid"),l=new u.RefElements,o=[];var a,d;"json-raw"===i&&(n=JSON.parse(n),i=n.elements?"json":"invalid"),"json"===i?(()=>{for(var e of n.elements)switch(e.type){case"node":var t=new f.Node(e.id,l);e.tags&&t.addTags(e.tags),t.addProps((0,u.purgeProps)(e,["id","type","tags","lat","lon"])),t.setLatLng(e);break;case"way":var r=new f.Way(e.id,l);if(e.tags&&r.addTags(e.tags),r.addProps((0,u.purgeProps)(e,["id","type","tags","nodes","geometry"])),e.geometry)r.setLatLngArray(e.geometry);else if(e.nodes)for(var s of e.nodes)r.addNodeRef(s);break;case"relation":var i=new f.Relation(e.id,l);if(e.bounds&&i.setBounds([parseFloat(e.bounds.minlon),parseFloat(e.bounds.minlat),parseFloat(e.bounds.maxlon),parseFloat(e.bounds.maxlat)]),e.tags&&i.addTags(e.tags),i.addProps((0,u.purgeProps)(e,["id","type","tags","bounds","members"])),e.members)for(var o of e.members)i.addMember(o)}})():"xml"===i&&(e=n,(a=new p.default({progressive:!0})).on("</osm.node>",e=>{var t,r,s=new f.Node(e.id,l);for([t,r]of Object.entries(e))!t.startsWith("$")&&["id","lon","lat"].indexOf(t)<0&&s.addProp(t,r);if(s.setLatLng(e),e.$innerNodes)for(var i of e.$innerNodes)"tag"===i.$tag&&s.addTag(i.k,i.v)}),a.on("</osm.way>",e=>{var t,r,s=new f.Way(e.id,l);for([t,r]of Object.entries(e))!t.startsWith("$")&&["id"].indexOf(t)<0&&s.addProp(t,r);if(e.$innerNodes)for(var i of e.$innerNodes)"nd"===i.$tag?i.lon&&i.lat?s.addLatLng(i):i.ref&&s.addNodeRef(i.ref):"tag"===i.$tag&&s.addTag(i.k,i.v)}),a.on("<osm.relation>",e=>new f.Relation(e.id,l)),a.on("</osm.relation.member>",(e,t)=>{var t=l.get("relation/"+(null==t?void 0:t.id)),r={type:e.type,role:e.role||"",ref:e.ref};if(e.lat&&e.lon){r.lat=e.lat,r.lon=e.lon,r.tags={};for(var[s,i]of Object.entries(e))!s.startsWith("$")&&["type","lat","lon"].indexOf(s)<0&&(r[s]=i)}if(e.$innerNodes){var o,n=[],a=[];for(o of e.$innerNodes)o.lat&&o.lon?n.push(o):o.ref&&a.push(o.ref);0<n.length?r.geometry=n:0<a.length&&(r.nodes=a)}t.addMember(r)}),a.on("</osm.relation.bounds>",(e,t)=>{l.get("relation/"+(null==t?void 0:t.id)).setBounds([parseFloat(e.minlon),parseFloat(e.minlat),parseFloat(e.maxlon),parseFloat(e.maxlat)])}),a.on("</osm.relation.tag>",(e,t)=>{l.get("relation/"+(null==t?void 0:t.id)).addTag(e.k,e.v)}),a.parse(e)),l.bindAll();for(d of l.values())if(d.refCount<=0||d.hasTag&&r&&!(d instanceof f.Way&&s)){var h=d.toFeatureArray();if(d instanceof f.Relation&&!t&&0<h.length)return h[0].geometry;o=o.concat(h)}return{type:"FeatureCollection",features:o}}},{"./osmobjs":2,"./utils":4,"./xmlparser":5}],2:[function(e,t,r){var s=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(r,"__esModule",{value:!0}),r.Relation=r.Way=r.Node=void 0;let w=e("./utils"),L=e("./utils"),i=s(e("./polytags.json"));class o{constructor(e,t,r){this.type=e,this.id=t,this.refElems=r,this.tags={},this.props={id:this.getCompositeId()},this.refCount=0,this.hasTag=!1,r&&r.add(this.getCompositeId(),this)}addTags(e){this.tags=Object.assign(this.tags,e),this.hasTag=!!e}addTag(e,t){this.tags[e]=t,this.hasTag=!!e}addProp(e,t){this.props[e]=t}addProps(e){this.props=Object.assign(this.props,e)}getCompositeId(){return this.type+"/"+this.id}getProps(){return Object.assign(this.props,this.tags)}toFeatureArray(){return[]}}class l extends o{constructor(e,t){super("node",e,t),this.latLng=null}setLatLng(e){this.latLng=e}toFeatureArray(){return this.latLng?[{type:"Feature",id:this.getCompositeId(),properties:this.getProps(),geometry:{type:"Point",coordinates:(0,w.strToFloat)([this.latLng.lon,this.latLng.lat])}}]:[]}getLatLng(){return this.latLng}}r.Node=l;class d extends o{constructor(e,t){super("way",e,t),this.latLngArray=[],this.isPolygon=!1}addLatLng(e){this.latLngArray.push(e)}setLatLngArray(e){this.latLngArray=e}addNodeRef(e){e=new L.LateBinder(this.latLngArray,e=>{e=this.refElems.get("node/"+e);if(e)return e.refCount++,e.getLatLng()},this,[e]);this.latLngArray.push(e),this.refElems.addBinder(e)}addTags(e){super.addTags(e);for(var[t,r]of Object.entries(e))this.analyzeTag(t,r)}addTag(e,t){super.addTag(e,t),this.analyzeTag(e,t)}toCoordsArray(){return this.latLngArray.map(e=>[e.lon,e.lat])}toFeatureArray(){var e,t=this.toCoordsArray();return 1<t.length?(t=(0,w.strToFloat)(t),e={type:"Feature",id:this.getCompositeId(),properties:this.getProps(),geometry:{type:"LineString",coordinates:t}},this.isPolygon&&(0,w.isRing)(t)&&("counterclockwise"!==(0,w.ringDirection)(t)&&t.reverse(),e.geometry={type:"Polygon",coordinates:[t]}),[e]):[]}analyzeTag(e,t){e=i.default[e];e&&(this.isPolygon=!0,e.whitelist?this.isPolygon=0<=e.whitelist.indexOf(t):e.blacklist&&(this.isPolygon=!(0<=e.blacklist.indexOf(t))))}}r.Way=d;class n extends o{constructor(e,t){super("relation",e,t),this.relations=[],this.nodes=[],this.bounds=void 0}setBounds(e){this.bounds=e}addMember(t){switch(t.type){case"relation":var r=new L.LateBinder(this.relations,e=>{e=this.refElems.get("relation/"+e);if(e)return e.refCount++,e},this,[t.ref]);this.relations.push(r),this.refElems.addBinder(r);break;case"way":t.role||(t.role="");let e=this[t.role];if(e=e||(this[t.role]=[]),t.geometry){r=new d(t.ref,this.refElems);r.setLatLngArray(t.geometry),r.refCount++,e.push(r)}else if(t.nodes){var s,i=new d(t.ref,this.refElems);for(s of t.nodes)i.addNodeRef(s);i.refCount++,e.push(i)}else{r=new L.LateBinder(e,e=>{e=this.refElems.get("way/"+e);if(e)return e.refCount++,e},this,[t.ref]);e.push(r),this.refElems.addBinder(r)}break;case"node":var o=null;if(t.lat&&t.lon){(o=new l(t.ref,this.refElems)).setLatLng({lon:t.lon,lat:t.lat}),t.tags&&o.addTags(t.tags);for(var[n,a]of Object.entries(t))["id","type","lat","lon"].indexOf(n)<0&&o.addProp(n,a);o.refCount++,this.nodes.push(o)}else{r=new L.LateBinder(this.nodes,e=>{e=this.refElems.get("node/"+e);if(e)return e.refCount++,e},this,[t.ref]);this.nodes.push(r),this.refElems.addBinder(r)}}}toFeatureArray(){var e,t,r=[],s=[];let i=[],o=["type","id","refElems","tags","props","refCount","hasTag","relations","nodes","bounds"];for(e of this.relations)if(e)for(t of Object.keys(e).filter(e=>o.indexOf(e)<0)){var n,a=e[t];a&&((n=this[t])?n.push(...a):this[t]=a)}var l,d=Object.keys(this).filter(e=>o.indexOf(e)<0);for(l of d){var h=this[l];if(h){this[l]=new L.WayCollection;for(var f of h)this[l].addWay(f)}}var u,p={type:"Feature",id:this.getCompositeId(),bbox:this.bounds,properties:this.getProps(),geometry:null};if(this.bounds||delete p.bbox,this.outer){var g=Object.assign({},p),c=((e,t)=>{var r=e?e.toRings("counterclockwise"):[],s=t?t.toRings("clockwise"):[];if(0<r.length){var i=[];let e;for(e of r)i.push([e]);for(e=s.shift();e;){for(var o in r)if((0,w.ptInsidePolygon)((0,w.first)(e),r[o])){i[o].push(e);break}e=s.shift()}return 1===i.length?{type:"Polygon",coordinates:i[0]}:{type:"MultiPolygon",coordinates:i}}return null})(this.outer,this.inner);c&&(g.geometry=c,r.push(g))}else{var y,m,v,b={type:"MultiLineString",coordinates:[]};for(y of d)null!=y&&"inner"!==y&&(m=this[y])&&(m=0<(m=(m=m)?m.toStrings():[]).length?1===m.length?{type:"LineString",coordinates:m[0]}:{type:"MultiLineString",coordinates:m}:null)&&("LineString"===m.type?b.coordinates.push(m.coordinates):"MultiLineString"===m.type&&((v=Object.assign({},p)).geometry=m,s.push(v)));0<b.coordinates.length&&((c=Object.assign({},p)).geometry=b,s.push(c))}for(u of this.nodes)i=i.concat(u.toFeatureArray());return[...r,...s,...i]}}r.Relation=n},{"./polytags.json":3,"./utils":4}],3:[function(e,t,r){t.exports={building:{},highway:{whitelist:["services","rest_area","escape","elevator"]},natural:{blacklist:["coastline","cliff","ridge","arete","tree_row"]},landuse:{},waterway:{whitelist:["riverbank","dock","boatyard","dam"]},amenity:{},leisure:{},barrier:{whitelist:["city_wall","ditch","hedge","retaining_wall","wall","spikes"]},railway:{whitelist:["station","turntable","roundhouse","platform"]},area:{},boundary:{},man_made:{blacklist:["cutline","embankment","pipeline"]},power:{whitelist:["plant","substation","generator","transformer"]},place:{},shop:{},aeroway:{blacklist:["taxiway"]},tourism:{},historic:{},public_transport:{},office:{},"building:part":{},military:{},ruins:{},"area:highway":{},craft:{},golf:{},indoor:{}}},{}],4:[function(e,t,o){function i(e,t,r){e.properties&&t&&r&&(e.properties[t]=r)}Object.defineProperty(o,"__esModule",{value:!0}),o.WayCollection=o.RefElements=o.LateBinder=o.strToFloat=o.ptInsidePolygon=o.ringDirection=o.isRing=o.coordsToKey=o.last=o.first=void 0,o.purgeProps=function(e,t){if(e){var r=Object.assign({},e);if(t)for(var s of t)delete r[s];return r}return{}},o.mergeProps=function(e,t){return e=e||{},t=t||{},Object.assign(e,t)},o.addPropToFeature=i,o.addPropToFeatures=function(e,t,r){for(var s of e)i(s,t,r)},o.addToMap=r,o.removeFromMap=n,o.getFirstFromMap=a;o.first=e=>e[0],o.last=e=>e[e.length-1];function r(e,t,r){var s=e[t];s?s.push(r):e[t]=[r]}function n(e,t,r){e=e[t];let s=-1;0<=(s=e?e.indexOf(r):s)&&e.splice(s,1)}function a(e,t){e=e[t];return e&&0<e.length?e[0]:null}o.coordsToKey=e=>e.join(",");o.isRing=e=>3<e.length&&(0,o.coordsToKey)((0,o.first)(e))===(0,o.coordsToKey)((0,o.last)(e)),o.ringDirection=(s,i,e)=>{i=i||0,e=e||1;var t=s.reduce((e,t,r)=>s[e][i||0]>t[i||0]?e:r,0),r=t<=0?s.length-2:t-1,o=t>=s.length-1?1:t+1,n=s[r][i],a=s[t][i],l=s[o][i],r=s[r][e],t=s[t][e];return(a-n)*(s[o][e]-r)-(l-n)*(t-r)<0?"clockwise":"counterclockwise"},o.ptInsidePolygon=(r,s,i,o)=>{i=i||0,o=o||1;let n=!1;for(let e=0,t=s.length-1;e<s.length;t=e++)(s[e][i]<=r[i]&&r[i]<s[t][i]||s[t][i]<=r[i]&&r[i]<s[e][i])&&r[o]<(s[t][o]-s[e][o])*(r[i]-s[e][i])/(s[t][i]-s[e][i])+s[e][o]&&(n=!n);return n};o.strToFloat=e=>e instanceof Array?e.map(o.strToFloat):parseFloat(e);o.LateBinder=class{constructor(e,t,r,s){this.container=e,this.valueFunc=t,this.ctx=r,this.args=s}bind(){var e=this.valueFunc.apply(this.ctx,this.args);if(this.container instanceof Array){var r=this.container.indexOf(this);0<=r&&(r=[r,1],e&&r.push(e),Array.prototype.splice.apply(this.container,r))}else if("object"==typeof this.container&&!Array.isArray(this.container)){let t=this.container;r=Object.keys(t).find(e=>t[e]===this);r&&(e?t[r]=e:delete t[r])}}};class s extends Map{constructor(){super(),this.binders=[]}add(e,t){this.set(e,t)}addBinder(e){this.binders.push(e)}bindAll(){this.binders.forEach(e=>e.bind())}}o.RefElements=s;class l extends Array{constructor(){super(),this.firstMap={},this.lastMap={}}addWay(e){e=e.toCoordsArray();0<e.length&&(this.push(e),r(this.firstMap,(0,o.coordsToKey)((0,o.first)(e)),e),r(this.lastMap,(0,o.coordsToKey)((0,o.last)(e)),e))}toStrings(){var e=[];let s=this.shift();for(;s;){n(this.firstMap,(0,o.coordsToKey)((0,o.first)(s)),s),n(this.lastMap,(0,o.coordsToKey)((0,o.last)(s)),s);let t=s,r;do{var i=(0,o.coordsToKey)((0,o.last)(t));let e=!1;(r=a(this.firstMap,i))||(r=a(this.lastMap,i),e=!0),r&&(this.splice(this.indexOf(r),1),n(this.firstMap,(0,o.coordsToKey)((0,o.first)(r)),r),n(this.lastMap,(0,o.coordsToKey)((0,o.last)(r)),r),e&&(r.length>t.length&&([t,r]=[r,t]),r.reverse()),t=t.concat(r.slice(1)))}while(r);e.push((0,o.strToFloat)(t)),s=this.shift()}return e}toRings(e){var t=this.toStrings(),r=[];let s=t.shift();for(;s;)(0,o.isRing)(s)&&((0,o.ringDirection)(s)!==e&&s.reverse(),r.push(s)),s=t.shift();return r}}o.WayCollection=l},{}],5:[function(e,t,r){function i(e){return null!==e.match(/^(.+?)\[(.+?)\]>$/g)}function o(e){var t=/^(.+?)\[(.+?)\]>$/g.exec(e);return t?{evt:t[1]+">",exp:t[2]}:{evt:e}}Object.defineProperty(r,"__esModule",{value:!0});class s{constructor(e){this.queryParent=!1,this.progressive=!1,this.parentMap=new WeakMap,e&&(this.queryParent=!!e.queryParent,this.progressive=e.progressive,this.queryParent)&&(this.parentMap=new WeakMap),this.evtListeners={}}parse(s,i,o){o=o?o+".":"";var n=/<([^ >\/]+)(.*?)>/gm,a=[];let l=n.exec(s);for(;l;){var d=l[1],h={$tag:d},f=o+d,u=l[2].trim();let e=!1;(u.endsWith("/")||d.startsWith("?")||d.startsWith("!"))&&(e=!0);var p,g=/([^ ]+?)="(.+?)"/g,c=/([^ ]+?)='(.+?)'/g;let t=g.exec(u),r=!1;for(;t;)r=!0,h[t[1]]=t[2],t=g.exec(u);if(!r)for(t=c.exec(u);t;)r=!0,h[t[1]]=t[2],t=c.exec(u);r||""===u||(h.text=u),this.progressive&&this.emit(`<${f}>`,h,i),e||((d=new RegExp(`([^]+?)</${d}>`,"g")).lastIndex=n.lastIndex,(p=d.exec(s))&&p[1]&&(n.lastIndex=d.lastIndex,0<(d=this.parse(p[1],h,f)).length?h.$innerNodes=d:h.$innerText=p[1])),this.queryParent&&i&&this.parentMap.set(h,i),this.progressive&&this.emit(`</${f}>`,h,i),a.push(h),l=n.exec(s)}return a}getParent(e){return this.queryParent?this.parentMap.get(e):null}addListener(e,t){var r,s;i(e)&&((r=o(e)).exp&&(t.condition=(s="return "+(s=r.exp).replace(/(\$.+?)(?=[=!.])/g,"node.$&")+";",new Function("node",s))),e=r.evt),this.$addListener(e,t)}removeListener(e,t){i(e)&&(e=o(e).evt),this.$removeListener(e,t)}on(e,t){this.addListener(e,t)}off(e,t){this.removeListener(e,t)}$addListener(e,t){var r=this.evtListeners[e];r?r.push(t):this.evtListeners[e]=[t]}$removeListener(e,t){e=this.evtListeners[e];let r=-1;0<=(r=e?e.indexOf(t):r)&&e.splice(r,1)}emit(e,...t){e=this.evtListeners[e];if(e)for(var r of e)(!r.condition||!0===r.condition.apply(null,t))&&r.apply(null,t)}}r.default=s},{}]},{},[1])(1)});