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
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";
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
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
Demonstrating the capability of SciChart.js to create a JavaScript Audio Analyzer 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.