Top of the mesh

Hi all,
In 3d slicer, I have a point (x,y,z) -a fiducial- into a brain 3D model (mesh). Without changing the x and y coordinates, I would like to create a new point where the z coordinate will be at the top of the mesh. Do you know how could I do that (perhaps by the different voxel value between the inside/outside of the mesh)?

Thanks in advance,
Frederic

It’s relatively easy to do with some python scripting. Something like this

m=getNode('Segment_1')
mp=m.GetPolyData()
top=-10.0**11
for i in xrange(0, mp.GetNumberOfPoints()):
  p=mp.GetPoint(i)
  if p[2] > top:
    top = p[2]
f=getNode('F')
fp=[0]*4
f.GetNthFiducialWorldCoordinates(0,fp)
fp[2] = top
f.SetNthFiducialWorldCoordinates(0,fp)

Please note that this is very simplistic (does not account for transforms on the model or the fiducial), and the code snippet is very sloppy (not dynamic, bad variable names etc), but it can be a good starting point.

To get the “top” point, you can also use GetBounds() method of the vtkPolyData instead of iterating through all the points (which may take long time for large meshes).

1 Like

Actually it’s a good point, not sure why I didn’t consider that. Use bounds for sure

b=[0]*3
mp.GetBounds(b)

Thanks @cpinter and @lassoan.
Thus, the script will be:

mod = model.GetModelDisplayNode()
mod_out=mod.GetOutputPolyData()
b=[0]*6 #(xmin,xmax, ymin,ymax, zmin,zmax)
mod_out.GetBounds(b)

No need to go through the dispay node, it contains display properties so should not be involved.

m=getNode('Segment_1')
mp=m.GetPolyData()
b=[0]*6 #(xmin,xmax, ymin,ymax, zmin,zmax)
mp.GetBounds(b)
f=getNode('F')
fp=[0]*4
f.GetNthFiducialWorldCoordinates(0,fp)
fp[2] = c[5]
f.SetNthFiducialWorldCoordinates(0,fp)

Thanks for your suggestion.
However, I don’t arrive to acces to the getNode of my model:

filename = "/directory/human-head.stl"
[success, model]= slicer.util.loadModel(filename, returnNode=True)
m=getNode(filename)
mp=m.GetPolyData()

AttributeError: ‘NoneType’ object has no attribute ‘GetPolyData’

Do you know why?

If you load the model from file using this script, then you already have the model node in the variable called “model”, so you don’t need to find it in the scene.

Note that the name of the model will not be the full path. If you drag&drop the model and want to know its name, Go to Data module and see the name of your model. Enter the model name instead of “filename”.

A gerenal advice is that in the python interactor you can type commands one by one. After each command it’s prudent to see if the variable contains what you expect or not. The error you got happens because the value of variable “m” will be None.

1 Like

Thanks a lot for your advice, the correct script is then:

b=[0]*6 #(xmin,xmax, ymin,ymax, zmin,zmax)
model.GetPolyData().GetBounds(b)
f=getNode(‘F’)
fp=[0]*4
f.GetNthFiducialWorldCoordinates(0,fp)
fp[2] = b[5]
f.SetNthFiducialWorldCoordinates(0,fp)

Again, you run unnecessary circles, because “m” will be the same as “model”. Just use “model”

1 Like

Ok sorry. Thanks @cpinter