Skip to content

Commit

Permalink
feat(las): Use laz-rs-wasm to support laz 1.4 (#3165)
Browse files Browse the repository at this point in the history
  • Loading branch information
alekzvik authored Dec 2, 2024
1 parent f1b999c commit 2d13ec2
Show file tree
Hide file tree
Showing 16 changed files with 787 additions and 20,747 deletions.
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ examples/experimental/gltf-with-raw-webgl/

modules/potree/test/data/**/cloud.js

modules/las/src/lib/libs

modules/flatgeobuf/src/lib/binary-geometries.ts

modules/i3s/src/i3s-attribute-loader.ts
Expand Down
34 changes: 20 additions & 14 deletions examples/website/pointcloud/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import React, {useState, useEffect} from 'react';
import {render} from 'react-dom';

import DeckGL from '@deck.gl/react';
import {COORDINATE_SYSTEM, OrbitView, LinearInterpolator} from '@deck.gl/core';
import {COORDINATE_SYSTEM, OrbitView, LinearInterpolator, OrbitViewState} from '@deck.gl/core';
import {PointCloudLayer} from '@deck.gl/layers';

import {load} from '@loaders.gl/core';
Expand All @@ -25,7 +25,7 @@ import {EXAMPLES} from './examples';
const POINT_CLOUD_LOADERS = [DracoLoader, LASLoader, PLYLoader, PCDLoader, OBJLoader];

const INITIAL_VIEW_STATE = {
target: [0, 0, 0],
target: [0, 0, 0] as [number, number, number],
rotationX: 0,
rotationOrbit: 0,
orbitAxis: 'Y',
Expand All @@ -46,25 +46,29 @@ type AppProps = {
/** On tiles load */
onTilesLoad?: Function;
/** Any informational text to display in the overlay */
children?: React.Children;
children?: typeof React.Children;
};

/** Application state */
type AppState = {
/** Currently active tile source */
pointData: any;
/** Metadata loaded from active tile source */
metadata: string;
metadata: string | null;
/**Current view state */
viewState: Record<string, number>;
viewState: OrbitViewState;
/** Metadata loaded from active tile source */
selectedExample?: string;
loadTimeMs?: number;
loadStartMs?: number;
};

export default function App(props: AppProps = {}) {
const [state, setState] = useState<AppState>({
viewState: INITIAL_VIEW_STATE,
pointData: null,
metadata: null
// TODO - handle errors
metadata: null,
// TODO - handle errors
// error: null
});

Expand Down Expand Up @@ -95,8 +99,8 @@ export default function App(props: AppProps = {}) {
{/* error ? <div style={{color: 'red'}}>{error}</div> : '' */}
<PointCloudStats
vertexCount={pointData?.length || 0}
loadTimeMs={state.loadTimeMs}
loadStartMs={state.loadStartMs}
loadTimeMs={state.loadTimeMs || 0}
loadStartMs={state.loadStartMs || 0}
/>
<h3>Schema and Metadata</h3>
<MetadataViewer metadata={state.metadata} />
Expand Down Expand Up @@ -128,7 +132,7 @@ export default function App(props: AppProps = {}) {
...state,
viewState: {
...state.viewState,
rotationOrbit: state.viewState.rotationOrbit + 10,
rotationOrbit: (state.viewState.rotationOrbit || 0) + 10,
transitionDuration: 600,
transitionInterpolator,
onTransitionEnd: rotateCamera
Expand All @@ -150,12 +154,14 @@ export default function App(props: AppProps = {}) {
pointData: null,
metadata: null,
loadTimeMs: undefined,
loadStartMs: Date.now()
loadStartMs: Date.now(),
selectedExample: exampleName,
}));

const {url} = example;
try {
const pointCloud = (await load(url, POINT_CLOUD_LOADERS)) as Mesh;
// TODO: remove worker: false, as it is used for local development
const pointCloud = (await load(url, POINT_CLOUD_LOADERS, {worker: false})) as Mesh;
const {schema, header, loaderData, attributes} = pointCloud;

const viewState = getViewState(state, loaderData, attributes);
Expand All @@ -164,7 +170,7 @@ export default function App(props: AppProps = {}) {

setState((state) => ({
...state,
loadTimeMs: Date.now() - state.loadStartMs,
loadTimeMs: state.loadStartMs ? Date.now() - state.loadStartMs : undefined,
loadStartMs: undefined,
// TODO - Some popular "point cloud" formats (PLY) can also generate indexed meshes
// in which case the vertex count is not correct for display as points
Expand Down Expand Up @@ -243,7 +249,7 @@ function getViewState(state: AppState, loaderData, attributes) {
return {
...INITIAL_VIEW_STATE,
...viewState,
target: [(mins[0] + maxs[0]) / 2, (mins[1] + maxs[1]) / 2, (mins[2] + maxs[2]) / 2],
target: [(mins[0] + maxs[0]) / 2, (mins[1] + maxs[1]) / 2, (mins[2] + maxs[2]) / 2] as [number, number, number],
zoom: Math.log2(window.innerWidth / (maxs[0] - mins[0])) - 1
};
}
Expand Down
11 changes: 9 additions & 2 deletions examples/website/pointcloud/examples.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,18 @@ export const EXAMPLES: Record<string, Record<string, Example>> = {
'Indoor Scan 800K': {
type: 'las',
url: `${DECK_DATA_URI}/examples/point-cloud-laz/indoor.0.1.laz`
}
},
'LAS 1-4 example': {
type: 'las',
// TODO upload the file to deck data
url: 'https://pub-0e04e4fabfef402d8789a24f6a393790.r2.dev/SerpentMound_LAS14_ExtraDims.laz'

},
// TODO need fix
// 'Indoor Scan 8M': {
// type: 'las',
// url: `${DECK_DATA_URI}/examples/point-cloud-laz/indoor.laz`
// }
// },
},

Draco: {
Expand Down
7 changes: 3 additions & 4 deletions modules/las/src/las-arrow-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,19 @@
import type {LoaderWithParser} from '@loaders.gl/loader-utils';
import type {ArrowTable} from '@loaders.gl/schema';

import {LASLoaderOptions, LASWorkerLoader} from './las-loader';
import {LASLoaderOptions, LASLoader} from './las-loader';
import {convertMeshToTable} from '@loaders.gl/schema-utils';
import {parseLAS} from './lib/parse-las';

/**
* Worker loader for LAS - Point Cloud Data
*/
export const LASArrowLoader = {
...LASWorkerLoader,
...LASLoader,
dataType: null as unknown as ArrowTable,
batchType: null as never,
worker: false,
parse: async (arrayBuffer: ArrayBuffer) => {
const mesh = parseLAS(arrayBuffer);
const mesh = await LASLoader.parse(arrayBuffer);
const arrowTable = convertMeshToTable(mesh, 'arrow-table');
return arrowTable;
}
Expand Down
4 changes: 2 additions & 2 deletions modules/las/src/las-format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const LASFormat = {
module: 'las',
extensions: ['las', 'laz'], // LAZ is the "compressed" flavor of LAS,
mimeTypes: ['application/octet-stream'], // TODO - text version?
text: true,
text: false,
binary: true,
tests: ['LAS']
tests: ['LASF']
} as const satisfies Format;
19 changes: 5 additions & 14 deletions modules/las/src/las-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {Loader, LoaderWithParser, LoaderOptions} from '@loaders.gl/loader-u
import type {LASMesh} from './lib/las-types';
import {LASFormat} from './las-format';
import {parseLAS} from './lib/parse-las';
import initLazRsWasm from './lib/libs/laz_rs_wasm';

// __VERSION__ is injected by babel-plugin-version-inline
// @ts-ignore TS2304: Cannot find name '__VERSION__'.
Expand All @@ -26,24 +27,15 @@ export type LASLoaderOptions = LoaderOptions & {

/**
* Loader for the LAS (LASer) point cloud format
* @note Does not support LAS v1.4
*/
export const LASWorkerLoader = {
...LASFormat,

dataType: null as unknown as LASMesh,
batchType: null as never,

name: 'LAS',
id: 'las',
module: 'las',
version: VERSION,
worker: true,
extensions: ['las', 'laz'], // LAZ is the "compressed" flavor of LAS,
mimeTypes: ['application/octet-stream'], // TODO - text version?
text: true,
binary: true,
tests: ['LAS'],
options: {
las: {
shape: 'mesh',
Expand All @@ -56,12 +48,11 @@ export const LASWorkerLoader = {

/**
* Loader for the LAS (LASer) point cloud format
* @note Does not support LAS v1.4
*/
export const LASLoader = {
...LASWorkerLoader,
parse: async (arrayBuffer: ArrayBuffer, options?: LASLoaderOptions) =>
parseLAS(arrayBuffer, options),
parseSync: (arrayBuffer: ArrayBuffer, options?: LASLoaderOptions) =>
parseLAS(arrayBuffer, options)
parse: async (arrayBuffer: ArrayBuffer, options?: LASLoaderOptions) => {
await initLazRsWasm();
return parseLAS(arrayBuffer, {...options});
}
} as const satisfies LoaderWithParser<LASMesh, never, LASLoaderOptions>;
2 changes: 1 addition & 1 deletion modules/las/src/lib/get-las-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {deduceMeshSchema} from '@loaders.gl/schema-utils';
import type {LASHeader} from './las-types';

/**
* Gets schema from PLY header
* Gets schema from LAS header
* @param lasHeader
* @param metadata
* @returns Schema
Expand Down
1 change: 1 addition & 0 deletions modules/las/src/lib/las-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export type LASHeader = {
mins?: number[];
totalToRead: number;
totalRead: number;
hasColor: boolean;
versionAsString?: string;
isCompressed?: boolean;
};
Expand Down
Loading

0 comments on commit 2d13ec2

Please sign in to comment.