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.
drawExample.ts
ExampleDataProvider.ts
angular.ts
theme.ts
AscReader.ts
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";
25import { fetchLidarData } from "../../../ExampleData/ExampleDataProvider";
26
27type TMetadata = {
28 vertexColor: number;
29 pointScale: number;
30};
31
32export const drawExample = async (rootElement: string | HTMLDivElement) => {
33 // Load data from the server
34 const dataFromServer = await getDataFromServer();
35
36 // Create a SciChart3DSurface
37 const { wasmContext, sciChart3DSurface } = await SciChart3DSurface.create(rootElement, {
38 theme: appTheme.SciChartJsTheme,
39 });
40 sciChart3DSurface.worldDimensions = new Vector3(1000, 200, 1000);
41
42 // Create and attach a camera to the 3D Viewport
43 sciChart3DSurface.camera = new CameraController(wasmContext, {
44 position: new Vector3(800, 1000, 800),
45 target: new Vector3(0, 50, 0),
46 });
47
48 // Add an X,Y,Z axis to the viewport
49 sciChart3DSurface.xAxis = new NumericAxis3D(wasmContext, { axisTitle: "X Distance (Meters)" });
50 sciChart3DSurface.yAxis = new NumericAxis3D(wasmContext, { axisTitle: "Height (Meters)" });
51 sciChart3DSurface.zAxis = new NumericAxis3D(wasmContext, { axisTitle: "Z Distance (Meters)" });
52
53 // Create a ScatterRenderableSeries3D and configure as a point cloud with 1px markers
54 sciChart3DSurface.renderableSeries.add(
55 new ScatterRenderableSeries3D(wasmContext, {
56 pointMarker: new PixelPointMarker3D(wasmContext),
57 dataSeries: new XyzDataSeries3D(wasmContext, {
58 xValues: dataFromServer.ascData.XValues,
59 yValues: dataFromServer.ascData.YValues,
60 zValues: dataFromServer.ascData.ZValues,
61 metadata: dataFromServer.meta,
62 }),
63 opacity: 1,
64 })
65 );
66
67 // Also render the point-cloud data as a heightmap / topology map with contours
68 sciChart3DSurface.renderableSeries.add(
69 new SurfaceMeshRenderableSeries3D(wasmContext, {
70 dataSeries: new UniformGridDataSeries3D(wasmContext, {
71 xStart: 0,
72 xStep: dataFromServer.ascData.CellSize,
73 zStart: 0,
74 zStep: dataFromServer.ascData.CellSize,
75 yValues: dataFromServer.heightValues2D,
76 }),
77 minimum: 0,
78 maximum: 50,
79 drawSkirt: true,
80 opacity: 0.7,
81 meshColorPalette: new GradientColorPalette(wasmContext, {
82 gradientStops: [
83 { offset: 1, color: appTheme.VividPink },
84 { offset: 0.9, color: appTheme.VividOrange },
85 { offset: 0.7, color: appTheme.MutedRed },
86 { offset: 0.5, color: appTheme.VividGreen },
87 { offset: 0.3, color: appTheme.VividSkyBlue },
88 { offset: 0.2, color: appTheme.Indigo },
89 { offset: 0, color: appTheme.DarkIndigo },
90 ],
91 }),
92 contourStroke: appTheme.PaleSkyBlue,
93 meshPaletteMode: EMeshPaletteMode.HEIGHT_MAP_INTERPOLATED,
94 contourStrokeThickness: 2,
95 drawMeshAs: EDrawMeshAs.SOLID_WITH_CONTOURS,
96 })
97 );
98
99 // Add interactivity modifiers for orbiting and zooming with the mousewheel
100 sciChart3DSurface.chartModifiers.add(new MouseWheelZoomModifier3D());
101 sciChart3DSurface.chartModifiers.add(new OrbitModifier3D());
102
103 return { sciChartSurface: sciChart3DSurface, wasmContext };
104};
105
106export const drawHeatmapLegend = async (rootElement: string | HTMLDivElement) => {
107 const { heatmapLegend, wasmContext } = await HeatmapLegend.create(rootElement, {
108 theme: {
109 ...appTheme.SciChartJsTheme,
110 sciChartBackground: appTheme.DarkIndigo + "BB",
111 loadingAnimationBackground: appTheme.DarkIndigo + "BB",
112 },
113 yAxisOptions: {
114 isInnerAxis: true,
115 labelStyle: {
116 fontSize: 12,
117 color: appTheme.ForegroundColor,
118 },
119 axisBorder: {
120 borderRight: 1,
121 color: appTheme.ForegroundColor + "77",
122 },
123 majorTickLineStyle: {
124 color: appTheme.ForegroundColor,
125 tickSize: 6,
126 strokeThickness: 1,
127 },
128 minorTickLineStyle: {
129 color: appTheme.ForegroundColor,
130 tickSize: 3,
131 strokeThickness: 1,
132 },
133 },
134 colorMap: {
135 minimum: 0,
136 maximum: 50,
137 gradientStops: [
138 { offset: 1, color: appTheme.VividPink },
139 { offset: 0.9, color: appTheme.VividOrange },
140 { offset: 0.7, color: appTheme.MutedRed },
141 { offset: 0.5, color: appTheme.VividGreen },
142 { offset: 0.3, color: appTheme.VividSkyBlue },
143 { offset: 0.2, color: appTheme.Indigo },
144 { offset: 0, color: appTheme.DarkIndigo },
145 ],
146 },
147 });
148
149 heatmapLegend.innerSciChartSurface.sciChartSurface.title = "Height (m)";
150
151 heatmapLegend.innerSciChartSurface.sciChartSurface.titleStyle = {
152 fontSize: 12,
153 color: appTheme.ForegroundColor,
154 position: ETitlePosition.Bottom,
155 };
156
157 return { sciChartSurface: heatmapLegend.innerSciChartSurface.sciChartSurface };
158};
159
160async function getDataFromServer() {
161 // The LinearColorMap type in SciChart allows you to generate a colour map based on a
162 // minimum and maximum value, e.g. min=0, max=50 means the gradient brush below is mapped into that range
163 //
164 const colorMap: TLinearColorMap = {
165 Minimum: 0,
166 Maximum: 50,
167 Mode: EColorMapMode.Interpolated,
168 GradientStops: [
169 { color: appTheme.DarkIndigo, offset: 0 },
170 { color: appTheme.Indigo, offset: 0.2 },
171 { color: appTheme.VividSkyBlue, offset: 0.3 },
172 { color: appTheme.VividGreen, offset: 0.5 },
173 { color: appTheme.MutedRed, offset: 0.7 },
174 { color: appTheme.VividOrange, offset: 0.9 },
175 { color: appTheme.VividPink, offset: 0 },
176 ],
177 };
178
179 // Read the ASC Lidar data file with optional color map data
180 const reader: AscReader = new AscReader((height) => {
181 // Linearly interpolate each heightValue into a colour and return to the ASCReader
182 // This will be injected into the SciChart XyzDataSeries3D to colour points in the point-cloud
183 return linearColorMapLerp(colorMap, height);
184 });
185
186 // See our source-code file tq3080_DSM_2M.js for format on this ASC Point cloud data
187 // find the source online at github: https://github.com/ABTSoftware/SciChart.JS.Examples/blob/master/Examples/src/server/Data/t
188 const rawData = await fetchLidarData();
189 const ascData: AscData = reader.parse(await rawData.text());
190
191 // Prepare metadata to contain the color values from ASCData
192 const meta: TMetadata[] = ascData.ColorValues.map((c) => ({
193 vertexColor: c,
194 pointScale: 0,
195 }));
196
197 // Prepare heightValues2D for the uniform surface mesh (transform point cloud to 2d array of heights)
198 const heightValues2D = zeroArray2D([ascData.NumberRows, ascData.NumberColumns]);
199 for (let index = 0, z = 0; z < ascData.NumberRows; z++) {
200 for (let x = 0; x < ascData.NumberColumns; x++) {
201 heightValues2D[z][x] = ascData.YValues[index++];
202 }
203 }
204
205 return {
206 ascData,
207 meta,
208 heightValues2D,
209 };
210}
211This example demonstrates a comprehensive 3D visualization of LiDAR UAV data using Angular and SciChart.js. The demo visualizes a 1km x 1km section of geospatial data as both a 3D point cloud and a contour map, enhanced by a dynamic heatmap legend that indicates elevation.
The implementation leverages Angular standalone components with the ScichartAngularComponent to integrate high-performance 3D charts into an Angular application. The chart initialization is performed asynchronously, setting up a custom 3D camera via the SciChart.js CameraController and configuring numeric axes to define the world dimensions. The example fetches ASC formatted LiDAR data, parses it to extract coordinate and elevation information, and applies a dynamic gradient color mapping for height visualization as discussed in the Getting Started with SciChart JS documentation.
Advanced features include real-time interactive 3D controls utilizing modifiers such as OrbitModifier3D and MouseWheelZoomModifier3D to enable smooth navigation around the point cloud. Furthermore, a detailed heatmap legend is rendered, which maps the elevation data to a vibrant color gradient, showcasing techniques from the Heatmap ColorMaps and Legends guide. The integration of WebAssembly via the SciChart.js backend ensures that even complex datasets render smoothly and efficiently, as highlighted in the SciChart.js for Web overview.
This demo follows best practices for Angular integration by utilizing standalone components as detailed in the Angular Standalone Components guide. Multiple ScichartAngularComponents are rendered on a single page to separate the main 3D chart from the heatmap legend, demonstrating effective techniques for managing complex chart layouts. The asynchronous data fetching and initialization ensure that charts update in real-time, and performance optimizations are achieved through efficient WebAssembly integration. Developers seeking further insights into component rendering and performance optimizations can refer to discussions on multiple component rendering and Angular Performance Optimization.

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.

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

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

See the frequency of recordings with the Angular audio spectrum analyzer example from SciChart. This real-time audio visualizer demo uses a Fourier Transform.

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

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

See the Angular Phasor Diagram example to combine a Cartesian surface with a Polar subsurface. Get seamless Angular integration with SciChart. View demo now.

Create Angular Correlation Plot with high performance SciChart.js. Easily render pre-defined point types. Supports custom shapes. Get your free trial now.
Angular **Semiconductors Dashboard** using SciChart.js, by leveraging the **FastRectangleRenderableSeries**, and its `customTextureOptions` property to have a custom tiling texture fill.

Angular **Wafer Analysis Chart** using SciChart.js, by leveraging the **FastRectangleRenderableSeries**, and crossfilter to enable live filtering.