Skip to content

ColoredAnnotatedCube

vtk-examples/Python/Visualization/ColoredAnnotatedCube

Description

This example demonstrates how to color the individual faces of an annotated cube.

This is based on a very nice example by Rodrigo Figueiredo in this discussion.

The process is:

  • Create the annotated cube actor using vtkAnnotatedCubeActor.
  • Select the names on the faces, text colors and, if needed, any rotations of the text.
  • Make the annotated cube transparent.
  • Create a cube actor with colored faces.
  • Combine the annotated cube actor and cube actor into a prop assembly using vtkPropAssembly. Since the annotated cube and the cube are the same size you get an assembly with colored cube faces and the requisite text.
  • Create a vtkOrientationMarkerWidget and set the set the orientation marker to be the prop assembly.

The function MakeAnnotatedCubeActor generates the annotated cube with different colored faces which is then added to a vtkOrientationMarkerWidget.

The colored annotated cube is then placed in the lower left of the view (default). Additionally, a vtkOrientationMarkerWidget containing an axes actor has been added to the lower right of the view.

Other languages

See (Cxx)

Question

If you have a question about this example, please use the VTK Discourse Forum

Code

ColoredAnnotatedCube.py

#!/usr/bin/env python

# noinspection PyUnresolvedReferences
import vtkmodules.vtkInteractionStyle
# noinspection PyUnresolvedReferences
import vtkmodules.vtkRenderingOpenGL2
from vtkmodules.vtkCommonColor import (
    vtkColorSeries,
    vtkNamedColors
)
from vtkmodules.vtkCommonCore import (
    vtkLookupTable,
    vtkUnsignedCharArray
)
from vtkmodules.vtkCommonTransforms import vtkTransform
from vtkmodules.vtkFiltersCore import vtkElevationFilter
from vtkmodules.vtkFiltersGeneral import vtkTransformPolyDataFilter
from vtkmodules.vtkFiltersModeling import vtkBandedPolyDataContourFilter
from vtkmodules.vtkFiltersSources import (
    vtkConeSource,
    vtkCubeSource
)
from vtkmodules.vtkInteractionWidgets import vtkOrientationMarkerWidget
from vtkmodules.vtkRenderingAnnotation import (
    vtkAnnotatedCubeActor,
    vtkAxesActor
)
from vtkmodules.vtkRenderingCore import (
    vtkActor,
    vtkPolyDataMapper,
    vtkPropAssembly,
    vtkRenderWindow,
    vtkRenderWindowInteractor,
    vtkRenderer
)


def main():
    # Basic stuff setup
    # Set up the renderer, window, and interactor
    colors = vtkNamedColors()

    ren = vtkRenderer()
    renWin = vtkRenderWindow()
    renWin.AddRenderer(ren)
    renWin.SetSize(640, 480)
    iRen = vtkRenderWindowInteractor()
    iRen.SetRenderWindow(renWin)

    # Create a cone with an elliptical base whose major axis is in the
    # X-direction.
    coneSource = vtkConeSource()
    coneSource.SetCenter(0.0, 0.0, 0.0)
    coneSource.SetRadius(5.0)
    coneSource.SetHeight(15.0)
    coneSource.SetDirection(0, 1, 0)
    coneSource.SetResolution(60)
    coneSource.Update()

    transform = vtkTransform()
    transform.Scale(1.0, 1.0, 0.75)

    transF = vtkTransformPolyDataFilter()
    transF.SetInputConnection(coneSource.GetOutputPort())
    transF.SetTransform(transform)

    bounds = transF.GetOutput().GetBounds()

    elevation = vtkElevationFilter()
    elevation.SetInputConnection(transF.GetOutputPort())
    elevation.SetLowPoint(0, bounds[2], 0)
    elevation.SetHighPoint(0, bounds[3], 0)

    bandedContours = vtkBandedPolyDataContourFilter()
    bandedContours.SetInputConnection(elevation.GetOutputPort())
    bandedContours.SetScalarModeToValue()
    bandedContours.GenerateContourEdgesOn()
    bandedContours.GenerateValues(11, elevation.GetScalarRange())

    # Make a lookup table using a color series.
    colorSeries = vtkColorSeries()
    colorSeries.SetColorScheme(vtkColorSeries.BREWER_DIVERGING_SPECTRAL_11)

    lut = vtkLookupTable()
    colorSeries.BuildLookupTable(lut, vtkColorSeries.ORDINAL)

    coneMapper = vtkPolyDataMapper()
    coneMapper.SetInputConnection(bandedContours.GetOutputPort())
    coneMapper.SetScalarRange(elevation.GetScalarRange())
    coneMapper.SetLookupTable(lut)

    coneActor = vtkActor()
    coneActor.SetMapper(coneMapper)

    # Contouring
    contourLineMapper = vtkPolyDataMapper()
    contourLineMapper.SetInputData(bandedContours.GetContourEdgesOutput())
    contourLineMapper.SetScalarRange(elevation.GetScalarRange())
    contourLineMapper.SetResolveCoincidentTopologyToPolygonOffset()

    contourLineActor = vtkActor()
    contourLineActor.SetMapper(contourLineMapper)
    contourLineActor.GetProperty().SetColor(
        colors.GetColor3d('DimGray'))

    # Set up the Orientation Marker Widget.
    prop_assembly = MakeAnnotatedCubeActor(colors)
    om1 = vtkOrientationMarkerWidget()
    om1.SetOrientationMarker(prop_assembly)
    om1.SetInteractor(iRen)
    om1.SetDefaultRenderer(ren)
    om1.On()
    om1.InteractiveOn()

    xyzLabels = ['X', 'Y', 'Z']
    scale = [1.0, 1.0, 1.0]
    axes = MakeAxesActor(scale, xyzLabels)

    om2 = vtkOrientationMarkerWidget()
    om2.SetOrientationMarker(axes)
    # Position lower right in the viewport.
    om2.SetViewport(0.8, 0, 1.0, 0.2)
    om2.SetInteractor(iRen)
    om2.EnabledOn()
    om2.InteractiveOn()

    ren.AddActor(coneActor)
    ren.AddActor(contourLineActor)
    ren.SetBackground2(colors.GetColor3d('RoyalBlue'))
    ren.SetBackground(colors.GetColor3d('MistyRose'))
    ren.GradientBackgroundOn()
    ren.GetActiveCamera().Azimuth(45)
    ren.GetActiveCamera().Pitch(-22.5)
    ren.ResetCamera()

    renWin.SetSize(600, 600)
    renWin.Render()
    renWin.SetWindowName('ColoredAnnotatedCube')
    renWin.Render()
    iRen.Start()


def MakeAnnotatedCubeActor(colors):
    # Annotated Cube setup
    annotated_cube = vtkAnnotatedCubeActor()
    annotated_cube.SetFaceTextScale(0.366667)

    # Anatomic labeling
    annotated_cube.SetXPlusFaceText('X+')
    annotated_cube.SetXMinusFaceText('X-')
    annotated_cube.SetYPlusFaceText('Y+')
    annotated_cube.SetYMinusFaceText('Y-')
    annotated_cube.SetZPlusFaceText('Z+')
    annotated_cube.SetZMinusFaceText('Z-')

    # Change the vector text colors
    annotated_cube.GetTextEdgesProperty().SetColor(
        colors.GetColor3d('Black'))
    annotated_cube.GetTextEdgesProperty().SetLineWidth(1)

    annotated_cube.GetXPlusFaceProperty().SetColor(
        colors.GetColor3d('Turquoise'))
    annotated_cube.GetXMinusFaceProperty().SetColor(
        colors.GetColor3d('Turquoise'))
    annotated_cube.GetYPlusFaceProperty().SetColor(
        colors.GetColor3d('Mint'))
    annotated_cube.GetYMinusFaceProperty().SetColor(
        colors.GetColor3d('Mint'))
    annotated_cube.GetZPlusFaceProperty().SetColor(
        colors.GetColor3d('Tomato'))
    annotated_cube.GetZMinusFaceProperty().SetColor(
        colors.GetColor3d('Tomato'))
    annotated_cube.SetXFaceTextRotation(90)
    annotated_cube.SetYFaceTextRotation(180)
    annotated_cube.SetZFaceTextRotation(-90)
    # Make the annotated cube transparent
    annotated_cube.GetCubeProperty().SetOpacity(0)

    # Colored faces cube setup
    cube_source = vtkCubeSource()
    cube_source.Update()

    face_colors = vtkUnsignedCharArray()
    face_colors.SetNumberOfComponents(3)
    face_x_plus = colors.GetColor3ub('Red')
    face_x_minus = colors.GetColor3ub('Green')
    face_y_plus = colors.GetColor3ub('Blue')
    face_y_minus = colors.GetColor3ub('Yellow')
    face_z_plus = colors.GetColor3ub('Cyan')
    face_z_minus = colors.GetColor3ub('Magenta')
    face_colors.InsertNextTypedTuple(face_x_minus)
    face_colors.InsertNextTypedTuple(face_x_plus)
    face_colors.InsertNextTypedTuple(face_y_minus)
    face_colors.InsertNextTypedTuple(face_y_plus)
    face_colors.InsertNextTypedTuple(face_z_minus)
    face_colors.InsertNextTypedTuple(face_z_plus)

    cube_source.GetOutput().GetCellData().SetScalars(face_colors)
    cube_source.Update()

    cube_mapper = vtkPolyDataMapper()
    cube_mapper.SetInputData(cube_source.GetOutput())
    cube_mapper.Update()

    cube_actor = vtkActor()
    cube_actor.SetMapper(cube_mapper)

    # Assemble the colored cube and annotated cube texts into a composite prop.
    prop_assembly = vtkPropAssembly()
    prop_assembly.AddPart(annotated_cube)
    prop_assembly.AddPart(cube_actor)
    return prop_assembly


def MakeAxesActor(scale, xyzLabels):
    axes = vtkAxesActor()
    axes.SetScale(scale[0], scale[1], scale[2])
    axes.SetShaftTypeToCylinder()
    axes.SetXAxisLabelText(xyzLabels[0])
    axes.SetYAxisLabelText(xyzLabels[1])
    axes.SetZAxisLabelText(xyzLabels[2])
    axes.SetCylinderRadius(0.5 * axes.GetCylinderRadius())
    axes.SetConeRadius(1.025 * axes.GetConeRadius())
    axes.SetSphereRadius(1.5 * axes.GetSphereRadius())
    tprop = axes.GetXAxisCaptionActor2D().GetCaptionTextProperty()
    tprop.ItalicOn()
    tprop.ShadowOn()
    tprop.SetFontFamilyToTimes()
    # Use the same text properties on the other two axes.
    axes.GetYAxisCaptionActor2D().GetCaptionTextProperty().ShallowCopy(tprop)
    axes.GetZAxisCaptionActor2D().GetCaptionTextProperty().ShallowCopy(tprop)
    return axes


if __name__ == '__main__':
    main()