Line elements cause missing edges in triangle cells

This started in VTK 9.6, but is present in 9.7 as well. I’m not sure how pervasive it is, but if I have an unstructured grid with only triangles and lines, the triangles don’t have edges shown. If I don’t have the lines, the triangles have edges with the same code.

With lines:

Without lines:

If I switch to quads instead of triangles, the quads have edges in both cases. So, its something about the interaction of triangles and lines that’s causing something weird to happen.

Is there any workaround for this?

example_triangles.py below shows the issue if using VTK 9.6 or later. If you comment out the line creation on 116-119, the triangles will then have edges. example_quads is the same as example_tris but its has quads instead of tris and shows edges whether line elements are present or not.

If you run any of these in VTK 9.4 .1 or earlier, edges are shown for all cases.

Example code:

example_triangles.py (4.5 KB)

example_quads.py (4.3 KB)

Doing some more research, the edges of triangles show if there are any other cells with a quad face shown (quad, wedge, hex, etc). The same issue with edges not showing also pertains to tetrahedral elements, so its something to do with triangular faces that are causing the issue.

Sounds ripe for a bisect if anyone wants to go on an adventure…

This started in VTK 9.6,

Very helpful hint. A change to rendering was made in 9.6 to use vtkGeometryFilter by default instead of vtkDataSetSurfaceFilter:
https://gitlab.kitware.com/vtk/vtk/-/merge_requests/12224

As a workaround, you can use vtkDataSetSurfaceFilter before the mapper.

``` py import vtk

-----------------------------------------------------------------------------

Points

-----------------------------------------------------------------------------

points = vtk.vtkPoints()

point_coordinates = [
# Surface points
(0.0, 0.0, 0.0), # 0
(1.0, 0.0, 0.0), # 1
(2.0, 0.0, 0.0), # 2

(0.0, 1.0, 0.0),  # 3
(1.0, 1.0, 0.0),  # 4
(2.0, 1.0, 0.0),  # 5

(0.0, 2.0, 0.0),  # 6
(1.0, 2.0, 0.0),  # 7
(2.0, 2.0, 0.0),  # 8

# Separate bar points
(3.0, 0.0, 0.0),  # 9
(4.0, 0.0, 0.0),  # 10

(3.0, 0.6, 0.0),  # 11
(4.0, 0.6, 0.0),  # 12

(3.0, 1.2, 0.0),  # 13
(4.0, 1.2, 0.0),  # 14

(3.0, 1.8, 0.0),  # 15
(4.0, 1.8, 0.0),  # 16

]

for p in point_coordinates:
points.InsertNextPoint(p)

-----------------------------------------------------------------------------

Unstructured grid

-----------------------------------------------------------------------------

mesh = vtk.vtkUnstructuredGrid()
mesh.SetPoints(points)

-----------------------------------------------------------------------------

Helper for adding triangles

-----------------------------------------------------------------------------

def add_triangle(mesh, p0, p1, p2):

triangle = vtk.vtkTriangle()

triangle.GetPointIds().SetId(0, p0)
triangle.GetPointIds().SetId(1, p1)
triangle.GetPointIds().SetId(2, p2)

mesh.InsertNextCell(
    triangle.GetCellType(),
    triangle.GetPointIds()
)

-----------------------------------------------------------------------------

Helper for adding lines

-----------------------------------------------------------------------------

def add_line(mesh, p0, p1):

line = vtk.vtkLine()

line.GetPointIds().SetId(0, p0)
line.GetPointIds().SetId(1, p1)

mesh.InsertNextCell(
    line.GetCellType(),
    line.GetPointIds()
)

-----------------------------------------------------------------------------

Add 8 triangles

6 ----- 7 ----- 8

| \ | \ |

| \ | \ |

3 ----- 4 ----- 5

| \ | \ |

| \ | \ |

0 ----- 1 ----- 2

-----------------------------------------------------------------------------

add_triangle(mesh, 0, 1, 4)
add_triangle(mesh, 0, 4, 3)

add_triangle(mesh, 1, 2, 5)
add_triangle(mesh, 1, 5, 4)

add_triangle(mesh, 3, 4, 7)
add_triangle(mesh, 3, 7, 6)

add_triangle(mesh, 4, 5, 8)
add_triangle(mesh, 4, 8, 7)

-----------------------------------------------------------------------------

Add 4 disconnected lines

Comment these out to test triangles without line elements.

-----------------------------------------------------------------------------

add_line(mesh, 9, 10)
add_line(mesh, 11, 12)
add_line(mesh, 13, 14)
add_line(mesh, 15, 16)

mesh.Modified()

-----------------------------------------------------------------------------

Geometry extraction

vtkUnstructuredGrid → vtkDataSetSurfaceFilter → vtkPolyData

-----------------------------------------------------------------------------

surface_filter = vtk.vtkDataSetSurfaceFilter()
surface_filter.SetInputData(mesh)

-----------------------------------------------------------------------------

Mapper

Filtered:

vtkDataSetSurfaceFilter → vtkPolyDataMapper

-----------------------------------------------------------------------------

mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(surface_filter.GetOutputPort())

-----------------------------------------------------------------------------

Actor

-----------------------------------------------------------------------------

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

actor.GetProperty().SetRepresentationToSurface()
actor.GetProperty().EdgeVisibilityOn()
actor.GetProperty().SetLineWidth(3.0)

-----------------------------------------------------------------------------

Renderer

-----------------------------------------------------------------------------

renderer = vtk.vtkRenderer()
renderer.AddActor(actor)
renderer.SetBackground(0.15, 0.18, 0.22)

-----------------------------------------------------------------------------

Render window

-----------------------------------------------------------------------------

render_window = vtk.vtkRenderWindow()
render_window.AddRenderer(renderer)
render_window.SetSize(900, 700)

-----------------------------------------------------------------------------

Interactor

-----------------------------------------------------------------------------

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

renderer.ResetCamera()

render_window.Render()
interactor.Start()

I appreciate the help and insight. My full application already has a vtkGeometryFilter ahead of the mapper and switching to vtkDataSetSurfaceFilter does fix this rendering issue. I need to investigate if there’s any negative consequences to that switch.

Is the thought that this new behavior of vtkGeometryFilter is unintended?

Thank you!

Is the thought that this new behavior of vtkGeometryFilter is unintended?

Seems like it! I’d call it a bug that should be fixed. There was another issue caused by this change too https://gitlab.kitware.com/vtk/vtk/-/work_items/19922, which is why I thought the mapper filter switch was likely the cause.