isard 0.3.0 → 0.5.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 +68 -0
- package/README.md +11 -3
- package/dist/basemap.worker.d.ts +10 -3
- package/dist/basemap.worker.js +2 -2
- package/dist/basemap.worker.js.map +4 -4
- package/dist/decoder.worker.js +4 -4
- package/dist/decoder.worker.js.map +7 -6
- package/dist/decoders.d.ts +3 -2
- package/dist/decoders.js +28 -5
- package/dist/decoders.js.map +1 -1
- package/dist/engine-loader.d.ts +8 -4
- package/dist/engine-loader.js +10 -3
- package/dist/engine-loader.js.map +1 -1
- package/dist/formats.d.ts +11 -0
- package/dist/formats.js +12 -0
- package/dist/formats.js.map +1 -0
- package/dist/glyphs.d.ts +3 -0
- package/dist/glyphs.js +12 -2
- package/dist/glyphs.js.map +1 -1
- package/dist/icons.d.ts +146 -0
- package/dist/icons.js +333 -0
- package/dist/icons.js.map +1 -0
- package/dist/index.d.ts +8 -5
- package/dist/index.js +2 -1
- 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.d.ts +88 -1
- package/dist/layers.js +165 -4
- package/dist/layers.js.map +1 -1
- package/dist/loader.d.ts +9 -3
- package/dist/loader.js +22 -3
- package/dist/loader.js.map +1 -1
- package/dist/map.d.ts +37 -3
- package/dist/map.js +76 -10
- package/dist/map.js.map +1 -1
- package/dist/pointclouds.d.ts +98 -0
- package/dist/pointclouds.js +232 -0
- package/dist/pointclouds.js.map +1 -0
- package/dist/projections.d.ts +13 -0
- package/dist/projections.js +13 -0
- package/dist/projections.js.map +1 -0
- package/dist/protocol.d.ts +17 -0
- package/dist/protocol.js.map +1 -1
- package/dist/symbols.d.ts +42 -8
- package/dist/symbols.js +160 -35
- package/dist/symbols.js.map +1 -1
- package/dist/types.d.ts +8 -3
- package/dist/types.js.map +1 -1
- package/dist/vectorstyle.d.ts +32 -3
- package/dist/vectorstyle.js.map +1 -1
- package/dist/vectortiles.d.ts +10 -5
- package/dist/vectortiles.js +54 -29
- package/dist/vectortiles.js.map +1 -1
- package/dist/wasm/isard.d.ts +168 -11
- package/dist/wasm/isard.js +234 -9
- package/dist/wasm/isard_core.d.ts +28 -3
- package/dist/wasm/isard_core.js +77 -4
- package/dist/wasm/isard_points.d.ts +43 -0
- package/dist/wasm/isard_points.js +212 -0
- package/package.json +17 -1
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Point clouds: a COPC file (Cloud Optimized Point Cloud: LAZ 1.4 with an octree, read by HTTP range requests, as the
|
|
3
|
+
* IGN distributes LiDAR HD) or a 3D Tiles point cloud (`.pnts`, glTF points), drawn by the engine with 3D Tiles. The
|
|
4
|
+
* COPC file's CRS comes from its WKT (built-in CRSs, or registered ones: `registerCrs`) or the `crs` option; altitudes
|
|
5
|
+
* in NGF-IGN69 (Lambert-93, the CC zones) are raised by the RAF20 geoid height onto the ellipsoid of the relief and
|
|
6
|
+
* the 3D Tiles.
|
|
7
|
+
*/
|
|
8
|
+
import { epsgCode, getCrs } from "./crs.js";
|
|
9
|
+
import { parseColor, rampTexels } from "./features.js";
|
|
10
|
+
import { Layer } from "./layers.js";
|
|
11
|
+
/** The default classes: ASPRS LAS 1.4, then IGN's LiDAR HD (64 permanent structures, 65 artefacts, 66 virtual points,
|
|
12
|
+
* 67 miscellaneous buildings) */
|
|
13
|
+
export const CLASSIFICATIONS = {
|
|
14
|
+
0: { color: '#a6a6a6', visible: true },
|
|
15
|
+
1: { color: '#c8c8c8', visible: true },
|
|
16
|
+
2: { color: '#b08458', visible: true },
|
|
17
|
+
3: { color: '#9ccc65', visible: true },
|
|
18
|
+
4: { color: '#5aa83f', visible: true },
|
|
19
|
+
5: { color: '#2e7d32', visible: true },
|
|
20
|
+
6: { color: '#e57352', visible: true },
|
|
21
|
+
7: { color: '#ff00ff', visible: false },
|
|
22
|
+
8: { color: '#ff0000', visible: true },
|
|
23
|
+
9: { color: '#3d8fd6', visible: true },
|
|
24
|
+
10: { color: '#8e6bb0', visible: true },
|
|
25
|
+
11: { color: '#7a7a7a', visible: true },
|
|
26
|
+
12: { color: '#ffe680', visible: true },
|
|
27
|
+
13: { color: '#ffff00', visible: true },
|
|
28
|
+
14: { color: '#ffc800', visible: true },
|
|
29
|
+
15: { color: '#c89600', visible: true },
|
|
30
|
+
16: { color: '#ff9632', visible: true },
|
|
31
|
+
17: { color: '#b48cc8', visible: true },
|
|
32
|
+
18: { color: '#ff00ff', visible: false },
|
|
33
|
+
64: { color: '#8c6e5a', visible: true },
|
|
34
|
+
65: { color: '#ff00ff', visible: false },
|
|
35
|
+
66: { color: '#5a6ec8', visible: true },
|
|
36
|
+
67: { color: '#e6966e', visible: true },
|
|
37
|
+
};
|
|
38
|
+
/** The default ramp of the altitudes, low to high */
|
|
39
|
+
export const ELEVATION_RAMP = [
|
|
40
|
+
[0, '#2b83ba'],
|
|
41
|
+
[0.25, '#abdda4'],
|
|
42
|
+
[0.5, '#ffffbf'],
|
|
43
|
+
[0.75, '#fdae61'],
|
|
44
|
+
[1, '#d7191c'],
|
|
45
|
+
];
|
|
46
|
+
/** The colors of the 256 classes (RGBA, alpha 0 hides one) */
|
|
47
|
+
export function classPalette(overrides = {}) {
|
|
48
|
+
const out = new Uint8Array(256 * 4);
|
|
49
|
+
for (let code = 0; code < 256; code += 1) {
|
|
50
|
+
const base = CLASSIFICATIONS[code] ?? { color: '#c8c8c8', visible: true };
|
|
51
|
+
const own = overrides[code] ?? {};
|
|
52
|
+
const [r = 0, g = 0, b = 0] = parseColor(own.color ?? base.color);
|
|
53
|
+
out.set([r * 255, g * 255, b * 255, (own.visible ?? base.visible) ? 255 : 0], code * 4);
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
/** The section of a WKT opening with one of `keywords` (`PROJCS[…]`), from its keyword to its closing bracket */
|
|
58
|
+
function section(wkt, keywords) {
|
|
59
|
+
for (const keyword of keywords) {
|
|
60
|
+
const start = wkt.indexOf(`${keyword}[`);
|
|
61
|
+
if (start < 0)
|
|
62
|
+
continue;
|
|
63
|
+
let depth = 0;
|
|
64
|
+
for (let i = start + keyword.length; i < wkt.length; i += 1) {
|
|
65
|
+
if (wkt[i] === '[')
|
|
66
|
+
depth += 1;
|
|
67
|
+
else if (wkt[i] === ']' && --depth === 0)
|
|
68
|
+
return wkt.slice(start, i + 1);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
/** The EPSG code a WKT section ends with (its own `AUTHORITY`, or `ID` in WKT2), the last of its nested ones */
|
|
74
|
+
function lastCode(part) {
|
|
75
|
+
const codes = [...part.matchAll(/(?:AUTHORITY|ID)\[\s*"EPSG"\s*,\s*"?(\d+)"?\s*\]/g)];
|
|
76
|
+
const last = codes.at(-1)?.[1];
|
|
77
|
+
return last === undefined ? undefined : Number(last);
|
|
78
|
+
}
|
|
79
|
+
/** The factor of the last `UNIT` (`LENGTHUNIT` in WKT2) of a WKT section */
|
|
80
|
+
function lastUnit(part) {
|
|
81
|
+
const units = [...(part ?? '').matchAll(/(?:LENGTH)?UNIT\[\s*"[^"]*"\s*,\s*([\d.eE+-]+)/g)];
|
|
82
|
+
const factor = Number(units.at(-1)?.[1]);
|
|
83
|
+
return Number.isFinite(factor) && factor > 0 ? factor : undefined;
|
|
84
|
+
}
|
|
85
|
+
/** What a WKT says of a CRS: its EPSG code (projected first), the metres of a unit of z */
|
|
86
|
+
export function wktCrs(wkt) {
|
|
87
|
+
const projected = section(wkt, ['PROJCS', 'PROJCRS']);
|
|
88
|
+
const geographic = section(wkt, ['GEOGCS', 'GEOGCRS']);
|
|
89
|
+
let code = lastCode(projected ?? geographic ?? '');
|
|
90
|
+
if (code === undefined && /Lambert[- ]93/i.test(wkt))
|
|
91
|
+
code = 2154;
|
|
92
|
+
const vertical = section(wkt, ['VERT_CS', 'VERTCRS']);
|
|
93
|
+
const verticalScale = lastUnit(vertical ?? projected);
|
|
94
|
+
return { code, verticalScale };
|
|
95
|
+
}
|
|
96
|
+
/** Whether the altitudes of a CRS are NGF-IGN69 by default: Lambert-93 and the CC zones */
|
|
97
|
+
const FRENCH = (code) => code === 2154 || (code !== undefined && code >= 3942 && code <= 3950);
|
|
98
|
+
/** The CRS of a COPC file for the engine, from its WKT and the options */
|
|
99
|
+
export function pointCloudCrs(wkt, options) {
|
|
100
|
+
const parsed = wkt ? wktCrs(wkt) : { code: undefined, verticalScale: undefined };
|
|
101
|
+
let crs;
|
|
102
|
+
let code = parsed.code;
|
|
103
|
+
if (options.crs !== undefined) {
|
|
104
|
+
crs = getCrs(options.crs);
|
|
105
|
+
if (typeof options.crs === 'string')
|
|
106
|
+
code = epsgCode(options.crs) ?? code;
|
|
107
|
+
}
|
|
108
|
+
else if (code !== undefined) {
|
|
109
|
+
try {
|
|
110
|
+
crs = getCrs(`EPSG:${code}`);
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
throw new Error(`the CRS of the file, EPSG:${code}, is not built in: give it as \`crs\` (proj4('EPSG:${code}'))`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
throw new Error('the file names no CRS: give it as `crs`');
|
|
118
|
+
}
|
|
119
|
+
const inverse = (xy) => {
|
|
120
|
+
const out = new Float64Array(xy.length);
|
|
121
|
+
for (let i = 0; i + 1 < xy.length; i += 2) {
|
|
122
|
+
const [lon = Number.NaN, lat = Number.NaN] = crs.inverse([xy[i], xy[i + 1]]);
|
|
123
|
+
out[i] = lon;
|
|
124
|
+
out[i + 1] = lat;
|
|
125
|
+
}
|
|
126
|
+
return out;
|
|
127
|
+
};
|
|
128
|
+
return {
|
|
129
|
+
inverse,
|
|
130
|
+
geoid: options.geoid ?? (FRENCH(code) || /IGN69|NGF/.test(wkt ?? '')),
|
|
131
|
+
verticalScale: options.verticalScale ?? parsed.verticalScale ?? 1,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
/** The style numbers of the engine (`setPointCloudStyle`) */
|
|
135
|
+
function styleNumbers(s, rate) {
|
|
136
|
+
const colors = ['rgb', 'classification', 'elevation', 'intensity'];
|
|
137
|
+
let edl;
|
|
138
|
+
if (s.edl)
|
|
139
|
+
edl = s.edl === true ? {} : s.edl;
|
|
140
|
+
const [emin = Number.NaN, emax = Number.NaN] = s.elevationRange ?? [];
|
|
141
|
+
const [imin = Number.NaN, imax = Number.NaN] = s.intensityRange ?? [];
|
|
142
|
+
return Float64Array.of(s.colorBy ? colors.indexOf(s.colorBy) : -1, s.pointSize, s.maxPointSize, s.sizeMode === 'fixed' ? 0 : 1, s.shape === 'square' ? 0 : 1, edl ? (edl.strength ?? 1) : 0, edl?.radius ?? 1.4, emin, emax, imin, imax, s.maxScreenSpaceError, s.pointBudget, rate);
|
|
143
|
+
}
|
|
144
|
+
/** A point cloud (`GeoMap.addPointCloud`): COPC or 3D Tiles points; `pickFeature` gives a COPC point's attributes */
|
|
145
|
+
export class PointCloudLayer extends Layer {
|
|
146
|
+
url;
|
|
147
|
+
format;
|
|
148
|
+
style;
|
|
149
|
+
options;
|
|
150
|
+
/** @internal */
|
|
151
|
+
constructor(map, options) {
|
|
152
|
+
super(map);
|
|
153
|
+
// Against the page: the decoding workers fetch it, and a relative URL would be theirs
|
|
154
|
+
const base = typeof document === 'undefined' ? undefined : document.baseURI;
|
|
155
|
+
this.url = base ? new URL(options.url, base).href : options.url;
|
|
156
|
+
this.format = options.format ?? (/\.json(?:[?#]|$)/i.test(options.url) ? '3dtiles' : 'copc');
|
|
157
|
+
this.options = options;
|
|
158
|
+
const tiles = this.format === '3dtiles';
|
|
159
|
+
this.style = {
|
|
160
|
+
...(options.colorBy ? { colorBy: options.colorBy } : {}),
|
|
161
|
+
pointSize: options.pointSize ?? 2,
|
|
162
|
+
maxPointSize: options.maxPointSize ?? 4,
|
|
163
|
+
sizeMode: options.sizeMode ?? 'adaptive',
|
|
164
|
+
shape: options.shape ?? 'circle',
|
|
165
|
+
edl: options.edl ?? false,
|
|
166
|
+
classifications: options.classifications ?? {},
|
|
167
|
+
...(options.elevationRange ? { elevationRange: options.elevationRange } : {}),
|
|
168
|
+
elevationRamp: options.elevationRamp ?? ELEVATION_RAMP,
|
|
169
|
+
...(options.intensityRange ? { intensityRange: options.intensityRange } : {}),
|
|
170
|
+
maxScreenSpaceError: options.maxScreenSpaceError ?? (tiles ? 16 : 1.5),
|
|
171
|
+
pointBudget: options.pointBudget ?? 3_000_000,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
/** @internal Drawn by the engine with 3D Tiles (the point cloud module loads with the first one) */
|
|
175
|
+
get needsFullEngine() {
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
/** Changes the style, the rest kept */
|
|
179
|
+
setStyle(style) {
|
|
180
|
+
this.style = { ...this.style, ...style };
|
|
181
|
+
// Kept for its creation while the engine with 3D Tiles loads
|
|
182
|
+
if (this.id < 0)
|
|
183
|
+
return;
|
|
184
|
+
this.apply(this.map.engine, this.id);
|
|
185
|
+
this.map.requestRender();
|
|
186
|
+
}
|
|
187
|
+
getStyle() {
|
|
188
|
+
return this.style;
|
|
189
|
+
}
|
|
190
|
+
/** Loading counters; undefined once removed and while the engine with 3D Tiles loads */
|
|
191
|
+
stats() {
|
|
192
|
+
if (this.id < 0)
|
|
193
|
+
return undefined;
|
|
194
|
+
return this.format === '3dtiles' ? this.map.engine.tiles3dStats(this.id) : this.map.engine.pointCloudStats(this.id);
|
|
195
|
+
}
|
|
196
|
+
/** What a COPC file says of itself (points, format, CRS, center, altitudes), once its head is read */
|
|
197
|
+
info() {
|
|
198
|
+
return this.id < 0 || this.format === '3dtiles' ? undefined : this.map.engine.pointCloudInfo(this.id);
|
|
199
|
+
}
|
|
200
|
+
/** @internal The point picked (`pickFeature`, 'hoverfeature'): a Point at its longitude, latitude and height, its
|
|
201
|
+
* attributes as properties */
|
|
202
|
+
featureAt(index) {
|
|
203
|
+
if (this.id < 0 || this.format === '3dtiles')
|
|
204
|
+
return undefined;
|
|
205
|
+
const point = this.map.engine.pointCloudPoint(this.id, index);
|
|
206
|
+
if (!point)
|
|
207
|
+
return undefined;
|
|
208
|
+
return {
|
|
209
|
+
type: 'Feature',
|
|
210
|
+
geometry: { type: 'Point', coordinates: [...point.lonLat, point.height] },
|
|
211
|
+
properties: point,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
apply(engine, id) {
|
|
215
|
+
const s = this.style;
|
|
216
|
+
if (this.format === '3dtiles') {
|
|
217
|
+
engine.setTiles3dStyle(id, s.maxScreenSpaceError, 1, s.pointSize);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const rate = this.options.requestsPerSecond ?? (/^https?:\/\/data\.geopf\.fr\//.test(this.url) ? 8 : 0);
|
|
221
|
+
engine.setPointCloudStyle(id, styleNumbers(s, rate), classPalette(s.classifications), rampTexels(s.elevationRamp).rgba);
|
|
222
|
+
}
|
|
223
|
+
/** @internal */
|
|
224
|
+
create(engine) {
|
|
225
|
+
const id = this.format === '3dtiles'
|
|
226
|
+
? engine.addTiles3d(this.url, this.style.maxScreenSpaceError)
|
|
227
|
+
: engine.addPointCloud(this.url, (wkt) => pointCloudCrs(wkt, this.options));
|
|
228
|
+
this.apply(engine, id);
|
|
229
|
+
return id;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
//# sourceMappingURL=pointclouds.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pointclouds.js","sourceRoot":"","sources":["../src/pointclouds.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Point clouds: a COPC file (Cloud Optimized Point Cloud: LAZ 1.4 with an octree, read by HTTP range requests, as the\n * IGN distributes LiDAR HD) or a 3D Tiles point cloud (`.pnts`, glTF points), drawn by the engine with 3D Tiles. The\n * COPC file's CRS comes from its WKT (built-in CRSs, or registered ones: `registerCrs`) or the `crs` option; altitudes\n * in NGF-IGN69 (Lambert-93, the CC zones) are raised by the RAF20 geoid height onto the ellipsoid of the relief and\n * the 3D Tiles.\n */\nimport { type Crs, type CrsLike, epsgCode, getCrs } from './crs.ts';\nimport { type Feature, parseColor, type Ramp, rampTexels } from './features.ts';\nimport { Layer } from './layers.ts';\nimport type { LayerHost } from './types.ts';\nimport type {\n Engine,\n PointCloudCrs,\n PointCloudInfo,\n PointCloudPoint,\n PointCloudStats,\n Tiles3dStats,\n} from './wasm/isard.js';\n\n/** What the points are colored by */\nexport type PointColor = 'rgb' | 'classification' | 'elevation' | 'intensity';\n\n/** The look of a class of points */\nexport interface ClassStyle {\n /** CSS color */\n color?: string;\n /** false hides the class */\n visible?: boolean;\n}\n\nexport interface PointCloudStyle {\n /** By RGB (files with colors), class (the ASPRS palette, `classifications`), altitude (`elevationRamp` over\n * `elevationRange`) or intensity (grey over `intensityRange`). Default: RGB when the file has colors, else class */\n colorBy?: PointColor;\n /** CSS pixels: the size of the points, or the smallest with `sizeMode: 'adaptive'` (default 2) */\n pointSize: number;\n /** CSS pixels: the largest adaptive size (default 4) */\n maxPointSize: number;\n /** `'adaptive'` (default): the spacing of the points of the finest level drawn there, at their distance (the\n * nearer, the larger, no gap); `'fixed'`: `pointSize` everywhere */\n sizeMode: 'adaptive' | 'fixed';\n /** `'circle'` (default) or `'square'` */\n shape: 'circle' | 'square';\n /** Eye-Dome Lighting: points shaded by the depth of their neighbours on screen, their relief read without normals\n * nor colors (default false; `strength` 1, `radius` 1.4 CSS pixels) */\n edl: boolean | { strength?: number; radius?: number };\n /** Colors and visibility by class code, over the defaults (ASPRS, and IGN's LiDAR HD classes 64 to 67; the noise\n * 7 and 18 and the artefacts 65 hidden): `{ 2: { color: '#a0522d' }, 66: { visible: false } }` */\n classifications: Record<number, ClassStyle>;\n /** Altitudes (metres, the file's vertical datum) mapped onto the ramp; default the file's lowest and highest */\n elevationRange?: [min: number, max: number];\n /** Colors from the lowest altitude (0) to the highest (1) */\n elevationRamp: Ramp;\n /** Intensities mapped from black to white; default the bulk of the first node's (2nd to 98th percentile) */\n intensityRange?: [min: number, max: number];\n /** CSS pixels: a node is refined while the spacing of its points covers more on screen (default 1.5; lower is finer\n * and heavier). For 3D Tiles, their screen-space error (default 16) */\n maxScreenSpaceError: number;\n /** Points drawn at most, the nearest and the coarsest first (default 3 000 000) */\n pointBudget: number;\n}\n\nexport interface PointCloudOptions extends Partial<PointCloudStyle> {\n /** A COPC file (`.copc.laz`) or a 3D Tiles `tileset.json` of points */\n url: string;\n /** Default: `'3dtiles'` for a `.json` URL, else `'copc'` */\n format?: 'copc' | '3dtiles';\n /** The CRS of a COPC file without a WKT, or whose CRS is not built in (`proj4('EPSG:2992')`) */\n crs?: CrsLike;\n /** Its altitudes are above the geoid (NGF-IGN69), raised by the RAF20 geoid height; default for Lambert-93 and the\n * CC zones */\n geoid?: boolean;\n /** Metres of a unit of z; default the vertical unit of the WKT (a US survey foot…), else that of x and y */\n verticalScale?: number;\n /** Requests a second at most: 8 by default for the Géoplateforme (data.geopf.fr allows 10), no limit elsewhere */\n requestsPerSecond?: number;\n}\n\n/** The default classes: ASPRS LAS 1.4, then IGN's LiDAR HD (64 permanent structures, 65 artefacts, 66 virtual points,\n * 67 miscellaneous buildings) */\nexport const CLASSIFICATIONS: Readonly<Record<number, Readonly<Required<ClassStyle>>>> = {\n 0: { color: '#a6a6a6', visible: true },\n 1: { color: '#c8c8c8', visible: true },\n 2: { color: '#b08458', visible: true },\n 3: { color: '#9ccc65', visible: true },\n 4: { color: '#5aa83f', visible: true },\n 5: { color: '#2e7d32', visible: true },\n 6: { color: '#e57352', visible: true },\n 7: { color: '#ff00ff', visible: false },\n 8: { color: '#ff0000', visible: true },\n 9: { color: '#3d8fd6', visible: true },\n 10: { color: '#8e6bb0', visible: true },\n 11: { color: '#7a7a7a', visible: true },\n 12: { color: '#ffe680', visible: true },\n 13: { color: '#ffff00', visible: true },\n 14: { color: '#ffc800', visible: true },\n 15: { color: '#c89600', visible: true },\n 16: { color: '#ff9632', visible: true },\n 17: { color: '#b48cc8', visible: true },\n 18: { color: '#ff00ff', visible: false },\n 64: { color: '#8c6e5a', visible: true },\n 65: { color: '#ff00ff', visible: false },\n 66: { color: '#5a6ec8', visible: true },\n 67: { color: '#e6966e', visible: true },\n};\n\n/** The default ramp of the altitudes, low to high */\nexport const ELEVATION_RAMP: Ramp = [\n [0, '#2b83ba'],\n [0.25, '#abdda4'],\n [0.5, '#ffffbf'],\n [0.75, '#fdae61'],\n [1, '#d7191c'],\n];\n\n/** The colors of the 256 classes (RGBA, alpha 0 hides one) */\nexport function classPalette(overrides: Record<number, ClassStyle> = {}): Uint8Array {\n const out = new Uint8Array(256 * 4);\n for (let code = 0; code < 256; code += 1) {\n const base = CLASSIFICATIONS[code] ?? { color: '#c8c8c8', visible: true };\n const own = overrides[code] ?? {};\n const [r = 0, g = 0, b = 0] = parseColor(own.color ?? base.color);\n out.set([r * 255, g * 255, b * 255, (own.visible ?? base.visible) ? 255 : 0], code * 4);\n }\n return out;\n}\n\n/** The section of a WKT opening with one of `keywords` (`PROJCS[…]`), from its keyword to its closing bracket */\nfunction section(wkt: string, keywords: string[]): string | undefined {\n for (const keyword of keywords) {\n const start = wkt.indexOf(`${keyword}[`);\n if (start < 0) continue;\n let depth = 0;\n for (let i = start + keyword.length; i < wkt.length; i += 1) {\n if (wkt[i] === '[') depth += 1;\n else if (wkt[i] === ']' && --depth === 0) return wkt.slice(start, i + 1);\n }\n }\n return undefined;\n}\n\n/** The EPSG code a WKT section ends with (its own `AUTHORITY`, or `ID` in WKT2), the last of its nested ones */\nfunction lastCode(part: string): number | undefined {\n const codes = [...part.matchAll(/(?:AUTHORITY|ID)\\[\\s*\"EPSG\"\\s*,\\s*\"?(\\d+)\"?\\s*\\]/g)];\n const last = codes.at(-1)?.[1];\n return last === undefined ? undefined : Number(last);\n}\n\n/** The factor of the last `UNIT` (`LENGTHUNIT` in WKT2) of a WKT section */\nfunction lastUnit(part: string | undefined): number | undefined {\n const units = [...(part ?? '').matchAll(/(?:LENGTH)?UNIT\\[\\s*\"[^\"]*\"\\s*,\\s*([\\d.eE+-]+)/g)];\n const factor = Number(units.at(-1)?.[1]);\n return Number.isFinite(factor) && factor > 0 ? factor : undefined;\n}\n\n/** What a WKT says of a CRS: its EPSG code (projected first), the metres of a unit of z */\nexport function wktCrs(wkt: string): { code: number | undefined; verticalScale: number | undefined } {\n const projected = section(wkt, ['PROJCS', 'PROJCRS']);\n const geographic = section(wkt, ['GEOGCS', 'GEOGCRS']);\n let code = lastCode(projected ?? geographic ?? '');\n if (code === undefined && /Lambert[- ]93/i.test(wkt)) code = 2154;\n const vertical = section(wkt, ['VERT_CS', 'VERTCRS']);\n const verticalScale = lastUnit(vertical ?? projected);\n return { code, verticalScale };\n}\n\n/** Whether the altitudes of a CRS are NGF-IGN69 by default: Lambert-93 and the CC zones */\nconst FRENCH = (code: number | undefined) => code === 2154 || (code !== undefined && code >= 3942 && code <= 3950);\n\n/** The CRS of a COPC file for the engine, from its WKT and the options */\nexport function pointCloudCrs(\n wkt: string | undefined,\n options: Pick<PointCloudOptions, 'crs' | 'geoid' | 'verticalScale'>,\n): PointCloudCrs {\n const parsed = wkt ? wktCrs(wkt) : { code: undefined, verticalScale: undefined };\n let crs: Crs;\n let code = parsed.code;\n if (options.crs !== undefined) {\n crs = getCrs(options.crs);\n if (typeof options.crs === 'string') code = epsgCode(options.crs) ?? code;\n } else if (code !== undefined) {\n try {\n crs = getCrs(`EPSG:${code}`);\n } catch {\n throw new Error(`the CRS of the file, EPSG:${code}, is not built in: give it as \\`crs\\` (proj4('EPSG:${code}'))`);\n }\n } else {\n throw new Error('the file names no CRS: give it as `crs`');\n }\n const inverse = (xy: Float64Array) => {\n const out = new Float64Array(xy.length);\n for (let i = 0; i + 1 < xy.length; i += 2) {\n const [lon = Number.NaN, lat = Number.NaN] = crs.inverse([xy[i] as number, xy[i + 1] as number]);\n out[i] = lon;\n out[i + 1] = lat;\n }\n return out;\n };\n return {\n inverse,\n geoid: options.geoid ?? (FRENCH(code) || /IGN69|NGF/.test(wkt ?? '')),\n verticalScale: options.verticalScale ?? parsed.verticalScale ?? 1,\n };\n}\n\n/** The style numbers of the engine (`setPointCloudStyle`) */\nfunction styleNumbers(s: PointCloudStyle, rate: number): Float64Array {\n const colors: PointColor[] = ['rgb', 'classification', 'elevation', 'intensity'];\n let edl: { strength?: number; radius?: number } | undefined;\n if (s.edl) edl = s.edl === true ? {} : s.edl;\n const [emin = Number.NaN, emax = Number.NaN] = s.elevationRange ?? [];\n const [imin = Number.NaN, imax = Number.NaN] = s.intensityRange ?? [];\n return Float64Array.of(\n s.colorBy ? colors.indexOf(s.colorBy) : -1,\n s.pointSize,\n s.maxPointSize,\n s.sizeMode === 'fixed' ? 0 : 1,\n s.shape === 'square' ? 0 : 1,\n edl ? (edl.strength ?? 1) : 0,\n edl?.radius ?? 1.4,\n emin,\n emax,\n imin,\n imax,\n s.maxScreenSpaceError,\n s.pointBudget,\n rate,\n );\n}\n\n/** A point cloud (`GeoMap.addPointCloud`): COPC or 3D Tiles points; `pickFeature` gives a COPC point's attributes */\nexport class PointCloudLayer extends Layer {\n readonly url: string;\n readonly format: 'copc' | '3dtiles';\n private style: PointCloudStyle;\n private readonly options: PointCloudOptions;\n\n /** @internal */\n constructor(map: LayerHost, options: PointCloudOptions) {\n super(map);\n // Against the page: the decoding workers fetch it, and a relative URL would be theirs\n const base = typeof document === 'undefined' ? undefined : document.baseURI;\n this.url = base ? new URL(options.url, base).href : options.url;\n this.format = options.format ?? (/\\.json(?:[?#]|$)/i.test(options.url) ? '3dtiles' : 'copc');\n this.options = options;\n const tiles = this.format === '3dtiles';\n this.style = {\n ...(options.colorBy ? { colorBy: options.colorBy } : {}),\n pointSize: options.pointSize ?? 2,\n maxPointSize: options.maxPointSize ?? 4,\n sizeMode: options.sizeMode ?? 'adaptive',\n shape: options.shape ?? 'circle',\n edl: options.edl ?? false,\n classifications: options.classifications ?? {},\n ...(options.elevationRange ? { elevationRange: options.elevationRange } : {}),\n elevationRamp: options.elevationRamp ?? ELEVATION_RAMP,\n ...(options.intensityRange ? { intensityRange: options.intensityRange } : {}),\n maxScreenSpaceError: options.maxScreenSpaceError ?? (tiles ? 16 : 1.5),\n pointBudget: options.pointBudget ?? 3_000_000,\n };\n }\n\n /** @internal Drawn by the engine with 3D Tiles (the point cloud module loads with the first one) */\n override get needsFullEngine(): boolean {\n return true;\n }\n\n /** Changes the style, the rest kept */\n setStyle(style: Partial<PointCloudStyle>): void {\n this.style = { ...this.style, ...style };\n // Kept for its creation while the engine with 3D Tiles loads\n if (this.id < 0) return;\n this.apply(this.map.engine, this.id);\n this.map.requestRender();\n }\n\n getStyle(): Readonly<PointCloudStyle> {\n return this.style;\n }\n\n /** Loading counters; undefined once removed and while the engine with 3D Tiles loads */\n stats(): PointCloudStats | Tiles3dStats | undefined {\n if (this.id < 0) return undefined;\n return this.format === '3dtiles' ? this.map.engine.tiles3dStats(this.id) : this.map.engine.pointCloudStats(this.id);\n }\n\n /** What a COPC file says of itself (points, format, CRS, center, altitudes), once its head is read */\n info(): PointCloudInfo | undefined {\n return this.id < 0 || this.format === '3dtiles' ? undefined : this.map.engine.pointCloudInfo(this.id);\n }\n\n /** @internal The point picked (`pickFeature`, 'hoverfeature'): a Point at its longitude, latitude and height, its\n * attributes as properties */\n featureAt(index: number): Feature<PointCloudPoint> | undefined {\n if (this.id < 0 || this.format === '3dtiles') return undefined;\n const point = this.map.engine.pointCloudPoint(this.id, index);\n if (!point) return undefined;\n return {\n type: 'Feature',\n geometry: { type: 'Point', coordinates: [...point.lonLat, point.height] },\n properties: point,\n };\n }\n\n private apply(engine: Engine, id: number): void {\n const s = this.style;\n if (this.format === '3dtiles') {\n engine.setTiles3dStyle(id, s.maxScreenSpaceError, 1, s.pointSize);\n return;\n }\n const rate = this.options.requestsPerSecond ?? (/^https?:\\/\\/data\\.geopf\\.fr\\//.test(this.url) ? 8 : 0);\n engine.setPointCloudStyle(\n id,\n styleNumbers(s, rate),\n classPalette(s.classifications),\n rampTexels(s.elevationRamp).rgba,\n );\n }\n\n /** @internal */\n protected create(engine: Engine): number {\n const id =\n this.format === '3dtiles'\n ? engine.addTiles3d(this.url, this.style.maxScreenSpaceError)\n : engine.addPointCloud(this.url, (wkt) => pointCloudCrs(wkt, this.options));\n this.apply(engine, id);\n return id;\n }\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `isard/projections`: coordinate reference systems (Lambert-93, the CC zones, UTM, or any proj4 converter), GeoJSON
|
|
3
|
+
* reprojected into longitudes and latitudes, and the tile grids of rasters served in another projection.
|
|
4
|
+
*
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { reproject, wmtsGrid } from 'isard/projections';
|
|
7
|
+
* map.addFills({ data: reproject(parcels, 'EPSG:2154') });
|
|
8
|
+
* map.addRaster({ url, grid: await wmtsGrid(capabilitiesUrl, 'PLANIGNV2.L93', '2154_10cm_6_20') });
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
export { type Crs, type CrsLike, getCrs, lambertConformalConic, registerCrs, reproject, transverseMercator, } from './crs.ts';
|
|
12
|
+
export type { TileGrid, TileMatrix } from './grid.ts';
|
|
13
|
+
export { parseWmtsGrid, wmtsGrid } from './wmts.ts';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `isard/projections`: coordinate reference systems (Lambert-93, the CC zones, UTM, or any proj4 converter), GeoJSON
|
|
3
|
+
* reprojected into longitudes and latitudes, and the tile grids of rasters served in another projection.
|
|
4
|
+
*
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { reproject, wmtsGrid } from 'isard/projections';
|
|
7
|
+
* map.addFills({ data: reproject(parcels, 'EPSG:2154') });
|
|
8
|
+
* map.addRaster({ url, grid: await wmtsGrid(capabilitiesUrl, 'PLANIGNV2.L93', '2154_10cm_6_20') });
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
export { getCrs, lambertConformalConic, registerCrs, reproject, transverseMercator, } from "./crs.js";
|
|
12
|
+
export { parseWmtsGrid, wmtsGrid } from "./wmts.js";
|
|
13
|
+
//# sourceMappingURL=projections.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projections.js","sourceRoot":"","sources":["../src/projections.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAGL,MAAM,EACN,qBAAqB,EACrB,WAAW,EACX,SAAS,EACT,kBAAkB,GACnB,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC","sourcesContent":["/**\n * `isard/projections`: coordinate reference systems (Lambert-93, the CC zones, UTM, or any proj4 converter), GeoJSON\n * reprojected into longitudes and latitudes, and the tile grids of rasters served in another projection.\n *\n * ```ts\n * import { reproject, wmtsGrid } from 'isard/projections';\n * map.addFills({ data: reproject(parcels, 'EPSG:2154') });\n * map.addRaster({ url, grid: await wmtsGrid(capabilitiesUrl, 'PLANIGNV2.L93', '2154_10cm_6_20') });\n * ```\n */\nexport {\n type Crs,\n type CrsLike,\n getCrs,\n lambertConformalConic,\n registerCrs,\n reproject,\n transverseMercator,\n} from './crs.ts';\nexport type { TileGrid, TileMatrix } from './grid.ts';\nexport { parseWmtsGrid, wmtsGrid } from './wmts.ts';\n"]}
|
package/dist/protocol.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export type WorkerRequest = {
|
|
|
6
6
|
module: WebAssembly.Module;
|
|
7
7
|
decoders: DecoderUrls;
|
|
8
8
|
formats: TextureFormats;
|
|
9
|
+
/** URL of the point cloud module (`isard_points_bg.wasm`), loaded with the first COPC chunk */
|
|
10
|
+
points: string;
|
|
9
11
|
} | {
|
|
10
12
|
type: 'load';
|
|
11
13
|
id: number;
|
|
@@ -14,6 +16,17 @@ export type WorkerRequest = {
|
|
|
14
16
|
yUp: boolean;
|
|
15
17
|
reload: boolean;
|
|
16
18
|
priority?: 'high' | 'low';
|
|
19
|
+
} | {
|
|
20
|
+
type: 'points';
|
|
21
|
+
id: number;
|
|
22
|
+
url: string;
|
|
23
|
+
offset: number;
|
|
24
|
+
size: number;
|
|
25
|
+
laz: Uint8Array;
|
|
26
|
+
layout: Float64Array;
|
|
27
|
+
grid: Float64Array;
|
|
28
|
+
count: number;
|
|
29
|
+
priority?: 'high' | 'low';
|
|
17
30
|
} | {
|
|
18
31
|
type: 'abort';
|
|
19
32
|
id: number;
|
|
@@ -22,6 +35,10 @@ export type WorkerReply = {
|
|
|
22
35
|
type: 'tile';
|
|
23
36
|
id: number;
|
|
24
37
|
tile: DecodedTile;
|
|
38
|
+
} | {
|
|
39
|
+
type: 'points';
|
|
40
|
+
id: number;
|
|
41
|
+
vertices: Uint8Array<ArrayBuffer>;
|
|
25
42
|
} | {
|
|
26
43
|
type: 'error';
|
|
27
44
|
id: number;
|
package/dist/protocol.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"","sourcesContent":["/** Messages between the main thread and the decoding workers */\nimport type { DecoderUrls } from './decoders.ts';\nimport type { DecodedTile, TextureFormats } from './wasm/isard.js';\n\nexport type WorkerRequest =\n | {
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"","sourcesContent":["/** Messages between the main thread and the decoding workers */\nimport type { DecoderUrls } from './decoders.ts';\nimport type { DecodedTile, TextureFormats } from './wasm/isard.js';\n\nexport type WorkerRequest =\n | {\n type: 'init';\n module: WebAssembly.Module;\n decoders: DecoderUrls;\n formats: TextureFormats;\n /** URL of the point cloud module (`isard_points_bg.wasm`), loaded with the first COPC chunk */\n points: string;\n }\n | {\n type: 'load';\n id: number;\n url: string;\n transform: Float64Array;\n yUp: boolean;\n reload: boolean;\n priority?: 'high' | 'low';\n }\n | {\n type: 'points';\n id: number;\n url: string;\n offset: number;\n size: number;\n laz: Uint8Array;\n layout: Float64Array;\n grid: Float64Array;\n count: number;\n priority?: 'high' | 'low';\n }\n | { type: 'abort'; id: number };\n\nexport type WorkerReply =\n | { type: 'tile'; id: number; tile: DecodedTile }\n | { type: 'points'; id: number; vertices: Uint8Array<ArrayBuffer> }\n | { type: 'error'; id: number; error: string; aborted: boolean };\n"]}
|
package/dist/symbols.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Text labels from GeoJSON: at points, at the middle of lines, at the center of polygons. Shaped on the page,
|
|
3
|
-
* the engine every frame with collisions shared by all symbol layers (the top layer first, each layer in
|
|
4
|
-
* drawn with a halo, standing on the relief.
|
|
2
|
+
* Text labels and icons from GeoJSON: at points, at the middle of lines, at the center of polygons. Shaped on the page,
|
|
3
|
+
* placed by the engine every frame with collisions shared by all symbol layers (the top layer first, each layer in
|
|
4
|
+
* data order), drawn with a halo, standing on the relief. The icons are the map's images (`map.addImage`, a vector
|
|
5
|
+
* basemap's sprite), beside their text or stretched around it.
|
|
5
6
|
*/
|
|
6
7
|
import { type Feature, type FeatureData, type FeatureLayerStyle, type Placement, type Properties, type Size, type Styled } from './features.ts';
|
|
7
8
|
import { type Glyphs, type TextPart } from './glyphs.ts';
|
|
9
|
+
import { type Icons } from './icons.ts';
|
|
8
10
|
import { Layer } from './layers.ts';
|
|
9
11
|
import type { Anchor } from './overlay.ts';
|
|
10
12
|
import type { LayerHost } from './types.ts';
|
|
@@ -16,7 +18,7 @@ export interface SymbolStyle<P = Properties> extends Omit<FeatureLayerStyle<P>,
|
|
|
16
18
|
/** CSS pixels, or zoom stops (default 12) */
|
|
17
19
|
size: Styled<Size, P>;
|
|
18
20
|
/** `'point'` (default): horizontal text; `'line'`: along the line at its middle, kept upright */
|
|
19
|
-
placement: 'point' | 'line'
|
|
21
|
+
placement: Styled<'point' | 'line', P>;
|
|
20
22
|
color: Styled<string, P>;
|
|
21
23
|
haloColor: Styled<string, P>;
|
|
22
24
|
/** CSS pixels (default 0) */
|
|
@@ -29,16 +31,48 @@ export interface SymbolStyle<P = Properties> extends Omit<FeatureLayerStyle<P>,
|
|
|
29
31
|
maxWidth: Styled<number, P>;
|
|
30
32
|
/** Ems (default 1.2) */
|
|
31
33
|
lineHeight: Styled<number, P>;
|
|
32
|
-
/** Shown even where it overlaps other labels, and hiding none (MapLibre's allow-overlap and ignore-placement)
|
|
33
|
-
*
|
|
34
|
-
|
|
34
|
+
/** Shown even where it overlaps other labels, and hiding none (MapLibre's allow-overlap and ignore-placement);
|
|
35
|
+
* `'allow'`: shown even where it overlaps, still hiding the labels after it; `'ignore'`: shown only where it fits,
|
|
36
|
+
* hiding none (default false) */
|
|
37
|
+
overlap: Styled<Overlap, P>;
|
|
38
|
+
/** Shown without its icon where the icon does not fit (default false) */
|
|
39
|
+
textOptional: Styled<boolean, P>;
|
|
40
|
+
/** An image of the map (`map.addImage`); empty: none (default) */
|
|
41
|
+
icon: Styled<string, P>;
|
|
42
|
+
/** Scale of the image, or zoom stops (default 1) */
|
|
43
|
+
iconSize: Styled<Size, P>;
|
|
44
|
+
/** Side of the icon at the anchor (default `'center'`) */
|
|
45
|
+
iconAnchor: Styled<Anchor, P>;
|
|
46
|
+
/** Shift, CSS pixels at size 1 (default [0, 0]) */
|
|
47
|
+
iconOffset: Styled<[x: number, y: number], P>;
|
|
48
|
+
/** Degrees, clockwise (default 0) */
|
|
49
|
+
iconRotate: Styled<number, P>;
|
|
50
|
+
/** `'viewport'`: facing the screen; `'map'`: turning with the map, along its line when placed on one; `'auto'`
|
|
51
|
+
* (default): `'map'` with the `'line'` placement */
|
|
52
|
+
iconRotationAlignment: Styled<'map' | 'viewport' | 'auto', P>;
|
|
53
|
+
/** As `overlap`, for the icon (default false) */
|
|
54
|
+
iconOverlap: Styled<Overlap, P>;
|
|
55
|
+
/** Shown without its text where the text does not fit (default false) */
|
|
56
|
+
iconOptional: Styled<boolean, P>;
|
|
57
|
+
/** Stretched around its text: its width, its height, both (a road shield; `'none'` by default) */
|
|
58
|
+
iconTextFit: Styled<'none' | 'width' | 'height' | 'both', P>;
|
|
59
|
+
/** Room around the text of a fitted icon: top, right, bottom, left (CSS pixels, default 0) */
|
|
60
|
+
iconTextFitPadding: Styled<[top: number, right: number, bottom: number, left: number], P>;
|
|
61
|
+
/** Color of a signed distance field image (default black) */
|
|
62
|
+
iconColor: Styled<string, P>;
|
|
63
|
+
/** 0 to 1 (default 1) */
|
|
64
|
+
iconOpacity: Styled<number, P>;
|
|
35
65
|
}
|
|
66
|
+
/** How a label's text or icon meets the others: `true` shown wherever and hiding none, `'allow'` shown wherever,
|
|
67
|
+
* `'ignore'` hiding none, `false` neither (MapLibre's allow-overlap and ignore-placement) */
|
|
68
|
+
export type Overlap = boolean | 'allow' | 'ignore';
|
|
36
69
|
export interface SymbolOptions<P = Properties> extends Partial<SymbolStyle<P>>, Placement {
|
|
37
70
|
data: FeatureData<P>;
|
|
38
71
|
}
|
|
39
|
-
/** The map's glyphs, for a layer */
|
|
72
|
+
/** The map's glyphs and icons, for a layer */
|
|
40
73
|
export interface GlyphHost extends LayerHost {
|
|
41
74
|
readonly glyphs: Glyphs;
|
|
75
|
+
readonly icons: Icons;
|
|
42
76
|
}
|
|
43
77
|
export declare class SymbolLayer<P = Properties> extends Layer {
|
|
44
78
|
private readonly host;
|