osm2geojson-lite 0.9.1 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/osmobjs.js CHANGED
@@ -1,390 +1,391 @@
1
1
  module.exports = (() => {
2
- 'use strict';
3
-
4
- const {first, last, coordsToKey,
5
- addToMap, removeFromMap, getFirstFromMap,
6
- isRing, ringDirection, ptInsidePolygon, strToFloat,
7
- LateBinder, WayCollection} = require('./utils.js'),
8
- polygonTags = require('./polytags.json');
9
-
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
-
24
- addTags(tags) {
25
- this.tags = Object.assign(this.tags, tags);
26
- this.hasTag = tags? true : false;
27
- }
28
-
29
- addTag(k, v) {
30
- this.tags[k] = v;
31
- this.hasTag = k? true : false;
32
- }
33
-
34
- addProp(k, v) {
35
- this.props[k] = v;
36
- }
37
-
38
- addProps(props) {
39
- this.props = Object.assign(this.props, props);
40
- }
41
-
42
- getCompositeId() {
43
- return `${this.type}/${this.id}`;
44
- }
45
-
46
- getProps() {
47
- return Object.assign(this.props, this.tags);
48
- }
49
-
50
- toFeatureArray() {
51
- return [];
52
- }
53
- }
54
-
55
- class Node extends OsmObject {
56
- constructor(id, refElems) {
57
- super('node', id, refElems);
58
- this.latLng = null;
59
- }
60
-
61
- setLatLng(latLng) {
62
- this.latLng = latLng;
63
- }
64
-
65
- toFeatureArray() {
66
- if (this.latLng) {
67
- return [{
68
- type: 'Feature',
69
- id: this.getCompositeId(),
70
- properties: this.getProps(),
71
- geometry: {
72
- type: 'Point',
73
- coordinates: strToFloat([this.latLng.lon, this.latLng.lat])
74
- }
75
- }];
76
- }
77
-
78
- return [];
79
- }
80
-
81
- getLatLng() {
82
- return this.latLng;
83
- }
84
- }
85
-
86
- class Way extends OsmObject {
87
- constructor(id, refElems) {
88
- super('way', id, refElems);
89
- this.latLngArray = [];
90
- this.isPolygon = false;
91
- }
92
-
93
- addLatLng(latLng) {
94
- this.latLngArray.push(latLng);
95
- }
96
-
97
- setLatLngArray(latLngArray) {
98
- this.latLngArray = latLngArray;
99
- }
100
-
101
- addNodeRef(ref) {
102
- let binder = new LateBinder(this.latLngArray, function(id) {
103
- let node = this.refElems.get(`node/${id}`);
104
- if (node) {
105
- node.refCount++;
106
- return node.getLatLng();
107
- }
108
- }, this, [ref]);
109
-
110
- this.latLngArray.push(binder);
111
- this.refElems.addBinder(binder);
112
- }
113
-
114
- analyzeTag(k, v) {
115
- let o = polygonTags[k];
116
- if (o) {
117
- this.isPolygon = true;
118
- if (o.whitelist) {
119
- this.isPolygon = o.whitelist.indexOf(v) >= 0? true : false;
120
- } else if(o.blacklist) {
121
- this.isPolygon = o.blacklist.indexOf(v) >= 0? false : true;
122
- }
123
- }
124
- }
125
-
126
- addTags(tags) {
127
- super.addTags(tags);
128
- for (let [k, v] of Object.entries(tags)) {
129
- this.analyzeTag(k, v);
130
- }
131
- }
132
-
133
- addTag(k, v) {
134
- super.addTag(k, v);
135
- this.analyzeTag(k, v);
136
- }
137
-
138
- toCoordsArray() {
139
- return this.latLngArray.map(latLng => [latLng.lon, latLng.lat]);
140
- }
141
-
142
- toFeatureArray() {
143
- let coordsArray = this.toCoordsArray();
144
- if (coordsArray.length > 1) {
145
- coordsArray = strToFloat(coordsArray);
146
- let feature = {
147
- type: 'Feature',
148
- id: this.getCompositeId(),
149
- properties: this.getProps(),
150
- geometry: {
151
- type: 'LineString',
152
- coordinates: coordsArray
153
- }
154
- };
155
-
156
- if (this.isPolygon && isRing(coordsArray)) {
157
- if (ringDirection(coordsArray) !== 'counterclockwise') {
158
- coordsArray.reverse();
159
- }
160
-
161
- feature.geometry = {
162
- type: 'Polygon',
163
- coordinates: [coordsArray]
164
- };
165
-
166
- return [feature];
167
- }
168
-
169
- return [feature];
170
- }
171
-
172
- return [];
173
- }
174
- }
175
-
176
- class Relation extends OsmObject {
177
- constructor(id, refElems) {
178
- super('relation', id, refElems);
179
- this.relations = [];
180
- this.nodes = [];
181
- this.bounds = null;
182
- }
183
-
184
- setBounds(bounds) {
185
- this.bounds = bounds;
186
- }
187
-
188
- addMember(member) {
189
- switch (member.type) {
190
- // super relation, need to do combination
191
- case 'relation':
192
- let binder = new LateBinder(this.relations, function(id) {
193
- let relation = this.refElems.get(`relation/${id}`);
194
- if (relation) {
195
- relation.refCount++;
196
- return relation;
197
- }
198
- }, this, [member.ref]);
199
- this.relations.push(binder);
200
- this.refElems.addBinder(binder);
201
- break;
202
-
203
- case 'way':
204
- if (!member.role) {
205
- member.role = '';
206
- }
207
- let ways = this[member.role];
208
- if (!ways) {
209
- ways = this[member.role] = [];
210
- }
211
- if (member.geometry) {
212
- let way = new Way(member.ref, this.refElems);
213
- way.setLatLngArray(member.geometry);
214
- way.refCount++;
215
- ways.push(way);
216
- } else if (member.nodes) {
217
- let way = new Way(member.ref, this.refElems);
218
- for (let nid of member.nodes) {
219
- way.addNodeRef(nid);
220
- }
221
- way.refCount++;
222
- ways.push(way);
223
- } else {
224
- let binder = new LateBinder(ways, function(id) {
225
- let way = this.refElems.get(`way/${id}`);
226
- if (way) {
227
- way.refCount++;
228
- return way;
229
- }
230
- }, this, [member.ref]);
231
- ways.push(binder);
232
- this.refElems.addBinder(binder);
233
- }
234
- break;
235
-
236
- case 'node':
237
- let node = null;
238
- if (member.lat && member.lon) {
239
- node = new Node(member.ref, this.refElems);
240
- node.setLatLng({lon: member.lon, lat: member.lat});
241
- if (member.tags) {
242
- node.addTags(member.tags);
243
- }
244
- for (let [k, v] of Object.entries(member)) {
245
- if (['id', 'type', 'lat', 'lon'].indexOf(k) < 0) {
246
- node.addProp(k, v);
247
- }
248
- }
249
-
250
- node.refCount++;
251
- this.nodes.push(node);
252
- } else {
253
- let binder = new LateBinder(this.nodes, function(id) {
254
- let node = this.refElems.get(`node/${id}`);
255
- if (node) {
256
- node.refCount++;
257
- return node;
258
- }
259
- }, this, [member.ref]);
260
- this.nodes.push(binder);
261
- this.refElems.addBinder(binder);
262
- }
263
- break;
264
-
265
- default:
266
- break;
267
- }
268
- }
269
-
270
- toFeatureArray() {
271
- const constructStringGeometry = (ws) => {
272
- let strings = ws? ws.toStrings() : [];
273
- if (strings.length > 0) {
274
- if (strings.length === 1) return {
275
- type: 'LineString',
276
- coordinates: strings[0]
277
- }
278
-
279
- return {
280
- type: 'MultiLineString',
281
- coordinates: strings
282
- }
283
- }
284
- return null; }
285
-
286
- const constructPolygonGeometry = (ows, iws) => {
287
- let outerRings = ows? ows.toRings('counterclockwise') : [],
288
- innerRings = iws? iws.toRings('clockwise') : [];
289
-
290
- if (outerRings.length > 0) {
291
- let compositPolyons = [];
292
-
293
- let ring = null;
294
- for (ring of outerRings)
295
- compositPolyons.push([ring]);
296
-
297
- // link inner polygons to outer containers
298
- while (ring = innerRings.shift()) {
299
- for (let idx in outerRings) {
300
- if (ptInsidePolygon(first(ring), outerRings[idx])) {
301
- compositPolyons[idx].push(ring);
302
- break;
303
- }
304
- }
305
- }
306
-
307
- // construct the Polygon/MultiPolygon geometry
308
- if (compositPolyons.length === 1) {
309
- return {
310
- type: 'Polygon',
311
- coordinates: compositPolyons[0]
312
- };
313
- }
314
-
315
- return {
316
- type: 'MultiPolygon',
317
- coordinates: compositPolyons
318
- }
319
- }
320
-
321
- return null;
322
- }
323
-
324
- let polygonFeatures = [], stringFeatures = [], pointFeatures = [];
325
- const waysFieldNames = ['outer', 'inner', ''];
326
- // need to do combination when there're nested relations
327
- for (let relation of this.relations) {
328
- if (relation) {
329
- for (let fieldName of waysFieldNames) {
330
- let ways = relation[fieldName];
331
- if (ways) {
332
- let thisWays = this[fieldName];
333
- if (thisWays) {
334
- [].splice.apply(thisWays, [thisWays.length, 0].concat(ways));
335
- } else {
336
- this[fieldName] = ways;
337
- }
338
- }
339
- }
340
- }
341
- }
342
-
343
- for (let fieldName of waysFieldNames) {
344
- let ways = this[fieldName];
345
- if (ways) {
346
- this[fieldName] = new WayCollection();
347
- for (let way of ways) {
348
- this[fieldName].addWay(way);
349
- }
350
- }
351
- }
352
-
353
- let geometry = null;
354
-
355
- let feature = {
356
- type: 'Feature',
357
- id: this.getCompositeId(),
358
- bbox: this.bounds,
359
- properties: this.getProps()
360
- };
361
-
362
- if (!this.bounds) {
363
- delete feature.bbox;
364
- }
365
-
366
- if (this.outer) {
367
- geometry = constructPolygonGeometry(this.outer, this.inner);
368
- if (geometry) {
369
- feature.geometry = geometry;
370
- polygonFeatures.push(feature);
371
- }
372
- }
373
- else if (this['']) {
374
- geometry = constructStringGeometry(this['']);
375
- if (geometry) {
376
- feature.geometry = geometry;
377
- stringFeatures.push(feature);
378
- }
379
- }
380
-
381
- for (let node of this.nodes) {
382
- pointFeatures = pointFeatures.concat(node.toFeatureArray());
383
- }
384
-
385
- return polygonFeatures.concat(stringFeatures).concat(pointFeatures);
386
- }
387
- }
388
-
389
- return {Node, Way, Relation};
390
- })();
2
+ 'use strict';
3
+
4
+ const {first, last, coordsToKey,
5
+ addToMap, removeFromMap, getFirstFromMap,
6
+ isRing, ringDirection, ptInsidePolygon, strToFloat,
7
+ LateBinder, WayCollection} = require('./utils.js'),
8
+ polygonTags = require('./polytags.json');
9
+
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
+
24
+ addTags(tags) {
25
+ this.tags = Object.assign(this.tags, tags);
26
+ this.hasTag = tags? true : false;
27
+ }
28
+
29
+ addTag(k, v) {
30
+ this.tags[k] = v;
31
+ this.hasTag = k? true : false;
32
+ }
33
+
34
+ addProp(k, v) {
35
+ this.props[k] = v;
36
+ }
37
+
38
+ addProps(props) {
39
+ this.props = Object.assign(this.props, props);
40
+ }
41
+
42
+ getCompositeId() {
43
+ return `${this.type}/${this.id}`;
44
+ }
45
+
46
+ getProps() {
47
+ return Object.assign(this.props, this.tags);
48
+ }
49
+
50
+ toFeatureArray() {
51
+ return [];
52
+ }
53
+ }
54
+
55
+ class Node extends OsmObject {
56
+ constructor(id, refElems) {
57
+ super('node', id, refElems);
58
+ this.latLng = null;
59
+ }
60
+
61
+ setLatLng(latLng) {
62
+ this.latLng = latLng;
63
+ }
64
+
65
+ toFeatureArray() {
66
+ if (this.latLng) {
67
+ return [{
68
+ type: 'Feature',
69
+ id: this.getCompositeId(),
70
+ properties: this.getProps(),
71
+ geometry: {
72
+ type: 'Point',
73
+ coordinates: strToFloat([this.latLng.lon, this.latLng.lat])
74
+ }
75
+ }];
76
+ }
77
+
78
+ return [];
79
+ }
80
+
81
+ getLatLng() {
82
+ return this.latLng;
83
+ }
84
+ }
85
+
86
+ class Way extends OsmObject {
87
+ constructor(id, refElems) {
88
+ super('way', id, refElems);
89
+ this.latLngArray = [];
90
+ this.isPolygon = false;
91
+ }
92
+
93
+ addLatLng(latLng) {
94
+ this.latLngArray.push(latLng);
95
+ }
96
+
97
+ setLatLngArray(latLngArray) {
98
+ this.latLngArray = latLngArray;
99
+ }
100
+
101
+ addNodeRef(ref) {
102
+ let binder = new LateBinder(this.latLngArray, function(id) {
103
+ let node = this.refElems.get(`node/${id}`);
104
+ if (node) {
105
+ node.refCount++;
106
+ return node.getLatLng();
107
+ }
108
+ }, this, [ref]);
109
+
110
+ this.latLngArray.push(binder);
111
+ this.refElems.addBinder(binder);
112
+ }
113
+
114
+ analyzeTag(k, v) {
115
+ let o = polygonTags[k];
116
+ if (o) {
117
+ this.isPolygon = true;
118
+ if (o.whitelist) {
119
+ this.isPolygon = o.whitelist.indexOf(v) >= 0? true : false;
120
+ } else if(o.blacklist) {
121
+ this.isPolygon = o.blacklist.indexOf(v) >= 0? false : true;
122
+ }
123
+ }
124
+ }
125
+
126
+ addTags(tags) {
127
+ super.addTags(tags);
128
+ for (let [k, v] of Object.entries(tags)) {
129
+ this.analyzeTag(k, v);
130
+ }
131
+ }
132
+
133
+ addTag(k, v) {
134
+ super.addTag(k, v);
135
+ this.analyzeTag(k, v);
136
+ }
137
+
138
+ toCoordsArray() {
139
+ return this.latLngArray.map(latLng => [latLng.lon, latLng.lat]);
140
+ }
141
+
142
+ toFeatureArray() {
143
+ let coordsArray = this.toCoordsArray();
144
+ if (coordsArray.length > 1) {
145
+ coordsArray = strToFloat(coordsArray);
146
+ let feature = {
147
+ type: 'Feature',
148
+ id: this.getCompositeId(),
149
+ properties: this.getProps(),
150
+ geometry: {
151
+ type: 'LineString',
152
+ coordinates: coordsArray
153
+ }
154
+ };
155
+
156
+ if (this.isPolygon && isRing(coordsArray)) {
157
+ if (ringDirection(coordsArray) !== 'counterclockwise') {
158
+ coordsArray.reverse();
159
+ }
160
+
161
+ feature.geometry = {
162
+ type: 'Polygon',
163
+ coordinates: [coordsArray]
164
+ };
165
+
166
+ return [feature];
167
+ }
168
+
169
+ return [feature];
170
+ }
171
+
172
+ return [];
173
+ }
174
+ }
175
+
176
+ class Relation extends OsmObject {
177
+ constructor(id, refElems) {
178
+ super('relation', id, refElems);
179
+ this.relations = [];
180
+ this.nodes = [];
181
+ this.bounds = null;
182
+ }
183
+
184
+ setBounds(bounds) {
185
+ this.bounds = bounds;
186
+ }
187
+
188
+ addMember(member) {
189
+ switch (member.type) {
190
+ // super relation, need to do combination
191
+ case 'relation':
192
+ let binder = new LateBinder(this.relations, function(id) {
193
+ let relation = this.refElems.get(`relation/${id}`);
194
+ if (relation) {
195
+ relation.refCount++;
196
+ return relation;
197
+ }
198
+ }, this, [member.ref]);
199
+ this.relations.push(binder);
200
+ this.refElems.addBinder(binder);
201
+ break;
202
+
203
+ case 'way':
204
+ if (!member.role) {
205
+ member.role = '';
206
+ }
207
+ let ways = this[member.role];
208
+ if (!ways) {
209
+ ways = this[member.role] = [];
210
+ }
211
+ if (member.geometry) {
212
+ let way = new Way(member.ref, this.refElems);
213
+ way.setLatLngArray(member.geometry);
214
+ way.refCount++;
215
+ ways.push(way);
216
+ } else if (member.nodes) {
217
+ let way = new Way(member.ref, this.refElems);
218
+ for (let nid of member.nodes) {
219
+ way.addNodeRef(nid);
220
+ }
221
+ way.refCount++;
222
+ ways.push(way);
223
+ } else {
224
+ let binder = new LateBinder(ways, function(id) {
225
+ let way = this.refElems.get(`way/${id}`);
226
+ if (way) {
227
+ way.refCount++;
228
+ return way;
229
+ }
230
+ }, this, [member.ref]);
231
+ ways.push(binder);
232
+ this.refElems.addBinder(binder);
233
+ }
234
+ break;
235
+
236
+ case 'node':
237
+ let node = null;
238
+ if (member.lat && member.lon) {
239
+ node = new Node(member.ref, this.refElems);
240
+ node.setLatLng({lon: member.lon, lat: member.lat});
241
+ if (member.tags) {
242
+ node.addTags(member.tags);
243
+ }
244
+ for (let [k, v] of Object.entries(member)) {
245
+ if (['id', 'type', 'lat', 'lon'].indexOf(k) < 0) {
246
+ node.addProp(k, v);
247
+ }
248
+ }
249
+
250
+ node.refCount++;
251
+ this.nodes.push(node);
252
+ } else {
253
+ let binder = new LateBinder(this.nodes, function(id) {
254
+ let node = this.refElems.get(`node/${id}`);
255
+ if (node) {
256
+ node.refCount++;
257
+ return node;
258
+ }
259
+ }, this, [member.ref]);
260
+ this.nodes.push(binder);
261
+ this.refElems.addBinder(binder);
262
+ }
263
+ break;
264
+
265
+ default:
266
+ break;
267
+ }
268
+ }
269
+
270
+ toFeatureArray() {
271
+ const constructStringGeometry = (ws) => {
272
+ let strings = ws? ws.toStrings() : [];
273
+ if (strings.length > 0) {
274
+ if (strings.length === 1) return {
275
+ type: 'LineString',
276
+ coordinates: strings[0]
277
+ }
278
+
279
+ return {
280
+ type: 'MultiLineString',
281
+ coordinates: strings
282
+ }
283
+ }
284
+ return null;
285
+ }
286
+
287
+ const constructPolygonGeometry = (ows, iws) => {
288
+ let outerRings = ows? ows.toRings('counterclockwise') : [],
289
+ innerRings = iws? iws.toRings('clockwise') : [];
290
+
291
+ if (outerRings.length > 0) {
292
+ let compositPolyons = [];
293
+
294
+ let ring = null;
295
+ for (ring of outerRings)
296
+ compositPolyons.push([ring]);
297
+
298
+ // link inner polygons to outer containers
299
+ while (ring = innerRings.shift()) {
300
+ for (let idx in outerRings) {
301
+ if (ptInsidePolygon(first(ring), outerRings[idx])) {
302
+ compositPolyons[idx].push(ring);
303
+ break;
304
+ }
305
+ }
306
+ }
307
+
308
+ // construct the Polygon/MultiPolygon geometry
309
+ if (compositPolyons.length === 1) {
310
+ return {
311
+ type: 'Polygon',
312
+ coordinates: compositPolyons[0]
313
+ };
314
+ }
315
+
316
+ return {
317
+ type: 'MultiPolygon',
318
+ coordinates: compositPolyons
319
+ }
320
+ }
321
+
322
+ return null;
323
+ }
324
+
325
+ let polygonFeatures = [], stringFeatures = [], pointFeatures = [];
326
+ const waysFieldNames = ['outer', 'inner', ''];
327
+ // need to do combination when there're nested relations
328
+ for (let relation of this.relations) {
329
+ if (relation) {
330
+ for (let fieldName of waysFieldNames) {
331
+ let ways = relation[fieldName];
332
+ if (ways) {
333
+ let thisWays = this[fieldName];
334
+ if (thisWays) {
335
+ [].splice.apply(thisWays, [thisWays.length, 0].concat(ways));
336
+ } else {
337
+ this[fieldName] = ways;
338
+ }
339
+ }
340
+ }
341
+ }
342
+ }
343
+
344
+ for (let fieldName of waysFieldNames) {
345
+ let ways = this[fieldName];
346
+ if (ways) {
347
+ this[fieldName] = new WayCollection();
348
+ for (let way of ways) {
349
+ this[fieldName].addWay(way);
350
+ }
351
+ }
352
+ }
353
+
354
+ let geometry = null;
355
+
356
+ let feature = {
357
+ type: 'Feature',
358
+ id: this.getCompositeId(),
359
+ bbox: this.bounds,
360
+ properties: this.getProps()
361
+ };
362
+
363
+ if (!this.bounds) {
364
+ delete feature.bbox;
365
+ }
366
+
367
+ if (this.outer) {
368
+ geometry = constructPolygonGeometry(this.outer, this.inner);
369
+ if (geometry) {
370
+ feature.geometry = geometry;
371
+ polygonFeatures.push(feature);
372
+ }
373
+ }
374
+ else if (this['']) {
375
+ geometry = constructStringGeometry(this['']);
376
+ if (geometry) {
377
+ feature.geometry = geometry;
378
+ stringFeatures.push(feature);
379
+ }
380
+ }
381
+
382
+ for (let node of this.nodes) {
383
+ pointFeatures = pointFeatures.concat(node.toFeatureArray());
384
+ }
385
+
386
+ return polygonFeatures.concat(stringFeatures).concat(pointFeatures);
387
+ }
388
+ }
389
+
390
+ return {Node, Way, Relation};
391
+ })();