# Model Undercuts Removal by Label Map Addition

**URL:** <https://discourse.slicer.org/t/model-undercuts-removal-by-label-map-addition/490>\
**Category:** Development\
**Created:** [June 13, 2017, 2:36am UTC](https://discourse.slicer.org/t/model-undercuts-removal-by-label-map-addition/490 "2017-06-13T02:36:10Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![patmo141](https://avatars.discourse-cdn.com/v4/letter/p/ee7513/32.png) [@patmo141](https://discourse.slicer.org/u/patmo141)\
**Post date:** [June 13, 2017, 2:36am UTC](https://discourse.slicer.org/t/model-undercuts-removal-by-label-map-addition/490/1 "2017-06-13T02:36:10Z")

</div>

Operating system: Win 10 64 Bit  
Slicer version: 4.7 Nightly

Background: Undercuts are important in dental CAD because for two rigidly mating objects (for example teeth and an appliance), a path of insertion is necessary or else the parts will bind. This is also useful in many other applications outside of dentistry

Goal: I would like to create a Module which takes as input a closed STL or other model surface, and outputs a closed surface which has all undercuts from a given direction removed.

Overall Plan: Create a label map from the model, and add layers above to all layers below it, ensuring that the model is always monotonically widening wrt to the desired insertion axis.  
-Import the model  
-Transform the model so that Z axis is aligned with desired insertion axis  
-Create volume based on desired slice thickness  
-Create label map from the model  
-Modify the label map by adding the layers “downward” across the volume  
-Recompute surface representation  
-Export

I’ll report back here as progress continues. Any tips appreciated!

---

<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:** [June 13, 2017, 3:44pm UTC](https://discourse.slicer.org/t/model-undercuts-removal-by-label-map-addition/490/2 "2017-06-13T15:44:00Z")

</div>

This sounds like a good approach. You may use Crop Volume module (even from your own module, programmatically) to create a reference volume with any size, axis directions (you can rotate the ROI by applying a transform to it), and any resolution.

You may use Segmentations module to convert between labelmap and closed surface representations: you can import your model, Segmentations can automatically create a labelmap representation; make it the master representation; process it; and at the end you can export the segment back to a model.

---

<div class="post-metadata">

**Author:** ![patmo141](https://avatars.discourse-cdn.com/v4/letter/p/ee7513/32.png) [@patmo141](https://discourse.slicer.org/u/patmo141)\
**Post date:** [June 19, 2017, 3:07am UTC](https://discourse.slicer.org/t/model-undercuts-removal-by-label-map-addition/490/3 "2017-06-19T03:07:00Z")

</div>

Progress Update 1 (Should I edit original post or keep adding replies?)

-A simple UI with a model select node, and a push button (More parameters to be added later)

On Push Button Code:

- The model bounding box is calculated
- Slice thickness, and number of slices are calculated
- A new volume is added to the MRML Scene
- A transform node is added that translates volume to fit the model

I verify this by going to the crop volume Module after I run my script and creating a new annotation ROI and fit ROI to volume.

> <https://gist.github.com/patmo141/1878acf70d45e4048699417a1238f053#file-modelundercutremoval-py>

---

<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:** [June 19, 2017, 5:03am UTC](https://discourse.slicer.org/t/model-undercuts-removal-by-label-map-addition/490/4 "2017-06-19T05:03:08Z")

</div>

Thanks for the update. Nice progress. A couple of suggestions:

- It seems that you use some very old template for your extension. Download the latest nightly build of Slicer (it works well and there are many bugfixes and improvements compared to the latest stable version) and use its Extension Wizard module to generate an up-to-date module template.
- Create a new project on github and keep updating that instead of sharing code in some temporary gists (make sure to include all the files that Extension Wizard generated - it will allow you to submit your module to the Slicer appstore when it’s ready)
- As a next step, I would recommend to have a look at Segmentations, as it allows seamless conversion between labelmaps and models. See [self-test of Segment Statistics module](https://github.com/Slicer/Slicer/blob/master/Modules/Scripted/SegmentStatistics/SegmentStatistics.py#L447-L459) for an example of how to create segments from models.
- You don’t need to create a linear transform to position your volume: a volume can be fully positioned, scaled, and rotated by [setting its IJK to RAS transform](http://apidocs.slicer.org/master/classvtkMRMLVolumeNode.html#a55550614d4cc322eed7bc9ed533dfed4). Once you have your volume, set it as reference geometry in your segmentation node (segmentationNode.SetReferenceImageGeometryParameterFromVolumeNode(…))
- To update your segment with undercut:
  - Change master representation to binary labelmap ([http://apidocs.slicer.org/master/classvtkMRMLSegmentationNode.html#a59f156080fdf87acd9d35f36056c928e](http://apidocs.slicer.org/master/classvtkMRMLSegmentationNode.html#a59f156080fdf87acd9d35f36056c928e))
  - [Get labelmap representation of a segment](https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#Get_a_representation_of_a_segment) by calling segmentationNode.GetBinaryLabelmapRepresentation(segmentID)
  - Modify the labelmap’s imagedata: go through slice by slice and combine them using numpy (see [how to access voxels as a numpy array here](https://github.com/Slicer/Slicer/blob/master/Modules/Scripted/EditorLib/WandEffect.py#L280-L286)), and finally
  - Export the processed segment to a model node, using [segmentations module logic’s ExportSegmentToRepresentationNode](http://apidocs.slicer.org/master/classvtkSlicerSegmentationsModuleLogic.html#a4ee8fb7834b01b8f06b41ccc7938570c)).

---

<div class="post-metadata">

**Author:** ![patmo141](https://avatars.discourse-cdn.com/v4/letter/p/ee7513/32.png) [@patmo141](https://discourse.slicer.org/u/patmo141)\
**Post date:** [June 19, 2017, 12:05pm UTC](https://discourse.slicer.org/t/model-undercuts-removal-by-label-map-addition/490/5 "2017-06-19T12:05:41Z")

</div>

Re: Extension Wizard. I have been following tutorial from Sonia Pujol and Steve Pieper for my Module Template. I will use the wizard and re-package once I get the initial workflow

Re Git: Absolutely. Most of my projects are github repos. In fact I just used Gist to get a quick show and tell 🙂

Re: Segmentation self test:  
I get an error with this line. First I used inputModel.GetPolyData() using my own input model, then I tried using a vtk.vtkSphereSource() from the example to see if it was my model. I’m using nightly from 6/11/2017 so I will download todays and try again but perhaps there is an error in that line?

> <https://github.com/Slicer/Slicer/blob/master/Modules/Scripted/SegmentStatistics/SegmentStatistics.py#L459>

Traceback (most recent call last):  
File “C:/Dev/slicer\_scripts/ModelUndercutRemoval.py”, line 173, in onHelloWorldButtonClicked  
segmentationNode.AddSegmentFromClosedSurfaceRepresentation (sphereSource.GetOutput(), segmentationNode.GetSegmentation().GenerateUniqueSegmentID(“Test”))  
AttributeError: ‘vtkCommonCorePython.vtkObject’ object has no attribute ‘GenerateUniqueSegmentID’

Things are moving along nicely! Thanks for you help and pointers.

-P

---

<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:** [June 19, 2017, 3:50pm UTC](https://discourse.slicer.org/t/model-undercuts-removal-by-label-map-addition/490/6 "2017-06-19T15:50:33Z")

</div>

> [@patmo141](#):
>
> Traceback (most recent call last):  
> File “C:/Dev/slicer\_scripts/ModelUndercutRemoval.py”, line 173, in onHelloWorldButtonClicked  
> segmentationNode.AddSegmentFromClosedSurfaceRepresentation (sphereSource.GetOutput(), segmentationNode.GetSegmentation().GenerateUniqueSegmentID(“Test”))  
> AttributeError: ‘vtkCommonCorePython.vtkObject’ object has no attribute ‘GenerateUniqueSegmentID’

To avoid this error, you need to import vtkSegmentationCore:

```
import vtkSegmentationCorePython as vtkSegmentationCore

```

Soon this import will be done automatically - see [Import vtkSegmentationCorePython and vtkAddonPython by default · Issue #4385 · Slicer/Slicer · GitHub](https://issues.slicer.org/view.php?id=4385).

---

<div class="post-metadata">

**Author:** ![patmo141](https://avatars.discourse-cdn.com/v4/letter/p/ee7513/32.png) [@patmo141](https://discourse.slicer.org/u/patmo141)\
**Post date:** [June 19, 2017, 11:00pm UTC](https://discourse.slicer.org/t/model-undercuts-removal-by-label-map-addition/490/7 "2017-06-19T23:00:17Z")

</div>

1. I used the Extension Wizard to generate cmakelists.txt, a png file.

2. I have uploaded project to a github directory. It is up to date with current code as seen in the video below.  
[https://github.com/patmo141/SlicerModelUndercuts](https://github.com/patmo141/SlicerModelUndercuts)

3. Initial workflow is very close! I seem to have a problem with the final step of generating a surface from the Label Map. It’s like it uses the old surface and ignores the new lablel map? Perhaps I need to delete the old surface model? See video.

1. After this, i will do code cleanup, start to tweak parameters, and add adjustable direction, add adjustable resolutions, then create a pull request for inclusion with Slicer Modules

So far a good time!

---

<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:** [June 19, 2017, 11:53pm UTC](https://discourse.slicer.org/t/model-undercuts-removal-by-label-map-addition/490/8 "2017-06-19T23:53:56Z")

</div>

It looks really nice! I think the only step you miss is calling modelLabelMap.Modified() after you’ve modified the modelLabelMap voxels using numpy (around line 175).

---

<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:** [June 19, 2017, 11:58pm UTC](https://discourse.slicer.org/t/model-undercuts-removal-by-label-map-addition/490/9 "2017-06-19T23:58:09Z")

</div>

Another small suggestion: instead of switching between Segmentations and Models modules to show/hide segments and models and export segment to model - you can use the Data module for all this. Click on the eye icon to show/hide a node. Right-click on a segmentation node to export to model.

---

<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:** [June 20, 2017, 12:06am UTC](https://discourse.slicer.org/t/model-undercuts-removal-by-label-map-addition/490/10 "2017-06-20T00:06:27Z")

</div>

> [@patmo141](#):
>
> I used the Extension Wizard to generate cmakelists.txt, a png file

Use the Extension wizard to create a complete skeleton for your extension and your module (adding just a CMakeListst.txt is not enough; you’ll need a separate subdirectory for your module, within that a Resources, Testing, etc. directory). Add a new module with identical name as your existing module and copy-paste content from your existing module.

---

<div class="post-metadata">

**Author:** ![patmo141](https://avatars.discourse-cdn.com/v4/letter/p/ee7513/32.png) [@patmo141](https://discourse.slicer.org/u/patmo141)\
**Post date:** [June 20, 2017, 12:27am UTC](https://discourse.slicer.org/t/model-undercuts-removal-by-label-map-addition/490/11 "2017-06-20T00:27:06Z")

</div>

> [@lassoan](#):
>
> modelLabelMap.Modified()

yes this fixed it! The output model now reflects the label map changes

---

<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:** [March 16, 2019, 6:04pm UTC](https://discourse.slicer.org/t/model-undercuts-removal-by-label-map-addition/490/12 "2019-03-16T18:04:45Z")

</div>

A post was split to a new topic: [How to install extensions?](https://discourse.slicer.org/t/how-to-install-extensions/6164)

---

<div class="post-metadata">

**Author:** ![clement\_laplace](https://avatars.discourse-cdn.com/v4/letter/c/a4c791/32.png) [@clement\_laplace](https://discourse.slicer.org/u/clement_laplace)\
**Post date:** [March 31, 2022, 2:10pm UTC](https://discourse.slicer.org/t/model-undercuts-removal-by-label-map-addition/490/13 "2022-03-31T14:10:58Z")

</div>

Hello Patrick,

I know it has been a while, but did you get the chance to finish your extension. The github repo does not seem to work as shown in the video. And I wasn’t able to find the option to choose the insertion axis.

Regardless thank you for the work, we are trying to create a module to produce dental surgical guide and this would be a key component.
