osm2geojson-lite 0.8.13 → 0.9.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/Makefile +1 -1
- package/index.html +7 -3
- package/lib/index.d.ts +21 -0
- package/lib/index.js +51 -59
- package/lib/osmobjs.js +1 -1
- package/lib/xmlparser.js +1 -1
- package/osm2geojson-lite +10 -0
- package/package.json +12 -2
- package/ts/release/index.js +195 -0
- package/ts/release/osmobjs.js +348 -0
- package/ts/release/utils.js +213 -0
- package/ts/release/xmlparser.js +157 -0
- package/ts/src/index.d.ts +17 -0
- package/ts/src/index.ts +217 -169
- package/ts/src/osmobjs.ts +400 -365
- package/ts/src/typings.d.ts +1 -1
- package/ts/src/utils.ts +207 -170
- package/ts/src/xmlparser.ts +173 -132
- package/ts/tsconfig.json +4 -0
- package/ts/tslint.json +24 -0
- package/ts/types/imports.d.ts +1 -0
package/Makefile
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
osm2geojson-lite.js: lib/index.js package.json
|
|
2
|
-
browserify -s osm2geojson lib/index.js | uglifyjs -c -m -o dist/osm2geojson-lite.js
|
|
2
|
+
npx browserify -s osm2geojson lib/index.js | npx uglifyjs -c -m -o dist/osm2geojson-lite.js
|
package/index.html
CHANGED
|
@@ -75,7 +75,7 @@ this page is based on https://github.com/aaronlidman/osm-and-geojson (c)Aaron Li
|
|
|
75
75
|
#osmdata, #geojson {
|
|
76
76
|
width: 100%;
|
|
77
77
|
background: white;
|
|
78
|
-
border: 1px solid #
|
|
78
|
+
border: 1px solid #cccccc;
|
|
79
79
|
height: 320px;
|
|
80
80
|
overflow: auto;
|
|
81
81
|
margin-bottom: 20px;
|
|
@@ -115,6 +115,10 @@ this page is based on https://github.com/aaronlidman/osm-and-geojson (c)Aaron Li
|
|
|
115
115
|
outline: none;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
textarea:focus {
|
|
119
|
+
box-shadow: 0 0 2px 1px #0c74a97f;
|
|
120
|
+
}
|
|
121
|
+
|
|
118
122
|
#top {
|
|
119
123
|
font-size: 22px;
|
|
120
124
|
text-align: center;
|
|
@@ -219,11 +223,11 @@ this page is based on https://github.com/aaronlidman/osm-and-geojson (c)Aaron Li
|
|
|
219
223
|
<div id="example">
|
|
220
224
|
<div id="left">
|
|
221
225
|
<h3>OSM Data</h3>
|
|
222
|
-
<textarea id="osmdata" contenteditable="true"></textarea>
|
|
226
|
+
<textarea class="ta" id="osmdata" contenteditable="true"></textarea>
|
|
223
227
|
</div>
|
|
224
228
|
<div id="right">
|
|
225
229
|
<h3>GeoJSON</h3>
|
|
226
|
-
<textarea id="geojson" contenteditable="true"></textarea>
|
|
230
|
+
<textarea class="ta" id="geojson" contenteditable="true"></textarea>
|
|
227
231
|
</div>
|
|
228
232
|
<a class="button" href="" id="toGeo">Convert to GeoJSON →</a>
|
|
229
233
|
</div>
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {FeatureCollection, GeometryObject} from 'geojson';
|
|
2
|
+
|
|
3
|
+
export = osm2geojson;
|
|
4
|
+
export as namespace osm2geojson;
|
|
5
|
+
|
|
6
|
+
declare var osm2geojson: osm2geojson.Default;
|
|
7
|
+
|
|
8
|
+
declare namespace osm2geojson {
|
|
9
|
+
interface Options {
|
|
10
|
+
completeFeature?: boolean;
|
|
11
|
+
allFeatures?: boolean;
|
|
12
|
+
renderTagged?: boolean;
|
|
13
|
+
excludeWay?: boolean;
|
|
14
|
+
suppressWay?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface Default {
|
|
18
|
+
// tslint:disable-next-line:no-any
|
|
19
|
+
(osm: string | {[k: string]: any}, opts?: Options): FeatureCollection<GeometryObject>;
|
|
20
|
+
}
|
|
21
|
+
}
|
package/lib/index.js
CHANGED
|
@@ -50,8 +50,9 @@ module.exports = (osm, opts) => {
|
|
|
50
50
|
|
|
51
51
|
case 'relation':
|
|
52
52
|
let relation = new Relation(elem.id, refElements);
|
|
53
|
-
|
|
54
|
-
relation.setBounds([parseFloat(minlon), parseFloat(minlat), parseFloat(maxlon), parseFloat(maxlat)]);
|
|
53
|
+
if (elem.bounds) {
|
|
54
|
+
relation.setBounds([parseFloat(elem.bounds.minlon), parseFloat(elem.bounds.minlat), parseFloat(elem.bounds.maxlon), parseFloat(elem.bounds.maxlat)]);
|
|
55
|
+
}
|
|
55
56
|
if (elem.tags) relation.addTags(elem.tags);
|
|
56
57
|
relation.addProps(purgeProps(elem, ['id', 'type', 'tags', 'bounds', 'members']));
|
|
57
58
|
if (elem.members)
|
|
@@ -69,35 +70,31 @@ module.exports = (osm, opts) => {
|
|
|
69
70
|
const xmlParser = new XmlParser({progressive: true});
|
|
70
71
|
|
|
71
72
|
xmlParser.on('</osm.node>', node => {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
nd.addTag(ind.k, ind.v);
|
|
82
|
-
}
|
|
73
|
+
let nd = new Node(node.id, refElements);
|
|
74
|
+
for (let [k, v] of Object.entries(node))
|
|
75
|
+
if (!k.startsWith('$') && ['id', 'lon', 'lat'].indexOf(k) < 0)
|
|
76
|
+
nd.addProp(k, v);
|
|
77
|
+
nd.setLatLng(node);
|
|
78
|
+
if (node.$innerNodes)
|
|
79
|
+
for (let ind of node.$innerNodes)
|
|
80
|
+
if(ind.$tag === 'tag')
|
|
81
|
+
nd.addTag(ind.k, ind.v);
|
|
83
82
|
});
|
|
84
83
|
|
|
85
84
|
xmlParser.on('</osm.way>', node => {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (ind
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
way.addTag(ind.k, ind.v);
|
|
100
|
-
}
|
|
85
|
+
let way = new Way(node.id, refElements);
|
|
86
|
+
for (let [k, v] of Object.entries(node))
|
|
87
|
+
if (!k.startsWith('$') && ['id'].indexOf(k) < 0)
|
|
88
|
+
way.addProp(k, v);
|
|
89
|
+
if (node.$innerNodes) {
|
|
90
|
+
for (let ind of node.$innerNodes)
|
|
91
|
+
if (ind.$tag === 'nd') {
|
|
92
|
+
if (ind.lon && ind.lat)
|
|
93
|
+
way.addLatLng(ind);
|
|
94
|
+
else if (ind.ref)
|
|
95
|
+
way.addNodeRef(ind.ref);
|
|
96
|
+
} else if (ind.$tag === 'tag')
|
|
97
|
+
way.addTag(ind.k, ind.v);
|
|
101
98
|
}
|
|
102
99
|
});
|
|
103
100
|
|
|
@@ -106,42 +103,37 @@ module.exports = (osm, opts) => {
|
|
|
106
103
|
});
|
|
107
104
|
|
|
108
105
|
xmlParser.on('</osm.relation.member>', (node, parent) => {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
geometry.push(ind);
|
|
130
|
-
else
|
|
131
|
-
nodes.push(ind.ref);
|
|
132
|
-
}
|
|
133
|
-
if (geometry.length > 0)
|
|
134
|
-
member.geometry = geometry;
|
|
135
|
-
else if (nodes.length > 0)
|
|
136
|
-
member.nodes = nodes;
|
|
106
|
+
let relation = refElements.get(`relation/${parent.id}`);
|
|
107
|
+
let member = {
|
|
108
|
+
type: node.type,
|
|
109
|
+
role: node.role? node.role : '',
|
|
110
|
+
ref: node.ref
|
|
111
|
+
};
|
|
112
|
+
if (node.lat && node.lon) {
|
|
113
|
+
member.lat = node.lat, member.lon = node.lon, member.tags = {};
|
|
114
|
+
for (let [k, v] of Object.entries(node))
|
|
115
|
+
if (!k.startsWith('$') && ['type', 'lat', 'lon'].indexOf(k) < 0)
|
|
116
|
+
member[k] = v;
|
|
117
|
+
}
|
|
118
|
+
if (node.$innerNodes) {
|
|
119
|
+
let geometry = [];
|
|
120
|
+
let nodes = [];
|
|
121
|
+
for (let ind of node.$innerNodes) {
|
|
122
|
+
if (ind.lat && ind.lon)
|
|
123
|
+
geometry.push(ind);
|
|
124
|
+
else
|
|
125
|
+
nodes.push(ind.ref);
|
|
137
126
|
}
|
|
138
|
-
|
|
127
|
+
if (geometry.length > 0)
|
|
128
|
+
member.geometry = geometry;
|
|
129
|
+
else if (nodes.length > 0)
|
|
130
|
+
member.nodes = nodes;
|
|
139
131
|
}
|
|
132
|
+
relation.addMember(member);
|
|
140
133
|
});
|
|
141
134
|
|
|
142
135
|
xmlParser.on('</osm.relation.bounds>', (node, parent) => {
|
|
143
|
-
|
|
144
|
-
refElements.get(`relation/${parent.id}`).setBounds([parseFloat(minlon), parseFloat(minlat), parseFloat(maxlon), parseFloat(maxlat)]);
|
|
136
|
+
refElements.get(`relation/${parent.id}`).setBounds([parseFloat(node.minlon), parseFloat(node.minlat), parseFloat(node.maxlon), parseFloat(node.maxlat)]);
|
|
145
137
|
});
|
|
146
138
|
|
|
147
139
|
xmlParser.on('</osm.relation.tag>', (node, parent) => {
|
package/lib/osmobjs.js
CHANGED
package/lib/xmlparser.js
CHANGED
|
@@ -27,7 +27,7 @@ module.exports = (() => {
|
|
|
27
27
|
this.evtListeners = {};
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
parse(xml, parent
|
|
30
|
+
parse(xml, parent, dir) {
|
|
31
31
|
dir = dir? dir + '.' : '';
|
|
32
32
|
let nodeRegEx = /<([^ >\/]+)(.*?)>/mg, nodeMatch = null, nodes = [];
|
|
33
33
|
while (nodeMatch = nodeRegEx.exec(xml)) {
|
package/osm2geojson-lite
ADDED
package/package.json
CHANGED
|
@@ -19,6 +19,9 @@
|
|
|
19
19
|
"/"
|
|
20
20
|
],
|
|
21
21
|
"author": "tibetty",
|
|
22
|
+
"bin": {
|
|
23
|
+
"osm2geojson-lite": "osm2geojson-lite"
|
|
24
|
+
},
|
|
22
25
|
"bugs": {
|
|
23
26
|
"url": "https://github.com/tibetty/osm2geojson-lite/issues"
|
|
24
27
|
},
|
|
@@ -52,10 +55,17 @@
|
|
|
52
55
|
"scripts": {
|
|
53
56
|
"test": "npm run --prefix test test"
|
|
54
57
|
},
|
|
55
|
-
"
|
|
58
|
+
"optionalDependencies": {
|
|
59
|
+
"@types/geojson": "^1.0.6"
|
|
60
|
+
},
|
|
61
|
+
"types": "lib/index.d.ts",
|
|
62
|
+
"version": "0.9.0",
|
|
56
63
|
"directories": {
|
|
57
64
|
"lib": "lib",
|
|
58
65
|
"test": "test"
|
|
59
66
|
},
|
|
60
|
-
"devDependencies": {
|
|
67
|
+
"devDependencies": {
|
|
68
|
+
"browserify": "^17.0.0",
|
|
69
|
+
"uglify-js": "^3.14.5"
|
|
70
|
+
}
|
|
61
71
|
}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const osmobjs_1 = require("./osmobjs");
|
|
4
|
+
const utils_1 = require("./utils");
|
|
5
|
+
const xmlparser_1 = require("./xmlparser");
|
|
6
|
+
exports.default = (osm, opts) => {
|
|
7
|
+
let completeFeature = false;
|
|
8
|
+
let renderTagged = false;
|
|
9
|
+
let excludeWay = true;
|
|
10
|
+
const parseOpts = (os) => {
|
|
11
|
+
if (os) {
|
|
12
|
+
completeFeature = os.completeFeature || os.allFeatures ? true : false;
|
|
13
|
+
renderTagged = os.renderTagged ? true : false;
|
|
14
|
+
const wayOpt = os.suppressWay || os.excludeWay;
|
|
15
|
+
if (wayOpt !== undefined && !wayOpt) {
|
|
16
|
+
excludeWay = false;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
if (opts) {
|
|
21
|
+
parseOpts(opts);
|
|
22
|
+
}
|
|
23
|
+
const detectFormat = (o) => {
|
|
24
|
+
if (o.elements) {
|
|
25
|
+
return 'json';
|
|
26
|
+
}
|
|
27
|
+
if (o.indexOf('<osm') >= 0) {
|
|
28
|
+
return 'xml';
|
|
29
|
+
}
|
|
30
|
+
if (o.trim().startsWith('{')) {
|
|
31
|
+
return 'json-raw';
|
|
32
|
+
}
|
|
33
|
+
return 'invalid';
|
|
34
|
+
};
|
|
35
|
+
let format = detectFormat(osm);
|
|
36
|
+
const refElements = new utils_1.RefElements();
|
|
37
|
+
let featureArray = [];
|
|
38
|
+
const analyzeFeaturesFromJson = (o) => {
|
|
39
|
+
for (const elem of osm.elements) {
|
|
40
|
+
switch (elem.type) {
|
|
41
|
+
case 'node':
|
|
42
|
+
const node = new osmobjs_1.Node(elem.id, refElements);
|
|
43
|
+
if (elem.tags) {
|
|
44
|
+
node.addTags(elem.tags);
|
|
45
|
+
}
|
|
46
|
+
node.addProps(utils_1.purgeProps(elem, ['id', 'type', 'tags', 'lat', 'lon']));
|
|
47
|
+
node.setLatLng(elem);
|
|
48
|
+
break;
|
|
49
|
+
case 'way':
|
|
50
|
+
const way = new osmobjs_1.Way(elem.id, refElements);
|
|
51
|
+
if (elem.tags) {
|
|
52
|
+
way.addTags(elem.tags);
|
|
53
|
+
}
|
|
54
|
+
way.addProps(utils_1.purgeProps(elem, ['id', 'type', 'tags', 'nodes', 'geometry']));
|
|
55
|
+
if (elem.nodes) {
|
|
56
|
+
for (const n of elem.nodes) {
|
|
57
|
+
way.addNodeRef(n);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else if (elem.geometry) {
|
|
61
|
+
way.setLatLngArray(elem.geometry);
|
|
62
|
+
}
|
|
63
|
+
break;
|
|
64
|
+
case 'relation':
|
|
65
|
+
const relation = new osmobjs_1.Relation(elem.id, refElements);
|
|
66
|
+
if (elem.bounds) {
|
|
67
|
+
relation.setBounds([parseFloat(elem.bounds.minlon), parseFloat(elem.bounds.minlat), parseFloat(elem.bounds.maxlon), parseFloat(elem.bounds.maxlat)]);
|
|
68
|
+
}
|
|
69
|
+
if (elem.tags) {
|
|
70
|
+
relation.addTags(elem.tags);
|
|
71
|
+
}
|
|
72
|
+
relation.addProps(utils_1.purgeProps(elem, ['id', 'type', 'tags', 'bounds', 'members']));
|
|
73
|
+
if (elem.members) {
|
|
74
|
+
for (const member of elem.members) {
|
|
75
|
+
relation.addMember(member);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
default:
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
const analyzeFeaturesFromXml = (o) => {
|
|
84
|
+
const xmlParser = new xmlparser_1.default({ progressive: true });
|
|
85
|
+
xmlParser.on('</osm.node>', (node) => {
|
|
86
|
+
const nd = new osmobjs_1.Node(node.id, refElements);
|
|
87
|
+
for (const [k, v] of Object.entries(node)) {
|
|
88
|
+
if (!k.startsWith('$') && ['id', 'lon', 'lat'].indexOf(k) < 0) {
|
|
89
|
+
nd.addProp(k, v);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
nd.setLatLng(node);
|
|
93
|
+
if (node.$innerNodes) {
|
|
94
|
+
for (const ind of node.$innerNodes) {
|
|
95
|
+
if (ind.$tag === 'tag') {
|
|
96
|
+
nd.addTag(ind.k, ind.v);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
xmlParser.on('</osm.way>', (node) => {
|
|
102
|
+
const way = new osmobjs_1.Way(node.id, refElements);
|
|
103
|
+
for (const [k, v] of Object.entries(node)) {
|
|
104
|
+
if (!k.startsWith('$') && ['id'].indexOf(k) < 0) {
|
|
105
|
+
way.addProp(k, v);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (node.$innerNodes) {
|
|
109
|
+
for (const ind of node.$innerNodes) {
|
|
110
|
+
if (ind.$tag === 'nd') {
|
|
111
|
+
if (ind.lon && ind.lat) {
|
|
112
|
+
way.addLatLng(ind);
|
|
113
|
+
}
|
|
114
|
+
else if (ind.ref) {
|
|
115
|
+
way.addNodeRef(ind.ref);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else if (ind.$tag === 'tag') {
|
|
119
|
+
way.addTag(ind.k, ind.v);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
xmlParser.on('<osm.relation>', (node) => new osmobjs_1.Relation(node.id, refElements));
|
|
125
|
+
xmlParser.on('</osm.relation.member>', (node, parent) => {
|
|
126
|
+
const relation = refElements.get(`relation/${parent.id}`);
|
|
127
|
+
const member = {
|
|
128
|
+
type: node.type,
|
|
129
|
+
role: node.role ? node.role : '',
|
|
130
|
+
ref: node.ref,
|
|
131
|
+
};
|
|
132
|
+
if (node.lat && node.lon) {
|
|
133
|
+
member.lat = node.lat, member.lon = node.lon, member.tags = {};
|
|
134
|
+
for (const [k, v] of Object.entries(node)) {
|
|
135
|
+
if (!k.startsWith('$') && ['type', 'lat', 'lon'].indexOf(k) < 0) {
|
|
136
|
+
member[k] = v;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (node.$innerNodes) {
|
|
141
|
+
const geometry = [];
|
|
142
|
+
const nodes = [];
|
|
143
|
+
for (const ind of node.$innerNodes) {
|
|
144
|
+
if (ind.lat && ind.lon) {
|
|
145
|
+
geometry.push(ind);
|
|
146
|
+
}
|
|
147
|
+
else if (ind.ref) {
|
|
148
|
+
nodes.push(ind.ref);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (geometry.length > 0) {
|
|
152
|
+
member.geometry = geometry;
|
|
153
|
+
}
|
|
154
|
+
else if (nodes.length > 0) {
|
|
155
|
+
member.nodes = nodes;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
relation.addMember(member);
|
|
159
|
+
});
|
|
160
|
+
xmlParser.on('</osm.relation.bounds>', (node, parent) => {
|
|
161
|
+
refElements.get(`relation/${parent.id}`).setBounds([parseFloat(node.minlon), parseFloat(node.minlat), parseFloat(node.maxlon), parseFloat(node.maxlat)]);
|
|
162
|
+
});
|
|
163
|
+
xmlParser.on('</osm.relation.tag>', (node, parent) => {
|
|
164
|
+
refElements.get(`relation/${parent.id}`).addTag(node.k, node.v);
|
|
165
|
+
});
|
|
166
|
+
xmlParser.parse(o);
|
|
167
|
+
};
|
|
168
|
+
if (format === 'json-raw') {
|
|
169
|
+
osm = JSON.parse(osm);
|
|
170
|
+
if (osm.elements) {
|
|
171
|
+
format = 'json';
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
format = 'invalid';
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (format === 'json') {
|
|
178
|
+
analyzeFeaturesFromJson(osm);
|
|
179
|
+
}
|
|
180
|
+
else if (format === 'xml') {
|
|
181
|
+
analyzeFeaturesFromXml(osm);
|
|
182
|
+
}
|
|
183
|
+
refElements.bindAll();
|
|
184
|
+
for (const v of refElements.values()) {
|
|
185
|
+
if (v.refCount <= 0 || (v.hasTag && renderTagged && !(v instanceof osmobjs_1.Way && excludeWay))) {
|
|
186
|
+
const features = v.toFeatureArray();
|
|
187
|
+
// return the first geometry of the first relation element
|
|
188
|
+
if (v instanceof osmobjs_1.Relation && !completeFeature && features.length > 0) {
|
|
189
|
+
return features[0].geometry;
|
|
190
|
+
}
|
|
191
|
+
featureArray = featureArray.concat(features);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return { type: 'FeatureCollection', features: featureArray };
|
|
195
|
+
};
|