@@ -30,11 +30,6 @@ import { errorLog } from "../utilities/loggingScript.js";
3030
3131const 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- */
3833export 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- */
5242export 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- */
6851export 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- */
8864export 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- */
11179export 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- */
148108export 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- */
158113export 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
302251function 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
322263function 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
344279function 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
358290function 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
369299function 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
386311function 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
441364function 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
469379function 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
480388function 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
499400function 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