@ifc-lite/pointcloud 0.7.2 → 0.9.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 +35 -0
- package/dist/formats/ascii-points.d.ts.map +1 -1
- package/dist/formats/ascii-points.js +1 -0
- package/dist/formats/ascii-points.js.map +1 -1
- package/dist/formats/e57-decode.js +1 -1
- package/dist/formats/e57-decode.js.map +1 -1
- package/dist/formats/e57.d.ts.map +1 -1
- package/dist/formats/e57.js +1 -0
- package/dist/formats/e57.js.map +1 -1
- package/dist/formats/ifcx-points.d.ts.map +1 -1
- package/dist/formats/ifcx-points.js +2 -0
- package/dist/formats/ifcx-points.js.map +1 -1
- package/dist/formats/las.d.ts.map +1 -1
- package/dist/formats/las.js +43 -12
- package/dist/formats/las.js.map +1 -1
- package/dist/formats/pcd.js +1 -1
- package/dist/formats/pcd.js.map +1 -1
- package/dist/formats/ply-color.d.ts +2 -0
- package/dist/formats/ply-color.d.ts.map +1 -1
- package/dist/formats/ply-color.js +6 -1
- package/dist/formats/ply-color.js.map +1 -1
- package/dist/formats/ply-fixed-binary.d.ts +9 -0
- package/dist/formats/ply-fixed-binary.d.ts.map +1 -0
- package/dist/formats/ply-fixed-binary.js +60 -0
- package/dist/formats/ply-fixed-binary.js.map +1 -0
- package/dist/formats/ply-scalar.d.ts +6 -0
- package/dist/formats/ply-scalar.d.ts.map +1 -0
- package/dist/formats/ply-scalar.js +25 -0
- package/dist/formats/ply-scalar.js.map +1 -0
- package/dist/formats/ply-variable-row.d.ts +15 -0
- package/dist/formats/ply-variable-row.d.ts.map +1 -0
- package/dist/formats/ply-variable-row.js +66 -0
- package/dist/formats/ply-variable-row.js.map +1 -0
- package/dist/formats/ply.d.ts +36 -10
- package/dist/formats/ply.d.ts.map +1 -1
- package/dist/formats/ply.js +83 -83
- package/dist/formats/ply.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/streaming/ascii-points-source.js +1 -0
- package/dist/streaming/ascii-points-source.js.map +1 -1
- package/dist/streaming/decode-worker.js +2 -1
- package/dist/streaming/decode-worker.js.map +1 -1
- package/dist/streaming/e57-source.js +1 -1
- package/dist/streaming/e57-source.js.map +1 -1
- package/dist/streaming/host.d.ts +3 -0
- package/dist/streaming/host.d.ts.map +1 -1
- package/dist/streaming/host.js +25 -10
- package/dist/streaming/host.js.map +1 -1
- package/dist/streaming/inline-worker.js +1 -1
- package/dist/streaming/pcd-source.js +1 -0
- package/dist/streaming/pcd-source.js.map +1 -1
- package/dist/streaming/ply-source.d.ts +9 -17
- package/dist/streaming/ply-source.d.ts.map +1 -1
- package/dist/streaming/ply-source.js +39 -69
- package/dist/streaming/ply-source.js.map +1 -1
- package/dist/streaming/ply-stream-decode.d.ts +32 -0
- package/dist/streaming/ply-stream-decode.d.ts.map +1 -0
- package/dist/streaming/ply-stream-decode.js +363 -0
- package/dist/streaming/ply-stream-decode.js.map +1 -0
- package/dist/streaming/ply-variable-stream.d.ts +15 -0
- package/dist/streaming/ply-variable-stream.d.ts.map +1 -0
- package/dist/streaming/ply-variable-stream.js +73 -0
- package/dist/streaming/ply-variable-stream.js.map +1 -0
- package/dist/streaming/protocol.d.ts +3 -1
- package/dist/streaming/protocol.d.ts.map +1 -1
- package/dist/streaming/protocol.js +18 -4
- package/dist/streaming/protocol.js.map +1 -1
- package/dist/streaming/stride.d.ts +3 -0
- package/dist/streaming/stride.d.ts.map +1 -0
- package/dist/streaming/stride.js +9 -0
- package/dist/streaming/stride.js.map +1 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { PlyPropertyDecl } from './ply.js';
|
|
2
|
+
interface FixedBinaryLayout {
|
|
3
|
+
count: number;
|
|
4
|
+
recordSize: number;
|
|
5
|
+
properties: PlyPropertyDecl[];
|
|
6
|
+
}
|
|
7
|
+
export declare function decodeFixedBinaryPlyBody(view: DataView, vertex: FixedBinaryLayout, positions: Float32Array, colors: Float32Array | undefined, normals: Float32Array | undefined, intensities: Uint16Array | undefined, littleEndian: boolean, originOffset?: readonly [number, number, number]): void;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=ply-fixed-binary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ply-fixed-binary.d.ts","sourceRoot":"","sources":["../../src/formats/ply-fixed-binary.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD,UAAU,iBAAiB;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,eAAe,EAAE,CAAC;CAC/B;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,iBAAiB,EAAE,SAAS,EAAE,YAAY,EAClE,MAAM,EAAE,YAAY,GAAG,SAAS,EAAE,OAAO,EAAE,YAAY,GAAG,SAAS,EACnE,WAAW,EAAE,WAAW,GAAG,SAAS,EAAE,YAAY,EAAE,OAAO,EAC3D,YAAY,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAC/C,IAAI,CAmCN"}
|
|
@@ -0,0 +1,60 @@
|
|
|
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
|
+
export function decodeFixedBinaryPlyBody(view, vertex, positions, colors, normals, intensities, littleEndian, originOffset) {
|
|
5
|
+
const offX = originOffset?.[0] ?? 0;
|
|
6
|
+
const offY = originOffset?.[1] ?? 0;
|
|
7
|
+
const offZ = originOffset?.[2] ?? 0;
|
|
8
|
+
const find = (name) => vertex.properties.find((property) => property.name === name);
|
|
9
|
+
const xProp = find('x');
|
|
10
|
+
const yProp = find('y');
|
|
11
|
+
const zProp = find('z');
|
|
12
|
+
const rProp = colors ? find('red') ?? find('r') : undefined;
|
|
13
|
+
const gProp = colors ? find('green') ?? find('g') : undefined;
|
|
14
|
+
const bProp = colors ? find('blue') ?? find('b') : undefined;
|
|
15
|
+
const nxProp = normals ? find('nx') : undefined;
|
|
16
|
+
const nyProp = normals ? find('ny') : undefined;
|
|
17
|
+
const nzProp = normals ? find('nz') : undefined;
|
|
18
|
+
const iProp = intensities ? find('intensity') ?? find('scalar_Intensity') : undefined;
|
|
19
|
+
for (let i = 0; i < vertex.count; i++) {
|
|
20
|
+
const base = i * vertex.recordSize;
|
|
21
|
+
positions[i * 3] = readScalar(view, base + xProp.offset, xProp.type, littleEndian) - offX;
|
|
22
|
+
positions[i * 3 + 1] = readScalar(view, base + yProp.offset, yProp.type, littleEndian) - offY;
|
|
23
|
+
positions[i * 3 + 2] = readScalar(view, base + zProp.offset, zProp.type, littleEndian) - offZ;
|
|
24
|
+
if (colors && rProp && gProp && bProp) {
|
|
25
|
+
colors[i * 3] = readScalar(view, base + rProp.offset, rProp.type, littleEndian);
|
|
26
|
+
colors[i * 3 + 1] = readScalar(view, base + gProp.offset, gProp.type, littleEndian);
|
|
27
|
+
colors[i * 3 + 2] = readScalar(view, base + bProp.offset, bProp.type, littleEndian);
|
|
28
|
+
}
|
|
29
|
+
if (normals && nxProp && nyProp && nzProp) {
|
|
30
|
+
normals[i * 3] = readScalar(view, base + nxProp.offset, nxProp.type, littleEndian);
|
|
31
|
+
normals[i * 3 + 1] = readScalar(view, base + nyProp.offset, nyProp.type, littleEndian);
|
|
32
|
+
normals[i * 3 + 2] = readScalar(view, base + nzProp.offset, nzProp.type, littleEndian);
|
|
33
|
+
}
|
|
34
|
+
if (intensities && iProp) {
|
|
35
|
+
intensities[i] = Math.min(65535, Math.max(0, readScalar(view, base + iProp.offset, iProp.type, littleEndian) | 0));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function readScalar(view, offset, type, littleEndian) {
|
|
40
|
+
switch (type) {
|
|
41
|
+
case 'char':
|
|
42
|
+
case 'int8': return view.getInt8(offset);
|
|
43
|
+
case 'uchar':
|
|
44
|
+
case 'uint8': return view.getUint8(offset);
|
|
45
|
+
case 'short':
|
|
46
|
+
case 'int16': return view.getInt16(offset, littleEndian);
|
|
47
|
+
case 'ushort':
|
|
48
|
+
case 'uint16': return view.getUint16(offset, littleEndian);
|
|
49
|
+
case 'int':
|
|
50
|
+
case 'int32': return view.getInt32(offset, littleEndian);
|
|
51
|
+
case 'uint':
|
|
52
|
+
case 'uint32': return view.getUint32(offset, littleEndian);
|
|
53
|
+
case 'float':
|
|
54
|
+
case 'float32': return view.getFloat32(offset, littleEndian);
|
|
55
|
+
case 'double':
|
|
56
|
+
case 'float64': return view.getFloat64(offset, littleEndian);
|
|
57
|
+
default: throw new Error(`PLY: cannot read scalar of type "${type}"`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=ply-fixed-binary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ply-fixed-binary.js","sourceRoot":"","sources":["../../src/formats/ply-fixed-binary.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ply-scalar.d.ts","sourceRoot":"","sources":["../../src/formats/ply-scalar.ts"],"names":[],"mappings":"AAIA,UAAU,cAAc;IAAG,IAAI,EAAE,MAAM,CAAA;CAAE;AAEzC,wBAAgB,aAAa,CAC3B,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,cAAc,EACpB,YAAY,EAAE,OAAO,GACpB,MAAM,CAoBR"}
|
|
@@ -0,0 +1,25 @@
|
|
|
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
|
+
export function readPlyScalar(view, offset, prop, littleEndian) {
|
|
5
|
+
switch (prop.type) {
|
|
6
|
+
case 'char':
|
|
7
|
+
case 'int8': return view.getInt8(offset);
|
|
8
|
+
case 'uchar':
|
|
9
|
+
case 'uint8': return view.getUint8(offset);
|
|
10
|
+
case 'short':
|
|
11
|
+
case 'int16': return view.getInt16(offset, littleEndian);
|
|
12
|
+
case 'ushort':
|
|
13
|
+
case 'uint16': return view.getUint16(offset, littleEndian);
|
|
14
|
+
case 'int':
|
|
15
|
+
case 'int32': return view.getInt32(offset, littleEndian);
|
|
16
|
+
case 'uint':
|
|
17
|
+
case 'uint32': return view.getUint32(offset, littleEndian);
|
|
18
|
+
case 'float':
|
|
19
|
+
case 'float32': return view.getFloat32(offset, littleEndian);
|
|
20
|
+
case 'double':
|
|
21
|
+
case 'float64': return view.getFloat64(offset, littleEndian);
|
|
22
|
+
default: throw new Error(`PLY: cannot read scalar of type "${prop.type}"`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=ply-scalar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ply-scalar.js","sourceRoot":"","sources":["../../src/formats/ply-scalar.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAI/D,MAAM,UAAU,aAAa,CAC3B,IAAc,EACd,MAAc,EACd,IAAoB,EACpB,YAAqB;IAErB,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,MAAM,CAAC;QACZ,KAAK,MAAM,CAAC,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACzC,KAAK,OAAO,CAAC;QACb,KAAK,OAAO,CAAC,CAAC,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC3C,KAAK,OAAO,CAAC;QACb,KAAK,OAAO,CAAC,CAAC,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QACzD,KAAK,QAAQ,CAAC;QACd,KAAK,QAAQ,CAAC,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QAC3D,KAAK,KAAK,CAAC;QACX,KAAK,OAAO,CAAC,CAAC,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QACzD,KAAK,MAAM,CAAC;QACZ,KAAK,QAAQ,CAAC,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QAC3D,KAAK,OAAO,CAAC;QACb,KAAK,SAAS,CAAC,CAAC,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QAC7D,KAAK,QAAQ,CAAC;QACd,KAAK,SAAS,CAAC,CAAC,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QAC7D,OAAO,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,oCAAoC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;IAC7E,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { PlyPropertyOrderEntry } from './ply.js';
|
|
2
|
+
export declare function parseAsciiVariableRow(tokens: readonly string[], order: readonly PlyPropertyOrderEntry[], row: number): Map<string, number>;
|
|
3
|
+
export declare function parseBinaryVariableRow(view: DataView, start: number, order: readonly PlyPropertyOrderEntry[], littleEndian: boolean, row: number): {
|
|
4
|
+
values: Map<string, number>;
|
|
5
|
+
end: number;
|
|
6
|
+
};
|
|
7
|
+
export interface VariablePlyOutputs {
|
|
8
|
+
positions: Float32Array;
|
|
9
|
+
colors?: Float32Array;
|
|
10
|
+
normals?: Float32Array;
|
|
11
|
+
intensities?: Uint16Array;
|
|
12
|
+
originOffset?: readonly [number, number, number];
|
|
13
|
+
}
|
|
14
|
+
export declare function writeVariablePlyRow(values: ReadonlyMap<string, number>, row: number, output: VariablePlyOutputs): void;
|
|
15
|
+
//# sourceMappingURL=ply-variable-row.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ply-variable-row.d.ts","sourceRoot":"","sources":["../../src/formats/ply-variable-row.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAGtD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,SAAS,qBAAqB,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAe1I;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,qBAAqB,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAkB/L;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,YAAY,CAAC;IAAC,MAAM,CAAC,EAAE,YAAY,CAAC;IAAC,OAAO,CAAC,EAAE,YAAY,CAAC;IAAC,WAAW,CAAC,EAAE,WAAW,CAAC;IAClG,YAAY,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;CAClD;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,GAAG,IAAI,CAmBtH"}
|
|
@@ -0,0 +1,66 @@
|
|
|
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 { readPlyScalar } from './ply-scalar.js';
|
|
5
|
+
export function parseAsciiVariableRow(tokens, order, row) {
|
|
6
|
+
const values = new Map();
|
|
7
|
+
let cursor = 0;
|
|
8
|
+
for (const entry of order) {
|
|
9
|
+
if (entry.kind === 'scalar') {
|
|
10
|
+
if (cursor >= tokens.length)
|
|
11
|
+
throw new Error(`PLY ascii: vertex row ${row + 1} is missing property ${entry.property.name}`);
|
|
12
|
+
values.set(entry.property.name, Number(tokens[cursor++]));
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
const count = Number(tokens[cursor++]);
|
|
16
|
+
if (!Number.isSafeInteger(count) || count < 0 || cursor + count > tokens.length)
|
|
17
|
+
throw new Error(`PLY ascii: vertex row ${row + 1} has an invalid ${entry.name} list`);
|
|
18
|
+
cursor += count;
|
|
19
|
+
}
|
|
20
|
+
if (cursor !== tokens.length)
|
|
21
|
+
throw new Error(`PLY ascii: vertex row ${row + 1} has unexpected trailing values`);
|
|
22
|
+
return values;
|
|
23
|
+
}
|
|
24
|
+
export function parseBinaryVariableRow(view, start, order, littleEndian, row) {
|
|
25
|
+
const values = new Map();
|
|
26
|
+
let cursor = start;
|
|
27
|
+
for (const entry of order) {
|
|
28
|
+
if (entry.kind === 'scalar') {
|
|
29
|
+
if (cursor + entry.property.size > view.byteLength)
|
|
30
|
+
throw new Error(`PLY binary: vertex row ${row + 1} is truncated`);
|
|
31
|
+
values.set(entry.property.name, readPlyScalar(view, cursor, entry.property, littleEndian));
|
|
32
|
+
cursor += entry.property.size;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (cursor + entry.countSize > view.byteLength)
|
|
36
|
+
throw new Error(`PLY binary: vertex row ${row + 1} list count is truncated`);
|
|
37
|
+
const count = readPlyScalar(view, cursor, { type: entry.countType }, littleEndian);
|
|
38
|
+
cursor += entry.countSize;
|
|
39
|
+
const bytes = count * entry.itemSize;
|
|
40
|
+
if (!Number.isSafeInteger(count) || count < 0 || cursor + bytes > view.byteLength)
|
|
41
|
+
throw new Error(`PLY binary: vertex row ${row + 1} has an invalid ${entry.name} list`);
|
|
42
|
+
cursor += bytes;
|
|
43
|
+
}
|
|
44
|
+
return { values, end: cursor };
|
|
45
|
+
}
|
|
46
|
+
export function writeVariablePlyRow(values, row, output) {
|
|
47
|
+
const origin = output.originOffset ?? [0, 0, 0];
|
|
48
|
+
output.positions[row * 3] = (values.get('x') ?? Number.NaN) - origin[0];
|
|
49
|
+
output.positions[row * 3 + 1] = (values.get('y') ?? Number.NaN) - origin[1];
|
|
50
|
+
output.positions[row * 3 + 2] = (values.get('z') ?? Number.NaN) - origin[2];
|
|
51
|
+
if (output.colors) {
|
|
52
|
+
output.colors[row * 3] = values.get('red') ?? values.get('r') ?? Number.NaN;
|
|
53
|
+
output.colors[row * 3 + 1] = values.get('green') ?? values.get('g') ?? Number.NaN;
|
|
54
|
+
output.colors[row * 3 + 2] = values.get('blue') ?? values.get('b') ?? Number.NaN;
|
|
55
|
+
}
|
|
56
|
+
if (output.normals) {
|
|
57
|
+
output.normals[row * 3] = values.get('nx') ?? Number.NaN;
|
|
58
|
+
output.normals[row * 3 + 1] = values.get('ny') ?? Number.NaN;
|
|
59
|
+
output.normals[row * 3 + 2] = values.get('nz') ?? Number.NaN;
|
|
60
|
+
}
|
|
61
|
+
if (output.intensities) {
|
|
62
|
+
const value = values.get('intensity') ?? values.get('scalar_Intensity') ?? 0;
|
|
63
|
+
output.intensities[row] = Math.min(65535, Math.max(0, value | 0));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=ply-variable-row.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ply-variable-row.js","sourceRoot":"","sources":["../../src/formats/ply-variable-row.ts"],"names":[],"mappings":"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"}
|
package/dist/formats/ply.d.ts
CHANGED
|
@@ -7,23 +7,37 @@
|
|
|
7
7
|
* meshes but not for the scan-style files this viewer ingests).
|
|
8
8
|
*
|
|
9
9
|
* Position fields (x/y/z) are required. RGB (r/g/b or red/green/blue,
|
|
10
|
-
* uchar)
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
10
|
+
* uchar), complete source normals (nx/ny/nz) and intensity
|
|
11
|
+
* (intensity, uchar/ushort/float) are optional and surfaced when present.
|
|
12
|
+
* `decodePly` is the direct whole-buffer API. The canonical Open/Add path
|
|
13
|
+
* uses `PlyStreamingSource`, whose bounded decoder never allocates full-count
|
|
14
|
+
* channels before applying its host-selected stride.
|
|
14
15
|
*/
|
|
15
|
-
import type { DecodedPointChunk } from '../types.js';
|
|
16
|
-
interface
|
|
16
|
+
import type { DecodedPointChunk, PointNormalState } from '../types.js';
|
|
17
|
+
export interface PlyPropertyDecl {
|
|
17
18
|
name: string;
|
|
18
19
|
type: string;
|
|
19
20
|
size: number;
|
|
20
21
|
/** Byte offset within a single vertex record (binary mode only). */
|
|
21
22
|
offset: number;
|
|
22
23
|
}
|
|
23
|
-
interface
|
|
24
|
+
export interface PlyListPropertyDecl {
|
|
25
|
+
kind: 'list';
|
|
26
|
+
name: string;
|
|
27
|
+
countType: string;
|
|
28
|
+
itemType: string;
|
|
29
|
+
countSize: number;
|
|
30
|
+
itemSize: number;
|
|
31
|
+
}
|
|
32
|
+
export type PlyPropertyOrderEntry = {
|
|
33
|
+
kind: 'scalar';
|
|
34
|
+
property: PlyPropertyDecl;
|
|
35
|
+
} | PlyListPropertyDecl;
|
|
36
|
+
export interface PlyElementDecl {
|
|
24
37
|
name: string;
|
|
25
38
|
count: number;
|
|
26
|
-
properties:
|
|
39
|
+
properties: PlyPropertyDecl[];
|
|
40
|
+
propertyOrder: PlyPropertyOrderEntry[];
|
|
27
41
|
/** Bytes per record (binary mode); unused for ascii. */
|
|
28
42
|
recordSize: number;
|
|
29
43
|
/**
|
|
@@ -33,15 +47,28 @@ interface ElementDecl {
|
|
|
33
47
|
* decoders walk with a fixed stride.
|
|
34
48
|
*/
|
|
35
49
|
hasListProperty: boolean;
|
|
50
|
+
listPropertyNames: string[];
|
|
36
51
|
}
|
|
37
52
|
export interface PlyHeader {
|
|
38
53
|
format: 'ascii' | 'binary_little_endian' | 'binary_big_endian';
|
|
39
54
|
version: string;
|
|
40
|
-
elements:
|
|
55
|
+
elements: PlyElementDecl[];
|
|
41
56
|
/** Byte offset where the body data starts. */
|
|
42
57
|
bodyOffset: number;
|
|
43
58
|
}
|
|
44
59
|
export declare function parsePlyHeader(buffer: Uint8Array): PlyHeader;
|
|
60
|
+
export interface PlyVertexLayout {
|
|
61
|
+
vertex: PlyElementDecl;
|
|
62
|
+
xProp: PlyPropertyDecl;
|
|
63
|
+
yProp: PlyPropertyDecl;
|
|
64
|
+
zProp: PlyPropertyDecl;
|
|
65
|
+
nxProp?: PlyPropertyDecl;
|
|
66
|
+
nyProp?: PlyPropertyDecl;
|
|
67
|
+
nzProp?: PlyPropertyDecl;
|
|
68
|
+
normalState: PointNormalState;
|
|
69
|
+
}
|
|
70
|
+
/** Validate the fixed-row vertex schema shared by whole-file and streaming decode. */
|
|
71
|
+
export declare function inspectPlyVertex(header: PlyHeader): PlyVertexLayout;
|
|
45
72
|
export declare function decodePly(buffer: Uint8Array,
|
|
46
73
|
/**
|
|
47
74
|
* Native (X, Y, Z)-axis offset subtracted from each decoded vertex in
|
|
@@ -51,5 +78,4 @@ export declare function decodePly(buffer: Uint8Array,
|
|
|
51
78
|
* byte-for-byte.
|
|
52
79
|
*/
|
|
53
80
|
originOffset?: readonly [number, number, number]): DecodedPointChunk;
|
|
54
|
-
export {};
|
|
55
81
|
//# sourceMappingURL=ply.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ply.d.ts","sourceRoot":"","sources":["../../src/formats/ply.ts"],"names":[],"mappings":"AAIA
|
|
1
|
+
{"version":3,"file":"ply.d.ts","sourceRoot":"","sources":["../../src/formats/ply.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAkB,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAavF,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAChE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;CACrC;AAED,MAAM,MAAM,qBAAqB,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,eAAe,CAAA;CAAE,GAAG,mBAAmB,CAAC;AAExG,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,aAAa,EAAE,qBAAqB,EAAE,CAAC;IACvC,wDAAwD;IACxD,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,eAAe,EAAE,OAAO,CAAC;IACzB,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,OAAO,GAAG,sBAAsB,GAAG,mBAAmB,CAAC;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAC;CACpB;AAID,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,CAiG5D;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,EAAE,eAAe,CAAC;IAAC,KAAK,EAAE,eAAe,CAAC;IAAC,KAAK,EAAE,eAAe,CAAC;IACvE,MAAM,CAAC,EAAE,eAAe,CAAC;IAAC,MAAM,CAAC,EAAE,eAAe,CAAC;IAAC,MAAM,CAAC,EAAE,eAAe,CAAC;IAC7E,WAAW,EAAE,gBAAgB,CAAC;CAC/B;AAED,sFAAsF;AACtF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,GAAG,eAAe,CAqBnE;AAED,wBAAgB,SAAS,CACvB,MAAM,EAAE,UAAU;AAClB;;;;;;GAMG;AACH,YAAY,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAC/C,iBAAiB,CAiFnB"}
|
package/dist/formats/ply.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
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
|
import { normalizePlyColors } from './ply-color.js';
|
|
5
|
+
import { parseAsciiVariableRow, parseBinaryVariableRow, writeVariablePlyRow } from './ply-variable-row.js';
|
|
6
|
+
import { decodeFixedBinaryPlyBody } from './ply-fixed-binary.js';
|
|
5
7
|
/** Name → byte size for the PLY-defined scalar types. */
|
|
6
8
|
const TYPE_SIZES = {
|
|
7
9
|
char: 1, int8: 1, uchar: 1, uint8: 1,
|
|
@@ -65,8 +67,10 @@ export function parsePlyHeader(buffer) {
|
|
|
65
67
|
name: parts[1],
|
|
66
68
|
count: parseInt(parts[2], 10),
|
|
67
69
|
properties: [],
|
|
70
|
+
propertyOrder: [],
|
|
68
71
|
recordSize: 0,
|
|
69
72
|
hasListProperty: false,
|
|
73
|
+
listPropertyNames: [],
|
|
70
74
|
};
|
|
71
75
|
elements.push(current);
|
|
72
76
|
continue;
|
|
@@ -80,7 +84,13 @@ export function parsePlyHeader(buffer) {
|
|
|
80
84
|
// fact and skip them — harmless on elements we never decode, rejected
|
|
81
85
|
// for the vertex element in decodePly.
|
|
82
86
|
if (parts[1] === 'list') {
|
|
87
|
+
const countType = parts[2], itemType = parts[3], name = parts[4];
|
|
88
|
+
const countSize = TYPE_SIZES[countType], itemSize = TYPE_SIZES[itemType];
|
|
89
|
+
if (!name || countSize === undefined || itemSize === undefined)
|
|
90
|
+
throw new Error(`PLY: invalid list property declaration "${line}"`);
|
|
83
91
|
current.hasListProperty = true;
|
|
92
|
+
current.listPropertyNames.push(name);
|
|
93
|
+
current.propertyOrder.push({ kind: 'list', name, countType, itemType, countSize, itemSize });
|
|
84
94
|
continue;
|
|
85
95
|
}
|
|
86
96
|
const type = parts[1];
|
|
@@ -89,7 +99,9 @@ export function parsePlyHeader(buffer) {
|
|
|
89
99
|
if (size === undefined) {
|
|
90
100
|
throw new Error(`PLY: unknown property type "${type}"`);
|
|
91
101
|
}
|
|
92
|
-
|
|
102
|
+
const property = { name, type, size, offset: current.recordSize };
|
|
103
|
+
current.properties.push(property);
|
|
104
|
+
current.propertyOrder.push({ kind: 'scalar', property });
|
|
93
105
|
current.recordSize += size;
|
|
94
106
|
continue;
|
|
95
107
|
}
|
|
@@ -101,6 +113,32 @@ export function parsePlyHeader(buffer) {
|
|
|
101
113
|
}
|
|
102
114
|
return { format, version, elements, bodyOffset };
|
|
103
115
|
}
|
|
116
|
+
/** Validate the fixed-row vertex schema shared by whole-file and streaming decode. */
|
|
117
|
+
export function inspectPlyVertex(header) {
|
|
118
|
+
const vertex = header.elements.find((element) => element.name === 'vertex');
|
|
119
|
+
if (!vertex)
|
|
120
|
+
throw new Error('PLY: no vertex element');
|
|
121
|
+
if (header.elements[0] !== vertex) {
|
|
122
|
+
throw new Error(`PLY: vertex element must appear first; saw "${header.elements[0]?.name}" first`);
|
|
123
|
+
}
|
|
124
|
+
const normalNames = new Set(['nx', 'ny', 'nz']);
|
|
125
|
+
const one = (name) => {
|
|
126
|
+
const matches = vertex.properties.filter((property) => property.name === name);
|
|
127
|
+
if (matches.length > 1)
|
|
128
|
+
throw new Error(`PLY: vertex property "${name}" must not be declared more than once`);
|
|
129
|
+
return matches[0];
|
|
130
|
+
};
|
|
131
|
+
const xProp = one('x'), yProp = one('y'), zProp = one('z');
|
|
132
|
+
if (!xProp || !yProp || !zProp)
|
|
133
|
+
throw new Error('PLY: vertex element must define x, y, z properties');
|
|
134
|
+
const normalProps = (name) => vertex.properties.filter((property) => property.name === name);
|
|
135
|
+
const nx = normalProps('nx'), ny = normalProps('ny'), nz = normalProps('nz');
|
|
136
|
+
const declared = nx.length + ny.length + nz.length + vertex.listPropertyNames.filter((name) => normalNames.has(name)).length;
|
|
137
|
+
const complete = declared === 3 && nx.length === 1 && ny.length === 1 && nz.length === 1;
|
|
138
|
+
return { vertex, xProp, yProp, zProp, nxProp: complete ? nx[0] : undefined,
|
|
139
|
+
nyProp: complete ? ny[0] : undefined, nzProp: complete ? nz[0] : undefined,
|
|
140
|
+
normalState: declared === 0 ? 'absent' : complete ? 'supplied' : 'invalid' };
|
|
141
|
+
}
|
|
104
142
|
export function decodePly(buffer,
|
|
105
143
|
/**
|
|
106
144
|
* Native (X, Y, Z)-axis offset subtracted from each decoded vertex in
|
|
@@ -111,32 +149,13 @@ export function decodePly(buffer,
|
|
|
111
149
|
*/
|
|
112
150
|
originOffset) {
|
|
113
151
|
const header = parsePlyHeader(buffer);
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
throw new Error('PLY: no vertex element');
|
|
117
|
-
// Both decoders start at header.bodyOffset, so vertex MUST be the first
|
|
118
|
-
// element. Files that declare another element first would silently
|
|
119
|
-
// produce garbage point data otherwise. Reject deterministically.
|
|
120
|
-
if (header.elements[0] !== vertex) {
|
|
121
|
-
throw new Error(`PLY: vertex element must appear first; saw "${header.elements[0]?.name}" first`);
|
|
122
|
-
}
|
|
123
|
-
// A list property on the vertex element makes its records variable length:
|
|
124
|
-
// `recordSize` (binary stride) and the ascii column map would both drift and
|
|
125
|
-
// silently read garbage. Reject up front; list properties on OTHER elements
|
|
126
|
-
// (face indices) stay fine because those elements are never decoded.
|
|
127
|
-
if (vertex.hasListProperty) {
|
|
128
|
-
throw new Error('PLY: list-valued properties on the vertex element are not supported (variable-length records)');
|
|
129
|
-
}
|
|
130
|
-
const xProp = vertex.properties.find((p) => p.name === 'x');
|
|
131
|
-
const yProp = vertex.properties.find((p) => p.name === 'y');
|
|
132
|
-
const zProp = vertex.properties.find((p) => p.name === 'z');
|
|
133
|
-
if (!xProp || !yProp || !zProp) {
|
|
134
|
-
throw new Error('PLY: vertex element must define x, y, z properties');
|
|
135
|
-
}
|
|
152
|
+
const layout = inspectPlyVertex(header);
|
|
153
|
+
const { vertex } = layout;
|
|
136
154
|
const rProp = vertex.properties.find((p) => p.name === 'red' || p.name === 'r');
|
|
137
155
|
const gProp = vertex.properties.find((p) => p.name === 'green' || p.name === 'g');
|
|
138
156
|
const bProp = vertex.properties.find((p) => p.name === 'blue' || p.name === 'b');
|
|
139
157
|
const hasRgb = !!(rProp && gProp && bProp);
|
|
158
|
+
const { nxProp, nyProp, nzProp } = layout;
|
|
140
159
|
const intensityProp = vertex.properties.find((p) => p.name === 'intensity' || p.name === 'scalar_Intensity');
|
|
141
160
|
const count = vertex.count;
|
|
142
161
|
if (!Number.isFinite(count) || count < 0) {
|
|
@@ -163,12 +182,34 @@ originOffset) {
|
|
|
163
182
|
}
|
|
164
183
|
const positions = new Float32Array(count * 3);
|
|
165
184
|
const colors = hasRgb ? new Float32Array(count * 3) : undefined;
|
|
185
|
+
const normals = nxProp && nyProp && nzProp ? new Float32Array(count * 3) : undefined;
|
|
166
186
|
const intensities = intensityProp ? new Uint16Array(count) : undefined;
|
|
167
187
|
if (header.format === 'ascii') {
|
|
168
|
-
|
|
188
|
+
if (vertex.hasListProperty) {
|
|
189
|
+
const lines = TEXT_DECODER.decode(buffer.subarray(header.bodyOffset)).split(/\r?\n/).filter(line => line.trim());
|
|
190
|
+
if (lines.length < count)
|
|
191
|
+
throw new Error(`PLY ascii: expected ${count} vertex lines, got ${lines.length}`);
|
|
192
|
+
for (let row = 0; row < count; row++)
|
|
193
|
+
writeVariablePlyRow(parseAsciiVariableRow(lines[row].trim().split(/\s+/), vertex.propertyOrder, row), row, { positions, colors, normals, intensities, originOffset });
|
|
194
|
+
}
|
|
195
|
+
else
|
|
196
|
+
decodeAsciiBody(buffer, header, vertex, positions, colors, normals, intensities, originOffset);
|
|
169
197
|
}
|
|
170
198
|
else {
|
|
171
|
-
|
|
199
|
+
const littleEndian = header.format === 'binary_little_endian';
|
|
200
|
+
if (vertex.hasListProperty) {
|
|
201
|
+
const view = new DataView(buffer.buffer, buffer.byteOffset + header.bodyOffset, buffer.length - header.bodyOffset);
|
|
202
|
+
let cursor = 0;
|
|
203
|
+
for (let row = 0; row < count; row++) {
|
|
204
|
+
const parsed = parseBinaryVariableRow(view, cursor, vertex.propertyOrder, littleEndian, row);
|
|
205
|
+
writeVariablePlyRow(parsed.values, row, { positions, colors, normals, intensities, originOffset });
|
|
206
|
+
cursor = parsed.end;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
const view = new DataView(buffer.buffer, buffer.byteOffset + header.bodyOffset, count * vertex.recordSize);
|
|
211
|
+
decodeFixedBinaryPlyBody(view, vertex, positions, colors, normals, intensities, littleEndian, originOffset);
|
|
212
|
+
}
|
|
172
213
|
}
|
|
173
214
|
if (colors && rProp && gProp && bProp) {
|
|
174
215
|
normalizePlyColors(colors, [rProp.type, gProp.type, bProp.type]);
|
|
@@ -176,13 +217,20 @@ originOffset) {
|
|
|
176
217
|
return {
|
|
177
218
|
positions,
|
|
178
219
|
colors,
|
|
220
|
+
normals,
|
|
221
|
+
normalState: normals && normals.every(Number.isFinite) && everyNormalNonzero(normals) ? 'supplied' : layout.normalState === 'supplied' ? 'invalid' : layout.normalState,
|
|
179
222
|
intensities,
|
|
180
223
|
pointCount: count,
|
|
181
224
|
bbox: computeBBox(positions),
|
|
182
225
|
};
|
|
183
226
|
}
|
|
184
|
-
|
|
185
|
-
|
|
227
|
+
function everyNormalNonzero(normals) {
|
|
228
|
+
for (let i = 0; i < normals.length; i += 3)
|
|
229
|
+
if (normals[i] ** 2 + normals[i + 1] ** 2 + normals[i + 2] ** 2 === 0)
|
|
230
|
+
return false;
|
|
231
|
+
return true;
|
|
232
|
+
}
|
|
233
|
+
function decodeAsciiBody(buffer, header, vertex, positions, colors, normals, intensities, originOffset) {
|
|
186
234
|
// Decode just the vertex part of the body (other elements come after).
|
|
187
235
|
// For ascii, each line = one vertex (in the order properties were
|
|
188
236
|
// declared).
|
|
@@ -196,6 +244,9 @@ function decodeAsciiBody(buffer, header, vertex, positions, colors, intensities,
|
|
|
196
244
|
const rCol = vertex.properties.findIndex((p) => p.name === 'red' || p.name === 'r');
|
|
197
245
|
const gCol = vertex.properties.findIndex((p) => p.name === 'green' || p.name === 'g');
|
|
198
246
|
const bCol = vertex.properties.findIndex((p) => p.name === 'blue' || p.name === 'b');
|
|
247
|
+
const nxCol = vertex.properties.findIndex((p) => p.name === 'nx');
|
|
248
|
+
const nyCol = vertex.properties.findIndex((p) => p.name === 'ny');
|
|
249
|
+
const nzCol = vertex.properties.findIndex((p) => p.name === 'nz');
|
|
199
250
|
const iCol = vertex.properties.findIndex((p) => p.name === 'intensity' || p.name === 'scalar_Intensity');
|
|
200
251
|
let lineStart = 0;
|
|
201
252
|
let written = 0;
|
|
@@ -216,6 +267,11 @@ function decodeAsciiBody(buffer, header, vertex, positions, colors, intensities,
|
|
|
216
267
|
colors[written * 3 + 1] = Number(parts[gCol]);
|
|
217
268
|
colors[written * 3 + 2] = Number(parts[bCol]);
|
|
218
269
|
}
|
|
270
|
+
if (normals) {
|
|
271
|
+
normals[written * 3] = Number(parts[nxCol]);
|
|
272
|
+
normals[written * 3 + 1] = Number(parts[nyCol]);
|
|
273
|
+
normals[written * 3 + 2] = Number(parts[nzCol]);
|
|
274
|
+
}
|
|
219
275
|
if (intensities && iCol >= 0) {
|
|
220
276
|
intensities[written] = Math.min(65535, Math.max(0, Number(parts[iCol]) | 0));
|
|
221
277
|
}
|
|
@@ -225,62 +281,6 @@ function decodeAsciiBody(buffer, header, vertex, positions, colors, intensities,
|
|
|
225
281
|
throw new Error(`PLY ascii: expected ${vertex.count} vertex lines, got ${written}`);
|
|
226
282
|
}
|
|
227
283
|
}
|
|
228
|
-
// ─── binary body ────────────────────────────────────────────────────────────
|
|
229
|
-
function decodeBinaryBody(buffer, header, vertex, positions, colors, intensities, littleEndian, originOffset) {
|
|
230
|
-
const stride = vertex.recordSize;
|
|
231
|
-
const need = vertex.count * stride;
|
|
232
|
-
if (buffer.length < header.bodyOffset + need) {
|
|
233
|
-
throw new Error(`PLY binary: expected ${need} body bytes, got ${buffer.length - header.bodyOffset}`);
|
|
234
|
-
}
|
|
235
|
-
const view = new DataView(buffer.buffer, buffer.byteOffset + header.bodyOffset, need);
|
|
236
|
-
const offX = originOffset?.[0] ?? 0;
|
|
237
|
-
const offY = originOffset?.[1] ?? 0;
|
|
238
|
-
const offZ = originOffset?.[2] ?? 0;
|
|
239
|
-
const xProp = vertex.properties.find((p) => p.name === 'x');
|
|
240
|
-
const yProp = vertex.properties.find((p) => p.name === 'y');
|
|
241
|
-
const zProp = vertex.properties.find((p) => p.name === 'z');
|
|
242
|
-
const rProp = colors ? vertex.properties.find((p) => p.name === 'red' || p.name === 'r') : undefined;
|
|
243
|
-
const gProp = colors ? vertex.properties.find((p) => p.name === 'green' || p.name === 'g') : undefined;
|
|
244
|
-
const bProp = colors ? vertex.properties.find((p) => p.name === 'blue' || p.name === 'b') : undefined;
|
|
245
|
-
const iProp = intensities
|
|
246
|
-
? vertex.properties.find((p) => p.name === 'intensity' || p.name === 'scalar_Intensity')
|
|
247
|
-
: undefined;
|
|
248
|
-
for (let i = 0; i < vertex.count; i++) {
|
|
249
|
-
const base = i * stride;
|
|
250
|
-
positions[i * 3] = readScalar(view, base + xProp.offset, xProp, littleEndian) - offX;
|
|
251
|
-
positions[i * 3 + 1] = readScalar(view, base + yProp.offset, yProp, littleEndian) - offY;
|
|
252
|
-
positions[i * 3 + 2] = readScalar(view, base + zProp.offset, zProp, littleEndian) - offZ;
|
|
253
|
-
if (colors && rProp && gProp && bProp) {
|
|
254
|
-
colors[i * 3] = readScalar(view, base + rProp.offset, rProp, littleEndian);
|
|
255
|
-
colors[i * 3 + 1] = readScalar(view, base + gProp.offset, gProp, littleEndian);
|
|
256
|
-
colors[i * 3 + 2] = readScalar(view, base + bProp.offset, bProp, littleEndian);
|
|
257
|
-
}
|
|
258
|
-
if (intensities && iProp) {
|
|
259
|
-
intensities[i] = Math.min(65535, Math.max(0, readScalar(view, base + iProp.offset, iProp, littleEndian) | 0));
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
function readScalar(view, offset, prop, le) {
|
|
264
|
-
switch (prop.type) {
|
|
265
|
-
case 'char':
|
|
266
|
-
case 'int8': return view.getInt8(offset);
|
|
267
|
-
case 'uchar':
|
|
268
|
-
case 'uint8': return view.getUint8(offset);
|
|
269
|
-
case 'short':
|
|
270
|
-
case 'int16': return view.getInt16(offset, le);
|
|
271
|
-
case 'ushort':
|
|
272
|
-
case 'uint16': return view.getUint16(offset, le);
|
|
273
|
-
case 'int':
|
|
274
|
-
case 'int32': return view.getInt32(offset, le);
|
|
275
|
-
case 'uint':
|
|
276
|
-
case 'uint32': return view.getUint32(offset, le);
|
|
277
|
-
case 'float':
|
|
278
|
-
case 'float32': return view.getFloat32(offset, le);
|
|
279
|
-
case 'double':
|
|
280
|
-
case 'float64': return view.getFloat64(offset, le);
|
|
281
|
-
default: throw new Error(`PLY: cannot read scalar of type "${prop.type}"`);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
284
|
function computeBBox(positions) {
|
|
285
285
|
let minX = Infinity, minY = Infinity, minZ = Infinity;
|
|
286
286
|
let maxX = -Infinity, maxY = -Infinity, maxZ = -Infinity;
|