isard 1.1.0 → 1.2.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/CHANGELOG.md +33 -0
- package/dist/basemap/basemaps.d.ts +1 -1
- package/dist/basemap/basemaps.js +2 -2
- package/dist/basemap/basemaps.js.map +1 -1
- package/dist/basemap/grid.d.ts +5 -5
- package/dist/basemap/grid.js +59 -65
- package/dist/basemap/grid.js.map +1 -1
- package/dist/basemap/mvt.d.ts +1 -1
- package/dist/basemap/mvt.js +6 -6
- package/dist/basemap/mvt.js.map +1 -1
- package/dist/basemap/pmtiles.d.ts +10 -10
- package/dist/basemap/pmtiles.js +39 -31
- package/dist/basemap/pmtiles.js.map +1 -1
- package/dist/basemap/resample.d.ts +2 -2
- package/dist/basemap/resample.js +16 -14
- package/dist/basemap/resample.js.map +1 -1
- package/dist/basemap/terrain.d.ts +3 -3
- package/dist/basemap/terrain.js +6 -6
- package/dist/basemap/terrain.js.map +1 -1
- package/dist/basemap/vectorstyle.d.ts +12 -10
- package/dist/basemap/vectorstyle.js +128 -110
- package/dist/basemap/vectorstyle.js.map +1 -1
- package/dist/basemap/vectortiles.d.ts +11 -11
- package/dist/basemap/vectortiles.js +141 -103
- package/dist/basemap/vectortiles.js.map +1 -1
- package/dist/basemap/wmts.d.ts +3 -3
- package/dist/basemap/wmts.js +16 -11
- package/dist/basemap/wmts.js.map +1 -1
- package/dist/basemap.worker.js +2 -2
- package/dist/basemap.worker.js.map +14 -13
- package/dist/bind/layers.d.ts +13 -4
- package/dist/bind/layers.js +64 -40
- package/dist/bind/layers.js.map +1 -1
- package/dist/data/crs.d.ts +10 -10
- package/dist/data/crs.js +38 -34
- package/dist/data/crs.js.map +1 -1
- package/dist/data/gpx.d.ts +1 -1
- package/dist/data/gpx.js +20 -20
- package/dist/data/gpx.js.map +1 -1
- package/dist/data/kml.d.ts +1 -1
- package/dist/data/kml.js +42 -39
- package/dist/data/kml.js.map +1 -1
- package/dist/data/topojson.d.ts +1 -1
- package/dist/data/topojson.js +15 -10
- package/dist/data/topojson.js.map +1 -1
- package/dist/data/xml.d.ts +5 -5
- package/dist/data/xml.js +19 -18
- package/dist/data/xml.js.map +1 -1
- package/dist/decoder.worker.js +4 -4
- package/dist/decoder.worker.js.map +6 -6
- package/dist/engine/decoders.d.ts +2 -2
- package/dist/engine/decoders.js +28 -25
- package/dist/engine/decoders.js.map +1 -1
- package/dist/engine/loader.js +13 -14
- package/dist/engine/loader.js.map +1 -1
- package/dist/engine/requests.d.ts +1 -1
- package/dist/engine/requests.js +19 -16
- package/dist/engine/requests.js.map +1 -1
- package/dist/engine-loader.d.ts +8 -8
- package/dist/engine-loader.js +27 -27
- package/dist/engine-loader.js.map +1 -1
- package/dist/geoplateforme.d.ts +10 -10
- package/dist/geoplateforme.js +22 -20
- package/dist/geoplateforme.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js.map +1 -1
- package/dist/isard_bg.wasm +0 -0
- package/dist/isard_core_bg.wasm +0 -0
- package/dist/isard_points_bg.wasm +0 -0
- package/dist/layers/extrusions.d.ts +1 -1
- package/dist/layers/extrusions.js +10 -5
- package/dist/layers/extrusions.js.map +1 -1
- package/dist/layers/features.d.ts +10 -10
- package/dist/layers/features.js +41 -42
- package/dist/layers/features.js.map +1 -1
- package/dist/layers/glyphs.d.ts +3 -3
- package/dist/layers/glyphs.js +34 -40
- package/dist/layers/glyphs.js.map +1 -1
- package/dist/layers/icons.d.ts +8 -8
- package/dist/layers/icons.js +76 -68
- package/dist/layers/icons.js.map +1 -1
- package/dist/layers/layers.d.ts +1 -1
- package/dist/layers/layers.js +33 -29
- package/dist/layers/layers.js.map +1 -1
- package/dist/layers/panoramas.d.ts +2 -2
- package/dist/layers/panoramas.js +52 -41
- package/dist/layers/panoramas.js.map +1 -1
- package/dist/layers/pointclouds.d.ts +3 -3
- package/dist/layers/pointclouds.js +25 -33
- package/dist/layers/pointclouds.js.map +1 -1
- package/dist/layers/symbols.d.ts +1 -1
- package/dist/layers/symbols.js +68 -71
- package/dist/layers/symbols.js.map +1 -1
- package/dist/map/basemap-layers.d.ts +26 -0
- package/dist/map/basemap-layers.js +61 -0
- package/dist/map/basemap-layers.js.map +1 -0
- package/dist/map/canvas.d.ts +17 -0
- package/dist/map/canvas.js +56 -0
- package/dist/map/canvas.js.map +1 -0
- package/dist/map/checks.d.ts +11 -0
- package/dist/map/checks.js +39 -0
- package/dist/map/checks.js.map +1 -0
- package/dist/map/credits.d.ts +17 -0
- package/dist/map/credits.js +34 -0
- package/dist/map/credits.js.map +1 -0
- package/dist/map/engine-settings.d.ts +15 -0
- package/dist/map/engine-settings.js +45 -0
- package/dist/map/engine-settings.js.map +1 -0
- package/dist/map/engines.d.ts +41 -0
- package/dist/map/engines.js +77 -0
- package/dist/map/engines.js.map +1 -0
- package/dist/map/events.d.ts +14 -0
- package/dist/map/events.js +46 -0
- package/dist/map/events.js.map +1 -0
- package/dist/map/frame-loop.d.ts +61 -0
- package/dist/map/frame-loop.js +139 -0
- package/dist/map/frame-loop.js.map +1 -0
- package/dist/map/hover-pick.d.ts +30 -0
- package/dist/map/hover-pick.js +56 -0
- package/dist/map/hover-pick.js.map +1 -0
- package/dist/map/layer-spec.d.ts +42 -0
- package/dist/map/layer-spec.js +34 -0
- package/dist/map/layer-spec.js.map +1 -0
- package/dist/map/layer-stack.d.ts +36 -0
- package/dist/map/layer-stack.js +101 -0
- package/dist/map/layer-stack.js.map +1 -0
- package/dist/map/overlay-host.d.ts +36 -0
- package/dist/map/overlay-host.js +101 -0
- package/dist/map/overlay-host.js.map +1 -0
- package/dist/map/panorama-host.d.ts +5 -0
- package/dist/map/panorama-host.js +32 -0
- package/dist/map/panorama-host.js.map +1 -0
- package/dist/map/raster-source.d.ts +11 -0
- package/dist/map/raster-source.js +26 -0
- package/dist/map/raster-source.js.map +1 -0
- package/dist/map/symbol-atlases.d.ts +26 -0
- package/dist/map/symbol-atlases.js +59 -0
- package/dist/map/symbol-atlases.js.map +1 -0
- package/dist/map/viewshed.d.ts +5 -0
- package/dist/map/viewshed.js +28 -0
- package/dist/map/viewshed.js.map +1 -0
- package/dist/map/workers.d.ts +46 -0
- package/dist/map/workers.js +73 -0
- package/dist/map/workers.js.map +1 -0
- package/dist/map.d.ts +33 -120
- package/dist/map.js +164 -689
- package/dist/map.js.map +1 -1
- package/dist/react/Control.d.ts +11 -0
- package/dist/react/Control.js +18 -0
- package/dist/react/Control.js.map +1 -0
- package/dist/react/CustomLayer.d.ts +11 -0
- package/dist/react/CustomLayer.js +30 -0
- package/dist/react/CustomLayer.js.map +1 -0
- package/dist/react/IsardMap.d.ts +43 -0
- package/dist/react/IsardMap.js +146 -0
- package/dist/react/IsardMap.js.map +1 -0
- package/dist/react/Layer.d.ts +42 -0
- package/dist/react/Layer.js +74 -0
- package/dist/react/Layer.js.map +1 -0
- package/dist/react/Marker.d.ts +24 -0
- package/dist/react/Marker.js +53 -0
- package/dist/react/Marker.js.map +1 -0
- package/dist/react/Panel.d.ts +11 -0
- package/dist/react/Panel.js +37 -0
- package/dist/react/Panel.js.map +1 -0
- package/dist/react/Popup.d.ts +18 -0
- package/dist/react/Popup.js +60 -0
- package/dist/react/Popup.js.map +1 -0
- package/dist/react/Swipe.d.ts +9 -0
- package/dist/react/Swipe.js +41 -0
- package/dist/react/Swipe.js.map +1 -0
- package/dist/react/Viewshed.d.ts +5 -0
- package/dist/react/Viewshed.js +28 -0
- package/dist/react/Viewshed.js.map +1 -0
- package/dist/react/context.d.ts +32 -0
- package/dist/react/context.js +20 -0
- package/dist/react/context.js.map +1 -0
- package/dist/react/index.d.ts +15 -108
- package/dist/react/index.js +10 -397
- package/dist/react/index.js.map +1 -1
- package/dist/settings.d.ts +5 -9
- package/dist/settings.js +17 -15
- package/dist/settings.js.map +1 -1
- package/dist/types.d.ts +3 -3
- package/dist/types.js.map +1 -1
- package/dist/ui/controls.js +6 -4
- package/dist/ui/controls.js.map +1 -1
- package/dist/ui/interaction.d.ts +2 -2
- package/dist/ui/interaction.js +8 -7
- package/dist/ui/interaction.js.map +1 -1
- package/dist/ui/overlay.js +18 -20
- package/dist/ui/overlay.js.map +1 -1
- package/dist/ui/style.d.ts +1 -1
- package/dist/ui/style.js +2 -2
- package/dist/ui/style.js.map +1 -1
- package/dist/util/animation.d.ts +3 -3
- package/dist/util/animation.js +6 -6
- package/dist/util/animation.js.map +1 -1
- package/dist/util/color.d.ts +1 -1
- package/dist/util/color.js +14 -16
- package/dist/util/color.js.map +1 -1
- package/dist/util/geo.d.ts +6 -6
- package/dist/util/geo.js +12 -12
- package/dist/util/geo.js.map +1 -1
- package/dist/util/guards.d.ts +7 -0
- package/dist/util/guards.js +8 -0
- package/dist/util/guards.js.map +1 -0
- package/dist/util/lru.js.map +1 -1
- package/dist/wasm/isard.d.ts +168 -0
- package/dist/wasm/isard.js +146 -0
- package/dist/wasm/isard_core.d.ts +144 -0
- package/dist/wasm/isard_core.js +122 -0
- package/dist/workers/basemap.worker.d.ts +3 -3
- package/dist/workers/basemap.worker.js +94 -83
- package/dist/workers/basemap.worker.js.map +1 -1
- package/package.json +1 -1
package/dist/data/gpx.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { child, children, childText, parseXml } from "./xml.js";
|
|
2
2
|
/** The fields of a waypoint, route or track kept as properties when present */
|
|
3
3
|
const FIELDS = ['name', 'cmt', 'desc', 'src', 'sym', 'type', 'number'];
|
|
4
|
-
|
|
4
|
+
const properties = (element) => {
|
|
5
5
|
const out = {};
|
|
6
|
-
|
|
6
|
+
FIELDS.forEach((key) => {
|
|
7
7
|
const value = childText(element, key);
|
|
8
8
|
if (value !== undefined)
|
|
9
9
|
out[key] = key === 'number' ? Number(value) : value;
|
|
10
|
-
}
|
|
10
|
+
});
|
|
11
11
|
const link = child(element, 'link')?.attributes.href;
|
|
12
12
|
if (link !== undefined)
|
|
13
13
|
out.link = link;
|
|
14
14
|
return out;
|
|
15
|
-
}
|
|
15
|
+
};
|
|
16
16
|
/** A point of a GPX file (wpt, rtept, trkpt): its position, its altitude third if any, and its time */
|
|
17
|
-
|
|
17
|
+
const point = (element) => {
|
|
18
18
|
const lon = Number(element.attributes.lon);
|
|
19
19
|
const lat = Number(element.attributes.lat);
|
|
20
20
|
if (!Number.isFinite(lon) || !Number.isFinite(lat) || element.attributes.lon === undefined)
|
|
@@ -22,44 +22,44 @@ function point(element) {
|
|
|
22
22
|
const ele = childText(element, 'ele');
|
|
23
23
|
const position = ele !== undefined && Number.isFinite(Number(ele)) ? [lon, lat, Number(ele)] : [lon, lat];
|
|
24
24
|
return { position, time: childText(element, 'time') };
|
|
25
|
-
}
|
|
25
|
+
};
|
|
26
26
|
/** The positions of a line of points, and their times when every point has one */
|
|
27
|
-
|
|
27
|
+
const line = (points) => {
|
|
28
28
|
const read = points.map(point).filter((p) => p !== undefined);
|
|
29
|
-
const times = read.map((p) => p.time);
|
|
29
|
+
const times = read.map((p) => p.time).filter((t) => t !== undefined);
|
|
30
30
|
return {
|
|
31
31
|
coordinates: read.map((p) => p.position),
|
|
32
|
-
times: read.length > 0 && times.
|
|
32
|
+
times: read.length > 0 && times.length === read.length ? times : undefined,
|
|
33
33
|
};
|
|
34
|
-
}
|
|
34
|
+
};
|
|
35
35
|
/**
|
|
36
36
|
* The waypoints, routes and tracks of a GPX file as GeoJSON features: a waypoint as a point (its `time` a property),
|
|
37
37
|
* a route as a line, a track as a line or, of several segments, a multi-line; altitudes (`ele`) as the third
|
|
38
38
|
* coordinate; `name`, `desc`, `cmt`, `type`… as properties, and the times of the points as `times` (one list, or one
|
|
39
39
|
* per segment) when they all have one
|
|
40
40
|
*/
|
|
41
|
-
export
|
|
41
|
+
export const parseGpx = (text) => {
|
|
42
42
|
const root = parseXml(text);
|
|
43
43
|
const features = [];
|
|
44
44
|
const add = (geometry, props) => features.push({ type: 'Feature', geometry, properties: props });
|
|
45
|
-
|
|
45
|
+
children(root, 'wpt').forEach((wpt) => {
|
|
46
46
|
const p = point(wpt);
|
|
47
47
|
if (!p)
|
|
48
|
-
|
|
48
|
+
return;
|
|
49
49
|
add({ type: 'Point', coordinates: p.position }, { ...properties(wpt), ...(p.time ? { time: p.time } : {}) });
|
|
50
|
-
}
|
|
51
|
-
|
|
50
|
+
});
|
|
51
|
+
children(root, 'rte').forEach((rte) => {
|
|
52
52
|
const { coordinates, times } = line(children(rte, 'rtept'));
|
|
53
53
|
if (coordinates.length >= 2)
|
|
54
54
|
add({ type: 'LineString', coordinates }, { ...properties(rte), ...(times ? { times } : {}) });
|
|
55
|
-
}
|
|
56
|
-
|
|
55
|
+
});
|
|
56
|
+
children(root, 'trk').forEach((trk) => {
|
|
57
57
|
const segments = children(trk, 'trkseg')
|
|
58
58
|
.map((s) => line(children(s, 'trkpt')))
|
|
59
59
|
.filter((s) => s.coordinates.length >= 2);
|
|
60
60
|
const [first] = segments;
|
|
61
61
|
if (!first)
|
|
62
|
-
|
|
62
|
+
return;
|
|
63
63
|
const props = properties(trk);
|
|
64
64
|
if (segments.length === 1) {
|
|
65
65
|
add({ type: 'LineString', coordinates: first.coordinates }, { ...props, ...(first.times ? { times: first.times } : {}) });
|
|
@@ -68,7 +68,7 @@ export function parseGpx(text) {
|
|
|
68
68
|
const times = segments.every((s) => s.times) ? { times: segments.map((s) => s.times) } : {};
|
|
69
69
|
add({ type: 'MultiLineString', coordinates: segments.map((s) => s.coordinates) }, { ...props, ...times });
|
|
70
70
|
}
|
|
71
|
-
}
|
|
71
|
+
});
|
|
72
72
|
return { type: 'FeatureCollection', features };
|
|
73
|
-
}
|
|
73
|
+
};
|
|
74
74
|
//# sourceMappingURL=gpx.js.map
|
package/dist/data/gpx.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gpx.js","sourceRoot":"","sources":["../../src/data/gpx.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAmB,MAAM,UAAU,CAAC;AAEjF,+EAA+E;AAC/E,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;AAEvE,
|
|
1
|
+
{"version":3,"file":"gpx.js","sourceRoot":"","sources":["../../src/data/gpx.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * GPX to GeoJSON, for the feature layers: `map.addLines({ data: parseGpx(await (await fetch(url)).text()) })`.\n */\nimport type { Feature, FeatureCollection, Geometry, Position, Properties } from '../layers/features.ts';\nimport { child, children, childText, parseXml, type XmlElement } from './xml.ts';\n\n/** The fields of a waypoint, route or track kept as properties when present */\nconst FIELDS = ['name', 'cmt', 'desc', 'src', 'sym', 'type', 'number'];\n\nconst properties = (element: XmlElement): Properties => {\n const out: Properties = {};\n\n FIELDS.forEach((key) => {\n const value = childText(element, key);\n\n if (value !== undefined) out[key] = key === 'number' ? Number(value) : value;\n });\n\n const link = child(element, 'link')?.attributes.href;\n\n if (link !== undefined) out.link = link;\n\n return out;\n};\n\n/** A point of a GPX file (wpt, rtept, trkpt): its position, its altitude third if any, and its time */\nconst point = (element: XmlElement): { position: Position; time: string | undefined } | undefined => {\n const lon = Number(element.attributes.lon);\n const lat = Number(element.attributes.lat);\n\n if (!Number.isFinite(lon) || !Number.isFinite(lat) || element.attributes.lon === undefined) return undefined;\n\n const ele = childText(element, 'ele');\n const position: Position = ele !== undefined && Number.isFinite(Number(ele)) ? [lon, lat, Number(ele)] : [lon, lat];\n\n return { position, time: childText(element, 'time') };\n};\n\n/** The positions of a line of points, and their times when every point has one */\nconst line = (points: XmlElement[]): { coordinates: Position[]; times: string[] | undefined } => {\n const read = points.map(point).filter((p) => p !== undefined);\n const times = read.map((p) => p.time).filter((t) => t !== undefined);\n\n return {\n coordinates: read.map((p) => p.position),\n times: read.length > 0 && times.length === read.length ? times : undefined,\n };\n};\n\n/**\n * The waypoints, routes and tracks of a GPX file as GeoJSON features: a waypoint as a point (its `time` a property),\n * a route as a line, a track as a line or, of several segments, a multi-line; altitudes (`ele`) as the third\n * coordinate; `name`, `desc`, `cmt`, `type`… as properties, and the times of the points as `times` (one list, or one\n * per segment) when they all have one\n */\nexport const parseGpx = <P = Properties>(text: string): FeatureCollection<P> => {\n const root = parseXml(text);\n const features: Feature<P>[] = [];\n const add = (geometry: Geometry, props: Properties) =>\n features.push({ type: 'Feature', geometry, properties: props as P });\n\n children(root, 'wpt').forEach((wpt) => {\n const p = point(wpt);\n\n if (!p) return;\n add({ type: 'Point', coordinates: p.position }, { ...properties(wpt), ...(p.time ? { time: p.time } : {}) });\n });\n children(root, 'rte').forEach((rte) => {\n const { coordinates, times } = line(children(rte, 'rtept'));\n\n if (coordinates.length >= 2)\n add({ type: 'LineString', coordinates }, { ...properties(rte), ...(times ? { times } : {}) });\n });\n children(root, 'trk').forEach((trk) => {\n const segments = children(trk, 'trkseg')\n .map((s) => line(children(s, 'trkpt')))\n .filter((s) => s.coordinates.length >= 2);\n const [first] = segments;\n\n if (!first) return;\n\n const props = properties(trk);\n\n if (segments.length === 1) {\n add(\n { type: 'LineString', coordinates: first.coordinates },\n { ...props, ...(first.times ? { times: first.times } : {}) },\n );\n } else {\n const times = segments.every((s) => s.times) ? { times: segments.map((s) => s.times) } : {};\n\n add({ type: 'MultiLineString', coordinates: segments.map((s) => s.coordinates) }, { ...props, ...times });\n }\n });\n\n return { type: 'FeatureCollection', features };\n};\n"]}
|
package/dist/data/kml.d.ts
CHANGED
|
@@ -9,4 +9,4 @@ import type { FeatureCollection, Properties } from '../layers/features.ts';
|
|
|
9
9
|
* `StyleMap`) as `stroke`, `stroke-opacity`, `stroke-width`, `fill`, `fill-opacity`, `marker-color`. A placemark
|
|
10
10
|
* without geometry has a null one
|
|
11
11
|
*/
|
|
12
|
-
export declare
|
|
12
|
+
export declare const parseKml: <P = Properties>(text: string) => FeatureCollection<P>;
|
package/dist/data/kml.js
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import { child, children, childText, descendants, parseXml } from "./xml.js";
|
|
2
|
+
/** Longitude, latitude and maybe more, all finite */
|
|
3
|
+
const isPosition = (values) => values.length >= 2 && values.every(Number.isFinite);
|
|
2
4
|
/** Positions of a `coordinates` element: `lon,lat[,alt]` tuples separated by spaces */
|
|
3
|
-
|
|
5
|
+
const positions = (element) => {
|
|
4
6
|
const out = [];
|
|
5
7
|
for (const tuple of (element?.text ?? '').trim().split(/\s+/)) {
|
|
6
8
|
const values = tuple.split(',').map(Number);
|
|
7
|
-
if (values
|
|
9
|
+
if (isPosition(values))
|
|
8
10
|
out.push(values);
|
|
9
11
|
}
|
|
10
12
|
return out;
|
|
11
|
-
}
|
|
13
|
+
};
|
|
12
14
|
/** The geometries of an element (a Placemark, a MultiGeometry), in order */
|
|
13
|
-
|
|
15
|
+
const geometries = (parent) => {
|
|
14
16
|
const out = [];
|
|
15
|
-
|
|
17
|
+
parent.children.forEach((g) => {
|
|
16
18
|
if (g.name === 'Point') {
|
|
17
19
|
const [p] = positions(child(g, 'coordinates'));
|
|
18
20
|
if (p)
|
|
@@ -34,46 +36,46 @@ function geometries(parent) {
|
|
|
34
36
|
// gx:Track: its gx:coord, `lon lat alt`
|
|
35
37
|
const line = children(g, 'coord')
|
|
36
38
|
.map((c) => c.text.trim().split(/\s+/).map(Number))
|
|
37
|
-
.filter(
|
|
39
|
+
.filter(isPosition);
|
|
38
40
|
if (line.length >= 2)
|
|
39
41
|
out.push({ type: 'LineString', coordinates: line });
|
|
40
42
|
}
|
|
41
43
|
else if (g.name === 'MultiGeometry' || g.name === 'MultiTrack') {
|
|
42
44
|
out.push(...geometries(g));
|
|
43
45
|
}
|
|
44
|
-
}
|
|
46
|
+
});
|
|
45
47
|
return out;
|
|
46
|
-
}
|
|
48
|
+
};
|
|
47
49
|
/** One geometry of several: a Multi… of one type, else a collection */
|
|
48
|
-
|
|
50
|
+
const merge = (list) => {
|
|
49
51
|
const [first] = list;
|
|
50
52
|
if (!first)
|
|
51
53
|
return null;
|
|
52
54
|
if (list.length === 1)
|
|
53
55
|
return first;
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (
|
|
62
|
-
return { type: 'MultiPolygon', coordinates:
|
|
56
|
+
const points = list.filter((g) => g.type === 'Point');
|
|
57
|
+
const lines = list.filter((g) => g.type === 'LineString');
|
|
58
|
+
const polygons = list.filter((g) => g.type === 'Polygon');
|
|
59
|
+
if (points.length === list.length)
|
|
60
|
+
return { type: 'MultiPoint', coordinates: points.map((g) => g.coordinates) };
|
|
61
|
+
if (lines.length === list.length)
|
|
62
|
+
return { type: 'MultiLineString', coordinates: lines.map((g) => g.coordinates) };
|
|
63
|
+
if (polygons.length === list.length) {
|
|
64
|
+
return { type: 'MultiPolygon', coordinates: polygons.map((g) => g.coordinates) };
|
|
63
65
|
}
|
|
64
66
|
return { type: 'GeometryCollection', geometries: list };
|
|
65
|
-
}
|
|
67
|
+
};
|
|
66
68
|
/** A KML color (`aabbggrr`, hexadecimal) as a CSS color and an opacity */
|
|
67
|
-
|
|
69
|
+
const color = (element) => {
|
|
68
70
|
const value = childText(element, 'color')?.replace(/^#/, '');
|
|
69
71
|
if (!value || !/^[\da-f]{8}$/i.test(value))
|
|
70
72
|
return undefined;
|
|
71
|
-
const [a, b, g, r] = [0, 2, 4, 6].map((i) => value.slice(i, i + 2));
|
|
73
|
+
const [a = '', b, g, r] = [0, 2, 4, 6].map((i) => value.slice(i, i + 2));
|
|
72
74
|
return [`#${r}${g}${b}`.toLowerCase(), Math.round((Number.parseInt(a, 16) / 255) * 1000) / 1000];
|
|
73
|
-
}
|
|
75
|
+
};
|
|
74
76
|
/** The properties of a style (simplestyle's names, as togeojson): stroke, stroke-opacity, stroke-width, fill,
|
|
75
77
|
* fill-opacity, marker-color */
|
|
76
|
-
|
|
78
|
+
const styleProperties = (style) => {
|
|
77
79
|
const out = {};
|
|
78
80
|
if (!style)
|
|
79
81
|
return out;
|
|
@@ -96,7 +98,7 @@ function styleProperties(style) {
|
|
|
96
98
|
if (icon)
|
|
97
99
|
out['marker-color'] = icon[0];
|
|
98
100
|
return out;
|
|
99
|
-
}
|
|
101
|
+
};
|
|
100
102
|
/**
|
|
101
103
|
* The placemarks of a KML document as GeoJSON features: their points, lines (and gx:Track), polygons (with their
|
|
102
104
|
* holes) and MultiGeometry (a Multi… of one type, else a GeometryCollection); their `name`, `description`, extended
|
|
@@ -104,19 +106,20 @@ function styleProperties(style) {
|
|
|
104
106
|
* `StyleMap`) as `stroke`, `stroke-opacity`, `stroke-width`, `fill`, `fill-opacity`, `marker-color`. A placemark
|
|
105
107
|
* without geometry has a null one
|
|
106
108
|
*/
|
|
107
|
-
export
|
|
109
|
+
export const parseKml = (text) => {
|
|
108
110
|
const root = parseXml(text);
|
|
109
111
|
const styles = new Map();
|
|
110
|
-
|
|
112
|
+
descendants(root, 'Style').forEach((s) => {
|
|
111
113
|
if (s.attributes.id)
|
|
112
114
|
styles.set(s.attributes.id, s);
|
|
115
|
+
});
|
|
113
116
|
const maps = new Map();
|
|
114
|
-
|
|
117
|
+
descendants(root, 'StyleMap').forEach((m) => {
|
|
115
118
|
const normal = children(m, 'Pair').find((p) => childText(p, 'key') === 'normal');
|
|
116
119
|
const url = childText(normal, 'styleUrl');
|
|
117
120
|
if (m.attributes.id && url)
|
|
118
121
|
maps.set(m.attributes.id, url);
|
|
119
|
-
}
|
|
122
|
+
});
|
|
120
123
|
/** The style of a `styleUrl` in this document (`#id`, through a StyleMap) */
|
|
121
124
|
const shared = (url, depth = 0) => {
|
|
122
125
|
const id = url?.slice(url.indexOf('#') + 1);
|
|
@@ -127,25 +130,25 @@ export function parseKml(text) {
|
|
|
127
130
|
const features = descendants(root, 'Placemark').map((placemark) => {
|
|
128
131
|
const properties = { ...styleProperties(shared(childText(placemark, 'styleUrl'))) };
|
|
129
132
|
Object.assign(properties, styleProperties(child(placemark, 'Style')));
|
|
130
|
-
|
|
133
|
+
['name', 'description', 'address', 'styleUrl'].forEach((key) => {
|
|
131
134
|
const value = childText(placemark, key);
|
|
132
135
|
if (value !== undefined)
|
|
133
136
|
properties[key] = value;
|
|
134
|
-
}
|
|
137
|
+
});
|
|
135
138
|
const time = childText(child(placemark, 'TimeStamp'), 'when');
|
|
136
139
|
if (time !== undefined)
|
|
137
140
|
properties.time = time;
|
|
138
141
|
const extended = child(placemark, 'ExtendedData');
|
|
139
|
-
|
|
142
|
+
children(extended, 'Data').forEach((data) => {
|
|
140
143
|
if (data.attributes.name)
|
|
141
144
|
properties[data.attributes.name] = childText(data, 'value') ?? '';
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
145
|
+
});
|
|
146
|
+
children(extended, 'SchemaData')
|
|
147
|
+
.flatMap((schema) => children(schema, 'SimpleData'))
|
|
148
|
+
.forEach((data) => {
|
|
149
|
+
if (data.attributes.name)
|
|
150
|
+
properties[data.attributes.name] = data.text.trim();
|
|
151
|
+
});
|
|
149
152
|
const id = placemark.attributes.id;
|
|
150
153
|
return {
|
|
151
154
|
type: 'Feature',
|
|
@@ -155,5 +158,5 @@ export function parseKml(text) {
|
|
|
155
158
|
};
|
|
156
159
|
});
|
|
157
160
|
return { type: 'FeatureCollection', features };
|
|
158
|
-
}
|
|
161
|
+
};
|
|
159
162
|
//# sourceMappingURL=kml.js.map
|
package/dist/data/kml.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kml.js","sourceRoot":"","sources":["../../src/data/kml.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * KML to GeoJSON, for the feature layers: `map.addLines({ data: parseKml(await (await fetch(url)).text()) })`.\n */\nimport type { Feature, FeatureCollection, Geometry, Position, Properties } from '../layers/features.ts';\nimport { child, children, childText, descendants, parseXml, type XmlElement } from './xml.ts';\n\n/** Positions of a `coordinates` element: `lon,lat[,alt]` tuples separated by spaces */\nfunction positions(element: XmlElement | undefined): Position[] {\n const out: Position[] = [];\n for (const tuple of (element?.text ?? '').trim().split(/\\s+/)) {\n const values = tuple.split(',').map(Number);\n if (values.length >= 2 && values.every(Number.isFinite)) out.push(values as Position);\n }\n return out;\n}\n\n/** The geometries of an element (a Placemark, a MultiGeometry), in order */\nfunction geometries(parent: XmlElement): Geometry[] {\n const out: Geometry[] = [];\n for (const g of parent.children) {\n if (g.name === 'Point') {\n const [p] = positions(child(g, 'coordinates'));\n if (p) out.push({ type: 'Point', coordinates: p });\n } else if (g.name === 'LineString' || g.name === 'LinearRing') {\n const line = positions(child(g, 'coordinates'));\n if (line.length >= 2) out.push({ type: 'LineString', coordinates: line });\n } else if (g.name === 'Polygon') {\n const ring = (b: XmlElement) => positions(child(child(b, 'LinearRing'), 'coordinates'));\n const outer = child(g, 'outerBoundaryIs');\n const rings = [...(outer ? [ring(outer)] : []), ...children(g, 'innerBoundaryIs').map(ring)];\n if ((rings[0]?.length ?? 0) >= 4) out.push({ type: 'Polygon', coordinates: rings.filter((r) => r.length >= 4) });\n } else if (g.name === 'Track') {\n // gx:Track: its gx:coord, `lon lat alt`\n const line = children(g, 'coord')\n .map((c) => c.text.trim().split(/\\s+/).map(Number))\n .filter((p) => p.length >= 2 && p.every(Number.isFinite)) as Position[];\n if (line.length >= 2) out.push({ type: 'LineString', coordinates: line });\n } else if (g.name === 'MultiGeometry' || g.name === 'MultiTrack') {\n out.push(...geometries(g));\n }\n }\n return out;\n}\n\n/** One geometry of several: a Multi… of one type, else a collection */\nfunction merge(list: Geometry[]): Geometry | null {\n const [first] = list;\n if (!first) return null;\n if (list.length === 1) return first;\n const same = list.every((g) => g.type === first.type);\n if (same && first.type === 'Point') {\n return { type: 'MultiPoint', coordinates: list.map((g) => (g as { coordinates: Position }).coordinates) };\n }\n if (same && first.type === 'LineString') {\n return { type: 'MultiLineString', coordinates: list.map((g) => (g as { coordinates: Position[] }).coordinates) };\n }\n if (same && first.type === 'Polygon') {\n return { type: 'MultiPolygon', coordinates: list.map((g) => (g as { coordinates: Position[][] }).coordinates) };\n }\n return { type: 'GeometryCollection', geometries: list };\n}\n\n/** A KML color (`aabbggrr`, hexadecimal) as a CSS color and an opacity */\nfunction color(element: XmlElement | undefined): [css: string, opacity: number] | undefined {\n const value = childText(element, 'color')?.replace(/^#/, '');\n if (!value || !/^[\\da-f]{8}$/i.test(value)) return undefined;\n const [a, b, g, r] = [0, 2, 4, 6].map((i) => value.slice(i, i + 2));\n return [`#${r}${g}${b}`.toLowerCase(), Math.round((Number.parseInt(a as string, 16) / 255) * 1000) / 1000];\n}\n\n/** The properties of a style (simplestyle's names, as togeojson): stroke, stroke-opacity, stroke-width, fill,\n * fill-opacity, marker-color */\nfunction styleProperties(style: XmlElement | undefined): Properties {\n const out: Properties = {};\n if (!style) return out;\n const line = child(style, 'LineStyle');\n const stroke = color(line);\n if (stroke) [out.stroke, out['stroke-opacity']] = stroke;\n const width = Number(childText(line, 'width'));\n if (childText(line, 'width') !== undefined && Number.isFinite(width)) out['stroke-width'] = width;\n const poly = child(style, 'PolyStyle');\n const fill = color(poly);\n if (fill) [out.fill, out['fill-opacity']] = fill;\n if (childText(poly, 'fill') === '0') out['fill-opacity'] = 0;\n if (childText(poly, 'outline') === '0') out['stroke-opacity'] = 0;\n const icon = color(child(style, 'IconStyle'));\n if (icon) out['marker-color'] = icon[0];\n return out;\n}\n\n/**\n * The placemarks of a KML document as GeoJSON features: their points, lines (and gx:Track), polygons (with their\n * holes) and MultiGeometry (a Multi… of one type, else a GeometryCollection); their `name`, `description`, extended\n * data (`Data`, `SimpleData`) as properties, and the colors of their style (inline, or shared through `styleUrl` and\n * `StyleMap`) as `stroke`, `stroke-opacity`, `stroke-width`, `fill`, `fill-opacity`, `marker-color`. A placemark\n * without geometry has a null one\n */\nexport function parseKml<P = Properties>(text: string): FeatureCollection<P> {\n const root = parseXml(text);\n const styles = new Map<string, XmlElement>();\n for (const s of descendants(root, 'Style')) if (s.attributes.id) styles.set(s.attributes.id, s);\n const maps = new Map<string, string>();\n for (const m of descendants(root, 'StyleMap')) {\n const normal = children(m, 'Pair').find((p) => childText(p, 'key') === 'normal');\n const url = childText(normal, 'styleUrl');\n if (m.attributes.id && url) maps.set(m.attributes.id, url);\n }\n /** The style of a `styleUrl` in this document (`#id`, through a StyleMap) */\n const shared = (url: string | undefined, depth = 0): XmlElement | undefined => {\n const id = url?.slice(url.indexOf('#') + 1);\n if (id === undefined || depth > 4) return undefined;\n return styles.get(id) ?? shared(maps.get(id), depth + 1);\n };\n const features = descendants(root, 'Placemark').map((placemark): Feature<P> => {\n const properties: Properties = { ...styleProperties(shared(childText(placemark, 'styleUrl'))) };\n Object.assign(properties, styleProperties(child(placemark, 'Style')));\n for (const key of ['name', 'description', 'address', 'styleUrl']) {\n const value = childText(placemark, key);\n if (value !== undefined) properties[key] = value;\n }\n const time = childText(child(placemark, 'TimeStamp'), 'when');\n if (time !== undefined) properties.time = time;\n const extended = child(placemark, 'ExtendedData');\n for (const data of children(extended, 'Data')) {\n if (data.attributes.name) properties[data.attributes.name] = childText(data, 'value') ?? '';\n }\n for (const schema of children(extended, 'SchemaData')) {\n for (const data of children(schema, 'SimpleData')) {\n if (data.attributes.name) properties[data.attributes.name] = data.text.trim();\n }\n }\n const id = placemark.attributes.id;\n return {\n type: 'Feature',\n geometry: merge(geometries(placemark)),\n properties: properties as P,\n ...(id === undefined ? {} : { id }),\n };\n });\n return { type: 'FeatureCollection', features };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"kml.js","sourceRoot":"","sources":["../../src/data/kml.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * KML to GeoJSON, for the feature layers: `map.addLines({ data: parseKml(await (await fetch(url)).text()) })`.\n */\nimport type { Feature, FeatureCollection, Geometry, Position, Properties } from '../layers/features.ts';\nimport { child, children, childText, descendants, parseXml, type XmlElement } from './xml.ts';\n\n/** Longitude, latitude and maybe more, all finite */\nconst isPosition = (values: number[]): values is Position => values.length >= 2 && values.every(Number.isFinite);\n\n/** Positions of a `coordinates` element: `lon,lat[,alt]` tuples separated by spaces */\nconst positions = (element: XmlElement | undefined): Position[] => {\n const out: Position[] = [];\n\n for (const tuple of (element?.text ?? '').trim().split(/\\s+/)) {\n const values = tuple.split(',').map(Number);\n\n if (isPosition(values)) out.push(values);\n }\n\n return out;\n};\n\n/** The geometries of an element (a Placemark, a MultiGeometry), in order */\nconst geometries = (parent: XmlElement): Geometry[] => {\n const out: Geometry[] = [];\n\n parent.children.forEach((g) => {\n if (g.name === 'Point') {\n const [p] = positions(child(g, 'coordinates'));\n\n if (p) out.push({ type: 'Point', coordinates: p });\n } else if (g.name === 'LineString' || g.name === 'LinearRing') {\n const line = positions(child(g, 'coordinates'));\n\n if (line.length >= 2) out.push({ type: 'LineString', coordinates: line });\n } else if (g.name === 'Polygon') {\n const ring = (b: XmlElement) => positions(child(child(b, 'LinearRing'), 'coordinates'));\n const outer = child(g, 'outerBoundaryIs');\n const rings = [...(outer ? [ring(outer)] : []), ...children(g, 'innerBoundaryIs').map(ring)];\n\n if ((rings[0]?.length ?? 0) >= 4) out.push({ type: 'Polygon', coordinates: rings.filter((r) => r.length >= 4) });\n } else if (g.name === 'Track') {\n // gx:Track: its gx:coord, `lon lat alt`\n const line = children(g, 'coord')\n .map((c) => c.text.trim().split(/\\s+/).map(Number))\n .filter(isPosition);\n\n if (line.length >= 2) out.push({ type: 'LineString', coordinates: line });\n } else if (g.name === 'MultiGeometry' || g.name === 'MultiTrack') {\n out.push(...geometries(g));\n }\n });\n\n return out;\n};\n\n/** One geometry of several: a Multi… of one type, else a collection */\nconst merge = (list: Geometry[]): Geometry | null => {\n const [first] = list;\n\n if (!first) return null;\n if (list.length === 1) return first;\n\n const points = list.filter((g) => g.type === 'Point');\n const lines = list.filter((g) => g.type === 'LineString');\n const polygons = list.filter((g) => g.type === 'Polygon');\n\n if (points.length === list.length) return { type: 'MultiPoint', coordinates: points.map((g) => g.coordinates) };\n if (lines.length === list.length) return { type: 'MultiLineString', coordinates: lines.map((g) => g.coordinates) };\n if (polygons.length === list.length) {\n return { type: 'MultiPolygon', coordinates: polygons.map((g) => g.coordinates) };\n }\n\n return { type: 'GeometryCollection', geometries: list };\n};\n\n/** A KML color (`aabbggrr`, hexadecimal) as a CSS color and an opacity */\nconst color = (element: XmlElement | undefined): [css: string, opacity: number] | undefined => {\n const value = childText(element, 'color')?.replace(/^#/, '');\n\n if (!value || !/^[\\da-f]{8}$/i.test(value)) return undefined;\n\n const [a = '', b, g, r] = [0, 2, 4, 6].map((i) => value.slice(i, i + 2));\n\n return [`#${r}${g}${b}`.toLowerCase(), Math.round((Number.parseInt(a, 16) / 255) * 1000) / 1000];\n};\n\n/** The properties of a style (simplestyle's names, as togeojson): stroke, stroke-opacity, stroke-width, fill,\n * fill-opacity, marker-color */\nconst styleProperties = (style: XmlElement | undefined): Properties => {\n const out: Properties = {};\n\n if (!style) return out;\n\n const line = child(style, 'LineStyle');\n const stroke = color(line);\n\n if (stroke) [out.stroke, out['stroke-opacity']] = stroke;\n\n const width = Number(childText(line, 'width'));\n\n if (childText(line, 'width') !== undefined && Number.isFinite(width)) out['stroke-width'] = width;\n\n const poly = child(style, 'PolyStyle');\n const fill = color(poly);\n\n if (fill) [out.fill, out['fill-opacity']] = fill;\n if (childText(poly, 'fill') === '0') out['fill-opacity'] = 0;\n if (childText(poly, 'outline') === '0') out['stroke-opacity'] = 0;\n\n const icon = color(child(style, 'IconStyle'));\n\n if (icon) out['marker-color'] = icon[0];\n\n return out;\n};\n\n/**\n * The placemarks of a KML document as GeoJSON features: their points, lines (and gx:Track), polygons (with their\n * holes) and MultiGeometry (a Multi… of one type, else a GeometryCollection); their `name`, `description`, extended\n * data (`Data`, `SimpleData`) as properties, and the colors of their style (inline, or shared through `styleUrl` and\n * `StyleMap`) as `stroke`, `stroke-opacity`, `stroke-width`, `fill`, `fill-opacity`, `marker-color`. A placemark\n * without geometry has a null one\n */\nexport const parseKml = <P = Properties>(text: string): FeatureCollection<P> => {\n const root = parseXml(text);\n const styles = new Map<string, XmlElement>();\n\n descendants(root, 'Style').forEach((s) => {\n if (s.attributes.id) styles.set(s.attributes.id, s);\n });\n\n const maps = new Map<string, string>();\n\n descendants(root, 'StyleMap').forEach((m) => {\n const normal = children(m, 'Pair').find((p) => childText(p, 'key') === 'normal');\n const url = childText(normal, 'styleUrl');\n\n if (m.attributes.id && url) maps.set(m.attributes.id, url);\n });\n\n /** The style of a `styleUrl` in this document (`#id`, through a StyleMap) */\n const shared = (url: string | undefined, depth = 0): XmlElement | undefined => {\n const id = url?.slice(url.indexOf('#') + 1);\n\n if (id === undefined || depth > 4) return undefined;\n\n return styles.get(id) ?? shared(maps.get(id), depth + 1);\n };\n const features = descendants(root, 'Placemark').map((placemark): Feature<P> => {\n const properties: Properties = { ...styleProperties(shared(childText(placemark, 'styleUrl'))) };\n\n Object.assign(properties, styleProperties(child(placemark, 'Style')));\n ['name', 'description', 'address', 'styleUrl'].forEach((key) => {\n const value = childText(placemark, key);\n\n if (value !== undefined) properties[key] = value;\n });\n\n const time = childText(child(placemark, 'TimeStamp'), 'when');\n\n if (time !== undefined) properties.time = time;\n\n const extended = child(placemark, 'ExtendedData');\n\n children(extended, 'Data').forEach((data) => {\n if (data.attributes.name) properties[data.attributes.name] = childText(data, 'value') ?? '';\n });\n children(extended, 'SchemaData')\n .flatMap((schema) => children(schema, 'SimpleData'))\n .forEach((data) => {\n if (data.attributes.name) properties[data.attributes.name] = data.text.trim();\n });\n\n const id = placemark.attributes.id;\n\n return {\n type: 'Feature',\n geometry: merge(geometries(placemark)),\n properties: properties as P,\n ...(id === undefined ? {} : { id }),\n };\n });\n\n return { type: 'FeatureCollection', features };\n};\n"]}
|
package/dist/data/topojson.d.ts
CHANGED
|
@@ -26,4 +26,4 @@ export interface Topology {
|
|
|
26
26
|
* The features of object `name` of a TopoJSON topology (default its first object): a GeometryCollection gives one
|
|
27
27
|
* feature per geometry, another geometry one feature; arcs are stitched and dequantized, ids and properties kept
|
|
28
28
|
*/
|
|
29
|
-
export declare
|
|
29
|
+
export declare const parseTopoJson: <P = Properties>(topology: Topology, name?: string) => FeatureCollection<P>;
|
package/dist/data/topojson.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
import { isNumbers } from "../util/guards.js";
|
|
2
|
+
/** The members of a geometry, checked: the topology is JSON from elsewhere */
|
|
3
|
+
const isLists = (value) => Array.isArray(value) && value.every(isNumbers);
|
|
4
|
+
const isListsOfLists = (value) => Array.isArray(value) && value.every(isLists);
|
|
1
5
|
/**
|
|
2
6
|
* The features of object `name` of a TopoJSON topology (default its first object): a GeometryCollection gives one
|
|
3
7
|
* feature per geometry, another geometry one feature; arcs are stitched and dequantized, ids and properties kept
|
|
4
8
|
*/
|
|
5
|
-
export
|
|
9
|
+
export const parseTopoJson = (topology, name) => {
|
|
6
10
|
const object = name === undefined ? Object.values(topology.objects)[0] : topology.objects[name];
|
|
7
11
|
if (!object)
|
|
8
12
|
throw new Error(`isard: no TopoJSON object ${name ?? ''}`);
|
|
@@ -24,27 +28,28 @@ export function parseTopoJson(topology, name) {
|
|
|
24
28
|
/** A line from arcs, each after the first without its first point (the last of the one before) */
|
|
25
29
|
const stitch = (indices) => {
|
|
26
30
|
const out = [];
|
|
27
|
-
|
|
31
|
+
indices.forEach((i) => {
|
|
28
32
|
const arc = arcs[i < 0 ? ~i : i] ?? [];
|
|
29
33
|
const points = i < 0 ? [...arc].reverse() : arc;
|
|
30
34
|
out.push(...(out.length > 0 ? points.slice(1) : points));
|
|
31
|
-
}
|
|
35
|
+
});
|
|
32
36
|
return out;
|
|
33
37
|
};
|
|
34
38
|
const geometry = (g) => {
|
|
39
|
+
const { coordinates, arcs } = g;
|
|
35
40
|
switch (g.type) {
|
|
36
41
|
case 'Point':
|
|
37
|
-
return { type: 'Point', coordinates: position(
|
|
42
|
+
return isNumbers(coordinates) ? { type: 'Point', coordinates: position(coordinates) } : null;
|
|
38
43
|
case 'MultiPoint':
|
|
39
|
-
return { type: 'MultiPoint', coordinates:
|
|
44
|
+
return isLists(coordinates) ? { type: 'MultiPoint', coordinates: coordinates.map(position) } : null;
|
|
40
45
|
case 'LineString':
|
|
41
|
-
return { type: 'LineString', coordinates: stitch(
|
|
46
|
+
return isNumbers(arcs) ? { type: 'LineString', coordinates: stitch(arcs) } : null;
|
|
42
47
|
case 'MultiLineString':
|
|
43
|
-
return { type: 'MultiLineString', coordinates:
|
|
48
|
+
return isLists(arcs) ? { type: 'MultiLineString', coordinates: arcs.map(stitch) } : null;
|
|
44
49
|
case 'Polygon':
|
|
45
|
-
return { type: 'Polygon', coordinates:
|
|
50
|
+
return isLists(arcs) ? { type: 'Polygon', coordinates: arcs.map(stitch) } : null;
|
|
46
51
|
case 'MultiPolygon':
|
|
47
|
-
return { type: 'MultiPolygon', coordinates:
|
|
52
|
+
return isListsOfLists(arcs) ? { type: 'MultiPolygon', coordinates: arcs.map((p) => p.map(stitch)) } : null;
|
|
48
53
|
case 'GeometryCollection':
|
|
49
54
|
return {
|
|
50
55
|
type: 'GeometryCollection',
|
|
@@ -62,5 +67,5 @@ export function parseTopoJson(topology, name) {
|
|
|
62
67
|
});
|
|
63
68
|
const features = object.type === 'GeometryCollection' ? (object.geometries ?? []).map(feature) : [feature(object)];
|
|
64
69
|
return { type: 'FeatureCollection', features };
|
|
65
|
-
}
|
|
70
|
+
};
|
|
66
71
|
//# sourceMappingURL=topojson.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"topojson.js","sourceRoot":"","sources":["../../src/data/topojson.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"topojson.js","sourceRoot":"","sources":["../../src/data/topojson.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * TopoJSON to GeoJSON, for the feature layers: `map.addFills({ data: parseTopoJson(topology, 'counties') })`.\n */\nimport type { Feature, FeatureCollection, Geometry, Position, Properties } from '../layers/features.ts';\nimport { isNumbers } from '../util/guards.ts';\n\n/** A TopoJSON geometry object (arcs by index, `~i` for arc i reversed; positions quantized with a transform) */\nexport interface TopoGeometry {\n type:\n | 'Point'\n | 'MultiPoint'\n | 'LineString'\n | 'MultiLineString'\n | 'Polygon'\n | 'MultiPolygon'\n | 'GeometryCollection'\n | null;\n id?: string | number;\n properties?: Properties;\n coordinates?: number[] | number[][];\n arcs?: number[] | number[][] | number[][][];\n geometries?: TopoGeometry[];\n}\n\n/** A TopoJSON topology */\nexport interface Topology {\n type: 'Topology';\n /** Quantized positions: x × scale + translate (arcs delta-encoded) */\n transform?: { scale: [number, number]; translate: [number, number] };\n arcs: number[][][];\n objects: Record<string, TopoGeometry>;\n}\n\n/** The members of a geometry, checked: the topology is JSON from elsewhere */\nconst isLists = (value: unknown): value is number[][] => Array.isArray(value) && value.every(isNumbers);\nconst isListsOfLists = (value: unknown): value is number[][][] => Array.isArray(value) && value.every(isLists);\n\n/**\n * The features of object `name` of a TopoJSON topology (default its first object): a GeometryCollection gives one\n * feature per geometry, another geometry one feature; arcs are stitched and dequantized, ids and properties kept\n */\nexport const parseTopoJson = <P = Properties>(topology: Topology, name?: string): FeatureCollection<P> => {\n const object = name === undefined ? Object.values(topology.objects)[0] : topology.objects[name];\n\n if (!object) throw new Error(`isard: no TopoJSON object ${name ?? ''}`);\n\n const { scale = [1, 1], translate = [0, 0] } = topology.transform ?? {};\n const quantized = topology.transform !== undefined;\n const at = (p: number[]): Position => [p[0] ?? 0, p[1] ?? 0, ...p.slice(2)];\n // The arcs decoded once\n const arcs = topology.arcs.map((arc) => {\n let [x, y] = [0, 0];\n\n return arc.map((p): Position => {\n if (!quantized) return at(p);\n x += p[0] ?? 0;\n y += p[1] ?? 0;\n\n return [x * scale[0] + translate[0], y * scale[1] + translate[1], ...p.slice(2)];\n });\n });\n const position = (p: number[]): Position =>\n quantized ? [(p[0] ?? 0) * scale[0] + translate[0], (p[1] ?? 0) * scale[1] + translate[1], ...p.slice(2)] : at(p);\n /** A line from arcs, each after the first without its first point (the last of the one before) */\n const stitch = (indices: number[]): Position[] => {\n const out: Position[] = [];\n\n indices.forEach((i) => {\n const arc = arcs[i < 0 ? ~i : i] ?? [];\n const points = i < 0 ? [...arc].reverse() : arc;\n\n out.push(...(out.length > 0 ? points.slice(1) : points));\n });\n\n return out;\n };\n const geometry = (g: TopoGeometry): Geometry | null => {\n const { coordinates, arcs } = g;\n\n switch (g.type) {\n case 'Point':\n return isNumbers(coordinates) ? { type: 'Point', coordinates: position(coordinates) } : null;\n case 'MultiPoint':\n return isLists(coordinates) ? { type: 'MultiPoint', coordinates: coordinates.map(position) } : null;\n case 'LineString':\n return isNumbers(arcs) ? { type: 'LineString', coordinates: stitch(arcs) } : null;\n case 'MultiLineString':\n return isLists(arcs) ? { type: 'MultiLineString', coordinates: arcs.map(stitch) } : null;\n case 'Polygon':\n return isLists(arcs) ? { type: 'Polygon', coordinates: arcs.map(stitch) } : null;\n case 'MultiPolygon':\n return isListsOfLists(arcs) ? { type: 'MultiPolygon', coordinates: arcs.map((p) => p.map(stitch)) } : null;\n case 'GeometryCollection':\n return {\n type: 'GeometryCollection',\n geometries: (g.geometries ?? []).map(geometry).filter((c) => c !== null),\n };\n default:\n return null;\n }\n };\n const feature = (g: TopoGeometry): Feature<P> => ({\n type: 'Feature',\n geometry: geometry(g),\n properties: (g.properties ?? {}) as P,\n ...(g.id === undefined ? {} : { id: g.id }),\n });\n const features = object.type === 'GeometryCollection' ? (object.geometries ?? []).map(feature) : [feature(object)];\n\n return { type: 'FeatureCollection', features };\n};\n"]}
|
package/dist/data/xml.d.ts
CHANGED
|
@@ -15,12 +15,12 @@ export interface XmlElement {
|
|
|
15
15
|
text: string;
|
|
16
16
|
}
|
|
17
17
|
/** The document's root element; throws if there is none */
|
|
18
|
-
export declare
|
|
18
|
+
export declare const parseXml: (source: string) => XmlElement;
|
|
19
19
|
/** The first child element of a name */
|
|
20
|
-
export declare
|
|
20
|
+
export declare const child: (element: XmlElement | undefined, name: string) => XmlElement | undefined;
|
|
21
21
|
/** The child elements of a name */
|
|
22
|
-
export declare
|
|
22
|
+
export declare const children: (element: XmlElement | undefined, name: string) => XmlElement[];
|
|
23
23
|
/** The trimmed text of the first child of a name; undefined without one */
|
|
24
|
-
export declare
|
|
24
|
+
export declare const childText: (element: XmlElement | undefined, name: string) => string | undefined;
|
|
25
25
|
/** Every element of a name under an element, in document order (not inside a match) */
|
|
26
|
-
export declare
|
|
26
|
+
export declare const descendants: (element: XmlElement, name: string, out?: XmlElement[]) => XmlElement[];
|
package/dist/data/xml.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
const ENTITIES = { lt: '<', gt: '>', amp: '&', quot: '"', apos: "'" };
|
|
9
9
|
/** Text with its entities decoded (unknown ones kept as they are) */
|
|
10
|
-
|
|
10
|
+
const decode = (text) => {
|
|
11
11
|
if (!text.includes('&'))
|
|
12
12
|
return text;
|
|
13
13
|
return text.replace(/&(#x[\da-f]+|#\d+|\w+);/gi, (whole, entity) => {
|
|
@@ -17,15 +17,15 @@ function decode(text) {
|
|
|
17
17
|
}
|
|
18
18
|
return ENTITIES[entity] ?? whole;
|
|
19
19
|
});
|
|
20
|
-
}
|
|
20
|
+
};
|
|
21
21
|
const local = (name) => name.slice(name.indexOf(':') + 1);
|
|
22
22
|
/** A start tag at the reader's position: its name, its attributes (quoted values may hold '>'), whether it closes */
|
|
23
23
|
const START = /<([^\s/>]+)((?:\s+[^\s=/>]+\s*=\s*(?:"[^"]*"|'[^']*'))*)\s*(\/?)>/y;
|
|
24
24
|
/** The document's root element; throws if there is none */
|
|
25
|
-
export
|
|
25
|
+
export const parseXml = (source) => {
|
|
26
26
|
const root = { name: '#document', attributes: {}, children: [], text: '' };
|
|
27
27
|
const stack = [root];
|
|
28
|
-
const top = () => stack
|
|
28
|
+
const top = () => stack.at(-1) ?? root;
|
|
29
29
|
let i = 0;
|
|
30
30
|
while (i < source.length) {
|
|
31
31
|
const lt = source.indexOf('<', i);
|
|
@@ -69,12 +69,13 @@ export function parseXml(source) {
|
|
|
69
69
|
i = lt + 1;
|
|
70
70
|
continue;
|
|
71
71
|
}
|
|
72
|
-
const
|
|
73
|
-
|
|
72
|
+
const [, name = '', attributes = '', closes] = tag;
|
|
73
|
+
const element = { name: local(name), attributes: {}, children: [], text: '' };
|
|
74
|
+
for (const [, key = '', double, single] of attributes.matchAll(/([^\s=]+)\s*=\s*(?:"([^"]*)"|'([^']*)')/g)) {
|
|
74
75
|
element.attributes[local(key)] = decode(double ?? single ?? '');
|
|
75
76
|
}
|
|
76
77
|
top().children.push(element);
|
|
77
|
-
if (!
|
|
78
|
+
if (!closes)
|
|
78
79
|
stack.push(element);
|
|
79
80
|
i = START.lastIndex;
|
|
80
81
|
}
|
|
@@ -83,27 +84,27 @@ export function parseXml(source) {
|
|
|
83
84
|
if (!first)
|
|
84
85
|
throw new Error('isard: no XML element');
|
|
85
86
|
return first;
|
|
86
|
-
}
|
|
87
|
+
};
|
|
87
88
|
/** The first child element of a name */
|
|
88
|
-
export
|
|
89
|
+
export const child = (element, name) => {
|
|
89
90
|
return element?.children.find((c) => c.name === name);
|
|
90
|
-
}
|
|
91
|
+
};
|
|
91
92
|
/** The child elements of a name */
|
|
92
|
-
export
|
|
93
|
+
export const children = (element, name) => {
|
|
93
94
|
return element?.children.filter((c) => c.name === name) ?? [];
|
|
94
|
-
}
|
|
95
|
+
};
|
|
95
96
|
/** The trimmed text of the first child of a name; undefined without one */
|
|
96
|
-
export
|
|
97
|
+
export const childText = (element, name) => {
|
|
97
98
|
return child(element, name)?.text.trim();
|
|
98
|
-
}
|
|
99
|
+
};
|
|
99
100
|
/** Every element of a name under an element, in document order (not inside a match) */
|
|
100
|
-
export
|
|
101
|
-
|
|
101
|
+
export const descendants = (element, name, out = []) => {
|
|
102
|
+
element.children.forEach((c) => {
|
|
102
103
|
if (c.name === name)
|
|
103
104
|
out.push(c);
|
|
104
105
|
else
|
|
105
106
|
descendants(c, name, out);
|
|
106
|
-
}
|
|
107
|
+
});
|
|
107
108
|
return out;
|
|
108
|
-
}
|
|
109
|
+
};
|
|
109
110
|
//# sourceMappingURL=xml.js.map
|