osm2geojson-lite 1.0.3 → 1.1.1
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 +13 -17
- package/dist/node/index.d.ts +16 -3
- package/dist/node/index.js +156 -159
- package/dist/node/late-binder.d.ts +8 -0
- package/dist/node/late-binder.js +24 -0
- package/dist/node/node.d.ts +14 -0
- package/dist/node/node.js +31 -0
- package/dist/node/osm-object.d.ts +25 -0
- package/dist/node/osm-object.js +38 -0
- package/dist/node/ref-elements.d.ts +9 -0
- package/dist/node/ref-elements.js +19 -0
- package/dist/node/relation.d.ts +20 -0
- package/dist/node/relation.js +205 -0
- package/dist/node/utils.d.ts +8 -46
- package/dist/node/utils.js +23 -148
- package/dist/node/way-collection.d.ts +14 -0
- package/dist/node/way-collection.js +108 -0
- package/dist/node/way.d.ts +21 -0
- package/dist/node/way.js +87 -0
- package/dist/node/xmlparser.d.ts +1 -1
- package/dist/node/xmlparser.js +3 -2
- package/dist/web/osm2geojson-lite.js +1 -1
- package/package.json +10 -5
- package/dist/node/osmobjs.d.ts +0 -73
- package/dist/node/osmobjs.js +0 -377
package/README.md
CHANGED
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
osm2geojson-lite
|
|
2
2
|
============
|
|
3
3
|
|
|
4
|
+
[](https://www.npmjs.com/package/osm2geojson-lite) [](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
|
-
|
|
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
|
|
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 `
|
|
51
|
-
- `
|
|
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
|
|
62
|
-
$
|
|
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`
|
|
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
|
-
|
|
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/dist/node/index.d.ts
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
|
-
import { FeatureCollection, GeometryObject } from 'geojson';
|
|
1
|
+
import type { FeatureCollection, GeometryObject } from 'geojson';
|
|
2
2
|
interface IOptions {
|
|
3
|
+
/**
|
|
4
|
+
* When it's set to `true`, the returned geojson will include all elements that meet the specified conditions in `FeatureCollection` format;
|
|
5
|
+
* otherwise, only the bare geometry of the first `relation` element will be returned.
|
|
6
|
+
* @default false
|
|
7
|
+
*/
|
|
3
8
|
completeFeature?: boolean;
|
|
4
|
-
|
|
9
|
+
/**
|
|
10
|
+
* When it's set to `true`, the returned geojson will include all elements with tags (i.e., tagged)
|
|
11
|
+
* until `suppressWay` changes its behavior a bit; otherwise only the unreferenced ones get returned.
|
|
12
|
+
* @default false
|
|
13
|
+
*/
|
|
5
14
|
renderTagged?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* When it's set to `true`, the returned `FeatureCollection` will exclude all referenced `way`s even though they are tagged;
|
|
17
|
+
* otherwise the features of those `way`s will be included in the resulted result as well.
|
|
18
|
+
* @default true
|
|
19
|
+
*/
|
|
6
20
|
excludeWay?: boolean;
|
|
7
|
-
suppressWay?: boolean;
|
|
8
21
|
}
|
|
9
22
|
declare function osm2geojson(osm: string | {
|
|
10
23
|
[k: string]: any;
|
package/dist/node/index.js
CHANGED
|
@@ -1,172 +1,168 @@
|
|
|
1
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
2
|
const utils_1 = require("./utils");
|
|
7
|
-
const xmlparser_1 =
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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);
|
|
3
|
+
const xmlparser_1 = require("./xmlparser");
|
|
4
|
+
const node_1 = require("./node");
|
|
5
|
+
const way_1 = require("./way");
|
|
6
|
+
const relation_1 = require("./relation");
|
|
7
|
+
const ref_elements_1 = require("./ref-elements");
|
|
8
|
+
function parseOptions(options) {
|
|
9
|
+
if (!options) {
|
|
10
|
+
return { completeFeature: false, renderTagged: false, excludeWay: true };
|
|
24
11
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return '
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
node.
|
|
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);
|
|
12
|
+
let excludeWay = options.excludeWay === undefined || options.excludeWay;
|
|
13
|
+
let completeFeature = options.completeFeature ? true : false;
|
|
14
|
+
let renderTagged = options.renderTagged ? true : false;
|
|
15
|
+
return { completeFeature, renderTagged, excludeWay };
|
|
16
|
+
}
|
|
17
|
+
function detectFormat(o) {
|
|
18
|
+
if (o.elements) {
|
|
19
|
+
return 'json';
|
|
20
|
+
}
|
|
21
|
+
if (o.indexOf('<osm') >= 0) {
|
|
22
|
+
return 'xml';
|
|
23
|
+
}
|
|
24
|
+
if (o.trim().startsWith('{')) {
|
|
25
|
+
return 'json-raw';
|
|
26
|
+
}
|
|
27
|
+
return 'invalid';
|
|
28
|
+
}
|
|
29
|
+
;
|
|
30
|
+
function analyzeFeaturesFromJson(osm, refElements) {
|
|
31
|
+
for (const elem of osm.elements) {
|
|
32
|
+
switch (elem.type) {
|
|
33
|
+
case 'node':
|
|
34
|
+
const node = new node_1.Node(elem.id, refElements);
|
|
35
|
+
if (elem.tags) {
|
|
36
|
+
node.addTags(elem.tags);
|
|
92
37
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
38
|
+
node.addProps((0, utils_1.purgeProps)(elem, ['id', 'type', 'tags', 'lat', 'lon']));
|
|
39
|
+
node.setLatLng(elem);
|
|
40
|
+
break;
|
|
41
|
+
case 'way':
|
|
42
|
+
const way = new way_1.Way(elem.id, refElements);
|
|
43
|
+
if (elem.tags) {
|
|
44
|
+
way.addTags(elem.tags);
|
|
100
45
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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);
|
|
46
|
+
way.addProps((0, utils_1.purgeProps)(elem, ['id', 'type', 'tags', 'nodes', 'geometry']));
|
|
47
|
+
if (elem.geometry) {
|
|
48
|
+
way.setLatLngArray(elem.geometry);
|
|
108
49
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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
|
-
}
|
|
50
|
+
else if (elem.nodes) {
|
|
51
|
+
for (const n of elem.nodes) {
|
|
52
|
+
way.addNodeRef(n);
|
|
119
53
|
}
|
|
120
|
-
|
|
121
|
-
|
|
54
|
+
}
|
|
55
|
+
break;
|
|
56
|
+
case 'relation':
|
|
57
|
+
const relation = new relation_1.Relation(elem.id, refElements);
|
|
58
|
+
if (elem.bounds) {
|
|
59
|
+
relation.setBounds([parseFloat(elem.bounds.minlon), parseFloat(elem.bounds.minlat), parseFloat(elem.bounds.maxlon), parseFloat(elem.bounds.maxlat)]);
|
|
60
|
+
}
|
|
61
|
+
if (elem.tags) {
|
|
62
|
+
relation.addTags(elem.tags);
|
|
63
|
+
}
|
|
64
|
+
relation.addProps((0, utils_1.purgeProps)(elem, ['id', 'type', 'tags', 'bounds', 'members']));
|
|
65
|
+
if (elem.members) {
|
|
66
|
+
for (const member of elem.members) {
|
|
67
|
+
relation.addMember(member);
|
|
122
68
|
}
|
|
123
69
|
}
|
|
70
|
+
default:
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function analyzeFeaturesFromXml(osm, refElements) {
|
|
76
|
+
const xmlParser = new xmlparser_1.XmlParser({ progressive: true });
|
|
77
|
+
xmlParser.on('</osm.node>', (node) => {
|
|
78
|
+
const nd = new node_1.Node(node.id, refElements);
|
|
79
|
+
for (const [k, v] of Object.entries(node)) {
|
|
80
|
+
if (!k.startsWith('$') && ['id', 'lon', 'lat'].indexOf(k) < 0) {
|
|
81
|
+
nd.addProp(k, v);
|
|
124
82
|
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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
|
-
}
|
|
83
|
+
}
|
|
84
|
+
nd.setLatLng(node);
|
|
85
|
+
if (node.$innerNodes) {
|
|
86
|
+
for (const ind of node.$innerNodes) {
|
|
87
|
+
if (ind.$tag === 'tag') {
|
|
88
|
+
nd.addTag(ind.k, ind.v);
|
|
140
89
|
}
|
|
141
90
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
xmlParser.on('</osm.way>', (node) => {
|
|
94
|
+
const way = new way_1.Way(node.id, refElements);
|
|
95
|
+
for (const [k, v] of Object.entries(node)) {
|
|
96
|
+
if (!k.startsWith('$') && ['id'].indexOf(k) < 0) {
|
|
97
|
+
way.addProp(k, v);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (node.$innerNodes) {
|
|
101
|
+
for (const ind of node.$innerNodes) {
|
|
102
|
+
if (ind.$tag === 'nd') {
|
|
103
|
+
if (ind.lon && ind.lat) {
|
|
104
|
+
way.addLatLng(ind);
|
|
148
105
|
}
|
|
149
106
|
else if (ind.ref) {
|
|
150
|
-
|
|
107
|
+
way.addNodeRef(ind.ref);
|
|
151
108
|
}
|
|
152
109
|
}
|
|
153
|
-
if (
|
|
154
|
-
|
|
110
|
+
else if (ind.$tag === 'tag') {
|
|
111
|
+
way.addTag(ind.k, ind.v);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
xmlParser.on('<osm.relation>', (node) => new relation_1.Relation(node.id, refElements));
|
|
117
|
+
xmlParser.on('</osm.relation.member>', (node, parent) => {
|
|
118
|
+
const relation = refElements.get(`relation/${parent === null || parent === void 0 ? void 0 : parent.id}`);
|
|
119
|
+
const member = {
|
|
120
|
+
type: node.type,
|
|
121
|
+
role: node.role ? node.role : '',
|
|
122
|
+
ref: node.ref,
|
|
123
|
+
};
|
|
124
|
+
if (node.lat && node.lon) {
|
|
125
|
+
member.lat = node.lat, member.lon = node.lon, member.tags = {};
|
|
126
|
+
for (const [k, v] of Object.entries(node)) {
|
|
127
|
+
if (!k.startsWith('$') && ['type', 'lat', 'lon'].indexOf(k) < 0) {
|
|
128
|
+
member[k] = v;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (node.$innerNodes) {
|
|
133
|
+
const geometry = [];
|
|
134
|
+
const nodes = [];
|
|
135
|
+
for (const ind of node.$innerNodes) {
|
|
136
|
+
if (ind.lat && ind.lon) {
|
|
137
|
+
geometry.push(ind);
|
|
155
138
|
}
|
|
156
|
-
else if (
|
|
157
|
-
|
|
139
|
+
else if (ind.ref) {
|
|
140
|
+
nodes.push(ind.ref);
|
|
158
141
|
}
|
|
159
142
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
143
|
+
if (geometry.length > 0) {
|
|
144
|
+
member.geometry = geometry;
|
|
145
|
+
}
|
|
146
|
+
else if (nodes.length > 0) {
|
|
147
|
+
member.nodes = nodes;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
relation.addMember(member);
|
|
151
|
+
});
|
|
152
|
+
xmlParser.on('</osm.relation.bounds>', (node, parent) => {
|
|
153
|
+
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)]);
|
|
154
|
+
});
|
|
155
|
+
xmlParser.on('</osm.relation.tag>', (node, parent) => {
|
|
156
|
+
refElements.get(`relation/${parent === null || parent === void 0 ? void 0 : parent.id}`).addTag(node.k, node.v);
|
|
157
|
+
});
|
|
158
|
+
xmlParser.parse(osm);
|
|
159
|
+
}
|
|
160
|
+
;
|
|
161
|
+
function osm2geojson(osm, opts) {
|
|
162
|
+
let { completeFeature, renderTagged, excludeWay } = parseOptions(opts);
|
|
163
|
+
let format = detectFormat(osm);
|
|
164
|
+
const refElements = new ref_elements_1.RefElements();
|
|
165
|
+
let featureArray = [];
|
|
170
166
|
if (format === 'json-raw') {
|
|
171
167
|
osm = JSON.parse(osm);
|
|
172
168
|
if (osm.elements) {
|
|
@@ -177,21 +173,22 @@ function osm2geojson(osm, opts) {
|
|
|
177
173
|
}
|
|
178
174
|
}
|
|
179
175
|
if (format === 'json') {
|
|
180
|
-
analyzeFeaturesFromJson(osm);
|
|
176
|
+
analyzeFeaturesFromJson(osm, refElements);
|
|
181
177
|
}
|
|
182
178
|
else if (format === 'xml') {
|
|
183
|
-
analyzeFeaturesFromXml(osm);
|
|
179
|
+
analyzeFeaturesFromXml(osm, refElements);
|
|
184
180
|
}
|
|
185
181
|
refElements.bindAll();
|
|
186
182
|
for (const v of refElements.values()) {
|
|
187
|
-
if (v.refCount
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
183
|
+
if (v.refCount > 0 && (!v.hasTag || !renderTagged || (v instanceof way_1.Way && excludeWay))) {
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
const features = v.toFeatureArray();
|
|
187
|
+
// return the first geometry of the first relation element
|
|
188
|
+
if (v instanceof relation_1.Relation && !completeFeature && features.length > 0) {
|
|
189
|
+
return features[0].geometry;
|
|
194
190
|
}
|
|
191
|
+
featureArray = featureArray.concat(features);
|
|
195
192
|
}
|
|
196
193
|
return { type: 'FeatureCollection', features: featureArray };
|
|
197
194
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LateBinder = void 0;
|
|
4
|
+
class LateBinder {
|
|
5
|
+
constructor(container, valueFunc, ctx, args) {
|
|
6
|
+
this.container = container;
|
|
7
|
+
this.valueFunc = valueFunc;
|
|
8
|
+
this.ctx = ctx;
|
|
9
|
+
this.args = args;
|
|
10
|
+
}
|
|
11
|
+
bind() {
|
|
12
|
+
const v = this.valueFunc.apply(this.ctx, this.args);
|
|
13
|
+
const idx = this.container.indexOf(this);
|
|
14
|
+
if (idx < 0) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const args = [idx, 1];
|
|
18
|
+
if (v) {
|
|
19
|
+
args.push(v);
|
|
20
|
+
}
|
|
21
|
+
Array.prototype.splice.apply(this.container, args);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.LateBinder = LateBinder;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { OsmObject } from "./osm-object";
|
|
2
|
+
import type { RefElements } from "./ref-elements";
|
|
3
|
+
import type { Feature } from "geojson";
|
|
4
|
+
export type LatLon = {
|
|
5
|
+
lat: string;
|
|
6
|
+
lon: string;
|
|
7
|
+
};
|
|
8
|
+
export declare class Node extends OsmObject {
|
|
9
|
+
private latLng;
|
|
10
|
+
constructor(id: string, refElems: RefElements);
|
|
11
|
+
setLatLng(latLng: LatLon): void;
|
|
12
|
+
toFeatureArray(): Array<Feature<any, any>>;
|
|
13
|
+
getLatLng(): LatLon | undefined;
|
|
14
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Node = void 0;
|
|
4
|
+
const osm_object_1 = require("./osm-object");
|
|
5
|
+
const utils_1 = require("./utils");
|
|
6
|
+
class Node extends osm_object_1.OsmObject {
|
|
7
|
+
constructor(id, refElems) {
|
|
8
|
+
super('node', id, refElems);
|
|
9
|
+
}
|
|
10
|
+
setLatLng(latLng) {
|
|
11
|
+
this.latLng = latLng;
|
|
12
|
+
}
|
|
13
|
+
toFeatureArray() {
|
|
14
|
+
if (this.latLng) {
|
|
15
|
+
return [{
|
|
16
|
+
type: 'Feature',
|
|
17
|
+
id: this.getCompositeId(),
|
|
18
|
+
properties: this.getProps(),
|
|
19
|
+
geometry: {
|
|
20
|
+
type: 'Point',
|
|
21
|
+
coordinates: (0, utils_1.strArrayToFloat)([this.latLng.lon, this.latLng.lat]),
|
|
22
|
+
},
|
|
23
|
+
}];
|
|
24
|
+
}
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
getLatLng() {
|
|
28
|
+
return this.latLng;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.Node = Node;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { RefElements } from './ref-elements';
|
|
2
|
+
import type { Feature } from 'geojson';
|
|
3
|
+
export declare abstract class OsmObject {
|
|
4
|
+
refCount: number;
|
|
5
|
+
hasTag: boolean;
|
|
6
|
+
protected refElems: RefElements;
|
|
7
|
+
private type;
|
|
8
|
+
private id;
|
|
9
|
+
private tags;
|
|
10
|
+
private props;
|
|
11
|
+
constructor(type: string, id: string, refElems: RefElements);
|
|
12
|
+
addTags(tags: {
|
|
13
|
+
[k: string]: string;
|
|
14
|
+
}): void;
|
|
15
|
+
addTag(k: string, v: string): void;
|
|
16
|
+
addProp(k: string, v: any): void;
|
|
17
|
+
addProps(props: {
|
|
18
|
+
[k: string]: string;
|
|
19
|
+
}): void;
|
|
20
|
+
getCompositeId(): string;
|
|
21
|
+
getProps(): {
|
|
22
|
+
[k: string]: string;
|
|
23
|
+
};
|
|
24
|
+
abstract toFeatureArray(): Array<Feature<any, any>>;
|
|
25
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OsmObject = void 0;
|
|
4
|
+
class OsmObject {
|
|
5
|
+
constructor(type, id, refElems) {
|
|
6
|
+
this.type = type;
|
|
7
|
+
this.id = id;
|
|
8
|
+
this.refElems = refElems;
|
|
9
|
+
this.tags = {};
|
|
10
|
+
this.props = { id: this.getCompositeId() };
|
|
11
|
+
this.refCount = 0;
|
|
12
|
+
this.hasTag = false;
|
|
13
|
+
if (refElems) {
|
|
14
|
+
refElems.add(this.getCompositeId(), this);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
addTags(tags) {
|
|
18
|
+
this.tags = Object.assign(this.tags, tags);
|
|
19
|
+
this.hasTag = true;
|
|
20
|
+
}
|
|
21
|
+
addTag(k, v) {
|
|
22
|
+
this.tags[k] = v;
|
|
23
|
+
this.hasTag = true;
|
|
24
|
+
}
|
|
25
|
+
addProp(k, v) {
|
|
26
|
+
this.props[k] = v;
|
|
27
|
+
}
|
|
28
|
+
addProps(props) {
|
|
29
|
+
this.props = Object.assign(this.props, props);
|
|
30
|
+
}
|
|
31
|
+
getCompositeId() {
|
|
32
|
+
return `${this.type}/${this.id}`;
|
|
33
|
+
}
|
|
34
|
+
getProps() {
|
|
35
|
+
return Object.assign(this.props, this.tags);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.OsmObject = OsmObject;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { LateBinder } from "./late-binder";
|
|
2
|
+
import type { OsmObject } from "./osm-object";
|
|
3
|
+
export declare class RefElements extends Map<string, OsmObject> {
|
|
4
|
+
private binders;
|
|
5
|
+
constructor();
|
|
6
|
+
add(k: string, v: OsmObject): void;
|
|
7
|
+
addBinder(binder: LateBinder<any>): void;
|
|
8
|
+
bindAll(): void;
|
|
9
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RefElements = void 0;
|
|
4
|
+
class RefElements extends Map {
|
|
5
|
+
constructor() {
|
|
6
|
+
super();
|
|
7
|
+
this.binders = [];
|
|
8
|
+
}
|
|
9
|
+
add(k, v) {
|
|
10
|
+
this.set(k, v);
|
|
11
|
+
}
|
|
12
|
+
addBinder(binder) {
|
|
13
|
+
this.binders.push(binder);
|
|
14
|
+
}
|
|
15
|
+
bindAll() {
|
|
16
|
+
this.binders.forEach((binder) => binder.bind());
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.RefElements = RefElements;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { OsmObject } from "./osm-object";
|
|
2
|
+
import { Way } from "./way";
|
|
3
|
+
import { LateBinder } from "./late-binder";
|
|
4
|
+
import type { RefElements } from "./ref-elements";
|
|
5
|
+
import type { Feature } from "geojson";
|
|
6
|
+
export declare class Relation extends OsmObject {
|
|
7
|
+
private relations;
|
|
8
|
+
private nodes;
|
|
9
|
+
private bounds;
|
|
10
|
+
ways: (LateBinder<Way> | Way)[];
|
|
11
|
+
roles: string[];
|
|
12
|
+
constructor(id: string, refElems: RefElements);
|
|
13
|
+
setBounds(bounds: any[]): void;
|
|
14
|
+
addMember(member: {
|
|
15
|
+
[k: string]: any;
|
|
16
|
+
}): void;
|
|
17
|
+
private constructStringGeometry;
|
|
18
|
+
private constructPolygonGeometry;
|
|
19
|
+
toFeatureArray(): Array<Feature<any, any>>;
|
|
20
|
+
}
|