GradientBackground
vtk-examples/Python/Rendering/GradientBackground
Description¶
Demonstrates the gradient backgrounds available in VTK.
The gradient background modes are:
- Vertical
- Horizontal
- Radial Farthest Side
- Radial Farthest Corner
The user can also edit the code to change the stop colors marking the beginning and end points in a gradient.
An option is provided for the user to read in a data file so that more interesting objects can be viewed.
The viewport border can also be set and colored.
For more information, see New in VTK 9.3: Radial Gradient Background
!!! note VTK 9.3 or later is required.
!!! note The C++ version requires C++ 17 or later as std::filesystem is used.
Other languages
See (Cxx)
Question
If you have a question about this example, please use the VTK Discourse Forum
Code¶
GradientBackground.py
#!/usr/bin/env python
# Based on:
# https://gitlab.kitware.com/vtk/vtk/-/blob/master/Rendering/Core/Testing/Cxx/TestGradientBackground.cxx?ref_type=heads
# See:
# [New in VTK 9.3: Radial Gradient Background](https://www.kitware.com/new-in-vtk-9-3-radial-gradient-background/)
from pathlib import Path
# noinspection PyUnresolvedReferences
import vtkmodules.vtkInteractionStyle
# noinspection PyUnresolvedReferences
import vtkmodules.vtkRenderingFreeType
# noinspection PyUnresolvedReferences
import vtkmodules.vtkRenderingOpenGL2
from vtkmodules.vtkCommonColor import vtkNamedColors
from vtkmodules.vtkCommonCore import vtkPoints
from vtkmodules.vtkCommonDataModel import (
vtkCellArray,
vtkPolyData,
vtkPolyLine
)
from vtkmodules.vtkFiltersSources import (
vtkConeSource,
vtkSphereSource
)
from vtkmodules.vtkIOGeometry import (
vtkBYUReader,
vtkOBJReader,
vtkSTLReader
)
from vtkmodules.vtkIOLegacy import vtkPolyDataReader
from vtkmodules.vtkIOPLY import vtkPLYReader
from vtkmodules.vtkIOXML import vtkXMLPolyDataReader
from vtkmodules.vtkInteractionStyle import vtkInteractorStyleTrackballCamera
from vtkmodules.vtkRenderingCore import (
vtkActor,
vtkActor2D,
vtkCoordinate,
vtkPolyDataMapper,
vtkPolyDataMapper2D,
vtkRenderWindow,
vtkRenderWindowInteractor,
vtkRenderer,
vtkTextMapper,
vtkTextProperty,
vtkViewport
)
def get_program_parameters(argv):
import argparse
description = 'Demonstrates the background shading options.'
epilogue = '''
'''
parser = argparse.ArgumentParser(description=description, epilog=epilogue,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('-f', '--file_name', default=None,
help='An optional file name, e.g. star-wars-vader-tie-fighter.obj.')
args = parser.parse_args()
return args.file_name
def main(fn):
if fn:
fp = Path(fn)
if not fp.is_file():
print(f'The path: {fp} does not exist.')
return
else:
fp = None
pd = read_polydata_(fp)
ren_win = vtkRenderWindow()
ren_win.SetWindowName('GradientBackground')
iren = vtkRenderWindowInteractor()
renderers = []
# For each gradient specify the mode.
modes = [
vtkViewport.GradientModes.VTK_GRADIENT_VERTICAL,
vtkViewport.GradientModes.VTK_GRADIENT_HORIZONTAL,
vtkViewport.GradientModes.VTK_GRADIENT_RADIAL_VIEWPORT_FARTHEST_SIDE,
vtkViewport.GradientModes.VTK_GRADIENT_RADIAL_VIEWPORT_FARTHEST_CORNER,
]
colors = vtkNamedColors()
mapper = vtkPolyDataMapper()
mapper.SetInputData(pd)
actor = vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetColor(colors.GetColor3d('Honeydew'))
actor.GetProperty().SetSpecular(0.3)
actor.GetProperty().SetSpecularPower(60.0)
ren_width = 640
ren_height = 480
# The bounds for each view port.
xmins = [0.0, 0.5, 0.0, 0.5]
ymins = [0.0, 0.0, 0.5, 0.5]
xmaxs = [0.5, 1.0, 0.5, 1.0]
ymaxs = [0.5, 0.5, 1.0, 1.0]
# Here we select and name the colors.
# Feel free to change colors.
bottom_color = colors.GetColor3d('Gold')
top_color = colors.GetColor3d('OrangeRed')
left_color = colors.GetColor3d('Gold')
right_color = colors.GetColor3d('OrangeRed')
center_color = colors.GetColor3d('Gold')
side_color = colors.GetColor3d('OrangeRed')
corner_color = colors.GetColor3d('OrangeRed')
viewport_title = ["Vertical",
"Horizontal",
"Radial Farthest Side",
"Radial Farthest Corner",
]
# Create one text property for all.
text_property = vtkTextProperty()
text_property.SetJustificationToCentered()
text_property.SetFontSize(ren_height // 12)
text_property.SetColor(colors.GetColor3d('MidnightBlue'))
text_mappers = []
text_actors = []
# Define borders for the viewports = [top, left, bottom, right].
lb = [False, True, True, False]
lbr = [False, True, True, True]
tlb = [True, True, True, False]
tlbr = [True, True, True, True]
border_color = 'DarkGreen'
border_width = 4.0
for i in range(0, 4):
text_mappers.append(vtkTextMapper())
text_mappers[i].SetInput(viewport_title[i])
text_mappers[i].SetTextProperty(text_property)
text_actors.append(vtkActor2D())
text_actors[i].SetMapper(text_mappers[i])
text_actors[i].SetPosition(ren_width / 2, 8)
renderers.append(vtkRenderer())
renderers[i].AddActor(text_actors[i])
renderers[i].AddActor(actor)
renderers[i].GradientBackgroundOn()
renderers[i].SetGradientMode(modes[i])
renderers[i].SetViewport(xmins[i], ymins[i], xmaxs[i], ymaxs[i])
if i == 1:
# Horizontal
renderers[i].SetBackground(left_color)
renderers[i].SetBackground2(right_color)
viewport_border(renderers[i], lbr, border_color, border_width)
elif i == 2:
# Radial Farthest Side
renderers[i].SetBackground(center_color)
renderers[i].SetBackground2(side_color)
viewport_border(renderers[i], tlb, border_color, border_width)
elif i == 3:
# Radial Farthest Corner
renderers[i].SetBackground(center_color)
renderers[i].SetBackground2(corner_color)
viewport_border(renderers[i], tlbr, border_color, border_width)
else:
# Vertical
renderers[i].SetBackground(bottom_color)
renderers[i].SetBackground2(top_color)
viewport_border(renderers[i], lb, border_color, border_width)
ren_win.AddRenderer(renderers[i])
ren_win.SetInteractor(iren)
ren_win.Render()
style = vtkInteractorStyleTrackballCamera()
iren.SetInteractorStyle(style)
iren.Initialize()
iren.UpdateSize(ren_width * 2, ren_height * 2)
iren.Start()
def read_polydata_(path):
"""
Read from a file containing vtkPolyData.
If the path is empty a cone is returned.
If the extension is unknown a sphere is returned.
:param path: The path to the file.
:return: The vtkPolyData.
"""
poly_data = vtkPolyData()
if path is None:
# Default to a cone if the path is empty.
source = vtkConeSource()
source.SetResolution(25)
source.SetDirection(0, 1, 0)
source.SetHeight(1)
source.Update()
poly_data.DeepCopy(source.GetOutput())
return poly_data
valid_suffixes = ['.g', '.obj', '.stl', '.ply', '.vtk', '.vtp']
ext = path.suffix.lower()
if path.suffix not in valid_suffixes:
print('Warning:', path, 'unknown extension, using a sphere instead.')
source = vtkSphereSource()
source.SetPhiResolution(50)
source.SetThetaResolution(50)
source.Update()
poly_data.DeepCopy(source.GetOutput())
else:
if ext == '.ply':
reader = vtkPLYReader()
reader.SetFileName(file_name)
reader.Update()
poly_data.DeepCopy(reader.GetOutput())
elif ext == '.vtp':
reader = vtkXMLPolyDataReader()
reader.SetFileName(file_name)
reader.Update()
poly_data.DeepCopy(reader.GetOutput())
elif ext == '.obj':
reader = vtkOBJReader()
reader.SetFileName(file_name)
reader.Update()
poly_data.DeepCopy(reader.GetOutput())
elif ext == '.stl':
reader = vtkSTLReader()
reader.SetFileName(file_name)
reader.Update()
poly_data.DeepCopy(reader.GetOutput())
elif ext == '.vtk':
reader = vtkPolyDataReader()
reader.SetFileName(file_name)
reader.Update()
poly_data.DeepCopy(reader.GetOutput())
elif ext == '.g':
reader = vtkBYUReader()
reader.SetGeometryFileName(file_name)
reader.Update()
poly_data.DeepCopy(reader.GetOutput())
return poly_data
def viewport_border(renderer, sides, border_color, border_width):
"""
Set a border around a viewport.
:param renderer: The renderer corresponding to the viewport.
:param sides: An array of boolean corresponding to [top, left, bottom, right]
:param border_color: The color of the border.
:param border_width: The width of the border.
:return:
"""
colors = vtkNamedColors()
# Points start at upper right and proceed anti-clockwise.
points = vtkPoints()
points.SetNumberOfPoints(4)
points.InsertPoint(0, 1, 1, 0)
points.InsertPoint(1, 0, 1, 0)
points.InsertPoint(2, 0, 0, 0)
points.InsertPoint(3, 1, 0, 0)
cells = vtkCellArray()
cells.Initialize()
if sides[0]:
# Top
top = vtkPolyLine()
top.GetPointIds().SetNumberOfIds(2)
top.GetPointIds().SetId(0, 0)
top.GetPointIds().SetId(1, 1)
cells.InsertNextCell(top)
if sides[1]:
# Left
left = vtkPolyLine()
left.GetPointIds().SetNumberOfIds(2)
left.GetPointIds().SetId(0, 1)
left.GetPointIds().SetId(1, 2)
cells.InsertNextCell(left)
if sides[2]:
# Bottom
bottom = vtkPolyLine()
bottom.GetPointIds().SetNumberOfIds(2)
bottom.GetPointIds().SetId(0, 2)
bottom.GetPointIds().SetId(1, 3)
cells.InsertNextCell(bottom)
if sides[3]:
# Right
right = vtkPolyLine()
right.GetPointIds().SetNumberOfIds(2)
right.GetPointIds().SetId(0, 3)
right.GetPointIds().SetId(1, 0)
cells.InsertNextCell(right)
# Now make the polydata and display it.
poly = vtkPolyData()
poly.Initialize()
poly.SetPoints(points)
poly.SetLines(cells)
# Use normalized viewport coordinates since
# they are independent of window size.
coordinate = vtkCoordinate()
coordinate.SetCoordinateSystemToNormalizedViewport()
mapper = vtkPolyDataMapper2D()
mapper.SetInputData(poly)
mapper.SetTransformCoordinate(coordinate)
actor = vtkActor2D()
actor.SetMapper(mapper)
actor.GetProperty().SetColor(colors.GetColor3d(border_color))
# Line width should be at least 2 to be visible at extremes.
actor.GetProperty().SetLineWidth(border_width)
renderer.AddViewProp(actor)
if __name__ == '__main__':
import sys
file_name = get_program_parameters(sys.argv)
main(file_name)