Connect vtkResliceCursorWidget with basic js slider

Hello there! I am using vtk.js with react.js and my goal is to connect the vtkResliceCursorWidget with basic html-js slider: <input type="range" />. In my mind I should have two functions - one for widget event and another one for slider event. For X axis slice my widget event looks like this:

widgetInstanceX.onInteractionEvent(() => {
  const modified = widget.updateReslicePlane(resliceX, xyzToViewType[0])
  if (modified) {
    const widgetResliceAxes = widget.getResliceAxes(xyzToViewType[0])
    setXSlice(Array.from(widgetResliceAxes)[12])
    resliceActorX.setUserMatrix(widgetResliceAxes)
  }
  widget.updateCameraPoints(rendererX, xyzToViewType[0])
  renderWindow.render()
})

For the same axis my slider event looks like this:

  useEffect(() => {
    if (context.current) {
      const {
        resliceX,
        resliceActorX,
        renderWindowX,
        renderWindow,
        widget,
        rendererX,
      } = context.current

      const widgetResliceAxes = widget.getResliceAxes(xyzToViewType[0])

      const widgetResliceAxesArray = Array.from(widgetResliceAxes)

      widgetResliceAxesArray[12] = XSlice

      resliceX.setResliceAxes(new Float64Array(widgetResliceAxesArray))
      resliceActorX.setUserMatrix(new Float64Array(widgetResliceAxesArray))

      widget.updateCameraPoints(rendererX, xyzToViewType[0])

      renderWindowX.render()
      renderWindow.render()
    }
  }, [XSlice])

Also some background information:

const [XSlice, setXSlice] = useState(0)
const widget = vtkResliceCursorWidget.newInstance()
const widgetManagerX = vtkWidgetManager.newInstance()
const widgetInstanceX = widgetManagerX.addWidget(widget, xyzToViewType[0])
const resliceX = vtkImageReslice.newInstance()
const resliceActorX = vtkImageSlice.newInstance()

<input
   type="range"
   name="X"
   min={axisBounds.X.min}
   max={axisBounds.X.max}
   step={spacings.X}
   value={XSlice}
   onChange={(e) => setXSlice(Number(e.target.value))}
/>

All this stuff works well except that when I’m changing the position of the slice using the widget and then switch to the slider, everything works as it should, but if firstly I will change the position of the slice using the slider and then will change it using the widget, the slice will not change from its actual position, since initially it will return to the position that the widget remembered and from that point changes will occur depending on the scroll movements.

It is obvious to me that this happens due to the fact that in the code for the slider there is no setter function for the slice position directly in the widget, since I couldn’t find it, but only managed to find the getter function widget.getResliceAxes(xyzToViewType[0]).

The logic is that I have an XSlice variable, the value of which should be relevant for both the slider and the widget slice position.

The question is whether there is any function or ability to set the XSlice variable to the widget while slider changes, so that the XSlice value will be relevant for both the slider and the widget. And if this is not possible, then is it worth using some other widget or disabling the existing widget event and performing scroll slicing using the interactor event?

You need to change the plane origin within the widget state. Something like widget.getState().getPlanes()[1].setOrigin(...) to change the y plane.
Hth

Thank you for your reply! I assume you meant widget.getPlaneSourceFromViewType(xyzToViewType[0]).getOrigin()
and
widget.getPlaneSourceFromViewType(xyzToViewType[0]).setOrigin(origin)

“get” function actually does its job. For example, if I add into my previous slider event:

console.log(widget.getPlaneSourceFromViewType(xyzToViewType[0]).getOrigin())

this will indeed return the actual slice positions for each of the axes:

[*current X axis which changes depending on the movement of the slider*, 127.5, 93]

however, if I try the next thing for X axis slider (the default value is [127.5, 127.5, 93]) :

// I move the slider, changing its value - now slider value is 148.5, widget value is 127.5
const origin = widget.getPlaneSourceFromViewType(xyzToViewType[0]).getOrigin() // get widget states
origin[0] = XSlice // set the X axis slice value manually to 148.5
console.log(origin) // [148.5, 127.5, 93] - done
console.log(origin[0]) // 148.5 - done
widget.getPlaneSourceFromViewType(xyzToViewType[0]).setOrigin(origin) // manually set the new values into the widget
console.log(widget.getPlaneSourceFromViewType(xyzToViewType[0]).setOrigin(origin)) // true – means it's done
console.log(widget.getPlaneSourceFromViewType(xyzToViewType[0]).getOrigin()) // [127.5, 127.5, 93] – the widget value has not changed :|

What can be wrong?

I created a PR to illustrate what I meant: feat(reslicecursor): expose a convenient getPlaneExtremities function by finetjul · Pull Request #2980 · Kitware/vtk-js · GitHub

1 Like

Thanks a lot for the provided code and function in particular! This indeed works great in my case.