# Surface toolbox revamp

**URL:** <https://discourse.slicer.org/t/surface-toolbox-revamp/7113>\
**Category:** Development\
**Created:** [June 10, 2019, 3:06pm UTC](https://discourse.slicer.org/t/surface-toolbox-revamp/7113 "2019-06-10T15:06:59Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![bpaniagua](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/bpaniagua/32/20_2.png) [@bpaniagua](https://discourse.slicer.org/u/bpaniagua)\
**Post date:** [June 10, 2019, 3:06pm UTC](https://discourse.slicer.org/t/surface-toolbox-revamp/7113/1 "2019-06-10T15:06:59Z")

</div>

Hi Slicer developers,  
cc: @pieper @lassoan @jcfr @styner

This week we plan to start a considerable effort to revamp [the Surface Toolbox](https://github.com/Slicer/Slicer/blob/d308a019361738d2cf4f827cddab5b4896a63f23/Modules/Scripted/SurfaceToolbox/SurfaceToolbox.py). The main idea is to port most of [MeshMath’s functionality](https://github.com/NIRALUser/SPHARM-PDM/blob/master/Modules/CLI/MetaMeshTools/MeshMath.cxx) into it. We have created a [lab’s page](https://www.slicer.org/wiki/Documentation/Labs/Surface_Toolbox_update) that details how we plan this effort to go.

If anybody has ideas or suggestions, please let us know!

Bea

---

<div class="post-metadata">

**Author:** ![jcfr](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/jcfr/32/17825_2.png) [@jcfr](https://discourse.slicer.org/u/jcfr)\
**Post date:** [July 10, 2019, 4:06pm UTC](https://discourse.slicer.org/t/surface-toolbox-revamp/7113/2 "2019-07-10T16:06:36Z")

</div>

@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:

> **[Slicer/Slicer-SurfaceToolBox](https://github.com/Slicer/Slicer-SurfaceToolBox)**
>
> Contribute to Slicer/Slicer-SurfaceToolBox development by creating an account on GitHub.

It was generated by extracting history using [jcfr/dockgit-rocket-filter](https://github.com/jcfr/dockgit-rocket-filter#readme):

```nohighlight
# Filter history
git clone git://github.com/Slicer/Slicer -b master Slicer-SurfaceToolBox
cd Slicer-SurfaceToolBox
git-rocket-filter --branch surfacetoolbox --keep Modules/Scripted/SurfaceToolbox

# publish extracted branch
git remote add SurfaceToolBox git@github.com:Slicer/Slicer-SurfaceToolBox.gi
git push SurfaceToolBox refs/heads/surfacetoolbox:master

```

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [July 10, 2019, 6:56pm UTC](https://discourse.slicer.org/t/surface-toolbox-revamp/7113/3 "2019-07-10T18:56:56Z")

</div>

Sounds like a good idea to me - thanks @jcfr 👍

---

<div class="post-metadata">

**Author:** ![jcfr](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/jcfr/32/17825_2.png) [@jcfr](https://discourse.slicer.org/u/jcfr)\
**Post date:** [July 10, 2019, 10:46pm UTC](https://discourse.slicer.org/t/surface-toolbox-revamp/7113/4 "2019-07-10T22:46:40Z")

</div>

Thanks for the feedback.

- Repository name changed to `SlicerSurfaceToolbox`
- `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

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [July 19, 2019, 3:53am UTC](https://discourse.slicer.org/t/surface-toolbox-revamp/7113/5 "2019-07-19T03:53:31Z")

</div>

A post was split to a new topic: [Convert mesh to engineering CAD software solid part](https://discourse.slicer.org/t/convert-mesh-to-engineering-cad-software-solid-part/7679)

---

<div class="post-metadata">

**Author:** ![jcfr](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/jcfr/32/17825_2.png) [@jcfr](https://discourse.slicer.org/u/jcfr)\
**Post date:** [August 12, 2019, 2:59pm UTC](https://discourse.slicer.org/t/surface-toolbox-revamp/7113/6 "2019-08-12T14:59:05Z")

</div>

Start with [r28434](http://viewvc.slicer.org/viewvc.cgi/Slicer4?view=revision&revision=28434), SurfaceToolbox is now integrated as a remote module whose sources are downloaded from [https://github.com/Slicer/SlicerSurfaceToolbox](https://github.com/Slicer/SlicerSurfaceToolbox)

---

<div class="post-metadata">

**Author:** ![rprueckl](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/rprueckl/32/4240_2.png) [@rprueckl](https://discourse.slicer.org/u/rprueckl)\
**Post date:** [September 13, 2019, 7:06am UTC](https://discourse.slicer.org/t/surface-toolbox-revamp/7113/7 "2019-09-13T07:06:32Z")

</div>

Hi!

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.

```auto
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](https://github.com/Slicer/SlicerSurfaceToolbox/blob/master/Connectivity/Connectivity.cxx) module.

BTW: I did not see any difference in extraction when I manipulated the ScalarRange or turned FullScalarConnectivityOn().

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [September 13, 2019, 3:22pm UTC](https://discourse.slicer.org/t/surface-toolbox-revamp/7113/8 "2019-09-13T15:22:24Z")

</div>

For segmentation problems like this, we normally use the Segment Editor:

1. Use Threshold effect to specify intensity range you are interested in.
2. Use Islands effect / Keep largest island method to keep the largest connected component.

You can continue with further processing or export directly to STL/OBJ file right from the Segment Editor.
