vtk.js

vtk.js


绘制矢量图

<h3>1. <strong>创建渲染器</strong></h3> <pre><code>const renderer = vtkRenderer.newInstance(); // 将渲染器的背景色设置为透明 renderer.setBackground(0, 0, 0, 0); // RGBA 中的 A 通道设置为 0 表示完全透明</code></pre> <ul> <li><strong><code>vtkRenderer.newInstance()</code></strong>:创建一个新的渲染器实例。</li> <li><strong><code>renderer.setBackground(0, 0, 0, 0)</code></strong>:设置渲染器的背景色为透明。<code>RGBA</code> 中的 <code>A</code> 通道设置为 <code>0</code> 表示完全透明。</li> </ul> <h3>2. <strong>创建点数据</strong></h3> <pre><code>const points = vtkPoints.newInstance(); const { location, vecArr } = data; points.setData(new Float32Array(location));</code></pre> <ul> <li><strong><code>vtkPoints.newInstance()</code></strong>:创建一个新的点集合实例。</li> <li><strong><code>points.setData(new Float32Array(location))</code></strong>:将点坐标数据(<code>location</code>)转化为 <code>Float32Array</code> 并设置到点集合中。</li> </ul> <h3>3. <strong>创建立方体源</strong></h3> <pre><code>const cubeSource = vtkCubeSource.newInstance( { xLength: xLength, // 立方体在 X 轴上的长度 yLength: yLength, // 立方体在 Y 轴上的长度 zLength: zLength // 立方体在 Z 轴上的长度 });</code></pre> <ul> <li><strong><code>vtkCubeSource.newInstance({...})</code></strong>:创建一个立方体数据源,立方体的尺寸由 <code>xLength</code>、<code>yLength</code> 和 <code>zLength</code> 指定。</li> </ul> <h3>4. <strong>设置立方体的透明度</strong></h3> <pre><code>const actorHidden = vtkActor.newInstance(); const mapperHidden = vtkMapper.newInstance(); mapperHidden.setInputConnection(cubeSource.getOutputPort()); const propertyHidden = actorHidden.getProperty(); propertyHidden.setOpacity(0); // 设置透明度为 0 actorHidden.setMapper(mapperHidden); actorHidden.setPosition(gridBounds[0] + xLength / 2, gridBounds[2] + yLength / 2, gridBounds[4] + zLength / 2);</code></pre> <ul> <li><strong><code>vtkActor.newInstance()</code></strong>:创建一个新的演员(<code>actor</code>)实例。</li> <li><strong><code>vtkMapper.newInstance()</code></strong>:创建一个新的映射器(<code>mapper</code>)实例。</li> <li><strong><code>mapperHidden.setInputConnection(cubeSource.getOutputPort())</code></strong>:将立方体源的输出连接到映射器。</li> <li><strong><code>propertyHidden.setOpacity(0)</code></strong>:将演员的透明度设置为 <code>0</code>,使其不可见。</li> <li><strong><code>actorHidden.setMapper(mapperHidden)</code></strong>:将映射器设置到演员。</li> <li><strong><code>actorHidden.setPosition(...)</code></strong>:将演员的位置设置到立方体中心。</li> </ul> <h3>5. <strong>设置向量数据</strong></h3> <pre><code>const vectors = vtkDataArray.newInstance({ numberOfComponents: 3, // 数据中的组件数量(例如,对于3D点,这将是x, y, z) values: new Float32Array(transVerPoints(data.vector, vecArr, data, modeView, config, data.median)), type: 'Float32' // 指定数据类型 });</code></pre> <ul> <li><strong><code>vtkDataArray.newInstance({...})</code></strong>:创建一个新的数据数组实例,用于存储向量数据。</li> <li><strong><code>numberOfComponents: 3</code></strong>:每个向量有三个组件 (x, y, z)。</li> <li><strong><code>values: new Float32Array(...)</code></strong>:将向量数据转化为 <code>Float32Array</code> 并设置到数据数组中。</li> </ul> <h3>6. <strong>设置缩放数据</strong></h3> <pre><code>const scales = vtkDataArray.newInstance({ numberOfComponents: 1, // size name: 'scales', type: 'float32', // 指定数据类型 values: new Float32Array(transVerScale(data.length, data.arrow_length_factor, vecArr, config, data.median)) });</code></pre> <ul> <li><strong><code>numberOfComponents: 1</code></strong>:每个缩放因子只有一个组件(即缩放大小)。</li> <li><strong><code>values: new Float32Array(...)</code></strong>:将缩放因子转化为 <code>Float32Array</code> 并设置到数据数组中。</li> </ul> <h3>7. <strong>设置颜色数据</strong></h3> <pre><code>const colors = vtkDataArray.newInstance({ numberOfComponents: 4, // r, g, b, a name: 'colorMode', type: 'uint8', values: new Uint8Array(arrData) });</code></pre> <ul> <li><strong><code>numberOfComponents: 4</code></strong>:每个颜色值有四个组件(红、绿、蓝、透明度)。</li> <li><strong><code>values: new Uint8Array(arrData)</code></strong>:将颜色数据转化为 <code>Uint8Array</code> 并设置到数据数组中。</li> </ul> <h3>8. <strong>创建 PolyData 并设置属性</strong></h3> <pre><code>const polyData = vtkPolyData.newInstance(); polyData.setPoints(points); const pointerD = polyData.getPointData(); pointerD.setVectors(vectors); pointerD.addArray(scales); pointerD.setScalars(colors);</code></pre> <ul> <li><strong><code>vtkPolyData.newInstance()</code></strong>:创建一个新的 <code>PolyData</code> 实例,用于存储点数据、向量数据、缩放数据和颜色数据。</li> <li><strong><code>pointerD.setVectors(vectors)</code></strong>:将向量数据设置到 <code>PolyData</code> 中。</li> <li><strong><code>pointerD.addArray(scales)</code></strong>:将缩放数据添加到 <code>PolyData</code> 中。</li> <li><strong><code>pointerD.setScalars(colors)</code></strong>:将颜色数据设置到 <code>PolyData</code> 中。</li> </ul> <h3>9. <strong>创建箭头源</strong></h3> <pre><code>const arrowSource = vtkArrowSource.newInstance(); arrowSource.setTipResolution(modeView === '2D' ? 2 : 6); arrowSource.setTipRadius(0.05 * config.arrowSize / 10); arrowSource.setTipLength(0.1 * config.arrowSize / 10); arrowSource.setShaftRadius(0.005 * config.strokeWidth / 10); arrowSource.setShaftResolution(modeView === '2D' ? 12 : 12);</code></pre> <ul> <li><strong><code>vtkArrowSource.newInstance()</code></strong>:创建一个新的箭头源实例。</li> <li><strong><code>setTipResolution(...)</code></strong>:设置箭头的尖端分辨率。</li> <li><strong><code>setTipRadius(...)</code></strong>、<strong><code>setTipLength(...)</code></strong>、<strong><code>setShaftRadius(...)</code></strong>:设置箭头的各个部分的尺寸。</li> <li><strong><code>setShaftResolution(...)</code></strong>:设置箭头杆的分辨率。</li> </ul> <h3>10. <strong>应用矩阵变换</strong></h3> <pre><code>const vtkMatrixBuilder = window.vtk.Common.Core.vtkMatrixBuilder; const allLength = 0.05 * config.arrowSize / 10 + 0.1 * config.arrowSize / 10 + 0.005 * config.strokeWidth / 10; vtkMatrixBuilder.buildFromRadian().translate(0 + allLength, 0.0, 0.0).apply(appendPts);</code></pre> <ul> <li><strong><code>vtkMatrixBuilder.buildFromRadian()</code></strong>:创建一个矩阵构建器实例。</li> <li><strong><code>translate(...)</code></strong>:应用平移变换,将箭头中心移动到 [0 + allLength, 0.0, 0.0] 位置。</li> </ul> <h3>11. <strong>创建 <code>Glyph3DMapper</code> 并设置属性</strong></h3> <pre><code>const glyph3DMapper = vtkGlyph3DMapper.newInstance({ scaleArray: 'scales', colorByArrayName: 'colors' }); glyph3DMapper.setInputData(polyData); glyph3DMapper.setSourceConnection(arrowSource.getOutputPort());</code></pre> <ul> <li><strong><code>vtkGlyph3DMapper.newInstance({...})</code></strong>:创建一个新的 <code>Glyph3DMapper</code> 实例,并设置其属性。</li> <li><strong><code>setInputData(polyData)</code></strong>:将 <code>PolyData</code> 设置到映射器中。</li> <li><strong><code>setSourceConnection(arrowSource.getOutputPort())</code></strong>:将箭头源的输出连接到 <code>Glyph3DMapper</code>。</li> </ul> <h3>12. <strong>创建演员并添加到渲染器</strong></h3> <pre><code>const actor = vtkActor.newInstance(); actor.setMapper(glyph3DMapper); // 添加演员到渲染器并渲染 renderer.addActor(actor); renderer.setLayer(4);</code></pre> <ul> <li><strong><code>vtkActor.newInstance()</code></strong>:创建一个新的演员实例。</li> <li><strong><code>actor.setMapper(glyph3DMapper)</code></strong>:将 <code>Glyph3DMapper</code> 设置到演员中。</li> <li><strong><code>renderer.addActor(actor)</code></strong>:将演员添加到渲染器中。</li> <li><strong><code>renderer.setLayer(4)</code></strong>:设置渲染器的图层为 4。</li> </ul> <h3>总结</h3> <p>这段代码主要做了以下事情:</p> <ol> <li>创建了一个透明背景的渲染器。</li> <li>生成了点数据并计算了其边界。</li> <li>创建了一个立方体源和一个不可见的立方体演员用于视觉辅助。</li> <li>设置了矢量数据、缩放因子和颜色数据。</li> <li>创建了一个 <code>PolyData</code> 对象,并将点数据、向量、</li> </ol> <p>源码</p> <pre><code class="language-javascript">/** * 添加矢量图 * @param {*} data * @param {*} renderer */ async addvector(data, renderWindow, modeView, options = {}) { const renderer = vtkRenderer.newInstance(); // 将渲染器的背景色设置为透明 renderer.setBackground(0, 0, 0, 0); // RGBA 中的 A 通道设置为 0 表示完全透明 // 创建流场数据 点坐标 const points = vtkPoints.newInstance(); const { location, vecArr } = data; points.setData(new Float32Array(location)); const actorHidden = vtkActor.newInstance(); // 如果返回了图片的世界坐标系 let gridBounds = points.getBounds(); const xLength = gridBounds[1] - gridBounds[0]; const yLength = gridBounds[3] - gridBounds[2]; const zLength = gridBounds[5] - gridBounds[4]; // 创建一个 CubeSource 作为立方体的数据源 const cubeSource = vtkCubeSource.newInstance({ xLength: xLength, // 立方体在 X 轴上的长度 yLength: yLength, // 立方体在 Y 轴上的长度 zLength: zLength // 立方体在 Z 轴上的长度 }); // 创建一个 Mapper const mapperHidden = vtkMapper.newInstance(); mapperHidden.setInputConnection(cubeSource.getOutputPort()); // 创建一个属性对象并设置透明度 const propertyHidden = actorHidden.getProperty(); propertyHidden.setOpacity(0); // 设置透明度为 0 actorHidden.setMapper(mapperHidden); actorHidden.setPosition(gridBounds[0] + xLength / 2, gridBounds[2] + yLength / 2, gridBounds[4] + zLength / 2); console.debug('原始图片网格大小', gridBounds, actorHidden.getBounds()); // 这是向量数据结构 const vectors = vtkDataArray.newInstance({ numberOfComponents: 3, // 数据中的组件数量(例如,对于3D点,这将是x, y, z) values: new Float32Array(transVerPoints(data.vector, vecArr, data, modeView, config, data.median)), type: 'Float32' // 指定数据类型 }); // 缩放 const scales = vtkDataArray.newInstance({ numberOfComponents: 1, // size name: 'scales', type: 'float32', // 指定数据类型 values: new Float32Array(transVerScale(data.length, data.arrow_length_factor, vecArr, config, data.median)) }); const { arrData, min, max, colorMin, colorMax } = growColorArr(data, vecArr, config, true); // 颜色 const colors = vtkDataArray.newInstance({ numberOfComponents: 4, // r, g, b a name: 'colorMode', type: 'uint8', values: new Uint8Array(arrData) }); // 创建vtkPolyData const polyData = vtkPolyData.newInstance(); polyData.setPoints(points); const pointerD = polyData.getPointData(); pointerD.setVectors(vectors); pointerD.addArray(scales); // 颜色设置必须通过setScalars来设置 pointerD.setScalars(colors); // 创建箭头源 const arrowSource = vtkArrowSource.newInstance(); arrowSource.setTipResolution(modeView === '2D' ? 2 : 6); arrowSource.setTipRadius(0.05 * config.arrowSize / 10); arrowSource.setTipLength(0.1 * config.arrowSize / 10); arrowSource.setShaftRadius(0.005 * config.strokeWidth / 10); arrowSource.setShaftResolution(modeView === '2D' ? 12 : 12); const appendPD = arrowSource.getOutputData(); const appendPts = appendPD.getPoints().getData(); const vtkMatrixBuilder = window.vtk.Common.Core.vtkMatrixBuilder; // Center the arrow about [0, 0, 0] const allLength = 0.05 * config.arrowSize / 10 + 0.1 * config.arrowSize / 10 + 0.005 * config.strokeWidth / 10; vtkMatrixBuilder.buildFromRadian().translate(0 + allLength, 0.0, 0.0).apply(appendPts); // 创建 Glyph3DMapper const glyph3DMapper = vtkGlyph3DMapper.newInstance({ scaleArray: 'scales', colorByArrayName: 'colors' }); glyph3DMapper.setInputData(polyData); glyph3DMapper.setSourceConnection(arrowSource.getOutputPort()); const actor = vtkActor.newInstance(); actor.setMapper(glyph3DMapper); // 添加演员到渲染器并渲染 renderer.addActor(actor); renderer.setLayer(4);</code></pre>

页面列表

ITEM_HTML