|
1 | 1 | import macro from 'vtk.js/Sources/macros';
|
2 | 2 | import * as vtkMath from 'vtk.js/Sources/Common/Core/Math';
|
3 | 3 | import vtkMatrixBuilder from 'vtk.js/Sources/Common/Core/MatrixBuilder';
|
| 4 | +import vtkBoundingBox from 'vtk.js/Sources/Common/DataModel/BoundingBox'; |
4 | 5 | import vtkInteractorStyleManipulator from 'vtk.js/Sources/Interaction/Style/InteractorStyleManipulator';
|
5 | 6 | import vtkMouseCameraTrackballRotateManipulator from 'vtk.js/Sources/Interaction/Manipulators/MouseCameraTrackballRotateManipulator';
|
6 | 7 | import vtkMouseCameraTrackballPanManipulator from 'vtk.js/Sources/Interaction/Manipulators/MouseCameraTrackballPanManipulator';
|
7 | 8 | import vtkMouseCameraTrackballZoomManipulator from 'vtk.js/Sources/Interaction/Manipulators/MouseCameraTrackballZoomManipulator';
|
8 | 9 | import vtkMouseRangeManipulator from 'vtk.js/Sources/Interaction/Manipulators/MouseRangeManipulator';
|
9 | 10 |
|
| 11 | +import { mat4 } from 'gl-matrix'; |
10 | 12 | // ----------------------------------------------------------------------------
|
11 | 13 | // Global methods
|
12 | 14 | // ----------------------------------------------------------------------------
|
13 | 15 |
|
14 |
| -function boundsToCorners(bounds) { |
15 |
| - return [ |
16 |
| - [bounds[0], bounds[2], bounds[4]], |
17 |
| - [bounds[0], bounds[2], bounds[5]], |
18 |
| - [bounds[0], bounds[3], bounds[4]], |
19 |
| - [bounds[0], bounds[3], bounds[5]], |
20 |
| - [bounds[1], bounds[2], bounds[4]], |
21 |
| - [bounds[1], bounds[2], bounds[5]], |
22 |
| - [bounds[1], bounds[3], bounds[4]], |
23 |
| - [bounds[1], bounds[3], bounds[5]], |
24 |
| - ]; |
25 |
| -} |
26 |
| - |
27 | 16 | // ----------------------------------------------------------------------------
|
28 | 17 |
|
29 | 18 | function clamp(value, min, max) {
|
@@ -153,14 +142,9 @@ function vtkInteractorStyleMPRSlice(publicAPI, model) {
|
153 | 142 |
|
154 | 143 | if (model.volumeMapper) {
|
155 | 144 | const range = publicAPI.getSliceRange();
|
156 |
| - const bounds = model.volumeMapper.getBounds(); |
157 | 145 |
|
158 | 146 | const clampedSlice = clamp(slice, ...range);
|
159 |
| - const center = [ |
160 |
| - (bounds[0] + bounds[1]) / 2.0, |
161 |
| - (bounds[2] + bounds[3]) / 2.0, |
162 |
| - (bounds[4] + bounds[5]) / 2.0, |
163 |
| - ]; |
| 147 | + const center = model.volumeMapper.getCenter(); |
164 | 148 |
|
165 | 149 | const distance = camera.getDistance();
|
166 | 150 | const dop = camera.getDirectionOfProjection();
|
@@ -193,37 +177,33 @@ function vtkInteractorStyleMPRSlice(publicAPI, model) {
|
193 | 177 | if (model.volumeMapper) {
|
194 | 178 | const sliceNormal = publicAPI.getSliceNormal();
|
195 | 179 |
|
196 |
| - if ( |
197 |
| - sliceNormal[0] === cache.sliceNormal[0] && |
198 |
| - sliceNormal[1] === cache.sliceNormal[1] && |
199 |
| - sliceNormal[2] === cache.sliceNormal[2] |
200 |
| - ) { |
| 180 | + if (vtkMath.areEquals(sliceNormal, cache.sliceNormal)) { |
201 | 181 | return cache.sliceRange;
|
202 | 182 | }
|
203 | 183 |
|
204 |
| - const bounds = model.volumeMapper.getBounds(); |
205 |
| - const points = boundsToCorners(bounds); |
206 |
| - |
207 | 184 | // Get rotation matrix from normal to +X (since bounds is aligned to XYZ)
|
208 |
| - const transform = vtkMatrixBuilder |
| 185 | + const sliceOrientation = vtkMatrixBuilder |
209 | 186 | .buildFromDegree()
|
210 | 187 | .identity()
|
211 | 188 | .rotateFromDirections(sliceNormal, [1, 0, 0]);
|
| 189 | + const imageAlongSliceNormal = mat4.create(); |
| 190 | + mat4.multiply( |
| 191 | + imageAlongSliceNormal, |
| 192 | + sliceOrientation.getMatrix(), |
| 193 | + model.volumeMapper.getInputData().getIndexToWorld() |
| 194 | + ); |
212 | 195 |
|
213 |
| - points.forEach((pt) => transform.apply(pt)); |
| 196 | + // Transform the 8 corners of the input data's bounding box |
| 197 | + // to rotate into the slice plane space without the intermediate |
| 198 | + // axis-aligned box (provided by getBounds) which would grow the bounds. |
| 199 | + const transformedBounds = vtkBoundingBox.transformBounds( |
| 200 | + model.volumeMapper.getInputData().getSpatialExtent(), |
| 201 | + imageAlongSliceNormal |
| 202 | + ); |
214 | 203 |
|
215 | 204 | // range is now maximum X distance
|
216 |
| - let minX = Infinity; |
217 |
| - let maxX = -Infinity; |
218 |
| - for (let i = 0; i < 8; i++) { |
219 |
| - const x = points[i][0]; |
220 |
| - if (x > maxX) { |
221 |
| - maxX = x; |
222 |
| - } |
223 |
| - if (x < minX) { |
224 |
| - minX = x; |
225 |
| - } |
226 |
| - } |
| 205 | + const minX = transformedBounds[0]; |
| 206 | + const maxX = transformedBounds[1]; |
227 | 207 |
|
228 | 208 | cache.sliceNormal = sliceNormal;
|
229 | 209 | cache.sliceRange = [minX, maxX];
|
|
0 commit comments