@ifc-lite/pointcloud 0.11.0 → 0.13.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/README.md +96 -0
- package/dist/copc/copc-hierarchy.d.ts +102 -0
- package/dist/copc/copc-hierarchy.d.ts.map +1 -0
- package/dist/copc/copc-hierarchy.js +210 -0
- package/dist/copc/copc-hierarchy.js.map +1 -0
- package/dist/copc/copc-info.d.ts +52 -0
- package/dist/copc/copc-info.d.ts.map +1 -0
- package/dist/copc/copc-info.js +147 -0
- package/dist/copc/copc-info.js.map +1 -0
- package/dist/copc/copc-reader.d.ts +60 -0
- package/dist/copc/copc-reader.d.ts.map +1 -0
- package/dist/copc/copc-reader.js +138 -0
- package/dist/copc/copc-reader.js.map +1 -0
- package/dist/copc/copc-worker-client.d.ts +37 -0
- package/dist/copc/copc-worker-client.d.ts.map +1 -0
- package/dist/copc/copc-worker-client.js +154 -0
- package/dist/copc/copc-worker-client.js.map +1 -0
- package/dist/copc/copc-worker-host.d.ts +11 -0
- package/dist/copc/copc-worker-host.d.ts.map +1 -0
- package/dist/copc/copc-worker-host.js +73 -0
- package/dist/copc/copc-worker-host.js.map +1 -0
- package/dist/formats/ifcx-points.d.ts +3 -0
- package/dist/formats/ifcx-points.d.ts.map +1 -1
- package/dist/formats/ifcx-points.js +23 -7
- package/dist/formats/ifcx-points.js.map +1 -1
- package/dist/formats/las.d.ts +1 -0
- package/dist/formats/las.d.ts.map +1 -1
- package/dist/formats/las.js +1 -1
- package/dist/formats/las.js.map +1 -1
- package/dist/formats/pcd-header.d.ts +19 -0
- package/dist/formats/pcd-header.d.ts.map +1 -0
- package/dist/formats/pcd-header.js +89 -0
- package/dist/formats/pcd-header.js.map +1 -0
- package/dist/formats/pcd.d.ts +3 -0
- package/dist/formats/pcd.d.ts.map +1 -1
- package/dist/formats/pcd.js +41 -119
- package/dist/formats/pcd.js.map +1 -1
- package/dist/from-ifcx-attributes.d.ts +3 -0
- package/dist/from-ifcx-attributes.d.ts.map +1 -1
- package/dist/from-ifcx-attributes.js +12 -5
- package/dist/from-ifcx-attributes.js.map +1 -1
- package/dist/index.d.ts +13 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -2
- package/dist/index.js.map +1 -1
- package/dist/lod/copc-lod-tree.d.ts +15 -0
- package/dist/lod/copc-lod-tree.d.ts.map +1 -0
- package/dist/lod/copc-lod-tree.js +67 -0
- package/dist/lod/copc-lod-tree.js.map +1 -0
- package/dist/lod/frustum.d.ts +13 -0
- package/dist/lod/frustum.d.ts.map +1 -0
- package/dist/lod/frustum.js +38 -0
- package/dist/lod/frustum.js.map +1 -0
- package/dist/lod/pacer.d.ts +62 -0
- package/dist/lod/pacer.d.ts.map +1 -0
- package/dist/lod/pacer.js +56 -0
- package/dist/lod/pacer.js.map +1 -0
- package/dist/lod/select.d.ts +80 -0
- package/dist/lod/select.d.ts.map +1 -0
- package/dist/lod/select.js +155 -0
- package/dist/lod/select.js.map +1 -0
- package/dist/point-source.d.ts +11 -0
- package/dist/point-source.d.ts.map +1 -0
- package/dist/point-source.js +5 -0
- package/dist/point-source.js.map +1 -0
- package/dist/streaming/blob-source.d.ts +3 -2
- package/dist/streaming/blob-source.d.ts.map +1 -1
- package/dist/streaming/blob-source.js +2 -9
- package/dist/streaming/blob-source.js.map +1 -1
- package/dist/streaming/decode-worker.js +22 -0
- package/dist/streaming/decode-worker.js.map +1 -1
- package/dist/streaming/http-range-source.d.ts +47 -0
- package/dist/streaming/http-range-source.d.ts.map +1 -0
- package/dist/streaming/http-range-source.js +102 -0
- package/dist/streaming/http-range-source.js.map +1 -0
- package/dist/streaming/inline-worker.js +1 -1
- package/dist/streaming/laz-perf-loader.d.ts +58 -0
- package/dist/streaming/laz-perf-loader.d.ts.map +1 -0
- package/dist/streaming/laz-perf-loader.js +107 -0
- package/dist/streaming/laz-perf-loader.js.map +1 -0
- package/dist/streaming/laz-source.d.ts +0 -40
- package/dist/streaming/laz-source.d.ts.map +1 -1
- package/dist/streaming/laz-source.js +1 -94
- package/dist/streaming/laz-source.js.map +1 -1
- package/dist/streaming/protocol.d.ts +45 -0
- package/dist/streaming/protocol.d.ts.map +1 -1
- package/dist/streaming/protocol.js.map +1 -1
- package/dist/streaming/types.d.ts +14 -0
- package/dist/streaming/types.d.ts.map +1 -1
- package/dist/streaming/worker-client.d.ts +25 -0
- package/dist/streaming/worker-client.d.ts.map +1 -1
- package/dist/streaming/worker-client.js +12 -5
- package/dist/streaming/worker-client.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copc-info.js","sourceRoot":"","sources":["../../src/copc/copc-info.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* COPC reader (#6869): header + info VLR, hierarchy pages, and per-node
|
|
3
|
+
* decode over any `RangeByteSource` (a local File, or HTTP Range).
|
|
4
|
+
*
|
|
5
|
+
* Node data is one LAZ chunk per node, decompressed with laz-perf's
|
|
6
|
+
* `ChunkDecoder` and then decoded by the SAME `decodeLasPoints` the LAS and
|
|
7
|
+
* LAZ sources use, so PDRF 6/7/8 field layout, 8-bit RGB detection and the
|
|
8
|
+
* f64 `originOffset` subtraction (#1804) have exactly one implementation.
|
|
9
|
+
*
|
|
10
|
+
* The reader holds no hierarchy state: it reads and parses pages, and the
|
|
11
|
+
* owner (worker client, LOD driver, test) keeps the `CopcHierarchy`. That
|
|
12
|
+
* lets the reader live in the decode worker while the hierarchy lives with
|
|
13
|
+
* the LOD selection on the main thread.
|
|
14
|
+
*/
|
|
15
|
+
import { type LasHeader } from '../formats/las.js';
|
|
16
|
+
import { type LazPerfModule } from '../streaming/laz-perf-loader.js';
|
|
17
|
+
import type { RangeByteSource } from '../streaming/types.js';
|
|
18
|
+
import type { DecodedPointChunk, PointCloudBBox } from '../types.js';
|
|
19
|
+
import { type CopcFileInfo } from './copc-info.js';
|
|
20
|
+
import { type CopcHierarchyPage, type CopcNodeEntry, type CopcPageRef } from './copc-hierarchy.js';
|
|
21
|
+
export interface CopcReadNodeOptions {
|
|
22
|
+
/** Keep every `stride`-th point of the node (>= 1). The whole chunk is still decompressed. */
|
|
23
|
+
stride?: number;
|
|
24
|
+
signal?: AbortSignal;
|
|
25
|
+
}
|
|
26
|
+
export declare class CopcReader {
|
|
27
|
+
private readonly source;
|
|
28
|
+
readonly file: CopcFileInfo;
|
|
29
|
+
readonly originOffset: readonly [number, number, number] | undefined;
|
|
30
|
+
/** Locked by the first decoded node so every node shares one colour scale. */
|
|
31
|
+
private rgbScale;
|
|
32
|
+
private constructor();
|
|
33
|
+
/** Read and validate the header and info VLR. No point data is read. */
|
|
34
|
+
static open(source: RangeByteSource, options?: {
|
|
35
|
+
originOffset?: readonly [number, number, number];
|
|
36
|
+
signal?: AbortSignal;
|
|
37
|
+
}): Promise<CopcReader>;
|
|
38
|
+
get header(): LasHeader;
|
|
39
|
+
/** The root hierarchy page's location. */
|
|
40
|
+
get rootPageRef(): CopcPageRef;
|
|
41
|
+
/** Header bounds in the decoded frame (with `originOffset` subtracted). */
|
|
42
|
+
get bbox(): PointCloudBBox;
|
|
43
|
+
/**
|
|
44
|
+
* Read and parse one page. `maxBytes` (the caller's remaining hierarchy
|
|
45
|
+
* budget) is enforced BEFORE any byte is read, so a hostile page size
|
|
46
|
+
* costs nothing.
|
|
47
|
+
*/
|
|
48
|
+
readPage(ref: CopcPageRef, signal?: AbortSignal, maxBytes?: number): Promise<CopcHierarchyPage>;
|
|
49
|
+
/** Fetch and decode one node. */
|
|
50
|
+
readNode(entry: CopcNodeEntry, options?: CopcReadNodeOptions): Promise<DecodedPointChunk>;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Decompress a node's chunk (`pointCount` records), keeping every
|
|
54
|
+
* `stride`-th record. Wasm allocations are freed on every path.
|
|
55
|
+
*/
|
|
56
|
+
export declare function decompressCopcChunk(mod: LazPerfModule, compressed: Uint8Array, header: LasHeader, pointCount: number, stride: number): {
|
|
57
|
+
slab: Uint8Array;
|
|
58
|
+
count: number;
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=copc-reader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copc-reader.d.ts","sourceRoot":"","sources":["../../src/copc/copc-reader.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAA4D,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC7G,OAAO,EAAe,KAAK,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAClF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAgC,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACjF,OAAO,EAIL,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,WAAW,EACjB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,WAAW,mBAAmB;IAClC,8FAA8F;IAC9F,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,qBAAa,UAAU;IAKnB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,QAAQ,CAAC,IAAI,EAAE,YAAY;IAC3B,QAAQ,CAAC,YAAY,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS;IANtE,8EAA8E;IAC9E,OAAO,CAAC,QAAQ,CAAqB;IAErC,OAAO;IAMP,wEAAwE;WAC3D,IAAI,CACf,MAAM,EAAE,eAAe,EACvB,OAAO,GAAE;QAAE,YAAY,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAO,GACvF,OAAO,CAAC,UAAU,CAAC;IAKtB,IAAI,MAAM,IAAI,SAAS,CAEtB;IAED,0CAA0C;IAC1C,IAAI,WAAW,IAAI,WAAW,CAM7B;IAED,2EAA2E;IAC3E,IAAI,IAAI,IAAI,cAAc,CAEzB;IAED;;;;OAIG;IACG,QAAQ,CACZ,GAAG,EAAE,WAAW,EAChB,MAAM,CAAC,EAAE,WAAW,EACpB,QAAQ,GAAE,MAAmD,GAC5D,OAAO,CAAC,iBAAiB,CAAC;IAY7B,iCAAiC;IAC3B,QAAQ,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAsBpG;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,aAAa,EAClB,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,SAAS,EACjB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GACb;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAyBrC"}
|
|
@@ -0,0 +1,138 @@
|
|
|
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
|
+
* COPC reader (#6869): header + info VLR, hierarchy pages, and per-node
|
|
6
|
+
* decode over any `RangeByteSource` (a local File, or HTTP Range).
|
|
7
|
+
*
|
|
8
|
+
* Node data is one LAZ chunk per node, decompressed with laz-perf's
|
|
9
|
+
* `ChunkDecoder` and then decoded by the SAME `decodeLasPoints` the LAS and
|
|
10
|
+
* LAZ sources use, so PDRF 6/7/8 field layout, 8-bit RGB detection and the
|
|
11
|
+
* f64 `originOffset` subtraction (#1804) have exactly one implementation.
|
|
12
|
+
*
|
|
13
|
+
* The reader holds no hierarchy state: it reads and parses pages, and the
|
|
14
|
+
* owner (worker client, LOD driver, test) keeps the `CopcHierarchy`. That
|
|
15
|
+
* lets the reader live in the decode worker while the hierarchy lives with
|
|
16
|
+
* the LOD selection on the main thread.
|
|
17
|
+
*/
|
|
18
|
+
import { bboxInDecodedFrame, decodeLasPoints, sampleMaxRgbChannel } from '../formats/las.js';
|
|
19
|
+
import { loadLazPerf } from '../streaming/laz-perf-loader.js';
|
|
20
|
+
import { readCopcFileInfo, voxelKeyId } from './copc-info.js';
|
|
21
|
+
import { DEFAULT_COPC_HIERARCHY_LIMITS, MAX_COPC_NODE_POINTS, parseCopcHierarchyPage, } from './copc-hierarchy.js';
|
|
22
|
+
export class CopcReader {
|
|
23
|
+
source;
|
|
24
|
+
file;
|
|
25
|
+
originOffset;
|
|
26
|
+
/** Locked by the first decoded node so every node shares one colour scale. */
|
|
27
|
+
rgbScale;
|
|
28
|
+
constructor(source, file, originOffset) {
|
|
29
|
+
this.source = source;
|
|
30
|
+
this.file = file;
|
|
31
|
+
this.originOffset = originOffset;
|
|
32
|
+
}
|
|
33
|
+
/** Read and validate the header and info VLR. No point data is read. */
|
|
34
|
+
static async open(source, options = {}) {
|
|
35
|
+
const file = await readCopcFileInfo(source, options.signal);
|
|
36
|
+
return new CopcReader(source, file, options.originOffset);
|
|
37
|
+
}
|
|
38
|
+
get header() {
|
|
39
|
+
return this.file.header;
|
|
40
|
+
}
|
|
41
|
+
/** The root hierarchy page's location. */
|
|
42
|
+
get rootPageRef() {
|
|
43
|
+
return {
|
|
44
|
+
key: { d: 0, x: 0, y: 0, z: 0 },
|
|
45
|
+
offset: this.file.info.rootHierOffset,
|
|
46
|
+
byteSize: this.file.info.rootHierSize,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/** Header bounds in the decoded frame (with `originOffset` subtracted). */
|
|
50
|
+
get bbox() {
|
|
51
|
+
return bboxInDecodedFrame(this.file.header.bbox, this.originOffset);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Read and parse one page. `maxBytes` (the caller's remaining hierarchy
|
|
55
|
+
* budget) is enforced BEFORE any byte is read, so a hostile page size
|
|
56
|
+
* costs nothing.
|
|
57
|
+
*/
|
|
58
|
+
async readPage(ref, signal, maxBytes = DEFAULT_COPC_HIERARCHY_LIMITS.maxPageBytes) {
|
|
59
|
+
if (ref.offset + ref.byteSize > this.file.fileSize || ref.byteSize <= 0) {
|
|
60
|
+
throw new Error(`COPC: page ${voxelKeyId(ref.key)} lies outside the file`);
|
|
61
|
+
}
|
|
62
|
+
if (ref.byteSize > maxBytes) {
|
|
63
|
+
throw new Error(`COPC: page ${voxelKeyId(ref.key)} of ${ref.byteSize} bytes exceeds the ${maxBytes}-byte hierarchy budget`);
|
|
64
|
+
}
|
|
65
|
+
const bytes = await this.source.read(ref.offset, ref.offset + ref.byteSize, signal);
|
|
66
|
+
if (bytes.length !== ref.byteSize)
|
|
67
|
+
throw new Error(`COPC: page ${voxelKeyId(ref.key)} truncated`);
|
|
68
|
+
return parseCopcHierarchyPage(bytes, this.file.fileSize);
|
|
69
|
+
}
|
|
70
|
+
/** Fetch and decode one node. */
|
|
71
|
+
async readNode(entry, options = {}) {
|
|
72
|
+
const { header, fileSize } = this.file;
|
|
73
|
+
const id = voxelKeyId(entry.key);
|
|
74
|
+
if (!Number.isSafeInteger(entry.pointCount) || entry.pointCount < 0 || entry.pointCount > MAX_COPC_NODE_POINTS) {
|
|
75
|
+
throw new Error(`COPC: node ${id} has invalid point count ${entry.pointCount}`);
|
|
76
|
+
}
|
|
77
|
+
if (entry.pointCount === 0)
|
|
78
|
+
return emptyChunk(header);
|
|
79
|
+
if (entry.byteSize <= 0 || entry.offset < header.pointDataOffset || entry.offset + entry.byteSize > fileSize) {
|
|
80
|
+
throw new Error(`COPC: node ${id} data lies outside the point block`);
|
|
81
|
+
}
|
|
82
|
+
const compressed = await this.source.read(entry.offset, entry.offset + entry.byteSize, options.signal);
|
|
83
|
+
if (compressed.length !== entry.byteSize)
|
|
84
|
+
throw new Error(`COPC: node ${id} truncated`);
|
|
85
|
+
const mod = await loadLazPerf();
|
|
86
|
+
options.signal?.throwIfAborted();
|
|
87
|
+
const stride = Math.max(1, Math.floor(options.stride ?? 1));
|
|
88
|
+
const { slab, count } = decompressCopcChunk(mod, compressed, header, entry.pointCount, stride);
|
|
89
|
+
if (this.rgbScale === undefined) {
|
|
90
|
+
const max = sampleMaxRgbChannel(slab, { ...header, pointCount: count });
|
|
91
|
+
this.rgbScale = header.hasRgb && max > 0 && max <= 255 ? 65535 / 255 : 1;
|
|
92
|
+
}
|
|
93
|
+
return decodeLasPoints(slab, header, count, header.pointRecordLength, this.rgbScale, this.originOffset);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Decompress a node's chunk (`pointCount` records), keeping every
|
|
98
|
+
* `stride`-th record. Wasm allocations are freed on every path.
|
|
99
|
+
*/
|
|
100
|
+
export function decompressCopcChunk(mod, compressed, header, pointCount, stride) {
|
|
101
|
+
const recordLength = header.pointRecordLength;
|
|
102
|
+
const count = Math.ceil(pointCount / stride);
|
|
103
|
+
const slab = new Uint8Array(count * recordLength);
|
|
104
|
+
const dataPtr = mod._malloc(compressed.byteLength);
|
|
105
|
+
const pointPtr = mod._malloc(recordLength);
|
|
106
|
+
const decoder = new mod.ChunkDecoder();
|
|
107
|
+
try {
|
|
108
|
+
mod.HEAPU8.set(compressed, dataPtr);
|
|
109
|
+
decoder.open(header.pointDataFormatId, recordLength, dataPtr);
|
|
110
|
+
let write = 0;
|
|
111
|
+
for (let i = 0; i < pointCount; i++) {
|
|
112
|
+
decoder.getPoint(pointPtr);
|
|
113
|
+
if (i % stride === 0) {
|
|
114
|
+
// Re-read HEAPU8 each time: a wasm memory growth detaches the old view.
|
|
115
|
+
slab.set(mod.HEAPU8.subarray(pointPtr, pointPtr + recordLength), write * recordLength);
|
|
116
|
+
write++;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return { slab, count };
|
|
120
|
+
}
|
|
121
|
+
finally {
|
|
122
|
+
decoder.delete();
|
|
123
|
+
mod._free(pointPtr);
|
|
124
|
+
mod._free(dataPtr);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function emptyChunk(header) {
|
|
128
|
+
return {
|
|
129
|
+
positions: new Float32Array(0),
|
|
130
|
+
colors: header.hasRgb ? new Float32Array(0) : undefined,
|
|
131
|
+
normalState: 'absent',
|
|
132
|
+
classifications: new Uint8Array(0),
|
|
133
|
+
intensities: new Uint16Array(0),
|
|
134
|
+
pointCount: 0,
|
|
135
|
+
bbox: { min: [Infinity, Infinity, Infinity], max: [-Infinity, -Infinity, -Infinity] },
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=copc-reader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copc-reader.js","sourceRoot":"","sources":["../../src/copc/copc-reader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main-thread COPC client (#6869). Range reads and LAZ decoding run in the
|
|
3
|
+
* shared decode worker; the hierarchy lives here, next to the LOD selection
|
|
4
|
+
* that walks it. Each page/node read is individually cancellable, so a
|
|
5
|
+
* camera move can drop fetches it no longer wants.
|
|
6
|
+
*/
|
|
7
|
+
import { type CopcSourceDescriptor } from '../streaming/protocol.js';
|
|
8
|
+
import { type DecodeWorkerOptions } from '../streaming/worker-client.js';
|
|
9
|
+
import type { DecodedPointChunk } from '../types.js';
|
|
10
|
+
import { type CopcFileInfo } from './copc-info.js';
|
|
11
|
+
import { CopcHierarchy, type CopcHierarchyLimits, type CopcHierarchyPage, type CopcNodeEntry, type CopcPageRef } from './copc-hierarchy.js';
|
|
12
|
+
export interface OpenCopcOptions extends DecodeWorkerOptions {
|
|
13
|
+
source: CopcSourceDescriptor;
|
|
14
|
+
/** Native offset subtracted in f64 before narrowing to f32 (#1804). */
|
|
15
|
+
originOffset?: readonly [number, number, number];
|
|
16
|
+
hierarchyLimits?: CopcHierarchyLimits;
|
|
17
|
+
signal?: AbortSignal;
|
|
18
|
+
}
|
|
19
|
+
export interface CopcWorkerReader {
|
|
20
|
+
readonly file: CopcFileInfo;
|
|
21
|
+
/** Root page loaded on open; further pages via `loadPage`. */
|
|
22
|
+
readonly hierarchy: CopcHierarchy;
|
|
23
|
+
readonly originOffset?: readonly [number, number, number];
|
|
24
|
+
/** Read and parse a page without admitting it (see `loadPendingCopcPages`). */
|
|
25
|
+
readPage(ref: CopcPageRef, signal?: AbortSignal): Promise<CopcHierarchyPage>;
|
|
26
|
+
/** Read a pending page and admit it to `hierarchy`; concurrent calls share one read. */
|
|
27
|
+
loadPage(ref: CopcPageRef, signal?: AbortSignal): Promise<void>;
|
|
28
|
+
/** Fetch and decode one node, keeping every `stride`-th point. */
|
|
29
|
+
readNode(node: CopcNodeEntry, options?: {
|
|
30
|
+
stride?: number;
|
|
31
|
+
signal?: AbortSignal;
|
|
32
|
+
}): Promise<DecodedPointChunk>;
|
|
33
|
+
close(): void;
|
|
34
|
+
}
|
|
35
|
+
/** Open a COPC file in the decode worker and load its root hierarchy page. */
|
|
36
|
+
export declare function openCopcWorkerReader(options: OpenCopcOptions): Promise<CopcWorkerReader>;
|
|
37
|
+
//# sourceMappingURL=copc-worker-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copc-worker-client.d.ts","sourceRoot":"","sources":["../../src/copc/copc-worker-client.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AAEH,OAAO,EAAiB,KAAK,oBAAoB,EAAuB,MAAM,0BAA0B,CAAC;AACzG,OAAO,EAAkC,KAAK,mBAAmB,EAAsB,MAAM,+BAA+B,CAAC;AAC7H,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EACL,aAAa,EAEb,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,WAAW,EACjB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,WAAW,eAAgB,SAAQ,mBAAmB;IAC1D,MAAM,EAAE,oBAAoB,CAAC;IAC7B,uEAAuE;IACvE,YAAY,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACjD,eAAe,CAAC,EAAE,mBAAmB,CAAC;IACtC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,8DAA8D;IAC9D,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1D,+EAA+E;IAC/E,QAAQ,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC7E,wFAAwF;IACxF,QAAQ,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,kEAAkE;IAClE,QAAQ,CAAC,IAAI,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC/G,KAAK,IAAI,IAAI,CAAC;CACf;AA4DD,8EAA8E;AAC9E,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA4F9F"}
|
|
@@ -0,0 +1,154 @@
|
|
|
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
|
+
* Main-thread COPC client (#6869). Range reads and LAZ decoding run in the
|
|
6
|
+
* shared decode worker; the hierarchy lives here, next to the LOD selection
|
|
7
|
+
* that walks it. Each page/node read is individually cancellable, so a
|
|
8
|
+
* camera move can drop fetches it no longer wants.
|
|
9
|
+
*/
|
|
10
|
+
import { chunkFromWire } from '../streaming/protocol.js';
|
|
11
|
+
import { defaultSpawn, getSharedSession } from '../streaming/worker-client.js';
|
|
12
|
+
import { voxelKeyId } from './copc-info.js';
|
|
13
|
+
import { CopcHierarchy, DEFAULT_COPC_HIERARCHY_LIMITS, } from './copc-hierarchy.js';
|
|
14
|
+
/**
|
|
15
|
+
* Send one request, forwarding `signal` to the worker as `copc-cancel`. A
|
|
16
|
+
* response that races the abort is discarded, as for stream chunks;
|
|
17
|
+
* `onDiscard` releases anything it carried (an opened reader's sourceId).
|
|
18
|
+
*/
|
|
19
|
+
async function cancellable(session, signal, build, onDiscard) {
|
|
20
|
+
signal?.throwIfAborted();
|
|
21
|
+
let requestId = -1;
|
|
22
|
+
const onAbort = () => session.notify({ kind: 'copc-cancel', targetRequestId: requestId });
|
|
23
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
|
24
|
+
try {
|
|
25
|
+
const resp = await session.send(build, [], (id) => { requestId = id; });
|
|
26
|
+
if (signal?.aborted) {
|
|
27
|
+
onDiscard?.(resp);
|
|
28
|
+
signal.throwIfAborted();
|
|
29
|
+
}
|
|
30
|
+
return resp;
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
signal?.removeEventListener('abort', onAbort);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/** Wait for `shared`, rejecting early (for this caller only) when `signal` aborts. */
|
|
37
|
+
function joinSharedLoad(shared, signal, onAllGone) {
|
|
38
|
+
shared.waiters++;
|
|
39
|
+
return new Promise((resolve, reject) => {
|
|
40
|
+
let settled = false;
|
|
41
|
+
const leave = () => {
|
|
42
|
+
if (settled)
|
|
43
|
+
return false;
|
|
44
|
+
settled = true;
|
|
45
|
+
shared.waiters--;
|
|
46
|
+
signal?.removeEventListener('abort', onAbort);
|
|
47
|
+
return true;
|
|
48
|
+
};
|
|
49
|
+
function onAbort() {
|
|
50
|
+
if (!leave())
|
|
51
|
+
return;
|
|
52
|
+
if (shared.waiters === 0)
|
|
53
|
+
onAllGone();
|
|
54
|
+
reject(signal?.reason ?? new DOMException('Aborted', 'AbortError'));
|
|
55
|
+
}
|
|
56
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
|
57
|
+
shared.promise.then(() => { if (leave())
|
|
58
|
+
resolve(); }, (err) => { if (leave())
|
|
59
|
+
reject(err); });
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
/** Open a COPC file in the decode worker and load its root hierarchy page. */
|
|
63
|
+
export async function openCopcWorkerReader(options) {
|
|
64
|
+
const session = await getSharedSession(options.spawn ?? defaultSpawn);
|
|
65
|
+
const limits = options.hierarchyLimits ?? DEFAULT_COPC_HIERARCHY_LIMITS;
|
|
66
|
+
const opened = await cancellable(session, options.signal, (requestId) => ({
|
|
67
|
+
kind: 'copc-open', requestId, source: options.source, originOffset: options.originOffset, maxPageBytes: limits.maxPageBytes,
|
|
68
|
+
}),
|
|
69
|
+
// Opened in the worker just as the caller gave up: nobody else knows
|
|
70
|
+
// this sourceId, so close it here or the reader lives forever.
|
|
71
|
+
(late) => session.notify({ kind: 'close', sourceId: late.sourceId }));
|
|
72
|
+
const sourceId = opened.sourceId;
|
|
73
|
+
const hierarchy = new CopcHierarchy(limits);
|
|
74
|
+
const rootRef = { offset: opened.file.info.rootHierOffset, byteSize: opened.file.info.rootHierSize };
|
|
75
|
+
try {
|
|
76
|
+
hierarchy.addPage(rootRef, opened.rootPage);
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
session.notify({ kind: 'close', sourceId });
|
|
80
|
+
throw err;
|
|
81
|
+
}
|
|
82
|
+
let closed = false;
|
|
83
|
+
const assertOpen = () => {
|
|
84
|
+
if (closed)
|
|
85
|
+
throw new Error('COPC reader is closed');
|
|
86
|
+
};
|
|
87
|
+
const readPage = async (ref, signal) => {
|
|
88
|
+
assertOpen();
|
|
89
|
+
const maxBytes = hierarchy.remainingPageBytes;
|
|
90
|
+
const resp = await cancellable(session, signal, (requestId) => ({ kind: 'copc-page', requestId, sourceId, page: ref, maxBytes }));
|
|
91
|
+
return resp.page;
|
|
92
|
+
};
|
|
93
|
+
const pageLoads = new Map();
|
|
94
|
+
return {
|
|
95
|
+
file: opened.file,
|
|
96
|
+
hierarchy,
|
|
97
|
+
originOffset: options.originOffset,
|
|
98
|
+
readPage,
|
|
99
|
+
loadPage(ref, signal) {
|
|
100
|
+
if (signal?.aborted)
|
|
101
|
+
return Promise.reject(signal.reason ?? new DOMException('Aborted', 'AbortError'));
|
|
102
|
+
const id = voxelKeyId(ref.key);
|
|
103
|
+
let shared = pageLoads.get(id);
|
|
104
|
+
if (!shared) {
|
|
105
|
+
if (!hierarchy.pendingPages.has(id))
|
|
106
|
+
return Promise.resolve();
|
|
107
|
+
try {
|
|
108
|
+
hierarchy.assertCanLoad(ref);
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
return Promise.reject(err);
|
|
112
|
+
}
|
|
113
|
+
// One read per page, owned by no single caller: each waiter races
|
|
114
|
+
// its own signal, and the read is cancelled only when all have gone.
|
|
115
|
+
const abort = new AbortController();
|
|
116
|
+
const load = { promise: Promise.resolve(), waiters: 0, abort };
|
|
117
|
+
load.promise = readPage(ref, abort.signal)
|
|
118
|
+
.then((page) => {
|
|
119
|
+
if (hierarchy.pendingPages.has(id))
|
|
120
|
+
hierarchy.addPage(ref, page);
|
|
121
|
+
})
|
|
122
|
+
.finally(() => {
|
|
123
|
+
if (pageLoads.get(id) === load)
|
|
124
|
+
pageLoads.delete(id);
|
|
125
|
+
});
|
|
126
|
+
// Waiters observe the outcome; this keeps an all-abandoned load quiet.
|
|
127
|
+
load.promise.catch(() => undefined);
|
|
128
|
+
pageLoads.set(id, load);
|
|
129
|
+
shared = load;
|
|
130
|
+
}
|
|
131
|
+
const joined = shared;
|
|
132
|
+
return joinSharedLoad(joined, signal, () => {
|
|
133
|
+
// Forget it first so a later caller starts afresh instead of joining a cancelled read.
|
|
134
|
+
if (pageLoads.get(id) === joined)
|
|
135
|
+
pageLoads.delete(id);
|
|
136
|
+
joined.abort.abort();
|
|
137
|
+
});
|
|
138
|
+
},
|
|
139
|
+
async readNode(node, opts = {}) {
|
|
140
|
+
assertOpen();
|
|
141
|
+
const resp = await cancellable(session, opts.signal, (requestId) => ({ kind: 'copc-node', requestId, sourceId, node, stride: Math.max(1, Math.floor(opts.stride ?? 1)) }));
|
|
142
|
+
if (!resp.chunk)
|
|
143
|
+
throw new Error('COPC: worker returned no chunk for a node');
|
|
144
|
+
return chunkFromWire(resp.chunk);
|
|
145
|
+
},
|
|
146
|
+
close() {
|
|
147
|
+
if (closed)
|
|
148
|
+
return;
|
|
149
|
+
closed = true;
|
|
150
|
+
session.notify({ kind: 'close', sourceId });
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=copc-worker-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copc-worker-client.js","sourceRoot":"","sources":["../../src/copc/copc-worker-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type WorkerRequest, type WorkerResponse } from '../streaming/protocol.js';
|
|
2
|
+
type Post = (msg: WorkerResponse, transfer?: Transferable[]) => void;
|
|
3
|
+
type CopcRequest = Extract<WorkerRequest, {
|
|
4
|
+
kind: 'copc-open' | 'copc-page' | 'copc-node' | 'copc-cancel';
|
|
5
|
+
}>;
|
|
6
|
+
/** Handle one COPC request; `allocateId` hands out ids shared with the stream sources. */
|
|
7
|
+
export declare function handleCopcRequest(msg: CopcRequest, post: Post, allocateId: () => number): Promise<void>;
|
|
8
|
+
/** Close a COPC reader; returns false when `sourceId` is not one. */
|
|
9
|
+
export declare function closeCopcSource(sourceId: number): boolean;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=copc-worker-host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copc-worker-host.d.ts","sourceRoot":"","sources":["../../src/copc/copc-worker-host.ts"],"names":[],"mappings":"AAaA,OAAO,EAA0C,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAI3H,KAAK,IAAI,GAAG,CAAC,GAAG,EAAE,cAAc,EAAE,QAAQ,CAAC,EAAE,YAAY,EAAE,KAAK,IAAI,CAAC;AACrE,KAAK,WAAW,GAAG,OAAO,CAAC,aAAa,EAAE;IAAE,IAAI,EAAE,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,aAAa,CAAA;CAAE,CAAC,CAAC;AAc7G,0FAA0F;AAC1F,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmC7G;AAED,qEAAqE;AACrE,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAMzD"}
|
|
@@ -0,0 +1,73 @@
|
|
|
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
|
+
* Worker-side COPC handlers (#6869). The decode worker forwards every
|
|
6
|
+
* `copc-*` request here. Readers are kept per `sourceId`; every page/node
|
|
7
|
+
* request gets its own AbortController so the LOD driver can cancel a
|
|
8
|
+
* fetch the camera no longer needs (`copc-cancel`).
|
|
9
|
+
*/
|
|
10
|
+
import { BlobByteSource } from '../streaming/blob-source.js';
|
|
11
|
+
import { HttpRangeSource } from '../streaming/http-range-source.js';
|
|
12
|
+
import { chunkToWire } from '../streaming/protocol.js';
|
|
13
|
+
import { CopcReader } from './copc-reader.js';
|
|
14
|
+
const readers = new Map();
|
|
15
|
+
const inFlight = new Map();
|
|
16
|
+
async function openSource(desc, signal) {
|
|
17
|
+
if (desc.kind === 'blob')
|
|
18
|
+
return new BlobByteSource(desc.blob);
|
|
19
|
+
return HttpRangeSource.open(desc.url, { headers: desc.headers, signal });
|
|
20
|
+
}
|
|
21
|
+
function errorMessage(err) {
|
|
22
|
+
return err instanceof Error ? err.message : String(err);
|
|
23
|
+
}
|
|
24
|
+
/** Handle one COPC request; `allocateId` hands out ids shared with the stream sources. */
|
|
25
|
+
export async function handleCopcRequest(msg, post, allocateId) {
|
|
26
|
+
if (msg.kind === 'copc-cancel') {
|
|
27
|
+
inFlight.get(msg.targetRequestId)?.abort();
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const abort = new AbortController();
|
|
31
|
+
inFlight.set(msg.requestId, abort);
|
|
32
|
+
try {
|
|
33
|
+
if (msg.kind === 'copc-open') {
|
|
34
|
+
const source = await openSource(msg.source, abort.signal);
|
|
35
|
+
const reader = await CopcReader.open(source, { originOffset: msg.originOffset, signal: abort.signal });
|
|
36
|
+
const rootPage = await reader.readPage(reader.rootPageRef, abort.signal, msg.maxPageBytes);
|
|
37
|
+
const sourceId = allocateId();
|
|
38
|
+
// Same ordering as the stream sources: report first, register after,
|
|
39
|
+
// so a failed post cannot leave an unreachable reader behind.
|
|
40
|
+
post({ kind: 'copc-opened', requestId: msg.requestId, sourceId, file: reader.file, rootPage });
|
|
41
|
+
readers.set(sourceId, { reader, closed: new AbortController() });
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const entry = readers.get(msg.sourceId);
|
|
45
|
+
if (!entry)
|
|
46
|
+
throw new Error(`Unknown COPC sourceId ${msg.sourceId}`);
|
|
47
|
+
const signal = AbortSignal.any([abort.signal, entry.closed.signal]);
|
|
48
|
+
if (msg.kind === 'copc-page') {
|
|
49
|
+
const page = await entry.reader.readPage(msg.page, signal, msg.maxBytes);
|
|
50
|
+
post({ kind: 'copc-page', requestId: msg.requestId, page });
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const chunk = await entry.reader.readNode(msg.node, { stride: msg.stride, signal });
|
|
54
|
+
const { payload, transfer } = chunkToWire(chunk);
|
|
55
|
+
post({ kind: 'chunk', requestId: msg.requestId, sourceId: msg.sourceId, chunk: payload }, transfer);
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
post({ kind: 'error', requestId: msg.requestId, message: errorMessage(err) });
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
inFlight.delete(msg.requestId);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/** Close a COPC reader; returns false when `sourceId` is not one. */
|
|
65
|
+
export function closeCopcSource(sourceId) {
|
|
66
|
+
const entry = readers.get(sourceId);
|
|
67
|
+
if (!entry)
|
|
68
|
+
return false;
|
|
69
|
+
entry.closed.abort();
|
|
70
|
+
readers.delete(sourceId);
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=copc-worker-host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copc-worker-host.js","sourceRoot":"","sources":["../../src/copc/copc-worker-host.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* The PCD schema (pcd::base64) is decoded by formats/pcd.ts; the adapter
|
|
13
13
|
* that picks between these three lives in `from-ifcx-attributes.ts`.
|
|
14
14
|
*/
|
|
15
|
+
import type { IfcxPointSource } from '../point-source.js';
|
|
15
16
|
import type { DecodedPointChunk } from '../types.js';
|
|
16
17
|
export interface PointsArrayAttribute {
|
|
17
18
|
positions: number[][];
|
|
@@ -22,5 +23,7 @@ export interface PointsBase64Attribute {
|
|
|
22
23
|
colors?: string;
|
|
23
24
|
}
|
|
24
25
|
export declare function decodePointsArray(attr: PointsArrayAttribute): DecodedPointChunk;
|
|
26
|
+
export declare function decodePointsArraySource(attr: PointsArrayAttribute): IfcxPointSource;
|
|
25
27
|
export declare function decodePointsBase64(attr: PointsBase64Attribute): DecodedPointChunk;
|
|
28
|
+
export declare function decodePointsBase64Source(attr: PointsBase64Attribute): IfcxPointSource;
|
|
26
29
|
//# sourceMappingURL=ifcx-points.d.ts.map
|
|
@@ -1 +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,
|
|
1
|
+
{"version":3,"file":"ifcx-points.d.ts","sourceRoot":"","sources":["../../src/formats/ifcx-points.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,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,CAO/E;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,oBAAoB,GAAG,eAAe,CA+CnF;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,qBAAqB,GAAG,iBAAiB,CAGjF;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,qBAAqB,GAAG,eAAe,CAOrF"}
|
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
4
|
export function decodePointsArray(attr) {
|
|
5
|
+
const source = decodePointsArraySource(attr);
|
|
6
|
+
const positions = new Float32Array(source.positions);
|
|
7
|
+
return {
|
|
8
|
+
positions, colors: source.colors ? new Float32Array(source.colors) : undefined,
|
|
9
|
+
normalState: 'absent', pointCount: source.pointCount, bbox: computeBBox(positions),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export function decodePointsArraySource(attr) {
|
|
5
13
|
if (!Array.isArray(attr.positions)) {
|
|
6
14
|
throw new Error('points::array: positions must be an array of [x,y,z] triples');
|
|
7
15
|
}
|
|
@@ -12,7 +20,7 @@ export function decodePointsArray(attr) {
|
|
|
12
20
|
// instead of returning a sentinel "empty cloud".
|
|
13
21
|
throw new Error('points::array: positions must contain at least one point');
|
|
14
22
|
}
|
|
15
|
-
const positions = new
|
|
23
|
+
const positions = new Float64Array(count * 3);
|
|
16
24
|
for (let i = 0; i < count; i++) {
|
|
17
25
|
const p = attr.positions[i];
|
|
18
26
|
if (!Array.isArray(p) || p.length < 3) {
|
|
@@ -31,7 +39,7 @@ export function decodePointsArray(attr) {
|
|
|
31
39
|
throw new Error(`points::array: colors length (${attr.colors.length}) ` +
|
|
32
40
|
`does not match positions length (${count})`);
|
|
33
41
|
}
|
|
34
|
-
colors = new
|
|
42
|
+
colors = new Float64Array(count * 3);
|
|
35
43
|
for (let i = 0; i < count; i++) {
|
|
36
44
|
const c = attr.colors[i];
|
|
37
45
|
if (!Array.isArray(c) || c.length < 3) {
|
|
@@ -45,12 +53,23 @@ export function decodePointsArray(attr) {
|
|
|
45
53
|
return {
|
|
46
54
|
positions,
|
|
47
55
|
colors,
|
|
48
|
-
|
|
56
|
+
sourcePrecision: 'f64', sourceEncoding: 'points-array',
|
|
49
57
|
pointCount: count,
|
|
50
|
-
bbox: computeBBox(positions),
|
|
51
58
|
};
|
|
52
59
|
}
|
|
53
60
|
export function decodePointsBase64(attr) {
|
|
61
|
+
const channels = decodeBase64Channels(attr);
|
|
62
|
+
return { ...channels, normalState: 'absent', bbox: computeBBox(channels.positions) };
|
|
63
|
+
}
|
|
64
|
+
export function decodePointsBase64Source(attr) {
|
|
65
|
+
const channels = decodeBase64Channels(attr);
|
|
66
|
+
return {
|
|
67
|
+
positions: new Float64Array(channels.positions),
|
|
68
|
+
colors: channels.colors ? new Float64Array(channels.colors) : undefined,
|
|
69
|
+
pointCount: channels.pointCount, sourcePrecision: 'f32', sourceEncoding: 'points-base64',
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function decodeBase64Channels(attr) {
|
|
54
73
|
if (typeof attr.positions !== 'string' || attr.positions.length === 0) {
|
|
55
74
|
throw new Error('points::base64: positions must be a non-empty base64 string');
|
|
56
75
|
}
|
|
@@ -80,9 +99,7 @@ export function decodePointsBase64(attr) {
|
|
|
80
99
|
return {
|
|
81
100
|
positions,
|
|
82
101
|
colors,
|
|
83
|
-
normalState: 'absent',
|
|
84
102
|
pointCount: count,
|
|
85
|
-
bbox: computeBBox(positions),
|
|
86
103
|
};
|
|
87
104
|
}
|
|
88
105
|
// ─── helpers ────────────────────────────────────────────────────────────────
|
|
@@ -106,7 +123,6 @@ function base64ToBytes(b64) {
|
|
|
106
123
|
out[i] = binary.charCodeAt(i);
|
|
107
124
|
return out;
|
|
108
125
|
}
|
|
109
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
110
126
|
const buf = globalThis.Buffer;
|
|
111
127
|
if (buf && typeof buf.from === 'function') {
|
|
112
128
|
return new Uint8Array(buf.from(b64, 'base64'));
|