@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.
Files changed (37) hide show
  1. package/dist/dist.dev.js +19541 -21
  2. package/dist/dist.min.js +21 -1
  3. package/dist/index.cjs +181 -20
  4. package/dist/index.cjs.map +4 -4
  5. package/dist/index.d.ts +1 -0
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +1 -0
  8. package/dist/lib/potree-node-source.d.ts +66 -0
  9. package/dist/lib/potree-node-source.d.ts.map +1 -0
  10. package/dist/lib/potree-node-source.js +141 -0
  11. package/dist/parsers/parse-potree-hierarchy-chunk.d.ts +21 -2
  12. package/dist/parsers/parse-potree-hierarchy-chunk.d.ts.map +1 -1
  13. package/dist/parsers/parse-potree-hierarchy-chunk.js +32 -18
  14. package/dist/potree-hierarchy-chunk-loader.d.ts +6 -1
  15. package/dist/potree-hierarchy-chunk-loader.d.ts.map +1 -1
  16. package/dist/potree-hierarchy-chunk-loader.js +9 -3
  17. package/dist/potree-loader.d.ts +3 -2
  18. package/dist/potree-loader.d.ts.map +1 -1
  19. package/dist/potree-loader.js +4 -5
  20. package/dist/potree-source.d.ts +22 -0
  21. package/dist/potree-source.d.ts.map +1 -0
  22. package/dist/potree-source.js +22 -0
  23. package/dist/types/potree-metadata.d.ts +88 -0
  24. package/dist/types/potree-metadata.d.ts.map +1 -0
  25. package/dist/types/potree-metadata.js +4 -0
  26. package/dist/utils/parse-version.d.ts +5 -0
  27. package/dist/utils/parse-version.d.ts.map +1 -0
  28. package/dist/utils/parse-version.js +7 -0
  29. package/package.json +5 -3
  30. package/src/index.ts +1 -0
  31. package/src/lib/potree-node-source.ts +174 -0
  32. package/src/parsers/parse-potree-hierarchy-chunk.ts +52 -26
  33. package/src/potree-hierarchy-chunk-loader.ts +10 -3
  34. package/src/potree-loader.ts +3 -4
  35. package/src/potree-source.ts +28 -0
  36. package/src/types/potree-metadata.ts +94 -0
  37. package/src/utils/parse-version.ts +8 -0
@@ -1,12 +1,20 @@
1
1
  // This file is derived from the Cesium code base under BSD 2-clause license
2
2
  // See LICENSE.md and https://github.com/potree/potree/blob/develop/LICENSE
3
- // type POTreeTileNode = POTreeNode;
4
- // load hierarchy
3
+ /**
4
+ * load hierarchy
5
+ * @param arrayBuffer - binary index data
6
+ * @returns root node
7
+ **/
5
8
  export function parsePotreeHierarchyChunk(arrayBuffer) {
6
9
  const tileHeaders = parseBinaryChunk(arrayBuffer);
7
10
  return buildHierarchy(tileHeaders);
8
11
  }
9
- // Parses the binary rows
12
+ /**
13
+ * Parses the binary rows
14
+ * @param arrayBuffer - binary index data to parse
15
+ * @param byteOffset - byte offset to start from
16
+ * @returns flat nodes array
17
+ * */
10
18
  function parseBinaryChunk(arrayBuffer, byteOffset = 0) {
11
19
  const dataView = new DataView(arrayBuffer);
12
20
  const stack = [];
@@ -15,7 +23,7 @@ function parseBinaryChunk(arrayBuffer, byteOffset = 0) {
15
23
  const topTileHeader = {};
16
24
  byteOffset = decodeRow(dataView, byteOffset, topTileHeader);
17
25
  stack.push(topTileHeader);
18
- const tileHeaders = [];
26
+ const tileHeaders = [topTileHeader];
19
27
  while (stack.length > 0) {
20
28
  const snode = stack.shift();
21
29
  let mask = 1;
@@ -25,7 +33,6 @@ function parseBinaryChunk(arrayBuffer, byteOffset = 0) {
25
33
  const tileHeader = {};
26
34
  byteOffset = decodeRow(dataView, byteOffset, tileHeader);
27
35
  tileHeader.name = snode.name + i;
28
- // @ts-expect-error
29
36
  stack.push(tileHeader);
30
37
  tileHeaders.push(tileHeader);
31
38
  snode.header.childCount++;
@@ -38,6 +45,13 @@ function parseBinaryChunk(arrayBuffer, byteOffset = 0) {
38
45
  }
39
46
  return tileHeaders;
40
47
  }
48
+ /**
49
+ * Reads next row from binary index file
50
+ * @param dataView - index data
51
+ * @param byteOffset - current offset in the index data
52
+ * @param tileHeader - container to read to
53
+ * @returns new offset
54
+ */
41
55
  function decodeRow(dataView, byteOffset, tileHeader) {
42
56
  tileHeader.header = tileHeader.header || {};
43
57
  tileHeader.header.childMask = dataView.getUint8(byteOffset);
@@ -47,31 +61,31 @@ function decodeRow(dataView, byteOffset, tileHeader) {
47
61
  byteOffset += 5;
48
62
  return byteOffset;
49
63
  }
50
- // Resolves the binary rows into a hierarchy (tree structure)
51
- function buildHierarchy(tileHeaders, options = {}) {
64
+ /** Resolves the binary rows into a hierarchy (tree structure) */
65
+ function buildHierarchy(flatNodes, options = {}) {
52
66
  const DEFAULT_OPTIONS = { spacing: 100 }; // TODO assert instead of default?
53
67
  options = { ...DEFAULT_OPTIONS, ...options };
54
- const topNode = tileHeaders[0];
68
+ const topNode = flatNodes[0];
55
69
  const nodes = {};
56
- for (const tileHeader of tileHeaders) {
57
- const { name } = tileHeader;
70
+ for (const node of flatNodes) {
71
+ const { name } = node;
58
72
  const index = parseInt(name.charAt(name.length - 1), 10);
59
73
  const parentName = name.substring(0, name.length - 1);
60
74
  const parentNode = nodes[parentName];
61
75
  const level = name.length - 1;
62
76
  // assert(parentNode && level >= 0);
63
- tileHeader.level = level;
64
- tileHeader.hasChildren = tileHeader.header.childCount;
65
- tileHeader.children = [];
66
- tileHeader.childrenByIndex = new Array(8).fill(null);
67
- tileHeader.spacing = (options?.spacing || 0) / Math.pow(2, level);
77
+ node.level = level;
78
+ node.hasChildren = Boolean(node.header.childCount);
79
+ node.children = [];
80
+ node.childrenByIndex = new Array(8).fill(null);
81
+ node.spacing = (options?.spacing || 0) / Math.pow(2, level);
68
82
  // tileHeader.boundingVolume = Utils.createChildAABB(parentNode.boundingBox, index);
69
83
  if (parentNode) {
70
- parentNode.children.push(tileHeader);
71
- parentNode.childrenByIndex[index] = tileHeader;
84
+ parentNode.children.push(node);
85
+ parentNode.childrenByIndex[index] = node;
72
86
  }
73
87
  // Add the node to the map
74
- nodes[name] = tileHeader;
88
+ nodes[name] = node;
75
89
  }
76
90
  // First node is the root
77
91
  return topNode;
@@ -4,12 +4,17 @@ import type { POTreeNode } from "./parsers/parse-potree-hierarchy-chunk.js";
4
4
  export declare const PotreeHierarchyChunkLoader: {
5
5
  readonly dataType: POTreeNode;
6
6
  readonly batchType: never;
7
- readonly id: "potree";
8
7
  readonly name: "potree Hierarchy Chunk";
8
+ readonly id: "potree-hrc";
9
+ readonly module: "potree";
10
+ readonly version: any;
9
11
  readonly extensions: ["hrc"];
10
12
  readonly mimeTypes: ["application/octet-stream"];
11
13
  readonly parse: (arrayBuffer: ArrayBuffer, options: POTreeLoaderOptions | undefined) => Promise<POTreeNode>;
12
14
  readonly parseSync: (arrayBuffer: ArrayBuffer, options: POTreeLoaderOptions | undefined) => POTreeNode;
15
+ readonly options: {
16
+ readonly potree: {};
17
+ };
13
18
  readonly binary: true;
14
19
  };
15
20
  //# sourceMappingURL=potree-hierarchy-chunk-loader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"potree-hierarchy-chunk-loader.d.ts","sourceRoot":"","sources":["../src/potree-hierarchy-chunk-loader.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,mBAAmB,EAAC,2BAAwB;AACzD,OAAO,KAAK,EAAC,UAAU,EAAC,kDAA+C;AAGvE,oCAAoC;AAEpC,eAAO,MAAM,0BAA0B;;;;;;;;;;CAcsC,CAAC"}
1
+ {"version":3,"file":"potree-hierarchy-chunk-loader.d.ts","sourceRoot":"","sources":["../src/potree-hierarchy-chunk-loader.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,mBAAmB,EAAC,2BAAwB;AACzD,OAAO,KAAK,EAAC,UAAU,EAAC,kDAA+C;AAOvE,oCAAoC;AACpC,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;CAkBsC,CAAC"}
@@ -2,19 +2,25 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright vis.gl contributors
4
4
  import { parsePotreeHierarchyChunk } from "./parsers/parse-potree-hierarchy-chunk.js";
5
+ // __VERSION__ is injected by babel-plugin-version-inline
6
+ // @ts-ignore TS2304: Cannot find name '__VERSION__'.
7
+ const VERSION = typeof "4.3.0-alpha.5" !== 'undefined' ? "4.3.0-alpha.5" : 'latest';
5
8
  /** Potree hierarchy chunk loader */
6
- // @ts-ignore not a valid loader
7
9
  export const PotreeHierarchyChunkLoader = {
8
10
  dataType: null,
9
11
  batchType: null,
10
- id: 'potree',
11
12
  name: 'potree Hierarchy Chunk',
13
+ id: 'potree-hrc',
14
+ module: 'potree',
15
+ version: VERSION,
12
16
  extensions: ['hrc'],
13
17
  mimeTypes: ['application/octet-stream'],
14
18
  // binary potree files have no header bytes, no content test function possible
15
19
  // test: ['...'],
16
20
  parse: async (arrayBuffer, options) => parsePotreeHierarchyChunk(arrayBuffer),
17
21
  parseSync: (arrayBuffer, options) => parsePotreeHierarchyChunk(arrayBuffer),
22
+ options: {
23
+ potree: {}
24
+ },
18
25
  binary: true
19
- // @ts-ignore
20
26
  };
@@ -6,13 +6,14 @@ export type POTreeLoaderOptions = LoaderOptions & {
6
6
  export declare const PotreeLoader: {
7
7
  readonly dataType: any;
8
8
  readonly batchType: never;
9
- readonly name: "potree";
9
+ readonly name: "potree metadata";
10
10
  readonly id: "potree";
11
11
  readonly module: "potree";
12
12
  readonly version: any;
13
- readonly extensions: ["json"];
13
+ readonly extensions: ["js"];
14
14
  readonly mimeTypes: ["application/json"];
15
15
  readonly testText: (text: string) => boolean;
16
+ readonly parse: (data: ArrayBuffer) => any;
16
17
  readonly parseTextSync: (text: string) => any;
17
18
  readonly options: {
18
19
  readonly potree: {};
@@ -1 +1 @@
1
- {"version":3,"file":"potree-loader.d.ts","sourceRoot":"","sources":["../src/potree-loader.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAmB,aAAa,EAAC,MAAM,0BAA0B,CAAC;AAM9E,MAAM,MAAM,mBAAmB,GAAG,aAAa,GAAG;IAChD,MAAM,CAAC,EAAE,EAAE,CAAC;CACb,CAAC;AAEF,oBAAoB;AAEpB,eAAO,MAAM,YAAY;;;;;;;;;;;;;;CAgB6C,CAAC"}
1
+ {"version":3,"file":"potree-loader.d.ts","sourceRoot":"","sources":["../src/potree-loader.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAmB,aAAa,EAAC,MAAM,0BAA0B,CAAC;AAM9E,MAAM,MAAM,mBAAmB,GAAG,aAAa,GAAG;IAChD,MAAM,CAAC,EAAE,EAAE,CAAC;CACb,CAAC;AAEF,oBAAoB;AACpB,eAAO,MAAM,YAAY;;;;;;;;;;2BAWT,WAAW;;;;;CAK2C,CAAC"}
@@ -3,22 +3,21 @@
3
3
  // Copyright vis.gl contributors
4
4
  // __VERSION__ is injected by babel-plugin-version-inline
5
5
  // @ts-ignore TS2304: Cannot find name '__VERSION__'.
6
- const VERSION = typeof "4.3.0-alpha.3" !== 'undefined' ? "4.3.0-alpha.3" : 'latest';
6
+ const VERSION = typeof "4.3.0-alpha.5" !== 'undefined' ? "4.3.0-alpha.5" : 'latest';
7
7
  /** Potree loader */
8
- // @ts-ignore
9
8
  export const PotreeLoader = {
10
9
  dataType: null,
11
10
  batchType: null,
12
- name: 'potree',
11
+ name: 'potree metadata',
13
12
  id: 'potree',
14
13
  module: 'potree',
15
14
  version: VERSION,
16
- extensions: ['json'],
15
+ extensions: ['js'],
17
16
  mimeTypes: ['application/json'],
18
17
  testText: (text) => text.indexOf('octreeDir') >= 0,
18
+ parse: (data) => JSON.parse(new TextDecoder().decode(data)),
19
19
  parseTextSync: (text) => JSON.parse(text),
20
20
  options: {
21
21
  potree: {}
22
22
  }
23
- // @ts-ignore
24
23
  };
@@ -0,0 +1,22 @@
1
+ import { PotreeNodesSource, PotreeNodesSourceProps } from "./lib/potree-node-source.js";
2
+ /**
3
+ * Creates point cloud data sources for Potree urls
4
+ */
5
+ export declare const PotreeSource: {
6
+ readonly name: "Potree";
7
+ readonly id: "potree";
8
+ readonly module: "potree";
9
+ readonly version: "1.7";
10
+ readonly extensions: ["bin", "las", "laz"];
11
+ readonly mimeTypes: ["application/octet-stream"];
12
+ readonly options: {
13
+ readonly url: never;
14
+ readonly potree: {};
15
+ };
16
+ readonly type: "potree";
17
+ readonly fromUrl: true;
18
+ readonly fromBlob: true;
19
+ readonly testURL: (url: string) => boolean;
20
+ readonly createDataSource: (url: string | Blob, props: PotreeNodesSourceProps) => PotreeNodesSource;
21
+ };
22
+ //# sourceMappingURL=potree-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"potree-source.d.ts","sourceRoot":"","sources":["../src/potree-source.ts"],"names":[],"mappings":"AAKA,OAAO,EAAC,iBAAiB,EAAE,sBAAsB,EAAC,oCAAiC;AAInF;;GAEG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;4BAYR,MAAM;qCACG,MAAM,GAAG,IAAI,SAAS,sBAAsB;CAEA,CAAC"}
@@ -0,0 +1,22 @@
1
+ // loaders.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+ import { PotreeNodesSource } from "./lib/potree-node-source.js";
5
+ const VERSION = '1.7';
6
+ /**
7
+ * Creates point cloud data sources for Potree urls
8
+ */
9
+ export const PotreeSource = {
10
+ name: 'Potree',
11
+ id: 'potree',
12
+ module: 'potree',
13
+ version: VERSION,
14
+ extensions: ['bin', 'las', 'laz'],
15
+ mimeTypes: ['application/octet-stream'],
16
+ options: { url: undefined, potree: {} },
17
+ type: 'potree',
18
+ fromUrl: true,
19
+ fromBlob: true,
20
+ testURL: (url) => url.endsWith('.js'),
21
+ createDataSource: (url, props) => new PotreeNodesSource(url, props)
22
+ };
@@ -0,0 +1,88 @@
1
+ /** Bounding box */
2
+ export interface PotreeBoundingBox {
3
+ /** Min X */
4
+ lx: number;
5
+ /** Min Y */
6
+ ly: number;
7
+ /** Min Z */
8
+ lz: number;
9
+ /** Max X */
10
+ ux: number;
11
+ /** Max Y */
12
+ uy: number;
13
+ /** Max Z */
14
+ uz: number;
15
+ }
16
+ /** Attribute types for *.bin content */
17
+ export type PotreeAttribute =
18
+ /** 3 (uint32) numbers: x, y, z */
19
+ 'POSITION_CARTESIAN'
20
+ /** 4 x (uint8) numbers for the color: r, g, b, a */
21
+ | 'RGBA_PACKED'
22
+ /** 4 x (uint8) numbers for the color: r, g, b, a */
23
+ | 'COLOR_PACKED'
24
+ /** 3 x (uint8) numbers for the color: r, g, b */
25
+ | 'RGB_PACKED'
26
+ /** 3 x (float) numbers: x', y', z' */
27
+ | 'NORMAL_FLOATS'
28
+ /** (uint8) number */
29
+ | 'FILLER_1B'
30
+ /** (uint16) number specifying the point's intensity */
31
+ | 'INTENSITY'
32
+ /** (uint8) id for the class used */
33
+ | 'CLASSIFICATION'
34
+ /** Note: might need to be revisited, best don't use */
35
+ | 'NORMAL_SPHEREMAPPED'
36
+ /** Note: might need to be revisited, best don't use */
37
+ | 'NORMAL_OCT16'
38
+ /** 3 x (float) numbers: x', y', z' */
39
+ | 'NORMAL';
40
+ /** Hierarchy item: [node name leading with 'r', points count
41
+ * @example [r043, 145]
42
+ ] */
43
+ export type HierarchyItem = [string, number];
44
+ /**
45
+ * Potree data set format metadata (cloud.js)
46
+ * @version 1.7
47
+ * @link https://github.com/potree/potree/blob/1.7/docs/potree-file-format.md
48
+ * */
49
+ export interface PotreeMetadata {
50
+ /** Version number in which this file is written */
51
+ version: string;
52
+ /** Folder that is used to load additional data */
53
+ octreeDir: string;
54
+ /** Amount of points contained in the whole pointcloud data */
55
+ points: number;
56
+ /**
57
+ * This parameter is used to transform the point data
58
+ * to the projection system used while visualizing the points. It has to be
59
+ * in a format that is parsable by [proj.4][proj4].
60
+ * */
61
+ projection: string;
62
+ /** Bounding box of the world used to limit the initial POV. */
63
+ boundingBox: PotreeBoundingBox;
64
+ /** Bounding box of the actual points in the data */
65
+ tightBoundingBox: PotreeBoundingBox;
66
+ /** Description of point attributes in data files */
67
+ pointAttributes: 'LAS' | 'LAZ' | PotreeAttribute[];
68
+ /**
69
+ * Space between points at the root node.
70
+ * This value is halved at each octree level.
71
+ * */
72
+ spacing: number;
73
+ /**
74
+ * Scale applied to convert POSITION_CARTESIAN components
75
+ * from uint32 values to floating point values. The full transformation
76
+ * to world coordinates is
77
+ * position = (POSITION_CARTESIAN * scale) + boundingBox.min
78
+ * */
79
+ scale: number;
80
+ /** Amount of Octree levels before a new folder hierarchy is expected. */
81
+ hierarchyStepSize: number;
82
+ /**
83
+ * The hierarchy of files, now loaded through index files.
84
+ * @deprecated
85
+ * */
86
+ hierarchy: HierarchyItem[];
87
+ }
88
+ //# sourceMappingURL=potree-metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"potree-metadata.d.ts","sourceRoot":"","sources":["../../src/types/potree-metadata.ts"],"names":[],"mappings":"AAIA,mBAAmB;AACnB,MAAM,WAAW,iBAAiB;IAChC,YAAY;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,YAAY;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,YAAY;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,YAAY;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,YAAY;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,YAAY;IACZ,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,wCAAwC;AACxC,MAAM,MAAM,eAAe;AACzB,kCAAkC;AAChC,oBAAoB;AACtB,oDAAoD;GAClD,aAAa;AACf,oDAAoD;GAClD,cAAc;AAChB,iDAAiD;GAC/C,YAAY;AACd,uCAAuC;GACrC,eAAe;AACjB,qBAAqB;GACnB,WAAW;AACb,uDAAuD;GACrD,WAAW;AACb,oCAAoC;GAClC,gBAAgB;AAClB,uDAAuD;GACrD,qBAAqB;AACvB,uDAAuD;GACrD,cAAc;AAChB,sCAAsC;GACpC,QAAQ,CAAC;AAEb;;IAEI;AACJ,MAAM,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE7C;;;;KAIK;AACL,MAAM,WAAW,cAAc;IAC7B,mDAAmD;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,MAAM,EAAE,MAAM,CAAC;IACf;;;;SAIK;IACL,UAAU,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,WAAW,EAAE,iBAAiB,CAAC;IAC/B,oDAAoD;IACpD,gBAAgB,EAAE,iBAAiB,CAAC;IACpC,oDAAoD;IACpD,eAAe,EAAE,KAAK,GAAG,KAAK,GAAG,eAAe,EAAE,CAAC;IACnD;;;SAGK;IACL,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;SAKK;IACL,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;;SAGK;IACL,SAAS,EAAE,aAAa,EAAE,CAAC;CAC5B"}
@@ -0,0 +1,4 @@
1
+ // loaders.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+ export {};
@@ -0,0 +1,5 @@
1
+ export declare function parseVersion(version: string): {
2
+ major: number;
3
+ minor: number;
4
+ };
5
+ //# sourceMappingURL=parse-version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-version.d.ts","sourceRoot":"","sources":["../../src/utils/parse-version.ts"],"names":[],"mappings":"AAIA,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CAG5E"}
@@ -0,0 +1,7 @@
1
+ // loaders.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+ export function parseVersion(version) {
5
+ const parts = version.split('.').map(Number);
6
+ return { major: parts[0], minor: parts[1] };
7
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loaders.gl/potree",
3
- "version": "4.3.0-alpha.4",
3
+ "version": "4.3.0-alpha.6",
4
4
  "description": "potree loaders for large point clouds.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -44,11 +44,13 @@
44
44
  "build-bundle-dev": "ocular-bundle ./bundle.ts --env=dev --output=dist/dist.dev.js"
45
45
  },
46
46
  "dependencies": {
47
- "@loaders.gl/math": "4.3.0-alpha.4",
47
+ "@loaders.gl/las": "4.3.0-alpha.6",
48
+ "@loaders.gl/math": "4.3.0-alpha.6",
49
+ "@loaders.gl/schema": "4.3.0-alpha.6",
48
50
  "@math.gl/core": "^4.0.0"
49
51
  },
50
52
  "peerDependencies": {
51
53
  "@loaders.gl/core": "^4.0.0"
52
54
  },
53
- "gitHead": "4900ac4c4de20366c050b80cef04dc5b52d167af"
55
+ "gitHead": "315f2e232fc4e6a477c41de800a54d3e3d957e8c"
54
56
  }
package/src/index.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export {PotreeLoader} from './potree-loader';
2
2
  export {PotreeHierarchyChunkLoader} from './potree-hierarchy-chunk-loader';
3
3
  export {PotreeBinLoader} from './potree-bin-loader';
4
+ export {PotreeSource} from './potree-source';
@@ -0,0 +1,174 @@
1
+ // loaders.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ import {load} from '@loaders.gl/core';
6
+ import {MeshGeometry} from '@loaders.gl/schema';
7
+ import {DataSource, DataSourceProps, LoaderOptions, resolvePath} from '@loaders.gl/loader-utils';
8
+ import {LASLoader} from '@loaders.gl/las';
9
+ import {PotreeMetadata} from '../types/potree-metadata';
10
+ import {POTreeNode} from '../parsers/parse-potree-hierarchy-chunk';
11
+ import {PotreeHierarchyChunkLoader} from '../potree-hierarchy-chunk-loader';
12
+ import {PotreeLoader} from '../potree-loader';
13
+ import {parseVersion} from '../utils/parse-version';
14
+
15
+ export type PotreeNodesSourceProps = DataSourceProps & {
16
+ attributions?: string[];
17
+ potree?: {
18
+ loadOptions?: LoaderOptions; // PotreeLoaderOptions;
19
+ // TODO - add options here
20
+ };
21
+ };
22
+
23
+ /**
24
+ * A Potree data source
25
+ * @version 1.0 - https://github.com/potree/potree/blob/1.0RC/docs/file_format.md
26
+ * @version 1.7 - https://github.com/potree/potree/blob/1.7/docs/potree-file-format.md
27
+ * @note Point cloud nodes tile source
28
+ */
29
+ export class PotreeNodesSource extends DataSource {
30
+ /** Dataset base URL */
31
+ baseUrl: string = '';
32
+ /** Input data: string - dataset url, blob - single file data */
33
+ data: string | Blob;
34
+ /** Input props */
35
+ props: PotreeNodesSourceProps;
36
+ /** Meta information from `cloud.js` */
37
+ metadata: PotreeMetadata | null = null;
38
+ /** Root node */
39
+ root: POTreeNode | null = null;
40
+ /** Is data source ready to use after initial loading */
41
+ isReady = false;
42
+
43
+ private initPromise: Promise<void> | null = null;
44
+
45
+ /**
46
+ * @constructor
47
+ * @param data - if string - data set path url or path to `cloud.js` metadata file
48
+ * - if Blob - single file data
49
+ * @param props - data source properties
50
+ */
51
+ constructor(data: string | Blob, props: PotreeNodesSourceProps) {
52
+ super(props);
53
+ this.props = props;
54
+ this.data = data;
55
+ this.makeBaseUrl(this.data);
56
+
57
+ this.initPromise = this.init();
58
+ }
59
+
60
+ /** Initial data source loading */
61
+ async init() {
62
+ if (this.initPromise) {
63
+ await this.initPromise;
64
+ return;
65
+ }
66
+ this.metadata = await load(`${this.baseUrl}/cloud.js`, PotreeLoader);
67
+ await this.loadHierarchy();
68
+ this.isReady = true;
69
+ }
70
+
71
+ /** Is data set supported */
72
+ isSupported(): boolean {
73
+ const {minor, major} = parseVersion(this.metadata?.version ?? '');
74
+ return (
75
+ this.isReady &&
76
+ major === 1 &&
77
+ minor < 2 &&
78
+ typeof this.metadata?.pointAttributes === 'string' &&
79
+ ['LAS', 'LAZ'].includes(this.metadata?.pointAttributes)
80
+ );
81
+ }
82
+
83
+ /** Get content files extension */
84
+ getContentExtension(): string | null {
85
+ if (!this.isReady) {
86
+ return null;
87
+ }
88
+ switch (this.metadata?.pointAttributes) {
89
+ case 'LAS':
90
+ return 'las';
91
+ case 'LAZ':
92
+ return 'laz';
93
+ default:
94
+ return 'bin';
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Load octree node content
100
+ * @param path array of numbers between 0-7 specifying successive octree divisions.
101
+ * @return node content geometry or null if the node doesn't exist
102
+ */
103
+ async loadNodeContent(path: number[]): Promise<MeshGeometry | null> {
104
+ await this.initPromise;
105
+
106
+ if (!this.isSupported()) {
107
+ return null;
108
+ }
109
+
110
+ const isAvailable = await this.isNodeAvailable(path);
111
+ if (isAvailable) {
112
+ return load(
113
+ `${this.baseUrl}/${this.metadata
114
+ ?.octreeDir}/r/r${path.join()}.${this.getContentExtension()}`,
115
+ LASLoader
116
+ );
117
+ }
118
+ return null;
119
+ }
120
+
121
+ /**
122
+ * Check if a node exists in the octree
123
+ * @param path array of numbers between 0-7 specifying successive octree divisions
124
+ * @returns true - the node does exist, false - the nodes doesn't exist
125
+ */
126
+ async isNodeAvailable(path: number[]): Promise<boolean> {
127
+ if (this.metadata?.hierarchy) {
128
+ return this.metadata.hierarchy.findIndex((item) => item[0] === `r${path.join()}`) !== -1;
129
+ }
130
+
131
+ if (!this.root) {
132
+ return false;
133
+ }
134
+ let currentParent = this.root;
135
+ let name = '';
136
+ let result = true;
137
+ for (const nodeLevel of path) {
138
+ const newName = `${name}${nodeLevel}`;
139
+ const node = currentParent.children.find((child) => child.name === newName);
140
+ if (node) {
141
+ currentParent = node;
142
+ name = newName;
143
+ } else {
144
+ result = false;
145
+ break;
146
+ }
147
+ }
148
+ return result;
149
+ }
150
+
151
+ /**
152
+ * Load data source hierarchy into tree of available nodes
153
+ */
154
+ private async loadHierarchy(): Promise<void> {
155
+ this.root = await load(
156
+ `${this.baseUrl}/${this.metadata?.octreeDir}/r/r.hrc`,
157
+ PotreeHierarchyChunkLoader
158
+ );
159
+ }
160
+
161
+ /**
162
+ * Deduce base url from the input url sring
163
+ * @param data - data source input data
164
+ */
165
+ private makeBaseUrl(data: string | Blob): void {
166
+ this.baseUrl = typeof data === 'string' ? resolvePath(data) : '';
167
+ if (this.baseUrl.endsWith('cloud.js')) {
168
+ this.baseUrl = this.baseUrl.substring(0, -8);
169
+ }
170
+ if (this.baseUrl.endsWith('/')) {
171
+ this.baseUrl = this.baseUrl.substring(0, -1);
172
+ }
173
+ }
174
+ }