@loaders.gl/potree 4.3.0-alpha.4 → 4.3.0-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dist.dev.js +19541 -21
- package/dist/dist.min.js +21 -1
- package/dist/index.cjs +181 -20
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/lib/potree-node-source.d.ts +66 -0
- package/dist/lib/potree-node-source.d.ts.map +1 -0
- package/dist/lib/potree-node-source.js +141 -0
- package/dist/parsers/parse-potree-hierarchy-chunk.d.ts +21 -2
- package/dist/parsers/parse-potree-hierarchy-chunk.d.ts.map +1 -1
- package/dist/parsers/parse-potree-hierarchy-chunk.js +32 -18
- package/dist/potree-hierarchy-chunk-loader.d.ts +6 -1
- package/dist/potree-hierarchy-chunk-loader.d.ts.map +1 -1
- package/dist/potree-hierarchy-chunk-loader.js +9 -3
- package/dist/potree-loader.d.ts +3 -2
- package/dist/potree-loader.d.ts.map +1 -1
- package/dist/potree-loader.js +4 -5
- package/dist/potree-source.d.ts +22 -0
- package/dist/potree-source.d.ts.map +1 -0
- package/dist/potree-source.js +22 -0
- package/dist/types/potree-metadata.d.ts +88 -0
- package/dist/types/potree-metadata.d.ts.map +1 -0
- package/dist/types/potree-metadata.js +4 -0
- package/dist/utils/parse-version.d.ts +5 -0
- package/dist/utils/parse-version.d.ts.map +1 -0
- package/dist/utils/parse-version.js +7 -0
- package/package.json +5 -3
- package/src/index.ts +1 -0
- package/src/lib/potree-node-source.ts +174 -0
- package/src/parsers/parse-potree-hierarchy-chunk.ts +52 -26
- package/src/potree-hierarchy-chunk-loader.ts +10 -3
- package/src/potree-loader.ts +3 -4
- package/src/potree-source.ts +28 -0
- package/src/types/potree-metadata.ts +94 -0
- package/src/utils/parse-version.ts +8 -0
|
@@ -54,32 +54,53 @@ Would have an index looking like this:
|
|
|
54
54
|
| r36 | `0b00000000` (=0) | `1` |
|
|
55
55
|
*/
|
|
56
56
|
|
|
57
|
-
/**
|
|
57
|
+
/** Node metadata from index file */
|
|
58
58
|
export type POTreeTileHeader = {
|
|
59
|
+
/** Number of child nodes */
|
|
59
60
|
childCount: number;
|
|
61
|
+
/** Human readable name */
|
|
60
62
|
name: string;
|
|
63
|
+
/** Child availability mask */
|
|
61
64
|
childMask: number;
|
|
62
65
|
};
|
|
63
66
|
|
|
64
|
-
/**
|
|
67
|
+
/** Hierarchical potree node structure */
|
|
65
68
|
export type POTreeNode = {
|
|
69
|
+
/** Index data */
|
|
66
70
|
header: POTreeTileHeader;
|
|
71
|
+
/** Human readable name */
|
|
67
72
|
name: string;
|
|
73
|
+
/** Number of points */
|
|
68
74
|
pointCount: number;
|
|
75
|
+
/** Node's level in the tree */
|
|
76
|
+
level: number;
|
|
77
|
+
/** Has children */
|
|
78
|
+
hasChildren: boolean;
|
|
79
|
+
/** Space between points */
|
|
80
|
+
spacing: number;
|
|
81
|
+
/** Available children */
|
|
69
82
|
children: POTreeNode[];
|
|
83
|
+
/** All children including unavailable */
|
|
70
84
|
childrenByIndex: POTreeNode[];
|
|
71
85
|
};
|
|
72
86
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
87
|
+
/**
|
|
88
|
+
* load hierarchy
|
|
89
|
+
* @param arrayBuffer - binary index data
|
|
90
|
+
* @returns root node
|
|
91
|
+
**/
|
|
92
|
+
export function parsePotreeHierarchyChunk(arrayBuffer: ArrayBuffer): POTreeNode {
|
|
77
93
|
const tileHeaders = parseBinaryChunk(arrayBuffer);
|
|
78
94
|
return buildHierarchy(tileHeaders);
|
|
79
95
|
}
|
|
80
96
|
|
|
81
|
-
|
|
82
|
-
|
|
97
|
+
/**
|
|
98
|
+
* Parses the binary rows
|
|
99
|
+
* @param arrayBuffer - binary index data to parse
|
|
100
|
+
* @param byteOffset - byte offset to start from
|
|
101
|
+
* @returns flat nodes array
|
|
102
|
+
* */
|
|
103
|
+
function parseBinaryChunk(arrayBuffer: ArrayBuffer, byteOffset = 0): POTreeNode[] {
|
|
83
104
|
const dataView = new DataView(arrayBuffer);
|
|
84
105
|
|
|
85
106
|
const stack: POTreeNode[] = [];
|
|
@@ -90,8 +111,7 @@ function parseBinaryChunk(arrayBuffer: ArrayBuffer, byteOffset = 0) {
|
|
|
90
111
|
byteOffset = decodeRow(dataView, byteOffset, topTileHeader);
|
|
91
112
|
|
|
92
113
|
stack.push(topTileHeader);
|
|
93
|
-
|
|
94
|
-
const tileHeaders: POTreeTileHeader[] = [];
|
|
114
|
+
const tileHeaders: POTreeNode[] = [topTileHeader];
|
|
95
115
|
|
|
96
116
|
while (stack.length > 0) {
|
|
97
117
|
const snode = stack.shift();
|
|
@@ -100,11 +120,10 @@ function parseBinaryChunk(arrayBuffer: ArrayBuffer, byteOffset = 0) {
|
|
|
100
120
|
for (let i = 0; i < 8; i++) {
|
|
101
121
|
if (snode && (snode.header.childMask & mask) !== 0) {
|
|
102
122
|
// @ts-expect-error
|
|
103
|
-
const tileHeader:
|
|
123
|
+
const tileHeader: POTreeNode = {};
|
|
104
124
|
byteOffset = decodeRow(dataView, byteOffset, tileHeader);
|
|
105
125
|
tileHeader.name = snode.name + i;
|
|
106
126
|
|
|
107
|
-
// @ts-expect-error
|
|
108
127
|
stack.push(tileHeader);
|
|
109
128
|
tileHeaders.push(tileHeader);
|
|
110
129
|
snode.header.childCount++;
|
|
@@ -120,7 +139,14 @@ function parseBinaryChunk(arrayBuffer: ArrayBuffer, byteOffset = 0) {
|
|
|
120
139
|
return tileHeaders;
|
|
121
140
|
}
|
|
122
141
|
|
|
123
|
-
|
|
142
|
+
/**
|
|
143
|
+
* Reads next row from binary index file
|
|
144
|
+
* @param dataView - index data
|
|
145
|
+
* @param byteOffset - current offset in the index data
|
|
146
|
+
* @param tileHeader - container to read to
|
|
147
|
+
* @returns new offset
|
|
148
|
+
*/
|
|
149
|
+
function decodeRow(dataView: DataView, byteOffset: number, tileHeader: POTreeNode): number {
|
|
124
150
|
tileHeader.header = tileHeader.header || {};
|
|
125
151
|
tileHeader.header.childMask = dataView.getUint8(byteOffset);
|
|
126
152
|
tileHeader.header.childCount = 0;
|
|
@@ -130,16 +156,16 @@ function decodeRow(dataView, byteOffset, tileHeader) {
|
|
|
130
156
|
return byteOffset;
|
|
131
157
|
}
|
|
132
158
|
|
|
133
|
-
|
|
134
|
-
function buildHierarchy(
|
|
159
|
+
/** Resolves the binary rows into a hierarchy (tree structure) */
|
|
160
|
+
function buildHierarchy(flatNodes: POTreeNode[], options: {spacing?: number} = {}): POTreeNode {
|
|
135
161
|
const DEFAULT_OPTIONS = {spacing: 100}; // TODO assert instead of default?
|
|
136
162
|
options = {...DEFAULT_OPTIONS, ...options};
|
|
137
163
|
|
|
138
|
-
const topNode =
|
|
164
|
+
const topNode: POTreeNode = flatNodes[0];
|
|
139
165
|
const nodes = {};
|
|
140
166
|
|
|
141
|
-
for (const
|
|
142
|
-
const {name} =
|
|
167
|
+
for (const node of flatNodes) {
|
|
168
|
+
const {name} = node;
|
|
143
169
|
|
|
144
170
|
const index = parseInt(name.charAt(name.length - 1), 10);
|
|
145
171
|
const parentName = name.substring(0, name.length - 1);
|
|
@@ -147,20 +173,20 @@ function buildHierarchy(tileHeaders, options: {spacing?: number} = {}): POTreeNo
|
|
|
147
173
|
const level = name.length - 1;
|
|
148
174
|
// assert(parentNode && level >= 0);
|
|
149
175
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
176
|
+
node.level = level;
|
|
177
|
+
node.hasChildren = Boolean(node.header.childCount);
|
|
178
|
+
node.children = [];
|
|
179
|
+
node.childrenByIndex = new Array(8).fill(null);
|
|
180
|
+
node.spacing = (options?.spacing || 0) / Math.pow(2, level);
|
|
155
181
|
// tileHeader.boundingVolume = Utils.createChildAABB(parentNode.boundingBox, index);
|
|
156
182
|
|
|
157
183
|
if (parentNode) {
|
|
158
|
-
parentNode.children.push(
|
|
159
|
-
parentNode.childrenByIndex[index] =
|
|
184
|
+
parentNode.children.push(node);
|
|
185
|
+
parentNode.childrenByIndex[index] = node;
|
|
160
186
|
}
|
|
161
187
|
|
|
162
188
|
// Add the node to the map
|
|
163
|
-
nodes[name] =
|
|
189
|
+
nodes[name] = node;
|
|
164
190
|
}
|
|
165
191
|
|
|
166
192
|
// First node is the root
|
|
@@ -7,20 +7,27 @@ import type {POTreeLoaderOptions} from './potree-loader';
|
|
|
7
7
|
import type {POTreeNode} from './parsers/parse-potree-hierarchy-chunk';
|
|
8
8
|
import {parsePotreeHierarchyChunk} from './parsers/parse-potree-hierarchy-chunk';
|
|
9
9
|
|
|
10
|
+
// __VERSION__ is injected by babel-plugin-version-inline
|
|
11
|
+
// @ts-ignore TS2304: Cannot find name '__VERSION__'.
|
|
12
|
+
const VERSION = typeof __VERSION__ !== 'undefined' ? __VERSION__ : 'latest';
|
|
13
|
+
|
|
10
14
|
/** Potree hierarchy chunk loader */
|
|
11
|
-
// @ts-ignore not a valid loader
|
|
12
15
|
export const PotreeHierarchyChunkLoader = {
|
|
13
16
|
dataType: null as unknown as POTreeNode,
|
|
14
17
|
batchType: null as never,
|
|
15
18
|
|
|
16
|
-
id: 'potree',
|
|
17
19
|
name: 'potree Hierarchy Chunk',
|
|
20
|
+
id: 'potree-hrc',
|
|
21
|
+
module: 'potree',
|
|
22
|
+
version: VERSION,
|
|
18
23
|
extensions: ['hrc'],
|
|
19
24
|
mimeTypes: ['application/octet-stream'],
|
|
20
25
|
// binary potree files have no header bytes, no content test function possible
|
|
21
26
|
// test: ['...'],
|
|
22
27
|
parse: async (arrayBuffer, options) => parsePotreeHierarchyChunk(arrayBuffer),
|
|
23
28
|
parseSync: (arrayBuffer, options) => parsePotreeHierarchyChunk(arrayBuffer),
|
|
29
|
+
options: {
|
|
30
|
+
potree: {}
|
|
31
|
+
},
|
|
24
32
|
binary: true
|
|
25
|
-
// @ts-ignore
|
|
26
33
|
} as const satisfies LoaderWithParser<POTreeNode, never, POTreeLoaderOptions>;
|
package/src/potree-loader.ts
CHANGED
|
@@ -13,21 +13,20 @@ export type POTreeLoaderOptions = LoaderOptions & {
|
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
/** Potree loader */
|
|
16
|
-
// @ts-ignore
|
|
17
16
|
export const PotreeLoader = {
|
|
18
17
|
dataType: null as unknown as any,
|
|
19
18
|
batchType: null as never,
|
|
20
19
|
|
|
21
|
-
name: 'potree',
|
|
20
|
+
name: 'potree metadata',
|
|
22
21
|
id: 'potree',
|
|
23
22
|
module: 'potree',
|
|
24
23
|
version: VERSION,
|
|
25
|
-
extensions: ['
|
|
24
|
+
extensions: ['js'],
|
|
26
25
|
mimeTypes: ['application/json'],
|
|
27
26
|
testText: (text) => text.indexOf('octreeDir') >= 0,
|
|
27
|
+
parse: (data: ArrayBuffer) => JSON.parse(new TextDecoder().decode(data)),
|
|
28
28
|
parseTextSync: (text) => JSON.parse(text),
|
|
29
29
|
options: {
|
|
30
30
|
potree: {}
|
|
31
31
|
}
|
|
32
|
-
// @ts-ignore
|
|
33
32
|
} as const satisfies LoaderWithParser<any, never, POTreeLoaderOptions>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// loaders.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
import {Source} from '@loaders.gl/loader-utils';
|
|
6
|
+
import {PotreeNodesSource, PotreeNodesSourceProps} from './lib/potree-node-source';
|
|
7
|
+
|
|
8
|
+
const VERSION = '1.7';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Creates point cloud data sources for Potree urls
|
|
12
|
+
*/
|
|
13
|
+
export const PotreeSource = {
|
|
14
|
+
name: 'Potree',
|
|
15
|
+
id: 'potree',
|
|
16
|
+
module: 'potree',
|
|
17
|
+
version: VERSION,
|
|
18
|
+
extensions: ['bin', 'las', 'laz'],
|
|
19
|
+
mimeTypes: ['application/octet-stream'],
|
|
20
|
+
options: {url: undefined!, potree: {}},
|
|
21
|
+
type: 'potree',
|
|
22
|
+
fromUrl: true,
|
|
23
|
+
fromBlob: true,
|
|
24
|
+
|
|
25
|
+
testURL: (url: string) => url.endsWith('.js'),
|
|
26
|
+
createDataSource: (url: string | Blob, props: PotreeNodesSourceProps) =>
|
|
27
|
+
new PotreeNodesSource(url, props)
|
|
28
|
+
} as const satisfies Source<PotreeNodesSource, PotreeNodesSourceProps>;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// loaders.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
/** Bounding box */
|
|
6
|
+
export interface PotreeBoundingBox {
|
|
7
|
+
/** Min X */
|
|
8
|
+
lx: number;
|
|
9
|
+
/** Min Y */
|
|
10
|
+
ly: number;
|
|
11
|
+
/** Min Z */
|
|
12
|
+
lz: number;
|
|
13
|
+
/** Max X */
|
|
14
|
+
ux: number;
|
|
15
|
+
/** Max Y */
|
|
16
|
+
uy: number;
|
|
17
|
+
/** Max Z */
|
|
18
|
+
uz: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Attribute types for *.bin content */
|
|
22
|
+
export type PotreeAttribute =
|
|
23
|
+
/** 3 (uint32) numbers: x, y, z */
|
|
24
|
+
| 'POSITION_CARTESIAN'
|
|
25
|
+
/** 4 x (uint8) numbers for the color: r, g, b, a */
|
|
26
|
+
| 'RGBA_PACKED'
|
|
27
|
+
/** 4 x (uint8) numbers for the color: r, g, b, a */
|
|
28
|
+
| 'COLOR_PACKED'
|
|
29
|
+
/** 3 x (uint8) numbers for the color: r, g, b */
|
|
30
|
+
| 'RGB_PACKED'
|
|
31
|
+
/** 3 x (float) numbers: x', y', z' */
|
|
32
|
+
| 'NORMAL_FLOATS'
|
|
33
|
+
/** (uint8) number */
|
|
34
|
+
| 'FILLER_1B'
|
|
35
|
+
/** (uint16) number specifying the point's intensity */
|
|
36
|
+
| 'INTENSITY'
|
|
37
|
+
/** (uint8) id for the class used */
|
|
38
|
+
| 'CLASSIFICATION'
|
|
39
|
+
/** Note: might need to be revisited, best don't use */
|
|
40
|
+
| 'NORMAL_SPHEREMAPPED'
|
|
41
|
+
/** Note: might need to be revisited, best don't use */
|
|
42
|
+
| 'NORMAL_OCT16'
|
|
43
|
+
/** 3 x (float) numbers: x', y', z' */
|
|
44
|
+
| 'NORMAL';
|
|
45
|
+
|
|
46
|
+
/** Hierarchy item: [node name leading with 'r', points count
|
|
47
|
+
* @example [r043, 145]
|
|
48
|
+
] */
|
|
49
|
+
export type HierarchyItem = [string, number];
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Potree data set format metadata (cloud.js)
|
|
53
|
+
* @version 1.7
|
|
54
|
+
* @link https://github.com/potree/potree/blob/1.7/docs/potree-file-format.md
|
|
55
|
+
* */
|
|
56
|
+
export interface PotreeMetadata {
|
|
57
|
+
/** Version number in which this file is written */
|
|
58
|
+
version: string;
|
|
59
|
+
/** Folder that is used to load additional data */
|
|
60
|
+
octreeDir: string;
|
|
61
|
+
/** Amount of points contained in the whole pointcloud data */
|
|
62
|
+
points: number;
|
|
63
|
+
/**
|
|
64
|
+
* This parameter is used to transform the point data
|
|
65
|
+
* to the projection system used while visualizing the points. It has to be
|
|
66
|
+
* in a format that is parsable by [proj.4][proj4].
|
|
67
|
+
* */
|
|
68
|
+
projection: string;
|
|
69
|
+
/** Bounding box of the world used to limit the initial POV. */
|
|
70
|
+
boundingBox: PotreeBoundingBox;
|
|
71
|
+
/** Bounding box of the actual points in the data */
|
|
72
|
+
tightBoundingBox: PotreeBoundingBox;
|
|
73
|
+
/** Description of point attributes in data files */
|
|
74
|
+
pointAttributes: 'LAS' | 'LAZ' | PotreeAttribute[];
|
|
75
|
+
/**
|
|
76
|
+
* Space between points at the root node.
|
|
77
|
+
* This value is halved at each octree level.
|
|
78
|
+
* */
|
|
79
|
+
spacing: number;
|
|
80
|
+
/**
|
|
81
|
+
* Scale applied to convert POSITION_CARTESIAN components
|
|
82
|
+
* from uint32 values to floating point values. The full transformation
|
|
83
|
+
* to world coordinates is
|
|
84
|
+
* position = (POSITION_CARTESIAN * scale) + boundingBox.min
|
|
85
|
+
* */
|
|
86
|
+
scale: number;
|
|
87
|
+
/** Amount of Octree levels before a new folder hierarchy is expected. */
|
|
88
|
+
hierarchyStepSize: number;
|
|
89
|
+
/**
|
|
90
|
+
* The hierarchy of files, now loaded through index files.
|
|
91
|
+
* @deprecated
|
|
92
|
+
* */
|
|
93
|
+
hierarchy: HierarchyItem[];
|
|
94
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// loaders.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
export function parseVersion(version: string): {major: number; minor: number} {
|
|
6
|
+
const parts = version.split('.').map(Number);
|
|
7
|
+
return {major: parts[0], minor: parts[1]};
|
|
8
|
+
}
|