From 0f6d27487fe46d311dea1b69bf2bc24f389cc488 Mon Sep 17 00:00:00 2001 From: Andrew Maclean <andrew.amaclean@gmail.com> Date: Wed, 11 Dec 2024 15:58:14 +1100 Subject: [PATCH] Renaming Slider to Slider3D, adding Slider2D and Slider3D to Snippets --- src/Cxx.md | 2 +- src/Cxx/Widgets/Slider2D.md | 2 +- src/Cxx/Widgets/{Slider.cxx => Slider3D.cxx} | 9 +- src/Cxx/Widgets/{Slider.md => Slider3D.md} | 0 src/PythonicAPI.md | 2 +- src/PythonicAPI/Snippets.md | 2 + src/PythonicAPI/Snippets/Slider2D.md | 141 ++++++++++++ src/PythonicAPI/Snippets/Slider3D.md | 141 ++++++++++++ src/PythonicAPI/Widgets/Slider.py | 184 ---------------- src/PythonicAPI/Widgets/Slider2D.md | 2 +- src/PythonicAPI/Widgets/Slider2D.py | 174 ++++++++------- .../Widgets/{Slider.md => Slider3D.md} | 0 src/PythonicAPI/Widgets/Slider3D.py | 205 ++++++++++++++++++ .../Baseline/Cxx/Widgets/TestSlider.png | 3 - .../Baseline/Cxx/Widgets/TestSlider3D.png | 3 + .../PythonicAPI/Widgets/TestSlider.png | 3 - .../PythonicAPI/Widgets/TestSlider2D.png | 4 +- .../PythonicAPI/Widgets/TestSlider3D.png | 3 + 18 files changed, 602 insertions(+), 278 deletions(-) rename src/Cxx/Widgets/{Slider.cxx => Slider3D.cxx} (92%) rename src/Cxx/Widgets/{Slider.md => Slider3D.md} (100%) create mode 100644 src/PythonicAPI/Snippets/Slider2D.md create mode 100644 src/PythonicAPI/Snippets/Slider3D.md delete mode 100755 src/PythonicAPI/Widgets/Slider.py rename src/PythonicAPI/Widgets/{Slider.md => Slider3D.md} (100%) create mode 100755 src/PythonicAPI/Widgets/Slider3D.py delete mode 100644 src/Testing/Baseline/Cxx/Widgets/TestSlider.png create mode 100644 src/Testing/Baseline/Cxx/Widgets/TestSlider3D.png delete mode 100644 src/Testing/Baseline/PythonicAPI/Widgets/TestSlider.png create mode 100644 src/Testing/Baseline/PythonicAPI/Widgets/TestSlider3D.png diff --git a/src/Cxx.md b/src/Cxx.md index 854715db962..72448c46843 100644 --- a/src/Cxx.md +++ b/src/Cxx.md @@ -1359,8 +1359,8 @@ See [this tutorial](http://www.vtk.org/Wiki/VTK/Tutorials/3DDataTypes) for a bri [SeedWidget](/Cxx/Widgets/SeedWidget) | Seed widget. [SeedWidgetImage](/Cxx/Widgets/SeedWidgetImage) | How to start the interaction? [SeedWidgetWithCustomCallback](/Cxx/Widgets/SeedWidgetWithCustomCallback) | How to place points in a scene using a custom callback. -[Slider](/Cxx/Widgets/Slider) | 3D Slider. [Slider2D](/Cxx/Widgets/Slider2D) | 2D Slider. +[Slider3D](/Cxx/Widgets/Slider3D) | 3D Slider. [SphereWidget](/Cxx/Widgets/SphereWidget) | Sphere widget. [SphereWidget2](/Cxx/Widgets/SphereWidget2) | [SphereWidgetEvents](/Cxx/Widgets/SphereWidgetEvents) | Sphere widget events. diff --git a/src/Cxx/Widgets/Slider2D.md b/src/Cxx/Widgets/Slider2D.md index 4e62dda3070..e6d2ca1bb03 100644 --- a/src/Cxx/Widgets/Slider2D.md +++ b/src/Cxx/Widgets/Slider2D.md @@ -1,6 +1,6 @@ ### Description -This example demonstrates how to use a slider that is drawn in window coordinates - so if you move the scene the slider is not affected. Contrast this with the [3D slider widget](../Slider) that remains at a fixed location in the world coordinates. +This example demonstrates how to use a slider that is drawn in window coordinates - so if you move the scene the slider is not affected. Contrast this with the [3D slider widget](../Slider3D) that remains at a fixed location in the world coordinates. If the callback is connected to *InteractionEvent*, the scene will update immediately. This is not ideal if the re-rendering takes significant time as it will make the interaction very choppy. diff --git a/src/Cxx/Widgets/Slider.cxx b/src/Cxx/Widgets/Slider3D.cxx similarity index 92% rename from src/Cxx/Widgets/Slider.cxx rename to src/Cxx/Widgets/Slider3D.cxx index aa330d3877c..2fb6bddd7ac 100644 --- a/src/Cxx/Widgets/Slider.cxx +++ b/src/Cxx/Widgets/Slider3D.cxx @@ -67,7 +67,8 @@ int main(int, char*[]) vtkNew<vtkRenderer> renderer; vtkNew<vtkRenderWindow> renderWindow; renderWindow->AddRenderer(renderer); - renderWindow->SetWindowName("Slider"); + renderWindow->SetWindowName("Slider3D"); + renderWindow->SetSize(640, 480); // An interactor. vtkNew<vtkRenderWindowInteractor> renderWindowInteractor; @@ -85,10 +86,12 @@ int main(int, char*[]) sliderRep->SetMaximumValue(50.0); sliderRep->SetValue(sphereSource->GetThetaResolution()); sliderRep->SetTitleText("Sphere Resolution"); + sliderRep->SetTitleHeight(0.125); + sliderRep->SetLabelHeight(0.055); sliderRep->GetPoint1Coordinate()->SetCoordinateSystemToWorld(); - sliderRep->GetPoint1Coordinate()->SetValue(-4, 6, 0); + sliderRep->GetPoint1Coordinate()->SetValue(-4, 5.9, 0); sliderRep->GetPoint2Coordinate()->SetCoordinateSystemToWorld(); - sliderRep->GetPoint2Coordinate()->SetValue(4, 6, 0); + sliderRep->GetPoint2Coordinate()->SetValue(4, 5.9, 0); sliderRep->SetSliderLength(0.075); sliderRep->SetSliderWidth(0.05); sliderRep->SetEndCapLength(0.05); diff --git a/src/Cxx/Widgets/Slider.md b/src/Cxx/Widgets/Slider3D.md similarity index 100% rename from src/Cxx/Widgets/Slider.md rename to src/Cxx/Widgets/Slider3D.md diff --git a/src/PythonicAPI.md b/src/PythonicAPI.md index 2104f3da63f..4dea198edf1 100644 --- a/src/PythonicAPI.md +++ b/src/PythonicAPI.md @@ -699,8 +699,8 @@ See [this tutorial](http://www.vtk.org/Wiki/VTK/Tutorials/3DDataTypes) for a bri [ImplicitPlaneWidget2](/PythonicAPI/Widgets/ImplicitPlaneWidget2) | Clip polydata with an implicit plane. [PolygonalSurfacePointPlacer](/PythonicAPI/PolyData/PolygonalSurfacePointPlacer) | Used in conjunction with vtkContourWidget to draw curves on a surface. [RectilinearWipeWidget](/PythonicAPI/Widgets/RectilinearWipeWidget) | Compare two images. -[Slider](/PythonicAPI/Widgets/Slider) | 3D Slider. [Slider2D](/PythonicAPI/Widgets/Slider2D) | 2D Slider. +[Slider3D](/PythonicAPI/Widgets/Slider3D) | 3D Slider. [SphereWidget](/PythonicAPI/Widgets/SphereWidget) | This 3D widget defines a sphere that can be interactively placed in a scene. [SplineWidget](/PythonicAPI/Widgets/SplineWidget) | This example shows how to use vtkSplineWidget with a callback being used to get the length of the spline widget. diff --git a/src/PythonicAPI/Snippets.md b/src/PythonicAPI/Snippets.md index 0a20930873e..65e6bae2eed 100644 --- a/src/PythonicAPI/Snippets.md +++ b/src/PythonicAPI/Snippets.md @@ -15,5 +15,7 @@ Snippets are chunks of code that can be cut (*snipped*) and pasted into examples [PointToGlyph](/PythonicAPI/Snippets/PointToGlyph.md) | Represent points as glyphs. [ReadPolyData](/PythonicAPI/Snippets/ReadPolyData.md) | Uses the appropriate vtkPolyData reader to read any ?vtkPolyData? file. [ScreenShot](/PythonicAPI/Snippets/ScreenshotCallback.md) | Take a screenshot from the render window by pressing a key on the keyboard, the default key is "k". The file extension selects the writer to use. +[Slider2D](/PythonicAPI/Snippets/Slider2D.md) | Implement a 2D slider widget. +[Slider3D](/PythonicAPI/Snippets/Slider3D.md) | Implement a 3D slider widget. [VTKDataClasses](/PythonicAPI/Snippets/VTKDataClasses.md) | The VTK immutable data classes for constants. These are usually used in the initialization VTK classes or to replace the Set/Get functions that set and get these constants. [WriteImage](/PythonicAPI/Snippets/WriteImage.md) | Take a screenshot from the render window and write it to a file. The file extension selects the writer to use. diff --git a/src/PythonicAPI/Snippets/Slider2D.md b/src/PythonicAPI/Snippets/Slider2D.md new file mode 100644 index 00000000000..b4c955d4968 --- /dev/null +++ b/src/PythonicAPI/Snippets/Slider2D.md @@ -0,0 +1,141 @@ +### Description + +Implement a 2D slider widget. + +To use the snippet, click the *Copy to clipboard* at the upper right of the code blocks. + +### Implementation + +``` Python +# from dataclasses import dataclass +# from typing import Tuple + +# from vtkmodules.vtkInteractionWidgets import ( +# vtkSliderRepresentation2D, +# vtkSliderWidget +# ) + +def make_2d_slider_widget(properties, interactor): + """ + Make a 2D slider widget. + + :param properties: The 2D slider properties. + :param interactor: The vtkInteractor. + :return: The slider widget. + """ + colors = vtkNamedColors() + + slider_rep = vtkSliderRepresentation2D(minimum_value=properties.Range.minimum_value, + maximum_value=properties.Range.maximum_value, + value=properties.Range.value, + title_text=properties.title_text, + tube_width=properties.Dimensions.tube_width, + slider_length=properties.Dimensions.slider_length, + slider_width=properties.Dimensions.slider_width, + end_cap_length=properties.Dimensions.end_cap_length, + end_cap_width=properties.Dimensions.end_cap_width, + title_height=properties.Dimensions.title_height, + label_height=properties.Dimensions.label_height, + ) + + # Set the color properties. + slider_rep.title_property.color = colors.GetColor3d(properties.Colors.title_color) + slider_rep.label_property.color = colors.GetColor3d(properties.Colors.label_color) + slider_rep.tube_property.color = colors.GetColor3d(properties.Colors.bar_color) + slider_rep.cap_property.color = colors.GetColor3d(properties.Colors.bar_ends_color) + slider_rep.slider_property.color = colors.GetColor3d(properties.Colors.slider_color) + slider_rep.selected_property.color = colors.GetColor3d(properties.Colors.selected_color) + + # Set the position. + slider_rep.point1_coordinate.coordinate_system = properties.Position.coordinate_system + slider_rep.point1_coordinate.value = properties.Position.point1 + slider_rep.point2_coordinate.coordinate_system = properties.Position.coordinate_system + slider_rep.point2_coordinate.value = properties.Position.point2 + + widget = vtkSliderWidget(representation=slider_rep, interactor=interactor, enabled=True) + widget.SetAnimationModeToAnimate() + + return widget + + +@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 + + +@dataclass +class Slider2DProperties: + @dataclass + class Colors: + title_color: str = 'White' + label_color: str = 'White' + slider_color: str = 'White' + selected_color: str = 'HotPink' + bar_color: str = 'White' + bar_ends_color: str = 'White' + + @dataclass + class Dimensions: + tube_width: float = 0.008 + slider_length: float = 0.01 + slider_width: float = 0.02 + end_cap_length: float = 0.005 + end_cap_width: float = 0.05 + title_height: float = 0.03 + label_height: float = 0.025 + + @dataclass + class Position: + coordinate_system: int = Coordinate.CoordinateSystem.VTK_NORMALIZED_VIEWPORT + point1: Tuple = (0.1, 0.1) + point2: Tuple = (0.9, 0.1) + + @dataclass + class Range: + minimum_value: float = 0.0 + maximum_value: float = 1.0 + value: float = 0.0 + + title_text: str = '' + + +class SliderCallback: + + def __init__(self, source): + """ + """ + self.source = source + + def __call__(self, caller, ev): + slider_widget = caller + # Get the value and do something with it. + value = slider_widget.representation.value + self.source.something = value + +``` + +### Usage + +For an example showing the usage of this snippet and changing most of the default parameters, please see: [Slider2D](../../Widgets/Slider2D). + +``` Python + ... + sp = Slider2DProperties() + sp.title_text = 'Sphere Resolution' + sp.Range.minimum_value = 3 + ... + widget = make_slider_widget(sp, render_window_interactor) + cb = SliderCallback(sphere_source) + widget.AddObserver(vtkCommand.InteractionEvent, cb) + ... + +``` diff --git a/src/PythonicAPI/Snippets/Slider3D.md b/src/PythonicAPI/Snippets/Slider3D.md new file mode 100644 index 00000000000..5141ce229c0 --- /dev/null +++ b/src/PythonicAPI/Snippets/Slider3D.md @@ -0,0 +1,141 @@ +### Description + +Implement a 3D slider widget. + +To use the snippet, click the *Copy to clipboard* at the upper right of the code blocks. + +### Implementation + +``` Python +# from dataclasses import dataclass +# from typing import Tuple + +# from vtkmodules.vtkInteractionWidgets import ( +# vtkSliderRepresentation3D, +# vtkSliderWidget +# ) + +def make_3d_slider_widget(properties, interactor): + """ + Make a 3D slider widget. + + :param properties: The 3D slider properties. + :param interactor: The vtkInteractor. + :return: The slider widget. + """ + colors = vtkNamedColors() + + slider_rep = vtkSliderRepresentation3D(minimum_value=properties.Range.minimum_value, + maximum_value=properties.Range.maximum_value, + value=properties.Range.value, + title_text=properties.title_text, + tube_width=properties.Dimensions.tube_width, + slider_length=properties.Dimensions.slider_length, + slider_width=properties.Dimensions.slider_width, + end_cap_length=properties.Dimensions.end_cap_length, + end_cap_width=properties.Dimensions.end_cap_width, + title_height=properties.Dimensions.title_height, + label_height=properties.Dimensions.label_height, + ) + + # Set the color properties. + # slider_rep.title_property.color = colors.GetColor3d(properties.Colors.title_color) + # slider_rep.label_property.color = colors.GetColor3d(properties.Colors.label_color) + slider_rep.tube_property.color = colors.GetColor3d(properties.Colors.bar_color) + slider_rep.cap_property.color = colors.GetColor3d(properties.Colors.bar_ends_color) + slider_rep.slider_property.color = colors.GetColor3d(properties.Colors.slider_color) + slider_rep.selected_property.color = colors.GetColor3d(properties.Colors.selected_color) + + # Set the position. + slider_rep.point1_coordinate.coordinate_system = properties.Position.coordinate_system + slider_rep.point1_coordinate.value = properties.Position.point1 + slider_rep.point2_coordinate.coordinate_system = properties.Position.coordinate_system + slider_rep.point2_coordinate.value = properties.Position.point2 + + widget = vtkSliderWidget(representation=slider_rep, interactor=interactor, enabled=True) + widget.SetAnimationModeToAnimate() + + return widget + + +@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 + + +@dataclass +class Slider3DProperties: + @dataclass + class Colors: + title_color: str = 'White' + label_color: str = 'White' + slider_color: str = 'White' + selected_color: str = 'HotPink' + bar_color: str = 'White' + bar_ends_color: str = 'White' + + @dataclass + class Dimensions: + tube_width: float = 0.008 + slider_length: float = 0.01 + slider_width: float = 0.02 + end_cap_length: float = 0.005 + end_cap_width: float = 0.05 + title_height: float = 0.03 + label_height: float = 0.025 + + @dataclass + class Position: + coordinate_system: int = Coordinate.CoordinateSystem.VTK_WORLD + point1: Tuple = (0.1, 0.1, 0.0) + point2: Tuple = (0.9, 0.1, 0.0) + + @dataclass + class Range: + minimum_value: float = 0.0 + maximum_value: float = 1.0 + value: float = 0.0 + + title_text: str = '' + + +class SliderCallback: + + def __init__(self, source): + """ + """ + self.source = source + + def __call__(self, caller, ev): + slider_widget = caller + # Get the value and do something with it. + value = slider_widget.representation.value + self.source.something = value + +``` + +### Usage + +For an example showing the usage of this snippet and changing most of the default parameters, please see: [Slider3D](../../Widgets/Slider3D). + +``` Python + ... + sp = Slider2DProperties() + sp.title_text = 'Sphere Resolution' + sp.Range.minimum_value = 3 + ... + widget = make_slider_widget(sp, render_window_interactor) + cb = SliderCallback(sphere_source) + widget.AddObserver(vtkCommand.InteractionEvent, cb) + ... + +``` diff --git a/src/PythonicAPI/Widgets/Slider.py b/src/PythonicAPI/Widgets/Slider.py deleted file mode 100755 index eded383db81..00000000000 --- a/src/PythonicAPI/Widgets/Slider.py +++ /dev/null @@ -1,184 +0,0 @@ -#!/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.vtkCommonCore import vtkCommand -from vtkmodules.vtkFiltersSources import vtkSphereSource -from vtkmodules.vtkInteractionWidgets import ( - vtkSliderRepresentation3D, - vtkSliderWidget -) -from vtkmodules.vtkRenderingCore import ( - vtkActor, - vtkPolyDataMapper, - vtkRenderWindow, - vtkRenderWindowInteractor, - vtkRenderer -) - - -def main(): - colors = vtkNamedColors() - - # A sphere. - phi_resolution = 4 - sphere_source = vtkSphereSource(center=(0.0, 0.0, 0.0), radius=4.0, - phi_resolution=phi_resolution, - theta_resolution=phi_resolution * 2) - - mapper = vtkPolyDataMapper() - sphere_source >> mapper - - actor = vtkActor(mapper=mapper) - actor.property.SetInterpolationToFlat() - actor.property.color = colors.GetColor3d('MistyRose') - actor.property.edge_color = colors.GetColor3d('Tomato') - actor.property.edge_visibility = True - - # A renderer and render window. - renderer = vtkRenderer(background=colors.GetColor3d('SlateGray')) - render_window = vtkRenderWindow(size=(640, 480), window_name='Slider') - render_window.AddRenderer(renderer) - - # An interactor. - render_window_interactor = vtkRenderWindowInteractor() - render_window_interactor.render_window = render_window - - # Add the actors to the scene. - renderer.AddActor(actor) - - # Render an image (lights and cameras are created automatically). - render_window.Render() - - sp = SliderProperties() - sp.title_text = 'Sphere Resolution' - sp.range['minimum_value'] = 3 - sp.range['maximum_value'] = 50 - sp.range['value'] = phi_resolution - sp.position['point1'] = (-4.0, 5.9, 0.0) - sp.position['point2'] = (4, 5.9, 0) - sp.dimensions['slider_length'] = 0.075 - sp.dimensions['slider_width'] = 0.05 - sp.dimensions['end_cap_length'] = 0.05 - sp.dimensions['title_height'] = 0.125 - sp.dimensions['label_height'] = 0.055 - # Set color properties: - # Change the color of the knob that slides. - sp.colors['slider_color'] = 'Green' - # Change the color of the text indicating what the slider controls. - sp.colors['title_color'] = 'AliceBlue' - # Change the color of the text displaying the value. - sp.colors['label_color'] = 'AliceBlue' - # Change the color of the knob when the mouse is held on it. - sp.colors['selected_color'] = 'DeepPink' - # Change the color of the bar. - sp.colors['bar_color'] = 'MistyRose' - # Change the color of the ends of the bar. - sp.colors['bar_ends_color'] = 'Yellow' - - widget = make_slider_widget(sp, render_window_interactor) - cb = SliderCallback(sphere_source) - widget.AddObserver(vtkCommand.InteractionEvent, cb) - - renderer.Render() - renderer.active_camera.Dolly(0.9) - render_window_interactor.Initialize() - render_window.Render() - - render_window_interactor.Start() - - -class SliderProperties: - dimensions = { - 'tube_width': 0.025, - 'slider_length': 0.05, 'slider_width': 0.05, - 'end_cap_length': 0.025, 'end_cap_width': 0.05, - 'title_height': 0.15, 'label_height': 0.05, - } - colors = { - 'title_color': 'AliceBlue', 'label_color': 'AliceBlue', 'slider_color': 'peacock', - 'selected_color': 'hot_pink', 'bar_color': 'Black', 'bar_ends_color': 'Indigo', - 'value_color': 'DarkSlateGray' - } - range = {'minimum_value': 0.0, 'maximum_value': 1.0, 'value': 0.0} - title_text = '', - position = {'point1': (-15.0, -40.0, 0.0), 'point2': (15.0, -40.0, 0.0)} - - -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 = vtkSliderRepresentation3D(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_WORLD - slider_rep.point1_coordinate.value = slider_properties.position['point1'] - slider_rep.point2_coordinate.coordinate_system = Coordinate.CoordinateSystem.VTK_WORLD - slider_rep.point2_coordinate.value = slider_properties.position['point2'] - - widget = vtkSliderWidget(representation=slider_rep, interactor=interactor, enabled=True) - widget.SetAnimationModeToAnimate() - - return widget - - -class SliderCallback: - - def __init__(self, sphere_source): - """ - """ - self.sphere_source = sphere_source - - def __call__(self, caller, ev): - slider_widget = caller - value = int(slider_widget.representation.value) - self.sphere_source.phi_resolution = value - self.sphere_source.theta_resolution = value * 2 - - -@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() diff --git a/src/PythonicAPI/Widgets/Slider2D.md b/src/PythonicAPI/Widgets/Slider2D.md index 4e62dda3070..e6d2ca1bb03 100644 --- a/src/PythonicAPI/Widgets/Slider2D.md +++ b/src/PythonicAPI/Widgets/Slider2D.md @@ -1,6 +1,6 @@ ### Description -This example demonstrates how to use a slider that is drawn in window coordinates - so if you move the scene the slider is not affected. Contrast this with the [3D slider widget](../Slider) that remains at a fixed location in the world coordinates. +This example demonstrates how to use a slider that is drawn in window coordinates - so if you move the scene the slider is not affected. Contrast this with the [3D slider widget](../Slider3D) that remains at a fixed location in the world coordinates. If the callback is connected to *InteractionEvent*, the scene will update immediately. This is not ideal if the re-rendering takes significant time as it will make the interaction very choppy. diff --git a/src/PythonicAPI/Widgets/Slider2D.py b/src/PythonicAPI/Widgets/Slider2D.py index c6b55a8420c..5c397b86656 100644 --- a/src/PythonicAPI/Widgets/Slider2D.py +++ b/src/PythonicAPI/Widgets/Slider2D.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 from dataclasses import dataclass +from typing import Tuple # noinspection PyUnresolvedReferences import vtkmodules.vtkInteractionStyle @@ -26,10 +27,7 @@ def main(): colors = vtkNamedColors() # A sphere. - phi_resolution = 4 - sphere_source = vtkSphereSource(center=(0.0, 0.0, 0.0), radius=4.0, - phi_resolution=phi_resolution, - theta_resolution=phi_resolution * 2) + sphere_source = vtkSphereSource(center=(0.0, 0.0, 0.0), radius=4.0) mapper = vtkPolyDataMapper() sphere_source >> mapper @@ -55,33 +53,33 @@ def main(): # Render an image (lights and cameras are created automatically). render_window.Render() - sp = SliderProperties() + sp = Slider2DProperties() sp.title_text = 'Sphere Resolution' - sp.range['minimum_value'] = 3 - sp.range['maximum_value'] = 50 - sp.range['value'] = phi_resolution - sp.position['point1'] = (0.3, 0.1) - sp.position['point2'] = (0.7, 0.1) - sp.dimensions['slider_length'] = 0.05 - sp.dimensions['slider_width'] = 0.025 - sp.dimensions['end_cap_length'] = 0.02 - sp.dimensions['title_height'] = 0.045 - sp.dimensions['label_height'] = 0.035 + sp.Range.minimum_value = 3 + sp.Range.maximum_value = 20 + sp.Range.value = 5 + sp.Position.point1 = (0.3, 0.1) + sp.Position.point2 = (0.7, 0.1) + sp.Dimensions.slider_length = 0.05 + sp.Dimensions.slider_width = 0.025 + sp.Dimensions.end_cap_length = 0.02 + sp.Dimensions.title_height = 0.045 + sp.Dimensions.label_height = 0.035 # Set color properties: # Change the color of the knob that slides. - sp.colors['slider_color'] = 'Green' + sp.Colors.slider_color = 'Green' # Change the color of the text indicating what the slider controls. - sp.colors['title_color'] = 'AliceBlue' + sp.Colors.title_color = 'AliceBlue' # Change the color of the text displaying the value. - sp.colors['label_color'] = 'AliceBlue' + sp.Colors.label_color = 'AliceBlue' # Change the color of the knob when the mouse is held on it. - sp.colors['selected_color'] = 'DeepPink' + sp.Colors.selected_color = 'DeepPink' # Change the color of the bar. - sp.colors['bar_color'] = 'MistyRose' + sp.Colors.bar_color = 'MistyRose' # Change the color of the ends of the bar. - sp.colors['bar_ends_color'] = 'Yellow' + sp.Colors.bar_ends_color = 'Yellow' - widget = make_slider_widget(sp, render_window_interactor) + widget = make_2d_slider_widget(sp, render_window_interactor) cb = SliderCallback(sphere_source) widget.AddObserver(vtkCommand.InteractionEvent, cb) @@ -93,60 +91,42 @@ def main(): render_window_interactor.Start() -class SliderProperties: +def make_2d_slider_widget(properties, interactor): """ - 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. + Make a 2D slider widget. + + :param properties: The 2D slider properties. :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'], + slider_rep = vtkSliderRepresentation2D(minimum_value=properties.Range.minimum_value, + maximum_value=properties.Range.maximum_value, + value=properties.Range.value, + title_text=properties.title_text, + tube_width=properties.Dimensions.tube_width, + slider_length=properties.Dimensions.slider_length, + slider_width=properties.Dimensions.slider_width, + end_cap_length=properties.Dimensions.end_cap_length, + end_cap_width=properties.Dimensions.end_cap_width, + title_height=properties.Dimensions.title_height, + label_height=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']) + slider_rep.title_property.color = colors.GetColor3d(properties.Colors.title_color) + slider_rep.label_property.color = colors.GetColor3d(properties.Colors.label_color) + slider_rep.tube_property.color = colors.GetColor3d(properties.Colors.bar_color) + slider_rep.cap_property.color = colors.GetColor3d(properties.Colors.bar_ends_color) + slider_rep.slider_property.color = colors.GetColor3d(properties.Colors.slider_color) + slider_rep.selected_property.color = colors.GetColor3d(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'] + slider_rep.point1_coordinate.coordinate_system = properties.Position.coordinate_system + slider_rep.point1_coordinate.value = properties.Position.point1 + slider_rep.point2_coordinate.coordinate_system = properties.Position.coordinate_system + slider_rep.point2_coordinate.value = properties.Position.point2 widget = vtkSliderWidget(representation=slider_rep, interactor=interactor, enabled=True) widget.SetAnimationModeToAnimate() @@ -154,20 +134,6 @@ def make_slider_widget(slider_properties, interactor): return widget -class SliderCallback: - - def __init__(self, sphere_source): - """ - """ - self.sphere_source = sphere_source - - def __call__(self, caller, ev): - slider_widget = caller - value = int(slider_widget.representation.value) - self.sphere_source.phi_resolution = value - self.sphere_source.theta_resolution = value * 2 - - @dataclass(frozen=True) class Coordinate: @dataclass(frozen=True) @@ -182,5 +148,55 @@ class Coordinate: VTK_USERDEFINED: int = 7 +@dataclass +class Slider2DProperties: + @dataclass + class Colors: + title_color: str = 'White' + label_color: str = 'White' + slider_color: str = 'White' + selected_color: str = 'HotPink' + bar_color: str = 'White' + bar_ends_color: str = 'White' + + @dataclass + class Dimensions: + tube_width: float = 0.008 + slider_length: float = 0.01 + slider_width: float = 0.02 + end_cap_length: float = 0.005 + end_cap_width: float = 0.05 + title_height: float = 0.03 + label_height: float = 0.025 + + @dataclass + class Position: + coordinate_system: int = Coordinate.CoordinateSystem.VTK_NORMALIZED_VIEWPORT + point1: Tuple = (0.1, 0.1) + point2: Tuple = (0.9, 0.1) + + @dataclass + class Range: + minimum_value: float = 0.0 + maximum_value: float = 1.0 + value: float = 0.0 + + title_text: str = '' + + +class SliderCallback: + + def __init__(self, sphere_source): + """ + """ + self.sphere_source = sphere_source + + def __call__(self, caller, ev): + slider_widget = caller + value = int(slider_widget.representation.value) + self.sphere_source.phi_resolution = value + self.sphere_source.theta_resolution = value * 2 + + if __name__ == '__main__': main() diff --git a/src/PythonicAPI/Widgets/Slider.md b/src/PythonicAPI/Widgets/Slider3D.md similarity index 100% rename from src/PythonicAPI/Widgets/Slider.md rename to src/PythonicAPI/Widgets/Slider3D.md diff --git a/src/PythonicAPI/Widgets/Slider3D.py b/src/PythonicAPI/Widgets/Slider3D.py new file mode 100755 index 00000000000..fe7a34afd6c --- /dev/null +++ b/src/PythonicAPI/Widgets/Slider3D.py @@ -0,0 +1,205 @@ +#!/usr/bin/env python3 + +from dataclasses import dataclass +from typing import Tuple + +# noinspection PyUnresolvedReferences +import vtkmodules.vtkInteractionStyle +# noinspection PyUnresolvedReferences +import vtkmodules.vtkRenderingOpenGL2 +from vtkmodules.vtkCommonColor import vtkNamedColors +from vtkmodules.vtkCommonCore import vtkCommand +from vtkmodules.vtkFiltersSources import vtkSphereSource +from vtkmodules.vtkInteractionWidgets import ( + vtkSliderRepresentation3D, + vtkSliderWidget +) +from vtkmodules.vtkRenderingCore import ( + vtkActor, + vtkPolyDataMapper, + vtkRenderWindow, + vtkRenderWindowInteractor, + vtkRenderer +) + + +def main(): + colors = vtkNamedColors() + + # A sphere. + phi_resolution = 4 + sphere_source = vtkSphereSource(center=(0.0, 0.0, 0.0), radius=4.0, + phi_resolution=phi_resolution, + theta_resolution=phi_resolution * 2) + + mapper = vtkPolyDataMapper() + sphere_source >> mapper + + actor = vtkActor(mapper=mapper) + actor.property.SetInterpolationToFlat() + actor.property.color = colors.GetColor3d('MistyRose') + actor.property.edge_color = colors.GetColor3d('Tomato') + actor.property.edge_visibility = True + + # A renderer and render window. + renderer = vtkRenderer(background=colors.GetColor3d('SlateGray')) + render_window = vtkRenderWindow(size=(640, 480), window_name='Slider3D') + render_window.AddRenderer(renderer) + + # An interactor. + render_window_interactor = vtkRenderWindowInteractor() + render_window_interactor.render_window = render_window + + # Add the actors to the scene. + renderer.AddActor(actor) + + # Render an image (lights and cameras are created automatically). + render_window.Render() + + sp = Slider3DProperties() + sp.title_text = 'Sphere Resolution' + sp.Range.minimum_value = 3 + sp.Range.maximum_value = 50 + sp.Range.value = sphere_source.theta_resolution + sp.Position.point1 = (-4.0, 5.9, 0.0) + sp.Position.point2 = (4, 5.9, 0) + sp.Dimensions.slider_length = 0.075 + sp.Dimensions.slider_width = 0.05 + sp.Dimensions.end_cap_length = 0.05 + sp.Dimensions.title_height = 0.125 + sp.Dimensions.label_height = 0.055 + # Set color properties: + # Change the color of the knob that slides. + sp.Colors.slider_color = 'Green' + # Change the color of the text indicating what the slider controls. + sp.Colors.title_color = 'AliceBlue' + # Change the color of the text displaying the value. + sp.Colors.label_color = 'AliceBlue' + # Change the color of the knob when the mouse is held on it. + sp.Colors.selected_color = 'DeepPink' + # Change the color of the bar. + sp.Colors.bar_color = 'MistyRose' + # Change the color of the ends of the bar. + sp.Colors.bar_ends_color = 'Yellow' + + widget = make_3d_slider_widget(sp, render_window_interactor) + cb = SliderCallback(sphere_source) + widget.AddObserver(vtkCommand.InteractionEvent, cb) + + renderer.Render() + renderer.active_camera.Dolly(0.9) + render_window_interactor.Initialize() + render_window.Render() + + render_window_interactor.Start() + + +def make_3d_slider_widget(properties, interactor): + """ + Make a 3D slider widget. + + :param properties: The 3D slider properties. + :param interactor: The vtkInteractor. + :return: The slider widget. + """ + colors = vtkNamedColors() + + slider_rep = vtkSliderRepresentation3D(minimum_value=properties.Range.minimum_value, + maximum_value=properties.Range.maximum_value, + value=properties.Range.value, + title_text=properties.title_text, + tube_width=properties.Dimensions.tube_width, + slider_length=properties.Dimensions.slider_length, + slider_width=properties.Dimensions.slider_width, + end_cap_length=properties.Dimensions.end_cap_length, + end_cap_width=properties.Dimensions.end_cap_width, + title_height=properties.Dimensions.title_height, + label_height=properties.Dimensions.label_height, + ) + + # Set the color properties. + # slider_rep.title_property.color = colors.GetColor3d(properties.Colors.title_color) + # slider_rep.label_property.color = colors.GetColor3d(properties.Colors.label_color) + slider_rep.tube_property.color = colors.GetColor3d(properties.Colors.bar_color) + slider_rep.cap_property.color = colors.GetColor3d(properties.Colors.bar_ends_color) + slider_rep.slider_property.color = colors.GetColor3d(properties.Colors.slider_color) + slider_rep.selected_property.color = colors.GetColor3d(properties.Colors.selected_color) + + # Set the position. + slider_rep.point1_coordinate.coordinate_system = properties.Position.coordinate_system + slider_rep.point1_coordinate.value = properties.Position.point1 + slider_rep.point2_coordinate.coordinate_system = properties.Position.coordinate_system + slider_rep.point2_coordinate.value = properties.Position.point2 + + widget = vtkSliderWidget(representation=slider_rep, interactor=interactor, enabled=True) + widget.SetAnimationModeToAnimate() + + return widget + + +@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 + + +@dataclass +class Slider3DProperties: + @dataclass + class Colors: + title_color: str = 'White' + label_color: str = 'White' + slider_color: str = 'White' + selected_color: str = 'HotPink' + bar_color: str = 'White' + bar_ends_color: str = 'White' + + @dataclass + class Dimensions: + tube_width: float = 0.008 + slider_length: float = 0.01 + slider_width: float = 0.02 + end_cap_length: float = 0.005 + end_cap_width: float = 0.05 + title_height: float = 0.03 + label_height: float = 0.025 + + @dataclass + class Position: + coordinate_system: int = Coordinate.CoordinateSystem.VTK_WORLD + point1: Tuple = (0.1, 0.1, 0.0) + point2: Tuple = (0.9, 0.1, 0.0) + + @dataclass + class Range: + minimum_value: float = 0.0 + maximum_value: float = 1.0 + value: float = 0.0 + + title_text: str = '' + + +class SliderCallback: + + def __init__(self, sphere_source): + """ + """ + self.sphere_source = sphere_source + + def __call__(self, caller, ev): + slider_widget = caller + value = int(slider_widget.representation.value) + self.sphere_source.phi_resolution = value // 2 + self.sphere_source.theta_resolution = value + + +if __name__ == '__main__': + main() diff --git a/src/Testing/Baseline/Cxx/Widgets/TestSlider.png b/src/Testing/Baseline/Cxx/Widgets/TestSlider.png deleted file mode 100644 index d4ac2b9165e..00000000000 --- a/src/Testing/Baseline/Cxx/Widgets/TestSlider.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4d52a5d71815dad486c2782b5cb60ca2f1e49f6602e81974d0dcdcb75bbf1cbf -size 8649 diff --git a/src/Testing/Baseline/Cxx/Widgets/TestSlider3D.png b/src/Testing/Baseline/Cxx/Widgets/TestSlider3D.png new file mode 100644 index 00000000000..627a8c8d05c --- /dev/null +++ b/src/Testing/Baseline/Cxx/Widgets/TestSlider3D.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4fe16555dc1f23e71d90bb4e8f5b9dffb122abe959eedacb8482bec10e237928 +size 14715 diff --git a/src/Testing/Baseline/PythonicAPI/Widgets/TestSlider.png b/src/Testing/Baseline/PythonicAPI/Widgets/TestSlider.png deleted file mode 100644 index 03dffe74b4d..00000000000 --- a/src/Testing/Baseline/PythonicAPI/Widgets/TestSlider.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a5f52daf0f3e9bdca5d77df62817f759e6594f888fe8f6ae93eb71f840d6c412 -size 14358 diff --git a/src/Testing/Baseline/PythonicAPI/Widgets/TestSlider2D.png b/src/Testing/Baseline/PythonicAPI/Widgets/TestSlider2D.png index b909e67a26f..6617e685e9d 100644 --- a/src/Testing/Baseline/PythonicAPI/Widgets/TestSlider2D.png +++ b/src/Testing/Baseline/PythonicAPI/Widgets/TestSlider2D.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c303d81b77bcbe1195d6d6e0daec9e4ddcb8dbbfce4501f840b60354a7208322 -size 15307 +oid sha256:b0a7d5af981bb697b5abc1c2a8f8fc65e2c2522cbd8adc623487adc99a95512b +size 35585 diff --git a/src/Testing/Baseline/PythonicAPI/Widgets/TestSlider3D.png b/src/Testing/Baseline/PythonicAPI/Widgets/TestSlider3D.png new file mode 100644 index 00000000000..25b718b09db --- /dev/null +++ b/src/Testing/Baseline/PythonicAPI/Widgets/TestSlider3D.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bf9cf67b5aab02e2a5ff6eda784be563903cfa182ac82798dcc9c9dcf512c3f2 +size 14542 -- GitLab