# vtkPlanarContourToBinaryLabelmapConversionRule

**URL:** <https://discourse.slicer.org/t/vtkplanarcontourtobinarylabelmapconversionrule/47507>\
**Category:** Development\
**Tags:** segmentation\
**Created:** [June 30, 2026, 11:29am UTC](https://discourse.slicer.org/t/vtkplanarcontourtobinarylabelmapconversionrule/47507 "2026-06-30T11:29:30Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![ferhue](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/ferhue/32/82557_2.png) [@ferhue](https://discourse.slicer.org/u/ferhue)\
**Post date:** [June 30, 2026, 11:29am UTC](https://discourse.slicer.org/t/vtkplanarcontourtobinarylabelmapconversionrule/47507/1 "2026-06-30T11:29:30Z")

</div>

I am interested in creating a variant of [SlicerRT/DicomRtImportExport/ConversionRules/vtkPlanarContourToClosedSurfaceConversionRule.cxx at master · SlicerRt/SlicerRT · GitHub](https://github.com/SlicerRt/SlicerRT/blob/master/DicomRtImportExport/ConversionRules/vtkPlanarContourToClosedSurfaceConversionRule.cxx)

that directly converts a 2D Planar Contour to a 2D Binary Labelmap (and if I have more than 1 slice, that will become naturally 3D), without the overhead of triangulating a closed surface as intermediate step, etc. There was some related discussion here [Convert binary label map into 2D contours (ideally splines) and back - #4 by cpinter](https://discourse.slicer.org/t/convert-binary-label-map-into-2d-contours-ideally-splines-and-back/11135/4) but I thought not to necro-bump an old thread.

My reason is that I have hundreds/thousands of datasets (I cannot change) all using Planar contours (RTstruct.dcm format) as representation, and I just want to extract the binary labelmap (and doing this quickly matters for my application), not visualize them as closed surface. Contours are exactly aligned with CT slices, so they can be treated independently and fully parallelized, unlike if you try to reconstruct a 3D surface.

Currently, my workaround is to use in my C++ project a parallel-for loop for each slice, reading the slice 2D contour, and calling `vtkPolygon::PointInPolygon` for each pixel to fill the matrix.

But I thought it’s maybe wiser to profit/reuse the more advanced handling of keyholes of [SlicerRT/DicomRtImportExport/ConversionRules/vtkPlanarContourToClosedSurfaceConversionRule.cxx at master · SlicerRt/SlicerRT · GitHub](https://github.com/SlicerRt/SlicerRT/blob/master/DicomRtImportExport/ConversionRules/vtkPlanarContourToClosedSurfaceConversionRule.cxx#L183) for which maybe PointInPolygon is not prepared to deal well with if not preprocessed.

I’d be happy to hear comments / suggestions from @Sunderlandkyl @lassoan @cpinter

---

<div class="post-metadata">

**Author:** ![cpinter](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/cpinter/32/7995_2.png) [@cpinter](https://discourse.slicer.org/u/cpinter)\
**Post date:** [June 30, 2026, 11:40am UTC](https://discourse.slicer.org/t/vtkplanarcontourtobinarylabelmapconversionrule/47507/2 "2026-06-30T11:40:59Z")

</div>

The reason for going via closed surfaces is not the need of visualization in 3D, but as an intermediate step towards converting to labelmap. This is a very hard geometrical problem, so I don’t suggest jumping headfirst into it, because it already took two masters projects and it’s much more complex than it seems. See paper

[Reconstruction of surfaces from planar contours through contour interpolation](https://labs.cs.queensu.ca/perklab/wp-content/uploads/sites/3/2024/02/Sunderland2015-manuscript.pdf)

---

<div class="post-metadata">

**Author:** ![ferhue](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/ferhue/32/82557_2.png) [@ferhue](https://discourse.slicer.org/u/ferhue)\
**Post date:** [June 30, 2026, 2:06pm UTC](https://discourse.slicer.org/t/vtkplanarcontourtobinarylabelmapconversionrule/47507/3 "2026-06-30T14:06:15Z")

</div>

Thanks Csaba for the prompt reply and the link to the paper.

The paper states: _These structures must be converted into 3D meshes in order to be visualized or to be used for treatment planning and further analyses._

Maybe I should frame the conditions of my problem differently: the contours of all these datasets are manual 2D contours done by hand. So for this specific type of input, it makes less sense to me to try to go to 3D as intermediate step in order to convert to a 2D labelmap.  
Since what the physician is actually doing is drawing a 2D labelmap with his mouse on a CT slice. This is why simply the function `vtkPolygon::PointInPolygon` works rather well for my specific application of creating a 2D labelmap.

In my mind, that would simplify the issues commented in this paper:

_One issue that needs to be solved by all triangulation algorithms is determining which contours should be connected by triangles between each of the slices. This is referred to as the correspondence problem. Another obstacle to overcome is the occurrence of branching contours. A branching contour occurs when a single contour on one of the slices must be_  
_connected to two or more contours on an adjacent slice._

The issue though that has to be dealt with in the independent 2D problem is the other one:

_Another issue that can occur is the existence of keyholes within the set of contours. The DICOM standard (RT structure set module) defines the storage of hollow structures as keyholes that are represented as an inner and outer contour connected by an arbitrarily small channel in order to be considered one contour._

which I agree is a hard geometrical problem, but I still do not see the need to go to a 3D problem to solve it (which also prevents parallelization for each slice). Here a related discussion: [https://stackoverflow.com/a/218081/7471760](https://stackoverflow.com/a/218081/7471760) [GitHub - Aditi1993/Point\_in\_Polygon: Application can tell whether a point is inside or outside a complex polygon with holes. · GitHub](https://github.com/Aditi1993/Point_in_Polygon) [Determining Whether A Point Is Inside A Complex Polygon](https://alienryderflex.com/polygon/)

Maybe the [GitHub - AngusJohnson/Clipper2: Polygon Clipping, Offsetting & Triangulation in C++, C# and Delphi · GitHub](https://github.com/AngusJohnson/Clipper2) library that @lassoan mentioned some time ago could be useful in this regard to be able to process the CLOSEDPLANAR\_XOR 2D contour types.

---

<div class="post-metadata">

**Author:** ![cpinter](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/cpinter/32/7995_2.png) [@cpinter](https://discourse.slicer.org/u/cpinter)\
**Post date:** [June 30, 2026, 3:31pm UTC](https://discourse.slicer.org/t/vtkplanarcontourtobinarylabelmapconversionrule/47507/4 "2026-06-30T15:31:05Z")

</div>

I haven’t re-read the paper but as I remember the main purpose for the triangulation was to facilitate interpolation between the slices (avoid the staircase effect). Handling the different special cases is harder with surface meshes than with labelmaps, I agree.

We have another conversion path, via ribbon models. If you go to the Segmentations module and click Update in the Representations section for Binary labelmap, and choose the path via Ribbon models, you’ll see how the output changes.

If you use this path via ribbons would it help? I’d argue that it is basically what you want, if I understand it correctly.

And if you need better interpolation, we could use the algorithm that is behind the Fill between slices Segment Editor effect.

---

<div class="post-metadata">

**Author:** ![ferhue](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/ferhue/32/82557_2.png) [@ferhue](https://discourse.slicer.org/u/ferhue)\
**Post date:** [June 30, 2026, 3:41pm UTC](https://discourse.slicer.org/t/vtkplanarcontourtobinarylabelmapconversionrule/47507/5 "2026-06-30T15:41:29Z")

</div>

Thanks for the reply!

> [@cpinter](#):
>
> If you use this path via ribbons would it help? I’d argue that it is basically what you want, if I understand it correctly.

Yes, I first thought so, but then I noticed that

- Major: the function `FixKeyhole` is not present in [SlicerRT/DicomRtImportExport/ConversionRules/vtkPlanarContourToRibbonModelConversionRule.cxx at master · SlicerRt/SlicerRT · GitHub](https://github.com/SlicerRt/SlicerRT/blob/master/DicomRtImportExport/ConversionRules/vtkPlanarContourToRibbonModelConversionRule.cxx) but only in [SlicerRT/DicomRtImportExport/ConversionRules/vtkPlanarContourToClosedSurfaceConversionRule.cxx at master · SlicerRt/SlicerRT · GitHub](https://github.com/SlicerRt/SlicerRT/blob/master/DicomRtImportExport/ConversionRules/vtkPlanarContourToClosedSurfaceConversionRule.cxx)
- Minor: there might be some 3D-specific overhead `// Attempt to compute plane equation with brute force`

> [@cpinter](#):
>
> And if you need better interpolation,

In principle not, in this case I am looking towards performance/parallelization more than precision.

---

<div class="post-metadata">

**Author:** ![ferhue](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/ferhue/32/82557_2.png) [@ferhue](https://discourse.slicer.org/u/ferhue)\
**Post date:** [July 1, 2026, 8:03am UTC](https://discourse.slicer.org/t/vtkplanarcontourtobinarylabelmapconversionrule/47507/6 "2026-07-01T08:03:50Z")

</div>

By the way, KiCad ([https://www.kicad.org/](https://www.kicad.org/)) extensively uses 2D polygons with complex holes, so the mathematical problem they solve is quite similar to the PlanarContour to Labelmap 2D conversion problem. Maybe we could borrow something from there since it’s open source, and they have a `PointInside` function for complex polygons with holes ([libs/kimath/include/geometry/shape\_poly\_set.h · master · KiCad / KiCad Source Code / kicad · GitLab](https://gitlab.com/kicad/code/kicad/-/blob/master/libs/kimath/include/geometry/shape_poly_set.h#L1258)).  
In fact, they are relying on the Clipper2 library that Andras mentioned ([thirdparty/clipper2/Clipper2Lib/include/clipper2/clipper.engine.h · master · KiCad / KiCad Source Code / kicad · GitLab](https://gitlab.com/kicad/code/kicad/-/blob/master/thirdparty/clipper2/Clipper2Lib/include/clipper2/clipper.engine.h))

---

<div class="post-metadata">

**Author:** ![cpinter](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/cpinter/32/7995_2.png) [@cpinter](https://discourse.slicer.org/u/cpinter)\
**Post date:** [July 1, 2026, 10:37am UTC](https://discourse.slicer.org/t/vtkplanarcontourtobinarylabelmapconversionrule/47507/7 "2026-07-01T10:37:05Z")

</div>

> [@ferhue](#):
>
> the function `FixKeyhole` is not present

I have never seen keyhole artifacts in output ribbon representation. For closed surfaces this is an issue because you don’t want to see those faces connecting the outer and inner ends of the keyholes. For labelmaps this is not an issue, because the width of the keyhole is much smaller than the voxel size.

> [@ferhue](#):
>
> Maybe we could borrow something from there

Feel free to create a new conversion rule if you see the need. However, if all you need is the simple 2D polygon to labelmap, you have it with ribbons. The SlicerRT community only had that for a few years (before the new segmentations infrastructure and the planar contours to closed surface algorithm) and no problems were reported.

---

<div class="post-metadata">

**Author:** ![ferhue](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/ferhue/32/82557_2.png) [@ferhue](https://discourse.slicer.org/u/ferhue)\
**Post date:** [July 1, 2026, 11:32am UTC](https://discourse.slicer.org/t/vtkplanarcontourtobinarylabelmapconversionrule/47507/8 "2026-07-01T11:32:00Z")

</div>

> [@cpinter](#):
>
> For labelmaps this is not an issue, because the width of the keyhole is much smaller than the voxel size.

Ahh ok, I understand now what you mean.

> [@cpinter](#):
>
> and no problems were reported.

I do see artefacts sometimes when I turn on the ribbon model representation, but maybe those are visualization glitches or rounding errors on my computer?

For example with Slicer 5.10.0:

 ![image](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/b/7/b76d4b94da22ad5991d9c0ce712902e0dd9b6bd2.png)

The contour in this case is simple, when plotted with excel is just a circle.

The glitch disappears if I use closed-surface or binary labelmap. If I choose for planar contour, the contour is simply just not drawn in 2D but yes in 3D. Maybe rounding error in z coordinate to know if it is on that plane?

---

<div class="post-metadata">

**Author:** ![cpinter](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/cpinter/32/7995_2.png) [@cpinter](https://discourse.slicer.org/u/cpinter)\
**Post date:** [July 1, 2026, 1:58pm UTC](https://discourse.slicer.org/t/vtkplanarcontourtobinarylabelmapconversionrule/47507/9 "2026-07-01T13:58:28Z")

</div>

> [@ferhue](#):
>
> I do see artefacts sometimes when I turn on the ribbon model representation, but maybe those are visualization glitches or rounding errors on my computer?

These are due to a 2D visualization issue. Unfortunately it is not uncommon that `vtkPlaneCutter` in `vtkMRMLSegmentationsDisplayableManager2D` fails to give correct result. This occurs when you have a polydata type representation selected for slice visualization for your segmentation. If you change it to labelmap (Segmentations / Display / Advanced) then you’ll see the correct slice display.
