Reputation: 11
I am busy writing a react app with the goal of having a global map that can display 3D point-clouds. Currently I am in the very beginning stages and I am still getting to grips with the deck-gl, react-map-gl and Maplibre libraries and how they interact in react code. I have gotten to the point where I can successfully parse some test LiDAR data using the LASWorkerLoader from the loaders.gl library from user input. I have it projected to the OGC:WGS84 projection as, as far as I understand, it needs to be in that projection to be able to display it in a MapView. However, it is failing to load the dataset and loses WebGL context whenever I try to load the dataset. It gives a Invalid LngLat object: (Nan, Nan) error when trying to load the layer.
I have tried to determine if the data has been parsed correctly and whether it is in a format that the loader can parse. I have logged the parsed data and the response can be seen in the image.LASMesh parsed object log
This is the code I've tried to use:
import 'maplibre-gl/dist/maplibre-gl.css';
import React, {useState, useEffect, useMemo} from 'react';
import {Map, NavigationControl, Popup, useControl, FullscreenControl} from 'react-map-gl/maplibre';
import {GeoJsonLayer, ArcLayer, PointCloudLayer, MapView, OrthographicView} from 'deck.gl';
import { COORDINATE_SYSTEM } from 'deck.gl';
import {MapboxOverlay as DeckOverlay} from '@deck.gl/mapbox';
import ControlPanel, {COLOURS} from './ControlPanel';
import {LASWorkerLoader} from '@loaders.gl/las'
import { load } from '@loaders.gl/core';
// source: Natural Earth http://www.naturalearthdata.com/ via geojson.xyz
const AIR_PORTS =
'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_airports.geojson';
const INITIAL_VIEW_STATE = {
longitude: 0,
latitude: 0,
zoom: 2,
pitch: 0,
bearing: 0
};
const MAP_STYLE = 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json';
function DeckGLOverlay(props) {
const overlay = useControl(() => new DeckOverlay(props));
overlay.setProps(props);
return null;
}
function MapOverlay() {
const [lasData, setLasData] = useState(null);
const [viewState, setViewState] = useState(INITIAL_VIEW_STATE);
const [error, setError] = useState(null);
const handleFileChange = async (event) => {
const file = event.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = async () => {
try {
const arrayBuffer = reader.result;
const parsedData = await load(arrayBuffer, LASWorkerLoader);
console.log('Parsed LAS data:', parsedData);
setLasData(parsedData);
if (parsedData.header && parsedData.header.boundingBox) {
const [minX, minY, , maxX, maxY] = parsedData.header.boundingBox;
const centerX = (minX + maxX) / 2;
const centerY = (minY + maxY) / 2;
setViewState({
...INITIAL_VIEW_STATE,
longitude: centerX,
latitude: centerY,
});
}
} catch (error) {
console.error('Error loading LAS data:', error);
setError('Failed to load LAS data. Please try a different file.');
}
};
reader.readAsArrayBuffer(file);
};
const layers = useMemo(() => {
if (!lasData) return [];
return [
new PointCloudLayer({
id: 'lidar-point-cloud',
data: lasData.attributes.POSITION.value,
coordinateSystem: COORDINATE_SYSTEM.CARTESIAN,
getPosition: d => [d[0], d[1], d[2]],
getColor: d => {
const intensity = lasData.attributes.intensity ?
lasData.attributes.intensity.value[Math.floor(d[3])] : 255;
return [intensity, intensity, intensity, 255];
},
pointSize: 1,
opacity: 0.5,
pickable: false,
onHover: info => console.log('Hovered:', info),
coordinateOrigin: lasData.header ? [
(lasData.header.boundingBox[0] + lasData.header.boundingBox[3]) / 2,
(lasData.header.boundingBox[1] + lasData.header.boundingBox[4]) / 2,
(lasData.header.boundingBox[2] + lasData.header.boundingBox[5]) / 2
] : [0, 0, 0]
})
];
}, [lasData]);
if (error) {
return <div className="error-message">{error}</div>;
}
return (
<>
<div>
<input type="file" accept=".laz,.las" onChange={handleFileChange} />
</div>
<div className='map-container'>
<Map
{...viewState}
onMove={evt => setViewState(evt.viewState)}
mapStyle={MAP_STYLE}
>
<DeckGLOverlay layers={layers} />
<NavigationControl position="top-right" />
<FullscreenControl position='top-right'/>
</Map>
<ControlPanel/>
</div>
</>
);
}
export default MapOverlay;
It is suppose to display the opensource laz data of the USGS_LPC_AZ_LowerColoradoRiver_2018_B18_w1561n1557 found at https://rockyweb.usgs.gov/vdelivery/Datasets/Staged/Elevation/LPC/Projects/AZ_LowerColoradoRiver_2018_B18/AZ_LowerColoradoRiver_B1_2018/LAZ/. I am quite stuck on how to correctly access the parsed data and I don't know whether I need to apply further transformations.
Upvotes: 1
Views: 111