@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.
Files changed (75) hide show
  1. package/README.md +35 -0
  2. package/dist/formats/ascii-points.d.ts.map +1 -1
  3. package/dist/formats/ascii-points.js +1 -0
  4. package/dist/formats/ascii-points.js.map +1 -1
  5. package/dist/formats/e57-decode.js +1 -1
  6. package/dist/formats/e57-decode.js.map +1 -1
  7. package/dist/formats/e57.d.ts.map +1 -1
  8. package/dist/formats/e57.js +1 -0
  9. package/dist/formats/e57.js.map +1 -1
  10. package/dist/formats/ifcx-points.d.ts.map +1 -1
  11. package/dist/formats/ifcx-points.js +2 -0
  12. package/dist/formats/ifcx-points.js.map +1 -1
  13. package/dist/formats/las.d.ts.map +1 -1
  14. package/dist/formats/las.js +43 -12
  15. package/dist/formats/las.js.map +1 -1
  16. package/dist/formats/pcd.js +1 -1
  17. package/dist/formats/pcd.js.map +1 -1
  18. package/dist/formats/ply-color.d.ts +2 -0
  19. package/dist/formats/ply-color.d.ts.map +1 -1
  20. package/dist/formats/ply-color.js +6 -1
  21. package/dist/formats/ply-color.js.map +1 -1
  22. package/dist/formats/ply-fixed-binary.d.ts +9 -0
  23. package/dist/formats/ply-fixed-binary.d.ts.map +1 -0
  24. package/dist/formats/ply-fixed-binary.js +60 -0
  25. package/dist/formats/ply-fixed-binary.js.map +1 -0
  26. package/dist/formats/ply-scalar.d.ts +6 -0
  27. package/dist/formats/ply-scalar.d.ts.map +1 -0
  28. package/dist/formats/ply-scalar.js +25 -0
  29. package/dist/formats/ply-scalar.js.map +1 -0
  30. package/dist/formats/ply-variable-row.d.ts +15 -0
  31. package/dist/formats/ply-variable-row.d.ts.map +1 -0
  32. package/dist/formats/ply-variable-row.js +66 -0
  33. package/dist/formats/ply-variable-row.js.map +1 -0
  34. package/dist/formats/ply.d.ts +36 -10
  35. package/dist/formats/ply.d.ts.map +1 -1
  36. package/dist/formats/ply.js +83 -83
  37. package/dist/formats/ply.js.map +1 -1
  38. package/dist/index.d.ts +1 -1
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/streaming/ascii-points-source.js +1 -0
  41. package/dist/streaming/ascii-points-source.js.map +1 -1
  42. package/dist/streaming/decode-worker.js +2 -1
  43. package/dist/streaming/decode-worker.js.map +1 -1
  44. package/dist/streaming/e57-source.js +1 -1
  45. package/dist/streaming/e57-source.js.map +1 -1
  46. package/dist/streaming/host.d.ts +3 -0
  47. package/dist/streaming/host.d.ts.map +1 -1
  48. package/dist/streaming/host.js +25 -10
  49. package/dist/streaming/host.js.map +1 -1
  50. package/dist/streaming/inline-worker.js +1 -1
  51. package/dist/streaming/pcd-source.js +1 -0
  52. package/dist/streaming/pcd-source.js.map +1 -1
  53. package/dist/streaming/ply-source.d.ts +9 -17
  54. package/dist/streaming/ply-source.d.ts.map +1 -1
  55. package/dist/streaming/ply-source.js +39 -69
  56. package/dist/streaming/ply-source.js.map +1 -1
  57. package/dist/streaming/ply-stream-decode.d.ts +32 -0
  58. package/dist/streaming/ply-stream-decode.d.ts.map +1 -0
  59. package/dist/streaming/ply-stream-decode.js +363 -0
  60. package/dist/streaming/ply-stream-decode.js.map +1 -0
  61. package/dist/streaming/ply-variable-stream.d.ts +15 -0
  62. package/dist/streaming/ply-variable-stream.d.ts.map +1 -0
  63. package/dist/streaming/ply-variable-stream.js +73 -0
  64. package/dist/streaming/ply-variable-stream.js.map +1 -0
  65. package/dist/streaming/protocol.d.ts +3 -1
  66. package/dist/streaming/protocol.d.ts.map +1 -1
  67. package/dist/streaming/protocol.js +18 -4
  68. package/dist/streaming/protocol.js.map +1 -1
  69. package/dist/streaming/stride.d.ts +3 -0
  70. package/dist/streaming/stride.d.ts.map +1 -0
  71. package/dist/streaming/stride.js +9 -0
  72. package/dist/streaming/stride.js.map +1 -0
  73. package/dist/types.d.ts +6 -0
  74. package/dist/types.d.ts.map +1 -1
  75. 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,6 @@
1
+ interface ScalarProperty {
2
+ type: string;
3
+ }
4
+ export declare function readPlyScalar(view: DataView, offset: number, prop: ScalarProperty, littleEndian: boolean): number;
5
+ export {};
6
+ //# sourceMappingURL=ply-scalar.d.ts.map
@@ -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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"}
@@ -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) and intensity (intensity, uchar/ushort/float) are optional and
11
- * surfaced when present. Returns a single `DecodedPointChunk` — large
12
- * .ply files (>25M points) get bounded by `streamPointCloud`'s memory
13
- * cap which downsamples upstream.
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 PropertyDecl {
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 ElementDecl {
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: PropertyDecl[];
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: ElementDecl[];
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;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAkB,MAAM,aAAa,CAAC;AAWrE,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,YAAY,EAAE,CAAC;IAC3B,wDAAwD;IACxD,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,OAAO,GAAG,sBAAsB,GAAG,mBAAmB,CAAC;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAC;CACpB;AAID,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,CAwF5D;AAED,wBAAgB,SAAS,CACvB,MAAM,EAAE,UAAU;AAClB;;;;;;GAMG;AACH,YAAY,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAC/C,iBAAiB,CA8FnB"}
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"}
@@ -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
- current.properties.push({ name, type, size, offset: current.recordSize });
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 vertex = header.elements.find((e) => e.name === 'vertex');
115
- if (!vertex)
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
- decodeAsciiBody(buffer, header, vertex, positions, colors, intensities, originOffset);
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
- decodeBinaryBody(buffer, header, vertex, positions, colors, intensities, header.format === 'binary_little_endian', originOffset);
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
- // ─── ascii body ─────────────────────────────────────────────────────────────
185
- function decodeAsciiBody(buffer, header, vertex, positions, colors, intensities, originOffset) {
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;