Skip to content

Commit 8539a17

Browse files
committed
Re #2127: make crosshair linked views rotations around the focus of the crosshair
1 parent 1296258 commit 8539a17

File tree

2 files changed

+58
-8
lines changed

2 files changed

+58
-8
lines changed

src/VTKViewport/vtkInteractorStyleRotatableMPRCrosshairs.js

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Constants from 'vtk.js/Sources/Rendering/Core/InteractorStyle/Constants';
44
import vtkCoordinate from 'vtk.js/Sources/Rendering/Core/Coordinate';
55
import vtkMatrixBuilder from 'vtk.js/Sources/Common/Core/MatrixBuilder';
66
import { vec2, vec3, quat } from 'gl-matrix';
7+
import vtkMath from 'vtk.js/Sources/Common/Core/Math';
78

89
const { States } = Constants;
910

@@ -250,23 +251,69 @@ function vtkInteractorStyleRotatableMPRCrosshairs(publicAPI, model) {
250251
const sliceNormal = thisApi.getSliceNormal();
251252
const axis = [-sliceNormal[0], -sliceNormal[1], -sliceNormal[2]];
252253

253-
const { matrix } = vtkMatrixBuilder.buildFromRadian().rotate(angle, axis);
254-
255254
// Rotate other apis
256255
apis.forEach((api, index) => {
257256
if (index !== apiIndex) {
258-
// get normal and viewUp.
257+
const cameraForApi = api.genericRenderWindow
258+
.getRenderWindow()
259+
.getInteractor()
260+
.getCurrentRenderer()
261+
.getActiveCamera();
262+
263+
const crosshairPointForApi = api.get('cachedCrosshairWorldPosition');
264+
const initialCrosshairPointForApi = api.get(
265+
'initialCachedCrosshairWorldPosition'
266+
);
267+
268+
const center = [];
269+
vtkMath.subtract(
270+
crosshairPointForApi,
271+
initialCrosshairPointForApi,
272+
center
273+
);
274+
const translate = [];
275+
vtkMath.add(crosshairPointForApi, center, translate);
276+
277+
const { matrix } = vtkMatrixBuilder
278+
.buildFromRadian()
279+
.translate(translate[0], translate[1], translate[2])
280+
.rotate(angle, axis)
281+
.translate(-translate[0], -translate[1], -translate[2]);
282+
283+
cameraForApi.applyTransform(matrix);
259284

260285
const sliceNormalForApi = api.getSliceNormal();
261286
const viewUpForApi = api.getViewUp();
287+
api.setOrientation(sliceNormalForApi, viewUpForApi);
288+
289+
/* After rotating the focal point line of sight coordinate is not on the crosshair.
290+
Find nearest point of the crosshair to the line of sight of the camera*/
291+
292+
/*p1 = cameraPositionForApi
293+
p2 = cameraFocalPointForApi
294+
q = crosshairPointForApi*/
295+
296+
/*Vector3 u = p2 - p1;
297+
Vector3 pq = q - p1;
298+
Vector3 w2 = pq - vtkMath.multiplyScalar(u, vtkMath.dot(pq, u) / u2);
299+
300+
Vector3 point = q - w2;*/
262301

263-
const newSliceNormalForApi = [];
264-
const newViewUpForApi = [];
302+
const cameraFocalPointForApi = cameraForApi.getFocalPoint();
303+
const cameraPositionForApi = cameraForApi.getPosition();
265304

266-
vec3.transformMat4(newSliceNormalForApi, sliceNormalForApi, matrix);
267-
vec3.transformMat4(newViewUpForApi, viewUpForApi, matrix);
305+
const u = [];
306+
vtkMath.subtract(cameraFocalPointForApi, cameraPositionForApi, u);
307+
const pq = [];
308+
vtkMath.subtract(crosshairPointForApi, cameraPositionForApi, pq);
309+
const uLength2 = u[0] * u[0] + u[1] * u[1] + u[2] * u[2];
310+
vtkMath.multiplyScalar(u, vtkMath.dot(pq, u) / uLength2);
311+
const w2 = [];
312+
vtkMath.subtract(pq, u, w2);
313+
const point = [];
314+
vtkMath.subtract(crosshairPointForApi, w2, point);
268315

269-
api.setOrientation(newSliceNormalForApi, newViewUpForApi);
316+
cameraForApi.setFocalPoint(point[0], point[1], point[2]);
270317
}
271318
});
272319

src/VTKViewport/vtkSVGRotatableCrosshairsWidget.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,9 @@ function vtkSVGRotatableCrosshairsWidget(publicAPI, model) {
429429
// Set camera focal point to world coordinate for linked views
430430
apis.forEach((api, apiIndex) => {
431431
api.set('cachedCrosshairWorldPosition', worldPos);
432+
if (api.get('initialCachedCrosshairWorldPosition') === undefined) {
433+
api.set('initialCachedCrosshairWorldPosition', worldPos);
434+
}
432435

433436
// We are basically doing the same as getSlice but with the world coordinate
434437
// that we want to jump to instead of the camera focal point.

0 commit comments

Comments
 (0)