LiDAR 3D Point Cloud of Geospatial Data

Demonstrates how to visualize LiDAR UAV Data from the Defra survey using SciChart.js. A 1km x 1km slice of London is visualised as a 3D point-cloud with contour map overlaid. A heatmap legend on the right indicates the heightmap.

Fullscreen

Edit

 Edit

Docs

drawExample.ts

angular.ts

theme.ts

AscReader.ts

Copy to clipboard
Minimise
Fullscreen
1import {
2    CameraController,
3    EColorMapMode,
4    EDrawMeshAs,
5    EMeshPaletteMode,
6    ETitlePosition,
7    GradientColorPalette,
8    HeatmapLegend,
9    linearColorMapLerp,
10    MouseWheelZoomModifier3D,
11    NumericAxis3D,
12    OrbitModifier3D,
13    PixelPointMarker3D,
14    ScatterRenderableSeries3D,
15    SciChart3DSurface,
16    SurfaceMeshRenderableSeries3D,
17    TLinearColorMap,
18    UniformGridDataSeries3D,
19    Vector3,
20    XyzDataSeries3D,
21    zeroArray2D,
22} from "scichart";
23import { AscData, AscReader } from "./AscReader";
24import { appTheme } from "../../../theme";
25
26type TMetadata = {
27    vertexColor: number;
28    pointScale: number;
29};
30
31export const drawExample = async (rootElement: string | HTMLDivElement) => {
32    // Load data from the server
33    const dataFromServer = await getDataFromServer();
34
35    // Create a SciChart3DSurface
36    const { wasmContext, sciChart3DSurface } = await SciChart3DSurface.create(rootElement, {
37        theme: appTheme.SciChartJsTheme,
38    });
39    sciChart3DSurface.worldDimensions = new Vector3(1000, 200, 1000);
40
41    // Create and attach a camera to the 3D Viewport
42    sciChart3DSurface.camera = new CameraController(wasmContext, {
43        position: new Vector3(800, 1000, 800),
44        target: new Vector3(0, 50, 0),
45    });
46
47    // Add an X,Y,Z axis to the viewport
48    sciChart3DSurface.xAxis = new NumericAxis3D(wasmContext, { axisTitle: "X Distance (Meters)" });
49    sciChart3DSurface.yAxis = new NumericAxis3D(wasmContext, { axisTitle: "Height (Meters)" });
50    sciChart3DSurface.zAxis = new NumericAxis3D(wasmContext, { axisTitle: "Z Distance (Meters)" });
51
52    // Create a ScatterRenderableSeries3D and configure as a point cloud with 1px markers
53    sciChart3DSurface.renderableSeries.add(
54        new ScatterRenderableSeries3D(wasmContext, {
55            pointMarker: new PixelPointMarker3D(wasmContext),
56            dataSeries: new XyzDataSeries3D(wasmContext, {
57                xValues: dataFromServer.ascData.XValues,
58                yValues: dataFromServer.ascData.YValues,
59                zValues: dataFromServer.ascData.ZValues,
60                metadata: dataFromServer.meta,
61            }),
62            opacity: 1,
63        })
64    );
65
66    // Also render the point-cloud data as a heightmap / topology map with contours
67    sciChart3DSurface.renderableSeries.add(
68        new SurfaceMeshRenderableSeries3D(wasmContext, {
69            dataSeries: new UniformGridDataSeries3D(wasmContext, {
70                xStart: 0,
71                xStep: dataFromServer.ascData.CellSize,
72                zStart: 0,
73                zStep: dataFromServer.ascData.CellSize,
74                yValues: dataFromServer.heightValues2D,
75            }),
76            minimum: 0,
77            maximum: 50,
78            drawSkirt: true,
79            opacity: 0.7,
80            meshColorPalette: new GradientColorPalette(wasmContext, {
81                gradientStops: [
82                    { offset: 1, color: appTheme.VividPink },
83                    { offset: 0.9, color: appTheme.VividOrange },
84                    { offset: 0.7, color: appTheme.MutedRed },
85                    { offset: 0.5, color: appTheme.VividGreen },
86                    { offset: 0.3, color: appTheme.VividSkyBlue },
87                    { offset: 0.2, color: appTheme.Indigo },
88                    { offset: 0, color: appTheme.DarkIndigo },
89                ],
90            }),
91            contourStroke: appTheme.PaleSkyBlue,
92            meshPaletteMode: EMeshPaletteMode.HEIGHT_MAP_INTERPOLATED,
93            contourStrokeThickness: 2,
94            drawMeshAs: EDrawMeshAs.SOLID_WITH_CONTOURS,
95        })
96    );
97
98    // Add interactivity modifiers for orbiting and zooming with the mousewheel
99    sciChart3DSurface.chartModifiers.add(new MouseWheelZoomModifier3D());
100    sciChart3DSurface.chartModifiers.add(new OrbitModifier3D());
101
102    return { sciChartSurface: sciChart3DSurface, wasmContext };
103};
104
105export const drawHeatmapLegend = async (rootElement: string | HTMLDivElement) => {
106    const { heatmapLegend, wasmContext } = await HeatmapLegend.create(rootElement, {
107        theme: {
108            ...appTheme.SciChartJsTheme,
109            sciChartBackground: appTheme.DarkIndigo + "BB",
110            loadingAnimationBackground: appTheme.DarkIndigo + "BB",
111        },
112        yAxisOptions: {
113            isInnerAxis: true,
114            labelStyle: {
115                fontSize: 12,
116                color: appTheme.ForegroundColor,
117            },
118            axisBorder: {
119                borderRight: 1,
120                color: appTheme.ForegroundColor + "77",
121            },
122            majorTickLineStyle: {
123                color: appTheme.ForegroundColor,
124                tickSize: 6,
125                strokeThickness: 1,
126            },
127            minorTickLineStyle: {
128                color: appTheme.ForegroundColor,
129                tickSize: 3,
130                strokeThickness: 1,
131            },
132        },
133        colorMap: {
134            minimum: 0,
135            maximum: 50,
136            gradientStops: [
137                { offset: 1, color: appTheme.VividPink },
138                { offset: 0.9, color: appTheme.VividOrange },
139                { offset: 0.7, color: appTheme.MutedRed },
140                { offset: 0.5, color: appTheme.VividGreen },
141                { offset: 0.3, color: appTheme.VividSkyBlue },
142                { offset: 0.2, color: appTheme.Indigo },
143                { offset: 0, color: appTheme.DarkIndigo },
144            ],
145        },
146    });
147
148    heatmapLegend.innerSciChartSurface.sciChartSurface.title = "Height (m)";
149
150    heatmapLegend.innerSciChartSurface.sciChartSurface.titleStyle = {
151        fontSize: 12,
152        color: appTheme.ForegroundColor,
153        position: ETitlePosition.Bottom,
154    };
155
156    return { sciChartSurface: heatmapLegend.innerSciChartSurface.sciChartSurface };
157};
158
159async function getDataFromServer() {
160    // The LinearColorMap type in SciChart allows you to generate a colour map based on a
161    // minimum and maximum value, e.g. min=0, max=50 means the gradient brush below is mapped into that range
162    //
163    const colorMap: TLinearColorMap = {
164        Minimum: 0,
165        Maximum: 50,
166        Mode: EColorMapMode.Interpolated,
167        GradientStops: [
168            { color: appTheme.DarkIndigo, offset: 0 },
169            { color: appTheme.Indigo, offset: 0.2 },
170            { color: appTheme.VividSkyBlue, offset: 0.3 },
171            { color: appTheme.VividGreen, offset: 0.5 },
172            { color: appTheme.MutedRed, offset: 0.7 },
173            { color: appTheme.VividOrange, offset: 0.9 },
174            { color: appTheme.VividPink, offset: 0 },
175        ],
176    };
177
178    // Read the ASC Lidar data file with optional color map data
179    const reader: AscReader = new AscReader((height) => {
180        // Linearly interpolate each heightValue into a colour and return to the ASCReader
181        // This will be injected into the SciChart XyzDataSeries3D to colour points in the point-cloud
182        return linearColorMapLerp(colorMap, height);
183    });
184
185    // See our source-code file tq3080_DSM_2M.js for format on this ASC Point cloud data
186    // find the source online at github: https://github.com/ABTSoftware/SciChart.JS.Examples/blob/master/Examples/src/server/Data/t
187    const hostname = window.location.hostname;
188    const port = window.location.port;
189    let host = hostname.includes("scichart.com") || hostname.includes("localhost") ? "" : "https://demo.scichart.com";
190
191    if (hostname === "localhost" && port === "4200") {
192        host = "https://demo.scichart.com";
193    }
194    const rawData = await fetch(host + "/api/lidardata");
195    const ascData: AscData = reader.parse(await rawData.text());
196
197    // Prepare metadata to contain the color values from ASCData
198    const meta: TMetadata[] = ascData.ColorValues.map((c) => ({
199        vertexColor: c,
200        pointScale: 0,
201    }));
202
203    // Prepare heightValues2D for the uniform surface mesh (transform point cloud to 2d array of heights)
204    const heightValues2D = zeroArray2D([ascData.NumberRows, ascData.NumberColumns]);
205    for (let index = 0, z = 0; z < ascData.NumberRows; z++) {
206        for (let x = 0; x < ascData.NumberColumns; x++) {
207            heightValues2D[z][x] = ascData.YValues[index++];
208        }
209    }
210
211    return {
212        ascData,
213        meta,
214        heightValues2D,
215    };
216}
217

See Also: Scientific & Medical Charts (5 Demos)

Angular Vital Signs ECG/EKG Medical Demo | SciChart.js Demo

Angular Vital Signs ECG/EKG Medical Demo

In this example we are simulating four channels of data showing that SciChart.js can be used to draw real-time ECG/EKG charts and graphs to monitor heart reate, body temperature, blood pressure, pulse rate, SPO2 blood oxygen, volumetric flow and more.

Angular Chart with Logarithmic Axis Example | SciChart.js Demo

Angular Chart with Logarithmic Axis Example

Demonstrates Logarithmic Axis on a Angular Chart using SciChart.js. SciChart supports logarithmic axis with scientific or engineering notation and positive and negative values

Angular Chart with Vertically Stacked Axes | SciChart.js Demo

Angular Chart with Vertically Stacked Axes

Demonstrates Vertically Stacked Axes on a Angular Chart using SciChart.js, allowing data to overlap

Realtime Audio Analyzer Demo | SciChart.js Demo

Realtime Audio Analyzer Demo

Demonstrating the capability of SciChart.js to create a JavaScript Audio Analyzer and visualize the Fourier-Transform of an audio waveform in realtime.

Interactive Waterfall Chart | SciChart.js Demo

Interactive Waterfall Spectral Chart

Demonstrates how to create a Waterfall chart in SciChart.js, showing chromotragraphy data with interactive selection of points.

SciChart Ltd, 16 Beaufort Court, Admirals Way, Docklands, London, E14 9XL.