Plane Fitting and Local to Global Transform Calculation

Hello,

I am trying to fit a plane to the glenoid to define a new local coordinate system, to calculate the transform between that coordinate system and a previous one.

The glenoid’s previous coordinate system is currently aligned with the global coordinate system, so as far as I understand I can use this code from @lassoan for the transform calculation.

However, I am running into issues defining my new coordinate system.
My goal is to create a plane fit to the eigenvectors of the glenoid surface mesh, and then simply translate the origin of the coordinate system to 0,0,0 (so that I am only checking rotation differences from the original coordinate system).

I found this very useful code by @mau_igna_06 from this related topic.
It is exactly what I am looking for.

However, when I test it, the plane x and y are not aligned with the surface object y and y:

Looking at this section of the code

modelZ = np.zeros(3)
modelX = eigenvectors0[0]
modelY = eigenvectors0[1]
vtk.vtkMath.Cross(modelX, modelY, modelZ)
modelZ = modelZ/np.linalg.norm(modelZ)
modelOrigin = modelPointsMean

I would expect the X and Y axes to be like this (my end goal):

image

In fact, it seems like the code is somehow fitting to the orginal scapula model - I made the glenoid with the curve cut tool. Could the vertices of the rest of the scapula somehow still be references by the plane fitting code?

I also tested the script Fit Markups Plane to Model and the plane is similarly misaligned (this code explicitly defines center and normal direction, so I wanted to use it as a test - and do not understand why the normal is not aligned to the global Z axis):

Additional question:
Is there a way to visualize the global CS as axes centered at 0,0,0 instead of in the bottom right of the screen?

Thank you!
Eva

I would expect the script to work for the purpose you intend. Could you public the exact code you are running and the model node of the glenoid (ie .vtk file) you are using?

Thanks Mauro for the quick reply!

Very strangely, when I tried to replicate the problem, I now get a correct result.
I re-did the surface cut - I will see if it comes up again in future tests.

I do have a question about your code.

At the end of the code, why do you define and calculate initialModeltoWorldMatrix? Should this not be the same as planeToWorldMatrix?
Since you define worldToInitialModel as the inverse of planeToWorldMatrix, and initialModeltoWorldMatrix as the inverse of worldToInitialModel?

Also, why is the worldToInitialModel applied as a transform to the model?
Isn’t the initial model’s “frame” just whatever the global coordinates are?
Indeed, when I take away the transform, the model is in the same spot.
Is this just a check?

I would also like to propose an adjustment to your script, which is flipping the Z axis to be aligned with the normals of the surface we are fitting the plane to.

So for example here:

I did this and tested it, let me know if I should make a pull request to your script?

E.g. by calculating average normal of the surface and if the difference between that and the normal of the plane is greater than 90 degrees, flip the plane normal (rotate by 180 degrees) about X.
Of course this also reorients the Y axis.

I did this and tested it, let me know what you think and if I should make a pull request to your script?

Also, for anyone else reading this post, I figured out how to visualize the global axes.
This can just be done making a new plane and setting the axes and origin to global XYZ and 0,0,0 - just didn’t think of this before.

Thanks again!
Eva

Hi Eva,

That code may not be the final version of the script, I think there maybe a newer gist on my library, please check.

But the description says: “Create a frame for the model in the principal components directions, set up a plane with interaction handles to move it.” I think that’s related to the matrix definition you asked about

HiH
Mauro

Thanks Mauro.

Ah I see, that explains why there are the duplicate matrices, since one is before and one after manual manipulation,

I did not find another script in the repository. Let me know if you want to add my Z axis adjustment.

Thank you,
Eva

I meant this one:

HIH

Thank you!
For now I was just using the code to assign new frames, get the transform between them, and use those in a different program, but I will also test your Slicer model transform tool in the future.

Best,
Eva