Skip to content

Commit c22805f

Browse files
committed
feat(View): autoCenterOfRotation
1 parent 71e4cea commit c22805f

File tree

2 files changed

+43
-19
lines changed

2 files changed

+43
-19
lines changed

src/core-ts/View.tsx

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
import vtkInteractorStyle from '@kitware/vtk.js/Interaction/Style/InteractorStyle';
12
import { ICameraInitialValues } from '@kitware/vtk.js/Rendering/Core/Camera';
2-
import { Nullable, Vector3 } from '@kitware/vtk.js/types';
3+
import { Bounds, Nullable, Vector3 } from '@kitware/vtk.js/types';
34
import {
45
CSSProperties,
56
forwardRef,
67
PropsWithChildren,
8+
useCallback,
79
useEffect,
810
useImperativeHandle,
911
useMemo,
@@ -84,18 +86,11 @@ interface Props extends PropsWithChildren {
8486
autoResetCamera?: boolean;
8587

8688
/**
87-
* Property use to trigger a render when changing.
88-
89-
* TODO remove because the recommended way is to use a ref
90-
*/
91-
// triggerRender?: number;
92-
93-
/**
94-
* Property use to trigger a resetCamera when changing.
89+
* Whether to automatically re-set the interactor style's center of rotation. (default: true)
9590
*
96-
* TODO remove because the recommended way is to use a ref
91+
* This is a convenience property for interactor styles that support setCenterOfRotation().
9792
*/
98-
// triggerResetCamera?: number;
93+
autoCenterOfRotation?: boolean;
9994

10095
/**
10196
* List of picking listeners to bind. By default it is disabled (empty array).
@@ -152,6 +147,7 @@ interface Props extends PropsWithChildren {
152147
const DefaultProps = {
153148
interactive: true,
154149
autoResetCamera: true,
150+
autoCenterOfRotation: true,
155151
background: [0.2, 0.3, 0.4] as Vector3,
156152
style: {
157153
width: '100%',
@@ -202,6 +198,7 @@ export default forwardRef(function View(props: Props, fwdRef) {
202198
background = DefaultProps.background,
203199
interactive = DefaultProps.interactive,
204200
autoResetCamera = DefaultProps.autoResetCamera,
201+
autoCenterOfRotation = DefaultProps.autoCenterOfRotation,
205202
interactorSettings = DefaultProps.interactorSettings,
206203
camera: cameraProps,
207204
} = props;
@@ -223,31 +220,53 @@ export default forwardRef(function View(props: Props, fwdRef) {
223220
useInteractorStyle(getInteractor);
224221
useInteractorStyleManipulatorSettings(getInteractorStyle, interactorSettings);
225222

226-
// handle renders
223+
// --- rendering state --- //
224+
227225
const [renderRequested, setRenderRequested] = useState(false);
228226
const requestRender = () => setRenderRequested(true);
229227

228+
// --- camera --- //
229+
230+
const getCamera = useCamera(getRenderer, requestRender, cameraProps);
231+
232+
const resetCamera = useCallback(
233+
(boundsToUse?: Bounds) => {
234+
getRenderer().resetCamera(boundsToUse);
235+
if (
236+
autoCenterOfRotation &&
237+
'setCenterOfRotation' in getInteractorStyle()
238+
) {
239+
const style = getInteractorStyle() as vtkInteractorStyle & {
240+
setCenterOfRotation(center: Vector3): boolean;
241+
};
242+
style.setCenterOfRotation(getCamera().getFocalPoint());
243+
}
244+
},
245+
[autoCenterOfRotation, getRenderer, getInteractorStyle, getCamera]
246+
);
247+
248+
// --- handle renders --- //
249+
230250
useEffect(() => {
231251
if (renderRequested) {
232252
if (autoResetCamera) {
233-
getRenderer().resetCamera();
253+
resetCamera();
234254
}
235255
getRenderWindow().render();
236256
setRenderRequested(false);
237257
}
238-
}, [renderRequested, autoResetCamera, getRenderer, getRenderWindow]);
258+
}, [renderRequested, autoResetCamera, resetCamera, getRenderWindow]);
239259

240-
// camera
241-
const getCamera = useCamera(getRenderer, requestRender, cameraProps);
260+
// --- view API --- //
242261

243-
// view API
244262
const view = useMemo<IView>(() => {
245263
return {
246264
getRenderer,
247265
getRenderWindow,
248266
getInteractor,
249267
getAPISpecificRenderWindow: getRWView,
250268
getCamera,
269+
getInteractorStyle,
251270
setInteractorStyle,
252271
/**
253272
* Requests a vtk.js render.
@@ -259,8 +278,8 @@ export default forwardRef(function View(props: Props, fwdRef) {
259278
/**
260279
* Resets the camera.
261280
*/
262-
resetCamera: () => {
263-
getRenderer().resetCamera();
281+
resetCamera: (boundsToUse?: Bounds) => {
282+
resetCamera(boundsToUse);
264283
requestRender();
265284
},
266285
};
@@ -270,7 +289,9 @@ export default forwardRef(function View(props: Props, fwdRef) {
270289
getRenderWindow,
271290
getInteractor,
272291
getCamera,
292+
getInteractorStyle,
273293
setInteractorStyle,
294+
resetCamera,
274295
]);
275296

276297
// expose the view as a ref for imperative control

src/types/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import vtkInteractorStyle from '@kitware/vtk.js/Interaction/Style/InteractorStyle';
12
import { vtkObject } from '@kitware/vtk.js/interfaces';
23
import vtkCamera from '@kitware/vtk.js/Rendering/Core/Camera';
34
import vtkRenderer from '@kitware/vtk.js/Rendering/Core/Renderer';
@@ -39,6 +40,8 @@ export interface IView {
3940
getRenderWindow(): vtkRenderWindow;
4041
getAPISpecificRenderWindow(): vtkOpenGLRenderWindow;
4142
getInteractor(): vtkRenderWindowInteractor;
43+
getInteractorStyle(): vtkInteractorStyle;
44+
setInteractorStyle(style: vtkInteractorStyle): void;
4245
getCamera(): vtkCamera;
4346
requestRender(): void;
4447
resetCamera(boundsToUse?: Bounds): void;

0 commit comments

Comments
 (0)