ParametricKuenDemo
Repository source: ParametricKuenDemo
Description¶
The example shows interaction with the vtkParametricKuen vtkParametricFunctionSource. The Kuen Surface This surface of constant Gaussian curvature K = -1 was discovered early. It is very popular because of its beauty.
Here's the embedded video:
Question
If you have a question about this example, please use the VTK Discourse Forum
Code¶
ParametricKuenDemo.py
#!/usr/bin/env python3
from dataclasses import dataclass
# noinspection PyUnresolvedReferences
import vtkmodules.vtkInteractionStyle
# noinspection PyUnresolvedReferences
import vtkmodules.vtkRenderingOpenGL2
from vtkmodules.vtkCommonColor import vtkNamedColors
from vtkmodules.vtkCommonComputationalGeometry import vtkParametricKuen
from vtkmodules.vtkCommonCore import (
vtkCommand,
vtkMath
)
from vtkmodules.vtkFiltersSources import vtkParametricFunctionSource
from vtkmodules.vtkInteractionWidgets import (
vtkSliderRepresentation2D,
vtkSliderWidget
)
from vtkmodules.vtkRenderingCore import (
vtkActor,
vtkPolyDataMapper,
vtkProperty,
vtkRenderWindow,
vtkRenderWindowInteractor,
vtkRenderer
)
def main():
colors = vtkNamedColors()
colors.SetColor('BkgColor', (26, 51, 102, 255))
# Create a parametric function source, renderer, mapper, and actor
surface = vtkParametricKuen(minimum_u=-4.5, maximum_u=4.5, minimum_v=0.05, maximum_v=vtkMath.Pi() - 0.05)
source = vtkParametricFunctionSource(parametric_function=surface)
mapper = vtkPolyDataMapper()
source >> mapper
back_property = vtkProperty(color=colors.GetColor3d('Tomato'))
actor = vtkActor(mapper=mapper, backface_property=back_property)
actor.property.diffuse_color = colors.GetColor3d('Banana')
actor.property.specular = 0.5
actor.property.specular_power = 20
renderer = vtkRenderer(background=colors.GetColor3d('BkgColor'))
renderer.AddActor(actor)
render_window = vtkRenderWindow(size=(640, 480), window_name='ParametricKuenDemo')
render_window.AddRenderer(renderer)
interactor = vtkRenderWindowInteractor()
interactor.render_window = render_window
# Setup a slider widget for each varying parameter.
slider_properties = SliderProperties()
# Setup a slider widget for each varying parameter.
slider_properties.title_text = 'U min'
slider_properties.range['maximum_value'] = 4.5
slider_properties.range['minimum_value'] = -4.5
slider_properties.range['value'] = -4.5
slider_properties.dimensions['tube_width'] = 0.008
slider_properties.dimensions['slider_length'] = 0.008
slider_properties.dimensions['label_height'] = 0.02
slider_properties.dimensions['title_height'] = 0.02
slider_properties.position = {'point1': (0.1, 0.1), 'point2': (0.9, 0.1)}
slider_widget_minimum_u = make_slider_widget(slider_properties, interactor)
slider_widget_minimum_u.AddObserver(vtkCommand.InteractionEvent, SliderCallbackMinimumU(surface))
slider_properties.title_text = 'U max'
slider_properties.range['value'] = 4.5
slider_properties.position = {'point1': (0.1, 0.9), 'point2': (0.9, 0.9)}
slider_widget_maximum_u = make_slider_widget(slider_properties, interactor)
slider_widget_maximum_u.AddObserver(vtkCommand.InteractionEvent, SliderCallbackMaximumU(surface))
slider_properties.title_text = 'V min'
slider_properties.range['maximum_value'] = vtkMath.Pi() - 0.05
slider_properties.range['minimum_value'] = 0.05
slider_properties.range['value'] = 0.05
slider_properties.position = {'point1': (0.1, 0.1), 'point2': (0.1, 0.9)}
slider_widget_minimum_v = make_slider_widget(slider_properties, interactor)
slider_widget_minimum_v.AddObserver(vtkCommand.InteractionEvent, SliderCallbackMaximumU(surface))
slider_properties.title_text = 'V max'
slider_properties.range['value'] = vtkMath.Pi() - 0.05
slider_properties.position = {'point1': (0.9, 0.1), 'point2': (0.9, 0.9)}
slider_widget_maximum_v = make_slider_widget(slider_properties, interactor)
slider_widget_maximum_v.AddObserver(vtkCommand.InteractionEvent, SliderCallbackMaximumU(surface))
render_window.Render()
renderer.active_camera.Azimuth(60)
renderer.active_camera.Elevation(-60)
renderer.active_camera.Zoom(0.9)
renderer.ResetCameraClippingRange()
interactor.Initialize()
interactor.Start()
class SliderProperties:
"""
These are default values.
"""
dimensions = {
'tube_width': 0.008,
'slider_length': 0.01, 'slider_width': 0.02,
'end_cap_length': 0.005, 'end_cap_width': 0.05,
'title_height': 0.03, 'label_height': 0.025,
}
colors = {
'title_color': 'White', 'label_color': 'White', 'slider_color': 'White',
'selected_color': 'HotPink', 'bar_color': 'White', 'bar_ends_color': 'White',
}
range = {'minimum_value': 0.0, 'maximum_value': 1.0, 'value': 0.0}
title_text = '',
position = {'point1': (0.1, 0.1), 'point2': (0.9, 0.1)}
def make_slider_widget(slider_properties, interactor):
"""
Make a slider widget.
:param slider_properties: range, title name, dimensions, colors, and position.
:param interactor: The vtkInteractor.
:return: The slider widget.
"""
colors = vtkNamedColors()
slider_rep = vtkSliderRepresentation2D(minimum_value=slider_properties.range['minimum_value'],
maximum_value=slider_properties.range['maximum_value'],
value=slider_properties.range['value'],
title_text=slider_properties.title_text,
tube_width=slider_properties.dimensions['tube_width'],
slider_length=slider_properties.dimensions['slider_length'],
slider_width=slider_properties.dimensions['slider_width'],
end_cap_length=slider_properties.dimensions['end_cap_length'],
end_cap_width=slider_properties.dimensions['end_cap_width'],
title_height=slider_properties.dimensions['title_height'],
label_height=slider_properties.dimensions['label_height'],
)
# Set the color properties.
slider_rep.title_property.color = colors.GetColor3d(slider_properties.colors['title_color'])
slider_rep.label_property.color = colors.GetColor3d(slider_properties.colors['label_color'])
slider_rep.tube_property.color = colors.GetColor3d(slider_properties.colors['bar_color'])
slider_rep.cap_property.color = colors.GetColor3d(slider_properties.colors['bar_ends_color'])
slider_rep.slider_property.color = colors.GetColor3d(slider_properties.colors['slider_color'])
slider_rep.selected_property.color = colors.GetColor3d(slider_properties.colors['selected_color'])
# Set the position.
slider_rep.point1_coordinate.coordinate_system = Coordinate.CoordinateSystem.VTK_NORMALIZED_VIEWPORT
slider_rep.point1_coordinate.value = slider_properties.position['point1']
slider_rep.point2_coordinate.coordinate_system = Coordinate.CoordinateSystem.VTK_NORMALIZED_VIEWPORT
slider_rep.point2_coordinate.value = slider_properties.position['point2']
widget = vtkSliderWidget(representation=slider_rep, interactor=interactor, enabled=True)
widget.SetAnimationModeToAnimate()
return widget
# These callbacks do the actual work.
# Callbacks for the interactions
class SliderCallbackMinimumU:
def __init__(self, kuen):
self.kuen = kuen
def __call__(self, caller, ev):
sliderWidget = caller
value = sliderWidget.representation.value
if value > 0.99 * self.kuen.maximum_u:
value = self.kuen.maximum_u
sliderWidget.GetRepresentation().value = value
self.kuen.minimum_u = value
class SliderCallbackMaximumU:
def __init__(self, kuen):
self.kuen = kuen
def __call__(self, caller, ev):
sliderWidget = caller
value = sliderWidget.representation.value
if value < self.kuen.minimum_u + .01:
value = self.kuen.minimum_u
sliderWidget.GetRepresentation().value = value
self.kuen.maximum_u = value
class SliderCallbackMinimumV:
def __init__(self, kuen):
self.kuen = kuen
def __call__(self, caller, ev):
sliderWidget = caller
value = sliderWidget.representation.value
if value > 0.99 * self.kuen.maximum_v:
value = self.kuen.maximum_v
sliderWidget.GetRepresentation().value = value
self.kuen.minimum_v = value
class SliderCallbackMaximumV():
def __init__(self, kuen):
self.kuen = kuen
def __call__(self, caller, ev):
slider_widget = caller
value = slider_widget.representation.value
if value < self.kuen.minimum_v + .01:
value = self.kuen.minimum_v
slider_widget.GetRepresentation().value = value
self.kuen.maximum_v = value
@dataclass(frozen=True)
class Coordinate:
@dataclass(frozen=True)
class CoordinateSystem:
VTK_DISPLAY: int = 0
VTK_NORMALIZED_DISPLAY: int = 1
VTK_VIEWPORT: int = 2
VTK_NORMALIZED_VIEWPORT: int = 3
VTK_VIEW: int = 4
VTK_POSE: int = 5
VTK_WORLD: int = 6
VTK_USERDEFINED: int = 7
if __name__ == '__main__':
main()