@ifc-lite/pointcloud 0.2.0 → 0.3.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/dist/formats/ascii-points.d.ts +61 -0
- package/dist/formats/ascii-points.d.ts.map +1 -0
- package/dist/formats/ascii-points.js +243 -0
- package/dist/formats/ascii-points.js.map +1 -0
- package/dist/formats/e57-decode.d.ts +28 -0
- package/dist/formats/e57-decode.d.ts.map +1 -0
- package/dist/formats/e57-decode.js +425 -0
- package/dist/formats/e57-decode.js.map +1 -0
- package/dist/formats/e57-page.d.ts +42 -0
- package/dist/formats/e57-page.d.ts.map +1 -0
- package/dist/formats/e57-page.js +107 -0
- package/dist/formats/e57-page.js.map +1 -0
- package/dist/formats/e57-xml.d.ts +55 -0
- package/dist/formats/e57-xml.d.ts.map +1 -0
- package/dist/formats/e57-xml.js +127 -0
- package/dist/formats/e57-xml.js.map +1 -0
- package/dist/formats/e57.d.ts +29 -117
- package/dist/formats/e57.d.ts.map +1 -1
- package/dist/formats/e57.js +51 -444
- package/dist/formats/e57.js.map +1 -1
- package/dist/formats/ifcx-points.js +13 -1
- package/dist/formats/ifcx-points.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/streaming/ascii-points-source.d.ts +31 -0
- package/dist/streaming/ascii-points-source.d.ts.map +1 -0
- package/dist/streaming/ascii-points-source.js +83 -0
- package/dist/streaming/ascii-points-source.js.map +1 -0
- package/dist/streaming/decode-worker.js +5 -0
- package/dist/streaming/decode-worker.js.map +1 -1
- package/dist/streaming/e57-source.js +6 -1
- package/dist/streaming/e57-source.js.map +1 -1
- package/dist/streaming/laz-source.d.ts.map +1 -1
- package/dist/streaming/laz-source.js +33 -1
- package/dist/streaming/laz-source.js.map +1 -1
- package/dist/streaming/protocol.d.ts +1 -1
- package/dist/streaming/protocol.d.ts.map +1 -1
- package/dist/streaming/worker-client.d.ts +1 -1
- package/dist/streaming/worker-client.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
import { findField } from './e57-xml.js';
|
|
5
|
+
/**
|
|
6
|
+
* Decode the binary section starting at `entry.binaryFileOffset` in the
|
|
7
|
+
* logical-bytes view. NOTE: `binaryFileOffset` here must already point
|
|
8
|
+
* at the first DataPacket (i.e. AFTER the 32-byte CompressedVector
|
|
9
|
+
* section header) — `decodeE57` does this conversion via
|
|
10
|
+
* `resolveCompressedVectorDataOffset`. Callers passing the raw XML
|
|
11
|
+
* offset directly will see a "bytestreamCount ≠ prototype length"
|
|
12
|
+
* mismatch.
|
|
13
|
+
*
|
|
14
|
+
* Supports Float (single/double), ScaledInteger (bit-packed integer
|
|
15
|
+
* with scale/offset), and Integer for cartesianX/Y/Z + colorRed/
|
|
16
|
+
* Green/Blue + intensity. Other prototype fields are honoured for
|
|
17
|
+
* stride math but discarded.
|
|
18
|
+
*/
|
|
19
|
+
export function decodeE57Scan(logical, entry) {
|
|
20
|
+
const xField = findField(entry.prototype, 'cartesianX');
|
|
21
|
+
const yField = findField(entry.prototype, 'cartesianY');
|
|
22
|
+
const zField = findField(entry.prototype, 'cartesianZ');
|
|
23
|
+
if (!xField || !yField || !zField) {
|
|
24
|
+
throw new Error('E57: prototype missing cartesianX/Y/Z');
|
|
25
|
+
}
|
|
26
|
+
for (const f of [xField, yField, zField]) {
|
|
27
|
+
if (f.kind === 'Integer') {
|
|
28
|
+
// Plain integer cartesian coords don't appear in any real exporter
|
|
29
|
+
// we've seen — the spec uses ScaledInteger when the cartesian is
|
|
30
|
+
// integer-quantised. Fail clearly rather than silently producing
|
|
31
|
+
// unscaled metres (or whatever the integer happens to be).
|
|
32
|
+
throw new Error(`E57: cartesian${f.name.slice(-1)} encoded as plain Integer (only Float / ScaledInteger supported)`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const rField = findField(entry.prototype, 'colorRed');
|
|
36
|
+
const gField = findField(entry.prototype, 'colorGreen');
|
|
37
|
+
const bField = findField(entry.prototype, 'colorBlue');
|
|
38
|
+
const hasRgb = !!(rField && gField && bField);
|
|
39
|
+
const iField = findField(entry.prototype, 'intensity');
|
|
40
|
+
// Classification: not in the standard ASTM E2807 prototype, but
|
|
41
|
+
// some exporters (CloudCompare, custom LIDAR pipelines) add a
|
|
42
|
+
// `classification` Integer / ScaledInteger field. We honour it
|
|
43
|
+
// when present so the splat shader's classification colour mode
|
|
44
|
+
// works on those files. Stock Faro / Leica scans don't carry it
|
|
45
|
+
// — that's why classification mode shows everything as class 0
|
|
46
|
+
// (the spec maps that to "Created, never classified").
|
|
47
|
+
const cField = findField(entry.prototype, 'classification');
|
|
48
|
+
const positions = new Float32Array(entry.recordCount * 3);
|
|
49
|
+
const colors = hasRgb ? new Float32Array(entry.recordCount * 3) : undefined;
|
|
50
|
+
// Allocate intensity for any supported field kind. ScaledInteger
|
|
51
|
+
// and Integer (u8 / u16) are both common in real exports.
|
|
52
|
+
const intensities = iField && (iField.kind === 'Float' || iField.kind === 'Integer' || iField.kind === 'ScaledInteger')
|
|
53
|
+
? new Uint16Array(entry.recordCount)
|
|
54
|
+
: undefined;
|
|
55
|
+
const classifications = cField && (cField.kind === 'Integer' || cField.kind === 'ScaledInteger')
|
|
56
|
+
? new Uint8Array(entry.recordCount)
|
|
57
|
+
: undefined;
|
|
58
|
+
// Walk DataPackets starting at binaryFileOffset.
|
|
59
|
+
// Packet header (4 bytes):
|
|
60
|
+
// byte 0: packetType (1=data, 2=index, 3=empty)
|
|
61
|
+
// byte 1: packetFlags (bit 0 = compressorRestart)
|
|
62
|
+
// bytes 2..3: packetLogicalLength - 1 (LE u16; total packet bytes minus 1)
|
|
63
|
+
let offset = entry.binaryFileOffset;
|
|
64
|
+
const view = new DataView(logical.buffer, logical.byteOffset, logical.byteLength);
|
|
65
|
+
let written = 0;
|
|
66
|
+
while (written < entry.recordCount && offset < logical.length) {
|
|
67
|
+
if (offset + 4 > logical.length) {
|
|
68
|
+
throw new Error('E57: truncated DataPacket header');
|
|
69
|
+
}
|
|
70
|
+
const packetType = view.getUint8(offset);
|
|
71
|
+
const packetLogicalLength = view.getUint16(offset + 2, true) + 1;
|
|
72
|
+
if (packetType !== 1) {
|
|
73
|
+
// Skip non-data packets (index/empty); they may appear interleaved.
|
|
74
|
+
offset += packetLogicalLength;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const packetEnd = offset + packetLogicalLength;
|
|
78
|
+
if (packetEnd > logical.length) {
|
|
79
|
+
throw new Error('E57: DataPacket runs past end of logical bytes');
|
|
80
|
+
}
|
|
81
|
+
// Data packet header beyond the common 4 bytes:
|
|
82
|
+
// byte 4..5: bytestreamCount (u16 LE)
|
|
83
|
+
// then `bytestreamCount` × u16 LE = bytestreamByteCount[]
|
|
84
|
+
// then payload (concatenated bytestreams, in prototype order)
|
|
85
|
+
//
|
|
86
|
+
// CRCs in E57 live at the PAGE level (4 bytes per 1024-byte
|
|
87
|
+
// physical page, stripped by `stripPageCrc` before we get here).
|
|
88
|
+
// There is no per-packet trailing CRC — the bytestreams fill the
|
|
89
|
+
// packet exactly up to `packetEnd`. An earlier version of this
|
|
90
|
+
// code subtracted 4 bytes assuming a packet-level CRC, which
|
|
91
|
+
// false-positived the bounds checks below on real-world Faro /
|
|
92
|
+
// Trimble exports whose last bytestream ends within the final
|
|
93
|
+
// 4 bytes of the packet.
|
|
94
|
+
const payloadEnd = packetEnd;
|
|
95
|
+
if (offset + 6 > payloadEnd) {
|
|
96
|
+
throw new Error('E57: truncated DataPacket header');
|
|
97
|
+
}
|
|
98
|
+
const bytestreamCount = view.getUint16(offset + 4, true);
|
|
99
|
+
if (bytestreamCount !== entry.prototype.length) {
|
|
100
|
+
throw new Error(`E57: packet bytestreamCount (${bytestreamCount}) ≠ prototype length (${entry.prototype.length})`);
|
|
101
|
+
}
|
|
102
|
+
const bytestreamLengths = [];
|
|
103
|
+
let cursor = offset + 6;
|
|
104
|
+
for (let i = 0; i < bytestreamCount; i++) {
|
|
105
|
+
if (cursor + 2 > payloadEnd) {
|
|
106
|
+
throw new Error('E57: truncated bytestream length table');
|
|
107
|
+
}
|
|
108
|
+
bytestreamLengths.push(view.getUint16(cursor, true));
|
|
109
|
+
cursor += 2;
|
|
110
|
+
}
|
|
111
|
+
const fieldOffsets = new Map();
|
|
112
|
+
let streamCursor = cursor;
|
|
113
|
+
for (let i = 0; i < bytestreamCount; i++) {
|
|
114
|
+
// Each bytestream must fit inside the packet payload — a corrupt
|
|
115
|
+
// file could otherwise have us read into the next packet or
|
|
116
|
+
// even past `logical`.
|
|
117
|
+
if (streamCursor + bytestreamLengths[i] > payloadEnd) {
|
|
118
|
+
throw new Error(`E57: bytestream ${entry.prototype[i].name} (${bytestreamLengths[i]} bytes) `
|
|
119
|
+
+ `runs past packet payload at offset ${streamCursor}`);
|
|
120
|
+
}
|
|
121
|
+
fieldOffsets.set(entry.prototype[i].name, { start: streamCursor, length: bytestreamLengths[i] });
|
|
122
|
+
streamCursor += bytestreamLengths[i];
|
|
123
|
+
}
|
|
124
|
+
// Per-axis packet capacity now varies by field kind: Float uses
|
|
125
|
+
// floor(length / byteSize), ScaledInteger uses floor(length * 8 /
|
|
126
|
+
// bitsPerRecord). Take the min so a mixed-encoding packet picks
|
|
127
|
+
// the shortest stream.
|
|
128
|
+
const xPos = fieldOffsets.get('cartesianX');
|
|
129
|
+
const yPos = fieldOffsets.get('cartesianY');
|
|
130
|
+
const zPos = fieldOffsets.get('cartesianZ');
|
|
131
|
+
const xCapacity = floatOrSiPointCapacity(xField, xPos.length);
|
|
132
|
+
const yCapacity = floatOrSiPointCapacity(yField, yPos.length);
|
|
133
|
+
const zCapacity = floatOrSiPointCapacity(zField, zPos.length);
|
|
134
|
+
const pointsInPacket = Math.min(xCapacity, yCapacity, zCapacity);
|
|
135
|
+
const take = Math.min(pointsInPacket, entry.recordCount - written);
|
|
136
|
+
readCartesianStream(logical, view, xField, xPos.start, positions, written, take, 0);
|
|
137
|
+
readCartesianStream(logical, view, yField, yPos.start, positions, written, take, 1);
|
|
138
|
+
readCartesianStream(logical, view, zField, zPos.start, positions, written, take, 2);
|
|
139
|
+
if (colors && rField && gField && bField) {
|
|
140
|
+
writeColorChannel(view, fieldOffsets.get('colorRed').start, rField, colors, written, take, 0, logical);
|
|
141
|
+
writeColorChannel(view, fieldOffsets.get('colorGreen').start, gField, colors, written, take, 1, logical);
|
|
142
|
+
writeColorChannel(view, fieldOffsets.get('colorBlue').start, bField, colors, written, take, 2, logical);
|
|
143
|
+
}
|
|
144
|
+
if (intensities && iField) {
|
|
145
|
+
readIntensityStream(logical, view, iField, fieldOffsets.get('intensity').start, intensities, written, take);
|
|
146
|
+
}
|
|
147
|
+
if (classifications && cField) {
|
|
148
|
+
readClassificationStream(logical, view, cField, fieldOffsets.get('classification').start, classifications, written, take);
|
|
149
|
+
}
|
|
150
|
+
written += take;
|
|
151
|
+
offset = packetEnd;
|
|
152
|
+
}
|
|
153
|
+
if (written < entry.recordCount) {
|
|
154
|
+
// Real-world files sometimes report counts a few records higher
|
|
155
|
+
// than what's actually stored; trim positions to the actual count
|
|
156
|
+
// so downstream code doesn't see uninitialised tail values.
|
|
157
|
+
return finalize(positions.subarray(0, written * 3), colors?.subarray(0, written * 3), intensities?.subarray(0, written), classifications?.subarray(0, written), written);
|
|
158
|
+
}
|
|
159
|
+
return finalize(positions, colors, intensities, classifications, entry.recordCount);
|
|
160
|
+
}
|
|
161
|
+
function writeColorChannel(view, start, field, colors, written, take, channelOffset, bytes) {
|
|
162
|
+
if (field.kind === 'Float') {
|
|
163
|
+
const stride = field.precision === 'single' ? 4 : 8;
|
|
164
|
+
for (let i = 0; i < take; i++) {
|
|
165
|
+
const v = stride === 4 ? view.getFloat32(start + i * stride, true) : view.getFloat64(start + i * stride, true);
|
|
166
|
+
colors[(written + i) * 3 + channelOffset] = clamp01(v);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
else if (field.kind === 'Integer') {
|
|
170
|
+
// Pick element width from the declared range. E57 producers use
|
|
171
|
+
// either u8 (0..255 — most common) or u16 (0..65535). Both
|
|
172
|
+
// appear in real files; assuming u8 distorts u16-encoded colors.
|
|
173
|
+
const min = field.minimum ?? 0;
|
|
174
|
+
const max = field.maximum ?? 255;
|
|
175
|
+
const span = max - min;
|
|
176
|
+
const inv = span > 0 ? 1 / span : 1;
|
|
177
|
+
const widest = Math.max(Math.abs(min), Math.abs(max));
|
|
178
|
+
const stride = widest > 255 ? 2 : 1;
|
|
179
|
+
const signed = min < 0;
|
|
180
|
+
for (let i = 0; i < take; i++) {
|
|
181
|
+
const off = start + i * stride;
|
|
182
|
+
const raw = stride === 2
|
|
183
|
+
? (signed ? view.getInt16(off, true) : view.getUint16(off, true))
|
|
184
|
+
: (signed ? view.getInt8(off) : view.getUint8(off));
|
|
185
|
+
colors[(written + i) * 3 + channelOffset] = clamp01((raw - min) * inv);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
// ScaledInteger colour: bit-packed integer normalised by the
|
|
190
|
+
// declared min/max range. The "scale + offset" prototype attrs
|
|
191
|
+
// still apply per spec but for colour they always normalise to
|
|
192
|
+
// the declared range, so we just remap [minimum, maximum] → [0, 1]
|
|
193
|
+
// like Integer colour does.
|
|
194
|
+
const min = field.minimum ?? 0;
|
|
195
|
+
const max = field.maximum ?? 1;
|
|
196
|
+
const span = max - min;
|
|
197
|
+
const inv = span > 0 ? 1 / span : 1;
|
|
198
|
+
const bitsPerRecord = scaledIntegerBitsPerRecord(field);
|
|
199
|
+
const startBit = start * 8;
|
|
200
|
+
for (let i = 0; i < take; i++) {
|
|
201
|
+
const raw = readBitsLE(bytes, startBit + i * bitsPerRecord, bitsPerRecord);
|
|
202
|
+
colors[(written + i) * 3 + channelOffset] = clamp01(raw * inv);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Read N points from a cartesian (X / Y / Z) bytestream into the
|
|
208
|
+
* positions array. Float: straight DataView reads; ScaledInteger:
|
|
209
|
+
* bit-pack walk plus per-record `(raw + minimum) * scale + offset`.
|
|
210
|
+
*
|
|
211
|
+
* `axis` selects which of the three position slots to write to
|
|
212
|
+
* (0 = X, 1 = Y, 2 = Z).
|
|
213
|
+
*/
|
|
214
|
+
function readCartesianStream(bytes, view, field, start, positions, written, take, axis) {
|
|
215
|
+
if (field.kind === 'Float') {
|
|
216
|
+
const stride = field.precision === 'single' ? 4 : 8;
|
|
217
|
+
if (stride === 4) {
|
|
218
|
+
for (let i = 0; i < take; i++) {
|
|
219
|
+
positions[(written + i) * 3 + axis] = view.getFloat32(start + i * stride, true);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
for (let i = 0; i < take; i++) {
|
|
224
|
+
positions[(written + i) * 3 + axis] = view.getFloat64(start + i * stride, true);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
// ScaledInteger: stream stores `raw_int = (value - minimum)` as
|
|
230
|
+
// an unsigned bit-pack; decoded float = (raw_int + minimum) * scale + offset.
|
|
231
|
+
const bitsPerRecord = scaledIntegerBitsPerRecord(field);
|
|
232
|
+
const minimum = field.minimum ?? 0;
|
|
233
|
+
const scale = field.scale ?? 1;
|
|
234
|
+
const offset = field.offset ?? 0;
|
|
235
|
+
const startBit = start * 8;
|
|
236
|
+
for (let i = 0; i < take; i++) {
|
|
237
|
+
const raw = readBitsLE(bytes, startBit + i * bitsPerRecord, bitsPerRecord);
|
|
238
|
+
positions[(written + i) * 3 + axis] = (raw + minimum) * scale + offset;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Read N intensity samples from a bytestream and normalise to u16.
|
|
243
|
+
* Handles Float, Integer, and ScaledInteger kinds.
|
|
244
|
+
*/
|
|
245
|
+
function readIntensityStream(bytes, view, field, start, intensities, written, take) {
|
|
246
|
+
if (field.kind === 'Float') {
|
|
247
|
+
const stride = field.precision === 'single' ? 4 : 8;
|
|
248
|
+
for (let i = 0; i < take; i++) {
|
|
249
|
+
const v = stride === 4 ? view.getFloat32(start + i * stride, true) : view.getFloat64(start + i * stride, true);
|
|
250
|
+
intensities[written + i] = Math.min(65535, Math.max(0, Math.round(v * 65535)));
|
|
251
|
+
}
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
if (field.kind === 'Integer') {
|
|
255
|
+
const min = field.minimum ?? 0;
|
|
256
|
+
const max = field.maximum ?? 65535;
|
|
257
|
+
const span = max - min;
|
|
258
|
+
const inv = span > 0 ? 1 / span : 1;
|
|
259
|
+
const widest = Math.max(Math.abs(min), Math.abs(max));
|
|
260
|
+
const stride = widest > 255 ? 2 : 1;
|
|
261
|
+
const signed = min < 0;
|
|
262
|
+
for (let i = 0; i < take; i++) {
|
|
263
|
+
const off = start + i * stride;
|
|
264
|
+
const raw = stride === 2
|
|
265
|
+
? (signed ? view.getInt16(off, true) : view.getUint16(off, true))
|
|
266
|
+
: (signed ? view.getInt8(off) : view.getUint8(off));
|
|
267
|
+
const norm = (raw - min) * inv;
|
|
268
|
+
intensities[written + i] = Math.min(65535, Math.max(0, Math.round(norm * 65535)));
|
|
269
|
+
}
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
// ScaledInteger intensity: range-remap from the bit-pack walk.
|
|
273
|
+
const bitsPerRecord = scaledIntegerBitsPerRecord(field);
|
|
274
|
+
const minimum = field.minimum ?? 0;
|
|
275
|
+
const maximum = field.maximum ?? minimum;
|
|
276
|
+
const span = maximum - minimum;
|
|
277
|
+
const inv = span > 0 ? 1 / span : 1;
|
|
278
|
+
const startBit = start * 8;
|
|
279
|
+
for (let i = 0; i < take; i++) {
|
|
280
|
+
const raw = readBitsLE(bytes, startBit + i * bitsPerRecord, bitsPerRecord);
|
|
281
|
+
intensities[written + i] = Math.min(65535, Math.max(0, Math.round(raw * inv * 65535)));
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* E57 §6.3.4: bitsPerRecord = ceil(log2(maximum - minimum + 1)).
|
|
286
|
+
* Caps at 53 bits (Number-precision limit). Real exporters top out
|
|
287
|
+
* around 32 bits.
|
|
288
|
+
*/
|
|
289
|
+
function scaledIntegerBitsPerRecord(field) {
|
|
290
|
+
const min = field.minimum ?? 0;
|
|
291
|
+
const max = field.maximum ?? min;
|
|
292
|
+
const span = Math.max(0, max - min);
|
|
293
|
+
if (span === 0)
|
|
294
|
+
return 1;
|
|
295
|
+
const bits = Math.ceil(Math.log2(span + 1));
|
|
296
|
+
if (bits > 53) {
|
|
297
|
+
throw new Error(`E57: ScaledInteger field "${field.name}" needs ${bits} bits — exceeds the 53-bit Number-precision limit`);
|
|
298
|
+
}
|
|
299
|
+
return Math.max(1, bits);
|
|
300
|
+
}
|
|
301
|
+
/** Float / Integer / ScaledInteger → max points that fit in `lengthBytes`. */
|
|
302
|
+
function floatOrSiPointCapacity(field, lengthBytes) {
|
|
303
|
+
if (field.kind === 'Float') {
|
|
304
|
+
const byteSize = field.precision === 'single' ? 4 : 8;
|
|
305
|
+
return Math.floor(lengthBytes / byteSize);
|
|
306
|
+
}
|
|
307
|
+
if (field.kind === 'ScaledInteger') {
|
|
308
|
+
const bits = scaledIntegerBitsPerRecord(field);
|
|
309
|
+
return Math.floor((lengthBytes * 8) / bits);
|
|
310
|
+
}
|
|
311
|
+
// Integer: same width selection as writeColorChannel.
|
|
312
|
+
const min = field.minimum ?? 0;
|
|
313
|
+
const max = field.maximum ?? 255;
|
|
314
|
+
const widest = Math.max(Math.abs(min), Math.abs(max));
|
|
315
|
+
const byteSize = widest > 255 ? 2 : 1;
|
|
316
|
+
return Math.floor(lengthBytes / byteSize);
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Read `bitsPerRecord` bits starting at `bitOffset` from `bytes`,
|
|
320
|
+
* LSB-first within each byte (E57 spec convention). Uses
|
|
321
|
+
* `Math.pow(2, n)` instead of `<< n` to keep precision up to 53 bits.
|
|
322
|
+
*/
|
|
323
|
+
function readBitsLE(bytes, bitOffset, bitsPerRecord) {
|
|
324
|
+
let value = 0;
|
|
325
|
+
let bitsRead = 0;
|
|
326
|
+
let cur = bitOffset >>> 3;
|
|
327
|
+
let inByte = bitOffset & 7;
|
|
328
|
+
while (bitsRead < bitsPerRecord) {
|
|
329
|
+
const avail = 8 - inByte;
|
|
330
|
+
const take = Math.min(avail, bitsPerRecord - bitsRead);
|
|
331
|
+
const mask = (1 << take) - 1;
|
|
332
|
+
const piece = (bytes[cur] >>> inByte) & mask;
|
|
333
|
+
value += piece * Math.pow(2, bitsRead);
|
|
334
|
+
bitsRead += take;
|
|
335
|
+
inByte = 0;
|
|
336
|
+
cur++;
|
|
337
|
+
}
|
|
338
|
+
return value;
|
|
339
|
+
}
|
|
340
|
+
function finalize(positions, colors, intensities, classifications, pointCount) {
|
|
341
|
+
return {
|
|
342
|
+
positions: new Float32Array(positions),
|
|
343
|
+
colors: colors ? new Float32Array(colors) : undefined,
|
|
344
|
+
intensities: intensities ? new Uint16Array(intensities) : undefined,
|
|
345
|
+
classifications: classifications ? new Uint8Array(classifications) : undefined,
|
|
346
|
+
pointCount,
|
|
347
|
+
bbox: computeBBox(positions),
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Read N classification samples from a bytestream into a Uint8Array.
|
|
352
|
+
* Handles the two encodings real exporters use: plain Integer (u8 /
|
|
353
|
+
* u16 picked from declared range) and ScaledInteger (bit-packed).
|
|
354
|
+
* Values are clamped into the u8 range — ASPRS LAS 1.4 only defines
|
|
355
|
+
* up to class 18, so >255 is meaningless but we don't error on it.
|
|
356
|
+
*/
|
|
357
|
+
function readClassificationStream(bytes, view, field, start, classifications, written, take) {
|
|
358
|
+
if (field.kind === 'Integer') {
|
|
359
|
+
const min = field.minimum ?? 0;
|
|
360
|
+
const max = field.maximum ?? 255;
|
|
361
|
+
const widest = Math.max(Math.abs(min), Math.abs(max));
|
|
362
|
+
const stride = widest > 255 ? 2 : 1;
|
|
363
|
+
const signed = min < 0;
|
|
364
|
+
for (let i = 0; i < take; i++) {
|
|
365
|
+
const off = start + i * stride;
|
|
366
|
+
const raw = stride === 2
|
|
367
|
+
? (signed ? view.getInt16(off, true) : view.getUint16(off, true))
|
|
368
|
+
: (signed ? view.getInt8(off) : view.getUint8(off));
|
|
369
|
+
// Class IDs are absolute labels (ASPRS LAS 1.4 0..31), not
|
|
370
|
+
// range-normalised offsets. The raw byte IS the class — don't
|
|
371
|
+
// subtract `minimum`. Mirrors the ScaledInteger branch below
|
|
372
|
+
// which uses `raw + minimum` to recover the original value.
|
|
373
|
+
classifications[written + i] = Math.max(0, Math.min(255, raw));
|
|
374
|
+
}
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
// ScaledInteger: classification is conceptually an integer but
|
|
378
|
+
// some exporters declare a scale anyway. Reader the raw bits and
|
|
379
|
+
// ignore scale/offset (no real meaning for class IDs).
|
|
380
|
+
const bitsPerRecord = scaledIntegerBitsPerRecord(field);
|
|
381
|
+
const minimum = field.minimum ?? 0;
|
|
382
|
+
const startBit = start * 8;
|
|
383
|
+
for (let i = 0; i < take; i++) {
|
|
384
|
+
const raw = readBitsLE(bytes, startBit + i * bitsPerRecord, bitsPerRecord);
|
|
385
|
+
classifications[written + i] = Math.max(0, Math.min(255, raw + minimum));
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
function clamp01(v) {
|
|
389
|
+
return v < 0 ? 0 : v > 1 ? 1 : v;
|
|
390
|
+
}
|
|
391
|
+
export function computeBBox(positions) {
|
|
392
|
+
// Empty / non-aligned input yields ±Infinity bounds, which poisons
|
|
393
|
+
// camera fit-to-view and section-plane math downstream. Return a
|
|
394
|
+
// finite zero-bbox instead.
|
|
395
|
+
if (positions.length < 3) {
|
|
396
|
+
return { min: [0, 0, 0], max: [0, 0, 0] };
|
|
397
|
+
}
|
|
398
|
+
let minX = Infinity, minY = Infinity, minZ = Infinity;
|
|
399
|
+
let maxX = -Infinity, maxY = -Infinity, maxZ = -Infinity;
|
|
400
|
+
let any = false;
|
|
401
|
+
for (let i = 0; i + 2 < positions.length; i += 3) {
|
|
402
|
+
const x = positions[i], y = positions[i + 1], z = positions[i + 2];
|
|
403
|
+
// Skip non-finite coords rather than letting them poison the bbox.
|
|
404
|
+
// A single NaN/Infinity from a corrupt scan would otherwise propagate.
|
|
405
|
+
if (!Number.isFinite(x) || !Number.isFinite(y) || !Number.isFinite(z))
|
|
406
|
+
continue;
|
|
407
|
+
any = true;
|
|
408
|
+
if (x < minX)
|
|
409
|
+
minX = x;
|
|
410
|
+
if (x > maxX)
|
|
411
|
+
maxX = x;
|
|
412
|
+
if (y < minY)
|
|
413
|
+
minY = y;
|
|
414
|
+
if (y > maxY)
|
|
415
|
+
maxY = y;
|
|
416
|
+
if (z < minZ)
|
|
417
|
+
minZ = z;
|
|
418
|
+
if (z > maxZ)
|
|
419
|
+
maxZ = z;
|
|
420
|
+
}
|
|
421
|
+
if (!any)
|
|
422
|
+
return { min: [0, 0, 0], max: [0, 0, 0] };
|
|
423
|
+
return { min: [minX, minY, minZ], max: [maxX, maxY, maxZ] };
|
|
424
|
+
}
|
|
425
|
+
//# sourceMappingURL=e57-decode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e57-decode.js","sourceRoot":"","sources":["../../src/formats/e57-decode.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface E57FileHeader {
|
|
2
|
+
majorVersion: number;
|
|
3
|
+
minorVersion: number;
|
|
4
|
+
fileLogicalSize: number;
|
|
5
|
+
xmlLogicalOffset: number;
|
|
6
|
+
xmlLogicalLength: number;
|
|
7
|
+
pageSize: number;
|
|
8
|
+
}
|
|
9
|
+
/** Read the 48-byte FileHeader. Throws on bad magic. */
|
|
10
|
+
export declare function parseE57FileHeader(bytes: Uint8Array): E57FileHeader;
|
|
11
|
+
/**
|
|
12
|
+
* Strip the 4-byte CRC tail from each `pageSize`-byte physical page.
|
|
13
|
+
*
|
|
14
|
+
* Returns a freshly-allocated buffer of "logical" bytes — the form that
|
|
15
|
+
* XML offsets and CompressedVector data offsets reference.
|
|
16
|
+
*
|
|
17
|
+
* `pageSize` is read from the header and is conventionally 1024.
|
|
18
|
+
*/
|
|
19
|
+
export declare function stripPageCrc(bytes: Uint8Array, pageSize: number): Uint8Array;
|
|
20
|
+
/** Convert a physical (CRC-paged) offset to the equivalent logical offset. */
|
|
21
|
+
export declare function physicalToLogical(physical: number, pageSize: number): number;
|
|
22
|
+
/**
|
|
23
|
+
* Read a CompressedVector binary-section header (E57 spec §6.4.2) and
|
|
24
|
+
* return the LOGICAL byte offset where its DataPackets actually start.
|
|
25
|
+
*
|
|
26
|
+
* Layout (32 bytes):
|
|
27
|
+
* [ 0] u8 sectionId (must == 1 for CompressedVector)
|
|
28
|
+
* [ 1] u8[7] reserved
|
|
29
|
+
* [ 8] u64 LE sectionLogicalLength
|
|
30
|
+
* [16] u64 LE dataPhysicalOffset
|
|
31
|
+
* [24] u64 LE indexPhysicalOffset
|
|
32
|
+
*
|
|
33
|
+
* The XML's `points@fileOffset` points at this section header — NOT at
|
|
34
|
+
* the first DataPacket. Reading packets straight at `fileOffset` puts
|
|
35
|
+
* the parser ~32 bytes off and the first u16 it reads is the low half
|
|
36
|
+
* of `sectionLogicalLength`, which usually decodes as a bytestreamCount
|
|
37
|
+
* of 0 (matched the user-reported `bytestreamCount (0) ≠ prototype
|
|
38
|
+
* length (7)` error exactly).
|
|
39
|
+
*/
|
|
40
|
+
export declare function resolveCompressedVectorDataOffset(logical: Uint8Array, physicalSectionOffset: number, pageSize: number): number;
|
|
41
|
+
export declare function readU64LE(view: DataView, offset: number): number;
|
|
42
|
+
//# sourceMappingURL=e57-page.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e57-page.d.ts","sourceRoot":"","sources":["../../src/formats/e57-page.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wDAAwD;AACxD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,GAAG,aAAa,CAiBnE;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,UAAU,CAoB5E;AAED,8EAA8E;AAC9E,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAK5E;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iCAAiC,CAC/C,OAAO,EAAE,UAAU,EACnB,qBAAqB,EAAE,MAAM,EAC7B,QAAQ,EAAE,MAAM,GACf,MAAM,CAgBR;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAIhE"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/**
|
|
5
|
+
* E57 file header + page-CRC handling.
|
|
6
|
+
*
|
|
7
|
+
* The file is divided into `pageSize`-byte physical pages, each
|
|
8
|
+
* carrying a 4-byte CRC32-C tail. XML offsets and binary-section
|
|
9
|
+
* offsets in the XML reference the LOGICAL byte stream — i.e. with
|
|
10
|
+
* those CRC tails stripped. Everything in this module helps callers
|
|
11
|
+
* convert between the two views.
|
|
12
|
+
*/
|
|
13
|
+
const E57_MAGIC = 'ASTM-E57';
|
|
14
|
+
/** Read the 48-byte FileHeader. Throws on bad magic. */
|
|
15
|
+
export function parseE57FileHeader(bytes) {
|
|
16
|
+
if (bytes.length < 48)
|
|
17
|
+
throw new Error('E57: header truncated (need 48 bytes)');
|
|
18
|
+
const magic = String.fromCharCode(...bytes.subarray(0, 8));
|
|
19
|
+
if (magic !== E57_MAGIC) {
|
|
20
|
+
throw new Error(`E57: bad magic "${magic}" (expected "${E57_MAGIC}")`);
|
|
21
|
+
}
|
|
22
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
23
|
+
return {
|
|
24
|
+
majorVersion: view.getUint32(8, true),
|
|
25
|
+
minorVersion: view.getUint32(12, true),
|
|
26
|
+
fileLogicalSize: readU64LE(view, 16),
|
|
27
|
+
// Physical XML offset → we convert to logical below; xmlLogicalLength
|
|
28
|
+
// is the byte length AFTER stripping page CRCs.
|
|
29
|
+
xmlLogicalOffset: physicalToLogical(readU64LE(view, 24), readU64LE(view, 40)),
|
|
30
|
+
xmlLogicalLength: readU64LE(view, 32),
|
|
31
|
+
pageSize: readU64LE(view, 40),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Strip the 4-byte CRC tail from each `pageSize`-byte physical page.
|
|
36
|
+
*
|
|
37
|
+
* Returns a freshly-allocated buffer of "logical" bytes — the form that
|
|
38
|
+
* XML offsets and CompressedVector data offsets reference.
|
|
39
|
+
*
|
|
40
|
+
* `pageSize` is read from the header and is conventionally 1024.
|
|
41
|
+
*/
|
|
42
|
+
export function stripPageCrc(bytes, pageSize) {
|
|
43
|
+
if (pageSize <= 4)
|
|
44
|
+
throw new Error('E57: pageSize too small');
|
|
45
|
+
const payloadPerPage = pageSize - 4;
|
|
46
|
+
const fullPages = Math.floor(bytes.length / pageSize);
|
|
47
|
+
const tail = bytes.length - fullPages * pageSize;
|
|
48
|
+
// Trailing partial page (if any) still carries 4 CRC bytes when complete;
|
|
49
|
+
// when the file ends mid-page we can't trust those tail bytes, so we
|
|
50
|
+
// stop at the last complete page boundary.
|
|
51
|
+
const out = new Uint8Array(fullPages * payloadPerPage + Math.max(0, tail - 4));
|
|
52
|
+
let dst = 0;
|
|
53
|
+
for (let p = 0; p < fullPages; p++) {
|
|
54
|
+
const src = p * pageSize;
|
|
55
|
+
out.set(bytes.subarray(src, src + payloadPerPage), dst);
|
|
56
|
+
dst += payloadPerPage;
|
|
57
|
+
}
|
|
58
|
+
if (tail > 4) {
|
|
59
|
+
const src = fullPages * pageSize;
|
|
60
|
+
out.set(bytes.subarray(src, src + tail - 4), dst);
|
|
61
|
+
}
|
|
62
|
+
return out;
|
|
63
|
+
}
|
|
64
|
+
/** Convert a physical (CRC-paged) offset to the equivalent logical offset. */
|
|
65
|
+
export function physicalToLogical(physical, pageSize) {
|
|
66
|
+
const payloadPerPage = pageSize - 4;
|
|
67
|
+
const pages = Math.floor(physical / pageSize);
|
|
68
|
+
const within = physical - pages * pageSize;
|
|
69
|
+
return pages * payloadPerPage + within;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Read a CompressedVector binary-section header (E57 spec §6.4.2) and
|
|
73
|
+
* return the LOGICAL byte offset where its DataPackets actually start.
|
|
74
|
+
*
|
|
75
|
+
* Layout (32 bytes):
|
|
76
|
+
* [ 0] u8 sectionId (must == 1 for CompressedVector)
|
|
77
|
+
* [ 1] u8[7] reserved
|
|
78
|
+
* [ 8] u64 LE sectionLogicalLength
|
|
79
|
+
* [16] u64 LE dataPhysicalOffset
|
|
80
|
+
* [24] u64 LE indexPhysicalOffset
|
|
81
|
+
*
|
|
82
|
+
* The XML's `points@fileOffset` points at this section header — NOT at
|
|
83
|
+
* the first DataPacket. Reading packets straight at `fileOffset` puts
|
|
84
|
+
* the parser ~32 bytes off and the first u16 it reads is the low half
|
|
85
|
+
* of `sectionLogicalLength`, which usually decodes as a bytestreamCount
|
|
86
|
+
* of 0 (matched the user-reported `bytestreamCount (0) ≠ prototype
|
|
87
|
+
* length (7)` error exactly).
|
|
88
|
+
*/
|
|
89
|
+
export function resolveCompressedVectorDataOffset(logical, physicalSectionOffset, pageSize) {
|
|
90
|
+
const sectionLogical = physicalToLogical(physicalSectionOffset, pageSize);
|
|
91
|
+
if (sectionLogical + 32 > logical.length) {
|
|
92
|
+
throw new Error(`E57: CompressedVector section header at logical ${sectionLogical} runs past end of file (length ${logical.length})`);
|
|
93
|
+
}
|
|
94
|
+
const view = new DataView(logical.buffer, logical.byteOffset + sectionLogical, 32);
|
|
95
|
+
const sectionId = view.getUint8(0);
|
|
96
|
+
if (sectionId !== 1) {
|
|
97
|
+
throw new Error(`E57: expected CompressedVector section (id=1) at physical ${physicalSectionOffset}, got id=${sectionId}`);
|
|
98
|
+
}
|
|
99
|
+
const dataPhysicalOffset = readU64LE(view, 16);
|
|
100
|
+
return physicalToLogical(dataPhysicalOffset, pageSize);
|
|
101
|
+
}
|
|
102
|
+
export function readU64LE(view, offset) {
|
|
103
|
+
const lo = view.getUint32(offset, true);
|
|
104
|
+
const hi = view.getUint32(offset + 4, true);
|
|
105
|
+
return hi * 0x100000000 + lo;
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=e57-page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e57-page.js","sourceRoot":"","sources":["../../src/formats/e57-page.ts"],"names":[],"mappings":"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"}
|