Is there a tool to select faces by clicking on them / with a lasso?
Do methods exist do grow this selection?
Are there methods to select faces based on angles between faces? E.g. to detect edges?
@mau_igna_06 I saw you implemented a “select by points” tool in the Dynamic modeler - once I select the faces I would want to export them similarly to a new surface. Have you done any work with face selection beyond the distance based selection in that tool?
The application is to try to select regions based on changes in curvature and then export the selected faces as a new surface mesh.
I think there is a property of the vtkFastMarchingGeodesicDistance that allows you to grow a seed using a defined cellsScalarArray. I remember that the paper that presented this geodesic distance filter showed using curvature (calculated from the curvature filters on vtk examples) to “weight” the growing “speed” as you want
You can use the Curve cut tool in Dynamic Modeler module with constraint the curve to the surface and preferring going through high‐curvature points:
You can combine this with cutting planes and other curves to partition complex surfaces.
It would not be hard to adapt “Grow from seeds” algorithm to surface meshes. It would allow painting a surface by placing one or few markup points on each region. A student with C++ and VTK experience could implement it in a couple of months (could be a nice Masters project).
Curve cut and Select by points dynamic modeler tools cover the “draw” and “paint” style selections quite well. They are both parametric editing tools, allowing fine-tuning and corrections anytime, which is generally considered to be superior to direct editing (that is shown in the Materialise video above). Usability of the current dynamic modeler tools is not optimal, because we did not develop the Dynamic Modeler module for end users, but to have a parametric editor “engine” for a future “Model Editor” module. The “Model Editor” will work similarly to the “Segment Editor” module, but will opearate on models instead of segmentations.
@lassoan I’ll try the curve cut method you proposed, looks good!
@mau_igna_06 yes I was also thinking of the Blender functionality.
The node selection approach I was thinking of was this tool in Artisynth, in which you can select regions based on the angles between faces (right now only nodes can be selected, not faces): Help - Eclipse Platform
Looking forward to a Model Editor in the future.
If at some point I have a suitable master’s student I will also consider this as a project.
I have also seen people have good luck accessing the point normals from the polydata as a numpy array and then assigning selection scalars based on simple clustering of the normals. This works when the models are fairly smooth and the edges are fairly distinct.
Thanks Steve! By clustering do you mean checking the change in normals over n faces, instead of just calculating the normals difference between two adjanet faces?
I was thinking of that approach as well…
The humerus is a bit tricky since the edges are not super sharp. I am trying to isolate the articular surface.
Here is using Andras’s approach, unfortunately that doesn’t work well:
That is why I think face selection and growing is nice, with some constraint based on normals - so I can avoid it going past the first concave area and spreading into the convex area.
The place where I saw clustering the normals working well was in isolating the top and bottom plates of a vertebral body, where there was a clear distinction between the normals pointing up or down vs the ones on the side. I agree the femural head isn’t as cleanly defined. Which edges are you trying to define?
Here is an algorithm I think may work: Place a fiducial, take the nearest cell of the model to that seed, save the normal of that cell, calculate the normal of all other cells, compare the angle between the normals using the threshold criteria you want, save results on a cellArray, use that for vtkThreshold filter
There are examples online (those instructions may not be thoroughgoing)
Thanks Steve!
I just saw someone present this (I think using slicer) at CMBBE - I think it was Prof. Andersen.
I am trying to do something like this (I selected it manually but am exploring options to automate). Currently trying to decide whether to go down Slicer or Blender or Artisynth route.
I am not sure how well it will work on the humerus, might need additional constraints such as distance from seed etc so it does not grow too much.
As you can see the boundary curvature changes are quite subtle
Did you run uniform remesh on this model? It seems vertices are quite sparse, and if you want to have smooth curve at the diaphysis you might have to work with a higher resolution mesh (at least those high curvature areas).
I did but not high enough. Just tried it again and the results are much much better, thanks so much for the tip.
Still a bit overshooting the articular surface but will get a student working on refining this. Thanks all for your help!
Looking at the images above, it seems to me that the boundary of the articular surface is not marked everywhere by sudden change in the surface normal direction (see green arrows). No matter how you smooth the normals or constrain region growing, you would not get the actual articular surface in these areas.
Instead, you could determine what part of the mesh is the articular surface by rotating the mesh around a bit around an axis and keep that mesh regions that is close to the original (non-rotated) surface. The center of rotation on the surface (marked with an X in the image) and the axis orientation can be easilty set approximately. You only need 4 parameters (shift of the center of rotation on the surface in two directions; tilting of the rotation axis in two directions) to get the true, optimal center of rotation axis position from the initial guess, which is a simple optimization problem (small number of unknowns, smooth objective function, fast computation of the maximized value). It should be very easy to write a small Python function that computes the size of the articular surface for the current axis position and angle (by rotating the surface a bit, computing distance using polydata distance filter, applying threshold filter, getting largest connected component) and use it in scipy.optimize. The axis position and orientation could be very useful for computing many other metrics for the joint.
One goal of isolating the articular surface is to then fit a sphere to estimate the center of rotation of the humeral head.
I didn’t think of first estimating a rotational axis roughly through the center and using that to get the articular surface- it is a nice idea. I will explore it.
Yes, there is no sudden change in normals at this region, rather a slight change in concavity, but I would need to test if this is consistent enough to detect and use.
I suggested to compute overlap of the surface with itself after slight rotation because I did not want to assume a spherical surface. But if you can assume that the articular surface is a sphere then the task is even simpler. You still have just 4 unknowns (sphere center position in 3D, radius), and if you implement a Python function that computes the goodness of the fit (e.g., number of mesh points that are closer to the sphere surface than a small threshold), then scipy.optimize should be able to compute those unknowns.
Thanks @lassoan! The articular region is almost spherical - I saw a study showing it is slightly elliptical but I think it depends on the patient. This idea is really nice as well - going by number of points close to a sphere surface (instead of minimizing mean error to surface which would presumably place the sphere more in the center of the proximal bone including the trochanters).
@lassoan Just an update - thanks again for your suggestions. I have a student starting in October on this project, we will keep you updated on how well the different methods work