Skip to content

Commit 2335be6

Browse files
committed
fix: converted into vtk js
1 parent 9161044 commit 2335be6

File tree

1 file changed

+33
-140
lines changed

1 file changed

+33
-140
lines changed

src/visualization/vtkSolutionScript.js

Lines changed: 33 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,6 @@ import { errorLog } from "../utilities/loggingScript.js";
3030

3131
const rendererCache = new Map();
3232

33-
/**
34-
* Create a configurable color scale definition for vtk rendering.
35-
* @param {object} [options] - Color scale options
36-
* @returns {object} Normalized color scale definition
37-
*/
3833
export function createColorScale(options = {}) {
3934
return {
4035
presetName: options.presetName ?? "Cool to Warm",
@@ -44,11 +39,6 @@ export function createColorScale(options = {}) {
4439
};
4540
}
4641

47-
/**
48-
* Create a configurable contour-lines definition.
49-
* @param {object} [options] - Contour options
50-
* @returns {object} Normalized contour line definition
51-
*/
5242
export function createContourLineOptions(options = {}) {
5343
return {
5444
enabled: options.enabled ?? true,
@@ -58,13 +48,6 @@ export function createContourLineOptions(options = {}) {
5848
};
5949
}
6050

61-
/**
62-
* Function to create plots of the solution vector using vtk.js.
63-
* @param {object} model - Object containing model properties
64-
* @param {object} result - Object containing solution vector and mesh information
65-
* @param {string} plotType - The type of plot
66-
* @param {string} plotDivId - The id of the div where the plot will be rendered
67-
*/
6851
export function plotSolution(model, result, plotType, plotDivId, renderOptions = {}) {
6952
console.time("plottingTime");
7053

@@ -78,13 +61,6 @@ export function plotSolution(model, result, plotType, plotDivId, renderOptions =
7861
console.timeEnd("plottingTime");
7962
}
8063

81-
/**
82-
* Function to generate a dense visualization grid and interpolate the FEM solution on it.
83-
* @param {object} model - Object containing model properties
84-
* @param {object} result - Object containing solution vector and mesh information
85-
* @param {string} plotType - The type of plot
86-
* @param {string} plotDivId - The id of the div where the plot will be rendered
87-
*/
8864
export function plotInterpolatedSolution(model, result, plotType, plotDivId, renderOptions = {}) {
8965
console.time("plottingTime");
9066

@@ -100,14 +76,6 @@ export function plotInterpolatedSolution(model, result, plotType, plotDivId, ren
10076
console.timeEnd("plottingTime");
10177
}
10278

103-
/**
104-
* Convert FEAScript standard solver output to vtk-friendly typed buffers.
105-
* @param {object} model - FE model configuration holder
106-
* @param {object} result - Solver result object with solutionVector and nodesCoordinates
107-
* @param {object} [meshData] - Optional prepared mesh data
108-
* @param {object} [options] - Conversion options
109-
* @returns {object} VTK friendly dataset and vtkPolyData instance
110-
*/
11179
export function transformSolverOutputToVtkData(model, result, meshData = null, options = {}) {
11280
const preparedMesh = meshData ?? prepareMesh(model.meshConfig);
11381
const { nodesXCoordinates, nodesYCoordinates } = result.nodesCoordinates;
@@ -137,24 +105,11 @@ export function transformSolverOutputToVtkData(model, result, meshData = null, o
137105
};
138106
}
139107

140-
/**
141-
* Convert FEAScript standard solver output to a VTP (XML PolyData) string.
142-
* @param {object} model - FE model configuration holder
143-
* @param {object} result - Solver result object
144-
* @param {object} [meshData] - Optional prepared mesh data
145-
* @param {object} [options] - Conversion options
146-
* @returns {string} VTP XML string
147-
*/
148108
export function transformSolverOutputToVTP(model, result, meshData = null, options = {}) {
149109
const vtkData = transformSolverOutputToVtkData(model, result, meshData, options);
150110
return buildVTPString(vtkData);
151111
}
152112

153-
/**
154-
* Build browser-friendly typed arrays for downstream on-device ML workflows.
155-
* @param {object} result - Solver result object
156-
* @returns {object} Typed arrays ready for ML preprocessing/inference
157-
*/
158113
export function transformSolverOutputToMLBuffers(result) {
159114
const { nodesXCoordinates, nodesYCoordinates } = result.nodesCoordinates;
160115
const scalars = extractScalarSolution(result.solutionVector, nodesXCoordinates.length);
@@ -188,8 +143,7 @@ function renderVtkScene(vtkData, plotDivId, solverConfig, plotType, renderOption
188143
}
189144

190145
if (rendererCache.has(plotDivId)) {
191-
const previous = rendererCache.get(plotDivId);
192-
previous.delete();
146+
rendererCache.get(plotDivId).delete();
193147
rendererCache.delete(plotDivId);
194148
}
195149

@@ -226,10 +180,7 @@ function renderVtkScene(vtkData, plotDivId, solverConfig, plotType, renderOption
226180

227181
const actor = vtkActor.newInstance();
228182
actor.setMapper(mapper);
229-
if (vtkData.mode === "line") {
230-
actor.getProperty().setLineWidth(3);
231-
}
232-
183+
if (vtkData.mode === "line") actor.getProperty().setLineWidth(3);
233184
renderer.addActor(actor);
234185

235186
if (colorScale.showScalarBar) {
@@ -246,9 +197,7 @@ function renderVtkScene(vtkData, plotDivId, solverConfig, plotType, renderOption
246197

247198
renderer.resetCamera();
248199
renderWindow.render();
249-
250200
rendererCache.set(plotDivId, genericRenderWindow);
251-
252201
container.title = `${plotType} plot - ${solverConfig}`;
253202
}
254203

@@ -300,97 +249,71 @@ function addContourLinesToRenderer(renderer, vtkData, scalarRange, contourOption
300249
}
301250

302251
function reverseColorMapPreset(preset, reverse) {
303-
if (!reverse || !preset || !Array.isArray(preset.RGBPoints) || preset.RGBPoints.length < 8) {
304-
return preset;
305-
}
306-
307-
const rgbPoints = preset.RGBPoints;
308-
const minX = rgbPoints[0];
309-
const maxX = rgbPoints[rgbPoints.length - 4];
252+
if (!reverse || !preset?.RGBPoints?.length) return preset;
253+
const rgb = preset.RGBPoints;
254+
const minX = rgb[0];
255+
const maxX = rgb[rgb.length - 4];
310256
const reversed = [];
311-
312-
for (let i = rgbPoints.length - 4; i >= 0; i -= 4) {
313-
reversed.push(maxX - (rgbPoints[i] - minX), rgbPoints[i + 1], rgbPoints[i + 2], rgbPoints[i + 3]);
257+
for (let i = rgb.length - 4; i >= 0; i -= 4) {
258+
reversed.push(maxX - (rgb[i] - minX), rgb[i + 1], rgb[i + 2], rgb[i + 3]);
314259
}
315-
316-
return {
317-
...preset,
318-
RGBPoints: reversed,
319-
};
260+
return { ...preset, RGBPoints: reversed };
320261
}
321262

322263
function buildPolyData(points, scalars, cells, mode = "surface") {
323264
const polyData = vtkPolyData.newInstance();
324265
polyData.getPoints().setData(points, 3);
325-
326266
if (cells.length > 0) {
327-
if (mode === "line") {
328-
polyData.getLines().setData(cells);
329-
} else {
330-
polyData.getPolys().setData(cells);
331-
}
267+
if (mode === "line") polyData.getLines().setData(cells);
268+
else polyData.getPolys().setData(cells);
332269
}
333-
334270
const scalarData = vtkDataArray.newInstance({
335271
name: "solution",
336272
numberOfComponents: 1,
337273
values: scalars,
338274
});
339275
polyData.getPointData().setScalars(scalarData);
340-
341276
return polyData;
342277
}
343278

344279
function buildPointsArray(nodesXCoordinates, nodesYCoordinates) {
345-
const totalNodes = nodesXCoordinates.length;
346-
const points = new Float32Array(totalNodes * 3);
347-
348-
for (let nodeIndex = 0; nodeIndex < totalNodes; nodeIndex++) {
349-
const base = nodeIndex * 3;
350-
points[base] = Number(nodesXCoordinates[nodeIndex]) || 0;
351-
points[base + 1] = Number(nodesYCoordinates?.[nodeIndex]) || 0;
280+
const points = new Float32Array(nodesXCoordinates.length * 3);
281+
for (let i = 0; i < nodesXCoordinates.length; i++) {
282+
const base = i * 3;
283+
points[base] = Number(nodesXCoordinates[i]) || 0;
284+
points[base + 1] = Number(nodesYCoordinates?.[i]) || 0;
352285
points[base + 2] = 0;
353286
}
354-
355287
return points;
356288
}
357289

358290
function extractScalarSolution(solutionVector, expectedLength) {
359291
const scalars = new Float32Array(expectedLength);
360-
361292
for (let i = 0; i < expectedLength; i++) {
362293
const value = solutionVector?.[i];
363294
scalars[i] = Number(Array.isArray(value) ? value[0] : value) || 0;
364295
}
365-
366296
return scalars;
367297
}
368298

369299
function buildLineCellsFromPoints(totalPoints) {
370-
if (totalPoints < 2) {
371-
return new Uint32Array(0);
372-
}
373-
300+
if (totalPoints < 2) return new Uint32Array(0);
374301
const packed = new Uint32Array((totalPoints - 1) * 3);
375302
let offset = 0;
376-
377303
for (let i = 0; i < totalPoints - 1; i++) {
378304
packed[offset++] = 2;
379305
packed[offset++] = i;
380306
packed[offset++] = i + 1;
381307
}
382-
383308
return packed;
384309
}
385310

386311
function buildCellArrayFromNop(nop) {
387312
const packed = [];
388-
389313
for (let i = 0; i < nop.length; i++) {
390314
const cell = convertElementNodesToLinearCell(nop[i]);
391315
packed.push(cell.length, ...cell);
392316
}
393-
394317
return Uint32Array.from(packed);
395318
}
396319

@@ -439,90 +362,60 @@ function convertElementNodesToLinearCell(elementNodes) {
439362
}
440363

441364
function getScalarRange(scalars) {
442-
if (!scalars || scalars.length === 0) {
443-
return [0, 1];
444-
}
445-
365+
if (!scalars?.length) return [0, 1];
446366
let minValue = Number.POSITIVE_INFINITY;
447367
let maxValue = Number.NEGATIVE_INFINITY;
448-
449368
for (let i = 0; i < scalars.length; i++) {
450369
const value = scalars[i];
451-
if (!Number.isFinite(value)) {
452-
continue;
453-
}
370+
if (!Number.isFinite(value)) continue;
454371
if (value < minValue) minValue = value;
455372
if (value > maxValue) maxValue = value;
456373
}
457-
458-
if (!Number.isFinite(minValue) || !Number.isFinite(maxValue)) {
459-
return [0, 1];
460-
}
461-
462-
if (minValue === maxValue) {
463-
return [minValue - 1, maxValue + 1];
464-
}
465-
374+
if (!Number.isFinite(minValue) || !Number.isFinite(maxValue)) return [0, 1];
375+
if (minValue === maxValue) return [minValue - 1, maxValue + 1];
466376
return [minValue, maxValue];
467377
}
468378

469379
function countPackedCells(packedCells) {
470-
let count = 0;
471-
let offset = 0;
380+
let count = 0, offset = 0;
472381
while (offset < packedCells.length) {
473-
const npts = packedCells[offset];
474-
offset += npts + 1;
382+
offset += packedCells[offset] + 1;
475383
count++;
476384
}
477385
return count;
478386
}
479387

480388
function packedCellsToConnectivityAndOffsets(packedCells) {
481-
const connectivity = [];
482-
const offsets = [];
483-
484-
let offset = 0;
485-
let running = 0;
486-
389+
const connectivity = [], offsets = [];
390+
let offset = 0, running = 0;
487391
while (offset < packedCells.length) {
488392
const npts = packedCells[offset++];
489-
for (let i = 0; i < npts; i++) {
490-
connectivity.push(packedCells[offset++]);
491-
}
393+
for (let i = 0; i < npts; i++) connectivity.push(packedCells[offset++]);
492394
running += npts;
493395
offsets.push(running);
494396
}
495-
496397
return { connectivity, offsets };
497398
}
498399

499400
function buildVTPString(vtkData) {
500401
const { connectivity, offsets } = packedCellsToConnectivityAndOffsets(vtkData.cells);
501402
const numberOfPoints = vtkData.points.length / 3;
502-
const numberOfPolys = vtkData.mode === "line" ? 0 : offsets.length;
503-
const numberOfLines = vtkData.mode === "line" ? offsets.length : 0;
504-
505-
const pointsText = Array.from(vtkData.points).join(" ");
506-
const scalarsText = Array.from(vtkData.scalars).join(" ");
507-
const connectivityText = connectivity.join(" ");
508-
const offsetsText = offsets.join(" ");
509-
510-
const topologyTag = vtkData.mode === "line" ? "Lines" : "Polys";
511-
403+
const isLine = vtkData.mode === "line";
404+
const topologyTag = isLine ? "Lines" : "Polys";
512405
return [
513406
'<?xml version="1.0"?>',
514407
'<VTKFile type="PolyData" version="0.1" byte_order="LittleEndian">',
515408
" <PolyData>",
516-
` <Piece NumberOfPoints="${numberOfPoints}" NumberOfVerts="0" NumberOfLines="${numberOfLines}" NumberOfStrips="0" NumberOfPolys="${numberOfPolys}">`,
409+
` <Piece NumberOfPoints="${numberOfPoints}" NumberOfVerts="0" NumberOfLines="${isLine ? offsets.length : 0}" NumberOfStrips="0" NumberOfPolys="${isLine ? 0 : offsets.length}">`,
517410
' <PointData Scalars="solution">',
518-
` <DataArray type="Float32" Name="solution" NumberOfComponents="1" format="ascii">${scalarsText}</DataArray>`,
411+
` <DataArray type="Float32" Name="solution" NumberOfComponents="1" format="ascii">${Array.from(vtkData.scalars).join(" ")}</DataArray>`,
519412
" </PointData>",
520413
" <Points>",
521-
` <DataArray type="Float32" NumberOfComponents="3" format="ascii">${pointsText}</DataArray>`,
414+
` <DataArray type="Float32" NumberOfComponents="3" format="ascii">${Array.from(vtkData.points).join(" ")}</DataArray>`,
522415
" </Points>",
523416
` <${topologyTag}>`,
524-
` <DataArray type="Int32" Name="connectivity" format="ascii">${connectivityText}</DataArray>`,
525-
` <DataArray type="Int32" Name="offsets" format="ascii">${offsetsText}</DataArray>`,
417+
` <DataArray type="Int32" Name="connectivity" format="ascii">${connectivity.join(" ")}</DataArray>`,
418+
` <DataArray type="Int32" Name="offsets" format="ascii">${offsets.join(" ")}</DataArray>`,
526419
` </${topologyTag}>`,
527420
" </Piece>",
528421
" </PolyData>",

0 commit comments

Comments
 (0)