Skip to content

ClampGlyphSizes

vtk-examples/Python/Visualization/ClampGlyphSizes

Question

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

Code

ClampGlyphSizes.py

#!/usr/bin/env python

# Example of how to use range clamping with vtkGlyph3D filter.
#
# Note that the internal algorithm does this to figure out the eventual scale
# of your data (say, if you're scaling by a scalar or vector magnitude):
#
#   scale = (scalar value of that particular data index);
#   denominator = Range[1] - Range[0];
#   scale = (scale < Range[0] ? Range[0] : (scale > Range[1] ? Range[1] : scale));
#   scale = (scale - Range[0]) / denominator;
#   scale *= scaleFactor;
#
# So, step 4 is the unintuitive one. Say your data varies from [0, 1] and you set the
# Range to [0.5, 1]. Everything below 0.5 will be mapped to 0. If you want to set a
# minimum size to your glyphs, then you can set the Range as something like [-0.5, 1]


# noinspection PyUnresolvedReferences
import vtkmodules.vtkRenderingOpenGL2
from vtkmodules.vtkCommonColor import vtkNamedColors
from vtkmodules.vtkFiltersCore import (
    vtkElevationFilter,
    vtkGlyph3D
)
from vtkmodules.vtkFiltersSources import vtkConeSource
from vtkmodules.vtkImagingCore import vtkRTAnalyticSource
from vtkmodules.vtkImagingGeneral import vtkImageGradient
from vtkmodules.vtkInteractionStyle import vtkInteractorStyleTrackballCamera
from vtkmodules.vtkRenderingCore import (
    vtkActor,
    vtkPolyDataMapper,
    vtkRenderWindow,
    vtkRenderWindowInteractor,
    vtkRenderer
)


def main():
    colors = vtkNamedColors()

    # Generate an image data set with multiple attribute arrays to probe and view
    # We will glyph these points with cones and scale/orient/color them with the
    # various attributes

    # The Wavelet Source is nice for generating a test vtkImageData set
    rt = vtkRTAnalyticSource()
    rt.SetWholeExtent(-2, 2, -2, 2, 0, 0)

    # Take the gradient of the only scalar 'RTData' to get a vector attribute
    grad = vtkImageGradient()
    grad.SetDimensionality(3)
    grad.SetInputConnection(rt.GetOutputPort())

    # Elevation just to generate another scalar attribute that varies nicely over the data range
    elev = vtkElevationFilter()
    # Elevation values will range from 0 to 1 between the Low and High Points
    elev.SetLowPoint(-2, 0, 0)
    elev.SetHighPoint(2, 0, 0)
    elev.SetInputConnection(grad.GetOutputPort())

    # Generate the cone for the glyphs
    sph = vtkConeSource()
    sph.SetRadius(0.1)
    sph.SetHeight(0.5)

    # Set up the glyph filter
    glyph = vtkGlyph3D()
    glyph.SetInputConnection(elev.GetOutputPort())
    glyph.SetSourceConnection(sph.GetOutputPort())
    glyph.ScalingOn()
    glyph.SetScaleModeToScaleByScalar()
    glyph.SetVectorModeToUseVector()
    glyph.OrientOn()

    # Tell the filter to 'clamp' the scalar range
    glyph.ClampingOn()

    # Set the overall (multiplicative) scaling factor
    glyph.SetScaleFactor(1)

    # Set the Range to 'clamp' the data to
    #   -- see equations above for nonintuitive definition of 'clamping'
    # The fact that I'm setting the minimum value of the range below
    #   the minimum of my data (real min=0.0) with the equations above
    #   forces a minimum non-zero glyph size.

    glyph.SetRange(-0.5, 1)  # Change these values to see effect on cone sizes

    # Tell glyph which attribute arrays to use for what
    glyph.SetInputArrayToProcess(0, 0, 0, 0, 'Elevation')  # scalars
    glyph.SetInputArrayToProcess(1, 0, 0, 0, 'RTDataGradient')  # vectors
    # glyph.SetInputArrayToProcess(2,0,0,0,'nothing')       # normals
    glyph.SetInputArrayToProcess(3, 0, 0, 0, 'RTData')  # colors

    # Calling update because I'm going to use the scalar range to set the color map range
    glyph.Update()

    coloring_by = 'RTData'
    mapper = vtkPolyDataMapper()
    mapper.SetInputConnection(glyph.GetOutputPort())
    mapper.SetScalarModeToUsePointFieldData()
    mapper.SetColorModeToMapScalars()
    mapper.ScalarVisibilityOn()
    mapper.SetScalarRange(glyph.GetOutputDataObject(0).GetPointData().GetArray(coloring_by).GetRange())
    mapper.SelectColorArray(coloring_by)
    actor = vtkActor()
    actor.SetMapper(mapper)

    ren = vtkRenderer()
    ren.AddActor(actor)
    ren.SetBackground(colors.GetColor3d('MidnightBlue'))
    renWin = vtkRenderWindow()
    renWin.AddRenderer(ren)
    renWin.SetWindowName('ClampGlyphSizes')

    iren = vtkRenderWindowInteractor()
    istyle = vtkInteractorStyleTrackballCamera()
    iren.SetInteractorStyle(istyle)
    iren.SetRenderWindow(renWin)
    ren.ResetCamera()
    renWin.Render()
    iren.Start()


if __name__ == '__main__':
    main()