Center coordinates of volume slices?

How do I get the center coordinates for a volume that is shifted to the left and zoomed in a bit during maniplations?

Example: from

to

I am interested in the screen coordinates. Thanks.

I think you may need to use this method to get the XYToRASMatrix and invert it, then transform the sliceCenterRAS with it

I’m not 100% sure it will work, hope it helps

1 Like

Thanks, Mauro, I think this got me on the right track.

There is a function in vtkSlicerMarkupsWidgetRepresentation2D which I could use with a world coordinate of 0.,0.,0. to be at the center of the CT volume and receive it’s display coordinate.

1 Like

I think you would need the sliceCenterRAS, that normally is not (0,0,0). You can get it by averaging the bounds on each axis of the corresponding CT volume

Hope it helps

Sorry, that has not solved it for me yet.

Managed to call GetXYToRAS() and to do the invert. Could anyone explain where the above metioned “sliceCenterRAS” is and how it is used?
Or how I could read the centers from the vtkMatrix4x4 matrix?

I would need to get CT volume centers as xy display coordinates for each axial, coronal and saggital 2D view.

Thanks.

Yes. Sorry, that’s the correct name for the variable volumeCenterRAS, not sliceCenterRAS.

And you can get it like this:

bounds=[0,0,0,0,0,0]
volume = getNode('myCT')
volume.GetRASBounds(bounds)
volumeCenterRAS = [(bounds[1]+bounds[0])/2,(bounds[3]+bounds[2])/2,(bounds[5]+bounds[4])/2,1]

I think this should work as RASToXY is a projection matrix:
RASToXY.MultiplyPoint(volumeCenterRAS, sliceCenterXY)

Please let me know how it goes

Thx Mauro, can only try that out next week. I´ll be doing this in C++ and need to see how to get to the volume node reliably in that module I am working on.

Think I got it working (C++) by

//----------------------------------------------------------------------
void GetBackgroundVolumeXYCenter(double slicePos[2])
{
    vtkMRMLSliceCompositeNode* compositeNode = nullptr;
    compositeNode = vtkMRMLSliceCompositeNode::SafeDownCast(this->GetSliceNode()->GetScene()->GetFirstNodeByClass("vtkMRMLSliceCompositeNode"));
    const char* backgroundVolumeID = compositeNode->GetBackgroundVolumeID();

    double volumeBounds[6] = { 0.0 };
    double volumeCenterRAS[4] = { 0.0 };
    double centerPosDisplay[4] = { 0.0 };

    if (backgroundVolumeID)
    {
        vtkMRMLScalarVolumeNode* sliceBackgroundVolumeNode = vtkMRMLScalarVolumeNode::SafeDownCast(this->GetSliceNode()->
            GetScene()->GetNodeByID(backgroundVolumeID));
        if (sliceBackgroundVolumeNode)
        {
            sliceBackgroundVolumeNode->GetRASBounds(volumeBounds);
            // xmin,ymax,ymin,ymax,zmin,zmax
            volumeCenterRAS[0] = (volumeBounds[1] + volumeBounds[0]) / 2.;
            volumeCenterRAS[1] = (volumeBounds[3] + volumeBounds[2]) / 2.;
            volumeCenterRAS[2] = (volumeBounds[5] + volumeBounds[4]) / 2.;
            volumeCenterRAS[3] = 1.;
            this->GetWorldToSliceCoordinates(volumeCenterRAS, centerPosDisplay);
        }
    }
    slicePos[0] = centerPosDisplay[0];
    slicePos[1] = centerPosDisplay[1];
}

This assumes you have a function this->GetSliceNode() and this->GetWorldToSliceCoordinates() in your code, as in vtkSlicerMarkupsWidgetRepresentation2D

1 Like