|
| 1 | +import test from 'tape-catch'; |
| 2 | +import testUtils from 'vtk.js/Sources/Testing/testUtils'; |
| 3 | + |
| 4 | +import vtkCalculator from 'vtk.js/Sources/Filters/General/Calculator'; |
| 5 | +import vtkOpenGLRenderWindow from 'vtk.js/Sources/Rendering/OpenGL/RenderWindow'; |
| 6 | +import vtkRenderWindow from 'vtk.js/Sources/Rendering/Core/RenderWindow'; |
| 7 | +import vtkRenderer from 'vtk.js/Sources/Rendering/Core/Renderer'; |
| 8 | +import vtkPlaneSource from 'vtk.js/Sources/Filters/Sources/PlaneSource'; |
| 9 | +import vtkConeSource from 'vtk.js/Sources/Filters/Sources/ConeSource'; |
| 10 | +import vtkGlyph3DMapper from 'vtk.js/Sources/Rendering/Core/Glyph3DMapper'; |
| 11 | +import vtkActor from 'vtk.js/Sources/Rendering/Core/Actor'; |
| 12 | + |
| 13 | +import { AttributeTypes } from 'vtk.js/Sources/Common/DataModel/DataSetAttributes/Constants'; |
| 14 | +import { FieldDataTypes } from 'vtk.js/Sources/Common/DataModel/DataSet/Constants'; |
| 15 | + |
| 16 | +import baseline from './testGlyph3DMapper.png'; |
| 17 | + |
| 18 | +test.onlyIfWebGL('Test vtkGlyph3DMapper Rendering', (t) => { |
| 19 | + const gc = testUtils.createGarbageCollector(t); |
| 20 | + t.ok('rendering', 'vtkGlyph3DMapper Rendering'); |
| 21 | + |
| 22 | + // Create some control UI |
| 23 | + const container = document.querySelector('body'); |
| 24 | + const renderWindowContainer = gc.registerDOMElement(document.createElement('div')); |
| 25 | + container.appendChild(renderWindowContainer); |
| 26 | + |
| 27 | + // create what we will view |
| 28 | + const renderWindow = gc.registerResource(vtkRenderWindow.newInstance()); |
| 29 | + const renderer = gc.registerResource(vtkRenderer.newInstance()); |
| 30 | + renderWindow.addRenderer(renderer); |
| 31 | + renderer.setBackground(0.32, 0.34, 0.43); |
| 32 | + |
| 33 | + const planeSource = vtkPlaneSource.newInstance(); |
| 34 | + const simpleFilter = vtkCalculator.newInstance(); |
| 35 | + const mapper = vtkGlyph3DMapper.newInstance(); |
| 36 | + const actor = vtkActor.newInstance(); |
| 37 | + |
| 38 | + simpleFilter.setFormula({ |
| 39 | + getArrays: inputDataSets => ({ |
| 40 | + input: [ |
| 41 | + { location: FieldDataTypes.COORDINATE }], // Require point coordinates as input |
| 42 | + output: [ // Generate two output arrays: |
| 43 | + { |
| 44 | + location: FieldDataTypes.POINT, // This array will be point-data ... |
| 45 | + name: 'pressure', // ... with the given name ... |
| 46 | + dataType: 'Float32Array', // ... of this type ... |
| 47 | + numberOfComponents: 3, // ... with this many components ... |
| 48 | + }, |
| 49 | + { |
| 50 | + location: FieldDataTypes.POINT, // This array will be field data ... |
| 51 | + name: 'temperature', // ... with the given name ... |
| 52 | + dataType: 'Float32Array', // ... of this type ... |
| 53 | + attribute: AttributeTypes.SCALARS, // ... and will be marked as the default scalars. |
| 54 | + numberOfComponents: 1, // ... with this many components ... |
| 55 | + }, |
| 56 | + ] }), |
| 57 | + evaluate: (arraysIn, arraysOut) => { |
| 58 | + // Convert in the input arrays of vtkDataArrays into variables |
| 59 | + // referencing the underlying JavaScript typed-data arrays: |
| 60 | + const [coords] = arraysIn.map(d => d.getData()); |
| 61 | + const [press, temp] = arraysOut.map(d => d.getData()); |
| 62 | + |
| 63 | + // Since we are passed coords as a 3-component array, |
| 64 | + // loop over all the points and compute the point-data output: |
| 65 | + for (let i = 0, sz = coords.length / 3; i < sz; ++i) { |
| 66 | + press[i * 3] = ((coords[3 * i] - 0.5) * (coords[3 * i] - 0.5)); |
| 67 | + press[(i * 3) + 1] = (((coords[(3 * i) + 1] - 0.5) * (coords[(3 * i) + 1] - 0.5)) + 0.125) * 0.1; |
| 68 | + press[(i * 3) + 2] = (((coords[3 * i] - 0.5) * (coords[3 * i] - 0.5)) + ((coords[(3 * i) + 1] - 0.5) * (coords[(3 * i) + 1] - 0.5)) + 0.125) * 0.1; |
| 69 | + temp[i] = coords[(3 * i) + 1] * 0.1; |
| 70 | + } |
| 71 | + // Mark the output vtkDataArray as modified |
| 72 | + arraysOut.forEach(x => x.modified()); |
| 73 | + }, |
| 74 | + }); |
| 75 | + |
| 76 | + // The generated 'temperature' array will become the default scalars, so the plane mapper will color by 'temperature': |
| 77 | + simpleFilter.setInputConnection(planeSource.getOutputPort()); |
| 78 | + |
| 79 | + mapper.setInputConnection(simpleFilter.getOutputPort(), 0); |
| 80 | + |
| 81 | + const coneSource = vtkConeSource.newInstance(); |
| 82 | + coneSource.setResolution(12); |
| 83 | + mapper.setInputConnection(coneSource.getOutputPort(), 1); |
| 84 | + mapper.setOrientationArray('pressure'); |
| 85 | + mapper.setScalarRange(0.0, 0.1); |
| 86 | + |
| 87 | + actor.setMapper(mapper); |
| 88 | + renderer.addActor(actor); |
| 89 | + renderer.resetCamera(); |
| 90 | + renderer.getActiveCamera().zoom(1.3); |
| 91 | + |
| 92 | + // now create something to view it, in this case webgl |
| 93 | + const glwindow = gc.registerResource(vtkOpenGLRenderWindow.newInstance()); |
| 94 | + glwindow.setContainer(renderWindowContainer); |
| 95 | + renderWindow.addView(glwindow); |
| 96 | + glwindow.setSize(400, 400); |
| 97 | + |
| 98 | + renderWindow.render(); |
| 99 | + |
| 100 | + const image = glwindow.captureImage(); |
| 101 | + testUtils.compareImages(image, [baseline], 'Rendering/Core/Glyph3DMapper/testGlyph3DMapper', t, 1.0, gc.releaseResources); |
| 102 | +}); |
0 commit comments