# How to transition away from vtkSurfaceNets3D SetOutputStyleToSelected API

**URL:** https://discourse.vtk.org/t/how-to-transition-away-from-vtksurfacenets3d-setoutputstyletoselected-api/16474
**Category:** Development
**Created:** [July 3, 2026, 6:43pm UTC](https://discourse.vtk.org/t/how-to-transition-away-from-vtksurfacenets3d-setoutputstyletoselected-api/16474 "2026-07-03T18:43:00Z")
**Posts on this page:** 17
**Page:** 1

<div class="post-metadata">

### Author: ![user27182](https://discourse.vtk.org/user_avatar/discourse.vtk.org/user27182/32/10104_2.png) [@user27182](https://discourse.vtk.org/u/user27182)
#### Post date: [July 3, 2026, 6:43pm UTC](https://discourse.vtk.org/t/how-to-transition-away-from-vtksurfacenets3d-setoutputstyletoselected-api/16474/1 "2026-07-03T18:43:00Z")

</div>

The following code creates image data with two regions, where one region (ID 2) is surrounded by background values (ID 0) on all sides except for one, where there is a single shared boundary with another region (ID 5).

Using `vtkSurfaceNets3D`, it’s possible to extract this internal boundary using a combination of `SetOutputStyleToSelected`, `SetLabel`, and `AddSelectedLabel`.

With VTK 9.6.2, the code below generates this output (using `contour_old(image)`):

 ![good](https://discourse.vtk.org/uploads/default/original/2X/7/7921cc62921878a1d846d98cd8c19f17b42cf255.jpeg)

where the `1` component of the two-component ‘BoundaryLabels’ array is shown as colored cells. The blue cells show the internal boundary [2, 5] (plotted as value `5`), whereas the red cells show the external boundary with the background [2, 0] (plotted as value `0`).

With the latest VTK built from master, we still get the same result using `contour_old(image)`, but there is a deprecation warning for `SetOutputStyleToSelected` and `AddSelectedLabel`, suggesting to use `vtkSurfaceNetsAtlas` instead. Notably `SetLabel` is not deprecated, but maybe it should be? I tried recreating the same result using the new API (and still using the old `SetLabel` on `vtkSurfaceNets3D`), but I am unable to reproduce the result using the `contour_new(image)` code below. This is the result I get instead, with the internal boundary between regions missing, such that we now see “inside” the contour.

 ![bad](https://discourse.vtk.org/uploads/default/original/2X/0/0d797e33bdffb0a2335fc59522c99637f28bbab2.jpeg)

Am I missing something, or was this perhaps an oversight for the deprecation, and the deprecation for `SetLabel` was missed?

Maybe @spyridon97 can comment on this?

```py
import vtk

def create_labeled_image():
    # Create 4x3x3 image with two adjacent labels

    # First label (ID 2):
    # has a single point near center of image,
    # is adjacent to second label,
    # is otherwise surrounded by background,

    # Second label (ID 5):
    # has two points near center of image,
    # is adjacent to first label,
    # has one side touching image boundary,
    # is otherwise surrounded by background

    dim = (4, 3, 3)

    image = vtk.vtkImageData()
    image.SetDimensions(dim)

    n_points = dim[0] * dim[1] * dim[2]
    labels = vtk.vtkIntArray()
    labels.SetName("labels")
    labels.SetNumberOfComponents(1)
    labels.SetNumberOfTuples(n_points)

    for i in range(n_points):
        labels.SetValue(i, 0)

    labels.SetValue(17, 2)
    labels.SetValue(18, 5)
    labels.SetValue(19, 5)

    image.GetPointData().AddArray(labels)
    image.GetPointData().SetActiveScalars("labels")
    return image

def contour_old(image):
    surface_nets = vtk.vtkSurfaceNets3D()
    surface_nets.SetInputData(image)
    surface_nets.SmoothingOff()

    surface_nets.AddSelectedLabel(2) # Moved to atlas in 9.7
    surface_nets.SetOutputStyleToSelected() # Moved to atlas in 9.7
    surface_nets.SetLabel(2, 2) # Missing from atlas in 9.7 (?)
    surface_nets.SetLabel(5, 5)

    surface_nets.Update()
    return surface_nets.GetOutput()

def contour_new(image):
    surface_nets = vtk.vtkSurfaceNets3D()
    surface_nets.SetInputData(image)
    surface_nets.SmoothingOff()
    surface_nets.SetLabel(2, 2)
    surface_nets.SetLabel(5, 5)
    surface_nets.Update()

    atlas = vtk.vtkSurfaceNetsAtlas()
    atlas.SetInputDataObject(surface_nets.GetOutput())
    atlas.SetExtractionModeToLabelSet()
    atlas.AddSelectedLabel(2)
    atlas.SetOutputStyleToBoundary()
    atlas.Update()
    pdc = atlas.GetOutput()

    blocks = [
        pds.GetPartition(j)
        for i in range(pdc.GetNumberOfPartitionedDataSets())
        for pds in [pdc.GetPartitionedDataSet(i)]
        for j in range(pds.GetNumberOfPartitions())
        if pds.GetPartition(j) is not None
    ]

    append = vtk.vtkAppendPolyData()
    for block in blocks:
        append.AddInputData(block)
    append.Update()
    return append.GetOutput()

def plot(poly):
    # Mapper
    mapper = vtk.vtkPolyDataMapper()
    mapper.SetInputData(poly)
    mapper.SetScalarModeToUseCellData()
    mapper.SelectColorArray("BoundaryLabels")
    mapper.ScalarVisibilityOn()
    mapper.SetColorModeToMapScalars()
    mapper.SetArrayComponent(1)

    # Actor
    actor = vtk.vtkActor()
    actor.SetMapper(mapper)

    # Renderer
    renderer = vtk.vtkRenderer()
    renderer.AddActor(actor)
    renderer.SetBackground(0.2, 0.3, 0.4)

    # Render window
    render_window = vtk.vtkRenderWindow()
    render_window.AddRenderer(renderer)
    render_window.SetSize(800, 600)

    # Interactor
    interactor = vtk.vtkRenderWindowInteractor()
    interactor.SetRenderWindow(render_window)

    renderer.ResetCamera()

    camera = renderer.GetActiveCamera()
    camera.SetPosition(1, 1, 1)
    camera.SetFocalPoint(0, 0, 0)
    camera.SetViewUp(0, 0, 1)

    renderer.ResetCamera()
    render_window.Render()

    # Start rendering
    render_window.Render()
    interactor.Start()

image = create_labeled_image()
# poly = contour_old(image)
poly = contour_new(image)
plot(poly)

```

EDIT: Fix colors that are referenced in plot

---

<div class="post-metadata">

### Author: ![spyridon97](https://discourse.vtk.org/user_avatar/discourse.vtk.org/spyridon97/32/7069_2.png) [@spyridon97](https://discourse.vtk.org/u/spyridon97)
#### Post date: [July 3, 2026, 6:53pm UTC](https://discourse.vtk.org/t/how-to-transition-away-from-vtksurfacenets3d-setoutputstyletoselected-api/16474/2 "2026-07-03T18:53:42Z")

</div>

SetValue/label sets the labels to consider from the input image while extracting the surface.

typically, all are extracted. so that smoothing and surface extraction can be more accurate geometrically.

AddSelectedLabel adds a label to extract out of the extracted ones (those defined above).

---

<div class="post-metadata">

### Author: ![user27182](https://discourse.vtk.org/user_avatar/discourse.vtk.org/user27182/32/10104_2.png) [@user27182](https://discourse.vtk.org/u/user27182)
#### Post date: [July 3, 2026, 7:05pm UTC](https://discourse.vtk.org/t/how-to-transition-away-from-vtksurfacenets3d-setoutputstyletoselected-api/16474/3 "2026-07-03T19:05:05Z")

</div>

So is there no way to reproduce the old output with the new API? I.e. this feature has been removed?

---

<div class="post-metadata">

### Author: ![user27182](https://discourse.vtk.org/user_avatar/discourse.vtk.org/user27182/32/10104_2.png) [@user27182](https://discourse.vtk.org/u/user27182)
#### Post date: [July 3, 2026, 8:10pm UTC](https://discourse.vtk.org/t/how-to-transition-away-from-vtksurfacenets3d-setoutputstyletoselected-api/16474/4 "2026-07-03T20:10:51Z")

</div>

> typically, all are extracted. so that smoothing and surface extraction can be more accurate geometrically.

Indeed my use case does not use the default settings. But what do you mean by “all” and “accurate”?

I find that the default settings for surface nets does _not_ extract all boundaries: it only extracts the exterior ones, and the internal boundaries are missing. Since the internal boundaries are missing, this makes the smoothing _less_ accurate. I use `SetOutputStyleToSelected` and `SetLabel` API specifically to improve the smoothing and the generated output. When the internal boundaries are generated, the smoothing takes these into account, resulting in much better contours IMO.

Here’s an example using a real data set with smoothing enabled (unlike the toy example above, which had it disabled).

[example.vti](https://discourse.vtk.org/uploads/short-url/y7zen2Rz6A7YGCgocn7ky76KMFi.vti) (2.7 KB)

Using the old (deprecated) API:

 ![Screenshot 2026-07-03 at 2.05.41 PM](https://discourse.vtk.org/uploads/default/original/2X/2/27946bdeb638f0a8c9de01cdb53bf9e37c9c8e1e.jpeg)

Using the new atlas API:

 ![image](https://discourse.vtk.org/uploads/default/original/2X/8/8b65e2a0ce041ae05dae5af793abe3e1f8a742e8.jpeg)

Code:

```py
import vtk

def contour_old(image):
    surface_nets = vtk.vtkSurfaceNets3D()
    surface_nets.SetInputData(image)

    surface_nets.SetOutputStyleToSelected()
    
    surface_nets.AddSelectedLabel(1)
    surface_nets.AddSelectedLabel(2)
    surface_nets.AddSelectedLabel(3)
    surface_nets.AddSelectedLabel(4)
    
    surface_nets.SetLabel(1, 1)
    surface_nets.SetLabel(2, 2)
    surface_nets.SetLabel(3, 3)
    surface_nets.SetLabel(4, 4)

    surface_nets.Update()
    return surface_nets.GetOutput()

def contour_new(image):
    surface_nets = vtk.vtkSurfaceNets3D()
    surface_nets.SetInputData(image)
    surface_nets.SmoothingOff()
    surface_nets.SetLabel(1, 1)
    surface_nets.SetLabel(2, 2)
    surface_nets.SetLabel(3, 3)
    surface_nets.SetLabel(4, 4)
    surface_nets.Update()

    atlas = vtk.vtkSurfaceNetsAtlas()
    atlas.SetInputDataObject(surface_nets.GetOutput())
    atlas.SetExtractionModeToLabelSet()
    atlas.AddSelectedLabel(1)
    atlas.AddSelectedLabel(2)
    atlas.AddSelectedLabel(3)
    atlas.AddSelectedLabel(4)
    atlas.SetOutputStyleToBoundary()
    atlas.Update()
    pdc = atlas.GetOutput()

    blocks = [
        pds.GetPartition(j)
        for i in range(pdc.GetNumberOfPartitionedDataSets())
        for pds in [pdc.GetPartitionedDataSet(i)]
        for j in range(pds.GetNumberOfPartitions())
        if pds.GetPartition(j) is not None
    ]

    append = vtk.vtkAppendPolyData()
    for block in blocks:
        append.AddInputData(block)
    append.Update()
    return append.GetOutput()

def plot(poly):
    # Mapper
    mapper = vtk.vtkPolyDataMapper()
    mapper.SetInputData(poly)
    mapper.SetScalarModeToUseCellData()
    mapper.SelectColorArray("BoundaryLabels")
    mapper.ScalarVisibilityOn()
    mapper.SetColorModeToMapScalars()
    mapper.SetArrayComponent(1)

    # Actor
    actor = vtk.vtkActor()
    actor.SetMapper(mapper)
    
    # Property
    property = actor.GetProperty()
    property.SetEdgeVisibility(True)

    # Renderer
    renderer = vtk.vtkRenderer()
    renderer.AddActor(actor)
    renderer.SetBackground(0.2, 0.3, 0.4)

    # Render window
    render_window = vtk.vtkRenderWindow()
    render_window.AddRenderer(renderer)
    render_window.SetSize(800, 600)

    # Interactor
    interactor = vtk.vtkRenderWindowInteractor()
    interactor.SetRenderWindow(render_window)

    renderer.ResetCamera()

    camera = renderer.GetActiveCamera()
    camera.SetPosition(1, 1, 1)
    camera.SetFocalPoint(0, 0, 0)
    camera.SetViewUp(0, 0, 1)

    renderer.ResetCamera()
    render_window.Render()

    # Start rendering
    render_window.Render()
    interactor.Start()

reader = vtk.vtkXMLImageDataReader()
reader.SetFileName('example.vti')
reader.Update()
image = reader.GetOutput()

poly_old = contour_old(image)
plot(poly_old)
poly_new = contour_new(image)
plot(poly_new)

```

---

<div class="post-metadata">

### Author: ![user27182](https://discourse.vtk.org/user_avatar/discourse.vtk.org/user27182/32/10104_2.png) [@user27182](https://discourse.vtk.org/u/user27182)
#### Post date: [July 3, 2026, 8:16pm UTC](https://discourse.vtk.org/t/how-to-transition-away-from-vtksurfacenets3d-setoutputstyletoselected-api/16474/5 "2026-07-03T20:16:22Z")

</div>

Whoops, I forgot to remove `SmoothingOff()` from the new version. Indeed, removing this, the output results look the same. So I guess the new API fixed what was previously a workaround?

I’ll have another look at my code and see what else I need to do to update to the new API.

---

<div class="post-metadata">

### Author: ![user27182](https://discourse.vtk.org/user_avatar/discourse.vtk.org/user27182/32/10104_2.png) [@user27182](https://discourse.vtk.org/u/user27182)
#### Post date: [July 3, 2026, 8:36pm UTC](https://discourse.vtk.org/t/how-to-transition-away-from-vtksurfacenets3d-setoutputstyletoselected-api/16474/6 "2026-07-03T20:36:59Z")

</div>

Okay so I was able to reproduce this bug after with the real dataset, and the new API does indeed remove boundaries that were otherwise there with the old API (just like the toy example I presented initially above).

Same code as above, but just remove the `AddSelectedLabel(2)` lines. We can see that the blue cells are completely gone with the new atlas.

Old API

 ![Screenshot 2026-07-03 at 2.34.54 PM](https://discourse.vtk.org/uploads/default/original/2X/1/1a6a5729e2702be04d8dd12b0d692b85b9b201b9.jpeg)

New API

 ![Screenshot 2026-07-03 at 2.34.57 PM](https://discourse.vtk.org/uploads/default/original/2X/c/cb93fa4372ec03c40926b4c106e3ff1208b65228.jpeg)

> ****
>
> ``` import vtk
> 
> def contour\_old(image):  
> surface\_nets = vtk.vtkSurfaceNets3D()  
> surface\_nets.SetInputData(image)
> 
> ```
> surface_nets.SetOutputStyleToSelected()
> 
> surface_nets.AddSelectedLabel(1)
> surface_nets.AddSelectedLabel(3)
> surface_nets.AddSelectedLabel(4)
> 
> surface_nets.SetLabel(1, 1)
> surface_nets.SetLabel(2, 2)
> surface_nets.SetLabel(4, 4)
> 
> surface_nets.Update()
> return surface_nets.GetOutput()
> 
> ```
> 
> def contour\_new(image):  
> surface\_nets = vtk.vtkSurfaceNets3D()  
> surface\_nets.SetInputData(image)  
> surface\_nets.SetLabel(1, 1)  
> surface\_nets.SetLabel(2, 2)  
> surface\_nets.SetLabel(4, 4)  
> surface\_nets.Update()
> 
> ```
> atlas = vtk.vtkSurfaceNetsAtlas()
> atlas.SetInputDataObject(surface_nets.GetOutput())
> atlas.SetExtractionModeToLabelSet()
> atlas.AddSelectedLabel(1)
> atlas.AddSelectedLabel(3)
> atlas.AddSelectedLabel(4)
> atlas.SetOutputStyleToBoundary()
> atlas.Update()
> pdc = atlas.GetOutput()
> 
> blocks = [
> pds.GetPartition(j)
> for i in range(pdc.GetNumberOfPartitionedDataSets())
> for pds in [pdc.GetPartitionedDataSet(i)]
> for j in range(pds.GetNumberOfPartitions())
> if pds.GetPartition(j) is not None
> ]
> 
> append = vtk.vtkAppendPolyData()
> for block in blocks:
> append.AddInputData(block)
> append.Update()
> return append.GetOutput()
> 
> ```
> 
> def plot(poly):  
> # Mapper  
> mapper = vtk.vtkPolyDataMapper()  
> mapper.SetInputData(poly)  
> mapper.SetScalarModeToUseCellData()  
> mapper.SelectColorArray(“BoundaryLabels”)  
> mapper.ScalarVisibilityOn()  
> mapper.SetColorModeToMapScalars()  
> mapper.SetArrayComponent(1)
> 
> ```
> # Actor
> actor = vtk.vtkActor()
> actor.SetMapper(mapper)
> 
> # Property
> property = actor.GetProperty()
> property.SetEdgeVisibility(True)
> 
> # Renderer
> renderer = vtk.vtkRenderer()
> renderer.AddActor(actor)
> renderer.SetBackground(0.2, 0.3, 0.4)
> 
> # Render window
> render_window = vtk.vtkRenderWindow()
> render_window.AddRenderer(renderer)
> render_window.SetSize(800, 600)
> 
> # Interactor
> interactor = vtk.vtkRenderWindowInteractor()
> interactor.SetRenderWindow(render_window)
> 
> renderer.ResetCamera()
> 
> camera = renderer.GetActiveCamera()
> camera.SetPosition(1, 1, 1)
> camera.SetFocalPoint(0, 0, 0)
> camera.SetViewUp(0, 0, 1)
> 
> renderer.ResetCamera()
> camera.Zoom(2)
> render_window.Render()
> 
> # Start rendering
> render_window.Render()
> interactor.Start()
> 
> ```
> 
> reader = vtk.vtkXMLImageDataReader()  
> reader.SetFileName(‘example.vti’)  
> reader.Update()  
> image = reader.GetOutput()
> 
> poly\_old = contour\_old(image)  
> plot(poly\_old)  
> poly\_new = contour\_new(image)  
> plot(poly\_new)
> 
> ```auto
> 
> ```

---

<div class="post-metadata">

### Author: ![spyridon97](https://discourse.vtk.org/user_avatar/discourse.vtk.org/spyridon97/32/7069_2.png) [@spyridon97](https://discourse.vtk.org/u/spyridon97)
#### Post date: [July 6, 2026, 2:37pm UTC](https://discourse.vtk.org/t/how-to-transition-away-from-vtksurfacenets3d-setoutputstyletoselected-api/16474/7 "2026-07-06T14:37:17Z")

</div>

I am sorry but you have sent a lot of messages. i lost track of what is the problem now.

the whole selection/boundary API has been replaced by vtkSurfaceNetsAtlas which is still used internally.

What’s the problem with using vtkSurfaceNetsAtlas?

---

<div class="post-metadata">

### Author: ![user27182](https://discourse.vtk.org/user_avatar/discourse.vtk.org/user27182/32/10104_2.png) [@user27182](https://discourse.vtk.org/u/user27182)
#### Post date: [July 6, 2026, 3:56pm UTC](https://discourse.vtk.org/t/how-to-transition-away-from-vtksurfacenets3d-setoutputstyletoselected-api/16474/8 "2026-07-06T15:56:46Z")

</div>

My initial message at the top is still valid and provides a minimal example of the problem. The issue is that previously it was possible to control both internal and external boundaries that were generated. Eg. for an input with two regions `2` and `5`, it was valid to do:

```py
    surface_nets.SetOutputStyleToSelected()
    surface_nets.AddSelectedLabel(2)
    surface_nets.SetLabel(2, 2)
    surface_nets.SetLabel(5, 5)

```

where `AddSelectedLabel` is only used for one label, but `SetLabel` is used for both. Using `SetLabel` this way enables internal boundaries with `[2, 5]` to be generated (the blue cell in my first post), while calling `AddSelectedLabel(2)` on the value `2` enables external boundaries with `[2, 0]` (the red cells in my first post). Since `AddSelectedLabel(5)` is _not_ called, we do not see external boundaries `[5, 0]`.

But with the new API, this no longer works, so the internal boundary `[2, 5]` is no longer generated, and is completely missing from the output of `vtkSurfaceNetsAtlas`. Hence, the new output only contains external boundaries `[5, 0]`, and the blue internal boundary `[2, 5]` is gone.

---

<div class="post-metadata">

### Author: ![spyridon97](https://discourse.vtk.org/user_avatar/discourse.vtk.org/spyridon97/32/7069_2.png) [@spyridon97](https://discourse.vtk.org/u/spyridon97)
#### Post date: [July 13, 2026, 4:06pm UTC](https://discourse.vtk.org/t/how-to-transition-away-from-vtksurfacenets3d-setoutputstyletoselected-api/16474/9 "2026-07-13T16:06:41Z")

</div>

This should fix the wrong behavior

[https://gitlab.kitware.com/vtk/vtk/-/merge\_requests/13452/diffs?commit\_id=74c86369dc70295e6bcd4aec9440d19899df3e4f](https://gitlab.kitware.com/vtk/vtk/-/merge_requests/13452/diffs?commit_id=74c86369dc70295e6bcd4aec9440d19899df3e4f)

---

<div class="post-metadata">

### Author: ![user27182](https://discourse.vtk.org/user_avatar/discourse.vtk.org/user27182/32/10104_2.png) [@user27182](https://discourse.vtk.org/u/user27182)
#### Post date: [July 21, 2026, 4:43pm UTC](https://discourse.vtk.org/t/how-to-transition-away-from-vtksurfacenets3d-setoutputstyletoselected-api/16474/10 "2026-07-21T16:43:04Z")

</div>

There are no 9.7 RC wheels to test with, but I did build a local copy of vtk from the `release` branch, and it seems things are now worse than before. In my original post at the top, there is a `contour_old` and `contour_new` function, which use the deprecated and new APIs, respectively. Previously, before [https://gitlab.kitware.com/vtk/vtk/-/merge\_requests/13452](https://gitlab.kitware.com/vtk/vtk/-/merge_requests/13452) (?), `contour_old` was producing correct output, and `contour_new` was not. But now, _both_ are not working, meaning that the old behavior is now broken. And the new behavior is still not fixed. i.e. both the old and new API are missing the internal blue surface (shown in the original post above), and instead show just the external ones:

 ![image](https://discourse.vtk.org/uploads/default/original/2X/5/5a28e4a49e28b6e6d5eaf2c6f3b7818c09e256aa.jpeg)

---

<div class="post-metadata">

### Author: ![spyridon97](https://discourse.vtk.org/user_avatar/discourse.vtk.org/spyridon97/32/7069_2.png) [@spyridon97](https://discourse.vtk.org/u/spyridon97)
#### Post date: [July 21, 2026, 9:59pm UTC](https://discourse.vtk.org/t/how-to-transition-away-from-vtksurfacenets3d-setoutputstyletoselected-api/16474/11 "2026-07-21T21:59:34Z")

</div>

I am very confused about what you mean by new API? we only deprecated API i did not add any new API to vtkSurfaceNets3D.

Could you please show me your old code and what it is producing.

with 9.6.2 and with release?

and then show me the new code you use with the atlas to generate the same output as the old results?

---

<div class="post-metadata">

### Author: ![user27182](https://discourse.vtk.org/user_avatar/discourse.vtk.org/user27182/32/10104_2.png) [@user27182](https://discourse.vtk.org/u/user27182)
#### Post date: [July 22, 2026, 4:36am UTC](https://discourse.vtk.org/t/how-to-transition-away-from-vtksurfacenets3d-setoutputstyletoselected-api/16474/12 "2026-07-22T04:36:52Z")

</div>

> I am very confused about what you mean by new API? we only deprecated API i did not add any new API to vtkSurfaceNets3D.

By old API, I mean `vtkSurfaceNets3D` with `SetOutputStyleToSelected`.  
By new API, I mean `vtkSurfaceNetsAtlas` with `ExtractionMode=EXTRACT_LABEL_SET`.

This stems directly from the deprecation warning emitted by VTK 9.7.0:

```auto
DeprecationWarning: Call to deprecated method SetOutputStyleToSelected. (Use vtkSurfaceNetsAtlas with ExtractionMode=EXTRACT_LABEL_SET instead) -- Deprecated since version 9.7.0.

```

> Could you please show me your old code and what it is producing.
> 
> with 9.6.2 and with release?

I have copied the code from my original post above verbatim here.

> ****
>
> ```py
> import vtk
> 
> def create_labeled_image():
> # Create 4x3x3 image with two adjacent labels
> 
> # First label (ID 2):
> # has a single point near center of image,
> # is adjacent to second label,
> # is otherwise surrounded by background,
> 
> # Second label (ID 5):
> # has two points near center of image,
> # is adjacent to first label,
> # has one side touching image boundary,
> # is otherwise surrounded by background
> 
> dim = (4, 3, 3)
> 
> image = vtk.vtkImageData()
> image.SetDimensions(dim)
> 
> n_points = dim[0] * dim[1] * dim[2]
> labels = vtk.vtkIntArray()
> labels.SetName("labels")
> labels.SetNumberOfComponents(1)
> labels.SetNumberOfTuples(n_points)
> 
> for i in range(n_points):
> labels.SetValue(i, 0)
> 
> labels.SetValue(17, 2)
> labels.SetValue(18, 5)
> labels.SetValue(19, 5)
> 
> image.GetPointData().AddArray(labels)
> image.GetPointData().SetActiveScalars("labels")
> return image
> 
> def contour_old(image):
> surface_nets = vtk.vtkSurfaceNets3D()
> surface_nets.SetInputData(image)
> surface_nets.SmoothingOff()
> 
> surface_nets.AddSelectedLabel(2) # Moved to atlas in 9.7
> surface_nets.SetOutputStyleToSelected() # Moved to atlas in 9.7
> surface_nets.SetLabel(2, 2) # Missing from atlas in 9.7 (?)
> surface_nets.SetLabel(5, 5)
> 
> surface_nets.Update()
> return surface_nets.GetOutput()
> 
> def plot(poly):
> # Mapper
> mapper = vtk.vtkPolyDataMapper()
> mapper.SetInputData(poly)
> mapper.SetScalarModeToUseCellData()
> mapper.SelectColorArray("BoundaryLabels")
> mapper.ScalarVisibilityOn()
> mapper.SetColorModeToMapScalars()
> mapper.SetArrayComponent(1)
> 
> # Actor
> actor = vtk.vtkActor()
> actor.SetMapper(mapper)
> 
> # Renderer
> renderer = vtk.vtkRenderer()
> renderer.AddActor(actor)
> renderer.SetBackground(0.2, 0.3, 0.4)
> 
> # Render window
> render_window = vtk.vtkRenderWindow()
> render_window.AddRenderer(renderer)
> render_window.SetSize(800, 600)
> 
> # Interactor
> interactor = vtk.vtkRenderWindowInteractor()
> interactor.SetRenderWindow(render_window)
> 
> renderer.ResetCamera()
> 
> camera = renderer.GetActiveCamera()
> camera.SetPosition(1, 1, 1)
> camera.SetFocalPoint(0, 0, 0)
> camera.SetViewUp(0, 0, 1)
> 
> renderer.ResetCamera()
> render_window.Render()
> 
> # Start rendering
> render_window.Render()
> interactor.Start()
> 
> ```

This is the output I get with vtk 9.6.2 using the old API

```py
plot(contour_old(create_labeled_image()))

```

 ![image](https://discourse.vtk.org/uploads/default/original/2X/0/04c2ff31e257e733b85c080c4f715abcd7e27066.jpeg)

With the latest release branch, I get

```auto
<ipython-input-2-fe88e5d367a6>:46: DeprecationWarning: Call to deprecated method AddSelectedLabel. (Use vtkSurfaceNetsAtlas with ExtractionMode=EXTRACT_LABEL_SET instead) -- Deprecated since version 9.7.0.
  surface_nets.AddSelectedLabel(2)
<ipython-input-2-fe88e5d367a6>:47: DeprecationWarning: Call to deprecated method SetOutputStyleToSelected. (Use vtkSurfaceNetsAtlas with ExtractionMode=EXTRACT_LABEL_SET instead) -- Deprecated since version 9.7.0.
  surface_nets.SetOutputStyleToSelected()

```

 ![image](https://discourse.vtk.org/uploads/default/original/2X/9/9ce8a4f49c7e241965a9cae8e9a5cac3b92aefe4.jpeg)

> and then show me the new code you use with the atlas to generate the same output as the old results?

This is what I tried to do to reproduce the output from 9.6.2. But I am unable to configure it so that it generates the blue internal polygon.

> ****
>
> ```auto
> def contour_new(image):
> surface_nets = vtk.vtkSurfaceNets3D()
> surface_nets.SetInputData(image)
> surface_nets.SmoothingOff()
> surface_nets.SetLabel(2, 2)
> surface_nets.SetLabel(5, 5)
> surface_nets.Update()
> 
> atlas = vtk.vtkSurfaceNetsAtlas()
> atlas.SetInputDataObject(surface_nets.GetOutput())
> atlas.SetExtractionModeToLabelSet()
> atlas.AddSelectedLabel(2)
> atlas.SetOutputStyleToBoundary()
> atlas.Update()
> pdc = atlas.GetOutput()
> 
> blocks = [
> pds.GetPartition(j)
> for i in range(pdc.GetNumberOfPartitionedDataSets())
> for pds in [pdc.GetPartitionedDataSet(i)]
> for j in range(pds.GetNumberOfPartitions())
> if pds.GetPartition(j) is not None
> ]
> 
> append = vtk.vtkAppendPolyData()
> for block in blocks:
> append.AddInputData(block)
> append.Update()
> return append.GetOutput()
> 
> ```

Running it with

```py
plot(contour_new(create_labeled_image()))

```

The output is the same as above.

 ![image](https://discourse.vtk.org/uploads/default/original/2X/9/9ce8a4f49c7e241965a9cae8e9a5cac3b92aefe4.jpeg)

---

<div class="post-metadata">

### Author: ![spyridon97](https://discourse.vtk.org/user_avatar/discourse.vtk.org/spyridon97/32/7069_2.png) [@spyridon97](https://discourse.vtk.org/u/spyridon97)
#### Post date: [July 22, 2026, 1:54pm UTC](https://discourse.vtk.org/t/how-to-transition-away-from-vtksurfacenets3d-setoutputstyletoselected-api/16474/13 "2026-07-22T13:54:44Z")

</div>

i added a fix with the last commit here

[https://gitlab.kitware.com/vtk/vtk/-/merge\_requests/13489](https://gitlab.kitware.com/vtk/vtk/-/merge_requests/13489)

if you want to understand how to reproduce the same behavior as the atlas just follow what surfacenets does internally.

the SetLabel as we discussed should only leave in surfacenets and not the atlas.

---

<div class="post-metadata">

### Author: ![ottogriffin43](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/o/a3d4f5/32.png) [@ottogriffin43](https://discourse.vtk.org/u/ottogriffin43)
#### Post date: [July 23, 2026, 10:49pm UTC](https://discourse.vtk.org/t/how-to-transition-away-from-vtksurfacenets3d-setoutputstyletoselected-api/16474/14 "2026-07-23T22:49:10Z")

</div>

I wonder if SetOutputStyleToBoundary() isn’t the right replacement for SetOutputStyleToSelected()—they might be computing boundaries differently. The old code extracts boundaries \*around\* selected labels, but the new atlas approach with Boundary mode might be interpreting it differently. Have you tried checking what other output style options the atlas has?

---

<div class="post-metadata">

### Author: ![user27182](https://discourse.vtk.org/user_avatar/discourse.vtk.org/user27182/32/10104_2.png) [@user27182](https://discourse.vtk.org/u/user27182)
#### Post date: [July 24, 2026, 3:21pm UTC](https://discourse.vtk.org/t/how-to-transition-away-from-vtksurfacenets3d-setoutputstyletoselected-api/16474/15 "2026-07-24T15:21:29Z")

</div>

Thanks for the feedback. I did look at the C++ code to try to reproduce the output (this is how I determined how to handle the conversion from partitioned output back to PolyData). But that didn’t produce the output I expected, which is the whole reason I even started this discussion.

Rather than continue guessing at how to make this previously-supported feature work with the new API, I am instead going to assume it is no longer supported, and I will work around it instead. Thanks again.

---

<div class="post-metadata">

### Author: ![spyridon97](https://discourse.vtk.org/user_avatar/discourse.vtk.org/spyridon97/32/7069_2.png) [@spyridon97](https://discourse.vtk.org/u/spyridon97)
#### Post date: [July 24, 2026, 3:38pm UTC](https://discourse.vtk.org/t/how-to-transition-away-from-vtksurfacenets3d-setoutputstyletoselected-api/16474/16 "2026-07-24T15:38:44Z")

</div>

@user27182 given that the deprecated API with my fix, now generates the same output as it used using the atlas. The atlas is sufficient to produce the same output.

as i have told you in a previous answer of mine.

SetLabel does not need to be part of the atlas API. that’s for the surface nets API.

That’s how to create the deprecated API using the atlas

```cpp
    auto atlas = vtkSmartPointer<vtkSurfaceNetsAtlas>::New();
    atlas->SetBackgroundLabel(static_cast<vtkIdType>(this->BackgroundLabel));
    atlas->SetOutputStyleToBoundary(); // that's also the default option
    atlas->SetResolveNonManifoldPoints(false); // you can remove that because it's the default
    if (this->OutputStyle == OUTPUT_STYLE_BOUNDARY)
    {
      atlas->SetExtractionModeToAll();
      atlas->SetGeneratePatches(false);
    }
    else // OUTPUT_STYLE_SELECTED
    {
      atlas->SetExtractionModeToLabelSet();
      atlas->SetGeneratePatches(true);
      for (const double label : this->SelectedLabels)
      {
        atlas->AddSelectedLabel(static_cast<vtkIdType>(label));
      }
    }
    atlas->SetInputDataObject(output);
    atlas->Update();
    auto datasets = vtkCompositeDataSet::GetDataSets(atlas->GetOutputDataObject(0));
    auto appender = vtkSmartPointer<vtkAppendPolyData>::New();
    for (vtkDataSet* dataset : datasets)
    {
      appender->AddInputDataObject(0, dataset);
    }

```

---

<div class="post-metadata">

### Author: ![user27182](https://discourse.vtk.org/user_avatar/discourse.vtk.org/user27182/32/10104_2.png) [@user27182](https://discourse.vtk.org/u/user27182)
#### Post date: [July 24, 2026, 7:45pm UTC](https://discourse.vtk.org/t/how-to-transition-away-from-vtksurfacenets3d-setoutputstyletoselected-api/16474/17 "2026-07-24T19:45:34Z")

</div>

Thank you @ottogriffin43.

The solution was to use `SetOutputStyleToAll()`, since in this case `SetOutputStyleToBoundary` only extracts the outer boundary and hence does not include the internal boundaries. This code works, it’s exactly the same as everywhere else I’ve posted it except for this change:

```diff
- atlas.SetOutputStyleToBoundary()
+ atlas.SetOutputStyleToAll()

```

> ****
>
> ```py
> import vtk
> 
> def create_labeled_image():
> # Create 4x3x3 image with two adjacent labels
> 
> # First label (ID 2):
> # has a single point near center of image,
> # is adjacent to second label,
> # is otherwise surrounded by background,
> 
> # Second label (ID 5):
> # has two points near center of image,
> # is adjacent to first label,
> # has one side touching image boundary,
> # is otherwise surrounded by background
> 
> dim = (4, 3, 3)
> 
> image = vtk.vtkImageData()
> image.SetDimensions(dim)
> 
> n_points = dim[0] * dim[1] * dim[2]
> labels = vtk.vtkIntArray()
> labels.SetName("labels")
> labels.SetNumberOfComponents(1)
> labels.SetNumberOfTuples(n_points)
> 
> for i in range(n_points):
> labels.SetValue(i, 0)
> 
> labels.SetValue(17, 2)
> labels.SetValue(18, 5)
> labels.SetValue(19, 5)
> 
> image.GetPointData().AddArray(labels)
> image.GetPointData().SetActiveScalars("labels")
> return image
> 
> def contour_old(image):
> surface_nets = vtk.vtkSurfaceNets3D()
> surface_nets.SetInputData(image)
> surface_nets.SmoothingOff()
> 
> surface_nets.AddSelectedLabel(2) # Moved to atlas in 9.7
> surface_nets.SetOutputStyleToSelected() # Moved to atlas in 9.7
> surface_nets.SetLabel(2, 2) # Missing from atlas in 9.7 (?)
> surface_nets.SetLabel(5, 5)
> 
> surface_nets.Update()
> return surface_nets.GetOutput()
> 
> def contour_new(image):
> surface_nets = vtk.vtkSurfaceNets3D()
> surface_nets.SetInputData(image)
> surface_nets.SmoothingOff()
> surface_nets.SetLabel(2, 2)
> surface_nets.SetLabel(5, 5)
> surface_nets.Update()
> 
> atlas = vtk.vtkSurfaceNetsAtlas()
> atlas.SetInputDataObject(surface_nets.GetOutput())
> atlas.SetExtractionModeToLabelSet()
> atlas.AddSelectedLabel(2)
> atlas.SetOutputStyleToAll()
> atlas.Update()
> pdc = atlas.GetOutput()
> 
> blocks = [
> pds.GetPartition(j)
> for i in range(pdc.GetNumberOfPartitionedDataSets())
> for pds in [pdc.GetPartitionedDataSet(i)]
> for j in range(pds.GetNumberOfPartitions())
> if pds.GetPartition(j) is not None
> ]
> 
> append = vtk.vtkAppendPolyData()
> for block in blocks:
> append.AddInputData(block)
> append.Update()
> return append.GetOutput()
> 
> def plot(poly):
> # Mapper
> mapper = vtk.vtkPolyDataMapper()
> mapper.SetInputData(poly)
> mapper.SetScalarModeToUseCellData()
> mapper.SelectColorArray("BoundaryLabels")
> mapper.ScalarVisibilityOn()
> mapper.SetColorModeToMapScalars()
> mapper.SetArrayComponent(1)
> 
> # Actor
> actor = vtk.vtkActor()
> actor.SetMapper(mapper)
> 
> # Renderer
> renderer = vtk.vtkRenderer()
> renderer.AddActor(actor)
> renderer.SetBackground(0.2, 0.3, 0.4)
> 
> # Render window
> render_window = vtk.vtkRenderWindow()
> render_window.AddRenderer(renderer)
> render_window.SetSize(800, 600)
> 
> # Interactor
> interactor = vtk.vtkRenderWindowInteractor()
> interactor.SetRenderWindow(render_window)
> 
> renderer.ResetCamera()
> 
> camera = renderer.GetActiveCamera()
> camera.SetPosition(1, 1, 1)
> camera.SetFocalPoint(0, 0, 0)
> camera.SetViewUp(0, 0, 1)
> 
> renderer.ResetCamera()
> render_window.Render()
> 
> # Start rendering
> render_window.Render()
> interactor.Start()
> 
> image = create_labeled_image()
> poly = contour_new(image)
> plot(poly)
> 
> ```
