This week we plan to start a considerable effort to revamp the Surface Toolbox. The main idea is to port most of MeshMath’s functionality into it. We have created a lab’s page that details how we plan this effort to go.
If anybody has ideas or suggestions, please let us know!
@benwilson is making good progress and should have a pull request shortly
To move forward, considering we will be adding around ~20 CLIs, I was thinking to develop the SurfaceToolBox (and associated modules) in its own repository Slicer/Slicer-SurfaceToolBox that we would integrate in Slicer as a remote module like it is already done for SimpleFilters, LandmarkRegistration, …
What do you think ?
This would allow …
to easily enable/disable building of the surface toolbox within Slicer or Slicer custom application
to easily integrate the modules in any system compliant with the SlicerExecutionModel interface
To illustrate here is a repository I just created:
LICENSE, README.md and top-level CMakeLists.txt added
History filtered to have all modules at the root of the repo and to fix the the git message trailers so that both Co-authored-by and git-svn-id are recognized
I was considering expanding the Connectivity option of the surface toolbox such, that not only the largest region is extracted, but to base the extraction on a volumetric threshold (I remember seeing a comment in the Python source code of the module in 4.10.2 regarding this). So I tried (in Python) to prototype something like this, without great success. Below is my prototype code.
input = slicer.mrmlScene.GetFirstNodeByName('Model')
surface = input.GetPolyDataConnection()
# get all regions
conn = vtk.vtkPolyDataConnectivityFilter()
conn.ScalarConnectivityOn()
conn.SetScalarRange(-1, 1)
conn.SetExtractionModeToAllRegions()
conn.SetInputConnection(surface)
conn.Update()
nrRegions = conn.GetNumberOfExtractedRegions()
sizes = conn.GetRegionSizes()
# now switch to extraction mode to process one after the other
conn.SetExtractionModeToSpecifiedRegions()
fhf = vtk.vtkFillHolesFilter()
fhf.SetHoleSize(1000.0)
fhf.SetInputConnection(conn.GetOutputPort())
normals = vtk.vtkPolyDataNormals()
normals.ConsistencyOn();
normals.SplittingOff();
normals.SetInputConnection(fhf.GetOutputPort())
mass = vtk.vtkMassProperties()
mass.SetInputConnection(normals.GetOutputPort())
volumetricThreshold = 4000
volumes = []
# measure all cells
for id in range(0, nrRegions):
if sizes.GetValue(id) > 5: # preselect, currently hardcoded
conn.InitializeSpecifiedRegionList()
conn.AddSpecifiedRegion(id)
mass.Update()
print(mass.GetVolume())
volumes.append(mass.GetVolume())
else:
volumes.append(0)
fhf.RemoveAllInputConnections(0)
# extract only those regions above the volumetricThreshold
conn.InitializeSpecifiedRegionList()
for id in range(0, nrRegions):
if volumes[id] > volumetricThreshold:
print(id)
conn.AddSpecifiedRegion(id)
surface = conn.GetOutputPort()
input.SetPolyDataConnection(surface)
conn.Update()
Can someone tell me whether this goes into the right direction? In principle, it seems to do what it should (I believe, I have not rigorously tested it), but it is extremely slow (takes about 2 minutes for a CT-head). Is there a significant difference between Python implementation and C++? If we could get something like this running, it would be suited for expanding this module.
BTW: I did not see any difference in extraction when I manipulated the ScalarRange or turned FullScalarConnectivityOn().