├── .gitignore
├── LICENSE
├── README.md
├── data
├── exodus
│ └── tetrahedron.exo
├── objs
│ └── cube.obj
├── open_foam
│ └── temp.case
├── stls
│ ├── ahmed_body.stl
│ ├── airfoil.stl
│ ├── cube.stl
│ ├── naca0012.stl
│ └── naca0012_meshed.stl
├── vtks
│ ├── cube_polydata.vtk
│ ├── grid_of_mixed_types.vtk
│ ├── grid_of_triangles.vtk
│ ├── polydata_line.vtk
│ └── texture_map.vtk
├── vtms
│ ├── grid_of_triangles.vtm
│ └── grid_of_triangles
│ │ └── grid_of_triangles_0.vtu
├── vtps
│ └── naca0012.vtp
└── vtus
│ └── grid_of_triangles.vtu
├── notes
├── 01_data_types_and_structures.md
├── 02_filters_and_algorithms.md
├── 03_input_and_output.md
├── 04_visualization_techniques.md
├── 05_interactivity.md
├── 06_animations.md
├── 07_performance_optimization_and_parallelism.md
├── 08_integration_with_other_tools.md
└── 09_custom_filters_and_algorithms.md
├── requirements.txt
├── src
├── 01_basic_shapes
│ ├── __init__.py
│ ├── circle.py
│ ├── cone.py
│ ├── cube.py
│ ├── cylinder.py
│ ├── glyph.py
│ ├── square.py
│ └── triangle.py
├── 02_advanced_shapes
│ ├── __init__.py
│ ├── custom_filter_sphere.py
│ ├── enclosing_box.py
│ ├── flow_simulation_visualization.py
│ ├── isosurface.py
│ ├── multiple_dependent_objects.py
│ ├── multiple_independent_objects.py
│ ├── streamlines.py
│ ├── triangulation.py
│ ├── visualization_techniques_comparison.py
│ └── volume_rendering.py
├── 03_structures_and_datasets
│ ├── __init__.py
│ ├── ahmed_body_visualization.py
│ ├── cells.py
│ ├── fields.py
│ ├── generate_naca0012.py
│ ├── image_data.py
│ ├── multiblock_dataset.py
│ ├── points.py
│ ├── poly_data.py
│ ├── rectilinear_grid.py
│ ├── structured_grid.py
│ ├── structured_mesh.py
│ ├── unstructured_grid.py
│ └── unstructured_mesh.py
├── 04_input_output
│ ├── __init__.py
│ ├── io_exodus_ii.py
│ ├── io_obj.py
│ ├── io_openfoam.py
│ ├── io_stl.py
│ ├── io_vtk.py
│ ├── io_vtm.py
│ └── io_vtu.py
├── 05_data_conversion
│ ├── __init__.py
│ ├── converter_interface.py
│ ├── stl_obj.py
│ ├── stl_vtk.py
│ ├── vtk_obj.py
│ ├── vtk_vtm.py
│ └── vtk_vtu.py
├── 06_visualization_pipeline
│ ├── __init__.py
│ ├── actor_mapper_multiple_objects.py
│ ├── adding_text_labels.py
│ ├── camera_movement.py
│ ├── filters_in_action.py
│ ├── lighting_and_shadows.py
│ ├── pipeline_animation.py
│ └── scalar_color_mapping.py
├── 07_interactive_widgets
│ ├── __init__.py
│ ├── deformation_cylinder.py
│ ├── interactive_flower_mesh.py
│ ├── orientation_marker.py
│ ├── planes_intersection.py
│ ├── simple_button.py
│ └── slider.py
├── 08_integration_with_ui
│ ├── __init__.py
│ ├── geospatial_data.py
│ ├── matplotlib_sphere.py
│ ├── matplotlib_surface_plot.py
│ ├── qt_sphere.py
│ └── spark_vtk_workflow.py
├── 09_cfd
│ ├── __init__.py
│ ├── convective_end_heat_transfer_1d.py
│ ├── enhanced_heat_transfer_solver_1d.py
│ ├── enhanced_heat_transfer_solver_2d.py
│ ├── fixed_end_heat_transfer_1d.py
│ ├── fluid_flow_simulator.py
│ ├── heat_conduction_solver_2d.py
│ ├── heat_convection_solver_1d.py
│ └── obstacle_flow_simulation.py
├── __init__.py
└── common
│ ├── __init__.py
│ ├── button.py
│ └── simple_pipeline.py
└── vtk_js
└── basic
├── .babelrc
├── README.md
├── index.html
├── package.json
├── src
└── main.js
└── webpack.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # Node modules
2 | node_modules/
3 | package-lock.json
4 |
5 | # Build output
6 | dist/
7 |
8 | # Environment files
9 | .env
10 |
11 | # Editor directories and files
12 | .vscode/
13 | .idea/
14 | *.swp
15 | *.swo
16 |
17 | # System files
18 | .DS_Store
19 | Thumbs.db
20 |
21 | # Logs
22 | npm-debug.log*
23 | yarn-debug.log*
24 | yarn-error.log*
25 |
26 |
27 | # Byte-compiled / optimized / DLL io
28 | __pycache__/
29 | *.py[cod]
30 | *$py.class
31 |
32 | # C extensions
33 | *.so
34 | .idea
35 |
36 | # Distribution / packaging
37 | .Python
38 | build/
39 | develop-eggs/
40 | dist/
41 | downloads/
42 | eggs/
43 | .eggs/
44 | lib/
45 | lib64/
46 | parts/
47 | sdist/
48 | var/
49 | wheels/
50 | pip-wheel-metadata/
51 | share/python-wheels/
52 | *.egg-info/
53 | .installed.cfg
54 | *.egg
55 | MANIFEST
56 |
57 | # PyInstaller
58 | # Usually these io are written by a python script from a template
59 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
60 | *.manifest
61 | *.spec
62 |
63 | # Installer logs
64 | pip-log.txt
65 | pip-delete-this-directory.txt
66 |
67 | # Unit test / coverage reports
68 | htmlcov/
69 | .tox/
70 | .nox/
71 | .coverage
72 | .coverage.*
73 | .cache
74 | nosetests.xml
75 | coverage.xml
76 | *.cover
77 | *.py,cover
78 | .hypothesis/
79 | .pytest_cache/
80 |
81 | # Translations
82 | *.mo
83 | *.pot
84 |
85 | # Django stuff:
86 | *.log
87 | local_settings.py
88 | db.sqlite3
89 | db.sqlite3-journal
90 |
91 | # Flask stuff:
92 | instance/
93 | .webassets-cache
94 |
95 | # Scrapy stuff:
96 | .scrapy
97 |
98 | # Sphinx documentation
99 | docs/_build/
100 |
101 | # PyBuilder
102 | target/
103 |
104 | # Jupyter Notebook
105 | .ipynb_checkpoints
106 |
107 | # IPython
108 | profile_default/
109 | ipython_config.py
110 |
111 | # pyenv
112 | .python-version
113 |
114 | # pipenv
115 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
116 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
117 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
118 | # install all needed dependencies.
119 | #Pipfile.lock
120 |
121 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
122 | __pypackages__/
123 |
124 | # Celery stuff
125 | celerybeat-schedule
126 | celerybeat.pid
127 |
128 | # SageMath parsed io
129 | *.sage.py
130 |
131 | # Environments
132 | .env
133 | .venv
134 | env/
135 | venv/
136 | ENV/
137 | env.bak/
138 | venv.bak/
139 |
140 | # Spyder project settings
141 | .spyderproject
142 | .spyproject
143 |
144 | # Rope project settings
145 | .ropeproject
146 |
147 | # mkdocs documentation
148 | /site
149 |
150 | # mypy
151 | .mypy_cache/
152 | .dmypy.json
153 | dmypy.json
154 |
155 | # Pyre type checker
156 | .pyre/
157 |
158 |
159 |
160 | # vtk
161 | src/**/*.vtk
162 | src/**/*.vtm
163 | src/**/*.vtu
164 | src/**/*.vtp
165 | src/**/*.stl
166 | src/**/*.obj
167 |
168 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Adam Djellouli
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/data/exodus/tetrahedron.exo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/djeada/Vtk-Examples/e9105e31800958705894eb94925ad251d2ad0117/data/exodus/tetrahedron.exo
--------------------------------------------------------------------------------
/data/objs/cube.obj:
--------------------------------------------------------------------------------
1 | # Generated by Visualization Toolkit
2 | v -134.3502960205078 17.677669525146484 20
3 | v -162.6345672607422 3.535533905029297 20
4 | v -106.0660171508789 3.535533905029297 20
5 | v -134.3502960205078 -10.60660171508789 20
6 | v -106.0660171508789 3.535533905029297 0
7 | v -134.3502960205078 -10.60660171508789 0
8 | v -134.3502960205078 17.677669525146484 0
9 | v -162.6345672607422 3.535533905029297 0
10 | f 1 2 3
11 | f 3 2 4
12 | f 5 6 7
13 | f 7 6 8
14 | f 4 6 3
15 | f 3 6 5
16 | f 2 8 4
17 | f 4 8 6
18 | f 1 7 2
19 | f 2 7 8
20 | f 3 5 1
21 | f 1 5 7
22 |
--------------------------------------------------------------------------------
/data/open_foam/temp.case:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/djeada/Vtk-Examples/e9105e31800958705894eb94925ad251d2ad0117/data/open_foam/temp.case
--------------------------------------------------------------------------------
/data/stls/airfoil.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/djeada/Vtk-Examples/e9105e31800958705894eb94925ad251d2ad0117/data/stls/airfoil.stl
--------------------------------------------------------------------------------
/data/stls/cube.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/djeada/Vtk-Examples/e9105e31800958705894eb94925ad251d2ad0117/data/stls/cube.stl
--------------------------------------------------------------------------------
/data/stls/naca0012.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/djeada/Vtk-Examples/e9105e31800958705894eb94925ad251d2ad0117/data/stls/naca0012.stl
--------------------------------------------------------------------------------
/data/stls/naca0012_meshed.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/djeada/Vtk-Examples/e9105e31800958705894eb94925ad251d2ad0117/data/stls/naca0012_meshed.stl
--------------------------------------------------------------------------------
/data/vtks/cube_polydata.vtk:
--------------------------------------------------------------------------------
1 | # vtk DataFile Version 1.0
2 | vtk output
3 | ASCII
4 | DATASET POLYDATA
5 | POINTS 64 float
6 | 3.449950 7.310000 1.000000 3.510010 5.389980 1.000000
7 | 3.449950 17.450001 1.000000 2.070010 19.580000 1.000000
8 | 0.000000 18.379999 1.000000 0.000000 17.450001 1.000000
9 | 3.719970 3.810000 1.000000 3.940000 21.000000 1.000000
10 | 4.089970 2.540010 1.000000 4.639950 1.560000 1.000000
11 | 5.389950 0.839996 1.000000 5.839970 22.840000 1.000000
12 | 6.339970 0.359985 1.000000 6.880000 23.969999 1.000000
13 | 7.539980 0.079987 1.000000 8.010010 6.470000 1.000000
14 | 8.010010 17.450001 1.000000 8.010010 19.180000 1.000000
15 | 8.010010 25.290001 1.000000 8.130000 4.810000 1.000000
16 | 8.500000 3.720000 1.000000 8.989990 0.000000 1.000000
17 | 9.159970 0.000000 1.000000 9.190000 3.109990 1.000000
18 | 10.220000 2.919980 1.000000 10.870000 3.000000 1.000000
19 | 11.490000 3.250000 1.000000 12.170000 3.729980 1.000000
20 | 13.010000 4.470000 1.000000 13.770000 3.410000 1.000000
21 | 13.010000 17.450001 1.000000 13.770000 19.180000 1.000000
22 | 3.449950 17.450001 0.000000 3.510010 5.389980 0.000000
23 | 3.449950 7.310000 0.000000 0.000000 17.450001 0.000000
24 | 0.000000 18.379999 0.000000 2.070010 19.580000 0.000000
25 | 3.719970 3.810000 0.000000 3.940000 21.000000 0.000000
26 | 4.089970 2.540010 0.000000 4.639950 1.560000 0.000000
27 | 5.389950 0.839996 0.000000 5.839970 22.840000 0.000000
28 | 6.339970 0.359985 0.000000 6.880000 23.969999 0.000000
29 | 7.539980 0.079987 0.000000 8.010010 6.470000 0.000000
30 | 8.010010 17.450001 0.000000 8.010010 19.180000 0.000000
31 | 8.010010 25.290001 0.000000 8.130000 4.810000 0.000000
32 | 8.500000 3.720000 0.000000 8.989990 0.000000 0.000000
33 | 9.159970 0.000000 0.000000 9.190000 3.109990 0.000000
34 | 10.220000 2.919980 0.000000 10.870000 3.000000 0.000000
35 | 11.490000 3.250000 0.000000 12.170000 3.729980 0.000000
36 | 13.010000 4.470000 0.000000 13.770000 3.410000 0.000000
37 | 13.010000 17.450001 0.000000 13.770000 19.180000 0.000000
38 |
39 | POLYGONS 92 400
40 | 3 0 1 2
41 | 3 3 4 5
42 | 3 2 3 5
43 | 3 1 6 2
44 | 3 7 2 6
45 | 3 3 2 7
46 | 3 6 8 7
47 | 3 9 7 8
48 | 3 10 7 9
49 | 3 11 7 10
50 | 3 12 11 10
51 | 3 13 11 12
52 | 3 14 13 12
53 | 3 15 13 14
54 | 3 16 13 15
55 | 3 17 13 16
56 | 3 18 13 17
57 | 3 19 15 14
58 | 3 20 19 14
59 | 3 21 20 14
60 | 3 22 20 21
61 | 3 23 20 22
62 | 3 24 23 22
63 | 3 25 24 22
64 | 3 26 25 22
65 | 3 27 26 22
66 | 3 28 27 22
67 | 3 29 28 22
68 | 3 16 30 17
69 | 3 31 17 30
70 | 3 32 33 34
71 | 3 35 36 37
72 | 3 35 37 32
73 | 3 32 38 33
74 | 3 38 32 39
75 | 3 39 32 37
76 | 3 39 40 38
77 | 3 40 39 41
78 | 3 41 39 42
79 | 3 42 39 43
80 | 3 42 43 44
81 | 3 44 43 45
82 | 3 44 45 46
83 | 3 46 45 47
84 | 3 47 45 48
85 | 3 48 45 49
86 | 3 49 45 50
87 | 3 46 47 51
88 | 3 46 51 52
89 | 3 46 52 53
90 | 3 53 52 54
91 | 3 54 52 55
92 | 3 54 55 56
93 | 3 54 56 57
94 | 3 54 57 58
95 | 3 54 58 59
96 | 3 54 59 60
97 | 3 54 60 61
98 | 3 49 62 48
99 | 3 62 49 63
100 | 4 63 49 17 31
101 | 4 49 50 18 17
102 | 4 50 45 13 18
103 | 4 45 43 11 13
104 | 4 43 39 7 11
105 | 4 39 37 3 7
106 | 4 37 36 4 3
107 | 4 36 35 5 4
108 | 4 35 32 2 5
109 | 4 32 34 0 2
110 | 4 34 33 1 0
111 | 4 33 38 6 1
112 | 4 38 40 8 6
113 | 4 40 41 9 8
114 | 4 41 42 10 9
115 | 4 42 44 12 10
116 | 4 44 46 14 12
117 | 4 46 53 21 14
118 | 4 53 54 22 21
119 | 4 54 61 29 22
120 | 4 61 60 28 29
121 | 4 60 59 27 28
122 | 4 59 58 26 27
123 | 4 58 57 25 26
124 | 4 57 56 24 25
125 | 4 56 55 23 24
126 | 4 55 52 20 23
127 | 4 52 51 19 20
128 | 4 51 47 15 19
129 | 4 47 48 16 15
130 | 4 48 62 30 16
131 | 4 62 63 31 30
--------------------------------------------------------------------------------
/data/vtks/grid_of_mixed_types.vtk:
--------------------------------------------------------------------------------
1 | # vtk DataFile Version 1.0
2 | Unstructured Grid Example
3 | ASCII
4 |
5 | DATASET UNSTRUCTURED_GRID
6 | POINTS 27 float
7 | 0.0 0.0 0.0
8 | 1.0 0.0 0.0
9 | 2.0 0.0 0.0
10 | 0.0 1.0 0.0
11 | 1.0 1.0 0.0
12 | 2.0 1.0 0.0
13 | 0.0 0.0 1.0
14 | 1.0 0.0 1.0
15 | 2.0 0.0 1.0
16 | 0.0 1.0 1.0
17 | 1.0 1.0 1.0
18 | 2.0 1.0 1.0
19 | 0.0 1.0 2.0
20 | 1.0 1.0 2.0
21 | 2.0 1.0 2.0
22 | 0.0 1.0 3.0
23 | 1.0 1.0 3.0
24 | 2.0 1.0 3.0
25 | 0.0 1.0 4.0
26 | 1.0 1.0 4.0
27 | 2.0 1.0 4.0
28 | 0.0 1.0 5.0
29 | 1.0 1.0 5.0
30 | 2.0 1.0 5.0
31 | 0.0 1.0 6.0
32 | 1.0 1.0 6.0
33 | 2.0 1.0 6.0
34 |
35 | CELLS 12 63
36 | 8 0 1 4 3 6 7 10 9
37 | 8 1 2 5 4 7 8 11 10
38 | 4 6 10 9 12
39 | 4 5 11 10 14
40 | 6 15 16 17 14 13 12
41 | 6 18 15 19 16 20 17
42 | 4 22 23 20 19
43 | 3 21 22 18
44 | 3 22 19 18
45 | 2 23 26
46 | 2 21 24
47 | 1 25
48 |
49 | CELL_TYPES 12
50 | 12
51 | 12
52 | 10
53 | 10
54 | 7
55 | 6
56 | 9
57 | 5
58 | 5
59 | 3
60 | 3
61 | 1
62 |
63 |
64 | POINT_DATA 27
65 | SCALARS scalars float
66 | LOOKUP_TABLE default
67 | 0.0
68 | 1.0
69 | 2.0
70 | 3.0
71 | 4.0
72 | 5.0
73 | 6.0
74 | 7.0
75 | 8.0
76 | 9.0
77 | 10.0
78 | 11.0
79 | 12.0
80 | 13.0
81 | 14.0
82 | 15.0
83 | 16.0
84 | 17.0
85 | 18.0
86 | 19.0
87 | 20.0
88 | 21.0
89 | 22.0
90 | 23.0
91 | 24.0
92 | 25.0
93 | 26.0
94 |
95 | VECTORS vectors float
96 | 1 0 0
97 | 1 1 0
98 | 0 2 0
99 | 1 0 0
100 | 1 1 0
101 | 0 2 0
102 | 1 0 0
103 | 1 1 0
104 | 0 2 0
105 | 1 0 0
106 | 1 1 0
107 | 0 2 0
108 | 0 0 1
109 | 0 0 1
110 | 0 0 1
111 | 0 0 1
112 | 0 0 1
113 | 0 0 1
114 | 0 0 1
115 | 0 0 1
116 | 0 0 1
117 | 0 0 1
118 | 0 0 1
119 | 0 0 1
120 | 0 0 1
121 | 0 0 1
122 | 0 0 1
123 |
--------------------------------------------------------------------------------
/data/vtks/grid_of_triangles.vtk:
--------------------------------------------------------------------------------
1 | # vtk DataFile Version 1.0
2 | 2D Unstructured Grid of Linear Triangles
3 | ASCII
4 |
5 | DATASET UNSTRUCTURED_GRID
6 | POINTS 8 float
7 | 0.0 0.0 0.0
8 | 1.0 0.0 0.0
9 | 2.0 0.0 0.0
10 | 0.0 1.0 0.0
11 | 1.0 1.0 0.0
12 | 2.0 1.0 0.0
13 | 0.0 2.0 0.0
14 | 1.0 2.0 0.0
15 |
16 | CELLS 6 24
17 | 3 0 1 3
18 | 3 1 4 3
19 | 3 1 2 4
20 | 3 2 5 4
21 | 3 3 4 6
22 | 3 4 7 6
23 |
24 | CELL_TYPES 6
25 | 5
26 | 5
27 | 5
28 | 5
29 | 5
30 | 5
31 |
32 | POINT_DATA 8
33 | SCALARS pressure float
34 | LOOKUP_TABLE default
35 | 0.0
36 | 1.0
37 | 2.0
38 | 1.0
39 | 2.0
40 | 3.0
41 | 2.0
42 | 3.0
43 |
44 | VECTORS velocity float
45 | 1.0 1.0 0.0
46 | 2.0 1.0 0.0
47 | 3.0 1.0 0.0
48 | 1.0 2.0 0.0
49 | 2.0 2.0 0.0
50 | 3.0 2.0 0.0
51 | 1.0 3.0 0.0
52 | 2.0 3.0 0.0
53 |
--------------------------------------------------------------------------------
/data/vtks/polydata_line.vtk:
--------------------------------------------------------------------------------
1 | # vtk DataFile Version 1.0
2 | Line representation of vtk
3 | ASCII
4 |
5 | DATASET POLYDATA
6 | POINTS 12 float
7 | 0.0 2.0 0.0
8 | 1.0 0.0 0.0
9 | 2.0 2.0 0.0
10 | 3.0 0.0 0.0
11 | 3.0 3.0 0.0
12 | 2.5 2.0 0.0
13 | 3.5 2.0 0.0
14 | 4.0 0.0 0.0
15 | 4.0 3.0 0.0
16 | 5.0 2.0 0.0
17 | 4.0 1.0 0.0
18 | 5.0 0.0 0.0
19 |
20 | LINES 5 17
21 | 3 0 1 2
22 | 2 3 4
23 | 2 5 6
24 | 2 7 8
25 | 3 9 10 11
26 |
--------------------------------------------------------------------------------
/data/vtks/texture_map.vtk:
--------------------------------------------------------------------------------
1 | # vtk DataFile Version 1.0
2 | Texture map for thresholding data (use boolean textures for 2D map)
3 | ASCII
4 |
5 | DATASET STRUCTURED_POINTS
6 | DIMENSIONS 128 1 1
7 | ASPECT_RATIO 1 1 1
8 | ORIGIN 0.0 0.0 0.0
9 |
10 | POINT_DATA 128
11 | COLOR_SCALARS texture 2
12 | 1.0 .5
13 | 1.0 .5
14 | 1.0 .5
15 | 1.0 .5
16 | 1.0 .5
17 | 1.0 .5
18 | 1.0 .5
19 | 1.0 .5
20 | 1.0 .5
21 | 1.0 .5
22 | 1.0 .5
23 | 1.0 .5
24 | 1.0 .5
25 | 1.0 .5
26 | 1.0 .5
27 | 1.0 .5
28 | 1.0 .5
29 | 1.0 .5
30 | 1.0 .5
31 | 1.0 .5
32 | 1.0 .5
33 | 1.0 .5
34 | 1.0 .5
35 | 1.0 .5
36 | 1.0 .5
37 | 1.0 .5
38 | 1.0 .5
39 | 1.0 .5
40 | 1.0 .5
41 | 1.0 .5
42 | 1.0 .5
43 | 1.0 .5
44 | 1.0 .5
45 | 1.0 .5
46 | 1.0 .5
47 | 1.0 .5
48 | 1.0 .5
49 | 1.0 .5
50 | 1.0 .5
51 | 1.0 .5
52 | 1.0 .5
53 | 1.0 .5
54 | 1.0 .5
55 | 1.0 .5
56 | 1.0 .5
57 | 1.0 .5
58 | 1.0 .5
59 | 1.0 .5
60 | 1.0 .5
61 | 1.0 .5
62 | 1.0 .5
63 | 1.0 .5
64 | 1.0 .5
65 | 1.0 .5
66 | 1.0 .5
67 | 1.0 .5
68 | 1.0 .5
69 | 1.0 .5
70 | 1.0 .5
71 | 1.0 .5
72 | 1.0 .5
73 | 1.0 .5
74 | 0.0 0.0
75 | 0.0 1.0
76 | 0.0 1.0
77 | 1.0 1.0
78 | 1.0 1.0
79 | 1.0 1.0
80 | 1.0 1.0
81 | 1.0 1.0
82 | 1.0 1.0
83 | 1.0 1.0
84 | 1.0 1.0
85 | 1.0 1.0
86 | 1.0 1.0
87 | 1.0 1.0
88 | 1.0 1.0
89 | 1.0 1.0
90 | 1.0 1.0
91 | 1.0 1.0
92 | 1.0 1.0
93 | 1.0 1.0
94 | 1.0 1.0
95 | 1.0 1.0
96 | 1.0 1.0
97 | 1.0 1.0
98 | 1.0 1.0
99 | 1.0 1.0
100 | 1.0 1.0
101 | 1.0 1.0
102 | 1.0 1.0
103 | 1.0 1.0
104 | 1.0 1.0
105 | 1.0 1.0
106 | 1.0 1.0
107 | 1.0 1.0
108 | 1.0 1.0
109 | 1.0 1.0
110 | 1.0 1.0
111 | 1.0 1.0
112 | 1.0 1.0
113 | 1.0 1.0
114 | 1.0 1.0
115 | 1.0 1.0
116 | 1.0 1.0
117 | 1.0 1.0
118 | 1.0 1.0
119 | 1.0 1.0
120 | 1.0 1.0
121 | 1.0 1.0
122 | 1.0 1.0
123 | 1.0 1.0
124 | 1.0 1.0
125 | 1.0 1.0
126 | 1.0 1.0
127 | 1.0 1.0
128 | 1.0 1.0
129 | 1.0 1.0
130 | 1.0 1.0
131 | 1.0 1.0
132 | 1.0 1.0
133 | 1.0 1.0
134 | 1.0 1.0
135 | 1.0 1.0
136 | 1.0 1.0
137 | 1.0 1.0
138 | 1.0 1.0
139 | 1.0 1.0
140 |
--------------------------------------------------------------------------------
/data/vtms/grid_of_triangles.vtm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/data/vtms/grid_of_triangles/grid_of_triangles_0.vtu:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | _AQAAAACAAAAgAAAAFQAAAA==eJxjYACBBnsg4YCgHRxgNAAvtgM/AQAAAACAAABgAAAANgAAAA==eJzjZ2hYepVlqz0DEIDorYfZHUDs/yymDiAMFd8PE//x//9SJHF7BbckmPoDyOph4gCScRw3AQAAAACAAABgAAAAMwAAAA==eJxjYECAqyxb7b+zmNqD2P9ZTB1AfKj4fpg4P0PDUiRx+62H2R2g6g8gq4eJAwApMBicAQAAAACAAACQAAAAIwAAAA==eJxjYIAARijNjMZnwSHOhCYP47Pi0Afjs6Hx2dHEAQ34AD0=AQAAAACAAAAwAAAAGAAAAA==eJxjZoAANijNCaV5oDQ/lBaC0gAFcABAAQAAAACAAAAGAAAACwAAAA==eJxjZQUBAABvAB8=
23 |
24 |
25 |
--------------------------------------------------------------------------------
/data/vtps/naca0012.vtp:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | _AQAAAACAAACwBAAADwMAAA==eJxF0n8s1HEYB3ApV0mIrBamH9xoEhaFz/d5ThKqqaTUqchxqKTi+qFfpKzlZmoRWWPMLqwf06wysUnZmbLVzY81V8patFpLtVtLv57P57v89Zrdfe55nvfbyur/X8tpL1bH9Iy7nrUHd5IdwcLW3x8T//eSdD3TpH9OMcdKGSFOEv/MMSltwJ1sflYqZdt5S+Idqc4tgKz3a5UqVoaI7z6TgvNV5JCSt5LTnCjxjkWa+nsDeeKIAozqOPGmIywKTCD3KF2hsDRRvO8FhjNJ5Jr+5TAyXSN+KxSy/bXko0VrwPA7Q54ZlCf2kWODd8AHQ5aYQQM5F7PJnu+yoFd5SN4LDPmHyZPrCiC5KkfMVgQOebnksdpiKPbQybvD8RJu048yiDbqxMxVEP6cuyOuBgqbdPJ9YHYCd1NjIzzszxW73Iatvtzl1i1wakeOfEN4nMTnKVB3wA3VIbFjF+gn+fxZzUbounpAvjNcduQ7brc1gXemvPsQNNRmkiNSzODdni5nATfb0sjLW99DQLVG3OQj1Gn3kBc4TcCoc5KcFzw17CTb7J0EnyVqcasp2F7E87K8nooRL+LlTDFzJs/0k91MHPLZKG44C/2DeO6jq+xR4Rsj547j9mvJQ6nOmGJeLW7rgp+uIbmvdD4qIpncDXQdXkV+3OaOFZogcfOF+GqQ97D1/WKMlfzk/mDYpaXkO3O98ZtJKbJYit0zlpDrVcvwq6+H3DF8EO5KrtofiLFR80RGQTgqOZMvVazEBi8HuYfY+cuWXNTFcJNRIbJDPHDemnzycziman8y0VVU10+QD7tFoal7nPFMY3D46Qg5PXoDHr03yESfsfJcH3lX7ua/N3zCeNbx6GFsI2+p2YagustE5zHxWgM5ujcRpYFqxjuwG69/LyODJRmXWYoZ74MGr7wsIK/w1OIbVTbj3cjAW3o12WfTPqyrjGS8J1n4SOtP9jh5ECe/LGC8MznoL9mQXW7oMOaCOYz35xgqZzeTbU15uFpxPox36RSeHfEjW1nlY7myPvSf/gBqtkEfAAAAAACAAAAAAAAAAAAAAACAAAAAAAAAAAAAAACAAAAAAAAAAAAAAACAAAAAAAAAAAAAAACAAAAAAAAAAAAAAACAAAAAAAAAAQAAAACAAAAgAwAArwAAAA==eJwtxdciAgAAAMCQWSFbJCuzsjNDiuyMyo7y///gwd3LBQL/WtzqNgfd7g53usvd7nHIYUfc6z73O+oBD3rIwx7xqMc87pgnPOm4p5zwtGc86znPO+kFL3rJy17xqlNOO+M1r3vDm97ytnec9a73vO8DH/rIOR/7xKfO+8wFF33uC5d86Stf+8a3vvO9y37wo5/87IqrrvnFr37zuz/86S/X/e0fN9z0r/8AXBwTVw==AQAAAACAAAAIAAAACwAAAA==eJxLYYAAAAMoAGU=
32 |
33 |
34 |
--------------------------------------------------------------------------------
/data/vtus/grid_of_triangles.vtu:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | _AQAAAACAAAAgAAAAFQAAAA==eJxjYACBBnsg4YCgHRxgNAAvtgM/AQAAAACAAABgAAAANgAAAA==eJzjZ2hYepVlqz0DEIDorYfZHUDs/yymDiAMFd8PE//x//9SJHF7BbckmPoDyOph4gCScRw3AQAAAACAAABgAAAAMwAAAA==eJxjYECAqyxb7b+zmNqD2P9ZTB1AfKj4fpg4P0PDUiRx+62H2R2g6g8gq4eJAwApMBicAQAAAACAAACQAAAAIwAAAA==eJxjYIAARijNjMZnwSHOhCYP47Pi0Afjs6Hx2dHEAQ34AD0=AQAAAACAAAAwAAAAGAAAAA==eJxjZoAANijNCaV5oDQ/lBaC0gAFcABAAQAAAACAAAAGAAAACwAAAA==eJxjZQUBAABvAB8=
23 |
24 |
25 |
--------------------------------------------------------------------------------
/notes/03_input_and_output.md:
--------------------------------------------------------------------------------
1 | ## Input and Output
2 |
3 | VTK offers a comprehensive suite of tools for reading and writing a variety of data formats. This includes the native VTK file formats (legacy and XML-based), as well as numerous third-party formats.
4 |
5 | ### Common File Formats
6 |
7 | VTK supports an extensive range of data formats, including:
8 |
9 | I. Legacy VTK File Format
10 |
11 | - **Nature**: ASCII or binary.
12 | - **Features**: Supports various data structures and attributes.
13 | - **Structure**: Composed of five main sections - file version and identifier, header, dataset type, dataset structure, and data attributes.
14 |
15 | Example:
16 |
17 | ```
18 | # vtk DataFile Version 3.0
19 | VTK Example Data
20 | ASCII
21 | DATASET POLYDATA
22 | POINTS 8 float
23 | 0.0 0.0 0.0
24 | 1.0 0.0 0.0
25 | 1.0 1.0 0.0
26 | 0.0 1.0 0.0
27 | 0.0 0.0 1.0
28 | 1.0 0.0 1.0
29 | 1.0 1.0 1.0
30 | 0.0 1.0 1.0
31 | POLYGONS 6 30
32 | 4 0 1 2 3
33 | ...
34 | ```
35 |
36 | II. XML-Based VTK File Format
37 |
38 | - **Nature**: ASCII or binary, offering enhanced flexibility and extensibility.
39 | - **Features**: Supports a diverse range of data structures and attributes.
40 | - **File Extensions**: Includes formats like `.vtp` for PolyData, `.vtu` for UnstructuredGrid, and `.vts` for StructuredGrid, among others.
41 |
42 | Example:
43 |
44 | ```
45 |
46 |
47 |
48 |
49 |
50 |
51 | 0.0 0.0 0.0 1.0 0.0 0.0 1.0 1.0 0.0 0.0 1.0 0.0 ...
52 |
53 |
54 |
55 |
56 | 0 1 2 3 ...
57 |
58 | ...
59 |
60 |
61 |
62 |
63 | ```
64 |
65 | III. Third-Party File Formats
66 |
67 | - **Scope**: VTK interfaces seamlessly with many popular 3D graphics and scientific visualization file formats.
68 | - **STL**: Predominantly used in 3D printing.
69 | - **PLY**: Specializes in storing polygonal meshes.
70 | - **OBJ**: Capable of holding complex 3D models encompassing geometry, texture, and material data.
71 |
72 | Example (STL):
73 |
74 | ```
75 | solid vtkGenerated
76 | facet normal 0 0 -1
77 | outer loop
78 | vertex 0.0 0.0 0.0
79 | vertex 1.0 0.0 0.0
80 | vertex 1.0 1.0 0.0
81 | endloop
82 | endfacet
83 | ...
84 | endsolid vtkGenerated
85 | ```
86 |
87 | Example (PLY):
88 |
89 | ```
90 | ply
91 | format ascii 1.0
92 | element vertex 8
93 | property float x
94 | property float y
95 | property float z
96 | element face 6
97 | property list uchar int vertex_indices
98 | end_header
99 | 0.0 0.0 0.0
100 | 1.0 0.0 0.0
101 | ...
102 | 3 0 1 2
103 | ...
104 | ```
105 |
106 | ### Reading and Writing Data
107 |
108 | There is a suite of subclasses derived from `vtkDataReader` and `vtkDataWriter`. These subclasses are specialized for handling various VTK data structures, emphasizing efficient and accurate data manipulation. The design ensures flexibility in reading and writing different types of data while maintaining the robustness of data integrity and format compatibility.
109 |
110 | #### Subclasses for Data Reading and Writing
111 |
112 | Each subclass under `vtkDataReader` and `vtkDataWriter` is tailored for specific data structures, facilitating precise and optimized read/write operations:
113 |
114 | - **vtkPolyDataReader** and **vtkPolyDataWriter**: For handling polygonal data, commonly used in 3D graphics and modeling.
115 | - **vtkStructuredPointsReader** and **vtkStructuredPointsWriter**: Optimized for structured point datasets, where data is arranged in a regular grid.
116 | - **vtkStructuredGridReader** and **vtkStructuredGridWriter**: Suitable for structured grid data, a step above structured points in complexity, allowing for non-uniform grids.
117 | - **vtkUnstructuredGridReader** and **vtkUnstructuredGridWriter**: Designed for unstructured grid data, which is the most flexible, accommodating irregularly spaced data points.
118 |
119 | #### Example
120 |
121 | Below is a Python script demonstrating how to read data from an STL file (common in 3D printing and modeling) and write it into VTK's native format.
122 |
123 | ```python
124 | import vtk
125 |
126 | # Initialize an STL reader and set the file to read
127 | stl_reader = vtk.vtkSTLReader()
128 | stl_reader.SetFileName("input.stl")
129 |
130 | # Set up a VTK writer and connect it to the output of the STL reader
131 | vtk_writer = vtk.vtkPolyDataWriter()
132 | vtk_writer.SetInputConnection(stl_reader.GetOutputPort())
133 | vtk_writer.SetFileName("output.vtk")
134 |
135 | # Execute the writing process to convert the STL file to a VTK file
136 | vtk_writer.Write()
137 | ```
138 |
139 | This script shows the straightforward approach of VTK in converting data between different formats, highlighting its powerful data processing capabilities.
140 |
141 | ## Readers and Writers Comparison
142 |
143 | A comparison of various readers and writers for different formats is provided below:
144 |
145 | | Format | Reader Class | Output Data Type | Writer Class | Input Data Type |
146 | |-----------|---------------------------------|-----------------------------|-------------------------------|--------------------------|
147 | | STL | `vtkSTLReader` | `vtkPolyData` | `vtkSTLWriter` | `vtkPolyData` |
148 | | OBJ | `vtkOBJReader` | `vtkPolyData` | `vtkOBJWriter` | `vtkPolyData` |
149 | | VTK (Legacy) | `vtkUnstructuredGridReader` | `vtkUnstructuredGrid` | `vtkUnstructuredGridWriter` | `vtkUnstructuredGrid` |
150 | | | `vtkStructuredGridReader` | `vtkStructuredGrid` | `vtkStructuredGridWriter` | `vtkStructuredGrid` |
151 | | | `vtkPolyDataReader` | `vtkPolyData` | `vtkPolyDataWriter` | `vtkPolyData` |
152 | | | `vtkRectilinearGridReader` | `vtkRectilinearGrid` | `vtkRectilinearGridWriter` | `vtkRectilinearGrid` |
153 | | | `vtkStructuredPointsReader` | `vtkStructuredPoints` | `vtkStructuredPointsWriter` | `vtkStructuredPoints` |
154 | | VTU | `vtkXMLUnstructuredGridReader` | `vtkUnstructuredGrid` | `vtkXMLUnstructuredGridWriter`| `vtkUnstructuredGrid` |
155 | | VTM | `vtkXMLMultiBlockDataReader` | `vtkMultiBlockDataSet` | `vtkXMLMultiBlockDataWriter` | `vtkMultiBlockDataSet` |
156 | | OpenFOAM | `vtkOpenFOAMReader` | `vtkMultiBlockDataSet` | N/A | N/A |
157 | | EnSight | `vtkEnSightGoldReader` | `vtkMultiBlockDataSet` | N/A | N/A |
158 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | aiohappyeyeballs==2.6.1
2 | aiohttp==3.11.18
3 | aiosignal==1.3.2
4 | async-timeout==5.0.1
5 | attrs==25.3.0
6 | charset-normalizer==3.4.1
7 | contourpy==1.3.2
8 | cramjam==2.10.0
9 | cycler==0.12.1
10 | fastparquet==2024.11.0
11 | fonttools==4.57.0
12 | frozenlist==1.6.0
13 | fsspec==2025.3.2
14 | idna==3.10
15 | kiwisolver==1.4.8
16 | matplotlib==3.10.1
17 | msgpack==1.1.0
18 | multidict==6.4.3
19 | numpy==2.2.5
20 | packaging==25.0
21 | pandas==2.2.3
22 | pillow==11.2.1
23 | propcache==0.3.1
24 | py4j==0.10.9.7
25 | pyarrow==19.0.1
26 | pyparsing==3.2.3
27 | PyQt6==6.9.0
28 | PyQt6-Qt6==6.9.0
29 | PyQt6_sip==13.10.0
30 | pyspark==3.5.5
31 | python-dateutil==2.9.0.post0
32 | pytz==2025.2
33 | PyVTK==0.5.18
34 | six==1.17.0
35 | tzdata==2025.2
36 | vtk==9.4.2
37 | wslink==2.3.3
38 | yarl==1.20.0
39 |
--------------------------------------------------------------------------------
/src/01_basic_shapes/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/djeada/Vtk-Examples/e9105e31800958705894eb94925ad251d2ad0117/src/01_basic_shapes/__init__.py
--------------------------------------------------------------------------------
/src/01_basic_shapes/circle.py:
--------------------------------------------------------------------------------
1 | from typing import Tuple
2 |
3 | import vtk
4 |
5 | from src.common.simple_pipeline import VisualisationPipeline
6 |
7 |
8 | def create_circle_mapper(
9 | radius: float, center: Tuple[float, float, float], resolution: int = 100
10 | ) -> vtk.vtkPolyDataMapper:
11 | circle = vtk.vtkRegularPolygonSource()
12 | circle.SetNumberOfSides(resolution)
13 | circle.SetRadius(radius)
14 | circle.SetCenter(center)
15 | circle.SetNormal(0, 0, 1)
16 |
17 | circle_mapper = vtk.vtkPolyDataMapper()
18 | circle_mapper.SetInputConnection(circle.GetOutputPort())
19 |
20 | return circle_mapper
21 |
22 |
23 | if __name__ == "__main__":
24 | # Create a circle with different radius and center
25 | circle_mapper1 = create_circle_mapper(radius=1.0, center=(0.0, 0.0, 0.0))
26 | circle_mapper2 = create_circle_mapper(radius=2.0, center=(4.0, 0.0, 0.0))
27 |
28 | # Display the circles
29 | pipeline = VisualisationPipeline(mappers=[circle_mapper1, circle_mapper2])
30 | pipeline.run()
31 |
--------------------------------------------------------------------------------
/src/01_basic_shapes/cone.py:
--------------------------------------------------------------------------------
1 | from typing import Tuple
2 |
3 | import vtk
4 |
5 | from src.common.simple_pipeline import VisualisationPipeline
6 |
7 |
8 | def create_cone_mapper(
9 | radius: float,
10 | height: float,
11 | center: Tuple[float, float, float],
12 | resolution: int = 100,
13 | ) -> vtk.vtkPolyDataMapper:
14 | cone = vtk.vtkConeSource()
15 | cone.SetRadius(radius)
16 | cone.SetHeight(height)
17 | cone.SetCenter(center)
18 | cone.SetDirection(0, 0, 1)
19 | cone.SetResolution(resolution)
20 |
21 | cone_mapper = vtk.vtkPolyDataMapper()
22 | cone_mapper.SetInputConnection(cone.GetOutputPort())
23 |
24 | return cone_mapper
25 |
26 |
27 | if __name__ == "__main__":
28 | # Create cones with different radius, height, and center
29 | cone_mapper1 = create_cone_mapper(radius=1.0, height=2.0, center=(0.0, 0.0, 0.0))
30 | cone_mapper2 = create_cone_mapper(radius=1.5, height=3.0, center=(4.0, 0.0, 0.0))
31 |
32 | # Display the cones
33 | pipeline = VisualisationPipeline(mappers=[cone_mapper1, cone_mapper2])
34 | pipeline.run()
35 |
--------------------------------------------------------------------------------
/src/01_basic_shapes/cube.py:
--------------------------------------------------------------------------------
1 | from typing import List
2 |
3 | import vtk
4 |
5 | from src.common.simple_pipeline import VisualisationPipeline
6 |
7 |
8 | def create_cube_mapper(bounds: List[float]) -> vtk.vtkPolyDataMapper:
9 | cube = vtk.vtkCubeSource()
10 | cube.SetBounds(bounds)
11 |
12 | cube_mapper = vtk.vtkPolyDataMapper()
13 | cube_mapper.SetInputConnection(cube.GetOutputPort())
14 |
15 | return cube_mapper
16 |
17 |
18 | if __name__ == "__main__":
19 | # Create cubes with different bounds
20 | cube_mapper1 = create_cube_mapper(bounds=[0.0, 1.0, 0.0, 1.0, 0.0, 1.0])
21 | cube_mapper2 = create_cube_mapper(bounds=[2.0, 4.0, 0.0, 1.0, 0.0, 1.0])
22 |
23 | # Display the cubes
24 | pipeline = VisualisationPipeline(mappers=[cube_mapper1, cube_mapper2])
25 | pipeline.run()
26 |
--------------------------------------------------------------------------------
/src/01_basic_shapes/cylinder.py:
--------------------------------------------------------------------------------
1 | from typing import Tuple
2 |
3 | import vtk
4 |
5 | from src.common.simple_pipeline import VisualisationPipeline
6 |
7 |
8 | def create_cylinder_mapper(
9 | radius: float,
10 | height: float,
11 | center: Tuple[float, float, float],
12 | resolution: int = 100,
13 | ) -> vtk.vtkPolyDataMapper:
14 | cylinder = vtk.vtkCylinderSource()
15 | cylinder.SetRadius(radius)
16 | cylinder.SetHeight(height)
17 | cylinder.SetCenter(center)
18 | cylinder.SetResolution(resolution)
19 |
20 | cylinder_mapper = vtk.vtkPolyDataMapper()
21 | cylinder_mapper.SetInputConnection(cylinder.GetOutputPort())
22 |
23 | return cylinder_mapper
24 |
25 |
26 | if __name__ == "__main__":
27 | # Create cylinders with different radius, height, and center
28 | cylinder_mapper1 = create_cylinder_mapper(
29 | radius=1.0, height=2.0, center=(0.0, 0.0, 0.0)
30 | )
31 | cylinder_mapper2 = create_cylinder_mapper(
32 | radius=1.5, height=3.0, center=(4.0, 0.0, 0.0)
33 | )
34 |
35 | # Display the cylinders
36 | pipeline = VisualisationPipeline(mappers=[cylinder_mapper1, cylinder_mapper2])
37 | pipeline.run()
38 |
--------------------------------------------------------------------------------
/src/01_basic_shapes/glyph.py:
--------------------------------------------------------------------------------
1 | import vtk
2 |
3 | from src.common.simple_pipeline import VisualisationPipeline
4 |
5 |
6 | def create_arrow_glyphs(vector_field):
7 | # Create arrow source
8 | arrow_source = vtk.vtkArrowSource()
9 |
10 | # Create glyph points and vectors
11 | glyph_points = vtk.vtkPoints()
12 | glyph_vectors = vtk.vtkDoubleArray()
13 | glyph_vectors.SetNumberOfComponents(3)
14 | glyph_vectors.SetNumberOfTuples(vector_field.shape[0] * vector_field.shape[1])
15 |
16 | idx = 0
17 | for i in range(vector_field.shape[0]):
18 | for j in range(vector_field.shape[1]):
19 | x, y, z = i, j, 0
20 | u, v, w = vector_field[i, j]
21 | glyph_points.InsertPoint(idx, x, y, z)
22 | glyph_vectors.SetTuple(idx, (u, v, w))
23 | idx += 1
24 |
25 | # Create glyph polydata
26 | glyph_polydata = vtk.vtkPolyData()
27 | glyph_polydata.SetPoints(glyph_points)
28 | glyph_polydata.GetPointData().SetVectors(glyph_vectors)
29 |
30 | # Create the glyph3D filter
31 | glyph3D = vtk.vtkGlyph3D()
32 | glyph3D.SetSourceConnection(arrow_source.GetOutputPort())
33 | glyph3D.SetInputData(glyph_polydata)
34 | glyph3D.SetVectorModeToUseVector()
35 | glyph3D.SetScaleModeToScaleByVector()
36 | glyph3D.SetScaleFactor(0.5)
37 |
38 | glyph_mapper = vtk.vtkPolyDataMapper()
39 | glyph_mapper.SetInputConnection(glyph3D.GetOutputPort())
40 |
41 | return glyph_mapper
42 |
43 |
44 | def generate_vector_field(size, scale):
45 | import numpy as np
46 |
47 | x, y = np.meshgrid(
48 | np.linspace(-scale, scale, size), np.linspace(-scale, scale, size)
49 | )
50 | u = -y
51 | v = x
52 | vector_field = np.stack((u, v, np.zeros_like(u)), axis=-1)
53 | return vector_field
54 |
55 |
56 | if __name__ == "__main__":
57 | vector_field = generate_vector_field(size=11, scale=5)
58 | glyph_mapper = create_arrow_glyphs(vector_field)
59 |
60 | # Display the glyphs
61 | pipeline = VisualisationPipeline(mappers=[glyph_mapper])
62 | pipeline.run()
63 |
--------------------------------------------------------------------------------
/src/01_basic_shapes/square.py:
--------------------------------------------------------------------------------
1 | from typing import Tuple
2 |
3 | import vtk
4 |
5 | from src.common.simple_pipeline import VisualisationPipeline
6 |
7 |
8 | def create_square_mapper(
9 | origin: Tuple[float, float, float],
10 | point1: Tuple[float, float, float],
11 | point2: Tuple[float, float, float],
12 | ) -> vtk.vtkPolyDataMapper:
13 | square = vtk.vtkPlaneSource()
14 | square.SetOrigin(origin)
15 | square.SetPoint1(point1)
16 | square.SetPoint2(point2)
17 |
18 | square_mapper = vtk.vtkPolyDataMapper()
19 | square_mapper.SetInputConnection(square.GetOutputPort())
20 |
21 | return square_mapper
22 |
23 |
24 | if __name__ == "__main__":
25 | # Create squares with different positions and sizes
26 | square_mapper1 = create_square_mapper(
27 | origin=(0.0, 0.0, 0.0), point1=(1.0, 0.0, 0.0), point2=(0.0, 1.0, 0.0)
28 | )
29 | square_mapper2 = create_square_mapper(
30 | origin=(3.0, 0.0, 0.0), point1=(4.0, 0.0, 0.0), point2=(3.0, 1.0, 0.0)
31 | )
32 |
33 | # Display the squares
34 | pipeline = VisualisationPipeline(mappers=[square_mapper1, square_mapper2])
35 | pipeline.run()
36 |
--------------------------------------------------------------------------------
/src/01_basic_shapes/triangle.py:
--------------------------------------------------------------------------------
1 | from typing import List, Tuple
2 |
3 | import vtk
4 |
5 | from src.common.simple_pipeline import VisualisationPipeline
6 |
7 |
8 | def create_triangle_mapper(
9 | points: List[Tuple[float, float, float]]
10 | ) -> vtk.vtkPolyDataMapper:
11 | triangle = vtk.vtkTriangle()
12 | triangle.GetPointIds().SetId(0, 0)
13 | triangle.GetPointIds().SetId(1, 1)
14 | triangle.GetPointIds().SetId(2, 2)
15 |
16 | points_array = vtk.vtkPoints()
17 | for point in points:
18 | points_array.InsertNextPoint(point)
19 |
20 | triangles = vtk.vtkCellArray()
21 | triangles.InsertNextCell(triangle)
22 |
23 | triangle_polydata = vtk.vtkPolyData()
24 | triangle_polydata.SetPoints(points_array)
25 | triangle_polydata.SetPolys(triangles)
26 |
27 | triangle_mapper = vtk.vtkPolyDataMapper()
28 | triangle_mapper.SetInputData(triangle_polydata)
29 |
30 | return triangle_mapper
31 |
32 |
33 | if __name__ == "__main__":
34 | # Create triangles with different vertex positions
35 | triangle_mapper1 = create_triangle_mapper(
36 | [(0.0, 0.0, 0.0), (1.0, 0.0, 0.0), (0.5, 1.0, 0.0)]
37 | )
38 | triangle_mapper2 = create_triangle_mapper(
39 | [(3.0, 0.0, 0.0), (4.0, 0.0, 0.0), (3.5, 1.0, 0.0)]
40 | )
41 |
42 | # Display the triangles
43 | pipeline = VisualisationPipeline(mappers=[triangle_mapper1, triangle_mapper2])
44 | pipeline.run()
45 |
--------------------------------------------------------------------------------
/src/02_advanced_shapes/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/djeada/Vtk-Examples/e9105e31800958705894eb94925ad251d2ad0117/src/02_advanced_shapes/__init__.py
--------------------------------------------------------------------------------
/src/02_advanced_shapes/custom_filter_sphere.py:
--------------------------------------------------------------------------------
1 | import vtk
2 | import math
3 | from datetime import datetime, UTC
4 |
5 |
6 | class DistanceToPointFilter(vtk.vtkPolyDataAlgorithm):
7 | """
8 | A VTK filter that computes the Euclidean distance from each point in the input
9 | vtkPolyData to a specified target point.
10 | """
11 |
12 | def __init__(self):
13 | super().__init__()
14 | self.__TargetPoint = [0.0, 0.0, 0.0]
15 | self.GetExecutive().SetOutputData(0, vtk.vtkPolyData())
16 |
17 | def SetTargetPoint(self, x, y, z):
18 | try:
19 | self.__TargetPoint = [float(x), float(y), float(z)]
20 | self.Modified()
21 | return True
22 | except ValueError as e:
23 | print(f"Error setting target point: {e}")
24 | return False
25 |
26 | def GetTargetPoint(self):
27 | return tuple(self.__TargetPoint)
28 |
29 | def ProcessDataObject(self, input_data):
30 | if not input_data:
31 | print("No input data provided")
32 | return None
33 |
34 | output_data = vtk.vtkPolyData()
35 | output_data.DeepCopy(input_data)
36 |
37 | num_points = input_data.GetNumberOfPoints()
38 | print(f"Processing {num_points} points...")
39 |
40 | distances = vtk.vtkDoubleArray()
41 | distances.SetName("DistanceToTarget")
42 | distances.SetNumberOfComponents(1)
43 | distances.SetNumberOfTuples(num_points)
44 |
45 | tx, ty, tz = self.__TargetPoint
46 | min_dist = float('inf')
47 | max_dist = float('-inf')
48 |
49 | for i in range(num_points):
50 | point = input_data.GetPoint(i)
51 | dx = point[0] - tx
52 | dy = point[1] - ty
53 | dz = point[2] - tz
54 | distance = math.sqrt(dx * dx + dy * dy + dz * dz)
55 | distances.SetValue(i, distance)
56 | min_dist = min(min_dist, distance)
57 | max_dist = max(max_dist, distance)
58 |
59 | print(f"Distance range: [{min_dist:.3f}, {max_dist:.3f}]")
60 | output_data.GetPointData().SetScalars(distances)
61 | return output_data
62 |
63 |
64 | def create_actor(poly_data, scalar_range=None, color=None):
65 | """Create a VTK actor from polydata with optional scalar coloring or solid color."""
66 | mapper = vtk.vtkPolyDataMapper()
67 | mapper.SetInputData(poly_data)
68 |
69 | if scalar_range and poly_data.GetPointData().GetScalars():
70 | mapper.SetScalarRange(scalar_range)
71 |
72 | # Create lookup table for distance visualization
73 | lut = vtk.vtkLookupTable()
74 | lut.SetHueRange(0.667, 0.0) # blue to red
75 | lut.SetSaturationRange(1.0, 1.0)
76 | lut.SetValueRange(1.0, 1.0)
77 | lut.SetTableRange(scalar_range)
78 | lut.Build()
79 |
80 | mapper.SetLookupTable(lut)
81 | mapper.SetScalarVisibility(1)
82 | else:
83 | mapper.SetScalarVisibility(0)
84 |
85 | actor = vtk.vtkActor()
86 | actor.SetMapper(mapper)
87 |
88 | if color:
89 | actor.GetProperty().SetColor(color)
90 |
91 | return actor
92 |
93 |
94 | def create_visualization():
95 | try:
96 | # Create source
97 | print("Creating sphere source...")
98 | sphere = vtk.vtkSphereSource()
99 | sphere.SetRadius(1.0)
100 | sphere.SetThetaResolution(30)
101 | sphere.SetPhiResolution(30)
102 | sphere.Update()
103 |
104 | input_data = sphere.GetOutput()
105 | print(f"Sphere created with {input_data.GetNumberOfPoints()} points")
106 |
107 | # Process with filter
108 | print("Creating and executing distance filter...")
109 | filter = DistanceToPointFilter()
110 | output_data = filter.ProcessDataObject(input_data)
111 |
112 | if not output_data:
113 | raise RuntimeError("Filter failed to process data")
114 |
115 | print(f"Filter output has {output_data.GetNumberOfPoints()} points")
116 |
117 | # Get scalar range for coloring
118 | scalars = output_data.GetPointData().GetScalars()
119 | if not scalars:
120 | raise RuntimeError("No scalar data in filter output")
121 |
122 | scalar_range = scalars.GetRange()
123 | print(f"Scalar range: [{scalar_range[0]:.3f}, {scalar_range[1]:.3f}]")
124 |
125 | # Create actors for both spheres
126 | original_actor = create_actor(input_data, color=(0.8, 0.8, 1.0)) # Light blue
127 | filtered_actor = create_actor(output_data, scalar_range=scalar_range)
128 |
129 | # Create renderers for split view
130 | left_renderer = vtk.vtkRenderer()
131 | right_renderer = vtk.vtkRenderer()
132 |
133 | # Set viewport (x1, y1, x2, y2) - split screen in half
134 | left_renderer.SetViewport(0.0, 0.0, 0.5, 1.0)
135 | right_renderer.SetViewport(0.5, 0.0, 1.0, 1.0)
136 |
137 | # Add actors to respective renderers
138 | left_renderer.AddActor(original_actor)
139 | right_renderer.AddActor(filtered_actor)
140 |
141 | # Set background colors
142 | left_renderer.SetBackground(0.1, 0.1, 0.1)
143 | right_renderer.SetBackground(0.2, 0.2, 0.2)
144 |
145 | # Create render window
146 | render_window = vtk.vtkRenderWindow()
147 | render_window.AddRenderer(left_renderer)
148 | render_window.AddRenderer(right_renderer)
149 | render_window.SetSize(1200, 600) # Wider window for side-by-side view
150 |
151 | # Create interactor
152 | interactor = vtk.vtkRenderWindowInteractor()
153 | interactor.SetRenderWindow(render_window)
154 |
155 | # Add orientation widgets to both views
156 | for renderer, viewport_coords in [(left_renderer, (0.0, 0.0, 0.2, 0.2)),
157 | (right_renderer, (0.5, 0.0, 0.7, 0.2))]:
158 | axes = vtk.vtkAxesActor()
159 | widget = vtk.vtkOrientationMarkerWidget()
160 | widget.SetOrientationMarker(axes)
161 | widget.SetInteractor(interactor)
162 | widget.SetViewport(*viewport_coords)
163 | widget.SetEnabled(1)
164 | widget.InteractiveOn()
165 |
166 | # Add titles
167 | left_text = vtk.vtkTextActor()
168 | left_text.SetInput("Original Sphere")
169 | left_text.GetTextProperty().SetFontSize(24)
170 | left_text.SetPosition(10, 10)
171 | left_renderer.AddActor2D(left_text)
172 |
173 | right_text = vtk.vtkTextActor()
174 | right_text.SetInput("Distance-Colored Sphere")
175 | right_text.GetTextProperty().SetFontSize(24)
176 | right_text.SetPosition(10, 10)
177 | right_renderer.AddActor2D(right_text)
178 |
179 | # Initialize view
180 | left_renderer.ResetCamera()
181 | right_renderer.ResetCamera()
182 |
183 | # Link cameras
184 | right_renderer.SetActiveCamera(left_renderer.GetActiveCamera())
185 |
186 | render_window.Render()
187 | interactor.Initialize()
188 |
189 | print("Visualization setup complete")
190 | return interactor
191 |
192 | except Exception as e:
193 | print(f"Error in visualization setup: {str(e)}")
194 | import traceback
195 | print(f"Traceback:\n{traceback.format_exc()}")
196 | return None
197 |
198 |
199 | if __name__ == "__main__":
200 | print("Current Date and Time (UTC - YYYY-MM-DD HH:MM:SS formatted):",
201 | datetime.now(UTC).strftime('%Y-%m-%d %H:%M:%S'))
202 | print("Current User's Login: djeada")
203 |
204 | interactor = create_visualization()
205 | if interactor:
206 | print("Starting interaction...")
207 | interactor.Start()
208 | else:
209 | print("Failed to setup visualization.")
--------------------------------------------------------------------------------
/src/02_advanced_shapes/enclosing_box.py:
--------------------------------------------------------------------------------
1 | """
2 | This module demonstrates the workflow of creating and visualizing a set of randomly positioned spheres within an enclosing box using the Visualization Toolkit (VTK). It highlights the use of VTK's capabilities for generating and displaying 3D objects in a defined space, showcasing fundamental concepts in computational geometry and 3D visualization.
3 |
4 | Workflow Overview:
5 |
6 | 1. Sphere Creation (create_random_sphere):
7 | - Generates individual spheres with specified centers and radii.
8 | - Illustrates how to create basic 3D objects (spheres) in VTK.
9 |
10 | 2. Random Spheres Mapper (create_random_spheres_mapper):
11 | - Constructs multiple spheres, each positioned randomly within a specified box size.
12 | - Utilizes vtkAppendPolyData to combine multiple vtkSphereSources into a single data structure.
13 | - Creates a vtkPolyDataMapper for the set of spheres, preparing them for visualization.
14 |
15 | 3. Enclosing Box Mapper (create_enclosing_box_mapper):
16 | - Generates an enclosing box (using vtkCubeSource) that defines the boundary for the random spheres.
17 | - Applies vtkOutlineFilter to create an outline of the box, enhancing spatial understanding.
18 | - Produces a vtkPolyDataMapper for the box, allowing it to be rendered alongside the spheres.
19 |
20 | 4. Visualization Pipeline:
21 | - The module uses a predefined 'VisualisationPipeline' class to manage the rendering process.
22 | - Both the random spheres and the enclosing box are visualized together, providing context and enhancing the perception of the 3D space.
23 | """
24 |
25 | import random
26 | from typing import Tuple
27 |
28 | import vtk
29 |
30 | from src.common.simple_pipeline import VisualisationPipeline
31 |
32 |
33 | def create_random_sphere(
34 | center: Tuple[float, float, float], radius: float
35 | ) -> vtk.vtkSphereSource:
36 | """
37 | Create a sphere source with specified center and radius.
38 |
39 | Args:
40 | center (tuple): The center of the sphere.
41 | radius (float): The radius of the sphere.
42 |
43 | Returns:
44 | vtkSphereSource: A VTK sphere source.
45 | """
46 | sphere = vtk.vtkSphereSource()
47 | sphere.SetCenter(*center)
48 | sphere.SetRadius(radius)
49 | sphere.Update()
50 | return sphere
51 |
52 |
53 | def create_random_spheres_mapper(
54 | n_spheres: int, box_size: float, sphere_radius: float = 0.2
55 | ) -> vtk.vtkPolyDataMapper:
56 | """
57 | Create a mapper for a set of randomly positioned spheres within a box.
58 |
59 | Args:
60 | n_spheres (int): Number of spheres to create.
61 | box_size (float): Size of the box in which spheres are contained.
62 | sphere_radius (float): Radius of each sphere.
63 |
64 | Returns:
65 | vtkPolyDataMapper: A mapper for the random spheres.
66 | """
67 | append_filter = vtk.vtkAppendPolyData()
68 |
69 | for _ in range(n_spheres):
70 | center = (
71 | random.uniform(-box_size / 2, box_size / 2),
72 | random.uniform(-box_size / 2, box_size / 2),
73 | random.uniform(-box_size / 2, box_size / 2),
74 | )
75 | sphere = create_random_sphere(center, sphere_radius)
76 | append_filter.AddInputConnection(sphere.GetOutputPort())
77 |
78 | append_filter.Update()
79 |
80 | mapper = vtk.vtkPolyDataMapper()
81 | mapper.SetInputConnection(append_filter.GetOutputPort())
82 | return mapper
83 |
84 |
85 | def create_enclosing_box_mapper(box_size: float) -> vtk.vtkPolyDataMapper:
86 | """
87 | Create a mapper for an enclosing box.
88 |
89 | Args:
90 | box_size (float): Size of the box.
91 |
92 | Returns:
93 | vtkPolyDataMapper: A mapper for the enclosing box.
94 | """
95 | box = vtk.vtkCubeSource()
96 | box.SetXLength(box_size)
97 | box.SetYLength(box_size)
98 | box.SetZLength(box_size)
99 | box.Update()
100 |
101 | outline = vtk.vtkOutlineFilter()
102 | outline.SetInputConnection(box.GetOutputPort())
103 |
104 | mapper = vtk.vtkPolyDataMapper()
105 | mapper.SetInputConnection(outline.GetOutputPort())
106 | return mapper
107 |
108 |
109 | if __name__ == "__main__":
110 | n_spheres = 50
111 | box_size = 5.0
112 |
113 | spheres_mapper = create_random_spheres_mapper(n_spheres, box_size)
114 | box_mapper = create_enclosing_box_mapper(box_size)
115 |
116 | pipeline = VisualisationPipeline(mappers=[spheres_mapper, box_mapper])
117 | pipeline.run()
118 |
--------------------------------------------------------------------------------
/src/02_advanced_shapes/isosurface.py:
--------------------------------------------------------------------------------
1 | """
2 | This module demonstrates the process of creating and visualizing a 3D scalar dataset using the Visualization Toolkit (VTK) and NumPy. It is structured into several key functions, each performing a distinct step in the visualization workflow.
3 |
4 | Workflow:
5 | 1. Creation of Sample Data (`create_sample_data`):
6 | - Generates a 3D scalar dataset based on a mathematical function.
7 | - Utilizes NumPy for efficient computation of scalar values within the dataset.
8 | - The dataset is represented as VTK's vtkImageData, which stores the 3D scalar values.
9 |
10 | 2. Isosurface Creation (`create_isosurface`):
11 | - Generates an isosurface from the vtkImageData.
12 | - An isosurface represents a 3D surface that connects points of equal scalar value (isovalue).
13 | - This function takes a range of isovalues and creates corresponding contours in the dataset.
14 |
15 | 3. Color Mapping (`apply_color_map`):
16 | - Applies a color map to the isosurface actor.
17 | - The color mapping is based on the scalar values, enhancing the visualization of the isosurface.
18 | - This step involves creating a vtkColorTransferFunction that maps scalar values to specific colors.
19 |
20 | 4. Visualization (`visualize_actor`):
21 | - Sets up a VTK renderer, render window, and interactor to display the isosurface.
22 | - The isosurface actor, created and colored in previous steps, is added to the VTK renderer for visualization.
23 | - The background color and other rendering settings are configured for optimal display.
24 | """
25 |
26 | from typing import List, Tuple
27 |
28 | import numpy as np
29 | import vtk
30 |
31 | # Constants
32 | BACKGROUND_COLOR = (0.1, 0.2, 0.3) # Background color for the visualization
33 |
34 |
35 | def create_sample_data(dimensions: Tuple[int, int, int]) -> vtk.vtkImageData:
36 | """
37 | Create a sample 3D scalar dataset using a mathematical function.
38 |
39 | Args:
40 | dimensions (Tuple[int, int, int]): Dimensions of the dataset (x, y, z).
41 |
42 | Returns:
43 | vtk.vtkImageData: The created 3D scalar dataset.
44 | """
45 | if not all(d > 0 for d in dimensions):
46 | raise ValueError("Dimensions must be positive integers")
47 |
48 | # Create an empty image data object
49 | imageData = vtk.vtkImageData()
50 | imageData.SetDimensions(dimensions)
51 | imageData.SetSpacing(1.0, 1.0, 1.0)
52 | imageData.SetOrigin(0, 0, 0)
53 |
54 | # Efficiently fill the image data with scalar values using NumPy
55 | x, y, z = np.indices(dimensions)
56 | values = np.sin(np.sqrt(x**2 + y**2 + z**2)).ravel()
57 |
58 | # Convert numpy array to VTK array
59 | scalars = vtk.vtkFloatArray()
60 | scalars.SetNumberOfValues(len(values))
61 | scalars.SetVoidArray(values, len(values), 1)
62 |
63 | imageData.GetPointData().SetScalars(scalars)
64 | return imageData
65 |
66 |
67 | def create_isosurface(
68 | data: vtk.vtkImageData, isovalue_range: List[float]
69 | ) -> vtk.vtkActor:
70 | """
71 | Create an isosurface with a range of isovalues from the given data.
72 |
73 | Args:
74 | data (vtk.vtkImageData): The input dataset.
75 | isovalue_range (List[float]): Range of isovalues.
76 |
77 | Returns:
78 | vtk.vtkActor: The actor representing the isosurface.
79 | """
80 | # Generate an isosurface
81 | contour = vtk.vtkContourFilter()
82 | contour.SetInputData(data)
83 | contour.GenerateValues(len(isovalue_range), isovalue_range[0], isovalue_range[-1])
84 |
85 | # Map the contours to graphical primitives
86 | mapper = vtk.vtkPolyDataMapper()
87 | mapper.SetInputConnection(contour.GetOutputPort())
88 | mapper.SetScalarRange(isovalue_range[0], isovalue_range[-1])
89 |
90 | # Create an actor for the contours
91 | actor = vtk.vtkActor()
92 | actor.SetMapper(mapper)
93 |
94 | return actor
95 |
96 |
97 | def apply_color_map(actor: vtk.vtkActor) -> None:
98 | """
99 | Apply a color map to the actor.
100 |
101 | Args:
102 | actor (vtk.vtkActor): The actor to apply the color map to.
103 | """
104 | # Create a color transfer function
105 | colorTransferFunction = vtk.vtkColorTransferFunction()
106 | colorTransferFunction.AddRGBPoint(-1.0, 0, 0, 1) # Blue for low values
107 | colorTransferFunction.AddRGBPoint(0, 0, 1, 0) # Green for mid values
108 | colorTransferFunction.AddRGBPoint(1.0, 1, 0, 0) # Red for high values
109 |
110 | # Apply the color transfer function to the actor
111 | actor.GetMapper().SetLookupTable(colorTransferFunction)
112 |
113 |
114 | def visualize_actor(actor: vtk.vtkActor) -> None:
115 | """
116 | Visualize the given actor in a render window.
117 |
118 | Args:
119 | actor (vtk.vtkActor): The actor to visualize.
120 | """
121 | # Create a renderer and render window
122 | renderer = vtk.vtkRenderer()
123 | renderWindow = vtk.vtkRenderWindow()
124 | renderWindow.AddRenderer(renderer)
125 |
126 | # Create a render window interactor
127 | renderWindowInteractor = vtk.vtkRenderWindowInteractor()
128 | renderWindowInteractor.SetRenderWindow(renderWindow)
129 |
130 | # Add the actor to the scene
131 | renderer.AddActor(actor)
132 | renderer.SetBackground(*BACKGROUND_COLOR)
133 |
134 | # Start the visualization
135 | renderWindow.Render()
136 | renderWindowInteractor.Start()
137 |
138 |
139 | # Main script
140 | if __name__ == "__main__":
141 | try:
142 | data = create_sample_data((50, 50, 50))
143 | iso_actor = create_isosurface(
144 | data, np.linspace(-1, 1, 10).tolist()
145 | ) # Isovalue range
146 | apply_color_map(iso_actor)
147 | visualize_actor(iso_actor)
148 | except Exception as e:
149 | print(f"Error: {e}")
150 |
--------------------------------------------------------------------------------
/src/02_advanced_shapes/multiple_dependent_objects.py:
--------------------------------------------------------------------------------
1 | import vtk
2 |
3 |
4 | def create_cube_mapper(center: tuple, length: float) -> vtk.vtkPolyDataMapper:
5 | cube_source = vtk.vtkCubeSource()
6 | cube_source.SetCenter(center)
7 | cube_source.SetXLength(length)
8 | cube_source.SetYLength(length)
9 | cube_source.SetZLength(length)
10 |
11 | cube_mapper = vtk.vtkPolyDataMapper()
12 | cube_mapper.SetInputConnection(cube_source.GetOutputPort())
13 |
14 | return cube_mapper
15 |
16 |
17 | def create_cone_mapper(
18 | center: tuple, height: float, radius: float, resolution: int = 30
19 | ) -> vtk.vtkPolyDataMapper:
20 | cone_source = vtk.vtkConeSource()
21 | cone_source.SetCenter(center)
22 | cone_source.SetHeight(height)
23 | cone_source.SetRadius(radius)
24 | cone_source.SetResolution(resolution)
25 |
26 | cone_mapper = vtk.vtkPolyDataMapper()
27 | cone_mapper.SetInputConnection(cone_source.GetOutputPort())
28 |
29 | return cone_mapper
30 |
31 |
32 | if __name__ == "__main__":
33 | cube_mapper = create_cube_mapper(center=(0, 0, 0), length=1.0)
34 | cone_mapper = create_cone_mapper(center=(0, 1.5, 0), height=1.5, radius=0.5)
35 |
36 | cube_actor = vtk.vtkActor()
37 | cube_actor.SetMapper(cube_mapper)
38 |
39 | cone_actor = vtk.vtkActor()
40 | cone_actor.SetMapper(cone_mapper)
41 |
42 | assembly = vtk.vtkAssembly()
43 | assembly.AddPart(cube_actor)
44 | assembly.AddPart(cone_actor)
45 |
46 | renderer = vtk.vtkRenderer()
47 | renderer.AddActor(assembly)
48 | renderer.SetBackground(0, 0, 0)
49 |
50 | window = vtk.vtkRenderWindow()
51 | window.AddRenderer(renderer)
52 | window.SetSize(800, 600)
53 |
54 | interactor = vtk.vtkRenderWindowInteractor()
55 | interactor.SetRenderWindow(window)
56 | interactor.Initialize()
57 |
58 | interactor.Start()
59 |
--------------------------------------------------------------------------------
/src/02_advanced_shapes/multiple_independent_objects.py:
--------------------------------------------------------------------------------
1 | import random
2 |
3 | import vtk
4 | from vtkmodules.util.numpy_support import vtk_to_numpy
5 |
6 |
7 | def create_cone(height: float, radius: float, resolution: int) -> vtk.vtkConeSource:
8 | cone = vtk.vtkConeSource()
9 | cone.SetHeight(height)
10 | cone.SetRadius(radius)
11 | cone.SetResolution(resolution)
12 | return cone
13 |
14 |
15 | def create_cube(length: float) -> vtk.vtkCubeSource:
16 | cube = vtk.vtkCubeSource()
17 | cube.SetXLength(length)
18 | cube.SetYLength(length)
19 | cube.SetZLength(length)
20 | return cube
21 |
22 |
23 | def create_sphere(
24 | radius: float, phi_resolution: int, theta_resolution: int
25 | ) -> vtk.vtkSphereSource:
26 | sphere = vtk.vtkSphereSource()
27 | sphere.SetRadius(radius)
28 | sphere.SetPhiResolution(phi_resolution)
29 | sphere.SetThetaResolution(theta_resolution)
30 | return sphere
31 |
32 |
33 | if __name__ == "__main__":
34 | # define sources
35 | cone = create_cone(height=5.0, radius=2.0, resolution=10)
36 | cube = create_cube(length=5.0)
37 | sphere = create_sphere(radius=3.0, phi_resolution=10, theta_resolution=10)
38 |
39 | sources = (cone, cube, sphere)
40 |
41 | mappers = []
42 | for source in sources:
43 | mapper = vtk.vtkPolyDataMapper()
44 | mapper.SetInputConnection(source.GetOutputPort())
45 | mappers.append(mapper)
46 |
47 | actors = []
48 | for mapper in mappers:
49 | actor = vtk.vtkActor()
50 | actor.SetMapper(mapper)
51 | actors.append(actor)
52 |
53 | renderers = []
54 | for i, actor in enumerate(actors):
55 | renderer = vtk.vtkRenderer()
56 | renderer.AddActor(actor)
57 | renderer.SetBackground(random.random(), random.random(), random.random())
58 | renderer.SetViewport(
59 | 0 + i * 1 / len(actors), 0.0, (i + 1) * 1 / len(actors), 1.0
60 | ) # x, y, width, height
61 | renderers.append(renderer)
62 |
63 | renderWindow = vtk.vtkRenderWindow()
64 | renderWindow.SetSize(800, 400)
65 |
66 | for renderer in renderers:
67 | renderWindow.AddRenderer(renderer)
68 |
69 | interactor = vtk.vtkRenderWindowInteractor()
70 | interactor.SetRenderWindow(renderWindow)
71 | interactor.Initialize()
72 | interactor.Start()
73 |
--------------------------------------------------------------------------------
/src/02_advanced_shapes/streamlines.py:
--------------------------------------------------------------------------------
1 | """
2 | This module demonstrates the visualization of a dipole field in a three-dimensional space using the Visualization Toolkit (VTK). A dipole field is a vector field that is typically created by two equal but opposite charges separated by a distance.
3 |
4 | Workflow:
5 | 1. Generate a structured grid of points in a 3D space.
6 | 2. Calculate the dipole field vectors at each point in the grid.
7 | 3. Combine these points and vectors into a vtkStructuredGrid object.
8 | 4. Create seed points for streamline initiation.
9 | 5. Generate streamlines representing the flow lines of the dipole field using vtkStreamTracer.
10 | 6. Visualize these streamlines using vtkPolyDataMapper, vtkActor, and vtkRenderer.
11 |
12 | Mathematics:
13 | - The dipole field at a point in space is calculated using the formula for the electric field due to point charges. The field due to each charge is \vec{E} = \frac{q \vec{r}}{4 \pi \epsilon_0 r^3}, where \vec{r} is the position vector relative to the charge, q is the charge magnitude, and \epsilon_0 is the vacuum permittivity.
14 | - The net field at any point is the vector sum of the fields due to both charges.
15 | - Streamlines are generated using vtkStreamTracer, which integrates the vector field to trace the paths of particles in the flow.
16 | """
17 |
18 | import numpy as np
19 | import vtk
20 |
21 |
22 | class DipoleFieldVisualization:
23 | def __init__(self, num_seed_points=30):
24 | self.num_seed_points = num_seed_points
25 | self.grid = self.create_structured_grid()
26 | self.seeds = self.create_seeds()
27 | self.streamer = self.create_streamlines()
28 |
29 | def create_structured_grid(self):
30 | points, vectors = self.generate_points_and_vectors()
31 | grid = vtk.vtkStructuredGrid()
32 | grid.SetDimensions(21, 21, 21)
33 | grid.SetPoints(points)
34 | grid.GetPointData().SetVectors(vectors)
35 | return grid
36 |
37 | def generate_points_and_vectors(self):
38 | points = vtk.vtkPoints()
39 | vectors = vtk.vtkDoubleArray()
40 | vectors.SetNumberOfComponents(3)
41 |
42 | for i in np.linspace(-10, 10, 21):
43 | for j in np.linspace(-10, 10, 21):
44 | for k in np.linspace(-10, 10, 21):
45 | points.InsertNextPoint(i, j, k)
46 | x, y, z = i, j, k
47 | r1 = np.sqrt((x - 1) ** 2 + y**2 + z**2) + 1e-2
48 | r2 = np.sqrt((x + 1) ** 2 + y**2 + z**2) + 1e-2
49 | vectors.InsertNextTuple3(
50 | (x - 1) / r1**3 - (x + 1) / r2**3,
51 | y / r1**3 - y / r2**3,
52 | z / r1**3 - z / r2**3,
53 | )
54 |
55 | return points, vectors
56 |
57 | def create_seeds(self):
58 | seeds = vtk.vtkPointSource()
59 | seeds.SetCenter(0, 0, 0)
60 | seeds.SetRadius(10)
61 | seeds.SetNumberOfPoints(self.num_seed_points)
62 | return seeds
63 |
64 | def create_streamlines(self):
65 | streamer = vtk.vtkStreamTracer()
66 | streamer.SetInputData(self.grid)
67 | streamer.SetSourceConnection(self.seeds.GetOutputPort())
68 | streamer.SetMaximumPropagation(500)
69 | streamer.SetIntegrationStepUnit(vtk.vtkStreamTracer.LENGTH_UNIT)
70 | streamer.SetInitialIntegrationStep(0.1)
71 | streamer.SetIntegrationDirectionToBoth()
72 | streamer.SetComputeVorticity(False)
73 | return streamer
74 |
75 | def visualize(self):
76 | mapper = vtk.vtkPolyDataMapper()
77 | mapper.SetInputConnection(self.streamer.GetOutputPort())
78 | actor = vtk.vtkActor()
79 | actor.SetMapper(mapper)
80 |
81 | renderer = vtk.vtkRenderer()
82 | renderer.AddActor(actor)
83 | renderer.SetBackground(0, 0, 0)
84 |
85 | render_window = vtk.vtkRenderWindow()
86 | render_window.AddRenderer(renderer)
87 |
88 | interactor = vtk.vtkRenderWindowInteractor()
89 | interactor.SetRenderWindow(render_window)
90 | interactor.Initialize()
91 | interactor.Start()
92 |
93 |
94 | if __name__ == "__main__":
95 | visualization = DipoleFieldVisualization()
96 | visualization.visualize()
97 |
--------------------------------------------------------------------------------
/src/02_advanced_shapes/triangulation.py:
--------------------------------------------------------------------------------
1 | """
2 | This module demonstrates the process of 3D triangulation and its visualization using the Visualization Toolkit (VTK). Triangulation is a fundamental operation in computational geometry, where a surface or volume is divided into simpler units, specifically triangles in 2D or tetrahedrons in 3D. These simple shapes facilitate easier rendering and enable complex geometrical shapes to be approximated with high accuracy.
3 |
4 | Workflow:
5 | 1. Generate a set of random points in 3D space.
6 | 2. Use the vtkDelaunay3D filter to perform Delaunay triangulation on these points.
7 | 3. Convert the output vtkUnstructuredGrid to vtkPolyData using vtkGeometryFilter.
8 | 4. Pass this vtkPolyData to vtkTriangleFilter to process and prepare it for visualization.
9 | 5. Create a vtkPolyDataMapper and vtkActor to render the triangulated geometry.
10 | 6. Set up a VTK renderer, render window, and interactor to display the result.
11 |
12 | Mathematics:
13 | - Delaunay Triangulation: For a given set of points in a space (R^3), Delaunay triangulation generates a mesh of tetrahedra such that no point is inside the circum-hypersphere of any tetrahedra. It maximizes the minimum angle of all the angles of the triangles in the triangulation, helping avoid skinny triangles.
14 | - 3D Space Representation: Points are randomly generated in a 3D space, each defined by (x, y, z) coordinates.
15 | - vtkDelaunay3D: This VTK filter computes the Delaunay triangulation in 3D. It outputs a vtkUnstructuredGrid representing the tetrahedral mesh.
16 | - vtkGeometryFilter: Converts the vtkUnstructuredGrid (tetrahedral mesh) to vtkPolyData, which is a suitable format for further processing and rendering.
17 | - vtkTriangleFilter: Processes the vtkPolyData to ensure that the geometry is represented purely with triangles, a requirement for many rendering and processing operations.
18 |
19 | """
20 |
21 | import random
22 |
23 | import vtk
24 |
25 |
26 | class Triangulation3D:
27 | def __init__(self, num_points=25):
28 | self.num_points = num_points
29 | self.points = vtk.vtkPoints()
30 | self.generate_random_points()
31 | self.triangulate()
32 |
33 | def generate_random_points(self):
34 | for _ in range(self.num_points):
35 | x, y, z = (
36 | random.uniform(-1, 1),
37 | random.uniform(-1, 1),
38 | random.uniform(-1, 1),
39 | )
40 | self.points.InsertNextPoint(x, y, z)
41 |
42 | def triangulate(self):
43 | input_polydata = vtk.vtkPolyData()
44 | input_polydata.SetPoints(self.points)
45 |
46 | delaunay = vtk.vtkDelaunay3D()
47 | delaunay.SetInputData(input_polydata)
48 | delaunay.Update()
49 |
50 | # Convert vtkUnstructuredGrid to vtkPolyData
51 | geometry_filter = vtk.vtkGeometryFilter()
52 | geometry_filter.SetInputConnection(delaunay.GetOutputPort())
53 | geometry_filter.Update()
54 |
55 | self.triangle_filter = vtk.vtkTriangleFilter()
56 | self.triangle_filter.SetInputConnection(geometry_filter.GetOutputPort())
57 | self.triangle_filter.PassLinesOn()
58 | self.triangle_filter.PassVertsOn()
59 | self.triangle_filter.Update()
60 |
61 | def get_actor(self):
62 | mapper = vtk.vtkPolyDataMapper()
63 | mapper.SetInputConnection(self.triangle_filter.GetOutputPort())
64 |
65 | actor = vtk.vtkActor()
66 | actor.SetMapper(mapper)
67 | actor.GetProperty().SetRepresentationToWireframe()
68 |
69 | return actor
70 |
71 |
72 | def main():
73 | triangulation = Triangulation3D()
74 |
75 | renderer = vtk.vtkRenderer()
76 | renderer.AddActor(triangulation.get_actor())
77 | renderer.SetBackground(0, 0, 0)
78 |
79 | render_window = vtk.vtkRenderWindow()
80 | render_window.AddRenderer(renderer)
81 |
82 | interactor = vtk.vtkRenderWindowInteractor()
83 | interactor.SetRenderWindow(render_window)
84 |
85 | interactor.Initialize()
86 | interactor.Start()
87 |
88 |
89 | if __name__ == "__main__":
90 | main()
91 |
--------------------------------------------------------------------------------
/src/02_advanced_shapes/visualization_techniques_comparison.py:
--------------------------------------------------------------------------------
1 | import random
2 |
3 | import vtk
4 |
5 |
6 | def create_render_window():
7 | render_window = vtk.vtkRenderWindow()
8 | render_window.SetSize(800, 600)
9 | interactor = vtk.vtkRenderWindowInteractor()
10 | interactor.SetRenderWindow(render_window)
11 | return render_window, interactor
12 |
13 |
14 | def create_data_source():
15 | volume_source = vtk.vtkRTAnalyticSource()
16 |
17 | vector_source = vtk.vtkPointSource()
18 | vector_source.SetNumberOfPoints(10)
19 | vector_source.Update()
20 |
21 | vectors = vtk.vtkFloatArray()
22 | vectors.SetNumberOfComponents(3)
23 | vectors.SetNumberOfTuples(vector_source.GetOutput().GetNumberOfPoints())
24 |
25 | for i in range(vectors.GetNumberOfTuples()):
26 | vectors.SetTuple3(i, 1, 2, 3)
27 |
28 | vector_source.GetOutput().GetPointData().SetVectors(vectors)
29 | return volume_source, vector_source
30 |
31 |
32 | def create_structured_grid():
33 | grid_dimensions = [10, 10, 10]
34 |
35 | structured_grid = vtk.vtkStructuredGrid()
36 | structured_grid.SetDimensions(grid_dimensions)
37 |
38 | points = vtk.vtkPoints()
39 |
40 | for z in range(grid_dimensions[2]):
41 | for y in range(grid_dimensions[1]):
42 | for x in range(grid_dimensions[0]):
43 | points.InsertNextPoint(x, y, z)
44 |
45 | structured_grid.SetPoints(points)
46 | return structured_grid
47 |
48 |
49 | def create_point_source():
50 | point_source = vtk.vtkPointSource()
51 | point_source.SetNumberOfPoints(50)
52 | point_source.SetRadius(3)
53 | point_source.Update()
54 | return point_source
55 |
56 |
57 | def create_visualizations(
58 | render_window,
59 | xmins,
60 | ymins,
61 | xmaxs,
62 | ymaxs,
63 | volume_source,
64 | structured_grid,
65 | point_source,
66 | vector_source,
67 | ):
68 | for i in range(4):
69 | renderer = vtk.vtkRenderer()
70 | render_window.AddRenderer(renderer)
71 | renderer.SetViewport(xmins[i], ymins[i], xmaxs[i], ymaxs[i])
72 |
73 | if i == 0: # Volume rendering
74 | create_volume_rendering(renderer, volume_source)
75 | elif i == 1: # Streamlines
76 | create_streamlines(renderer, structured_grid, point_source)
77 | elif i == 2: # Glyphs
78 | create_glyphs(renderer, vector_source)
79 | elif i == 3: # Contouring
80 | create_contouring(renderer, volume_source)
81 |
82 |
83 | def create_volume_rendering(renderer, volume_source):
84 | volume_mapper = vtk.vtkSmartVolumeMapper()
85 | volume_mapper.SetInputConnection(volume_source.GetOutputPort())
86 | volume = vtk.vtkVolume()
87 | volume.SetMapper(volume_mapper)
88 | renderer.AddVolume(volume)
89 |
90 | # Add text annotation
91 | text_actor = vtk.vtkTextActor()
92 | text_actor.SetInput("Volume Rendering")
93 | text_actor.GetTextProperty().SetFontSize(24)
94 | text_actor.GetTextProperty().SetColor(1, 1, 1) # White text
95 | renderer.AddActor2D(text_actor)
96 |
97 |
98 | def create_streamlines(renderer, structured_grid, point_source):
99 | vector_data_array = vtk.vtkDoubleArray()
100 | vector_data_array.SetNumberOfComponents(3)
101 | vector_data_array.SetNumberOfTuples(structured_grid.GetNumberOfPoints())
102 |
103 | for j in range(structured_grid.GetNumberOfPoints()):
104 | vector_data_array.SetTuple3(
105 | j, random.random(), random.random(), random.random()
106 | )
107 |
108 | vector_data_array.SetName("VectorField")
109 | structured_grid.GetPointData().SetVectors(vector_data_array)
110 |
111 | stream_tracer = vtk.vtkStreamTracer()
112 | stream_tracer.SetInputData(structured_grid)
113 | stream_tracer.SetSourceConnection(point_source.GetOutputPort())
114 | stream_tracer.SetMaximumPropagation(500)
115 | stream_tracer.SetInitialIntegrationStep(0.1)
116 | stream_tracer.SetIntegratorType(2)
117 |
118 | tube_filter = vtk.vtkTubeFilter()
119 | tube_filter.SetInputConnection(stream_tracer.GetOutputPort())
120 | tube_filter.SetRadius(0.1)
121 | tube_filter.SetNumberOfSides(6)
122 |
123 | streamline_mapper = vtk.vtkPolyDataMapper()
124 | streamline_mapper.SetInputConnection(tube_filter.GetOutputPort())
125 | streamline_actor = vtk.vtkActor()
126 | streamline_actor.SetMapper(streamline_mapper)
127 |
128 | renderer.AddActor(streamline_actor)
129 |
130 | # Add text annotation
131 | text_actor = vtk.vtkTextActor()
132 | text_actor.SetInput("Streamlines")
133 | text_actor.GetTextProperty().SetFontSize(24)
134 | text_actor.GetTextProperty().SetColor(1, 1, 1) # White text
135 | renderer.AddActor2D(text_actor)
136 |
137 |
138 | def create_glyphs(renderer, vector_source):
139 | # Create a glyph source and mapper
140 | glyph_source = vtk.vtkArrowSource()
141 | glyph3D = vtk.vtkGlyph3D()
142 | glyph3D.SetSourceConnection(glyph_source.GetOutputPort())
143 | glyph3D.SetInputConnection(vector_source.GetOutputPort())
144 | glyph3D.SetVectorModeToUseVector()
145 | glyph3D.SetScaleModeToScaleByVector()
146 | glyph3D.SetScaleFactor(0.1)
147 | glyph_mapper = vtk.vtkPolyDataMapper()
148 | glyph_mapper.SetInputConnection(glyph3D.GetOutputPort())
149 | # Create an actor
150 | glyph_actor = vtk.vtkActor()
151 | glyph_actor.SetMapper(glyph_mapper)
152 | renderer.AddActor(glyph_actor)
153 |
154 | # Add text annotation
155 | text_actor = vtk.vtkTextActor()
156 | text_actor.SetInput("Glyphs")
157 | text_actor.GetTextProperty().SetFontSize(24)
158 | text_actor.GetTextProperty().SetColor(1, 1, 1) # White text
159 | renderer.AddActor2D(text_actor)
160 |
161 |
162 | def create_contouring(renderer, volume_source):
163 | contour_filter = vtk.vtkContourFilter()
164 | contour_filter.SetInputConnection(volume_source.GetOutputPort())
165 | contour_filter.SetValue(0, 150)
166 |
167 | contour_mapper = vtk.vtkPolyDataMapper()
168 | contour_mapper.SetInputConnection(contour_filter.GetOutputPort())
169 |
170 | contour_actor = vtk.vtkActor()
171 | contour_actor.SetMapper(contour_mapper)
172 | renderer.AddActor(contour_actor)
173 |
174 | # Add text annotation
175 | text_actor = vtk.vtkTextActor()
176 | text_actor.SetInput("Contouring")
177 | text_actor.GetTextProperty().SetFontSize(24)
178 | text_actor.GetTextProperty().SetColor(1, 1, 1) # White text
179 | renderer.AddActor2D(text_actor)
180 |
181 |
182 | def main():
183 | xmins = [0, 0.5, 0, 0.5]
184 | xmaxs = [0.5, 1, 0.5, 1]
185 | ymins = [0, 0, 0.5, 0.5]
186 | ymaxs = [0.5, 0.5, 1, 1]
187 |
188 | render_window, interactor = create_render_window()
189 | volume_source, vector_source = create_data_source()
190 | structured_grid = create_structured_grid()
191 | point_source = create_point_source()
192 |
193 | create_visualizations(
194 | render_window,
195 | xmins,
196 | ymins,
197 | xmaxs,
198 | ymaxs,
199 | volume_source,
200 | structured_grid,
201 | point_source,
202 | vector_source,
203 | )
204 |
205 | interactor.Initialize()
206 | interactor.Start()
207 |
208 |
209 | if __name__ == "__main__":
210 | main()
211 |
--------------------------------------------------------------------------------
/src/02_advanced_shapes/volume_rendering.py:
--------------------------------------------------------------------------------
1 | """
2 | This module demonstrates volume rendering in three-dimensional space using the Visualization Toolkit (VTK). Volume rendering is a technique used to display a 3D volume of data, typically visualizing scalar fields within a given space.
3 |
4 | Workflow:
5 | 1. Generate synthetic volume data as a 3D grid of scalars (voxels).
6 | 2. Define opacity and color transfer functions to map scalar values to opacity and color.
7 | 3. Combine these transfer functions into volume properties.
8 | 4. Set up a volume mapper to map the 3D volume data to 2D screen space.
9 | 5. Create a volume actor to position and orient the volume in the scene.
10 | 6. Initialize a renderer, render window, and interactor to display the volume.
11 |
12 | Mathematics:
13 | - Scalar Field: The module creates a synthetic scalar field where each voxel's scalar value is determined by its coordinates (x, y, z).
14 | - Opacity Transfer Function: This function maps scalar values to opacity levels, controlling how transparent or opaque each voxel appears. Typically, lower scalar values are more transparent, and higher values are more opaque.
15 | - Color Transfer Function: Similar to opacity, this function maps scalar values to colors, allowing for visual differentiation based on the scalar value.
16 | - Volume Rendering: The process involves casting rays through the volume data and accumulating color and opacity along the way based on the transfer functions. The final image is a composite of these contributions, creating a 3D representation of the scalar field.
17 | """
18 |
19 | import vtk
20 |
21 |
22 | class VolumeRenderer:
23 | def __init__(self):
24 | self.volume_data = self.create_volume_data()
25 | self.opacity_transfer_function = self.create_opacity_transfer_function()
26 | self.color_transfer_function = self.create_color_transfer_function()
27 | self.volume_properties = self.create_volume_properties()
28 | self.volume_mapper = self.create_volume_mapper()
29 | self.volume_actor = self.create_volume_actor()
30 |
31 | def create_volume_data(self):
32 | volume_data = vtk.vtkImageData()
33 | volume_data.SetDimensions(50, 50, 50)
34 | volume_data.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 1)
35 |
36 | for z in range(50):
37 | for y in range(50):
38 | for x in range(50):
39 | scalar_value = x + y + z
40 | volume_data.SetScalarComponentFromDouble(x, y, z, 0, scalar_value)
41 | return volume_data
42 |
43 | def create_opacity_transfer_function(self):
44 | opacity_tf = vtk.vtkPiecewiseFunction()
45 | opacity_tf.AddPoint(0, 0.0)
46 | opacity_tf.AddPoint(255, 1.0)
47 | return opacity_tf
48 |
49 | def create_color_transfer_function(self):
50 | color_tf = vtk.vtkColorTransferFunction()
51 | color_tf.AddRGBPoint(0.0, 0.0, 0.0, 1.0)
52 | color_tf.AddRGBPoint(255.0, 1.0, 0.0, 0.0)
53 | return color_tf
54 |
55 | def create_volume_properties(self):
56 | volume_properties = vtk.vtkVolumeProperty()
57 | volume_properties.SetColor(self.color_transfer_function)
58 | volume_properties.SetScalarOpacity(self.opacity_transfer_function)
59 | volume_properties.ShadeOn()
60 | return volume_properties
61 |
62 | def create_volume_mapper(self):
63 | volume_mapper = vtk.vtkSmartVolumeMapper()
64 | volume_mapper.SetInputData(self.volume_data)
65 | return volume_mapper
66 |
67 | def create_volume_actor(self):
68 | volume_actor = vtk.vtkVolume()
69 | volume_actor.SetMapper(self.volume_mapper)
70 | volume_actor.SetProperty(self.volume_properties)
71 | return volume_actor
72 |
73 | def render(self):
74 | renderer = vtk.vtkRenderer()
75 | render_window = vtk.vtkRenderWindow()
76 | render_window_interactor = vtk.vtkRenderWindowInteractor()
77 |
78 | render_window.AddRenderer(renderer)
79 | render_window_interactor.SetRenderWindow(render_window)
80 |
81 | renderer.AddVolume(self.volume_actor)
82 |
83 | render_window_interactor.Initialize()
84 | render_window.Render()
85 | render_window.SetWindowName("Volume Rendering - Cube")
86 | render_window_interactor.Start()
87 |
88 |
89 | if __name__ == "__main__":
90 | volume_renderer = VolumeRenderer()
91 | volume_renderer.render()
92 |
--------------------------------------------------------------------------------
/src/03_structures_and_datasets/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/djeada/Vtk-Examples/e9105e31800958705894eb94925ad251d2ad0117/src/03_structures_and_datasets/__init__.py
--------------------------------------------------------------------------------
/src/03_structures_and_datasets/ahmed_body_visualization.py:
--------------------------------------------------------------------------------
1 | import vtk
2 | import numpy as np
3 |
4 |
5 | # Load the STL file into VTK
6 | def load_stl_geometry(file_path):
7 | reader = vtk.vtkSTLReader()
8 | reader.SetFileName(file_path)
9 | reader.Update()
10 | return reader.GetOutput()
11 |
12 |
13 | # Apply scalar values to the geometry
14 | def apply_scalar_values(geometry):
15 | scalar_values = vtk.vtkDoubleArray()
16 | scalar_values.SetName("StaticPressure")
17 | scalar_values.SetNumberOfComponents(1)
18 |
19 | num_points = geometry.GetNumberOfPoints()
20 | for i in range(num_points):
21 | scalar_value = np.sin(i / num_points * np.pi * 2) * 300 # Example values
22 | scalar_values.InsertNextValue(scalar_value)
23 |
24 | geometry.GetPointData().SetScalars(scalar_values)
25 |
26 |
27 | # Create a color legend bar
28 | def create_color_legend(mapper):
29 | scalar_bar = vtk.vtkScalarBarActor()
30 | scalar_bar.SetLookupTable(mapper.GetLookupTable())
31 | scalar_bar.SetTitle("Static Pressure")
32 | scalar_bar.GetLabelTextProperty().SetColor(0, 0, 0)
33 | scalar_bar.GetTitleTextProperty().SetColor(0, 0, 0)
34 | scalar_bar.SetNumberOfLabels(5)
35 | return scalar_bar
36 |
37 |
38 | # Visualize the geometry with scalar values
39 | def visualize_geometry(geometry):
40 | mapper = vtk.vtkPolyDataMapper()
41 | mapper.SetInputData(geometry)
42 | mapper.SetScalarRange(-300, 300)
43 | mapper.SetScalarModeToUsePointData()
44 |
45 | actor = vtk.vtkActor()
46 | actor.SetMapper(mapper)
47 |
48 | renderer = vtk.vtkRenderer()
49 | renderer.AddActor(actor)
50 | renderer.SetBackground(1, 1, 1)
51 |
52 | # Create and add the color legend bar
53 | scalar_bar = create_color_legend(mapper)
54 | renderer.AddActor2D(scalar_bar)
55 |
56 | render_window = vtk.vtkRenderWindow()
57 | render_window.AddRenderer(renderer)
58 | render_window.SetSize(800, 600)
59 |
60 | render_window_interactor = vtk.vtkRenderWindowInteractor()
61 | render_window_interactor.SetRenderWindow(render_window)
62 |
63 | # Set up the title and labels
64 | title = vtk.vtkTextActor()
65 | title.SetInput("Ahmed Body CFD Simulation")
66 | title.GetTextProperty().SetFontSize(24)
67 | title.GetTextProperty().SetColor(0, 0, 0)
68 | title.SetPosition2(10, 570)
69 | renderer.AddActor2D(title)
70 |
71 | x_label = vtk.vtkTextActor()
72 | x_label.SetInput("X-Axis")
73 | x_label.GetTextProperty().SetFontSize(14)
74 | x_label.GetTextProperty().SetColor(0, 0, 0)
75 | x_label.SetPosition2(700, 30)
76 | renderer.AddActor2D(x_label)
77 |
78 | y_label = vtk.vtkTextActor()
79 | y_label.SetInput("Y-Axis")
80 | y_label.GetTextProperty().SetFontSize(14)
81 | y_label.GetTextProperty().SetColor(0, 0, 0)
82 | y_label.SetPosition2(30, 550)
83 | renderer.AddActor2D(y_label)
84 |
85 | render_window.Render()
86 | render_window_interactor.Start()
87 |
88 |
89 | # Main function to download, load, and visualize the Ahmed body
90 | def main():
91 | save_path = "../../data/stls/ahmed_body.stl"
92 |
93 | # Load the STL file
94 | car_geometry = load_stl_geometry(save_path)
95 |
96 | # Apply scalar values to the geometry
97 | apply_scalar_values(car_geometry)
98 |
99 | # Visualize the geometry with scalar values
100 | visualize_geometry(car_geometry)
101 |
102 |
103 | if __name__ == "__main__":
104 | main()
105 |
--------------------------------------------------------------------------------
/src/03_structures_and_datasets/cells.py:
--------------------------------------------------------------------------------
1 | """
2 | The cells in VTK represent a topology or a type of connectivity between points.
3 | They do not hold any positional data of their own but refer to points which are separately stored.
4 | They can be of various types: for example, a line (connecting two points), a triangle (connecting three points),
5 | or a tetrahedron (connecting four points).
6 | """
7 |
8 | import math
9 |
10 | import vtk
11 |
12 | from src.common.simple_pipeline import VisualisationPipeline
13 |
14 |
15 | def create_points_and_cell(cell_type, offset):
16 | points = vtk.vtkPoints()
17 | cell = None
18 |
19 | if cell_type == "triangle":
20 | points.InsertNextPoint(offset, 0, 0)
21 | points.InsertNextPoint(offset + 1, 0, 0)
22 | points.InsertNextPoint(offset + 0.5, 1, 0)
23 | cell = vtk.vtkTriangle()
24 | for i in range(3):
25 | cell.GetPointIds().SetId(i, i)
26 |
27 | elif cell_type == "quad":
28 | points.InsertNextPoint(offset + 2, 0, 0)
29 | points.InsertNextPoint(offset + 3, 0, 0)
30 | points.InsertNextPoint(offset + 3, 1, 0)
31 | points.InsertNextPoint(offset + 2, 1, 0)
32 | cell = vtk.vtkQuad()
33 | for i in range(4):
34 | cell.GetPointIds().SetId(i, i)
35 |
36 | elif cell_type == "line":
37 | points.InsertNextPoint(offset + 2, 0, 0)
38 | points.InsertNextPoint(offset + 7, 0, 0)
39 | cell = vtk.vtkLine()
40 | for i in range(2):
41 | cell.GetPointIds().SetId(i, i)
42 |
43 | elif cell_type == "vertex":
44 | points.InsertNextPoint(offset + 6, 0, 0)
45 | cell = vtk.vtkVertex()
46 | cell.GetPointIds().SetId(0, 0)
47 |
48 | elif cell_type == "polygon":
49 | for i in range(5):
50 | angle = 2 * math.pi * i / 5
51 | x = math.cos(angle) + offset + 7
52 | y = math.sin(angle)
53 | points.InsertNextPoint(x, y, 0)
54 | cell = vtk.vtkPolygon()
55 | cell.GetPointIds().SetNumberOfIds(5)
56 | for i in range(5):
57 | cell.GetPointIds().SetId(i, i)
58 |
59 | elif cell_type == "tetra":
60 | points.InsertNextPoint(offset + 9, 0, 0)
61 | points.InsertNextPoint(offset + 10, 0, 0)
62 | points.InsertNextPoint(offset + 9.5, 1, 0)
63 | points.InsertNextPoint(offset + 9.75, 0.5, 1)
64 | cell = vtk.vtkTetra()
65 | for i in range(4):
66 | cell.GetPointIds().SetId(i, i)
67 |
68 | return points, cell
69 |
70 |
71 | def main():
72 | cell_types = ["triangle", "quad", "line", "vertex", "polygon", "tetra"]
73 | offsets = [0, 3, 6, 9, 12, 15]
74 |
75 | all_points = vtk.vtkPoints()
76 | all_cells = vtk.vtkCellArray()
77 |
78 | for cell_type, offset in zip(cell_types, offsets):
79 | points, cell = create_points_and_cell(cell_type, offset)
80 | point_ids = [
81 | all_points.InsertNextPoint(points.GetPoint(i))
82 | for i in range(points.GetNumberOfPoints())
83 | ]
84 | for i, pid in enumerate(point_ids):
85 | cell.GetPointIds().SetId(i, pid)
86 | all_cells.InsertNextCell(cell)
87 |
88 | polydata = vtk.vtkPolyData()
89 | polydata.SetPoints(all_points)
90 |
91 | # Set appropriate data for each cell type
92 | polydata.SetVerts(all_cells) # For vertices
93 | polydata.SetLines(all_cells) # For lines
94 | polydata.SetPolys(all_cells) # For polygons
95 |
96 | mapper = vtk.vtkPolyDataMapper()
97 | mapper.SetInputData(polydata)
98 |
99 | pipeline = VisualisationPipeline(mappers=[mapper])
100 | pipeline.run()
101 |
102 |
103 | if __name__ == "__main__":
104 | main()
105 |
--------------------------------------------------------------------------------
/src/03_structures_and_datasets/fields.py:
--------------------------------------------------------------------------------
1 | """
2 | Fields in VTK can be attached to both points and cells. In this example, I will demonstrate how to attach a scalar field to points and a vector field to cells. We can create a simple situation where we assign random scalar values to points and random vector values to cells.
3 | in VTK, you can store physical properties such as pressure, temperature, or any scalar or vector quantity associated with the points or cells in your dataset. These are often referred to as point data or cell data, respectively.
4 |
5 | Point Data: These are data attributes that are associated with the points of a dataset. For example, in a computational fluid dynamics (CFD) simulation, you might store the velocity vector at each point in the mesh as point data.
6 |
7 | Cell Data: These are data attributes that are associated with the cells of a dataset. For example, you might store the pressure or temperature within each cell of the mesh as cell data.
8 |
9 | Workflow Overview:
10 |
11 | 1. Point Creation (create_points):
12 | - Initializes a set of points in 3D space, laying the groundwork for constructing geometric shapes.
13 | - In this case, points defining the corners of a quad are created.
14 |
15 | 2. Quad Creation (create_quad):
16 | - Utilizes the previously defined points to create a quad cell, a basic polygonal element.
17 | - Demonstrates how cells are constructed from points to form geometric shapes.
18 |
19 | 3. Scalar Field Attachment (attach_scalar_field):
20 | - Attaches a scalar field to the points, assigning a random scalar value to each point.
21 | - This highlights how to associate data with geometric entities in VTK.
22 |
23 | 4. Vector Field Attachment (attach_vector_field):
24 | - Similar to the scalar field, a random vector field is attached to the cells of the polydata.
25 | - Shows the capability of VTK to handle complex data associations, including vectorial data.
26 |
27 | 5. Polydata Assembly (create_polydata):
28 | - Integrates the points and the quad cell into a vtkPolyData object, a versatile format for representing and manipulating geometric data in VTK.
29 |
30 | 6. Visualization Process:
31 | - The vtkPolyDataMapper maps the polydata to graphical primitives for rendering.
32 | - A visualization pipeline, provided by the 'VisualisationPipeline' class, is employed to render the polydata, showcasing the scalar and vector fields attached to it.
33 | """
34 |
35 | import numpy as np
36 | import vtk
37 |
38 | from src.common.simple_pipeline import VisualisationPipeline
39 |
40 |
41 | def create_points():
42 | """
43 | Create a set of points for the polydata.
44 | """
45 | points = vtk.vtkPoints()
46 | points.InsertNextPoint(0, 0, 0)
47 | points.InsertNextPoint(1, 0, 0)
48 | points.InsertNextPoint(0, 1, 0)
49 | points.InsertNextPoint(1, 1, 0)
50 | return points
51 |
52 |
53 | def create_quad(points):
54 | """
55 | Create a quad cell using the provided points.
56 | """
57 | quad = vtk.vtkQuad()
58 | # Assign points to the quad corners
59 | quad.GetPointIds().SetId(0, 0)
60 | quad.GetPointIds().SetId(1, 1)
61 | quad.GetPointIds().SetId(2, 3)
62 | quad.GetPointIds().SetId(3, 2)
63 | return quad
64 |
65 |
66 | def attach_scalar_field(points):
67 | """
68 | Attach a random scalar field to the points.
69 | """
70 | scalars = vtk.vtkFloatArray()
71 | scalars.SetName("Scalars")
72 | for i in range(points.GetNumberOfPoints()):
73 | scalars.InsertNextValue(np.random.rand())
74 | return scalars
75 |
76 |
77 | def attach_vector_field(cells):
78 | """
79 | Attach a random vector field to the cells.
80 | """
81 | vectors = vtk.vtkFloatArray()
82 | vectors.SetNumberOfComponents(3)
83 | vectors.SetName("Vectors")
84 | for i in range(cells.GetNumberOfCells()):
85 | vectors.InsertNextTuple3(np.random.rand(), np.random.rand(), np.random.rand())
86 | return vectors
87 |
88 |
89 | def create_polydata(points, quad):
90 | """
91 | Create polydata to hold the points and cells.
92 | """
93 | cells = vtk.vtkCellArray()
94 | cells.InsertNextCell(quad)
95 |
96 | polydata = vtk.vtkPolyData()
97 | polydata.SetPoints(points)
98 | polydata.SetPolys(cells)
99 | return polydata, cells
100 |
101 |
102 | def main():
103 | points = create_points()
104 | quad = create_quad(points)
105 | polydata, cells = create_polydata(points, quad)
106 |
107 | polydata.GetPointData().SetScalars(attach_scalar_field(points))
108 | polydata.GetCellData().SetVectors(attach_vector_field(cells))
109 |
110 | # Visualizing the fields
111 | mapper = vtk.vtkPolyDataMapper()
112 | mapper.SetInputData(polydata)
113 | mapper.SetScalarModeToUsePointData()
114 | mapper.SetColorModeToMapScalars()
115 | mapper.SelectColorArray("Scalars")
116 |
117 | pipeline = VisualisationPipeline(mappers=[mapper])
118 | pipeline.run()
119 |
120 |
121 | if __name__ == "__main__":
122 | main()
123 |
--------------------------------------------------------------------------------
/src/03_structures_and_datasets/generate_naca0012.py:
--------------------------------------------------------------------------------
1 | import vtk
2 | import numpy as np
3 |
4 |
5 | def naca0012(x):
6 | """Calculate the NACA 0012 airfoil shape."""
7 | m = 0
8 | p = 0
9 | t = 0.12
10 | c = 1.0
11 | y_t = (
12 | 5
13 | * t
14 | * c
15 | * (
16 | 0.2969 * np.sqrt(x / c)
17 | - 0.1260 * (x / c)
18 | - 0.3516 * (x / c) ** 2
19 | + 0.2843 * (x / c) ** 3
20 | - 0.1015 * (x / c) ** 4
21 | )
22 | )
23 | return y_t
24 |
25 |
26 | # Generate airfoil points
27 | x_coords = np.linspace(0, 1, 100)
28 | y_coords = naca0012(x_coords)
29 |
30 | # Create VTK points
31 | points = vtk.vtkPoints()
32 | for x, y in zip(x_coords, y_coords):
33 | points.InsertNextPoint(x, y, 0)
34 |
35 | # Create a polygon
36 | polygon = vtk.vtkPolygon()
37 | polygon.GetPointIds().SetNumberOfIds(len(x_coords))
38 | for i in range(len(x_coords)):
39 | polygon.GetPointIds().SetId(i, i)
40 |
41 | # Create a cell array to store the polygon
42 | polygons = vtk.vtkCellArray()
43 | polygons.InsertNextCell(polygon)
44 |
45 | # Create a polydata object
46 | polydata = vtk.vtkPolyData()
47 | polydata.SetPoints(points)
48 | polydata.SetPolys(polygons)
49 |
50 | # Write the polydata to a file
51 | writer = vtk.vtkXMLPolyDataWriter()
52 | writer.SetFileName("naca0012.vtp")
53 | writer.SetInputData(polydata)
54 | writer.Write()
55 |
56 | # Now, visualize the airfoil
57 | mapper = vtk.vtkPolyDataMapper()
58 | mapper.SetInputData(polydata)
59 |
60 | actor = vtk.vtkActor()
61 | actor.SetMapper(mapper)
62 |
63 | renderer = vtk.vtkRenderer()
64 | renderWindow = vtk.vtkRenderWindow()
65 | renderWindow.AddRenderer(renderer)
66 | renderWindowInteractor = vtk.vtkRenderWindowInteractor()
67 | renderWindowInteractor.SetRenderWindow(renderWindow)
68 |
69 | renderer.AddActor(actor)
70 | renderer.SetBackground(1, 1, 1)
71 |
72 | renderWindow.Render()
73 | renderWindowInteractor.Start()
74 |
--------------------------------------------------------------------------------
/src/03_structures_and_datasets/image_data.py:
--------------------------------------------------------------------------------
1 | from PIL import Image
2 | import numpy as np
3 | import vtk
4 |
5 |
6 | def create_gradient_image(width, height, filename="gradient_image.png"):
7 | """
8 | Create a gradient image and save it.
9 | """
10 | # Create a gradient from blue to green
11 | gradient = np.zeros((height, width, 3), dtype=np.uint8)
12 | for i in range(height):
13 | color = int(255 * i / height) # Gradient factor
14 | gradient[i, :, 0] = 255 - color
15 | gradient[i, :, 1] = color
16 |
17 | image = Image.fromarray(gradient, "RGB")
18 | image.save(filename)
19 | return filename
20 |
21 |
22 | def load_image_as_vtk_image_data(filename):
23 | """
24 | Load an image and convert it into vtkImageData.
25 | """
26 | reader = vtk.vtkPNGReader()
27 | reader.SetFileName(filename)
28 | reader.Update()
29 | return reader.GetOutput()
30 |
31 |
32 | def visualize_vtk_image_data(vtk_image_data):
33 | """
34 | Visualize vtkImageData.
35 | """
36 | # Map the image data through a lookup table
37 | color = vtk.vtkImageMapToColors()
38 | color.SetOutputFormatToRGB()
39 | color.SetInputData(vtk_image_data)
40 |
41 | # Create an actor
42 | actor = vtk.vtkImageActor()
43 | actor.GetMapper().SetInputConnection(color.GetOutputPort())
44 |
45 | # Create a renderer
46 | renderer = vtk.vtkRenderer()
47 | renderer.AddActor(actor)
48 | renderer.SetBackground(0, 0, 0) # Set black background
49 |
50 | # Create a render window
51 | render_window = vtk.vtkRenderWindow()
52 | render_window.AddRenderer(renderer)
53 |
54 | # Create a render window interactor
55 | render_window_interactor = vtk.vtkRenderWindowInteractor()
56 | render_window_interactor.SetRenderWindow(render_window)
57 |
58 | # Start the interaction
59 | render_window.Render()
60 | render_window_interactor.Start()
61 |
62 |
63 | def main():
64 | filename = create_gradient_image(256, 256)
65 | vtk_image_data = load_image_as_vtk_image_data(filename)
66 | visualize_vtk_image_data(vtk_image_data)
67 |
68 |
69 | if __name__ == "__main__":
70 | main()
71 |
--------------------------------------------------------------------------------
/src/03_structures_and_datasets/multiblock_dataset.py:
--------------------------------------------------------------------------------
1 | """
2 | A multiblock dataset in VTK is a composite dataset that can store other datasets including other composite datasets.
3 | - It is used to represent complex data where different regions can be meshed differently.
4 | - It is also used to group multiple datasets into one.
5 |
6 | Workflow Overview:
7 |
8 | 1. Geometric Source Creation:
9 | - The process begins with the dynamic creation of various geometric shapes such as spheres, cylinders, cones, and cubes.
10 | - Each shape is generated based on specific parameters (like radius, height, and dimensions), illustrating how VTK can be used to create a wide range of 3D objects.
11 |
12 | 2. Multiblock Dataset Assembly:
13 | - Once individual geometric shapes are created, they are assembled into a vtkMultiBlockDataSet.
14 | - This dataset serves as a container that can hold multiple disparate data sources, showcasing its capability to manage complex collections of 3D objects.
15 |
16 | 3. Conversion to PolyData:
17 | - The vtkMultiBlockDataSet is then converted into vtkPolyData, a versatile format in VTK used for rendering and visualizing geometric data.
18 | - This step is crucial as it transforms the multiblock dataset into a format that can be easily rendered by VTK's visualization pipeline.
19 |
20 | 4. Visualization Pipeline:
21 | - Finally, the polydata is fed into a pre-defined visualization pipeline, which is responsible for rendering the 3D objects on the screen.
22 | - This pipeline not only displays the assembled 3D shapes but also allows for interactive exploration of the scene, such as zooming and rotating the objects.
23 | """
24 |
25 | import vtk
26 |
27 | from src.common.simple_pipeline import VisualisationPipeline
28 |
29 |
30 | def create_geometric_source(source_type, **params):
31 | """
32 | Create and return a geometric source based on the specified type and parameters.
33 | Supported types: 'Sphere', 'Cylinder', 'Cone', 'Cube'.
34 | """
35 | if source_type == "Sphere":
36 | source = vtk.vtkSphereSource()
37 | source.SetRadius(params.get("radius", 1.0))
38 | source.SetCenter(params.get("center", [0.0, 0.0, 0.0]))
39 | elif source_type == "Cylinder":
40 | source = vtk.vtkCylinderSource()
41 | source.SetHeight(params.get("height", 2.0))
42 | source.SetRadius(params.get("radius", 0.5))
43 | elif source_type == "Cone":
44 | source = vtk.vtkConeSource()
45 | source.SetHeight(params.get("height", 2.0))
46 | source.SetRadius(params.get("radius", 0.5))
47 | elif source_type == "Cube":
48 | source = vtk.vtkCubeSource()
49 | source.SetXLength(params.get("length", 1.0))
50 | source.SetYLength(params.get("width", 1.0))
51 | source.SetZLength(params.get("height", 1.0))
52 | else:
53 | raise ValueError("Unsupported source type")
54 |
55 | source.Update()
56 | return source.GetOutput()
57 |
58 |
59 | def create_multiblock_dataset(sources):
60 | """
61 | Create a multiblock dataset from a list of VTK data sources.
62 | """
63 | multiBlock = vtk.vtkMultiBlockDataSet()
64 | multiBlock.SetNumberOfBlocks(len(sources))
65 | for i, source in enumerate(sources):
66 | multiBlock.SetBlock(i, source)
67 | return multiBlock
68 |
69 |
70 | def convert_to_polydata(multiBlock):
71 | """
72 | Convert the multiblock dataset to polydata.
73 | """
74 | geometryFilter = vtk.vtkCompositeDataGeometryFilter()
75 | geometryFilter.SetInputDataObject(multiBlock)
76 | geometryFilter.Update()
77 | return geometryFilter.GetOutput()
78 |
79 |
80 | def main():
81 | # Create various geometric sources
82 | sphere = create_geometric_source("Sphere", radius=1.0)
83 | cylinder = create_geometric_source("Cylinder", height=2.0, radius=0.5)
84 | cone = create_geometric_source("Cone", height=2.0, radius=0.5)
85 | cube = create_geometric_source("Cube", length=1.0, width=1.0, height=1.0)
86 |
87 | # Create a multiblock dataset containing all sources
88 | sources = [sphere, cylinder, cone, cube]
89 | multiBlock = create_multiblock_dataset(sources)
90 | polydata = convert_to_polydata(multiBlock)
91 |
92 | # Create a mapper
93 | mapper = vtk.vtkPolyDataMapper()
94 | mapper.SetInputData(polydata)
95 |
96 | # Run the visualization pipeline
97 | pipeline = VisualisationPipeline(mappers=[mapper], point_size=30)
98 | pipeline.run()
99 |
100 |
101 | if __name__ == "__main__":
102 | main()
103 |
--------------------------------------------------------------------------------
/src/03_structures_and_datasets/points.py:
--------------------------------------------------------------------------------
1 | """
2 | n VTK, a point is a location in space. Points are used to define the geometry of graphical primitives. You can think of points as the vertices of graphical primitives such as lines, polygons, and volumes.
3 |
4 | To store and manipulate points, VTK provides the vtkPoints class. This class stores an array of 3D points, and provides methods for inserting points, retrieving points, and other point-related operations.
5 | """
6 |
7 | import numpy as np
8 | import vtk
9 | import vtk.util.numpy_support as vtk_np
10 |
11 | from src.common.simple_pipeline import VisualisationPipeline
12 |
13 |
14 | def create_vtk_points():
15 | """
16 | Create a vtkPoints object and insert some points.
17 | """
18 | points = vtk.vtkPoints()
19 | points.InsertNextPoint(0.0, 0.0, 0.0)
20 | points.InsertNextPoint(1.0, 0.0, 0.0)
21 | points.InsertNextPoint(0.0, 1.0, 0.0)
22 | return points
23 |
24 |
25 | def print_points_info(points):
26 | """
27 | Print information about the vtkPoints object.
28 | """
29 | print("Number of points:", points.GetNumberOfPoints())
30 | for i in range(points.GetNumberOfPoints()):
31 | point = points.GetPoint(i)
32 | print(f"Point {i}: {point}")
33 |
34 |
35 | def vtk_points_to_numpy(points):
36 | """
37 | Convert vtkPoints to a NumPy array.
38 | """
39 | return vtk_np.vtk_to_numpy(points.GetData())
40 |
41 |
42 | def numpy_to_vtk_points(numpy_array):
43 | """
44 | Convert a NumPy array to vtkPoints.
45 | """
46 | vtk_points = vtk.vtkPoints()
47 | vtk_points.SetData(vtk_np.numpy_to_vtk(numpy_array))
48 | return vtk_points
49 |
50 |
51 | def create_and_visualize_polydata(points):
52 | """
53 | Create polydata from vtkPoints and visualize them.
54 | """
55 | polydata = vtk.vtkPolyData()
56 | polydata.SetPoints(points)
57 |
58 | glyphFilter = vtk.vtkVertexGlyphFilter()
59 | glyphFilter.SetInputData(polydata)
60 | glyphFilter.Update()
61 |
62 | mapper = vtk.vtkPolyDataMapper()
63 | mapper.SetInputConnection(glyphFilter.GetOutputPort())
64 |
65 | pipeline = VisualisationPipeline(mappers=[mapper], point_size=30)
66 | pipeline.run()
67 |
68 |
69 | def main():
70 | vtk_points = create_vtk_points()
71 | print_points_info(vtk_points)
72 |
73 | numpy_points = vtk_points_to_numpy(vtk_points)
74 | print("Numpy array:\n", numpy_points)
75 |
76 | new_numpy_points = np.array([[0.0, 0.0, 1.0], [1.0, 0.0, 1.0], [0.0, 1.0, 1.0]])
77 | new_vtk_points = numpy_to_vtk_points(new_numpy_points)
78 | print_points_info(new_vtk_points)
79 |
80 | create_and_visualize_polydata(vtk_points)
81 |
82 |
83 | if __name__ == "__main__":
84 | main()
85 |
--------------------------------------------------------------------------------
/src/03_structures_and_datasets/poly_data.py:
--------------------------------------------------------------------------------
1 | """
2 | This module demonstrates the creation and visualization of a simple triangle using the Visualization Toolkit (VTK). It is structured into several distinct steps, each utilizing specific VTK components for 3D graphics and visualization:
3 |
4 | 1. Point Creation (vtkPoints):
5 | - Responsible for defining and storing the coordinates of vertices in a 3D space.
6 | - In this example, three points are created to represent the vertices of a triangle.
7 |
8 | 2. Triangle Geometry (vtkTriangle):
9 | - Defines the geometry of a triangle by specifying the connectivity between the points.
10 | - It uses the points' indices to create a triangular cell.
11 |
12 | 3. Cell Array (vtkCellArray):
13 | - A collection of cells (in this case, just one triangle).
14 | - Used to store the triangle geometry and facilitates the handling of multiple cells.
15 |
16 | 4. PolyData Creation (vtkPolyData):
17 | - A data object that holds geometric and topological data.
18 | - In this example, it stores the points and the triangle cell, representing the complete geometry of the triangle.
19 |
20 | 5. Data Mapping (vtkPolyDataMapper):
21 | - Maps the polydata (geometric data) to graphical primitives.
22 | - Essential for rendering the data in a window.
23 |
24 | 6. Actor Creation (vtkActor):
25 | - Represents an entity in the rendering process.
26 | - It is linked with the data mapper and controls the rendering of the polydata.
27 |
28 | 7. Renderer and Render Window:
29 | - The renderer (vtkRenderer) adds the actor to the scene.
30 | - The render window (vtkRenderWindow) displays the rendered graphics.
31 |
32 | 8. Interaction:
33 | - The render window interactor (vtkRenderWindowInteractor) allows user interaction with the visualization, such as rotating and zooming.
34 |
35 | The module serves as an educational example to illustrate the basic components and workflow in VTK for creating and displaying simple geometric shapes in 3D. It highlights the use of polydata as a versatile structure for representing and manipulating geometric data in VTK, which is a cornerstone for more complex 3D visualizations in scientific and engineering applications.
36 | """
37 |
38 | import vtk
39 |
40 | from src.common.simple_pipeline import VisualisationPipeline
41 |
42 |
43 | def create_points():
44 | """
45 | Create and return a vtkPoints object with predefined points.
46 | """
47 | points = vtk.vtkPoints()
48 | points.InsertNextPoint([0.0, 0.0, 0.0]) # Point 1
49 | points.InsertNextPoint([1.0, 0.0, 0.0]) # Point 2
50 | points.InsertNextPoint([0.5, 0.866, 0.0]) # Point 3
51 | return points
52 |
53 |
54 | def create_triangle():
55 | """
56 | Create and return a vtkTriangle.
57 | """
58 | triangle = vtk.vtkTriangle()
59 | triangle.GetPointIds().SetId(0, 0) # Vertex 1
60 | triangle.GetPointIds().SetId(1, 1) # Vertex 2
61 | triangle.GetPointIds().SetId(2, 2) # Vertex 3
62 | return triangle
63 |
64 |
65 | def create_polydata(points, triangle):
66 | """
67 | Create and return a vtkPolyData object containing the points and triangle.
68 | """
69 | triangles = vtk.vtkCellArray()
70 | triangles.InsertNextCell(triangle)
71 |
72 | polydata = vtk.vtkPolyData()
73 | polydata.SetPoints(points)
74 | polydata.SetPolys(triangles)
75 | return polydata
76 |
77 |
78 | def main():
79 | points = create_points()
80 | triangle = create_triangle()
81 | polydata = create_polydata(points, triangle)
82 |
83 | mapper = vtk.vtkPolyDataMapper()
84 | mapper.SetInputData(polydata)
85 |
86 | pipeline = VisualisationPipeline(mappers=[mapper])
87 | pipeline.run()
88 |
89 |
90 | if __name__ == "__main__":
91 | main()
92 |
--------------------------------------------------------------------------------
/src/03_structures_and_datasets/rectilinear_grid.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import vtk
3 |
4 | from src.common.simple_pipeline import VisualisationPipeline
5 |
6 |
7 | def create_rectilinear_grid(x_coords, y_coords, z_coords):
8 | """
9 | Create and return a rectilinear grid.
10 | """
11 | rgrid = vtk.vtkRectilinearGrid()
12 | rgrid.SetDimensions(len(x_coords), len(y_coords), len(z_coords))
13 |
14 | # Set X coordinates
15 | x_array = vtk.vtkFloatArray()
16 | for x in x_coords:
17 | x_array.InsertNextValue(x)
18 | rgrid.SetXCoordinates(x_array)
19 |
20 | # Set Y coordinates
21 | y_array = vtk.vtkFloatArray()
22 | for y in y_coords:
23 | y_array.InsertNextValue(y)
24 | rgrid.SetYCoordinates(y_array)
25 |
26 | # Set Z coordinates
27 | z_array = vtk.vtkFloatArray()
28 | for z in z_coords:
29 | z_array.InsertNextValue(z)
30 | rgrid.SetZCoordinates(z_array)
31 |
32 | return rgrid
33 |
34 |
35 | def attach_fields_to_grid(rgrid):
36 | """
37 | Attach scalar and vector fields to the rectilinear grid.
38 | """
39 | # Attach a scalar field
40 | scalars = vtk.vtkFloatArray()
41 | scalars.SetName("Scalars")
42 | num_points = rgrid.GetNumberOfPoints()
43 | for i in range(num_points):
44 | scalars.InsertNextValue(np.random.rand())
45 | rgrid.GetPointData().SetScalars(scalars)
46 |
47 | # Attach a vector field
48 | vectors = vtk.vtkFloatArray()
49 | vectors.SetNumberOfComponents(3)
50 | vectors.SetName("Vectors")
51 | for i in range(num_points):
52 | vectors.InsertNextTuple3(np.random.rand(), np.random.rand(), np.random.rand())
53 | rgrid.GetPointData().SetVectors(vectors)
54 |
55 |
56 | def visualize_rectilinear_grid(rgrid):
57 | """
58 | Visualize the rectilinear grid with scalar and vector fields.
59 | """
60 | geometry_filter = vtk.vtkRectilinearGridGeometryFilter()
61 | geometry_filter.SetInputData(rgrid)
62 |
63 | mapper = vtk.vtkPolyDataMapper()
64 | mapper.SetInputConnection(geometry_filter.GetOutputPort())
65 | mapper.SetScalarModeToUsePointData()
66 | mapper.SetColorModeToMapScalars()
67 | mapper.SelectColorArray("Scalars")
68 |
69 | pipeline = VisualisationPipeline(mappers=[mapper], point_size=30)
70 | pipeline.run()
71 |
72 |
73 | def main():
74 | x_coords = np.linspace(0, 10, 11)
75 | y_coords = np.linspace(0, 5, 6)
76 | z_coords = np.linspace(0, 3, 4)
77 | rgrid = create_rectilinear_grid(x_coords, y_coords, z_coords)
78 | attach_fields_to_grid(rgrid)
79 | visualize_rectilinear_grid(rgrid)
80 |
81 |
82 | if __name__ == "__main__":
83 | main()
84 |
--------------------------------------------------------------------------------
/src/03_structures_and_datasets/structured_grid.py:
--------------------------------------------------------------------------------
1 | """
2 | Structured grids in VTK represent a mesh in which points are arranged in a regular lattice in 3D space. It is best suited for problems where the domain can be discretized as a regular grid. For example, in computational fluid dynamics, it is common to use a structured grid to represent the fluid domain.
3 |
4 | Workflow Overview:
5 |
6 | 1. Structured Grid Creation (create_structured_grid):
7 | - Initializes a vtkStructuredGrid with specified dimensions (nx, ny, nz), representing the grid's resolution in each direction.
8 | - Populates the grid with points in a regular, lattice-like arrangement using vtkPoints, illustrating how to define spatial coordinates in a structured grid.
9 | - Returns a fully defined vtkStructuredGrid, ready for visualization.
10 |
11 | 2. Visualization (visualize_structured_grid):
12 | - Takes the created structured grid as input and sets up a vtkDataSetMapper for it. The mapper translates the grid data into a format suitable for rendering.
13 | - Utilizes a predefined 'VisualisationPipeline' to handle the rendering process. This pipeline is configured to make the edges of the grid visible, enhancing the perception of the grid structure in 3D space.
14 |
15 | 3. Main Function (main):
16 | - Defines the dimensions for the structured grid.
17 | - Calls the grid creation and visualization functions, orchestrating the process from grid setup to rendering.
18 | """
19 |
20 | import vtk
21 |
22 | from src.common.simple_pipeline import VisualisationPipeline
23 |
24 |
25 | def create_structured_grid(nx, ny, nz):
26 | """
27 | Create a structured grid with specified dimensions.
28 |
29 | Args:
30 | nx, ny, nz (int): Dimensions of the grid in the x, y, and z directions.
31 |
32 | Returns:
33 | vtkStructuredGrid: A structured grid with the specified dimensions.
34 | """
35 | structuredGrid = vtk.vtkStructuredGrid()
36 | structuredGrid.SetDimensions(nx, ny, nz)
37 |
38 | points = vtk.vtkPoints()
39 | for k in range(nz):
40 | for j in range(ny):
41 | for i in range(nx):
42 | points.InsertNextPoint(i, j, k)
43 |
44 | structuredGrid.SetPoints(points)
45 | return structuredGrid
46 |
47 |
48 | def visualize_structured_grid(structuredGrid):
49 | """
50 | Visualize the given structured grid using a predefined visualization pipeline.
51 |
52 | Args:
53 | structuredGrid (vtkStructuredGrid): The structured grid to be visualized.
54 | """
55 | mapper = vtk.vtkDataSetMapper()
56 | mapper.SetInputData(structuredGrid)
57 |
58 | # Configure and run the visualization pipeline
59 | pipeline = VisualisationPipeline(mappers=[mapper], edges_visible=True)
60 | pipeline.run()
61 |
62 |
63 | def main():
64 | # Define dimensions for the structured grid
65 | nx, ny, nz = 6, 6, 2
66 |
67 | # Create and visualize the structured grid
68 | structuredGrid = create_structured_grid(nx, ny, nz)
69 | visualize_structured_grid(structuredGrid)
70 |
71 |
72 | if __name__ == "__main__":
73 | main()
74 |
--------------------------------------------------------------------------------
/src/03_structures_and_datasets/structured_mesh.py:
--------------------------------------------------------------------------------
1 | import vtk
2 |
3 |
4 | # Enhanced grid creation with function
5 | def create_structured_grid(dimensions):
6 | grid = vtk.vtkStructuredGrid()
7 | grid.SetDimensions(dimensions)
8 |
9 | points = vtk.vtkPoints()
10 | for z in range(dimensions[2]):
11 | for y in range(dimensions[1]):
12 | for x in range(dimensions[0]):
13 | points.InsertNextPoint(x, y, z)
14 | grid.SetPoints(points)
15 | return grid
16 |
17 |
18 | # Function to create a standard mapper and actor
19 | def create_actor(source, color=None, point_size=None, line_width=None):
20 | mapper = vtk.vtkPolyDataMapper()
21 | mapper.SetInputConnection(source.GetOutputPort())
22 |
23 | actor = vtk.vtkActor()
24 | actor.SetMapper(mapper)
25 |
26 | if color:
27 | actor.GetProperty().SetColor(color)
28 | if point_size:
29 | actor.GetProperty().SetPointSize(point_size)
30 | if line_width:
31 | actor.GetProperty().SetLineWidth(line_width)
32 |
33 | return actor
34 |
35 |
36 | # Grid dimensions
37 | dimensions = [10, 10, 10]
38 | structuredGrid = create_structured_grid(dimensions)
39 |
40 | # Outline creation
41 | outline = vtk.vtkStructuredGridOutlineFilter()
42 | outline.SetInputData(structuredGrid)
43 | outlineActor = create_actor(outline)
44 |
45 | # Points visualization
46 | pointGlyph = vtk.vtkVertexGlyphFilter()
47 | pointGlyph.SetInputData(structuredGrid)
48 | pointActor = create_actor(pointGlyph, point_size=1)
49 |
50 | # Highlight node
51 | highlightNode = vtk.vtkSphereSource()
52 | highlightNode.SetCenter(5, 5, 5)
53 | highlightNode.SetRadius(0.2)
54 | highlightNodeActor = create_actor(highlightNode, color=(1, 0, 0))
55 |
56 | # Edges visualization
57 | edgeFilter = vtk.vtkExtractEdges()
58 | edgeFilter.SetInputData(structuredGrid)
59 | edgeActor = create_actor(edgeFilter, color=(0.5, 0.5, 0.5), line_width=1)
60 |
61 | # Highlight edge
62 | highlightEdge = vtk.vtkLineSource()
63 | highlightEdge.SetPoint1(5, 5, 5)
64 | highlightEdge.SetPoint2(6, 5, 5)
65 | highlightEdgeActor = create_actor(highlightEdge, color=(0, 1, 0), line_width=3)
66 |
67 | # Highlight cell
68 | highlightCell = vtk.vtkCubeSource()
69 | highlightCell.SetCenter(7.5, 7.5, 7.5)
70 | highlightCell.SetXLength(1)
71 | highlightCell.SetYLength(1)
72 | highlightCell.SetZLength(1)
73 | highlightCellActor = create_actor(highlightCell, color=(0, 0, 1))
74 |
75 | # Legend creation
76 | legend = vtk.vtkLegendBoxActor()
77 | legend.SetNumberOfEntries(3)
78 | legend.SetEntry(0, vtk.vtkPolyData(), "Node (Red)", [1, 0, 0])
79 | legend.SetEntry(1, vtk.vtkPolyData(), "Edge (Green)", [0, 1, 0])
80 | legend.SetEntry(2, vtk.vtkPolyData(), "Cell (Blue)", [0, 0, 1])
81 |
82 | # Renderer and Render Window setup
83 | renderer = vtk.vtkRenderer()
84 | renderWindow = vtk.vtkRenderWindow()
85 | renderWindow.AddRenderer(renderer)
86 | renderWindow.SetSize(800, 600)
87 | renderer.SetBackground(0.2, 0.3, 0.4)
88 |
89 | # Render Window Interactor
90 | renderWindowInteractor = vtk.vtkRenderWindowInteractor()
91 | renderWindowInteractor.SetRenderWindow(renderWindow)
92 |
93 | # Adding actors and legend to renderer
94 | actors = [
95 | outlineActor,
96 | pointActor,
97 | edgeActor,
98 | highlightNodeActor,
99 | highlightEdgeActor,
100 | highlightCellActor,
101 | legend,
102 | ]
103 | for actor in actors:
104 | renderer.AddActor(actor)
105 |
106 |
107 | # Visibility toggle functions
108 | def toggle_visibility(actor):
109 | actor.SetVisibility(not actor.GetVisibility())
110 | renderWindow.Render()
111 |
112 |
113 | # Button creation and setup
114 | from src.common.button import Button2D
115 |
116 | # Create a 2D button for toggling points
117 | pointsButton = Button2D(renderWindowInteractor, "Points", (10, 10), (100, 40))
118 | pointsButton.add_click_callback(lambda: toggle_visibility(pointActor))
119 |
120 | # Create a 2D button for toggling edges
121 | edgesButton = Button2D(renderWindowInteractor, "Edges", (120, 10), (100, 40))
122 | edgesButton.add_click_callback(lambda: toggle_visibility(edgeActor))
123 |
124 | # Start the interaction
125 | renderWindow.Render()
126 | renderWindowInteractor.Start()
127 |
--------------------------------------------------------------------------------
/src/03_structures_and_datasets/unstructured_grid.py:
--------------------------------------------------------------------------------
1 | """
2 | This module demonstrates the creation, manipulation, and visualization of an unstructured grid using the Visualization Toolkit (VTK). An unstructured grid is a versatile data structure in VTK that allows for representing complex geometries composed of various types of cells. In this example, a hexahedron and a tetrahedron are created, along with their associated points, and then combined into a single unstructured grid. Additionally, scalar and vector fields are attached to this grid to illustrate the concept of data association with grid points and cells.
3 |
4 | Key Components and Workflow:
5 |
6 | 1. Hexahedron and Tetrahedron Creation:
7 | - Hexahedron (vtkHexahedron) and tetrahedron (vtkTetra) cells are created to represent two different 3D geometric shapes.
8 | - The point ids for each cell are set to define the geometry of these cells.
9 |
10 | 2. Points Creation (vtkPoints):
11 | - A vtkPoints object is created to store the coordinates of the vertices for both the hexahedron and tetrahedron.
12 |
13 | 3. Unstructured Grid (vtkUnstructuredGrid):
14 | - An unstructured grid is defined to hold the created cells.
15 | - This grid type is chosen for its ability to handle diverse cell types within a single data structure.
16 |
17 | 4. Scalar and Vector Fields:
18 | - Scalar values (random) are attached to the points of the grid, demonstrating how to associate data with grid points.
19 | - Vector values (random) are attached to the cells of the grid, showing data association with grid cells.
20 |
21 | 5. Visualization:
22 | - A vtkDataSetMapper is used to map the unstructured grid data to graphical primitives.
23 | - The visualization pipeline, encapsulated in the 'VisualisationPipeline' class, is then utilized to render the grid with the scalar and vector fields. The pipeline is configured to highlight the edges of the grid and enhance the visual understanding of its structure.
24 |
25 | """
26 |
27 | import numpy as np
28 | import vtk
29 |
30 | from src.common.simple_pipeline import VisualisationPipeline
31 |
32 |
33 | def create_hexahedron():
34 | """
35 | Create and return a hexahedron cell.
36 | """
37 | hexahedron = vtk.vtkHexahedron()
38 | for i in range(8):
39 | hexahedron.GetPointIds().SetId(i, i)
40 | return hexahedron
41 |
42 |
43 | def create_tetrahedron():
44 | """
45 | Create and return a tetrahedron cell.
46 | """
47 | tetrahedron = vtk.vtkTetra()
48 | for i in range(4):
49 | tetrahedron.GetPointIds().SetId(i, i + 8)
50 | return tetrahedron
51 |
52 |
53 | def create_points():
54 | """
55 | Create and return vtkPoints for the hexahedron and tetrahedron.
56 | """
57 | points = vtk.vtkPoints()
58 | # Hexahedron points
59 | for i in range(8):
60 | points.InsertNextPoint(i % 2, (i // 2) % 2, i // 4)
61 | # Tetrahedron points
62 | points.InsertNextPoint(2, 2, 2)
63 | points.InsertNextPoint(2, 3, 2)
64 | points.InsertNextPoint(3, 2, 2)
65 | points.InsertNextPoint(2, 2, 3)
66 | return points
67 |
68 |
69 | def create_unstructured_grid(points, hexahedron, tetrahedron):
70 | """
71 | Create and return an unstructured grid containing the hexahedron and tetrahedron.
72 | """
73 | ugrid = vtk.vtkUnstructuredGrid()
74 | ugrid.SetPoints(points)
75 | ugrid.InsertNextCell(hexahedron.GetCellType(), hexahedron.GetPointIds())
76 | ugrid.InsertNextCell(tetrahedron.GetCellType(), tetrahedron.GetPointIds())
77 | return ugrid
78 |
79 |
80 | def attach_fields_to_grid(ugrid, points):
81 | """
82 | Attach scalar and vector fields to the unstructured grid.
83 | """
84 | # Attach a scalar field to the points
85 | scalars = vtk.vtkFloatArray()
86 | scalars.SetName("Scalars")
87 | for i in range(points.GetNumberOfPoints()):
88 | scalars.InsertNextValue(np.random.rand())
89 | ugrid.GetPointData().SetScalars(scalars)
90 |
91 | # Attach a vector field to the cells
92 | vectors = vtk.vtkFloatArray()
93 | vectors.SetNumberOfComponents(3)
94 | vectors.SetName("Vectors")
95 | for i in range(ugrid.GetNumberOfCells()):
96 | vectors.InsertNextTuple3(np.random.rand(), np.random.rand(), np.random.rand())
97 | ugrid.GetCellData().SetVectors(vectors)
98 |
99 |
100 | def visualize_unstructured_grid(ugrid):
101 | """
102 | Visualize the unstructured grid with scalar and vector fields.
103 | """
104 | mapper = vtk.vtkDataSetMapper()
105 | mapper.SetInputData(ugrid)
106 | mapper.SetScalarModeToUsePointData()
107 | mapper.SetColorModeToMapScalars()
108 | mapper.SelectColorArray("Scalars")
109 |
110 | pipeline = VisualisationPipeline(mappers=[mapper], point_size=30)
111 | pipeline.run()
112 |
113 |
114 | def main():
115 | hexahedron = create_hexahedron()
116 | tetrahedron = create_tetrahedron()
117 | points = create_points()
118 | ugrid = create_unstructured_grid(points, hexahedron, tetrahedron)
119 | attach_fields_to_grid(ugrid, points)
120 | visualize_unstructured_grid(ugrid)
121 |
122 |
123 | if __name__ == "__main__":
124 | main()
125 |
--------------------------------------------------------------------------------
/src/03_structures_and_datasets/unstructured_mesh.py:
--------------------------------------------------------------------------------
1 | import random
2 |
3 | import vtk
4 |
5 |
6 | # Function to create an unstructured grid with a variety of cell types
7 | def create_unstructured_grid():
8 | grid = vtk.vtkUnstructuredGrid()
9 | points = vtk.vtkPoints()
10 |
11 | # Define points for a larger structure
12 | point_ids = [
13 | points.InsertNextPoint(x, y, z)
14 | for x in range(4)
15 | for y in range(4)
16 | for z in range(4)
17 | ]
18 |
19 | for x in range(4):
20 | for y in range(4):
21 | for z in range(4):
22 | # Add some randomness to the node positions
23 | dx, dy, dz = (
24 | random.uniform(-0.2, 0.2),
25 | random.uniform(-0.2, 0.2),
26 | random.uniform(-0.2, 0.2),
27 | )
28 | points.InsertNextPoint(x + dx, y + dy, z + dz)
29 |
30 | grid.SetPoints(points)
31 |
32 | # Add different types of cells to the unstructured grid
33 | for i in range(0, len(point_ids), 4):
34 | # Adding a hexahedron cell
35 | hexahedron = vtk.vtkHexahedron()
36 | for j in range(8):
37 | hexahedron.GetPointIds().SetId(j, (i + j) % len(point_ids))
38 | grid.InsertNextCell(hexahedron.GetCellType(), hexahedron.GetPointIds())
39 |
40 | # Adding a tetrahedron cell
41 | tetra = vtk.vtkTetra()
42 | for j in range(4):
43 | tetra.GetPointIds().SetId(j, (i + j) % len(point_ids))
44 | grid.InsertNextCell(tetra.GetCellType(), tetra.GetPointIds())
45 |
46 | return grid
47 |
48 |
49 | # Function to create a standard mapper and actor
50 | def create_actor(source, color=None, point_size=None, line_width=None):
51 | mapper = vtk.vtkPolyDataMapper()
52 | mapper.SetInputConnection(source.GetOutputPort())
53 |
54 | actor = vtk.vtkActor()
55 | actor.SetMapper(mapper)
56 |
57 | if color:
58 | actor.GetProperty().SetColor(color)
59 | if point_size:
60 | actor.GetProperty().SetPointSize(point_size)
61 | if line_width:
62 | actor.GetProperty().SetLineWidth(line_width)
63 |
64 | return actor
65 |
66 |
67 | # Create an unstructured grid
68 | unstructuredGrid = create_unstructured_grid()
69 |
70 | # Nodes visualization with smaller size
71 | nodeGlyph = vtk.vtkGlyph3D()
72 | nodeGlyph.SetInputData(unstructuredGrid)
73 | sphereSource = vtk.vtkSphereSource()
74 | sphereSource.SetRadius(0.05) # Smaller radius for nodes
75 | nodeGlyph.SetSourceConnection(sphereSource.GetOutputPort())
76 | nodeActor = create_actor(nodeGlyph, point_size=1)
77 |
78 | # Edges visualization with smaller width
79 | edgeFilter = vtk.vtkExtractEdges()
80 | edgeFilter.SetInputData(unstructuredGrid)
81 | edgeActor = create_actor(edgeFilter, line_width=0.5)
82 |
83 | # Highlight node
84 | highlightNode = vtk.vtkSphereSource()
85 | highlightNode.SetCenter(2, 2, 2)
86 | highlightNode.SetRadius(0.1)
87 | highlightNodeActor = create_actor(highlightNode, color=(1, 0, 0))
88 |
89 | # Highlight edge
90 | highlightEdge = vtk.vtkLineSource()
91 | highlightEdge.SetPoint1(1, 1, 1)
92 | highlightEdge.SetPoint2(2, 1, 1)
93 | highlightEdgeActor = create_actor(highlightEdge, color=(0, 1, 0), line_width=2)
94 |
95 | # Highlight cell
96 | highlightCell = vtk.vtkCubeSource()
97 | highlightCell.SetCenter(1.5, 1.5, 1.5)
98 | highlightCell.SetXLength(1)
99 | highlightCell.SetYLength(1)
100 | highlightCell.SetZLength(1)
101 | highlightCellActor = create_actor(highlightCell, color=(0, 0, 1))
102 |
103 | # Legend creation
104 | legend = vtk.vtkLegendBoxActor()
105 | legend.SetNumberOfEntries(3)
106 | legend.SetEntry(0, vtk.vtkPolyData(), "Node (Red)", [1, 0, 0])
107 | legend.SetEntry(1, vtk.vtkPolyData(), "Edge (Green)", [0, 1, 0])
108 | legend.SetEntry(2, vtk.vtkPolyData(), "Cell (Blue)", [0, 0, 1])
109 |
110 | # Renderer and Render Window setup
111 | renderer = vtk.vtkRenderer()
112 | renderWindow = vtk.vtkRenderWindow()
113 | renderWindow.AddRenderer(renderer)
114 | renderWindow.SetSize(800, 600)
115 | renderer.SetBackground(0.2, 0.3, 0.4)
116 |
117 | # Render Window Interactor
118 | renderWindowInteractor = vtk.vtkRenderWindowInteractor()
119 | renderWindowInteractor.SetRenderWindow(renderWindow)
120 |
121 | # Adding actors to renderer
122 | actors = [
123 | nodeActor,
124 | edgeActor,
125 | highlightNodeActor,
126 | highlightEdgeActor,
127 | highlightCellActor,
128 | legend,
129 | ]
130 | for actor in actors:
131 | renderer.AddActor(actor)
132 |
133 |
134 | # Visibility toggle functions
135 | def toggle_visibility(actor):
136 | actor.SetVisibility(not actor.GetVisibility())
137 | renderWindow.Render()
138 |
139 |
140 | # Button creation and setup
141 | from src.common.button import Button2D
142 |
143 | # Create a 2D button for toggling nodes
144 | nodesButton = Button2D(renderWindowInteractor, "Nodes", (10, 10), (100, 40))
145 | nodesButton.add_click_callback(lambda: toggle_visibility(nodeActor))
146 |
147 | # Create a 2D button for toggling edges
148 | edgesButton = Button2D(renderWindowInteractor, "Edges", (120, 10), (100, 40))
149 | edgesButton.add_click_callback(lambda: toggle_visibility(edgeActor))
150 |
151 | # Start the interaction
152 | renderWindow.Render()
153 | renderWindowInteractor.Start()
154 |
--------------------------------------------------------------------------------
/src/04_input_output/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/djeada/Vtk-Examples/e9105e31800958705894eb94925ad251d2ad0117/src/04_input_output/__init__.py
--------------------------------------------------------------------------------
/src/04_input_output/io_exodus_ii.py:
--------------------------------------------------------------------------------
1 | import vtk
2 | from vtkmodules.vtkCommonDataModel import vtkMultiBlockDataSet
3 |
4 | from src.common.simple_pipeline import VisualisationPipeline
5 |
6 | FILE_NAME = "../../data/exodus/tetrahedron.exo"
7 |
8 |
9 | def read_exodus(filename: str) -> vtkMultiBlockDataSet:
10 | """Read an Exodus II file."""
11 | reader = vtk.vtkExodusIIReader()
12 | reader.SetFileName(filename)
13 | reader.UpdateInformation()
14 | reader.SetAllArrayStatus(
15 | vtk.vtkExodusIIReader.NODAL, 1
16 | ) # Enables the reading of all nodal fields.
17 | reader.Update()
18 | return reader.GetOutput()
19 |
20 |
21 | def write_exodus(data: vtkMultiBlockDataSet, filename: str) -> None:
22 | """Write an Exodus II file."""
23 | writer = vtk.vtkExodusIIWriter()
24 | writer.SetFileName(filename)
25 | writer.SetInputData(data)
26 | writer.Write()
27 |
28 |
29 | def translate_mesh(input_block, dx, dy, dz):
30 | if isinstance(input_block, vtk.vtkMultiBlockDataSet):
31 | for i in range(input_block.GetNumberOfBlocks()):
32 | sub_block = input_block.GetBlock(i)
33 | if sub_block is not None:
34 | translate_mesh(sub_block, dx, dy, dz)
35 |
36 | elif isinstance(input_block, vtk.vtkPointSet):
37 | points = input_block.GetPoints()
38 | for i in range(points.GetNumberOfPoints()):
39 | x, y, z = points.GetPoint(i)
40 | points.SetPoint(i, x + dx, y + dy, z + dz)
41 |
42 |
43 | if __name__ == "__main__":
44 | # Read Exodus II file
45 | exodus_data = read_exodus(FILE_NAME)
46 |
47 | # Use vtkCompositeDataGeometryFilter to convert the multiblock dataset to polydata
48 | geometryFilter = vtk.vtkCompositeDataGeometryFilter()
49 | geometryFilter.SetInputDataObject(exodus_data)
50 | geometryFilter.Update()
51 |
52 | # Create a mapper and actor for the polydata
53 | mapper = vtk.vtkPolyDataMapper()
54 | mapper.SetInputConnection(geometryFilter.GetOutputPort())
55 | # Display
56 | pipeline = VisualisationPipeline(mappers=[mapper])
57 | pipeline.run()
58 |
59 | # Translate the mesh along the x-axis by 10 units
60 | translate_mesh(exodus_data, 10.0, 0.0, 0.0)
61 |
62 | # Write Exodus II file
63 | write_exodus(exodus_data, "output.exo")
64 |
--------------------------------------------------------------------------------
/src/04_input_output/io_obj.py:
--------------------------------------------------------------------------------
1 | import vtk
2 |
3 | from src.common.simple_pipeline import VisualisationPipeline
4 |
5 | FILE_NAME = "../../data/objs/cube.obj"
6 |
7 |
8 | def write_obj(data: vtk.vtkPolyData, filename: str):
9 | writer = vtk.vtkOBJWriter()
10 | writer.SetFileName(filename)
11 | writer.SetInputData(data)
12 | writer.Write()
13 |
14 |
15 | def read_obj(filename: str) -> vtk.vtkPolyData:
16 | reader = vtk.vtkOBJReader()
17 | reader.SetFileName(filename)
18 | reader.Update()
19 | return reader.GetOutput()
20 |
21 |
22 | def transform_polydata(polydata: vtk.vtkPolyData, transform: vtk.vtkTransform):
23 | transform_filter = vtk.vtkTransformPolyDataFilter()
24 | transform_filter.SetInputData(polydata)
25 | transform_filter.SetTransform(transform)
26 | transform_filter.Update()
27 | return transform_filter.GetOutput()
28 |
29 |
30 | if __name__ == "__main__":
31 |
32 | # Read OBJ file
33 | obj_data = read_obj(FILE_NAME)
34 |
35 | # Display for verification
36 | mapper = vtk.vtkPolyDataMapper()
37 | mapper.SetInputData(obj_data)
38 |
39 | # Display
40 | pipeline = VisualisationPipeline(mappers=[mapper])
41 | pipeline.run()
42 |
43 | # Apply a translation transform
44 | transform = vtk.vtkTransform()
45 | transform.Scale(2.0, 1.0, 1.0) # Double the size along the x-axis
46 | transform.RotateZ(45.0) # Rotate 45 degrees about the z-axis
47 | obj_data = transform_polydata(obj_data, transform)
48 |
49 | # Write OBJ file
50 | write_obj(obj_data, "../../data/objs/cube.obj")
51 |
--------------------------------------------------------------------------------
/src/04_input_output/io_openfoam.py:
--------------------------------------------------------------------------------
1 | import vtk
2 |
3 | from src.common.simple_pipeline import VisualisationPipeline
4 |
5 | FOAM_CASE_PATH = "../../data/open_foam/temp.case"
6 |
7 |
8 | def write_vtk(data: vtk.vtkMultiBlockDataSet, filename: str):
9 | writer = vtk.vtkXMLMultiBlockDataWriter()
10 | writer.SetFileName(filename)
11 | writer.SetInputData(data)
12 | writer.Write()
13 |
14 |
15 | def read_foam(case_path: str) -> vtk.vtkMultiBlockDataSet:
16 | reader = vtk.vtkOpenFOAMReader()
17 | reader.SetFileName(case_path + "/system/controlDict")
18 | reader.Update()
19 | return reader.GetOutput()
20 |
21 |
22 | def transform_block(block: vtk.vtkMultiBlockDataSet, transform: vtk.vtkTransform):
23 | transform_filter = vtk.vtkTransformFilter()
24 | transform_filter.SetInputData(block)
25 | transform_filter.SetTransform(transform)
26 | transform_filter.Update()
27 | return transform_filter.GetOutput()
28 |
29 |
30 | if __name__ == "__main__":
31 |
32 | # Read OpenFOAM case
33 | foam_data = read_foam(FOAM_CASE_PATH)
34 |
35 | # Display for verification
36 | mapper = vtk.vtkCompositePolyDataMapper2()
37 | mapper.SetInputData(foam_data)
38 |
39 | # Display
40 | pipeline = VisualisationPipeline(mappers=[mapper])
41 | pipeline.run()
42 |
43 | # Apply a translation transform
44 | transform = vtk.vtkTransform()
45 | transform.Scale(2.0, 1.0, 1.0) # Double the size along the x-axis
46 | transform.RotateZ(45.0) # Rotate 45 degrees about the z-axis
47 | foam_data = transform_block(foam_data, transform)
48 |
49 | # Write VTK file
50 | write_vtk(foam_data, "test.vtk")
51 |
--------------------------------------------------------------------------------
/src/04_input_output/io_stl.py:
--------------------------------------------------------------------------------
1 | import vtk
2 |
3 | from src.common.simple_pipeline import VisualisationPipeline
4 |
5 | FILE_NAME = "../../data/stls/cube.stl"
6 |
7 |
8 | def write_stl(data: vtk.vtkUnstructuredGrid, filename: str):
9 | writer = vtk.vtkSTLWriter()
10 | writer.SetFileName(filename)
11 | writer.SetInputData(data)
12 | writer.Write()
13 |
14 |
15 | def read_stl(filename: str) -> vtk.vtkPolyData:
16 | reader = vtk.vtkSTLReader()
17 | reader.SetFileName(filename)
18 | reader.Update()
19 | return reader.GetOutput()
20 |
21 |
22 | def transform_grid(grid: vtk.vtkUnstructuredGrid, transform: vtk.vtkTransform):
23 | transform_filter = vtk.vtkTransformFilter()
24 | transform_filter.SetInputData(grid)
25 | transform_filter.SetTransform(transform)
26 | transform_filter.Update()
27 | return transform_filter.GetOutput()
28 |
29 |
30 | if __name__ == "__main__":
31 |
32 | # Read STL file
33 | stl_data = read_stl(FILE_NAME)
34 |
35 | # Display for verification
36 | mapper = vtk.vtkDataSetMapper()
37 | mapper.SetInputData(stl_data)
38 |
39 | # Display
40 | pipeline = VisualisationPipeline(mappers=[mapper])
41 | pipeline.run()
42 |
43 | # Apply a translation transform
44 | transform = vtk.vtkTransform()
45 | transform.Scale(2.0, 1.0, 1.0) # Double the size along the x-axis
46 | transform.RotateZ(45.0) # Rotate 45 degrees about the z-axis
47 | stl_data = transform_grid(stl_data, transform)
48 |
49 | # Write STL file
50 | write_stl(stl_data, "test.stl")
51 |
--------------------------------------------------------------------------------
/src/04_input_output/io_vtk.py:
--------------------------------------------------------------------------------
1 | import vtk
2 |
3 | from src.common.simple_pipeline import VisualisationPipeline
4 |
5 | FILE_NAME = "../../data/vtks/grid_of_triangles.vtk"
6 |
7 |
8 | def write_vtk(data: vtk.vtkUnstructuredGrid, filename: str):
9 | writer = vtk.vtkUnstructuredGridWriter()
10 | writer.SetFileName(filename)
11 | writer.SetInputData(data)
12 | writer.Write()
13 |
14 |
15 | def read_vtk(filename: str) -> vtk.vtkUnstructuredGrid:
16 | reader = vtk.vtkUnstructuredGridReader()
17 | reader.SetFileName(filename)
18 | reader.Update()
19 | return reader.GetOutput()
20 |
21 |
22 | def transform_grid(grid: vtk.vtkUnstructuredGrid, transform: vtk.vtkTransform):
23 | transform_filter = vtk.vtkTransformFilter()
24 | transform_filter.SetInputData(grid)
25 | transform_filter.SetTransform(transform)
26 | transform_filter.Update()
27 | return transform_filter.GetOutput()
28 |
29 |
30 | def print_dataset_info(dataset: vtk.vtkUnstructuredGrid):
31 | point_data = dataset.GetPointData()
32 | cell_data = dataset.GetCellData()
33 |
34 | print(f"Number of point data arrays: {point_data.GetNumberOfArrays()}")
35 | for j in range(point_data.GetNumberOfArrays()):
36 | array = point_data.GetArray(j)
37 | print(f" Point data array {j}: {point_data.GetArrayName(j)}")
38 | print(f" Number of components: {array.GetNumberOfComponents()}")
39 | print(f" Number of tuples: {array.GetNumberOfTuples()}")
40 | print(f" Range: {array.GetRange()}")
41 |
42 | print(f"Number of cell data arrays: {cell_data.GetNumberOfArrays()}")
43 | for j in range(cell_data.GetNumberOfArrays()):
44 | array = cell_data.GetArray(j)
45 | print(f" Cell data array {j}: {cell_data.GetArrayName(j)}")
46 | print(f" Number of components: {array.GetNumberOfComponents()}")
47 | print(f" Number of tuples: {array.GetNumberOfTuples()}")
48 | print(f" Range: {array.GetRange()}")
49 |
50 |
51 | if __name__ == "__main__":
52 |
53 | # Read VTK file
54 | vtk_data = read_vtk(FILE_NAME)
55 |
56 | # Print dataset info
57 | print_dataset_info(vtk_data)
58 |
59 | # Display for verification
60 | mapper = vtk.vtkDataSetMapper()
61 | mapper.SetInputData(vtk_data)
62 |
63 | # Display
64 | pipeline = VisualisationPipeline(mappers=[mapper])
65 | pipeline.run()
66 |
67 | # Apply a translation transform
68 | transform = vtk.vtkTransform()
69 | transform.Scale(2.0, 1.0, 1.0) # Double the size along the x-axis
70 | transform.RotateZ(45.0) # Rotate 45 degrees about the z-axis
71 | vtk_data = transform_grid(vtk_data, transform)
72 |
73 | # Write VTK file
74 | write_vtk(vtk_data, "test.vtk")
75 |
--------------------------------------------------------------------------------
/src/04_input_output/io_vtm.py:
--------------------------------------------------------------------------------
1 | import vtk
2 |
3 | from src.common.simple_pipeline import VisualisationPipeline
4 |
5 | FILE_NAME = "../../data/vtms/grid_of_triangles.vtm"
6 |
7 |
8 | def write_vtm(data: vtk.vtkMultiBlockDataSet, filename: str):
9 | writer = vtk.vtkXMLMultiBlockDataWriter()
10 | writer.SetFileName(filename)
11 | writer.SetInputData(data)
12 | writer.Write()
13 |
14 |
15 | def read_vtm(filename: str) -> vtk.vtkMultiBlockDataSet:
16 | reader = vtk.vtkXMLMultiBlockDataReader()
17 | reader.SetFileName(filename)
18 | reader.Update()
19 | return reader.GetOutput()
20 |
21 |
22 | def print_dataset_info(dataset: vtk.vtkMultiBlockDataSet):
23 | for i in range(dataset.GetNumberOfBlocks()):
24 | block = dataset.GetBlock(i)
25 | if block:
26 | point_data = block.GetPointData()
27 | cell_data = block.GetCellData()
28 |
29 | print(f"Block {i}:")
30 | print(f" Number of point data arrays: {point_data.GetNumberOfArrays()}")
31 | for j in range(point_data.GetNumberOfArrays()):
32 | array = point_data.GetArray(j)
33 | print(f" Point data array {j}: {point_data.GetArrayName(j)}")
34 | print(f" Number of components: {array.GetNumberOfComponents()}")
35 | print(f" Number of tuples: {array.GetNumberOfTuples()}")
36 | print(f" Range: {array.GetRange()}")
37 |
38 | print(f" Number of cell data arrays: {cell_data.GetNumberOfArrays()}")
39 | for j in range(cell_data.GetNumberOfArrays()):
40 | array = cell_data.GetArray(j)
41 | print(f" Cell data array {j}: {cell_data.GetArrayName(j)}")
42 | print(f" Number of components: {array.GetNumberOfComponents()}")
43 | print(f" Number of tuples: {array.GetNumberOfTuples()}")
44 | print(f" Range: {array.GetRange()}")
45 |
46 |
47 | if __name__ == "__main__":
48 |
49 | # Read VTM file
50 | vtm_data = read_vtm(FILE_NAME)
51 |
52 | # Print dataset info
53 | print_dataset_info(vtm_data)
54 |
55 | # Use vtkCompositeDataGeometryFilter to convert the multiblock dataset to polydata
56 | geometryFilter = vtk.vtkCompositeDataGeometryFilter()
57 | geometryFilter.SetInputDataObject(vtm_data)
58 | geometryFilter.Update()
59 |
60 | # Create a mapper and actor for the polydata
61 | mapper = vtk.vtkPolyDataMapper()
62 | mapper.SetInputConnection(geometryFilter.GetOutputPort())
63 |
64 | # Display
65 | pipeline = VisualisationPipeline(mappers=[mapper])
66 | pipeline.run()
67 |
68 | # Write VTM file
69 | write_vtm(vtm_data, "test.vtm")
70 |
--------------------------------------------------------------------------------
/src/04_input_output/io_vtu.py:
--------------------------------------------------------------------------------
1 | import vtk
2 |
3 | from src.common.simple_pipeline import VisualisationPipeline
4 |
5 | FILE_NAME = "../../data/vtus/grid_of_triangles.vtu"
6 |
7 |
8 | def write_vtu(data: vtk.vtkUnstructuredGrid, filename: str):
9 | writer = vtk.vtkXMLUnstructuredGridWriter()
10 | writer.SetFileName(filename)
11 | writer.SetInputData(data)
12 | writer.Write()
13 |
14 |
15 | def read_vtu(filename: str) -> vtk.vtkUnstructuredGrid:
16 | reader = vtk.vtkXMLUnstructuredGridReader()
17 | reader.SetFileName(filename)
18 | reader.Update()
19 | return reader.GetOutput()
20 |
21 |
22 | def transform_grid(grid: vtk.vtkUnstructuredGrid, transform: vtk.vtkTransform):
23 | transform_filter = vtk.vtkTransformFilter()
24 | transform_filter.SetInputData(grid)
25 | transform_filter.SetTransform(transform)
26 | transform_filter.Update()
27 | return transform_filter.GetOutput()
28 |
29 |
30 | def print_dataset_info(dataset: vtk.vtkUnstructuredGrid):
31 | point_data = dataset.GetPointData()
32 | cell_data = dataset.GetCellData()
33 |
34 | print(f"Number of point data arrays: {point_data.GetNumberOfArrays()}")
35 | for j in range(point_data.GetNumberOfArrays()):
36 | array = point_data.GetArray(j)
37 | print(f" Point data array {j}: {point_data.GetArrayName(j)}")
38 | print(f" Number of components: {array.GetNumberOfComponents()}")
39 | print(f" Number of tuples: {array.GetNumberOfTuples()}")
40 | print(f" Range: {array.GetRange()}")
41 |
42 | print(f"Number of cell data arrays: {cell_data.GetNumberOfArrays()}")
43 | for j in range(cell_data.GetNumberOfArrays()):
44 | array = cell_data.GetArray(j)
45 | print(f" Cell data array {j}: {cell_data.GetArrayName(j)}")
46 | print(f" Number of components: {array.GetNumberOfComponents()}")
47 | print(f" Number of tuples: {array.GetNumberOfTuples()}")
48 | print(f" Range: {array.GetRange()}")
49 |
50 |
51 | if __name__ == "__main__":
52 |
53 | # Read VTU file
54 | vtu_data = read_vtu(FILE_NAME)
55 |
56 | # Print dataset info
57 | print_dataset_info(vtu_data)
58 |
59 | # Display for verification
60 | mapper = vtk.vtkDataSetMapper()
61 | mapper.SetInputData(vtu_data)
62 |
63 | # Display
64 | pipeline = VisualisationPipeline(mappers=[mapper])
65 | pipeline.run()
66 |
67 | # Apply a translation transform
68 | transform = vtk.vtkTransform()
69 | transform.Scale(2.0, 1.0, 1.0) # Double the size along the x-axis
70 | transform.RotateZ(45.0) # Rotate 45 degrees about the z-axis
71 | vtu_data = transform_grid(vtu_data, transform)
72 |
73 | # Write VTU file
74 | write_vtu(vtu_data, "test.vtu")
75 |
--------------------------------------------------------------------------------
/src/05_data_conversion/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/djeada/Vtk-Examples/e9105e31800958705894eb94925ad251d2ad0117/src/05_data_conversion/__init__.py
--------------------------------------------------------------------------------
/src/05_data_conversion/converter_interface.py:
--------------------------------------------------------------------------------
1 | from abc import ABC, abstractmethod
2 |
3 |
4 | class Converter(ABC):
5 | @abstractmethod
6 | def convert(self, input_filename: str, output_filename: str):
7 | pass
8 |
--------------------------------------------------------------------------------
/src/05_data_conversion/stl_obj.py:
--------------------------------------------------------------------------------
1 | import vtk
2 | import logging
3 | from converter_interface import Converter
4 |
5 |
6 | class StlToObjConverter(Converter):
7 | def convert(self, input_filename: str, output_filename: str):
8 | if not input_filename or not output_filename:
9 | raise ValueError("Input and output filenames must be provided.")
10 |
11 | if not (
12 | input_filename.lower().endswith(".stl")
13 | and output_filename.lower().endswith(".obj")
14 | ):
15 | raise ValueError("Invalid file extensions. Expected '.stl' and '.obj'.")
16 |
17 | try:
18 | # Read STL File
19 | reader = vtk.vtkSTLReader()
20 | reader.SetFileName(input_filename)
21 | reader.Update()
22 |
23 | # Write OBJ File
24 | writer = vtk.vtkOBJWriter()
25 | writer.SetFileName(output_filename)
26 | writer.SetInputConnection(reader.GetOutputPort())
27 | writer.Write()
28 | logging.info(
29 | f"Conversion successful: {input_filename} to {output_filename}"
30 | )
31 | except Exception as e:
32 | logging.error(f"Error during conversion: {e}")
33 | raise
34 |
35 |
36 | class ObjToStlConverter(Converter):
37 | def convert(self, input_filename: str, output_filename: str):
38 | if not input_filename or not output_filename:
39 | raise ValueError("Input and output filenames must be provided.")
40 |
41 | if not (
42 | input_filename.lower().endswith(".obj")
43 | and output_filename.lower().endswith(".stl")
44 | ):
45 | raise ValueError("Invalid file extensions. Expected '.obj' and '.stl'.")
46 |
47 | try:
48 | # Read OBJ File
49 | reader = vtk.vtkOBJReader()
50 | reader.SetFileName(input_filename)
51 | reader.Update()
52 |
53 | # Write STL File
54 | writer = vtk.vtkSTLWriter()
55 | writer.SetFileName(output_filename)
56 | writer.SetInputConnection(reader.GetOutputPort())
57 | writer.Write()
58 | logging.info(
59 | f"Conversion successful: {input_filename} to {output_filename}"
60 | )
61 | except Exception as e:
62 | logging.error(f"Error during conversion: {e}")
63 | raise
64 |
--------------------------------------------------------------------------------
/src/05_data_conversion/stl_vtk.py:
--------------------------------------------------------------------------------
1 | import vtk
2 | import logging
3 | from converter_interface import Converter
4 |
5 |
6 | class VtkToStlConverter(Converter):
7 | def convert(self, input_filename: str, output_filename: str):
8 | if not input_filename or not output_filename:
9 | raise ValueError("Input and output filenames must be provided.")
10 |
11 | if not (
12 | input_filename.lower().endswith(".vtk")
13 | and output_filename.lower().endswith(".stl")
14 | ):
15 | raise ValueError("Invalid file extensions. Expected '.vtk' and '.stl'.")
16 |
17 | try:
18 | # Read VTK File
19 | reader = vtk.vtkGenericDataObjectReader()
20 | reader.SetFileName(input_filename)
21 | reader.Update()
22 |
23 | # Write STL File
24 | writer = vtk.vtkSTLWriter()
25 | writer.SetFileName(output_filename)
26 | writer.SetInputConnection(reader.GetOutputPort())
27 | writer.Write()
28 | logging.info(
29 | f"Conversion successful: {input_filename} to {output_filename}"
30 | )
31 | except Exception as e:
32 | logging.error(f"Error during conversion: {e}")
33 | raise
34 |
35 |
36 | class StlToVtkConverter(Converter):
37 | def convert(self, input_filename: str, output_filename: str):
38 | if not input_filename or not output_filename:
39 | raise ValueError("Input and output filenames must be provided.")
40 |
41 | if not (
42 | input_filename.lower().endswith(".stl")
43 | and output_filename.lower().endswith(".vtk")
44 | ):
45 | raise ValueError("Invalid file extensions. Expected '.stl' and '.vtk'.")
46 |
47 | try:
48 | # Read STL File
49 | reader = vtk.vtkSTLReader()
50 | reader.SetFileName(input_filename)
51 | reader.Update()
52 |
53 | # Write VTK File
54 | writer = vtk.vtkPolyDataWriter()
55 | writer.SetFileName(output_filename)
56 | writer.SetInputConnection(reader.GetOutputPort())
57 | writer.Write()
58 | logging.info(
59 | f"Conversion successful: {input_filename} to {output_filename}"
60 | )
61 | except Exception as e:
62 | logging.error(f"Error during conversion: {e}")
63 | raise
64 |
--------------------------------------------------------------------------------
/src/05_data_conversion/vtk_obj.py:
--------------------------------------------------------------------------------
1 | import vtk
2 | import logging
3 | from converter_interface import Converter
4 |
5 |
6 | class VtkToObjConverter(Converter):
7 | def convert(self, input_filename: str, output_filename: str):
8 | if not input_filename or not output_filename:
9 | raise ValueError("Input and output filenames must be provided.")
10 |
11 | if not (
12 | input_filename.lower().endswith(".vtk")
13 | and output_filename.lower().endswith(".obj")
14 | ):
15 | raise ValueError("Invalid file extensions. Expected '.vtk' and '.obj'.")
16 |
17 | try:
18 | # Read VTK File
19 | reader = vtk.vtkGenericDataObjectReader()
20 | reader.SetFileName(input_filename)
21 | reader.Update()
22 |
23 | # Write OBJ File
24 | writer = vtk.vtkOBJWriter()
25 | writer.SetFileName(output_filename)
26 | writer.SetInputConnection(reader.GetOutputPort())
27 | writer.Write()
28 | logging.info(
29 | f"Conversion successful: {input_filename} to {output_filename}"
30 | )
31 | except Exception as e:
32 | logging.error(f"Error during conversion: {e}")
33 | raise
34 |
35 |
36 | class ObjToVtkConverter(Converter):
37 | def convert(self, input_filename: str, output_filename: str):
38 | if not input_filename or not output_filename:
39 | raise ValueError("Input and output filenames must be provided.")
40 |
41 | if not (
42 | input_filename.lower().endswith(".obj")
43 | and output_filename.lower().endswith(".vtk")
44 | ):
45 | raise ValueError("Invalid file extensions. Expected '.obj' and '.vtk'.")
46 |
47 | try:
48 | # Read OBJ File
49 | reader = vtk.vtkOBJReader()
50 | reader.SetFileName(input_filename)
51 | reader.Update()
52 |
53 | # Write VTK File
54 | writer = vtk.vtkDataSetWriter()
55 | writer.SetFileName(output_filename)
56 | writer.SetInputConnection(reader.GetOutputPort())
57 | writer.Write()
58 | logging.info(
59 | f"Conversion successful: {input_filename} to {output_filename}"
60 | )
61 | except Exception as e:
62 | logging.error(f"Error during conversion: {e}")
63 | raise
64 |
--------------------------------------------------------------------------------
/src/05_data_conversion/vtk_vtm.py:
--------------------------------------------------------------------------------
1 | import vtk
2 | import logging
3 | from converter_interface import Converter
4 |
5 |
6 | class VtkToVtmConverter(Converter):
7 | def convert(self, input_filename: str, output_filename: str):
8 | if not input_filename or not output_filename:
9 | raise ValueError("Input and output filenames must be provided.")
10 |
11 | if not (
12 | input_filename.lower().endswith(".vtk")
13 | and output_filename.lower().endswith(".vtm")
14 | ):
15 | raise ValueError("Invalid file extensions. Expected '.vtk' and '.vtm'.")
16 |
17 | try:
18 | # Read VTK File
19 | reader = vtk.vtkGenericDataObjectReader()
20 | reader.SetFileName(input_filename)
21 | reader.Update()
22 |
23 | # Create a multiblock dataset and add the output to it
24 | mbds = vtk.vtkMultiBlockDataSet()
25 | mbds.SetNumberOfBlocks(1)
26 | mbds.SetBlock(0, reader.GetOutput())
27 |
28 | # Write VTM File
29 | writer = vtk.vtkXMLMultiBlockDataWriter()
30 | writer.SetFileName(output_filename)
31 | writer.SetInputData(mbds)
32 | writer.Write()
33 | logging.info(
34 | f"Conversion successful: {input_filename} to {output_filename}"
35 | )
36 | except Exception as e:
37 | logging.error(f"Error during conversion: {e}")
38 | raise
39 |
40 |
41 | class VtmToVtkConverter(Converter):
42 | def convert(self, input_filename: str, output_filename: str):
43 | if not input_filename or not output_filename:
44 | raise ValueError("Input and output filenames must be provided.")
45 |
46 | if not (
47 | input_filename.lower().endswith(".vtm")
48 | and output_filename.lower().endswith(".vtk")
49 | ):
50 | raise ValueError("Invalid file extensions. Expected '.vtm' and '.vtk'.")
51 |
52 | try:
53 | # Read VTM File
54 | reader = vtk.vtkXMLMultiBlockDataReader()
55 | reader.SetFileName(input_filename)
56 | reader.Update()
57 |
58 | # Write VTK File
59 | writer = vtk.vtkDataSetWriter()
60 | writer.SetFileName(output_filename)
61 | writer.SetInputConnection(reader.GetOutputPort())
62 | writer.Write()
63 | logging.info(
64 | f"Conversion successful: {input_filename} to {output_filename}"
65 | )
66 | except Exception as e:
67 | logging.error(f"Error during conversion: {e}")
68 | raise
69 |
--------------------------------------------------------------------------------
/src/05_data_conversion/vtk_vtu.py:
--------------------------------------------------------------------------------
1 | import vtk
2 | import logging
3 | from converter_interface import Converter
4 |
5 |
6 | class VtkToVtuConverter(Converter):
7 | def convert(self, input_filename: str, output_filename: str):
8 | if not input_filename or not output_filename:
9 | raise ValueError("Input and output filenames must be provided.")
10 |
11 | if not (
12 | input_filename.lower().endswith(".vtk")
13 | and output_filename.lower().endswith(".vtu")
14 | ):
15 | raise ValueError("Invalid file extensions. Expected '.vtk' and '.vtu'.")
16 |
17 | try:
18 | # Read VTK File
19 | reader = vtk.vtkGenericDataObjectReader()
20 | reader.SetFileName(input_filename)
21 | reader.Update()
22 |
23 | # Write VTU File
24 | writer = vtk.vtkXMLUnstructuredGridWriter()
25 | writer.SetFileName(output_filename)
26 | writer.SetInputConnection(reader.GetOutputPort())
27 | writer.Write()
28 | logging.info(
29 | f"Conversion successful: {input_filename} to {output_filename}"
30 | )
31 | except Exception as e:
32 | logging.error(f"Error during conversion: {e}")
33 | raise
34 |
35 |
36 | class VtuToVtkConverter(Converter):
37 | def convert(self, input_filename: str, output_filename: str):
38 | if not input_filename or not output_filename:
39 | raise ValueError("Input and output filenames must be provided.")
40 |
41 | if not (
42 | input_filename.lower().endswith(".vtu")
43 | and output_filename.lower().endswith(".vtk")
44 | ):
45 | raise ValueError("Invalid file extensions. Expected '.vtu' and '.vtk'.")
46 |
47 | try:
48 | # Read VTU File
49 | reader = vtk.vtkXMLUnstructuredGridReader()
50 | reader.SetFileName(input_filename)
51 | reader.Update()
52 |
53 | # Write VTK File
54 | writer = vtk.vtkDataSetWriter()
55 | writer.SetFileName(output_filename)
56 | writer.SetInputConnection(reader.GetOutputPort())
57 | writer.Write()
58 | logging.info(
59 | f"Conversion successful: {input_filename} to {output_filename}"
60 | )
61 | except Exception as e:
62 | logging.error(f"Error during conversion: {e}")
63 | raise
64 |
--------------------------------------------------------------------------------
/src/06_visualization_pipeline/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/djeada/Vtk-Examples/e9105e31800958705894eb94925ad251d2ad0117/src/06_visualization_pipeline/__init__.py
--------------------------------------------------------------------------------
/src/06_visualization_pipeline/actor_mapper_multiple_objects.py:
--------------------------------------------------------------------------------
1 | import vtk
2 |
3 | # create a sphere source
4 | sphereSource = vtk.vtkSphereSource()
5 | sphereSource.SetCenter(0, 0, 0)
6 | sphereSource.SetRadius(1)
7 |
8 | # create a cube source
9 | cubeSource = vtk.vtkCubeSource()
10 | cubeSource.SetCenter(2, 0, 0)
11 | cubeSource.SetXLength(1)
12 | cubeSource.SetYLength(1)
13 | cubeSource.SetZLength(1)
14 |
15 | # create mappers
16 | sphereMapper = vtk.vtkPolyDataMapper()
17 | sphereMapper.SetInputConnection(sphereSource.GetOutputPort())
18 |
19 | cubeMapper = vtk.vtkPolyDataMapper()
20 | cubeMapper.SetInputConnection(cubeSource.GetOutputPort())
21 |
22 | # create actors
23 | sphereActor = vtk.vtkActor()
24 | sphereActor.SetMapper(sphereMapper)
25 |
26 | cubeActor = vtk.vtkActor()
27 | cubeActor.SetMapper(cubeMapper)
28 |
29 | # create a renderer and add both actors
30 | renderer = vtk.vtkRenderer()
31 | renderer.AddActor(sphereActor)
32 | renderer.AddActor(cubeActor)
33 |
34 | # create a render window and add the renderer
35 | renderWindow = vtk.vtkRenderWindow()
36 | renderWindow.AddRenderer(renderer)
37 |
38 | # create an interactor and set it up to work with the render window
39 | interactor = vtk.vtkRenderWindowInteractor()
40 | interactor.SetRenderWindow(renderWindow)
41 |
42 | # initialize the interactor and start the rendering loop
43 | interactor.Initialize()
44 | interactor.Start()
45 |
--------------------------------------------------------------------------------
/src/06_visualization_pipeline/adding_text_labels.py:
--------------------------------------------------------------------------------
1 | import vtk
2 |
3 | # Create a sphere
4 | sphereSource = vtk.vtkSphereSource()
5 | sphereSource.SetCenter(0.0, 0.0, 0.0)
6 | sphereSource.SetRadius(0.5)
7 |
8 | # Create a mapper
9 | mapper = vtk.vtkPolyDataMapper()
10 | mapper.SetInputConnection(sphereSource.GetOutputPort())
11 |
12 | # Create an actor
13 | actor = vtk.vtkActor()
14 | actor.SetMapper(mapper)
15 |
16 | # Create a renderer
17 | renderer = vtk.vtkRenderer()
18 | renderer.AddActor(actor)
19 |
20 | # Create a render window
21 | renderWindow = vtk.vtkRenderWindow()
22 | renderWindow.AddRenderer(renderer)
23 |
24 | # Create a text actor
25 | textActor = vtk.vtkTextActor()
26 | textActor.SetInput("This is a sphere")
27 | textActor.GetTextProperty().SetFontSize(24)
28 | textActor.GetTextProperty().SetColor(1.0, 0.0, 0.0) # Red text
29 | textActor.SetPosition(20, 20)
30 |
31 | # Add the text actor to the renderer
32 | renderer.AddActor2D(textActor)
33 |
34 | # Create an interactor
35 | interactor = vtk.vtkRenderWindowInteractor()
36 | interactor.SetRenderWindow(renderWindow)
37 |
38 | # Start the rendering loop
39 | interactor.Initialize()
40 | interactor.Start()
41 |
--------------------------------------------------------------------------------
/src/06_visualization_pipeline/camera_movement.py:
--------------------------------------------------------------------------------
1 | import math
2 |
3 | import vtk
4 |
5 | # Create a VTK renderer and render window
6 | renderer = vtk.vtkRenderer()
7 | render_window = vtk.vtkRenderWindow()
8 | render_window.AddRenderer(renderer)
9 |
10 | # Create a VTK render window interactor
11 | interactor = vtk.vtkRenderWindowInteractor()
12 | interactor.SetRenderWindow(render_window)
13 |
14 | # Create a VTK cone source and mapper
15 | cone_source = vtk.vtkConeSource()
16 | cone_mapper = vtk.vtkPolyDataMapper()
17 | cone_mapper.SetInputConnection(cone_source.GetOutputPort())
18 |
19 | # Create a VTK actor and set the mapper
20 | cone_actor = vtk.vtkActor()
21 | cone_actor.SetMapper(cone_mapper)
22 |
23 | # Add the actor to the renderer
24 | renderer.AddActor(cone_actor)
25 |
26 | # Set up the camera
27 | camera = vtk.vtkCamera()
28 | renderer.SetActiveCamera(camera)
29 |
30 | # Set initial camera parameters
31 | camera.SetPosition(0, 0, 5)
32 | camera.SetFocalPoint(0, 0, 0)
33 | camera.SetViewUp(0, 1, 0)
34 |
35 | # Define camera animation parameters
36 | num_frames = 100
37 | delta_angle = 360.0 / num_frames
38 |
39 |
40 | def animate_camera():
41 | for frame in range(num_frames):
42 | angle = frame * delta_angle
43 | rad_angle = math.radians(angle) # Convert angle to radians
44 |
45 | # Update camera position
46 | camera.SetPosition(5 * math.cos(rad_angle), 0, 5 * math.sin(rad_angle))
47 |
48 | # Update the render window
49 | render_window.Render()
50 |
51 |
52 | animate_camera()
53 |
54 | # Start the interactor
55 | interactor.Start()
56 |
--------------------------------------------------------------------------------
/src/06_visualization_pipeline/filters_in_action.py:
--------------------------------------------------------------------------------
1 | import vtk
2 |
3 | # create a cube source
4 | cubeSource = vtk.vtkCubeSource()
5 | cubeSource.SetCenter(-2, 0, 0) # Move the cube to the left
6 | cubeSource.SetXLength(1)
7 | cubeSource.SetYLength(1)
8 | cubeSource.SetZLength(1)
9 |
10 | # create a mapper for the original cube
11 | cubeMapper = vtk.vtkPolyDataMapper()
12 | cubeMapper.SetInputConnection(cubeSource.GetOutputPort())
13 |
14 | # create an actor for the original cube
15 | cubeActor = vtk.vtkActor()
16 | cubeActor.SetMapper(cubeMapper)
17 |
18 | # create an elevation filter
19 | elevationFilter = vtk.vtkElevationFilter()
20 | elevationFilter.SetInputConnection(cubeSource.GetOutputPort())
21 | elevationFilter.SetLowPoint(-1, -1, -1)
22 | elevationFilter.SetHighPoint(1, 1, 1)
23 |
24 | # create a mapper for the cube after elevation filter
25 | elevationMapper = vtk.vtkPolyDataMapper()
26 | elevationMapper.SetInputConnection(elevationFilter.GetOutputPort())
27 | elevationMapper.SetScalarRange(
28 | 0, 1
29 | ) # To use the scalar data generated from the elevation filter
30 |
31 | # create an actor for the cube after elevation filter
32 | elevationActor = vtk.vtkActor()
33 | elevationActor.SetMapper(elevationMapper)
34 | elevationActor.SetPosition(2, 0, 0) # Move this cube to the center
35 |
36 | # create a warp filter
37 | warpFilter = vtk.vtkWarpScalar()
38 | warpFilter.SetInputConnection(elevationFilter.GetOutputPort())
39 | warpFilter.SetScaleFactor(0.5) # Modify this to increase or decrease the deformation
40 |
41 | # create a mapper for the cube after warp filter
42 | warpMapper = vtk.vtkPolyDataMapper()
43 | warpMapper.SetInputConnection(warpFilter.GetOutputPort())
44 | warpMapper.SetScalarRange(
45 | 0, 1
46 | ) # To use the scalar data generated from the elevation filter
47 |
48 | # create an actor for the cube after warp filter
49 | warpActor = vtk.vtkActor()
50 | warpActor.SetMapper(warpMapper)
51 | warpActor.SetPosition(4, 0, 0) # Move this cube to the right
52 |
53 | # create a renderer and add the actors
54 | renderer = vtk.vtkRenderer()
55 | renderer.AddActor(cubeActor)
56 | renderer.AddActor(elevationActor)
57 | renderer.AddActor(warpActor)
58 |
59 | # create a render window and add the renderer
60 | renderWindow = vtk.vtkRenderWindow()
61 | renderWindow.AddRenderer(renderer)
62 |
63 | # create an interactor and set it up to work with the render window
64 | interactor = vtk.vtkRenderWindowInteractor()
65 | interactor.SetRenderWindow(renderWindow)
66 |
67 | # initialize the interactor and start the rendering loop
68 | interactor.Initialize()
69 | interactor.Start()
70 |
--------------------------------------------------------------------------------
/src/06_visualization_pipeline/lighting_and_shadows.py:
--------------------------------------------------------------------------------
1 | import vtk
2 |
3 |
4 | def create_scene():
5 | # Create a renderer and render window
6 | renderer = vtk.vtkRenderer()
7 | render_window = vtk.vtkRenderWindow()
8 | render_window.AddRenderer(renderer)
9 | render_window.SetSize(800, 600)
10 |
11 | # Create an interactor
12 | interactor = vtk.vtkRenderWindowInteractor()
13 | interactor.SetRenderWindow(render_window)
14 |
15 | # Create a light source
16 | light = vtk.vtkLight()
17 | light.SetFocalPoint(0, 0, 0)
18 | light.SetPosition(0, 0, 10)
19 | light.SetColor(1.0, 1.0, 1.0)
20 | renderer.AddLight(light)
21 |
22 | # Create a sphere
23 | sphere_source = vtk.vtkSphereSource()
24 | sphere_source.SetRadius(1.0)
25 | sphere_mapper = vtk.vtkPolyDataMapper()
26 | sphere_mapper.SetInputConnection(sphere_source.GetOutputPort())
27 | sphere_actor = vtk.vtkActor()
28 | sphere_actor.SetMapper(sphere_mapper)
29 | sphere_actor.GetProperty().SetColor(1.0, 0.0, 0.0) # Set sphere color to red
30 | sphere_actor.SetPosition(-1.5, 0, 0) # Set sphere position
31 | renderer.AddActor(sphere_actor)
32 |
33 | # Create a cube
34 | cube_source = vtk.vtkCubeSource()
35 | cube_source.SetXLength(1.0)
36 | cube_source.SetYLength(1.0)
37 | cube_source.SetZLength(1.0)
38 | cube_mapper = vtk.vtkPolyDataMapper()
39 | cube_mapper.SetInputConnection(cube_source.GetOutputPort())
40 | cube_actor = vtk.vtkActor()
41 | cube_actor.SetMapper(cube_mapper)
42 | cube_actor.GetProperty().SetColor(0.0, 1.0, 0.0) # Set cube color to green
43 | cube_actor.SetPosition(0, 0, 0) # Set cube position
44 | renderer.AddActor(cube_actor)
45 |
46 | # Create a cone
47 | cone_source = vtk.vtkConeSource()
48 | cone_source.SetHeight(2.0)
49 | cone_source.SetRadius(1.0)
50 | cone_mapper = vtk.vtkPolyDataMapper()
51 | cone_mapper.SetInputConnection(cone_source.GetOutputPort())
52 | cone_actor = vtk.vtkActor()
53 | cone_actor.SetMapper(cone_mapper)
54 | cone_actor.GetProperty().SetColor(0.0, 0.0, 1.0) # Set cone color to blue
55 | cone_actor.SetPosition(1.5, 0, 0) # Set cone position
56 | renderer.AddActor(cone_actor)
57 |
58 | # Set camera position and orientation
59 | camera = vtk.vtkCamera()
60 | camera.SetPosition(0, -5, 5)
61 | camera.SetFocalPoint(0, 0, 0)
62 | renderer.SetActiveCamera(camera)
63 |
64 | # Set background color to black
65 | renderer.SetBackground(0.0, 0.0, 0.0)
66 |
67 | # Initialize the interactor and start the rendering loop
68 | interactor.Initialize()
69 | render_window.Render()
70 | interactor.Start()
71 |
72 |
73 | if __name__ == "__main__":
74 | create_scene()
75 |
--------------------------------------------------------------------------------
/src/06_visualization_pipeline/pipeline_animation.py:
--------------------------------------------------------------------------------
1 | import vtk
2 |
3 | # Create a cube
4 | cubeSource = vtk.vtkCubeSource()
5 |
6 | # Create a mapper and set the cube source as its input
7 | cubeMapper = vtk.vtkPolyDataMapper()
8 | cubeMapper.SetInputConnection(cubeSource.GetOutputPort())
9 |
10 | # Create an actor and set the mapper as its input
11 | cubeActor = vtk.vtkActor()
12 | cubeActor.SetMapper(cubeMapper)
13 |
14 | # Create a renderer and add the cube actor to it
15 | renderer = vtk.vtkRenderer()
16 | renderer.AddActor(cubeActor)
17 |
18 | # Create a render window and add the renderer to it
19 | renderWindow = vtk.vtkRenderWindow()
20 | renderWindow.AddRenderer(renderer)
21 |
22 | # Create an interactor and set the render window as its input
23 | interactor = vtk.vtkRenderWindowInteractor()
24 | interactor.SetRenderWindow(renderWindow)
25 |
26 | # Initialize the interactor
27 | interactor.Initialize()
28 |
29 | # The main animation loop
30 | for i in range(360):
31 | # Rotate the cube actor
32 | cubeActor.RotateY(1)
33 |
34 | # Render the scene
35 | renderWindow.Render()
36 |
37 | # Start the interaction
38 | interactor.Start()
39 |
--------------------------------------------------------------------------------
/src/06_visualization_pipeline/scalar_color_mapping.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import vtk
3 |
4 | # Create a 3D grid of points, each with a scalar value
5 | dims = (20, 20, 20)
6 | x = np.linspace(-1.0, 1.0, dims[0])
7 | y = np.linspace(-1.0, 1.0, dims[1])
8 | z = np.linspace(-1.0, 1.0, dims[2])
9 | x, y, z = np.meshgrid(x, y, z, indexing="ij")
10 |
11 | # Create a scalar value for each point in the grid
12 | scalars = np.sqrt(x**2 + y**2 + z**2)
13 |
14 | # Create a structured grid object and assign the points and scalars
15 | grid = vtk.vtkStructuredGrid()
16 | grid.SetDimensions(dims)
17 |
18 | points = vtk.vtkPoints()
19 | points.SetNumberOfPoints(np.prod(dims))
20 |
21 | for i in range(dims[0]):
22 | for j in range(dims[1]):
23 | for k in range(dims[2]):
24 | points.SetPoint(
25 | i * dims[1] * dims[2] + j * dims[2] + k,
26 | x[i, j, k],
27 | y[i, j, k],
28 | z[i, j, k],
29 | )
30 | grid.SetPoints(points)
31 |
32 | scalarArray = vtk.vtkDoubleArray()
33 | scalarArray.SetNumberOfTuples(np.prod(dims))
34 | for i in range(np.prod(dims)):
35 | scalarArray.SetTuple(i, (scalars.ravel()[i],))
36 | scalarArray.SetName("Scalars")
37 | grid.GetPointData().SetScalars(scalarArray)
38 |
39 | # Create a mapper and set the scalar range to the range of our scalar data
40 | mapper = vtk.vtkDataSetMapper()
41 | mapper.SetInputData(grid)
42 | mapper.SetScalarModeToUsePointData()
43 | mapper.SetScalarRange(scalars.min(), scalars.max())
44 |
45 | # Create an actor
46 | actor = vtk.vtkActor()
47 | actor.SetMapper(mapper)
48 |
49 | # Create a renderer, add the actor to it
50 | renderer = vtk.vtkRenderer()
51 | renderer.AddActor(actor)
52 |
53 | # Create a render window, add the renderer to it
54 | renderWindow = vtk.vtkRenderWindow()
55 | renderWindow.AddRenderer(renderer)
56 |
57 | # Create an interactor, add the render window to it
58 | interactor = vtk.vtkRenderWindowInteractor()
59 | interactor.SetRenderWindow(renderWindow)
60 |
61 | # Initialize the interactor and start the rendering loop
62 | interactor.Initialize()
63 | interactor.Start()
64 |
--------------------------------------------------------------------------------
/src/07_interactive_widgets/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/djeada/Vtk-Examples/e9105e31800958705894eb94925ad251d2ad0117/src/07_interactive_widgets/__init__.py
--------------------------------------------------------------------------------
/src/07_interactive_widgets/deformation_cylinder.py:
--------------------------------------------------------------------------------
1 | import vtk
2 | import numpy as np
3 | from vtkmodules.vtkInteractionWidgets import vtkSliderWidget, vtkSliderRepresentation2D
4 | from vtkmodules.vtkFiltersSources import vtkCylinderSource
5 | from vtkmodules.vtkRenderingCore import (
6 | vtkActor,
7 | vtkRenderer,
8 | vtkRenderWindow,
9 | vtkRenderWindowInteractor,
10 | vtkPolyDataMapper,
11 | )
12 | from vtkmodules.vtkCommonColor import vtkNamedColors
13 |
14 | # Create the cylinder
15 | cylinder = vtkCylinderSource()
16 | cylinder.SetHeight(10)
17 | cylinder.SetRadius(2)
18 | cylinder.SetResolution(100)
19 | cylinder.Update()
20 |
21 | # Get the cylinder's points
22 | points = cylinder.GetOutput().GetPoints()
23 |
24 | # Store the original point coordinates for reference
25 | original_points = np.array(
26 | [points.GetPoint(i) for i in range(points.GetNumberOfPoints())]
27 | )
28 |
29 | # Mapper
30 | cylinderMapper = vtkPolyDataMapper()
31 | cylinderMapper.SetInputConnection(cylinder.GetOutputPort())
32 |
33 | # Actor
34 | cylinderActor = vtkActor()
35 | cylinderActor.SetMapper(cylinderMapper)
36 |
37 | # Renderer
38 | renderer = vtkRenderer()
39 | renderer.AddActor(cylinderActor)
40 | renderer.SetBackground(0, 0, 0) # Background color black
41 |
42 | # Render Window
43 | renderWindow = vtkRenderWindow()
44 | renderWindow.AddRenderer(renderer)
45 | renderWindow.SetSize(1200, 800) # Increased size for more space
46 |
47 | # Interactor
48 | renderWindowInteractor = vtkRenderWindowInteractor()
49 | renderWindowInteractor.SetRenderWindow(renderWindow)
50 |
51 | # Global variables to store slider values
52 | current_bending = 0
53 | current_compression = 0
54 | current_torsion = 0
55 | current_shear = 0
56 |
57 |
58 | def apply_deformation():
59 | for i in range(points.GetNumberOfPoints()):
60 | x, y, z = original_points[i]
61 |
62 | # Apply compression along the Z-axis
63 | z = z * (1 - current_compression)
64 |
65 | # Apply bending (displacement along Y-axis based on Z, similar to image)
66 | if current_bending != 0:
67 | curvature = current_bending / 100.0 # Adjust curvature sensitivity
68 | y = y + curvature * z**2
69 |
70 | # Apply torsion (twisting, rotation around Z-axis based on Z, like a corkscrew)
71 | if current_torsion != 0:
72 | theta = current_torsion * (z / 10.0)
73 | x_new = x * np.cos(np.radians(theta)) - y * np.sin(np.radians(theta))
74 | y_new = x * np.sin(np.radians(theta)) + y * np.cos(np.radians(theta))
75 | x, y = x_new, y_new
76 |
77 | # Apply shear (lateral displacement along XZ-plane)
78 | x = x + current_shear * z
79 |
80 | points.SetPoint(i, x, y, z)
81 |
82 | # Update the cylinder with new point data
83 | points.Modified()
84 | renderWindow.Render()
85 |
86 |
87 | # Slider callback functions
88 | def update_bending(obj, event):
89 | global current_bending
90 | current_bending = obj.GetRepresentation().GetValue()
91 | apply_deformation()
92 |
93 |
94 | def update_compression(obj, event):
95 | global current_compression
96 | current_compression = obj.GetRepresentation().GetValue()
97 | apply_deformation()
98 |
99 |
100 | def update_torsion(obj, event):
101 | global current_torsion
102 | current_torsion = obj.GetRepresentation().GetValue()
103 | apply_deformation()
104 |
105 |
106 | def update_shear(obj, event):
107 | global current_shear
108 | current_shear = obj.GetRepresentation().GetValue()
109 | apply_deformation()
110 |
111 |
112 | # Creating Sliders
113 | def create_slider(min_val, max_val, title, y_position):
114 | sliderRep = vtkSliderRepresentation2D()
115 | sliderRep.SetMinimumValue(min_val)
116 | sliderRep.SetMaximumValue(max_val)
117 | sliderRep.SetValue(0.0)
118 | sliderRep.SetTitleText(title)
119 | sliderRep.GetPoint1Coordinate().SetCoordinateSystemToNormalizedDisplay()
120 | sliderRep.GetPoint1Coordinate().SetValue(0.01, y_position) # Farther to the left
121 | sliderRep.GetPoint2Coordinate().SetCoordinateSystemToNormalizedDisplay()
122 | sliderRep.GetPoint2Coordinate().SetValue(
123 | 0.3, y_position
124 | ) # Enough distance from cylinder
125 |
126 | sliderWidget = vtkSliderWidget()
127 | sliderWidget.SetInteractor(renderWindowInteractor)
128 | sliderWidget.SetRepresentation(sliderRep)
129 | sliderWidget.EnabledOn()
130 |
131 | return sliderWidget
132 |
133 |
134 | # Adjusted positions for sliders to avoid overlapping
135 | bending_slider = create_slider(-30, 30, "Bending", 0.8)
136 | bending_slider.AddObserver("EndInteractionEvent", update_bending)
137 |
138 | compression_slider = create_slider(0, 0.5, "Compression", 0.6)
139 | compression_slider.AddObserver("EndInteractionEvent", update_compression)
140 |
141 | torsion_slider = create_slider(-180, 180, "Torsion", 0.4)
142 | torsion_slider.AddObserver("EndInteractionEvent", update_torsion)
143 |
144 | shear_slider = create_slider(-1, 1, "Shear", 0.2)
145 | shear_slider.AddObserver("EndInteractionEvent", update_shear)
146 |
147 | # Start interaction
148 | renderWindow.Render()
149 | renderWindowInteractor.Start()
150 |
--------------------------------------------------------------------------------
/src/07_interactive_widgets/interactive_flower_mesh.py:
--------------------------------------------------------------------------------
1 | import vtk
2 | import numpy as np
3 |
4 |
5 | def generate_flower_mesh(petal_count: int, points_per_petal: int) -> vtk.vtkPolyData:
6 | theta = np.linspace(0, 2 * np.pi, points_per_petal)
7 | radius = np.cos(petal_count * theta) + 2
8 |
9 | points = vtk.vtkPoints()
10 | for i in range(points_per_petal):
11 | x = radius[i] * np.cos(theta[i])
12 | y = radius[i] * np.sin(theta[i])
13 | points.InsertNextPoint(x, y, 0)
14 |
15 | points.InsertNextPoint(0, 0, 0)
16 |
17 | polygons = vtk.vtkCellArray()
18 | for i in range(points_per_petal - 1):
19 | polygon = vtk.vtkPolygon()
20 | polygon.GetPointIds().SetNumberOfIds(3)
21 | polygon.GetPointIds().SetId(0, i)
22 | polygon.GetPointIds().SetId(1, i + 1)
23 | polygon.GetPointIds().SetId(2, points_per_petal)
24 | polygons.InsertNextCell(polygon)
25 |
26 | polygon = vtk.vtkPolygon()
27 | polygon.GetPointIds().SetNumberOfIds(3)
28 | polygon.GetPointIds().SetId(0, points_per_petal - 1)
29 | polygon.GetPointIds().SetId(1, 0)
30 | polygon.GetPointIds().SetId(2, points_per_petal)
31 | polygons.InsertNextCell(polygon)
32 |
33 | poly_data = vtk.vtkPolyData()
34 | poly_data.SetPoints(points)
35 | poly_data.SetPolys(polygons)
36 |
37 | return poly_data
38 |
39 |
40 | def update_flower_mesh(
41 | petal_count: int, points_per_petal: int, actor: vtk.vtkActor
42 | ) -> None:
43 | new_mesh = generate_flower_mesh(petal_count, points_per_petal)
44 | mapper = vtk.vtkPolyDataMapper()
45 | mapper.SetInputData(new_mesh)
46 | actor.SetMapper(mapper)
47 |
48 |
49 | def slider_callback(
50 | obj: vtk.vtkObject,
51 | event: str,
52 | petal_slider: vtk.vtkSliderWidget,
53 | points_slider: vtk.vtkSliderWidget,
54 | actor: vtk.vtkActor,
55 | render_window: vtk.vtkRenderWindow,
56 | text_actor: vtk.vtkTextActor,
57 | ) -> None:
58 | petal_count = int(petal_slider.GetRepresentation().GetValue())
59 | points_per_petal = int(points_slider.GetRepresentation().GetValue())
60 | update_flower_mesh(petal_count, points_per_petal, actor)
61 | text_actor.SetInput(f"Petals: {petal_count}\nPoints: {points_per_petal}")
62 | render_window.Render()
63 |
64 |
65 | def create_slider_widget(
66 | title: str,
67 | interactor: vtk.vtkRenderWindowInteractor,
68 | min_value: float,
69 | max_value: float,
70 | initial_value: float,
71 | position: list[float],
72 | ) -> vtk.vtkSliderWidget:
73 | slider_rep = vtk.vtkSliderRepresentation2D()
74 | slider_rep.SetMinimumValue(min_value)
75 | slider_rep.SetMaximumValue(max_value)
76 | slider_rep.SetValue(initial_value)
77 | slider_rep.SetTitleText(title)
78 | slider_rep.GetPoint1Coordinate().SetCoordinateSystemToNormalizedDisplay()
79 | slider_rep.GetPoint1Coordinate().SetValue(position[0], position[1])
80 | slider_rep.GetPoint2Coordinate().SetCoordinateSystemToNormalizedDisplay()
81 | slider_rep.GetPoint2Coordinate().SetValue(position[2], position[3])
82 | slider_widget = vtk.vtkSliderWidget()
83 | slider_widget.SetInteractor(interactor)
84 | slider_widget.SetRepresentation(slider_rep)
85 | slider_widget.SetAnimationModeToAnimate()
86 | slider_widget.EnabledOn()
87 | return slider_widget
88 |
89 |
90 | def rotate_flower(obj: vtk.vtkObject, event: str) -> None:
91 | actor.RotateZ(1)
92 | obj.GetRenderWindow().Render()
93 |
94 |
95 | if __name__ == "__main__":
96 | petal_count = 8
97 | points_per_petal = 80
98 |
99 | flower_mesh = generate_flower_mesh(petal_count, points_per_petal)
100 |
101 | mapper = vtk.vtkPolyDataMapper()
102 | mapper.SetInputData(flower_mesh)
103 |
104 | actor = vtk.vtkActor()
105 | actor.SetMapper(mapper)
106 | actor.GetProperty().SetEdgeVisibility(True)
107 | actor.GetProperty().SetEdgeColor(0, 0, 0)
108 | actor.GetProperty().SetColor(1, 1, 1) # Light-colored flower
109 |
110 | renderer = vtk.vtkRenderer()
111 | render_window = vtk.vtkRenderWindow()
112 | render_window.AddRenderer(renderer)
113 | render_window_interactor = vtk.vtkRenderWindowInteractor()
114 | render_window_interactor.SetRenderWindow(render_window)
115 |
116 | renderer.AddActor(actor)
117 | renderer.SetBackground(0.1, 0.1, 0.1) # Dark background
118 |
119 | text_actor = vtk.vtkTextActor()
120 | text_actor.SetInput(f"Petals: {petal_count}\nPoints: {points_per_petal}")
121 | text_actor.GetTextProperty().SetColor(1, 1, 1) # White text
122 | text_actor.GetTextProperty().SetFontSize(24)
123 | text_actor.SetPosition2(10, 40)
124 | text_actor.GetPositionCoordinate().SetCoordinateSystemToNormalizedViewport()
125 | text_actor.SetPosition(0.75, 0.85)
126 | renderer.AddActor2D(text_actor)
127 |
128 | petal_slider = create_slider_widget(
129 | "Petals", render_window_interactor, 1, 20, petal_count, [0.1, 0.1, 0.4, 0.1]
130 | )
131 | points_slider = create_slider_widget(
132 | "Points",
133 | render_window_interactor,
134 | 10,
135 | 200,
136 | points_per_petal,
137 | [0.1, 0.2, 0.4, 0.2],
138 | )
139 |
140 | slider_callback_closure = lambda obj, event: slider_callback(
141 | obj, event, petal_slider, points_slider, actor, render_window, text_actor
142 | )
143 | petal_slider.AddObserver("EndInteractionEvent", slider_callback_closure)
144 | points_slider.AddObserver("EndInteractionEvent", slider_callback_closure)
145 |
146 | render_window_interactor.AddObserver("TimerEvent", rotate_flower)
147 | render_window_interactor.CreateRepeatingTimer(100)
148 |
149 | render_window.Render()
150 | render_window_interactor.Start()
151 |
--------------------------------------------------------------------------------
/src/07_interactive_widgets/orientation_marker.py:
--------------------------------------------------------------------------------
1 | import vtk
2 | from vtkmodules.vtkCommonTransforms import vtkTransform
3 | from vtkmodules.vtkFiltersSources import vtkPlaneSource
4 | from vtkmodules.vtkInteractionWidgets import vtkBoxWidget
5 | from vtkmodules.vtkRenderingCore import (
6 | vtkPolyDataMapper,
7 | vtkRenderer,
8 | vtkRenderWindow,
9 | vtkRenderWindowInteractor,
10 | )
11 |
12 |
13 | def create_plane_actor(color: tuple) -> vtk.vtkActor:
14 | """
15 | Create a plane actor with specified color.
16 |
17 | Args:
18 | color (tuple): A tuple of three float values representing RGB color.
19 |
20 | Returns:
21 | vtk.vtkActor: An actor representing a colored plane.
22 | """
23 | plane = vtkPlaneSource()
24 | plane.SetXResolution(10)
25 | plane.SetYResolution(10)
26 |
27 | mapper = vtkPolyDataMapper()
28 | mapper.SetInputConnection(plane.GetOutputPort())
29 |
30 | actor = vtk.vtkActor()
31 | actor.SetMapper(mapper)
32 | actor.GetProperty().SetColor(color)
33 |
34 | return actor
35 |
36 |
37 | def plane_widget_callback(obj, event):
38 | """
39 | Callback function to modify the plane when the widget is manipulated.
40 |
41 | Args:
42 | obj: The object associated with the callback.
43 | event: The event triggering the callback.
44 | """
45 | transform = vtkTransform()
46 | obj.GetTransform(transform)
47 | matrix = transform.GetMatrix()
48 | obj.GetProp3D().SetUserMatrix(matrix)
49 |
50 |
51 | def setup_interaction(
52 | plane_actor: vtk.vtkActor, render_window_interactor: vtk.vtkRenderWindowInteractor
53 | ):
54 | """
55 | Set up interaction widget for a plane actor.
56 |
57 | Args:
58 | plane_actor (vtk.vtkActor): The plane actor to interact with.
59 | render_window_interactor (vtk.vtkRenderWindowInteractor): The render window interactor.
60 | """
61 | plane_widget = vtkBoxWidget()
62 | plane_widget.SetInteractor(render_window_interactor)
63 | plane_widget.SetProp3D(plane_actor)
64 | plane_widget.On()
65 | plane_widget.AddObserver("InteractionEvent", plane_widget_callback)
66 |
67 |
68 | # Main execution
69 | if __name__ == "__main__":
70 | # Create two plane actors with different colors
71 | red_plane_actor = create_plane_actor((1, 0, 0))
72 | blue_plane_actor = create_plane_actor((0, 0, 1))
73 |
74 | # Define a vtkRenderer and add the two actors
75 | renderer = vtkRenderer()
76 | renderer.AddActor(red_plane_actor)
77 | renderer.AddActor(blue_plane_actor)
78 |
79 | # Create and set up render window and interactor
80 | render_window = vtkRenderWindow()
81 | render_window.AddRenderer(renderer)
82 |
83 | render_window_interactor = vtkRenderWindowInteractor()
84 | render_window_interactor.SetRenderWindow(render_window)
85 |
86 | # Set up interaction for both planes
87 | setup_interaction(red_plane_actor, render_window_interactor)
88 | setup_interaction(blue_plane_actor, render_window_interactor)
89 |
90 | # Initialize and start the interactor
91 | render_window_interactor.Initialize()
92 | render_window.Render()
93 | render_window_interactor.Start()
94 |
--------------------------------------------------------------------------------
/src/07_interactive_widgets/simple_button.py:
--------------------------------------------------------------------------------
1 | import vtk
2 |
3 | from src.common.button import Button2D
4 |
5 |
6 | def on_button_clicked():
7 | print("Button clicked!")
8 |
9 |
10 | def main():
11 | # Create a renderer, render window, and interactor
12 | renderer = vtk.vtkRenderer()
13 | renderer.SetBackground(1, 1, 1) # White background
14 | render_window = vtk.vtkRenderWindow()
15 | render_window.SetSize(300, 300)
16 | render_window.AddRenderer(renderer)
17 | interactor = vtk.vtkRenderWindowInteractor()
18 | interactor.SetRenderWindow(render_window)
19 |
20 | # Create a 2D button
21 | button = Button2D(interactor, "Click Me", (50, 50), (100, 50))
22 | button.add_click_callback(on_button_clicked)
23 |
24 | # Start the interaction
25 | render_window.Render()
26 | interactor.Initialize()
27 | interactor.Start()
28 |
29 |
30 | if __name__ == "__main__":
31 | main()
32 |
--------------------------------------------------------------------------------
/src/07_interactive_widgets/slider.py:
--------------------------------------------------------------------------------
1 | import vtk
2 |
3 |
4 | def main():
5 | # Create a sphere
6 | sphereSource = vtk.vtkSphereSource()
7 | sphereSource.Update()
8 |
9 | # Create a mapper
10 | mapper = vtk.vtkPolyDataMapper()
11 | mapper.SetInputConnection(sphereSource.GetOutputPort())
12 |
13 | # Create an actor
14 | actor = vtk.vtkActor()
15 | actor.SetMapper(mapper)
16 |
17 | # Create a renderer
18 | renderer = vtk.vtkRenderer()
19 | renderer.AddActor(actor)
20 |
21 | # Create a render window
22 | renderWindow = vtk.vtkRenderWindow()
23 | renderWindow.AddRenderer(renderer)
24 |
25 | # Create a render window interactor
26 | renderWindowInteractor = vtk.vtkRenderWindowInteractor()
27 | renderWindowInteractor.SetRenderWindow(renderWindow)
28 |
29 | # Initialize the interactor and start the rendering loop
30 | renderWindow.Render()
31 | renderWindowInteractor.Initialize()
32 |
33 | # Setup picker
34 | picker = vtk.vtkCellPicker()
35 |
36 | # Create a text actor to display the cell ID
37 | textActor = vtk.vtkTextActor()
38 | textActor.SetInput("Cell ID: ")
39 | textActor.GetTextProperty().SetColor(1.0, 1.0, 1.0) # White color
40 | textActor.SetPosition(10, 10) # Position in screen coordinates
41 | renderer.AddActor(textActor)
42 |
43 | def onClick(event, obj):
44 | x, y = renderWindowInteractor.GetEventPosition()
45 | picker.Pick(x, y, 0, renderer)
46 | pickedCell = picker.GetCellId()
47 | if pickedCell != -1:
48 | textActor.SetInput(f"Cell ID: {pickedCell}")
49 | renderWindow.Render()
50 |
51 | # Add click event listener
52 | renderWindowInteractor.AddObserver("LeftButtonPressEvent", onClick)
53 |
54 | # Start interaction
55 | renderWindowInteractor.Start()
56 |
57 |
58 | if __name__ == "__main__":
59 | main()
60 |
--------------------------------------------------------------------------------
/src/08_integration_with_ui/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/djeada/Vtk-Examples/e9105e31800958705894eb94925ad251d2ad0117/src/08_integration_with_ui/__init__.py
--------------------------------------------------------------------------------
/src/08_integration_with_ui/matplotlib_sphere.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | import vtkmodules.all as vtk
3 | from vtkmodules.util import numpy_support
4 |
5 |
6 | def create_sphere(radius=1.0, theta_resolution=40, phi_resolution=40):
7 | # Create a sphere
8 | sphere = vtk.vtkSphereSource()
9 | sphere.SetRadius(radius)
10 | sphere.SetThetaResolution(theta_resolution)
11 | sphere.SetPhiResolution(phi_resolution)
12 | sphere.Update()
13 | return sphere
14 |
15 |
16 | def convert_vtk_to_numpy(vtk_data):
17 | # Convert vtk to numpy
18 | numpy_array = numpy_support.vtk_to_numpy(vtk_data)
19 | return numpy_array
20 |
21 |
22 | def main():
23 | # Create a sphere
24 | sphere = create_sphere()
25 |
26 | # Convert vtk to numpy
27 | vtk_array = sphere.GetOutput().GetPoints().GetData()
28 | numpy_array = convert_vtk_to_numpy(vtk_array)
29 |
30 | # Split the numpy array into x, y, z components for 3D plotting
31 | x, y, z = numpy_array[:, 0], numpy_array[:, 1], numpy_array[:, 2]
32 |
33 | # Plot the sphere using matplotlib
34 | fig = plt.figure()
35 | ax = fig.add_subplot(111, projection="3d")
36 | ax.scatter(x, y, z, color="b", alpha=0.6, edgecolors="w", s=20)
37 | plt.show()
38 |
39 |
40 | if __name__ == "__main__":
41 | main()
42 |
--------------------------------------------------------------------------------
/src/08_integration_with_ui/matplotlib_surface_plot.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | import numpy as np
3 | import vtkmodules.all as vtk
4 | from mpl_toolkits.mplot3d import Axes3D
5 |
6 | # Create a grid of points for the Rosenbrock Function
7 | x = np.linspace(-5, 5, 100)
8 | y = np.linspace(-5, 5, 100)
9 | X, Y = np.meshgrid(x, y)
10 | Z = (1 - X) ** 2 + 100 * (Y - X**2) ** 2 # Rosenbrock Function
11 |
12 |
13 | def create_surface_from_grid(x, y, z):
14 | # Create a surface from the grid data
15 | points = vtk.vtkPoints()
16 | vertices = vtk.vtkCellArray()
17 |
18 | for i in range(len(x)):
19 | for j in range(len(y)):
20 | points.InsertNextPoint(x[i][j], y[i][j], z[i][j])
21 | if i < len(x) - 1 and j < len(y) - 1:
22 | vertices.InsertNextCell(4)
23 | vertices.InsertCellPoint(i * len(y) + j)
24 | vertices.InsertCellPoint((i + 1) * len(y) + j)
25 | vertices.InsertCellPoint((i + 1) * len(y) + (j + 1))
26 | vertices.InsertCellPoint(i * len(y) + (j + 1))
27 |
28 | grid = vtk.vtkPolyData()
29 | grid.SetPoints(points)
30 | grid.SetPolys(vertices)
31 | return grid
32 |
33 |
34 | def main():
35 | # Create a surface from the grid data
36 | surface = create_surface_from_grid(X, Y, Z)
37 |
38 | # Create a Matplotlib 3D plot
39 | fig = plt.figure()
40 | ax = fig.add_subplot(111, projection="3d")
41 |
42 | # Plot the surface
43 | ax.plot_surface(
44 | X, Y, Z, cmap="viridis", rstride=1, cstride=1, linewidth=0, antialiased=False
45 | )
46 |
47 | # Customize the plot (add labels, title, etc.)
48 | ax.set_xlabel("X")
49 | ax.set_ylabel("Y")
50 | ax.set_zlabel("Z")
51 | ax.set_title("Rosenbrock Function")
52 |
53 | # Show the plot
54 | plt.show()
55 |
56 |
57 | if __name__ == "__main__":
58 | main()
59 |
--------------------------------------------------------------------------------
/src/08_integration_with_ui/qt_sphere.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | import vtkmodules.all as vtk
4 | from PyQt6 import QtCore
5 | from PyQt6.QtWidgets import (
6 | QApplication,
7 | QColorDialog,
8 | QMainWindow,
9 | QPushButton,
10 | QSlider,
11 | QVBoxLayout,
12 | QWidget,
13 | )
14 | from vtkmodules.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
15 |
16 |
17 | class CustomActor(vtk.vtkActor):
18 | def __init__(self, source=None):
19 | super().__init__()
20 | self.source = source or vtk.vtkSphereSource()
21 | self.color = (0.1, 0.8, 0.5) # Default color
22 | self.update_mapper()
23 |
24 | def update_mapper(self):
25 | mapper = vtk.vtkPolyDataMapper()
26 | mapper.SetInputConnection(self.source.GetOutputPort())
27 | self.SetMapper(mapper)
28 | self.SetPosition(0.2, 0.2, 0.6)
29 | self.GetProperty().SetColor(self.color)
30 |
31 | def update_radius(self, radius):
32 | self.source.SetRadius(radius)
33 | self.source.Update()
34 | self.update_mapper()
35 |
36 | def update_color(self, color):
37 | self.color = (color.redF(), color.greenF(), color.blueF())
38 | self.GetProperty().SetColor(self.color)
39 |
40 |
41 | class VtkDisplay(QWidget):
42 | def __init__(self, parent=None):
43 | super().__init__(parent)
44 |
45 | layout = QVBoxLayout(self)
46 | self.vtk_display = QVTKRenderWindowInteractor(self)
47 | layout.addWidget(self.vtk_display)
48 |
49 | self.slider = QSlider(QtCore.Qt.Orientation.Horizontal)
50 | self.slider.setMinimum(1)
51 | self.slider.setMaximum(10)
52 | self.slider.setValue(1)
53 | layout.addWidget(self.slider)
54 |
55 | self.color_button = QPushButton("Change color")
56 | layout.addWidget(self.color_button)
57 |
58 | self.renderer = vtk.vtkRenderer()
59 | self.vtk_display.GetRenderWindow().AddRenderer(self.renderer)
60 | self.interactor = self.vtk_display.GetRenderWindow().GetInteractor()
61 |
62 | self.actor = CustomActor()
63 | self.renderer.AddActor(self.actor)
64 |
65 | self.slider.valueChanged.connect(self.change_radius)
66 | self.color_button.clicked.connect(self.change_color)
67 |
68 | self.renderer.ResetCamera()
69 | self.interactor.Initialize()
70 |
71 | def change_radius(self, value):
72 | self.actor.update_radius(value / 12)
73 | self.vtk_display.GetRenderWindow().Render()
74 |
75 | def change_color(self):
76 | color = QColorDialog.getColor()
77 | if color.isValid():
78 | self.actor.update_color(color)
79 | self.vtk_display.GetRenderWindow().Render()
80 |
81 |
82 | if __name__ == "__main__":
83 | app = QApplication(sys.argv)
84 | window = QMainWindow()
85 | widget = VtkDisplay()
86 | window.setCentralWidget(widget)
87 | window.show()
88 | sys.exit(app.exec())
89 |
--------------------------------------------------------------------------------
/src/08_integration_with_ui/spark_vtk_workflow.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 | import numpy as np
4 | import pandas as pd
5 | import vtk
6 | from vtk.util import numpy_support
7 | import logging
8 |
9 | # Configure logging
10 | logging.basicConfig(
11 | level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
12 | )
13 | logger = logging.getLogger(__name__)
14 |
15 |
16 | def check_environment():
17 | """Check if the environment is properly configured."""
18 | # Check for Java
19 | java_home = os.environ.get("JAVA_HOME")
20 | if not java_home:
21 | raise EnvironmentError(
22 | "JAVA_HOME is not set. Please install Java and set JAVA_HOME environment variable.\n"
23 | "On Ubuntu/Debian: \n"
24 | "1. sudo apt update\n"
25 | "2. sudo apt install default-jdk\n"
26 | "3. Add to ~/.bashrc:\n"
27 | " export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64\n"
28 | " (adjust path according to your Java installation)"
29 | )
30 |
31 | # Check if Java is accessible
32 | if os.system("java -version > /dev/null 2>&1") != 0:
33 | raise EnvironmentError("Java is not accessible from command line")
34 |
35 | return True
36 |
37 |
38 | def create_sample_data_without_spark(num_points=1000):
39 | """Generate sample 3D points with a scalar value using only Pandas."""
40 | np.random.seed(42)
41 | data = {
42 | "x": np.random.normal(0, 1, num_points),
43 | "y": np.random.normal(0, 1, num_points),
44 | "z": np.random.normal(0, 1, num_points),
45 | }
46 | df = pd.DataFrame(data)
47 | df["distance"] = np.sqrt(df["x"] ** 2 + df["y"] ** 2 + df["z"] ** 2)
48 | return df
49 |
50 |
51 | def process_data_without_spark(df):
52 | """Process data using Pandas instead of Spark."""
53 | return df[df["distance"] < 2.0].copy()
54 |
55 |
56 | def convert_to_vtk(df):
57 | """Convert DataFrame to VTK PolyData."""
58 | try:
59 | # Create points array
60 | points = vtk.vtkPoints()
61 | vertices = vtk.vtkCellArray()
62 |
63 | # Create array for scalar values
64 | scalars = vtk.vtkDoubleArray()
65 | scalars.SetName("Distance")
66 |
67 | # Add points and scalar values
68 | for idx, row in df.iterrows():
69 | point_id = points.InsertNextPoint(row["x"], row["y"], row["z"])
70 | scalars.InsertNextValue(row["distance"])
71 |
72 | # Create a vertex cell for each point
73 | vertex = vtk.vtkVertex()
74 | vertex.GetPointIds().SetId(0, point_id)
75 | vertices.InsertNextCell(vertex)
76 |
77 | # Create PolyData
78 | polydata = vtk.vtkPolyData()
79 | polydata.SetPoints(points)
80 | polydata.SetVerts(vertices)
81 | polydata.GetPointData().SetScalars(scalars)
82 |
83 | return polydata
84 | except Exception as e:
85 | logger.error(f"Error in converting to VTK: {str(e)}")
86 | raise
87 |
88 |
89 | def visualize_vtk(polydata):
90 | """Create a basic VTK visualization."""
91 | try:
92 | # Create mapper and actor
93 | mapper = vtk.vtkPolyDataMapper()
94 | mapper.SetInputData(polydata)
95 | mapper.ScalarVisibilityOn()
96 | mapper.SetScalarRange(polydata.GetPointData().GetScalars().GetRange())
97 |
98 | actor = vtk.vtkActor()
99 | actor.SetMapper(mapper)
100 |
101 | # Create renderer and window
102 | renderer = vtk.vtkRenderer()
103 | renderer.AddActor(actor)
104 | renderer.SetBackground(0.1, 0.1, 0.1)
105 |
106 | window = vtk.vtkRenderWindow()
107 | window.AddRenderer(renderer)
108 | window.SetSize(800, 600)
109 |
110 | # Add interactor
111 | interactor = vtk.vtkRenderWindowInteractor()
112 | interactor.SetRenderWindow(window)
113 |
114 | # Initialize and start
115 | interactor.Initialize()
116 | window.Render()
117 | interactor.Start()
118 | except Exception as e:
119 | logger.error(f"Error in visualization: {str(e)}")
120 | raise
121 |
122 |
123 | def main():
124 | try:
125 | logger.info("Starting data processing and visualization workflow")
126 |
127 | # Create and process data using Pandas
128 | logger.info("Generating sample data")
129 | df = create_sample_data_without_spark()
130 |
131 | logger.info("Processing data")
132 | processed_df = process_data_without_spark(df)
133 |
134 | # Save to parquet (optional)
135 | parquet_path = "processed_data.parquet"
136 | logger.info(f"Saving data to {parquet_path}")
137 | processed_df.to_parquet(parquet_path)
138 |
139 | # Convert to VTK
140 | logger.info("Converting data to VTK format")
141 | vtk_data = convert_to_vtk(processed_df)
142 |
143 | # Visualize
144 | logger.info("Starting visualization")
145 | visualize_vtk(vtk_data)
146 |
147 | # Clean up
148 | if os.path.exists(parquet_path):
149 | os.remove(parquet_path)
150 | logger.info("Cleaned up temporary files")
151 |
152 | except Exception as e:
153 | logger.error(f"An error occurred: {str(e)}")
154 | sys.exit(1)
155 |
156 |
157 | if __name__ == "__main__":
158 | try:
159 | # Check environment before running
160 | check_environment()
161 | main()
162 | except EnvironmentError as e:
163 | logger.error(f"Environment configuration error: {str(e)}")
164 | sys.exit(1)
165 | except Exception as e:
166 | logger.error(f"Unexpected error: {str(e)}")
167 | sys.exit(1)
168 |
--------------------------------------------------------------------------------
/src/09_cfd/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/djeada/Vtk-Examples/e9105e31800958705894eb94925ad251d2ad0117/src/09_cfd/__init__.py
--------------------------------------------------------------------------------
/src/09_cfd/fluid_flow_simulator.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | import numpy as np
3 | import vtk
4 | from vtkmodules.util import numpy_support
5 |
6 |
7 | def initialize_grid(l, h, dx, dy, u0):
8 | nx, ny = int(l / dx), int(h / dy)
9 | x, y = np.arange(0, l + dx, dx), np.arange(0, h + dy, dy)
10 | u = u0 * np.ones((ny + 1, nx + 1))
11 | u[0, :] = u[-1, :] = 0 # No-slip boundary condition
12 | p = np.zeros((ny + 1, nx + 1))
13 | return x, y, u, p, nx, ny
14 |
15 |
16 | def update_velocity(u, p, rho, mu, dx, dy, dt, ua, nx, ny):
17 | bmax = 0
18 | u_new = np.copy(u)
19 |
20 | # Compute velocity field
21 | for i in range(1, ny):
22 | for j in range(1, nx):
23 | # Compute pressure gradient
24 | dpdx = (p[i, j - 1] - p[i, j + 1]) / (2 * dx)
25 | dpdy = (p[i - 1, j] - p[i + 1, j]) / (2 * dy)
26 |
27 | # Compute viscous term
28 | viscous_term_x = mu * (u[i, j + 1] - 2 * u[i, j] + u[i, j - 1]) / dx**2
29 | viscous_term_y = mu * (u[i + 1, j] - 2 * u[i, j] + u[i - 1, j]) / dy**2
30 |
31 | # Update velocity
32 | u_new[i, j] = u[i, j] + dt * (
33 | -u[i, j] * dpdx + viscous_term_x - dpdy + viscous_term_y
34 | )
35 |
36 | # Update max change for convergence check
37 | bmax = max(bmax, abs(u_new[i, j] - u[i, j]))
38 |
39 | return u_new, bmax
40 |
41 |
42 | def create_points(x, y, u):
43 | points = vtk.vtkPoints()
44 | velocity_values = vtk.vtkFloatArray()
45 | velocity_values.SetName("Velocity")
46 |
47 | nx, ny = len(x), len(y)
48 | for j in range(ny):
49 | for i in range(nx):
50 | points.InsertNextPoint(x[i], y[j], 0)
51 | velocity_values.InsertNextValue(u[j, i]) # Ensure correct indexing
52 |
53 | return points, velocity_values
54 |
55 |
56 | # Create vtkPolyData for visualization
57 | def create_poly_data(nx, ny, points, velocity_values):
58 | polyData = vtk.vtkPolyData()
59 | polyData.SetPoints(points)
60 |
61 | cells = vtk.vtkCellArray()
62 | for i in range(ny - 1):
63 | for j in range(nx - 1):
64 | quad = vtk.vtkQuad()
65 | quad.GetPointIds().SetId(0, i * nx + j)
66 | quad.GetPointIds().SetId(1, (i + 1) * nx + j)
67 | quad.GetPointIds().SetId(2, (i + 1) * nx + (j + 1))
68 | quad.GetPointIds().SetId(3, i * nx + (j + 1))
69 | cells.InsertNextCell(quad)
70 |
71 | polyData.SetPolys(cells)
72 | polyData.GetPointData().SetScalars(velocity_values)
73 |
74 | return polyData
75 |
76 |
77 | # Create a color map for VTK visualization
78 | def create_color_map(u):
79 | color_map = vtk.vtkLookupTable()
80 | min_val, max_val = np.min(u), np.max(u)
81 | color_map.SetRange(min_val, max_val)
82 | color_map.SetHueRange(0.667, 0) # Blue to red
83 | color_map.Build()
84 | return color_map
85 |
86 |
87 | # Visualizes the velocity field using VTK
88 | def vtk_velocity_plot(x, y, snapshots):
89 | # Setup renderer and render window
90 | renderer = vtk.vtkRenderer()
91 | renderWindow = vtk.vtkRenderWindow()
92 | renderWindow.AddRenderer(renderer)
93 |
94 | # Enable user interaction with the scene
95 | renderWindowInteractor = vtk.vtkRenderWindowInteractor()
96 | renderWindowInteractor.SetRenderWindow(renderWindow)
97 | renderWindowInteractor.Initialize()
98 |
99 | # Set up interaction style for camera controls
100 | interact_style = vtk.vtkInteractorStyleTrackballCamera()
101 | renderWindowInteractor.SetInteractorStyle(interact_style)
102 |
103 | # Initialize variables to store actors
104 | surface_actor = None
105 | scalar_bar = None
106 |
107 | # Define a callback function for the timer
108 | def update_visualization(obj, event):
109 | nonlocal surface_actor, scalar_bar
110 | nonlocal snapshots
111 |
112 | # Remove the current actors
113 | if surface_actor:
114 | renderer.RemoveActor(surface_actor)
115 | renderer.RemoveActor(scalar_bar)
116 |
117 | # Stop the timer if no more snapshots are available
118 | if not snapshots:
119 | return
120 |
121 | # Get the next snapshot
122 | u_vtk = snapshots.pop(0)
123 |
124 | # Process the snapshot
125 | if isinstance(u_vtk, vtk.vtkTypeFloat32Array):
126 | u_np = numpy_support.vtk_to_numpy(u_vtk)
127 | u_np = u_np.reshape(len(y), len(x))
128 | else:
129 | u_np = u_vtk
130 |
131 | points, velocity_values = create_points(x, y, u_np)
132 | polyData = create_poly_data(len(x), len(y), points, velocity_values)
133 | color_map = create_color_map(u_np)
134 |
135 | mapper = vtk.vtkPolyDataMapper()
136 | mapper.SetInputData(polyData)
137 | mapper.SetLookupTable(color_map)
138 | mapper.SetScalarModeToUsePointData()
139 | mapper.SetScalarRange(np.min(u_np), np.max(u_np))
140 |
141 | # Create and add new actors
142 | surface_actor = vtk.vtkActor()
143 | surface_actor.SetMapper(mapper)
144 | scalar_bar = vtk.vtkScalarBarActor()
145 | scalar_bar.SetLookupTable(color_map)
146 | scalar_bar.SetTitle("Velocity")
147 | scalar_bar.SetNumberOfLabels(5)
148 |
149 | renderer.AddActor(surface_actor)
150 | renderer.AddActor(scalar_bar)
151 | renderer.ResetCamera()
152 | renderWindow.Render()
153 |
154 | # Add a timer to update the visualization
155 | renderWindowInteractor.AddObserver("TimerEvent", update_visualization)
156 | timerId = renderWindowInteractor.CreateRepeatingTimer(1000) # Time in milliseconds
157 |
158 | # Start the interaction
159 | renderWindow.Render()
160 | renderWindowInteractor.Start()
161 |
162 | # Clean up
163 | renderWindow.Finalize()
164 | renderWindowInteractor.TerminateApp()
165 |
166 |
167 | def main():
168 | # Simulation parameters
169 | l, h = 20.0, 2.0
170 | dx, dy = 0.1, 0.1
171 | dt = 0.01 # Time step
172 | rho, mu, ua = 1.0, 0.01, 0.5
173 | u0 = 1.0 # Inlet velocity
174 | btol = 1e-4 # Convergence tolerance
175 |
176 | # Initialize the grid and variables
177 | x, y, u, p, nx, ny = initialize_grid(l, h, dx, dy, u0)
178 |
179 | snapshots = []
180 | snapshot_interval = 100 # Define how often to take snapshots
181 |
182 | # Iterative solver
183 | iter_count = 0
184 | time_elapsed = 0
185 |
186 | while True:
187 | u, bmax = update_velocity(u, p, rho, mu, dx, dy, dt, ua, nx, ny)
188 | time_elapsed += dt
189 | print(
190 | f"Iteration {iter_count}, Time: {time_elapsed:.2f} s, Residual: {bmax:.6f}"
191 | )
192 |
193 | if iter_count % snapshot_interval == 0:
194 | # Convert u to a VTK array and store it
195 | vtk_u = numpy_support.numpy_to_vtk(
196 | num_array=u.ravel(), deep=True, array_type=vtk.VTK_FLOAT
197 | )
198 | vtk_u.SetName("Velocity")
199 | snapshots.append(vtk_u)
200 |
201 | if bmax < btol:
202 | print(f"Convergence achieved in {time_elapsed:.2f} seconds.")
203 | break
204 |
205 | iter_count += 1
206 | if iter_count > 10000: # Prevent infinite loop
207 | print("Convergence not achieved")
208 | break
209 |
210 | # Plotting the velocity field
211 | X, Y = np.meshgrid(x, y)
212 | plt.contourf(X, Y, u, levels=np.linspace(u.min(), u.max(), 20))
213 | plt.colorbar()
214 | plt.xlabel("x (m)")
215 | plt.ylabel("y (m)")
216 | plt.title("Velocity Field")
217 | plt.show()
218 |
219 | # Post-simulation visualization
220 | vtk_velocity_plot(x, y, snapshots)
221 |
222 |
223 | if __name__ == "__main__":
224 | main()
225 |
--------------------------------------------------------------------------------
/src/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/djeada/Vtk-Examples/e9105e31800958705894eb94925ad251d2ad0117/src/__init__.py
--------------------------------------------------------------------------------
/src/common/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/djeada/Vtk-Examples/e9105e31800958705894eb94925ad251d2ad0117/src/common/__init__.py
--------------------------------------------------------------------------------
/src/common/button.py:
--------------------------------------------------------------------------------
1 | import vtk
2 |
3 |
4 | class Button2D:
5 | def __init__(self, interactor, label="Button", pos=(100, 100), size=(100, 40)):
6 | self.interactor = interactor
7 | self.label = label
8 | self.pos = pos
9 | self.size = size
10 |
11 | # Create the 2D button representation
12 | self.button_actor = vtk.vtkTexturedButtonRepresentation2D()
13 | self.button_actor.SetNumberOfStates(1)
14 | self.button_actor.SetPlaceFactor(1)
15 | self.button_actor.PlaceWidget(
16 | [pos[0], pos[0] + size[0], pos[1], pos[1] + size[1], 0, 0]
17 | )
18 |
19 | # Create a texture for the button
20 | self.create_button_texture()
21 |
22 | # Create the button widget
23 | self.button_widget = vtk.vtkButtonWidget()
24 | self.button_widget.SetInteractor(interactor)
25 | self.button_widget.SetRepresentation(self.button_actor)
26 | self.button_widget.On()
27 |
28 | # Create the text label
29 | self.create_button_label()
30 |
31 | def create_button_texture(self):
32 | # Create an image for the button texture
33 | image = vtk.vtkImageData()
34 | image.SetDimensions(self.size[0], self.size[1], 1)
35 | image.AllocateScalars(vtk.VTK_UNSIGNED_CHAR, 3)
36 |
37 | # Fill the image with a color
38 | for y in range(self.size[1]):
39 | for x in range(self.size[0]):
40 | pixel = [180, 180, 180] # Light gray color
41 | image.SetScalarComponentFromFloat(x, y, 0, 0, pixel[0])
42 | image.SetScalarComponentFromFloat(x, y, 0, 1, pixel[1])
43 | image.SetScalarComponentFromFloat(x, y, 0, 2, pixel[2])
44 |
45 | # Set the image directly as the button texture
46 | self.button_actor.SetButtonTexture(0, image)
47 |
48 | def create_button_label(self):
49 | # Create a text actor
50 | text_actor = vtk.vtkTextActor()
51 | text_actor.SetInput(self.label)
52 |
53 | # Adjust font size and alignment
54 | text_property = text_actor.GetTextProperty()
55 | text_property.SetFontSize(
56 | min(self.size) // 2
57 | ) # Adjust font size based on button size
58 | text_property.SetColor(0, 0, 0) # Black text
59 | text_property.SetJustificationToCentered()
60 | text_property.SetVerticalJustificationToCentered()
61 |
62 | # Estimate the vertical centering position
63 | approx_text_height = text_property.GetFontSize() * 0.5
64 | y_position = self.pos[1] + (self.size[1] - approx_text_height) / 2
65 |
66 | # Position the text in the center of the button
67 | text_actor.SetPosition(self.pos[0] + self.size[0] / 2, y_position)
68 |
69 | # Add the text actor to the renderer
70 | self.interactor.GetRenderWindow().GetRenderers().GetFirstRenderer().AddActor(
71 | text_actor
72 | )
73 |
74 | def add_click_callback(self, callback):
75 | # Add click event listener
76 | def on_button_press(widget, event_string):
77 | callback()
78 |
79 | self.button_widget.AddObserver("StateChangedEvent", on_button_press)
80 |
--------------------------------------------------------------------------------
/src/common/simple_pipeline.py:
--------------------------------------------------------------------------------
1 | import vtk
2 |
3 |
4 | class VisualisationPipeline:
5 | def __init__(
6 | self,
7 | mappers,
8 | point_size=1,
9 | edges_visible=False,
10 | background_color=(0, 0, 0),
11 | window_title="VTK Visualization",
12 | ):
13 | """
14 | Initialize the visualization pipeline with specified parameters.
15 |
16 | Args:
17 | mappers (list of vtkPolyDataMapper): The data mappers for rendering.
18 | point_size (int): Size of points in the rendered actors.
19 | edges_visible (bool): Flag to render edges of the actors.
20 | background_color (tuple): Background color of the renderer.
21 | window_title (str): Title of the visualization window.
22 | """
23 | self.mappers = mappers
24 | self.point_size = point_size
25 | self.edges_visible = edges_visible
26 | self.background_color = background_color
27 | self.window_title = window_title
28 |
29 | def create_actors(self):
30 | """
31 | Create actors based on the mappers provided.
32 |
33 | Returns:
34 | list of vtkActor: List of actors for rendering.
35 | """
36 | actors = []
37 | for mapper in self.mappers:
38 | actor = vtk.vtkActor()
39 | actor.SetMapper(mapper)
40 | actor.GetProperty().SetPointSize(self.point_size)
41 | if self.edges_visible:
42 | actor.GetProperty().SetEdgeVisibility(1)
43 | actor.GetProperty().SetOpacity(0.5)
44 | actor.GetProperty().BackfaceCullingOn()
45 | actors.append(actor)
46 | return actors
47 |
48 | def create_renderer(self, actors):
49 | """
50 | Create a renderer and add actors to it.
51 |
52 | Args:
53 | actors (list of vtkActor): Actors to be rendered.
54 |
55 | Returns:
56 | vtkRenderer: Configured renderer.
57 | """
58 | renderer = vtk.vtkRenderer()
59 | for actor in actors:
60 | renderer.AddActor(actor)
61 | renderer.SetBackground(*self.background_color)
62 | return renderer
63 |
64 | def create_window(self, renderer):
65 | """
66 | Create a rendering window.
67 |
68 | Args:
69 | renderer (vtkRenderer): Renderer to be displayed in the window.
70 |
71 | Returns:
72 | vtkRenderWindow: Configured rendering window.
73 | """
74 | window = vtk.vtkRenderWindow()
75 | window.AddRenderer(renderer)
76 | window.SetSize(800, 600)
77 | # window.SetTitle(self.window_title)
78 | return window
79 |
80 | def create_interactor(self, window):
81 | """
82 | Create an interactor for the rendering window.
83 |
84 | Args:
85 | window (vtkRenderWindow): Rendering window.
86 |
87 | Returns:
88 | vtkRenderWindowInteractor: Configured window interactor.
89 | """
90 | interactor = vtk.vtkRenderWindowInteractor()
91 | interactor.SetRenderWindow(window)
92 | return interactor
93 |
94 | def run(self):
95 | """
96 | Run the visualization pipeline.
97 | """
98 | actors = self.create_actors()
99 | renderer = self.create_renderer(actors)
100 | window = self.create_window(renderer)
101 | interactor = self.create_interactor(window)
102 | interactor.Start()
103 |
--------------------------------------------------------------------------------
/vtk_js/basic/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["@babel/preset-env"]
3 | }
4 |
5 |
--------------------------------------------------------------------------------
/vtk_js/basic/README.md:
--------------------------------------------------------------------------------
1 | 1. Install Dependencies:
2 |
3 | ```
4 | npm install
5 | ```
6 |
7 | 2. Build the Project:
8 |
9 | ```
10 | npm run build
11 | ```
12 |
13 | 3. Run the Application:
14 |
15 | ```
16 | npm start
17 | ```
18 |
19 | 4. Access the Application:
20 | - Open a web browser and navigate to the localhost URL provided by the server (typically http://localhost:8080).
21 |
--------------------------------------------------------------------------------
/vtk_js/basic/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | VTK.js Hello World
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/vtk_js/basic/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vtk-js-example",
3 | "version": "1.0.0",
4 | "description": "A simple VTK.js example using @kitware/vtk.js",
5 | "main": "src/main.js",
6 | "scripts": {
7 | "build": "webpack --progress --mode=development",
8 | "start": "webpack serve --progress --mode=development --static=dist"
9 | },
10 | "dependencies": {
11 | "@kitware/vtk.js": "^29.2.0"
12 | },
13 | "devDependencies": {
14 | "@babel/core": "^7.23.6",
15 | "@babel/preset-env": "^7.23.6",
16 | "babel-loader": "^9.1.3",
17 | "webpack": "^5.89.0",
18 | "webpack-cli": "^5.1.4",
19 | "webpack-dev-server": "^4.15.1"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/vtk_js/basic/src/main.js:
--------------------------------------------------------------------------------
1 | import '@kitware/vtk.js/Rendering/Profiles/Geometry';
2 | import vtkFullScreenRenderWindow from '@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow';
3 | import vtkActor from '@kitware/vtk.js/Rendering/Core/Actor';
4 | import vtkMapper from '@kitware/vtk.js/Rendering/Core/Mapper';
5 | import vtkCalculator from '@kitware/vtk.js/Filters/General/Calculator';
6 | import vtkConeSource from '@kitware/vtk.js/Filters/Sources/ConeSource';
7 |
8 | const fullScreenRenderWindow = vtkFullScreenRenderWindow.newInstance();
9 | const renderer = fullScreenRenderWindow.getRenderer();
10 | const renderWindow = fullScreenRenderWindow.getRenderWindow();
11 |
12 | const coneSource = vtkConeSource.newInstance();
13 | const mapper = vtkMapper.newInstance();
14 | mapper.setInputConnection(coneSource.getOutputPort());
15 |
16 | const actor = vtkActor.newInstance();
17 | actor.setMapper(mapper);
18 |
19 | renderer.addActor(actor);
20 | renderer.resetCamera();
21 | renderWindow.render();
22 |
23 |
--------------------------------------------------------------------------------
/vtk_js/basic/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | module.exports = {
4 | mode: 'development',
5 | entry: './src/main.js', // make sure this points to your main JavaScript file
6 | output: {
7 | path: path.resolve(__dirname, 'dist'),
8 | filename: 'bundle.js',
9 | libraryTarget: 'umd', // This exposes your bundle on different environments
10 | globalObject: 'this' // This ensures compatibility with both browser and Node environments
11 | },
12 | module: {
13 | rules: [
14 | {
15 | test: /\.js$/,
16 | exclude: /node_modules/,
17 | use: {
18 | loader: 'babel-loader',
19 | options: {
20 | presets: ['@babel/preset-env']
21 | }
22 | },
23 | },
24 | ],
25 | },
26 | resolve: {
27 | extensions: ['.js'], // Add '.ts' if you are using TypeScript
28 | fallback: {
29 | "stream": require.resolve("stream-browserify"),
30 | "buffer": require.resolve("buffer")
31 | }
32 | },
33 | };
34 |
35 |
--------------------------------------------------------------------------------