umap-project 3.0.4__py3-none-any.whl → 3.0.6__py3-none-any.whl
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.
Potentially problematic release.
This version of umap-project might be problematic. Click here for more details.
- umap/__init__.py +1 -1
- umap/locale/el/LC_MESSAGES/django.mo +0 -0
- umap/locale/el/LC_MESSAGES/django.po +136 -56
- umap/locale/en/LC_MESSAGES/django.mo +0 -0
- umap/locale/en/LC_MESSAGES/django.po +18 -18
- umap/locale/es/LC_MESSAGES/django.mo +0 -0
- umap/locale/es/LC_MESSAGES/django.po +136 -56
- umap/locale/it/LC_MESSAGES/django.mo +0 -0
- umap/locale/it/LC_MESSAGES/django.po +143 -63
- umap/locale/nl/LC_MESSAGES/django.mo +0 -0
- umap/locale/nl/LC_MESSAGES/django.po +1 -1
- umap/models.py +1 -0
- umap/settings/base.py +1 -0
- umap/static/umap/css/bar.css +1 -1
- umap/static/umap/css/tooltip.css +13 -0
- umap/static/umap/js/modules/autocomplete.js +7 -8
- umap/static/umap/js/modules/browser.js +89 -94
- umap/static/umap/js/modules/caption.js +6 -4
- umap/static/umap/js/modules/data/features.js +1 -19
- umap/static/umap/js/modules/data/layer.js +100 -61
- umap/static/umap/js/modules/facets.js +1 -1
- umap/static/umap/js/modules/form/fields.js +1 -1
- umap/static/umap/js/modules/help.js +4 -0
- umap/static/umap/js/modules/importer.js +1 -1
- umap/static/umap/js/modules/managers.js +46 -0
- umap/static/umap/js/modules/permissions.js +1 -1
- umap/static/umap/js/modules/rendering/controls.js +251 -0
- umap/static/umap/js/modules/rendering/layers/heat.js +5 -0
- umap/static/umap/js/modules/rendering/map.js +21 -10
- umap/static/umap/js/modules/rendering/ui.js +0 -1
- umap/static/umap/js/modules/rules.js +56 -46
- umap/static/umap/js/modules/schema.js +5 -1
- umap/static/umap/js/modules/share.js +2 -2
- umap/static/umap/js/modules/slideshow.js +1 -1
- umap/static/umap/js/modules/sync/engine.js +23 -9
- umap/static/umap/js/modules/ui/bar.js +2 -2
- umap/static/umap/js/modules/ui/base.js +13 -0
- umap/static/umap/js/modules/umap.js +69 -111
- umap/static/umap/js/umap.controls.js +0 -310
- umap/static/umap/js/umap.core.js +0 -40
- umap/static/umap/locale/am_ET.js +8 -3
- umap/static/umap/locale/am_ET.json +8 -3
- umap/static/umap/locale/ar.js +8 -3
- umap/static/umap/locale/ar.json +8 -3
- umap/static/umap/locale/ast.js +8 -3
- umap/static/umap/locale/ast.json +8 -3
- umap/static/umap/locale/bg.js +8 -3
- umap/static/umap/locale/bg.json +8 -3
- umap/static/umap/locale/br.js +8 -3
- umap/static/umap/locale/br.json +8 -3
- umap/static/umap/locale/ca.js +20 -17
- umap/static/umap/locale/ca.json +20 -17
- umap/static/umap/locale/cs_CZ.js +5 -2
- umap/static/umap/locale/cs_CZ.json +5 -2
- umap/static/umap/locale/da.js +8 -3
- umap/static/umap/locale/da.json +8 -3
- umap/static/umap/locale/de.js +5 -2
- umap/static/umap/locale/de.json +5 -2
- umap/static/umap/locale/el.js +92 -87
- umap/static/umap/locale/el.json +92 -87
- umap/static/umap/locale/en.js +6 -2
- umap/static/umap/locale/en.json +6 -2
- umap/static/umap/locale/en_US.json +8 -3
- umap/static/umap/locale/es.js +18 -15
- umap/static/umap/locale/es.json +18 -15
- umap/static/umap/locale/et.js +8 -3
- umap/static/umap/locale/et.json +8 -3
- umap/static/umap/locale/eu.js +5 -2
- umap/static/umap/locale/eu.json +5 -2
- umap/static/umap/locale/fa_IR.js +5 -2
- umap/static/umap/locale/fa_IR.json +5 -2
- umap/static/umap/locale/fi.js +8 -3
- umap/static/umap/locale/fi.json +8 -3
- umap/static/umap/locale/fr.js +5 -2
- umap/static/umap/locale/fr.json +5 -2
- umap/static/umap/locale/gl.js +5 -2
- umap/static/umap/locale/gl.json +5 -2
- umap/static/umap/locale/he.js +8 -3
- umap/static/umap/locale/he.json +8 -3
- umap/static/umap/locale/hr.js +8 -3
- umap/static/umap/locale/hr.json +8 -3
- umap/static/umap/locale/hu.js +5 -2
- umap/static/umap/locale/hu.json +5 -2
- umap/static/umap/locale/id.js +8 -3
- umap/static/umap/locale/id.json +8 -3
- umap/static/umap/locale/is.js +8 -3
- umap/static/umap/locale/is.json +8 -3
- umap/static/umap/locale/it.js +5 -2
- umap/static/umap/locale/it.json +5 -2
- umap/static/umap/locale/ja.js +8 -3
- umap/static/umap/locale/ja.json +8 -3
- umap/static/umap/locale/ko.js +8 -3
- umap/static/umap/locale/ko.json +8 -3
- umap/static/umap/locale/lt.js +8 -3
- umap/static/umap/locale/lt.json +8 -3
- umap/static/umap/locale/ms.js +8 -3
- umap/static/umap/locale/ms.json +8 -3
- umap/static/umap/locale/nl.js +7 -4
- umap/static/umap/locale/nl.json +7 -4
- umap/static/umap/locale/no.js +8 -3
- umap/static/umap/locale/no.json +8 -3
- umap/static/umap/locale/pl.js +8 -3
- umap/static/umap/locale/pl.json +8 -3
- umap/static/umap/locale/pl_PL.json +8 -3
- umap/static/umap/locale/pt.js +5 -2
- umap/static/umap/locale/pt.json +5 -2
- umap/static/umap/locale/pt_BR.js +8 -3
- umap/static/umap/locale/pt_BR.json +8 -3
- umap/static/umap/locale/pt_PT.js +5 -2
- umap/static/umap/locale/pt_PT.json +5 -2
- umap/static/umap/locale/ro.js +8 -3
- umap/static/umap/locale/ro.json +8 -3
- umap/static/umap/locale/ru.js +8 -3
- umap/static/umap/locale/ru.json +8 -3
- umap/static/umap/locale/sk_SK.js +8 -3
- umap/static/umap/locale/sk_SK.json +8 -3
- umap/static/umap/locale/sl.js +8 -3
- umap/static/umap/locale/sl.json +8 -3
- umap/static/umap/locale/sr.js +8 -3
- umap/static/umap/locale/sr.json +8 -3
- umap/static/umap/locale/sv.js +8 -3
- umap/static/umap/locale/sv.json +8 -3
- umap/static/umap/locale/th_TH.js +8 -3
- umap/static/umap/locale/th_TH.json +8 -3
- umap/static/umap/locale/tr.js +8 -3
- umap/static/umap/locale/tr.json +8 -3
- umap/static/umap/locale/uk_UA.js +8 -3
- umap/static/umap/locale/uk_UA.json +8 -3
- umap/static/umap/locale/vi.js +8 -3
- umap/static/umap/locale/vi.json +8 -3
- umap/static/umap/locale/vi_VN.json +8 -3
- umap/static/umap/locale/zh.js +8 -3
- umap/static/umap/locale/zh.json +8 -3
- umap/static/umap/locale/zh_CN.json +8 -3
- umap/static/umap/locale/zh_TW.Big5.json +8 -3
- umap/static/umap/locale/zh_TW.js +5 -2
- umap/static/umap/locale/zh_TW.json +5 -2
- umap/static/umap/map.css +9 -31
- umap/static/umap/vendors/togeojson/togeojson.es.js +350 -177
- umap/static/umap/vendors/togeojson/togeojson.es.mjs.map +1 -1
- umap/templates/umap/design_system.html +355 -0
- umap/templates/umap/map_init.html +3 -1
- umap/tests/base.py +2 -2
- umap/tests/fixtures/heatmap_data.json +1044 -0
- umap/tests/integration/test_basics.py +9 -1
- umap/tests/integration/test_browser.py +3 -3
- umap/tests/integration/test_conditional_rules.py +2 -2
- umap/tests/integration/test_datalayer.py +0 -1
- umap/tests/integration/test_edit_map.py +7 -7
- umap/tests/integration/test_facets_browser.py +2 -2
- umap/tests/integration/test_heatmap.py +41 -0
- umap/tests/integration/test_import.py +58 -1
- umap/tests/integration/test_map.py +7 -8
- umap/tests/integration/test_optimistic_merge.py +12 -4
- umap/tests/integration/test_querystring.py +1 -1
- umap/tests/integration/test_remote_data.py +79 -0
- umap/tests/integration/test_websocket_sync.py +2 -2
- umap/urls.py +1 -0
- umap/views.py +8 -1
- {umap_project-3.0.4.dist-info → umap_project-3.0.6.dist-info}/METADATA +11 -11
- {umap_project-3.0.4.dist-info → umap_project-3.0.6.dist-info}/RECORD +164 -158
- {umap_project-3.0.4.dist-info → umap_project-3.0.6.dist-info}/WHEEL +0 -0
- {umap_project-3.0.4.dist-info → umap_project-3.0.6.dist-info}/entry_points.txt +0 -0
- {umap_project-3.0.4.dist-info → umap_project-3.0.6.dist-info}/licenses/LICENSE +0 -0
|
@@ -12,7 +12,7 @@ function $ns(element, tagName, ns) {
|
|
|
12
12
|
*/
|
|
13
13
|
function nodeVal(node) {
|
|
14
14
|
node?.normalize();
|
|
15
|
-
return
|
|
15
|
+
return node?.textContent || "";
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
18
|
* Get one Y child of X, if any, otherwise null
|
|
@@ -42,16 +42,16 @@ function val1(node, tagName, callback) {
|
|
|
42
42
|
return {};
|
|
43
43
|
}
|
|
44
44
|
function $num(node, tagName, callback) {
|
|
45
|
-
const val = parseFloat(nodeVal(get1(node, tagName)));
|
|
46
|
-
if (isNaN(val))
|
|
45
|
+
const val = Number.parseFloat(nodeVal(get1(node, tagName)));
|
|
46
|
+
if (Number.isNaN(val))
|
|
47
47
|
return undefined;
|
|
48
48
|
if (val && callback)
|
|
49
49
|
return callback(val) || {};
|
|
50
50
|
return {};
|
|
51
51
|
}
|
|
52
52
|
function num1(node, tagName, callback) {
|
|
53
|
-
const val = parseFloat(nodeVal(get1(node, tagName)));
|
|
54
|
-
if (isNaN(val))
|
|
53
|
+
const val = Number.parseFloat(nodeVal(get1(node, tagName)));
|
|
54
|
+
if (Number.isNaN(val))
|
|
55
55
|
return undefined;
|
|
56
56
|
if (callback)
|
|
57
57
|
callback(val);
|
|
@@ -70,20 +70,6 @@ function isElement(node) {
|
|
|
70
70
|
return node?.nodeType === 1;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
function getLineStyle(node) {
|
|
74
|
-
return get(node, "line", (lineStyle) => {
|
|
75
|
-
const val = Object.assign({}, val1(lineStyle, "color", (color) => {
|
|
76
|
-
return { stroke: `#${color}` };
|
|
77
|
-
}), $num(lineStyle, "opacity", (opacity) => {
|
|
78
|
-
return { "stroke-opacity": opacity };
|
|
79
|
-
}), $num(lineStyle, "width", (width) => {
|
|
80
|
-
// GPX width is in mm, convert to px with 96 px per inch
|
|
81
|
-
return { "stroke-width": (width * 96) / 25.4 };
|
|
82
|
-
}));
|
|
83
|
-
return val;
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
|
|
87
73
|
function getExtensions(node) {
|
|
88
74
|
let values = [];
|
|
89
75
|
if (node === null)
|
|
@@ -108,16 +94,16 @@ function abbreviateName(name) {
|
|
|
108
94
|
return ["heart", "gpxtpx:hr", "hr"].includes(name) ? "heart" : name;
|
|
109
95
|
}
|
|
110
96
|
function parseNumeric(val) {
|
|
111
|
-
const num = parseFloat(val);
|
|
112
|
-
return isNaN(num) ? val : num;
|
|
97
|
+
const num = Number.parseFloat(val);
|
|
98
|
+
return Number.isNaN(num) ? val : num;
|
|
113
99
|
}
|
|
114
100
|
|
|
115
101
|
function coordPair$1(node) {
|
|
116
102
|
const ll = [
|
|
117
|
-
parseFloat(node.getAttribute("lon") || ""),
|
|
118
|
-
parseFloat(node.getAttribute("lat") || ""),
|
|
103
|
+
Number.parseFloat(node.getAttribute("lon") || ""),
|
|
104
|
+
Number.parseFloat(node.getAttribute("lat") || ""),
|
|
119
105
|
];
|
|
120
|
-
if (isNaN(ll[0]) || isNaN(ll[1])) {
|
|
106
|
+
if (Number.isNaN(ll[0]) || Number.isNaN(ll[1])) {
|
|
121
107
|
return null;
|
|
122
108
|
}
|
|
123
109
|
num1(node, "ele", (val) => {
|
|
@@ -131,7 +117,21 @@ function coordPair$1(node) {
|
|
|
131
117
|
};
|
|
132
118
|
}
|
|
133
119
|
|
|
134
|
-
function
|
|
120
|
+
function getLineStyle(node) {
|
|
121
|
+
return get(node, "line", (lineStyle) => {
|
|
122
|
+
const val = Object.assign({}, val1(lineStyle, "color", (color) => {
|
|
123
|
+
return { stroke: `#${color}` };
|
|
124
|
+
}), $num(lineStyle, "opacity", (opacity) => {
|
|
125
|
+
return { "stroke-opacity": opacity };
|
|
126
|
+
}), $num(lineStyle, "width", (width) => {
|
|
127
|
+
// GPX width is in mm, convert to px with 96 px per inch
|
|
128
|
+
return { "stroke-width": (width * 96) / 25.4 };
|
|
129
|
+
}));
|
|
130
|
+
return val;
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function extractProperties(ns, node) {
|
|
135
135
|
const properties = getMulti(node, [
|
|
136
136
|
"name",
|
|
137
137
|
"cmt",
|
|
@@ -140,10 +140,9 @@ function extractProperties(node) {
|
|
|
140
140
|
"time",
|
|
141
141
|
"keywords",
|
|
142
142
|
]);
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
properties[child.tagName.replace(":", "_")] = nodeVal(child);
|
|
143
|
+
for (const [n, url] of ns) {
|
|
144
|
+
for (const child of Array.from(node.getElementsByTagNameNS(url, "*"))) {
|
|
145
|
+
properties[child.tagName.replace(":", "_")] = nodeVal(child)?.trim();
|
|
147
146
|
}
|
|
148
147
|
}
|
|
149
148
|
const links = $(node, "link");
|
|
@@ -170,7 +169,7 @@ function getPoints$1(node, pointname) {
|
|
|
170
169
|
if (c.time)
|
|
171
170
|
times.push(c.time);
|
|
172
171
|
for (const [name, val] of c.extendedValues) {
|
|
173
|
-
const plural = name === "heart" ? name : name.replace("gpxtpx:", "")
|
|
172
|
+
const plural = name === "heart" ? name : `${name.replace("gpxtpx:", "")}s`;
|
|
174
173
|
if (!extendedValues[plural]) {
|
|
175
174
|
extendedValues[plural] = Array(pts.length).fill(null);
|
|
176
175
|
}
|
|
@@ -189,20 +188,20 @@ function getPoints$1(node, pointname) {
|
|
|
189
188
|
* Extract a LineString geometry from a rte
|
|
190
189
|
* element.
|
|
191
190
|
*/
|
|
192
|
-
function getRoute(node) {
|
|
191
|
+
function getRoute(ns, node) {
|
|
193
192
|
const line = getPoints$1(node, "rtept");
|
|
194
193
|
if (!line)
|
|
195
194
|
return;
|
|
196
195
|
return {
|
|
197
196
|
type: "Feature",
|
|
198
|
-
properties: Object.assign({ _gpxType: "rte" }, extractProperties(node), getLineStyle(get1(node, "extensions"))),
|
|
197
|
+
properties: Object.assign({ _gpxType: "rte" }, extractProperties(ns, node), getLineStyle(get1(node, "extensions"))),
|
|
199
198
|
geometry: {
|
|
200
199
|
type: "LineString",
|
|
201
200
|
coordinates: line.line,
|
|
202
201
|
},
|
|
203
202
|
};
|
|
204
203
|
}
|
|
205
|
-
function getTrack(node) {
|
|
204
|
+
function getTrack(ns, node) {
|
|
206
205
|
const segments = $(node, "trkseg");
|
|
207
206
|
const track = [];
|
|
208
207
|
const times = [];
|
|
@@ -211,14 +210,14 @@ function getTrack(node) {
|
|
|
211
210
|
const line = getPoints$1(segment, "trkpt");
|
|
212
211
|
if (line) {
|
|
213
212
|
extractedLines.push(line);
|
|
214
|
-
if (line.times
|
|
213
|
+
if (line.times?.length)
|
|
215
214
|
times.push(line.times);
|
|
216
215
|
}
|
|
217
216
|
}
|
|
218
217
|
if (extractedLines.length === 0)
|
|
219
218
|
return null;
|
|
220
219
|
const multi = extractedLines.length > 1;
|
|
221
|
-
const properties = Object.assign({ _gpxType: "trk" }, extractProperties(node), getLineStyle(get1(node, "extensions")), times.length
|
|
220
|
+
const properties = Object.assign({ _gpxType: "trk" }, extractProperties(ns, node), getLineStyle(get1(node, "extensions")), times.length
|
|
222
221
|
? {
|
|
223
222
|
coordinateProperties: {
|
|
224
223
|
times: multi ? times : times[0],
|
|
@@ -263,8 +262,8 @@ function getTrack(node) {
|
|
|
263
262
|
* Extract a point, if possible, from a given node,
|
|
264
263
|
* which is usually a wpt or trkpt
|
|
265
264
|
*/
|
|
266
|
-
function getPoint(node) {
|
|
267
|
-
const properties = Object.assign(extractProperties(node), getMulti(node, ["sym"]));
|
|
265
|
+
function getPoint(ns, node) {
|
|
266
|
+
const properties = Object.assign(extractProperties(ns, node), getMulti(node, ["sym"]));
|
|
268
267
|
const pair = coordPair$1(node);
|
|
269
268
|
if (!pair)
|
|
270
269
|
return null;
|
|
@@ -283,18 +282,31 @@ function getPoint(node) {
|
|
|
283
282
|
* that yields output feature by feature.
|
|
284
283
|
*/
|
|
285
284
|
function* gpxGen(node) {
|
|
286
|
-
|
|
287
|
-
|
|
285
|
+
const n = node;
|
|
286
|
+
const GPXX = "gpxx";
|
|
287
|
+
const GPXX_URI = "http://www.garmin.com/xmlschemas/GpxExtensions/v3";
|
|
288
|
+
// Namespaces
|
|
289
|
+
const ns = [[GPXX, GPXX_URI]];
|
|
290
|
+
const attrs = n.getElementsByTagName("gpx")[0]?.attributes;
|
|
291
|
+
if (attrs) {
|
|
292
|
+
for (const attr of Array.from(attrs)) {
|
|
293
|
+
if (attr.name?.startsWith("xmlns:") && attr.value !== GPXX_URI) {
|
|
294
|
+
ns.push([attr.name, attr.value]);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
for (const track of $(n, "trk")) {
|
|
299
|
+
const feature = getTrack(ns, track);
|
|
288
300
|
if (feature)
|
|
289
301
|
yield feature;
|
|
290
302
|
}
|
|
291
|
-
for (const route of $(
|
|
292
|
-
const feature = getRoute(route);
|
|
303
|
+
for (const route of $(n, "rte")) {
|
|
304
|
+
const feature = getRoute(ns, route);
|
|
293
305
|
if (feature)
|
|
294
306
|
yield feature;
|
|
295
307
|
}
|
|
296
|
-
for (const waypoint of $(
|
|
297
|
-
const point = getPoint(waypoint);
|
|
308
|
+
for (const waypoint of $(n, "wpt")) {
|
|
309
|
+
const point = getPoint(ns, waypoint);
|
|
298
310
|
if (point)
|
|
299
311
|
yield point;
|
|
300
312
|
}
|
|
@@ -346,8 +358,8 @@ function getProperties(node, attributeNames) {
|
|
|
346
358
|
elem = elements[0];
|
|
347
359
|
}
|
|
348
360
|
}
|
|
349
|
-
const val = parseFloat(nodeVal(elem));
|
|
350
|
-
if (!isNaN(val)) {
|
|
361
|
+
const val = Number.parseFloat(nodeVal(elem));
|
|
362
|
+
if (!Number.isNaN(val)) {
|
|
351
363
|
properties.push([alias, val]);
|
|
352
364
|
}
|
|
353
365
|
}
|
|
@@ -356,23 +368,23 @@ function getProperties(node, attributeNames) {
|
|
|
356
368
|
function coordPair(node) {
|
|
357
369
|
const ll = [num1(node, "LongitudeDegrees"), num1(node, "LatitudeDegrees")];
|
|
358
370
|
if (ll[0] === undefined ||
|
|
359
|
-
isNaN(ll[0]) ||
|
|
371
|
+
Number.isNaN(ll[0]) ||
|
|
360
372
|
ll[1] === undefined ||
|
|
361
|
-
isNaN(ll[1])) {
|
|
373
|
+
Number.isNaN(ll[1])) {
|
|
362
374
|
return null;
|
|
363
375
|
}
|
|
364
376
|
const heartRate = get1(node, "HeartRateBpm");
|
|
365
377
|
const time = nodeVal(get1(node, "Time"));
|
|
366
378
|
get1(node, "AltitudeMeters", (alt) => {
|
|
367
|
-
const a = parseFloat(nodeVal(alt));
|
|
368
|
-
if (!isNaN(a)) {
|
|
379
|
+
const a = Number.parseFloat(nodeVal(alt));
|
|
380
|
+
if (!Number.isNaN(a)) {
|
|
369
381
|
ll.push(a);
|
|
370
382
|
}
|
|
371
383
|
});
|
|
372
384
|
return {
|
|
373
385
|
coordinates: ll,
|
|
374
386
|
time: time || null,
|
|
375
|
-
heartRate: heartRate ? parseFloat(nodeVal(heartRate)) : null,
|
|
387
|
+
heartRate: heartRate ? Number.parseFloat(nodeVal(heartRate)) : null,
|
|
376
388
|
extensions: getProperties(node, TRACKPOINT_ATTRIBUTES),
|
|
377
389
|
};
|
|
378
390
|
}
|
|
@@ -504,17 +516,18 @@ function tcx(node) {
|
|
|
504
516
|
|
|
505
517
|
function fixColor(v, prefix) {
|
|
506
518
|
const properties = {};
|
|
507
|
-
const colorProp = prefix
|
|
519
|
+
const colorProp = prefix === "stroke" || prefix === "fill" ? prefix : `${prefix}-color`;
|
|
508
520
|
if (v[0] === "#") {
|
|
509
521
|
v = v.substring(1);
|
|
510
522
|
}
|
|
511
523
|
if (v.length === 6 || v.length === 3) {
|
|
512
|
-
properties[colorProp] =
|
|
524
|
+
properties[colorProp] = `#${v}`;
|
|
513
525
|
}
|
|
514
526
|
else if (v.length === 8) {
|
|
515
|
-
properties[prefix
|
|
527
|
+
properties[`${prefix}-opacity`] =
|
|
528
|
+
Number.parseInt(v.substring(0, 2), 16) / 255;
|
|
516
529
|
properties[colorProp] =
|
|
517
|
-
|
|
530
|
+
`#${v.substring(6, 8)}${v.substring(4, 6)}${v.substring(2, 4)}`;
|
|
518
531
|
}
|
|
519
532
|
return properties;
|
|
520
533
|
}
|
|
@@ -540,11 +553,11 @@ function extractIconHref(node) {
|
|
|
540
553
|
function extractIcon(node) {
|
|
541
554
|
return get(node, "IconStyle", (iconStyle) => {
|
|
542
555
|
return Object.assign(getColor(iconStyle, "icon"), numericProperty(iconStyle, "scale", "icon-scale"), numericProperty(iconStyle, "heading", "icon-heading"), get(iconStyle, "hotSpot", (hotspot) => {
|
|
543
|
-
const left = parseFloat(hotspot.getAttribute("x") || "");
|
|
544
|
-
const top = parseFloat(hotspot.getAttribute("y") || "");
|
|
556
|
+
const left = Number.parseFloat(hotspot.getAttribute("x") || "");
|
|
557
|
+
const top = Number.parseFloat(hotspot.getAttribute("y") || "");
|
|
545
558
|
const xunits = hotspot.getAttribute("xunits") || "";
|
|
546
559
|
const yunits = hotspot.getAttribute("yunits") || "";
|
|
547
|
-
if (!isNaN(left) && !isNaN(top))
|
|
560
|
+
if (!Number.isNaN(left) && !Number.isNaN(top))
|
|
548
561
|
return {
|
|
549
562
|
"icon-offset": [left, top],
|
|
550
563
|
"icon-offset-units": [xunits, yunits],
|
|
@@ -578,71 +591,6 @@ function extractStyle(node) {
|
|
|
578
591
|
return Object.assign({}, extractPoly(node), extractLine(node), extractLabel(node), extractIcon(node));
|
|
579
592
|
}
|
|
580
593
|
|
|
581
|
-
const toNumber = (x) => Number(x);
|
|
582
|
-
const typeConverters = {
|
|
583
|
-
string: (x) => x,
|
|
584
|
-
int: toNumber,
|
|
585
|
-
uint: toNumber,
|
|
586
|
-
short: toNumber,
|
|
587
|
-
ushort: toNumber,
|
|
588
|
-
float: toNumber,
|
|
589
|
-
double: toNumber,
|
|
590
|
-
bool: (x) => Boolean(x),
|
|
591
|
-
};
|
|
592
|
-
function extractExtendedData(node, schema) {
|
|
593
|
-
return get(node, "ExtendedData", (extendedData, properties) => {
|
|
594
|
-
for (const data of $(extendedData, "Data")) {
|
|
595
|
-
properties[data.getAttribute("name") || ""] = nodeVal(get1(data, "value"));
|
|
596
|
-
}
|
|
597
|
-
for (const simpleData of $(extendedData, "SimpleData")) {
|
|
598
|
-
const name = simpleData.getAttribute("name") || "";
|
|
599
|
-
const typeConverter = schema[name] || typeConverters.string;
|
|
600
|
-
properties[name] = typeConverter(nodeVal(simpleData));
|
|
601
|
-
}
|
|
602
|
-
return properties;
|
|
603
|
-
});
|
|
604
|
-
}
|
|
605
|
-
function getMaybeHTMLDescription(node) {
|
|
606
|
-
const descriptionNode = get1(node, "description");
|
|
607
|
-
for (const c of Array.from(descriptionNode?.childNodes || [])) {
|
|
608
|
-
if (c.nodeType === 4) {
|
|
609
|
-
return {
|
|
610
|
-
description: {
|
|
611
|
-
"@type": "html",
|
|
612
|
-
value: nodeVal(c),
|
|
613
|
-
},
|
|
614
|
-
};
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
return {};
|
|
618
|
-
}
|
|
619
|
-
function extractTimeSpan(node) {
|
|
620
|
-
return get(node, "TimeSpan", (timeSpan) => {
|
|
621
|
-
return {
|
|
622
|
-
timespan: {
|
|
623
|
-
begin: nodeVal(get1(timeSpan, "begin")),
|
|
624
|
-
end: nodeVal(get1(timeSpan, "end")),
|
|
625
|
-
},
|
|
626
|
-
};
|
|
627
|
-
});
|
|
628
|
-
}
|
|
629
|
-
function extractTimeStamp(node) {
|
|
630
|
-
return get(node, "TimeStamp", (timeStamp) => {
|
|
631
|
-
return { timestamp: nodeVal(get1(timeStamp, "when")) };
|
|
632
|
-
});
|
|
633
|
-
}
|
|
634
|
-
function extractCascadedStyle(node, styleMap) {
|
|
635
|
-
return val1(node, "styleUrl", (styleUrl) => {
|
|
636
|
-
styleUrl = normalizeId(styleUrl);
|
|
637
|
-
if (styleMap[styleUrl]) {
|
|
638
|
-
return Object.assign({ styleUrl }, styleMap[styleUrl]);
|
|
639
|
-
}
|
|
640
|
-
// For backward-compatibility. Should we still include
|
|
641
|
-
// styleUrl even if it's not resolved?
|
|
642
|
-
return { styleUrl };
|
|
643
|
-
});
|
|
644
|
-
}
|
|
645
|
-
|
|
646
594
|
const removeSpace = /\s*/g;
|
|
647
595
|
const trimSpace = /^\s*|\s*$/g;
|
|
648
596
|
const splitSpace = /\s+/;
|
|
@@ -653,8 +601,8 @@ function coord1(value) {
|
|
|
653
601
|
return value
|
|
654
602
|
.replace(removeSpace, "")
|
|
655
603
|
.split(",")
|
|
656
|
-
.map(parseFloat)
|
|
657
|
-
.filter((num) => !isNaN(num))
|
|
604
|
+
.map(Number.parseFloat)
|
|
605
|
+
.filter((num) => !Number.isNaN(num))
|
|
658
606
|
.slice(0, 3);
|
|
659
607
|
}
|
|
660
608
|
/**
|
|
@@ -675,7 +623,7 @@ function gxCoords(node) {
|
|
|
675
623
|
elems = $ns(node, "coord", "*");
|
|
676
624
|
}
|
|
677
625
|
const coordinates = elems.map((elem) => {
|
|
678
|
-
return nodeVal(elem).split(" ").map(parseFloat);
|
|
626
|
+
return nodeVal(elem).split(" ").map(Number.parseFloat);
|
|
679
627
|
});
|
|
680
628
|
if (coordinates.length === 0) {
|
|
681
629
|
return null;
|
|
@@ -785,47 +733,92 @@ function getGeometry(node) {
|
|
|
785
733
|
};
|
|
786
734
|
}
|
|
787
735
|
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
736
|
+
const toNumber = (x) => Number(x);
|
|
737
|
+
const typeConverters = {
|
|
738
|
+
string: (x) => x,
|
|
739
|
+
int: toNumber,
|
|
740
|
+
uint: toNumber,
|
|
741
|
+
short: toNumber,
|
|
742
|
+
ushort: toNumber,
|
|
743
|
+
float: toNumber,
|
|
744
|
+
double: toNumber,
|
|
745
|
+
bool: (x) => Boolean(x),
|
|
746
|
+
};
|
|
747
|
+
function extractExtendedData(node, schema) {
|
|
748
|
+
return get(node, "ExtendedData", (extendedData, properties) => {
|
|
749
|
+
for (const data of $(extendedData, "Data")) {
|
|
750
|
+
properties[data.getAttribute("name") || ""] = nodeVal(get1(data, "value"));
|
|
751
|
+
}
|
|
752
|
+
for (const simpleData of $(extendedData, "SimpleData")) {
|
|
753
|
+
const name = simpleData.getAttribute("name") || "";
|
|
754
|
+
const typeConverter = schema[name] || typeConverters.string;
|
|
755
|
+
properties[name] = typeConverter(nodeVal(simpleData));
|
|
756
|
+
}
|
|
757
|
+
return properties;
|
|
758
|
+
});
|
|
797
759
|
}
|
|
798
|
-
function
|
|
799
|
-
const
|
|
800
|
-
const
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
geometry,
|
|
807
|
-
properties: Object.assign(getMulti(node, [
|
|
808
|
-
"name",
|
|
809
|
-
"address",
|
|
810
|
-
"visibility",
|
|
811
|
-
"open",
|
|
812
|
-
"phoneNumber",
|
|
813
|
-
"description",
|
|
814
|
-
]), getMaybeHTMLDescription(node), extractCascadedStyle(node, styleMap), extractStyle(node), extractExtendedData(node, schema), extractTimeSpan(node), extractTimeStamp(node), coordTimes.length
|
|
815
|
-
? {
|
|
816
|
-
coordinateProperties: {
|
|
817
|
-
times: coordTimes.length === 1 ? coordTimes[0] : coordTimes,
|
|
760
|
+
function getMaybeHTMLDescription(node) {
|
|
761
|
+
const descriptionNode = get1(node, "description");
|
|
762
|
+
for (const c of Array.from(descriptionNode?.childNodes || [])) {
|
|
763
|
+
if (c.nodeType === 4) {
|
|
764
|
+
return {
|
|
765
|
+
description: {
|
|
766
|
+
"@type": "html",
|
|
767
|
+
value: nodeVal(c),
|
|
818
768
|
},
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
};
|
|
822
|
-
if (feature.properties?.visibility !== undefined) {
|
|
823
|
-
feature.properties.visibility = feature.properties.visibility !== "0";
|
|
769
|
+
};
|
|
770
|
+
}
|
|
824
771
|
}
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
return
|
|
772
|
+
return {};
|
|
773
|
+
}
|
|
774
|
+
function extractTimeSpan(node) {
|
|
775
|
+
return get(node, "TimeSpan", (timeSpan) => {
|
|
776
|
+
return {
|
|
777
|
+
timespan: {
|
|
778
|
+
begin: nodeVal(get1(timeSpan, "begin")),
|
|
779
|
+
end: nodeVal(get1(timeSpan, "end")),
|
|
780
|
+
},
|
|
781
|
+
};
|
|
782
|
+
});
|
|
783
|
+
}
|
|
784
|
+
function extractTimeStamp(node) {
|
|
785
|
+
return get(node, "TimeStamp", (timeStamp) => {
|
|
786
|
+
return { timestamp: nodeVal(get1(timeStamp, "when")) };
|
|
787
|
+
});
|
|
788
|
+
}
|
|
789
|
+
function extractCascadedStyle(node, styleMap) {
|
|
790
|
+
return val1(node, "styleUrl", (styleUrl) => {
|
|
791
|
+
styleUrl = normalizeId(styleUrl);
|
|
792
|
+
if (styleMap[styleUrl]) {
|
|
793
|
+
return Object.assign({ styleUrl }, styleMap[styleUrl]);
|
|
794
|
+
}
|
|
795
|
+
// For backward-compatibility. Should we still include
|
|
796
|
+
// styleUrl even if it's not resolved?
|
|
797
|
+
return { styleUrl };
|
|
798
|
+
});
|
|
799
|
+
}
|
|
800
|
+
var AltitudeMode;
|
|
801
|
+
(function (AltitudeMode) {
|
|
802
|
+
AltitudeMode["ABSOLUTE"] = "absolute";
|
|
803
|
+
AltitudeMode["RELATIVE_TO_GROUND"] = "relativeToGround";
|
|
804
|
+
AltitudeMode["CLAMP_TO_GROUND"] = "clampToGround";
|
|
805
|
+
AltitudeMode["CLAMP_TO_SEAFLOOR"] = "clampToSeaFloor";
|
|
806
|
+
AltitudeMode["RELATIVE_TO_SEAFLOOR"] = "relativeToSeaFloor";
|
|
807
|
+
})(AltitudeMode || (AltitudeMode = {}));
|
|
808
|
+
function processAltitudeMode(mode) {
|
|
809
|
+
switch (mode?.textContent) {
|
|
810
|
+
case AltitudeMode.ABSOLUTE:
|
|
811
|
+
return AltitudeMode.ABSOLUTE;
|
|
812
|
+
case AltitudeMode.CLAMP_TO_GROUND:
|
|
813
|
+
return AltitudeMode.CLAMP_TO_GROUND;
|
|
814
|
+
case AltitudeMode.CLAMP_TO_SEAFLOOR:
|
|
815
|
+
return AltitudeMode.CLAMP_TO_SEAFLOOR;
|
|
816
|
+
case AltitudeMode.RELATIVE_TO_GROUND:
|
|
817
|
+
return AltitudeMode.RELATIVE_TO_GROUND;
|
|
818
|
+
case AltitudeMode.RELATIVE_TO_SEAFLOOR:
|
|
819
|
+
return AltitudeMode.RELATIVE_TO_SEAFLOOR;
|
|
820
|
+
}
|
|
821
|
+
return null;
|
|
829
822
|
}
|
|
830
823
|
|
|
831
824
|
function getGroundOverlayBox(node) {
|
|
@@ -848,7 +841,7 @@ function rotateBox(bbox, coordinates, rotation) {
|
|
|
848
841
|
coordinates[0].map((coordinate) => {
|
|
849
842
|
const dy = coordinate[1] - center[1];
|
|
850
843
|
const dx = coordinate[0] - center[0];
|
|
851
|
-
const distance = Math.sqrt(
|
|
844
|
+
const distance = Math.sqrt(dy ** 2 + dx ** 2);
|
|
852
845
|
const angle = Math.atan2(dy, dx) + rotation * DEGREES_TO_RADIANS;
|
|
853
846
|
return [
|
|
854
847
|
center[0] + Math.cos(angle) * distance,
|
|
@@ -872,10 +865,10 @@ function getLatLonBox(node) {
|
|
|
872
865
|
const bbox = [west, south, east, north];
|
|
873
866
|
let coordinates = [
|
|
874
867
|
[
|
|
875
|
-
[west, north],
|
|
876
|
-
[east, north],
|
|
877
|
-
[east, south],
|
|
878
|
-
[west, south],
|
|
868
|
+
[west, north], // top left
|
|
869
|
+
[east, north], // top right
|
|
870
|
+
[east, south], // top right
|
|
871
|
+
[west, south], // bottom left
|
|
879
872
|
[west, north], // top left (again)
|
|
880
873
|
],
|
|
881
874
|
];
|
|
@@ -928,6 +921,178 @@ function getGroundOverlay(node, styleMap, schema, options) {
|
|
|
928
921
|
return feature;
|
|
929
922
|
}
|
|
930
923
|
|
|
924
|
+
function getNetworkLinkRegion(node) {
|
|
925
|
+
const region = get1(node, "Region");
|
|
926
|
+
if (region) {
|
|
927
|
+
return {
|
|
928
|
+
coordinateBox: getLatLonAltBox(region),
|
|
929
|
+
lod: getLod(node),
|
|
930
|
+
};
|
|
931
|
+
}
|
|
932
|
+
return null;
|
|
933
|
+
}
|
|
934
|
+
function getLod(node) {
|
|
935
|
+
const lod = get1(node, "Lod");
|
|
936
|
+
if (lod) {
|
|
937
|
+
return [
|
|
938
|
+
num1(lod, "minLodPixels") ?? -1,
|
|
939
|
+
num1(lod, "maxLodPixels") ?? -1,
|
|
940
|
+
num1(lod, "minFadeExtent") ?? null,
|
|
941
|
+
num1(lod, "maxFadeExtent") ?? null,
|
|
942
|
+
];
|
|
943
|
+
}
|
|
944
|
+
return null;
|
|
945
|
+
}
|
|
946
|
+
function getLatLonAltBox(node) {
|
|
947
|
+
const latLonAltBox = get1(node, "LatLonAltBox");
|
|
948
|
+
if (latLonAltBox) {
|
|
949
|
+
const north = num1(latLonAltBox, "north");
|
|
950
|
+
const west = num1(latLonAltBox, "west");
|
|
951
|
+
const east = num1(latLonAltBox, "east");
|
|
952
|
+
const south = num1(latLonAltBox, "south");
|
|
953
|
+
const altitudeMode = processAltitudeMode(get1(latLonAltBox, "altitudeMode") ||
|
|
954
|
+
get1(latLonAltBox, "gx:altitudeMode"));
|
|
955
|
+
if (altitudeMode) {
|
|
956
|
+
console.debug("Encountered an unsupported feature of KML for togeojson: please contact developers for support of altitude mode.");
|
|
957
|
+
}
|
|
958
|
+
if (typeof north === "number" &&
|
|
959
|
+
typeof south === "number" &&
|
|
960
|
+
typeof west === "number" &&
|
|
961
|
+
typeof east === "number") {
|
|
962
|
+
const bbox = [west, south, east, north];
|
|
963
|
+
const coordinates = [
|
|
964
|
+
[
|
|
965
|
+
[west, north], // top left
|
|
966
|
+
[east, north], // top right
|
|
967
|
+
[east, south], // top right
|
|
968
|
+
[west, south], // bottom left
|
|
969
|
+
[west, north], // top left (again)
|
|
970
|
+
],
|
|
971
|
+
];
|
|
972
|
+
return {
|
|
973
|
+
bbox,
|
|
974
|
+
geometry: {
|
|
975
|
+
type: "Polygon",
|
|
976
|
+
coordinates,
|
|
977
|
+
},
|
|
978
|
+
};
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
return null;
|
|
982
|
+
}
|
|
983
|
+
function getLinkObject(node) {
|
|
984
|
+
/*
|
|
985
|
+
<Link id="ID">
|
|
986
|
+
<!-- specific to Link -->
|
|
987
|
+
<href>...</href> <!-- string -->
|
|
988
|
+
<refreshMode>onChange</refreshMode>
|
|
989
|
+
<!-- refreshModeEnum: onChange, onInterval, or onExpire -->
|
|
990
|
+
<refreshInterval>4</refreshInterval> <!-- float -->
|
|
991
|
+
<viewRefreshMode>never</viewRefreshMode>
|
|
992
|
+
<!-- viewRefreshModeEnum: never, onStop, onRequest, onRegion -->
|
|
993
|
+
<viewRefreshTime>4</viewRefreshTime> <!-- float -->
|
|
994
|
+
<viewBoundScale>1</viewBoundScale> <!-- float -->
|
|
995
|
+
<viewFormat>BBOX=[bboxWest],[bboxSouth],[bboxEast],[bboxNorth]</viewFormat>
|
|
996
|
+
<!-- string -->
|
|
997
|
+
<httpQuery>...</httpQuery> <!-- string -->
|
|
998
|
+
</Link>
|
|
999
|
+
*/
|
|
1000
|
+
const linkObj = get1(node, "Link");
|
|
1001
|
+
if (linkObj) {
|
|
1002
|
+
return getMulti(linkObj, [
|
|
1003
|
+
"href",
|
|
1004
|
+
"refreshMode",
|
|
1005
|
+
"refreshInterval",
|
|
1006
|
+
"viewRefreshMode",
|
|
1007
|
+
"viewRefreshTime",
|
|
1008
|
+
"viewBoundScale",
|
|
1009
|
+
"viewFormat",
|
|
1010
|
+
"httpQuery",
|
|
1011
|
+
]);
|
|
1012
|
+
}
|
|
1013
|
+
return {};
|
|
1014
|
+
}
|
|
1015
|
+
function getNetworkLink(node, styleMap, schema, options) {
|
|
1016
|
+
const box = getNetworkLinkRegion(node);
|
|
1017
|
+
const geometry = box?.coordinateBox?.geometry || null;
|
|
1018
|
+
if (!geometry && options.skipNullGeometry) {
|
|
1019
|
+
return null;
|
|
1020
|
+
}
|
|
1021
|
+
const feature = {
|
|
1022
|
+
type: "Feature",
|
|
1023
|
+
geometry,
|
|
1024
|
+
properties: Object.assign(
|
|
1025
|
+
/**
|
|
1026
|
+
* Related to
|
|
1027
|
+
* https://gist.github.com/tmcw/037a1cb6660d74a392e9da7446540f46
|
|
1028
|
+
*/
|
|
1029
|
+
{ "@geometry-type": "networklink" }, getMulti(node, [
|
|
1030
|
+
"name",
|
|
1031
|
+
"address",
|
|
1032
|
+
"visibility",
|
|
1033
|
+
"open",
|
|
1034
|
+
"phoneNumber",
|
|
1035
|
+
"styleUrl",
|
|
1036
|
+
"refreshVisibility",
|
|
1037
|
+
"flyToView",
|
|
1038
|
+
"description",
|
|
1039
|
+
]), getMaybeHTMLDescription(node), extractCascadedStyle(node, styleMap), extractStyle(node), extractIconHref(node), extractExtendedData(node, schema), extractTimeSpan(node), extractTimeStamp(node), getLinkObject(node), box?.lod ? { lod: box.lod } : {}),
|
|
1040
|
+
};
|
|
1041
|
+
if (box?.coordinateBox?.bbox) {
|
|
1042
|
+
feature.bbox = box.coordinateBox.bbox;
|
|
1043
|
+
}
|
|
1044
|
+
if (feature.properties?.visibility !== undefined) {
|
|
1045
|
+
feature.properties.visibility = feature.properties.visibility !== "0";
|
|
1046
|
+
}
|
|
1047
|
+
const id = node.getAttribute("id");
|
|
1048
|
+
if (id !== null && id !== "")
|
|
1049
|
+
feature.id = id;
|
|
1050
|
+
return feature;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
function geometryListToGeometry(geometries) {
|
|
1054
|
+
return geometries.length === 0
|
|
1055
|
+
? null
|
|
1056
|
+
: geometries.length === 1
|
|
1057
|
+
? geometries[0]
|
|
1058
|
+
: {
|
|
1059
|
+
type: "GeometryCollection",
|
|
1060
|
+
geometries,
|
|
1061
|
+
};
|
|
1062
|
+
}
|
|
1063
|
+
function getPlacemark(node, styleMap, schema, options) {
|
|
1064
|
+
const { coordTimes, geometries } = getGeometry(node);
|
|
1065
|
+
const geometry = geometryListToGeometry(geometries);
|
|
1066
|
+
if (!geometry && options.skipNullGeometry) {
|
|
1067
|
+
return null;
|
|
1068
|
+
}
|
|
1069
|
+
const feature = {
|
|
1070
|
+
type: "Feature",
|
|
1071
|
+
geometry,
|
|
1072
|
+
properties: Object.assign(getMulti(node, [
|
|
1073
|
+
"name",
|
|
1074
|
+
"address",
|
|
1075
|
+
"visibility",
|
|
1076
|
+
"open",
|
|
1077
|
+
"phoneNumber",
|
|
1078
|
+
"description",
|
|
1079
|
+
]), getMaybeHTMLDescription(node), extractCascadedStyle(node, styleMap), extractStyle(node), extractExtendedData(node, schema), extractTimeSpan(node), extractTimeStamp(node), coordTimes.length
|
|
1080
|
+
? {
|
|
1081
|
+
coordinateProperties: {
|
|
1082
|
+
times: coordTimes.length === 1 ? coordTimes[0] : coordTimes,
|
|
1083
|
+
},
|
|
1084
|
+
}
|
|
1085
|
+
: {}),
|
|
1086
|
+
};
|
|
1087
|
+
if (feature.properties?.visibility !== undefined) {
|
|
1088
|
+
feature.properties.visibility = feature.properties.visibility !== "0";
|
|
1089
|
+
}
|
|
1090
|
+
const id = node.getAttribute("id");
|
|
1091
|
+
if (id !== null && id !== "")
|
|
1092
|
+
feature.id = id;
|
|
1093
|
+
return feature;
|
|
1094
|
+
}
|
|
1095
|
+
|
|
931
1096
|
function getStyleId(style) {
|
|
932
1097
|
let id = style.getAttribute("id");
|
|
933
1098
|
const parentNode = style.parentNode;
|
|
@@ -958,8 +1123,7 @@ function buildSchema(node) {
|
|
|
958
1123
|
const schema = {};
|
|
959
1124
|
for (const field of $(node, "SimpleField")) {
|
|
960
1125
|
schema[field.getAttribute("name") || ""] =
|
|
961
|
-
typeConverters[field.getAttribute("type") || ""] ||
|
|
962
|
-
typeConverters["string"];
|
|
1126
|
+
typeConverters[field.getAttribute("type") || ""] || typeConverters.string;
|
|
963
1127
|
}
|
|
964
1128
|
return schema;
|
|
965
1129
|
}
|
|
@@ -1028,8 +1192,9 @@ function getFolder(node) {
|
|
|
1028
1192
|
function kmlWithFolders(node, options = {
|
|
1029
1193
|
skipNullGeometry: false,
|
|
1030
1194
|
}) {
|
|
1031
|
-
const
|
|
1032
|
-
const
|
|
1195
|
+
const n = node;
|
|
1196
|
+
const styleMap = buildStyleMap(n);
|
|
1197
|
+
const schema = buildSchema(n);
|
|
1033
1198
|
const tree = { type: "root", children: [] };
|
|
1034
1199
|
function traverse(node, pointer, options) {
|
|
1035
1200
|
if (isElement(node)) {
|
|
@@ -1054,6 +1219,13 @@ function kmlWithFolders(node, options = {
|
|
|
1054
1219
|
pointer = folder;
|
|
1055
1220
|
break;
|
|
1056
1221
|
}
|
|
1222
|
+
case "NetworkLink": {
|
|
1223
|
+
const networkLink = getNetworkLink(node, styleMap, schema, options);
|
|
1224
|
+
if (networkLink) {
|
|
1225
|
+
pointer.children.push(networkLink);
|
|
1226
|
+
}
|
|
1227
|
+
break;
|
|
1228
|
+
}
|
|
1057
1229
|
}
|
|
1058
1230
|
}
|
|
1059
1231
|
if (node.childNodes) {
|
|
@@ -1062,7 +1234,7 @@ function kmlWithFolders(node, options = {
|
|
|
1062
1234
|
}
|
|
1063
1235
|
}
|
|
1064
1236
|
}
|
|
1065
|
-
traverse(
|
|
1237
|
+
traverse(n, tree, options);
|
|
1066
1238
|
return tree;
|
|
1067
1239
|
}
|
|
1068
1240
|
/**
|
|
@@ -1073,14 +1245,15 @@ function kmlWithFolders(node, options = {
|
|
|
1073
1245
|
function* kmlGen(node, options = {
|
|
1074
1246
|
skipNullGeometry: false,
|
|
1075
1247
|
}) {
|
|
1076
|
-
const
|
|
1077
|
-
const
|
|
1078
|
-
|
|
1248
|
+
const n = node;
|
|
1249
|
+
const styleMap = buildStyleMap(n);
|
|
1250
|
+
const schema = buildSchema(n);
|
|
1251
|
+
for (const placemark of $(n, "Placemark")) {
|
|
1079
1252
|
const feature = getPlacemark(placemark, styleMap, schema, options);
|
|
1080
1253
|
if (feature)
|
|
1081
1254
|
yield feature;
|
|
1082
1255
|
}
|
|
1083
|
-
for (const groundOverlay of $(
|
|
1256
|
+
for (const groundOverlay of $(n, "GroundOverlay")) {
|
|
1084
1257
|
const feature = getGroundOverlay(groundOverlay, styleMap, schema, options);
|
|
1085
1258
|
if (feature)
|
|
1086
1259
|
yield feature;
|