@ifc-lite/pointcloud 0.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/LICENSE +373 -0
- package/README.md +26 -0
- package/dist/formats/e57.d.ts +129 -0
- package/dist/formats/e57.d.ts.map +1 -0
- package/dist/formats/e57.js +495 -0
- package/dist/formats/e57.js.map +1 -0
- package/dist/formats/ifcx-points.d.ts +26 -0
- package/dist/formats/ifcx-points.d.ts.map +1 -0
- package/dist/formats/ifcx-points.js +134 -0
- package/dist/formats/ifcx-points.js.map +1 -0
- package/dist/formats/las.d.ts +54 -0
- package/dist/formats/las.d.ts.map +1 -0
- package/dist/formats/las.js +203 -0
- package/dist/formats/las.js.map +1 -0
- package/dist/formats/pcd.d.ts +3 -0
- package/dist/formats/pcd.d.ts.map +1 -0
- package/dist/formats/pcd.js +302 -0
- package/dist/formats/pcd.js.map +1 -0
- package/dist/formats/ply.d.ts +40 -0
- package/dist/formats/ply.d.ts.map +1 -0
- package/dist/formats/ply.js +250 -0
- package/dist/formats/ply.js.map +1 -0
- package/dist/from-ifcx-attributes.d.ts +10 -0
- package/dist/from-ifcx-attributes.d.ts.map +1 -0
- package/dist/from-ifcx-attributes.js +49 -0
- package/dist/from-ifcx-attributes.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/lzf.d.ts +10 -0
- package/dist/lzf.d.ts.map +1 -0
- package/dist/lzf.js +64 -0
- package/dist/lzf.js.map +1 -0
- package/dist/streaming/blob-source.d.ts +15 -0
- package/dist/streaming/blob-source.d.ts.map +1 -0
- package/dist/streaming/blob-source.js +30 -0
- package/dist/streaming/blob-source.js.map +1 -0
- package/dist/streaming/decode-worker.d.ts +2 -0
- package/dist/streaming/decode-worker.d.ts.map +1 -0
- package/dist/streaming/decode-worker.js +131 -0
- package/dist/streaming/decode-worker.js.map +1 -0
- package/dist/streaming/e57-source.d.ts +17 -0
- package/dist/streaming/e57-source.d.ts.map +1 -0
- package/dist/streaming/e57-source.js +83 -0
- package/dist/streaming/e57-source.js.map +1 -0
- package/dist/streaming/host.d.ts +54 -0
- package/dist/streaming/host.d.ts.map +1 -0
- package/dist/streaming/host.js +120 -0
- package/dist/streaming/host.js.map +1 -0
- package/dist/streaming/las-source.d.ts +28 -0
- package/dist/streaming/las-source.d.ts.map +1 -0
- package/dist/streaming/las-source.js +117 -0
- package/dist/streaming/las-source.js.map +1 -0
- package/dist/streaming/laz-source.d.ts +35 -0
- package/dist/streaming/laz-source.d.ts.map +1 -0
- package/dist/streaming/laz-source.js +205 -0
- package/dist/streaming/laz-source.js.map +1 -0
- package/dist/streaming/pcd-source.d.ts +25 -0
- package/dist/streaming/pcd-source.d.ts.map +1 -0
- package/dist/streaming/pcd-source.js +86 -0
- package/dist/streaming/pcd-source.js.map +1 -0
- package/dist/streaming/ply-source.d.ts +26 -0
- package/dist/streaming/ply-source.d.ts.map +1 -0
- package/dist/streaming/ply-source.js +98 -0
- package/dist/streaming/ply-source.js.map +1 -0
- package/dist/streaming/protocol.d.ts +62 -0
- package/dist/streaming/protocol.d.ts.map +1 -0
- package/dist/streaming/protocol.js +45 -0
- package/dist/streaming/protocol.js.map +1 -0
- package/dist/streaming/types.d.ts +41 -0
- package/dist/streaming/types.d.ts.map +1 -0
- package/dist/streaming/types.js +5 -0
- package/dist/streaming/types.js.map +1 -0
- package/dist/streaming/worker-client.d.ts +20 -0
- package/dist/streaming/worker-client.d.ts.map +1 -0
- package/dist/streaming/worker-client.js +152 -0
- package/dist/streaming/worker-client.js.map +1 -0
- package/dist/types.d.ts +36 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/xml-mini.d.ts +29 -0
- package/dist/xml-mini.d.ts.map +1 -0
- package/dist/xml-mini.js +181 -0
- package/dist/xml-mini.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,495 @@
|
|
|
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 { childByName, childrenByName, parseXml, textChild, } from '../xml-mini.js';
|
|
5
|
+
const E57_MAGIC = 'ASTM-E57';
|
|
6
|
+
/** Read the 48-byte FileHeader. Throws on bad magic. */
|
|
7
|
+
export function parseE57FileHeader(bytes) {
|
|
8
|
+
if (bytes.length < 48)
|
|
9
|
+
throw new Error('E57: header truncated (need 48 bytes)');
|
|
10
|
+
const magic = String.fromCharCode(...bytes.subarray(0, 8));
|
|
11
|
+
if (magic !== E57_MAGIC) {
|
|
12
|
+
throw new Error(`E57: bad magic "${magic}" (expected "${E57_MAGIC}")`);
|
|
13
|
+
}
|
|
14
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
15
|
+
return {
|
|
16
|
+
majorVersion: view.getUint32(8, true),
|
|
17
|
+
minorVersion: view.getUint32(12, true),
|
|
18
|
+
fileLogicalSize: readU64LE(view, 16),
|
|
19
|
+
// Physical XML offset → we convert to logical below; xmlLogicalLength
|
|
20
|
+
// is the byte length AFTER stripping page CRCs.
|
|
21
|
+
xmlLogicalOffset: physicalToLogical(readU64LE(view, 24), readU64LE(view, 40)),
|
|
22
|
+
xmlLogicalLength: readU64LE(view, 32),
|
|
23
|
+
pageSize: readU64LE(view, 40),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Strip the 4-byte CRC tail from each `pageSize`-byte physical page.
|
|
28
|
+
*
|
|
29
|
+
* Returns a freshly-allocated buffer of "logical" bytes — the form that
|
|
30
|
+
* XML offsets and CompressedVector data offsets reference.
|
|
31
|
+
*
|
|
32
|
+
* `pageSize` is read from the header and is conventionally 1024.
|
|
33
|
+
*/
|
|
34
|
+
export function stripPageCrc(bytes, pageSize) {
|
|
35
|
+
if (pageSize <= 4)
|
|
36
|
+
throw new Error('E57: pageSize too small');
|
|
37
|
+
const payloadPerPage = pageSize - 4;
|
|
38
|
+
const fullPages = Math.floor(bytes.length / pageSize);
|
|
39
|
+
const tail = bytes.length - fullPages * pageSize;
|
|
40
|
+
// Trailing partial page (if any) still carries 4 CRC bytes when complete;
|
|
41
|
+
// when the file ends mid-page we can't trust those tail bytes, so we
|
|
42
|
+
// stop at the last complete page boundary.
|
|
43
|
+
const out = new Uint8Array(fullPages * payloadPerPage + Math.max(0, tail - 4));
|
|
44
|
+
let dst = 0;
|
|
45
|
+
for (let p = 0; p < fullPages; p++) {
|
|
46
|
+
const src = p * pageSize;
|
|
47
|
+
out.set(bytes.subarray(src, src + payloadPerPage), dst);
|
|
48
|
+
dst += payloadPerPage;
|
|
49
|
+
}
|
|
50
|
+
if (tail > 4) {
|
|
51
|
+
const src = fullPages * pageSize;
|
|
52
|
+
out.set(bytes.subarray(src, src + tail - 4), dst);
|
|
53
|
+
}
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
56
|
+
/** Convert a physical (CRC-paged) offset to the equivalent logical offset. */
|
|
57
|
+
function physicalToLogical(physical, pageSize) {
|
|
58
|
+
const payloadPerPage = pageSize - 4;
|
|
59
|
+
const pages = Math.floor(physical / pageSize);
|
|
60
|
+
const within = physical - pages * pageSize;
|
|
61
|
+
return pages * payloadPerPage + within;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Read a CompressedVector binary-section header (E57 spec §6.4.2) and
|
|
65
|
+
* return the LOGICAL byte offset where its DataPackets actually start.
|
|
66
|
+
*
|
|
67
|
+
* Layout (32 bytes):
|
|
68
|
+
* [ 0] u8 sectionId (must == 1 for CompressedVector)
|
|
69
|
+
* [ 1] u8[7] reserved
|
|
70
|
+
* [ 8] u64 LE sectionLogicalLength
|
|
71
|
+
* [16] u64 LE dataPhysicalOffset
|
|
72
|
+
* [24] u64 LE indexPhysicalOffset
|
|
73
|
+
*
|
|
74
|
+
* The XML's `points@fileOffset` points at this section header — NOT at
|
|
75
|
+
* the first DataPacket. Reading packets straight at `fileOffset` puts
|
|
76
|
+
* the parser ~32 bytes off and the first u16 it reads is the low half
|
|
77
|
+
* of `sectionLogicalLength`, which usually decodes as a bytestreamCount
|
|
78
|
+
* of 0 (matched the user-reported `bytestreamCount (0) ≠ prototype
|
|
79
|
+
* length (7)` error exactly).
|
|
80
|
+
*/
|
|
81
|
+
export function resolveCompressedVectorDataOffset(logical, physicalSectionOffset, pageSize) {
|
|
82
|
+
const sectionLogical = physicalToLogical(physicalSectionOffset, pageSize);
|
|
83
|
+
if (sectionLogical + 32 > logical.length) {
|
|
84
|
+
throw new Error(`E57: CompressedVector section header at logical ${sectionLogical} runs past end of file (length ${logical.length})`);
|
|
85
|
+
}
|
|
86
|
+
const view = new DataView(logical.buffer, logical.byteOffset + sectionLogical, 32);
|
|
87
|
+
const sectionId = view.getUint8(0);
|
|
88
|
+
if (sectionId !== 1) {
|
|
89
|
+
throw new Error(`E57: expected CompressedVector section (id=1) at physical ${physicalSectionOffset}, got id=${sectionId}`);
|
|
90
|
+
}
|
|
91
|
+
const dataPhysicalOffset = readU64LE(view, 16);
|
|
92
|
+
return physicalToLogical(dataPhysicalOffset, pageSize);
|
|
93
|
+
}
|
|
94
|
+
const TEXT_DECODER = new TextDecoder();
|
|
95
|
+
/**
|
|
96
|
+
* Parse the E57 XML section.
|
|
97
|
+
*
|
|
98
|
+
* Uses our own minimal SAX-style parser (`xml-mini.ts`) instead of
|
|
99
|
+
* `DOMParser` because dedicated Web Workers — where the decode runs —
|
|
100
|
+
* don't expose DOMParser. The shape we need (e57Root → data3D →
|
|
101
|
+
* vectorChild → prototype) is shallow and attribute-heavy, well within
|
|
102
|
+
* the mini parser's scope.
|
|
103
|
+
*/
|
|
104
|
+
export function parseE57Xml(xmlText) {
|
|
105
|
+
const root = parseXml(xmlText);
|
|
106
|
+
if (root.name !== 'e57Root') {
|
|
107
|
+
throw new Error(`E57: XML root is not <e57Root> (saw <${root.name || '?'}>)`);
|
|
108
|
+
}
|
|
109
|
+
const data3D = childByName(root, 'data3D');
|
|
110
|
+
if (!data3D)
|
|
111
|
+
return [];
|
|
112
|
+
const entries = [];
|
|
113
|
+
for (const scan of childrenByName(data3D, 'vectorChild')) {
|
|
114
|
+
const points = childByName(scan, 'points');
|
|
115
|
+
if (!points)
|
|
116
|
+
continue;
|
|
117
|
+
if (points.attrs.get('type') !== 'CompressedVector') {
|
|
118
|
+
// Skip non-compressed-vector points (rare).
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
const fileOffsetAttr = points.attrs.get('fileOffset');
|
|
122
|
+
const recordCountAttr = points.attrs.get('recordCount');
|
|
123
|
+
if (!fileOffsetAttr || !recordCountAttr)
|
|
124
|
+
continue;
|
|
125
|
+
const proto = childByName(points, 'prototype');
|
|
126
|
+
if (!proto)
|
|
127
|
+
continue;
|
|
128
|
+
const fields = [];
|
|
129
|
+
for (const f of proto.children) {
|
|
130
|
+
const type = f.attrs.get('type') ?? '';
|
|
131
|
+
if (type === 'Float') {
|
|
132
|
+
fields.push({
|
|
133
|
+
name: f.name,
|
|
134
|
+
kind: 'Float',
|
|
135
|
+
precision: f.attrs.get('precision') === 'single' ? 'single' : 'double',
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
else if (type === 'ScaledInteger') {
|
|
139
|
+
fields.push({
|
|
140
|
+
name: f.name,
|
|
141
|
+
kind: 'ScaledInteger',
|
|
142
|
+
scale: Number(f.attrs.get('scale') ?? '1'),
|
|
143
|
+
offset: Number(f.attrs.get('offset') ?? '0'),
|
|
144
|
+
minimum: Number(f.attrs.get('minimum') ?? '0'),
|
|
145
|
+
maximum: Number(f.attrs.get('maximum') ?? '0'),
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
else if (type === 'Integer') {
|
|
149
|
+
fields.push({
|
|
150
|
+
name: f.name,
|
|
151
|
+
kind: 'Integer',
|
|
152
|
+
minimum: Number(f.attrs.get('minimum') ?? '0'),
|
|
153
|
+
maximum: Number(f.attrs.get('maximum') ?? '0'),
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
// Other types (e.g. String) ignored — never carry point data.
|
|
157
|
+
}
|
|
158
|
+
entries.push({
|
|
159
|
+
guid: textChild(scan, 'guid') ?? '',
|
|
160
|
+
name: textChild(scan, 'name') ?? undefined,
|
|
161
|
+
recordCount: Number(recordCountAttr),
|
|
162
|
+
binaryFileOffset: Number(fileOffsetAttr),
|
|
163
|
+
prototype: fields,
|
|
164
|
+
hasPose: childByName(scan, 'pose') !== null,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
return entries;
|
|
168
|
+
}
|
|
169
|
+
// ─── binary decode ──────────────────────────────────────────────────────────
|
|
170
|
+
/**
|
|
171
|
+
* Decode the binary section starting at `entry.binaryFileOffset` in the
|
|
172
|
+
* logical-bytes view. NOTE: `binaryFileOffset` here must already point
|
|
173
|
+
* at the first DataPacket (i.e. AFTER the 32-byte CompressedVector
|
|
174
|
+
* section header) — `decodeE57` does this conversion via
|
|
175
|
+
* `resolveCompressedVectorDataOffset`. Callers passing the raw XML
|
|
176
|
+
* offset directly will see a "bytestreamCount ≠ prototype length"
|
|
177
|
+
* mismatch.
|
|
178
|
+
*
|
|
179
|
+
* Returns one DecodedPointChunk per scan; caller can concatenate or
|
|
180
|
+
* emit them as separate streaming chunks.
|
|
181
|
+
*
|
|
182
|
+
* Limitations (Phase-1 E57):
|
|
183
|
+
* - Only Float (single/double) prototype fields are decoded. Files
|
|
184
|
+
* using ScaledInteger throw a clear error so the host can fall back
|
|
185
|
+
* gracefully.
|
|
186
|
+
* - Reads only cartesianX/Y/Z + colorRed/Green/Blue + intensity when
|
|
187
|
+
* present. Other fields are honoured for stride math but discarded.
|
|
188
|
+
*/
|
|
189
|
+
export function decodeE57Scan(logical, entry) {
|
|
190
|
+
const xField = findField(entry.prototype, 'cartesianX');
|
|
191
|
+
const yField = findField(entry.prototype, 'cartesianY');
|
|
192
|
+
const zField = findField(entry.prototype, 'cartesianZ');
|
|
193
|
+
if (!xField || !yField || !zField) {
|
|
194
|
+
throw new Error('E57: prototype missing cartesianX/Y/Z');
|
|
195
|
+
}
|
|
196
|
+
for (const f of [xField, yField, zField]) {
|
|
197
|
+
if (f.kind !== 'Float') {
|
|
198
|
+
throw new Error(`E57: cartesianX/Y/Z encoded as ${f.kind} (only Float supported in this build)`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
const rField = findField(entry.prototype, 'colorRed');
|
|
202
|
+
const gField = findField(entry.prototype, 'colorGreen');
|
|
203
|
+
const bField = findField(entry.prototype, 'colorBlue');
|
|
204
|
+
const hasRgb = !!(rField && gField && bField);
|
|
205
|
+
const iField = findField(entry.prototype, 'intensity');
|
|
206
|
+
// Bit-packed (ScaledInteger) intensity isn't supported yet — surface
|
|
207
|
+
// the limitation explicitly rather than silently dropping it.
|
|
208
|
+
if (iField && iField.kind === 'ScaledInteger') {
|
|
209
|
+
throw new Error('E57: intensity encoded as ScaledInteger (bit-packed integer codec not yet supported)');
|
|
210
|
+
}
|
|
211
|
+
const positions = new Float32Array(entry.recordCount * 3);
|
|
212
|
+
const colors = hasRgb ? new Float32Array(entry.recordCount * 3) : undefined;
|
|
213
|
+
// Allocate intensity buffer for both Float and Integer kinds — only
|
|
214
|
+
// ScaledInteger is unsupported (rejected above). Otherwise
|
|
215
|
+
// Integer-encoded intensity (common with u16-range producers) was
|
|
216
|
+
// silently dropped.
|
|
217
|
+
const intensities = iField && (iField.kind === 'Float' || iField.kind === 'Integer')
|
|
218
|
+
? new Uint16Array(entry.recordCount)
|
|
219
|
+
: undefined;
|
|
220
|
+
// Walk DataPackets starting at binaryFileOffset.
|
|
221
|
+
// Packet header (4 bytes):
|
|
222
|
+
// byte 0: packetType (1=data, 2=index, 3=empty)
|
|
223
|
+
// byte 1: packetFlags (bit 0 = compressorRestart)
|
|
224
|
+
// bytes 2..3: packetLogicalLength - 1 (LE u16; total packet bytes minus 1)
|
|
225
|
+
// Followed by per-bytestream sections, then 4-byte CRC at the end of
|
|
226
|
+
// each packet (already part of the page-level CRC strip — packet CRCs
|
|
227
|
+
// sit in the LOGICAL stream and we ignore them here for speed).
|
|
228
|
+
let offset = entry.binaryFileOffset;
|
|
229
|
+
const view = new DataView(logical.buffer, logical.byteOffset, logical.byteLength);
|
|
230
|
+
let written = 0;
|
|
231
|
+
while (written < entry.recordCount && offset < logical.length) {
|
|
232
|
+
if (offset + 4 > logical.length) {
|
|
233
|
+
throw new Error('E57: truncated DataPacket header');
|
|
234
|
+
}
|
|
235
|
+
const packetType = view.getUint8(offset);
|
|
236
|
+
// packetFlags = view.getUint8(offset + 1) // unused for plain data
|
|
237
|
+
const packetLogicalLength = view.getUint16(offset + 2, true) + 1;
|
|
238
|
+
if (packetType !== 1) {
|
|
239
|
+
// Skip non-data packets (index/empty); they may appear interleaved.
|
|
240
|
+
offset += packetLogicalLength;
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
const packetEnd = offset + packetLogicalLength;
|
|
244
|
+
if (packetEnd > logical.length) {
|
|
245
|
+
throw new Error('E57: DataPacket runs past end of logical bytes');
|
|
246
|
+
}
|
|
247
|
+
// Data packet header beyond the common 4 bytes:
|
|
248
|
+
// byte 4..5: bytestreamCount (u16 LE)
|
|
249
|
+
// then `bytestreamCount` × u16 LE = bytestreamByteCount[]
|
|
250
|
+
// then payload (concatenated bytestreams, in prototype order)
|
|
251
|
+
const bytestreamCount = view.getUint16(offset + 4, true);
|
|
252
|
+
if (bytestreamCount !== entry.prototype.length) {
|
|
253
|
+
throw new Error(`E57: packet bytestreamCount (${bytestreamCount}) ≠ prototype length (${entry.prototype.length})`);
|
|
254
|
+
}
|
|
255
|
+
const bytestreamLengths = [];
|
|
256
|
+
let cursor = offset + 6;
|
|
257
|
+
for (let i = 0; i < bytestreamCount; i++) {
|
|
258
|
+
bytestreamLengths.push(view.getUint16(cursor, true));
|
|
259
|
+
cursor += 2;
|
|
260
|
+
}
|
|
261
|
+
// CRC at packet tail (4 bytes) — ignored.
|
|
262
|
+
const packetPointsBefore = written;
|
|
263
|
+
const fieldOffsets = new Map();
|
|
264
|
+
let streamCursor = cursor;
|
|
265
|
+
for (let i = 0; i < bytestreamCount; i++) {
|
|
266
|
+
fieldOffsets.set(entry.prototype[i].name, { start: streamCursor, length: bytestreamLengths[i] });
|
|
267
|
+
streamCursor += bytestreamLengths[i];
|
|
268
|
+
}
|
|
269
|
+
// Decode this packet's points
|
|
270
|
+
const xByteSize = xField.precision === 'single' ? 4 : 8;
|
|
271
|
+
const yByteSize = yField.precision === 'single' ? 4 : 8;
|
|
272
|
+
const zByteSize = zField.precision === 'single' ? 4 : 8;
|
|
273
|
+
const pointsInPacket = Math.floor((fieldOffsets.get('cartesianX').length) / xByteSize);
|
|
274
|
+
if (pointsInPacket !== Math.floor(fieldOffsets.get('cartesianY').length / yByteSize)
|
|
275
|
+
|| pointsInPacket !== Math.floor(fieldOffsets.get('cartesianZ').length / zByteSize)) {
|
|
276
|
+
throw new Error('E57: cartesianX/Y/Z bytestream lengths disagree on point count');
|
|
277
|
+
}
|
|
278
|
+
const take = Math.min(pointsInPacket, entry.recordCount - written);
|
|
279
|
+
const xStart = fieldOffsets.get('cartesianX').start;
|
|
280
|
+
const yStart = fieldOffsets.get('cartesianY').start;
|
|
281
|
+
const zStart = fieldOffsets.get('cartesianZ').start;
|
|
282
|
+
if (xField.precision === 'single') {
|
|
283
|
+
for (let i = 0; i < take; i++) {
|
|
284
|
+
positions[(written + i) * 3] = view.getFloat32(xStart + i * 4, true);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
for (let i = 0; i < take; i++) {
|
|
289
|
+
positions[(written + i) * 3] = view.getFloat64(xStart + i * 8, true);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
if (yField.precision === 'single') {
|
|
293
|
+
for (let i = 0; i < take; i++) {
|
|
294
|
+
positions[(written + i) * 3 + 1] = view.getFloat32(yStart + i * 4, true);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
for (let i = 0; i < take; i++) {
|
|
299
|
+
positions[(written + i) * 3 + 1] = view.getFloat64(yStart + i * 8, true);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
if (zField.precision === 'single') {
|
|
303
|
+
for (let i = 0; i < take; i++) {
|
|
304
|
+
positions[(written + i) * 3 + 2] = view.getFloat32(zStart + i * 4, true);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
for (let i = 0; i < take; i++) {
|
|
309
|
+
positions[(written + i) * 3 + 2] = view.getFloat64(zStart + i * 8, true);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
if (colors && rField && gField && bField) {
|
|
313
|
+
writeColorChannel(view, fieldOffsets.get('colorRed').start, rField, colors, written, take, 0);
|
|
314
|
+
writeColorChannel(view, fieldOffsets.get('colorGreen').start, gField, colors, written, take, 1);
|
|
315
|
+
writeColorChannel(view, fieldOffsets.get('colorBlue').start, bField, colors, written, take, 2);
|
|
316
|
+
}
|
|
317
|
+
if (intensities && iField) {
|
|
318
|
+
const iStart = fieldOffsets.get('intensity').start;
|
|
319
|
+
if (iField.kind === 'Float') {
|
|
320
|
+
const stride = iField.precision === 'single' ? 4 : 8;
|
|
321
|
+
for (let i = 0; i < take; i++) {
|
|
322
|
+
const v = stride === 4 ? view.getFloat32(iStart + i * stride, true) : view.getFloat64(iStart + i * stride, true);
|
|
323
|
+
intensities[written + i] = Math.min(65535, Math.max(0, Math.round(v * 65535)));
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
// Integer-encoded intensity — pick element width from declared
|
|
328
|
+
// range (same logic as the integer color channels).
|
|
329
|
+
const min = iField.minimum ?? 0;
|
|
330
|
+
const max = iField.maximum ?? 65535;
|
|
331
|
+
const span = max - min;
|
|
332
|
+
const inv = span > 0 ? 1 / span : 1;
|
|
333
|
+
const widest = Math.max(Math.abs(min), Math.abs(max));
|
|
334
|
+
const stride = widest > 255 ? 2 : 1;
|
|
335
|
+
const signed = min < 0;
|
|
336
|
+
for (let i = 0; i < take; i++) {
|
|
337
|
+
const off = iStart + i * stride;
|
|
338
|
+
const raw = stride === 2
|
|
339
|
+
? (signed ? view.getInt16(off, true) : view.getUint16(off, true))
|
|
340
|
+
: (signed ? view.getInt8(off) : view.getUint8(off));
|
|
341
|
+
const norm = (raw - min) * inv;
|
|
342
|
+
intensities[written + i] = Math.min(65535, Math.max(0, Math.round(norm * 65535)));
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
written += take;
|
|
347
|
+
void packetPointsBefore;
|
|
348
|
+
offset = packetEnd;
|
|
349
|
+
}
|
|
350
|
+
if (written < entry.recordCount) {
|
|
351
|
+
// Real-world files sometimes report counts a few records higher
|
|
352
|
+
// than what's actually stored; trim positions to the actual count
|
|
353
|
+
// so downstream code doesn't see uninitialised tail values.
|
|
354
|
+
return finalize(positions.subarray(0, written * 3), colors?.subarray(0, written * 3), intensities?.subarray(0, written), written);
|
|
355
|
+
}
|
|
356
|
+
return finalize(positions, colors, intensities, entry.recordCount);
|
|
357
|
+
}
|
|
358
|
+
function writeColorChannel(view, start, field, colors, written, take, channelOffset) {
|
|
359
|
+
if (field.kind === 'Float') {
|
|
360
|
+
const stride = field.precision === 'single' ? 4 : 8;
|
|
361
|
+
for (let i = 0; i < take; i++) {
|
|
362
|
+
const v = stride === 4 ? view.getFloat32(start + i * stride, true) : view.getFloat64(start + i * stride, true);
|
|
363
|
+
colors[(written + i) * 3 + channelOffset] = clamp01(v);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
else if (field.kind === 'Integer') {
|
|
367
|
+
// Pick element width from the declared range. E57 producers use
|
|
368
|
+
// either u8 (0..255 — most common) or u16 (0..65535). Both
|
|
369
|
+
// appear in real files; assuming u8 distorts u16-encoded colors.
|
|
370
|
+
const min = field.minimum ?? 0;
|
|
371
|
+
const max = field.maximum ?? 255;
|
|
372
|
+
const span = max - min;
|
|
373
|
+
const inv = span > 0 ? 1 / span : 1;
|
|
374
|
+
const widest = Math.max(Math.abs(min), Math.abs(max));
|
|
375
|
+
const stride = widest > 255 ? 2 : 1;
|
|
376
|
+
const signed = min < 0;
|
|
377
|
+
for (let i = 0; i < take; i++) {
|
|
378
|
+
const off = start + i * stride;
|
|
379
|
+
const raw = stride === 2
|
|
380
|
+
? (signed ? view.getInt16(off, true) : view.getUint16(off, true))
|
|
381
|
+
: (signed ? view.getInt8(off) : view.getUint8(off));
|
|
382
|
+
colors[(written + i) * 3 + channelOffset] = clamp01((raw - min) * inv);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
throw new Error('E57: ScaledInteger color encoding not yet supported');
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
function finalize(positions, colors, intensities, pointCount) {
|
|
390
|
+
return {
|
|
391
|
+
positions: new Float32Array(positions),
|
|
392
|
+
colors: colors ? new Float32Array(colors) : undefined,
|
|
393
|
+
intensities: intensities ? new Uint16Array(intensities) : undefined,
|
|
394
|
+
pointCount,
|
|
395
|
+
bbox: computeBBox(positions),
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
function findField(proto, name) {
|
|
399
|
+
return proto.find((p) => p.name === name);
|
|
400
|
+
}
|
|
401
|
+
function readU64LE(view, offset) {
|
|
402
|
+
const lo = view.getUint32(offset, true);
|
|
403
|
+
const hi = view.getUint32(offset + 4, true);
|
|
404
|
+
return hi * 0x100000000 + lo;
|
|
405
|
+
}
|
|
406
|
+
function clamp01(v) {
|
|
407
|
+
return v < 0 ? 0 : v > 1 ? 1 : v;
|
|
408
|
+
}
|
|
409
|
+
function computeBBox(positions) {
|
|
410
|
+
let minX = Infinity, minY = Infinity, minZ = Infinity;
|
|
411
|
+
let maxX = -Infinity, maxY = -Infinity, maxZ = -Infinity;
|
|
412
|
+
for (let i = 0; i < positions.length; i += 3) {
|
|
413
|
+
const x = positions[i], y = positions[i + 1], z = positions[i + 2];
|
|
414
|
+
if (x < minX)
|
|
415
|
+
minX = x;
|
|
416
|
+
if (x > maxX)
|
|
417
|
+
maxX = x;
|
|
418
|
+
if (y < minY)
|
|
419
|
+
minY = y;
|
|
420
|
+
if (y > maxY)
|
|
421
|
+
maxY = y;
|
|
422
|
+
if (z < minZ)
|
|
423
|
+
minZ = z;
|
|
424
|
+
if (z > maxZ)
|
|
425
|
+
maxZ = z;
|
|
426
|
+
}
|
|
427
|
+
return { min: [minX, minY, minZ], max: [maxX, maxY, maxZ] };
|
|
428
|
+
}
|
|
429
|
+
// ─── high-level entry ───────────────────────────────────────────────────────
|
|
430
|
+
/**
|
|
431
|
+
* Decode all Data3D scans in an E57 file. Combines them into a single
|
|
432
|
+
* DecodedPointChunk (positions concatenated). Returns null when the
|
|
433
|
+
* file has no scans.
|
|
434
|
+
*/
|
|
435
|
+
export function decodeE57(bytes) {
|
|
436
|
+
const header = parseE57FileHeader(bytes);
|
|
437
|
+
const logical = stripPageCrc(bytes, header.pageSize);
|
|
438
|
+
const xmlBytes = logical.subarray(header.xmlLogicalOffset, header.xmlLogicalOffset + header.xmlLogicalLength);
|
|
439
|
+
const xmlText = TEXT_DECODER.decode(xmlBytes);
|
|
440
|
+
const entries = parseE57Xml(xmlText);
|
|
441
|
+
if (entries.length === 0)
|
|
442
|
+
return null;
|
|
443
|
+
// Multi-scan registered E57 files store each scan in its own local
|
|
444
|
+
// frame and rely on the per-Data3D `pose` (rotation + translation) to
|
|
445
|
+
// place them in the file's global frame. We don't apply that
|
|
446
|
+
// transform yet, so silently concatenating registered multi-scan
|
|
447
|
+
// files would produce a misaligned mess. Reject upfront with a
|
|
448
|
+
// clear error so the user can use the export-merged option in their
|
|
449
|
+
// scan-processing tool.
|
|
450
|
+
if (entries.length > 1 && entries.some((e) => e.hasPose)) {
|
|
451
|
+
throw new Error(`E57: file contains ${entries.length} scans with per-scan poses (registered multi-scan). `
|
|
452
|
+
+ 'Multi-scan pose merging is not yet supported — please re-export as a single merged scan.');
|
|
453
|
+
}
|
|
454
|
+
// Resolve every entry's binary file offset through the
|
|
455
|
+
// CompressedVector section header. The XML's fileOffset is the
|
|
456
|
+
// section header (physical), not the first DataPacket.
|
|
457
|
+
const chunks = entries.map((entry) => {
|
|
458
|
+
const dataLogicalOffset = resolveCompressedVectorDataOffset(logical, entry.binaryFileOffset, header.pageSize);
|
|
459
|
+
return decodeE57Scan(logical, { ...entry, binaryFileOffset: dataLogicalOffset });
|
|
460
|
+
});
|
|
461
|
+
if (chunks.length === 1)
|
|
462
|
+
return chunks[0];
|
|
463
|
+
// Concatenate. Use some() so a single scan that lacks color/intensity
|
|
464
|
+
// doesn't drop the channel for the whole merged cloud — we just leave
|
|
465
|
+
// its slice at the default zeros and emit the channel anyway.
|
|
466
|
+
let total = 0;
|
|
467
|
+
for (const c of chunks)
|
|
468
|
+
total += c.pointCount;
|
|
469
|
+
const positions = new Float32Array(total * 3);
|
|
470
|
+
const hasColors = chunks.some((c) => c.colors);
|
|
471
|
+
const hasIntensity = chunks.some((c) => c.intensities);
|
|
472
|
+
const colors = hasColors ? new Float32Array(total * 3) : undefined;
|
|
473
|
+
const intensities = hasIntensity ? new Uint16Array(total) : undefined;
|
|
474
|
+
let off = 0;
|
|
475
|
+
for (const c of chunks) {
|
|
476
|
+
positions.set(c.positions, off * 3);
|
|
477
|
+
// Per-chunk conditional set: chunks without a channel just leave
|
|
478
|
+
// their slice at the default zero, which renders as black for
|
|
479
|
+
// colors / unlit for intensity. Better than dropping the whole
|
|
480
|
+
// channel because of a single mixed-attribute file.
|
|
481
|
+
if (colors && c.colors)
|
|
482
|
+
colors.set(c.colors, off * 3);
|
|
483
|
+
if (intensities && c.intensities)
|
|
484
|
+
intensities.set(c.intensities, off);
|
|
485
|
+
off += c.pointCount;
|
|
486
|
+
}
|
|
487
|
+
return {
|
|
488
|
+
positions,
|
|
489
|
+
colors,
|
|
490
|
+
intensities,
|
|
491
|
+
pointCount: total,
|
|
492
|
+
bbox: computeBBox(positions),
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
//# sourceMappingURL=e57.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e57.js","sourceRoot":"","sources":["../../src/formats/e57.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AA8B/D,OAAO,EACL,WAAW,EACX,cAAc,EACd,QAAQ,EACR,SAAS,GACV,MAAM,gBAAgB,CAAC;AAExB,MAAM,SAAS,GAAG,UAAU,CAAC;AAW7B,wDAAwD;AACxD,MAAM,UAAU,kBAAkB,CAAC,KAAiB;IAClD,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAChF,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3D,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,mBAAmB,KAAK,gBAAgB,SAAS,IAAI,CAAC,CAAC;IACzE,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAC5E,OAAO;QACL,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC;QACrC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,CAAC;QACtC,eAAe,EAAE,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;QACpC,sEAAsE;QACtE,gDAAgD;QAChD,gBAAgB,EAAE,iBAAiB,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC7E,gBAAgB,EAAE,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;QACrC,QAAQ,EAAE,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;KAC9B,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,KAAiB,EAAE,QAAgB;IAC9D,IAAI,QAAQ,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC9D,MAAM,cAAc,GAAG,QAAQ,GAAG,CAAC,CAAC;IACpC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAC;IACtD,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;IACjD,0EAA0E;IAC1E,qEAAqE;IACrE,2CAA2C;IAC3C,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,SAAS,GAAG,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;IAC/E,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,CAAC,GAAG,QAAQ,CAAC;QACzB,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,cAAc,CAAC,EAAE,GAAG,CAAC,CAAC;QACxD,GAAG,IAAI,cAAc,CAAC;IACxB,CAAC;IACD,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,SAAS,GAAG,QAAQ,CAAC;QACjC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,8EAA8E;AAC9E,SAAS,iBAAiB,CAAC,QAAgB,EAAE,QAAgB;IAC3D,MAAM,cAAc,GAAG,QAAQ,GAAG,CAAC,CAAC;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,QAAQ,CAAC;IAC3C,OAAO,KAAK,GAAG,cAAc,GAAG,MAAM,CAAC;AACzC,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,iCAAiC,CAC/C,OAAmB,EACnB,qBAA6B,EAC7B,QAAgB;IAEhB,MAAM,cAAc,GAAG,iBAAiB,CAAC,qBAAqB,EAAE,QAAQ,CAAC,CAAC;IAC1E,IAAI,cAAc,GAAG,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CACb,mDAAmD,cAAc,kCAAkC,OAAO,CAAC,MAAM,GAAG,CACrH,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,GAAG,cAAc,EAAE,EAAE,CAAC,CAAC;IACnF,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACnC,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CACb,6DAA6D,qBAAqB,YAAY,SAAS,EAAE,CAC1G,CAAC;IACJ,CAAC;IACD,MAAM,kBAAkB,GAAG,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAC/C,OAAO,iBAAiB,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;AACzD,CAAC;AAgCD,MAAM,YAAY,GAAG,IAAI,WAAW,EAAE,CAAC;AAEvC;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC/B,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,wCAAwC,IAAI,CAAC,IAAI,IAAI,GAAG,IAAI,CAAC,CAAC;IAChF,CAAC;IACD,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC3C,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,cAAc,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,CAAC;QACzD,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM;YAAE,SAAS;QACtB,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,kBAAkB,EAAE,CAAC;YACpD,4CAA4C;YAC5C,SAAS;QACX,CAAC;QACD,MAAM,cAAc,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACtD,MAAM,eAAe,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QACxD,IAAI,CAAC,cAAc,IAAI,CAAC,eAAe;YAAE,SAAS;QAClD,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAC/C,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,MAAM,MAAM,GAAqB,EAAE,CAAC;QACpC,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YAC/B,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YACvC,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;gBACrB,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,IAAI,EAAE,OAAO;oBACb,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ;iBACvE,CAAC,CAAC;YACL,CAAC;iBAAM,IAAI,IAAI,KAAK,eAAe,EAAE,CAAC;gBACpC,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,IAAI,EAAE,eAAe;oBACrB,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC;oBAC1C,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC;oBAC5C,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC;oBAC9C,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC;iBAC/C,CAAC,CAAC;YACL,CAAC;iBAAM,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC9B,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,IAAI,EAAE,SAAS;oBACf,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC;oBAC9C,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC;iBAC/C,CAAC,CAAC;YACL,CAAC;YACD,8DAA8D;QAChE,CAAC;QACD,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE;YACnC,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,SAAS;YAC1C,WAAW,EAAE,MAAM,CAAC,eAAe,CAAC;YACpC,gBAAgB,EAAE,MAAM,CAAC,cAAc,CAAC;YACxC,SAAS,EAAE,MAAM;YACjB,OAAO,EAAE,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,IAAI;SAC5C,CAAC,CAAC;IACL,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,+EAA+E;AAE/E;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,aAAa,CAAC,OAAmB,EAAE,KAAkB;IACnE,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IACxD,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;QACzC,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CACb,kCAAkC,CAAC,CAAC,IAAI,uCAAuC,CAChF,CAAC;QACJ,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IACvD,MAAM,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,MAAM,IAAI,MAAM,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IACvD,qEAAqE;IACrE,8DAA8D;IAC9D,IAAI,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CACb,sFAAsF,CACvF,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,YAAY,CAAC,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5E,oEAAoE;IACpE,2DAA2D;IAC3D,kEAAkE;IAClE,oBAAoB;IACpB,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC;QAClF,CAAC,CAAC,IAAI,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC;QACpC,CAAC,CAAC,SAAS,CAAC;IAEd,iDAAiD;IACjD,2BAA2B;IAC3B,kDAAkD;IAClD,oDAAoD;IACpD,6EAA6E;IAC7E,qEAAqE;IACrE,sEAAsE;IACtE,gEAAgE;IAChE,IAAI,MAAM,GAAG,KAAK,CAAC,gBAAgB,CAAC;IACpC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAClF,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,OAAO,OAAO,GAAG,KAAK,CAAC,WAAW,IAAI,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;QAC9D,IAAI,MAAM,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACtD,CAAC;QACD,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACzC,oEAAoE;QACpE,MAAM,mBAAmB,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QACjE,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;YACrB,oEAAoE;YACpE,MAAM,IAAI,mBAAmB,CAAC;YAC9B,SAAS;QACX,CAAC;QACD,MAAM,SAAS,GAAG,MAAM,GAAG,mBAAmB,CAAC;QAC/C,IAAI,SAAS,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACpE,CAAC;QACD,gDAAgD;QAChD,wCAAwC;QACxC,4DAA4D;QAC5D,gEAAgE;QAChE,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;QACzD,IAAI,eAAe,KAAK,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;YAC/C,MAAM,IAAI,KAAK,CACb,gCAAgC,eAAe,yBAAyB,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,CAClG,CAAC;QACJ,CAAC;QACD,MAAM,iBAAiB,GAAa,EAAE,CAAC;QACvC,IAAI,MAAM,GAAG,MAAM,GAAG,CAAC,CAAC;QACxB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,eAAe,EAAE,CAAC,EAAE,EAAE,CAAC;YACzC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;YACrD,MAAM,IAAI,CAAC,CAAC;QACd,CAAC;QACD,0CAA0C;QAC1C,MAAM,kBAAkB,GAAG,OAAO,CAAC;QACnC,MAAM,YAAY,GAAG,IAAI,GAAG,EAA6C,CAAC;QAC1E,IAAI,YAAY,GAAG,MAAM,CAAC;QAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,eAAe,EAAE,CAAC,EAAE,EAAE,CAAC;YACzC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACjG,YAAY,IAAI,iBAAiB,CAAC,CAAC,CAAC,CAAC;QACvC,CAAC;QAED,8BAA8B;QAC9B,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxD,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxD,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxD,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,CAAE,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC;QACxF,IACE,cAAc,KAAK,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,CAAE,CAAC,MAAM,GAAG,SAAS,CAAC;eAC9E,cAAc,KAAK,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,CAAE,CAAC,MAAM,GAAG,SAAS,CAAC,EACpF,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;QACpF,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,CAAC,WAAW,GAAG,OAAO,CAAC,CAAC;QAEnE,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,YAAY,CAAE,CAAC,KAAK,CAAC;QACrD,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,YAAY,CAAE,CAAC,KAAK,CAAC;QACrD,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,YAAY,CAAE,CAAC,KAAK,CAAC;QAErD,IAAI,MAAM,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;YAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC9B,SAAS,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;YACvE,CAAC;QACH,CAAC;aAAM,CAAC;YACN,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC9B,SAAS,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;YACvE,CAAC;QACH,CAAC;QACD,IAAI,MAAM,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;YAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC9B,SAAS,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;YAC3E,CAAC;QACH,CAAC;aAAM,CAAC;YACN,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC9B,SAAS,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;YAC3E,CAAC;QACH,CAAC;QACD,IAAI,MAAM,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;YAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC9B,SAAS,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;YAC3E,CAAC;QACH,CAAC;aAAM,CAAC;YACN,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC9B,SAAS,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;YAC3E,CAAC;QACH,CAAC;QAED,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,EAAE,CAAC;YACzC,iBAAiB,CAAC,IAAI,EAAE,YAAY,CAAC,GAAG,CAAC,UAAU,CAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YAC/F,iBAAiB,CAAC,IAAI,EAAE,YAAY,CAAC,GAAG,CAAC,YAAY,CAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YACjG,iBAAiB,CAAC,IAAI,EAAE,YAAY,CAAC,GAAG,CAAC,WAAW,CAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAClG,CAAC;QACD,IAAI,WAAW,IAAI,MAAM,EAAE,CAAC;YAC1B,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,WAAW,CAAE,CAAC,KAAK,CAAC;YACpD,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC5B,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACrD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC9B,MAAM,CAAC,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,GAAG,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,GAAG,MAAM,EAAE,IAAI,CAAC,CAAC;oBACjH,WAAW,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBACjF,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,+DAA+D;gBAC/D,oDAAoD;gBACpD,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC;gBAChC,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,IAAI,KAAK,CAAC;gBACpC,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC;gBACvB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;gBACpC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;gBACtD,MAAM,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACpC,MAAM,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC;gBACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC9B,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC;oBAChC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC;wBACtB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;wBACjE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;oBACtD,MAAM,IAAI,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;oBAC/B,WAAW,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBACpF,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,IAAI,IAAI,CAAC;QAChB,KAAK,kBAAkB,CAAC;QACxB,MAAM,GAAG,SAAS,CAAC;IACrB,CAAC;IAED,IAAI,OAAO,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QAChC,gEAAgE;QAChE,kEAAkE;QAClE,4DAA4D;QAC5D,OAAO,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;IACpI,CAAC;IACD,OAAO,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;AACrE,CAAC;AAED,SAAS,iBAAiB,CACxB,IAAc,EACd,KAAa,EACb,KAAqB,EACrB,MAAoB,EACpB,OAAe,EACf,IAAY,EACZ,aAAwB;IAExB,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACpD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;YAC9B,MAAM,CAAC,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,CAAC,GAAG,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,CAAC,GAAG,MAAM,EAAE,IAAI,CAAC,CAAC;YAC/G,MAAM,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;SAAM,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QACpC,gEAAgE;QAChE,2DAA2D;QAC3D,iEAAiE;QACjE,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;QAC/B,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,IAAI,GAAG,CAAC;QACjC,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC;QACvB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;QACtD,MAAM,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC;QACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;YAC9B,MAAM,GAAG,GAAG,KAAK,GAAG,CAAC,GAAG,MAAM,CAAC;YAC/B,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC;gBACtB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;gBACjE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;YACtD,MAAM,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACzE,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CACf,SAAuB,EACvB,MAAgC,EAChC,WAAoC,EACpC,UAAkB;IAElB,OAAO;QACL,SAAS,EAAE,IAAI,YAAY,CAAC,SAAS,CAAC;QACtC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;QACrD,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS;QACnE,UAAU;QACV,IAAI,EAAE,WAAW,CAAC,SAAS,CAAC;KAC7B,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,KAAuB,EAAE,IAAY;IACtD,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,SAAS,CAAC,IAAc,EAAE,MAAc;IAC/C,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACxC,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;IAC5C,OAAO,EAAE,GAAG,WAAW,GAAG,EAAE,CAAC;AAC/B,CAAC;AAED,SAAS,OAAO,CAAC,CAAS;IACxB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,WAAW,CAAC,SAAuB;IAC1C,IAAI,IAAI,GAAG,QAAQ,EAAE,IAAI,GAAG,QAAQ,EAAE,IAAI,GAAG,QAAQ,CAAC;IACtD,IAAI,IAAI,GAAG,CAAC,QAAQ,EAAE,IAAI,GAAG,CAAC,QAAQ,EAAE,IAAI,GAAG,CAAC,QAAQ,CAAC;IACzD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7C,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACnE,IAAI,CAAC,GAAG,IAAI;YAAE,IAAI,GAAG,CAAC,CAAC;QAAC,IAAI,CAAC,GAAG,IAAI;YAAE,IAAI,GAAG,CAAC,CAAC;QAC/C,IAAI,CAAC,GAAG,IAAI;YAAE,IAAI,GAAG,CAAC,CAAC;QAAC,IAAI,CAAC,GAAG,IAAI;YAAE,IAAI,GAAG,CAAC,CAAC;QAC/C,IAAI,CAAC,GAAG,IAAI;YAAE,IAAI,GAAG,CAAC,CAAC;QAAC,IAAI,CAAC,GAAG,IAAI;YAAE,IAAI,GAAG,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;AAC9D,CAAC;AAED,+EAA+E;AAE/E;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,KAAiB;IACzC,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACrD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAC9G,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACrC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEtC,mEAAmE;IACnE,sEAAsE;IACtE,6DAA6D;IAC7D,iEAAiE;IACjE,+DAA+D;IAC/D,oEAAoE;IACpE,wBAAwB;IACxB,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CACb,sBAAsB,OAAO,CAAC,MAAM,sDAAsD;cACxF,0FAA0F,CAC7F,CAAC;IACJ,CAAC;IAED,uDAAuD;IACvD,+DAA+D;IAC/D,uDAAuD;IACvD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACnC,MAAM,iBAAiB,GAAG,iCAAiC,CACzD,OAAO,EACP,KAAK,CAAC,gBAAgB,EACtB,MAAM,CAAC,QAAQ,CAChB,CAAC;QACF,OAAO,aAAa,CAAC,OAAO,EAAE,EAAE,GAAG,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,CAAC,CAAC;IACnF,CAAC,CAAC,CAAC;IACH,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;IAE1C,sEAAsE;IACtE,sEAAsE;IACtE,8DAA8D;IAC9D,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,CAAC,IAAI,MAAM;QAAE,KAAK,IAAI,CAAC,CAAC,UAAU,CAAC;IAC9C,MAAM,SAAS,GAAG,IAAI,YAAY,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IACvD,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACnE,MAAM,WAAW,GAAG,YAAY,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACtE,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;QACpC,iEAAiE;QACjE,8DAA8D;QAC9D,+DAA+D;QAC/D,oDAAoD;QACpD,IAAI,MAAM,IAAI,CAAC,CAAC,MAAM;YAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;QACtD,IAAI,WAAW,IAAI,CAAC,CAAC,WAAW;YAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;QACtE,GAAG,IAAI,CAAC,CAAC,UAAU,CAAC;IACtB,CAAC;IACD,OAAO;QACL,SAAS;QACT,MAAM;QACN,WAAW;QACX,UAAU,EAAE,KAAK;QACjB,IAAI,EAAE,WAAW,CAAC,SAAS,CAAC;KAC7B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decoders for the two non-PCD IFCx point cloud schemas authored by
|
|
3
|
+
* buildingSMART:
|
|
4
|
+
*
|
|
5
|
+
* points::array — { positions: number[][], colors?: number[][] }
|
|
6
|
+
* inline JSON arrays of [x,y,z] and [r,g,b] in 0..1
|
|
7
|
+
*
|
|
8
|
+
* points::base64 — { positions: base64-string, colors?: base64-string }
|
|
9
|
+
* little-endian Float32 buffers, [x,y,z, x,y,z, ...]
|
|
10
|
+
* and [r,g,b, r,g,b, ...] in 0..1
|
|
11
|
+
*
|
|
12
|
+
* The PCD schema (pcd::base64) is decoded by formats/pcd.ts; the adapter
|
|
13
|
+
* that picks between these three lives in `from-ifcx-attributes.ts`.
|
|
14
|
+
*/
|
|
15
|
+
import type { DecodedPointChunk } from '../types.js';
|
|
16
|
+
export interface PointsArrayAttribute {
|
|
17
|
+
positions: number[][];
|
|
18
|
+
colors?: number[][];
|
|
19
|
+
}
|
|
20
|
+
export interface PointsBase64Attribute {
|
|
21
|
+
positions: string;
|
|
22
|
+
colors?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare function decodePointsArray(attr: PointsArrayAttribute): DecodedPointChunk;
|
|
25
|
+
export declare function decodePointsBase64(attr: PointsBase64Attribute): DecodedPointChunk;
|
|
26
|
+
//# sourceMappingURL=ifcx-points.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ifcx-points.d.ts","sourceRoot":"","sources":["../../src/formats/ifcx-points.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAkB,MAAM,aAAa,CAAC;AAErE,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,EAAE,EAAE,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,oBAAoB,GAAG,iBAAiB,CA+C/E;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,qBAAqB,GAAG,iBAAiB,CAiCjF"}
|