PyNiteFEA 2.0.1__tar.gz → 2.0.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. {pynitefea-2.0.1 → pynitefea-2.0.2}/PKG-INFO +6 -1
  2. {pynitefea-2.0.1 → pynitefea-2.0.2}/PyNiteFEA.egg-info/PKG-INFO +6 -1
  3. {pynitefea-2.0.1 → pynitefea-2.0.2}/Pynite/Rendering.py +5 -9
  4. {pynitefea-2.0.1 → pynitefea-2.0.2}/Pynite/Visualization.py +202 -61
  5. {pynitefea-2.0.1 → pynitefea-2.0.2}/README.md +5 -0
  6. {pynitefea-2.0.1 → pynitefea-2.0.2}/setup.py +1 -1
  7. {pynitefea-2.0.1 → pynitefea-2.0.2}/LICENSE +0 -0
  8. {pynitefea-2.0.1 → pynitefea-2.0.2}/PyNiteFEA.egg-info/SOURCES.txt +0 -0
  9. {pynitefea-2.0.1 → pynitefea-2.0.2}/PyNiteFEA.egg-info/dependency_links.txt +0 -0
  10. {pynitefea-2.0.1 → pynitefea-2.0.2}/PyNiteFEA.egg-info/requires.txt +0 -0
  11. {pynitefea-2.0.1 → pynitefea-2.0.2}/PyNiteFEA.egg-info/top_level.txt +0 -0
  12. {pynitefea-2.0.1 → pynitefea-2.0.2}/Pynite/Analysis.py +0 -0
  13. {pynitefea-2.0.1 → pynitefea-2.0.2}/Pynite/BeamSegY.py +0 -0
  14. {pynitefea-2.0.1 → pynitefea-2.0.2}/Pynite/BeamSegZ.py +0 -0
  15. {pynitefea-2.0.1 → pynitefea-2.0.2}/Pynite/FEModel3D.py +0 -0
  16. {pynitefea-2.0.1 → pynitefea-2.0.2}/Pynite/FixedEndReactions.py +0 -0
  17. {pynitefea-2.0.1 → pynitefea-2.0.2}/Pynite/LoadCombo.py +0 -0
  18. {pynitefea-2.0.1 → pynitefea-2.0.2}/Pynite/MainStyleSheet.css +0 -0
  19. {pynitefea-2.0.1 → pynitefea-2.0.2}/Pynite/MatFoundation.py +0 -0
  20. {pynitefea-2.0.1 → pynitefea-2.0.2}/Pynite/Material.py +0 -0
  21. {pynitefea-2.0.1 → pynitefea-2.0.2}/Pynite/Member3D.py +0 -0
  22. {pynitefea-2.0.1 → pynitefea-2.0.2}/Pynite/Mesh.py +0 -0
  23. {pynitefea-2.0.1 → pynitefea-2.0.2}/Pynite/Node3D.py +0 -0
  24. {pynitefea-2.0.1 → pynitefea-2.0.2}/Pynite/PhysMember.py +0 -0
  25. {pynitefea-2.0.1 → pynitefea-2.0.2}/Pynite/Plate3D.py +0 -0
  26. {pynitefea-2.0.1 → pynitefea-2.0.2}/Pynite/Quad3D.py +0 -0
  27. {pynitefea-2.0.1 → pynitefea-2.0.2}/Pynite/Report_Template.html +0 -0
  28. {pynitefea-2.0.1 → pynitefea-2.0.2}/Pynite/Reporting.py +0 -0
  29. {pynitefea-2.0.1 → pynitefea-2.0.2}/Pynite/Section.py +0 -0
  30. {pynitefea-2.0.1 → pynitefea-2.0.2}/Pynite/ShearWall.py +0 -0
  31. {pynitefea-2.0.1 → pynitefea-2.0.2}/Pynite/Spring3D.py +0 -0
  32. {pynitefea-2.0.1 → pynitefea-2.0.2}/Pynite/Tri3D.py +0 -0
  33. {pynitefea-2.0.1 → pynitefea-2.0.2}/Pynite/VTKWriter.py +0 -0
  34. {pynitefea-2.0.1 → pynitefea-2.0.2}/Pynite/__init__.py +0 -0
  35. {pynitefea-2.0.1 → pynitefea-2.0.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyNiteFEA
3
- Version: 2.0.1
3
+ Version: 2.0.2
4
4
  Summary: A simple elastic 3D structural finite element library for Python.
5
5
  Home-page: https://github.com/JWock82/Pynite.git
6
6
  Author: D. Craig Brinck, PE, SE
@@ -117,6 +117,11 @@ Here's a list of projects that use Pynite:
117
117
  * Phaenotyp (https://github.com/bewegende-Architektur/Phaenotyp) (https://youtu.be/shloSw9HjVI)
118
118
 
119
119
  # What's New?
120
+ v2.0.2
121
+ * Added docstrings to the VTK `Renderer` class to help the user.
122
+ * Enforced use of properties instead of attributes in the VTK `Renderer` and added docstrings to properties help the user make decisions.
123
+ * Removed the VTK `Renderer`'s properties that began with "set_". These were redundant and caused confusion. The prefix "set_" is no longer used to access or set any of the `Renderer`'s properties.
124
+
120
125
  v2.0.1
121
126
  * Pynite no longer struggles rendering load cases and combinations when no loads are present. This is especially helpful for rendering modal load combinations, which don't have loads (only masses).
122
127
  * The pyvista plotter's "X" button now works just like pressing "q". This was an annoying pyvista-ism that led to error messages when closing the window with the "X" button.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyNiteFEA
3
- Version: 2.0.1
3
+ Version: 2.0.2
4
4
  Summary: A simple elastic 3D structural finite element library for Python.
5
5
  Home-page: https://github.com/JWock82/Pynite.git
6
6
  Author: D. Craig Brinck, PE, SE
@@ -117,6 +117,11 @@ Here's a list of projects that use Pynite:
117
117
  * Phaenotyp (https://github.com/bewegende-Architektur/Phaenotyp) (https://youtu.be/shloSw9HjVI)
118
118
 
119
119
  # What's New?
120
+ v2.0.2
121
+ * Added docstrings to the VTK `Renderer` class to help the user.
122
+ * Enforced use of properties instead of attributes in the VTK `Renderer` and added docstrings to properties help the user make decisions.
123
+ * Removed the VTK `Renderer`'s properties that began with "set_". These were redundant and caused confusion. The prefix "set_" is no longer used to access or set any of the `Renderer`'s properties.
124
+
120
125
  v2.0.1
121
126
  * Pynite no longer struggles rendering load cases and combinations when no loads are present. This is especially helpful for rendering modal load combinations, which don't have loads (only masses).
122
127
  * The pyvista plotter's "X" button now works just like pressing "q". This was an annoying pyvista-ism that led to error messages when closing the window with the "X" button.
@@ -209,13 +209,15 @@ class Renderer:
209
209
  generating images in headless environments. Default is `False`.
210
210
  """
211
211
 
212
- # Update the plotter with the latest geometry
213
- self.update(reset_camera)
214
-
215
212
  # Set off-screen mode if requested (for testing/headless environments)
213
+ # This must be done BEFORE calling update() so the plotter is in off-screen mode
214
+ # when adding meshes, preventing PyVista camera initialization issues
216
215
  if off_screen:
217
216
  self.plotter.off_screen = True
218
217
 
218
+ # Update the plotter with the latest geometry
219
+ self.update(reset_camera)
220
+
219
221
  # Render the model (code execution will pause here until the user closes the window)
220
222
  try:
221
223
  self.plotter.show(title='Pynite - Simple Finite Element Analysis for Python', auto_close=False)
@@ -281,12 +283,6 @@ class Renderer:
281
283
  # Clear out the old plot (if any)
282
284
  self.plotter.clear()
283
285
 
284
- # In off-screen mode, ensure renderer is initialized after clear
285
- # Accessing plotter.renderer forces lazy initialization in PyVista
286
- if pv.OFF_SCREEN and self.plotter.renderer is None:
287
- # Force renderer creation by enabling it
288
- self.plotter.enable_lightkit()
289
-
290
286
  # Set up view and axes (works for both interactive and off-screen modes)
291
287
  try:
292
288
  self.plotter.view_xy()
@@ -1,5 +1,4 @@
1
1
  from __future__ import annotations # Allows more recent type hints features
2
- from json import load
3
2
  import warnings
4
3
 
5
4
  from IPython.display import Image
@@ -8,28 +7,83 @@ from numpy.linalg import norm
8
7
  import vtk
9
8
 
10
9
  class Renderer():
11
- """Used to render finite element models.
10
+ """Renderer for visualizing finite element models using VTK.
11
+
12
+ This class provides a flexible interface for rendering 3D finite element models,
13
+ including nodes, members, springs, plates, and quads. It supports rendering of
14
+ undeformed and deformed shapes, load visualizations, and stress/force contours.
15
+
16
+ Parameters
17
+ ----------
18
+ model : FEModel3D
19
+ The finite element model to be rendered.
20
+
21
+ Attributes
22
+ ----------
23
+ annotation_size : float
24
+ Controls the size of text labels and visual elements (default: 5).
25
+ deformed_shape : bool
26
+ Whether to render the deformed shape of the model (default: False).
27
+ deformed_scale : float
28
+ Scale factor for deformation visualization (default: 30).
29
+ render_nodes : bool
30
+ Whether to render nodes in the visualization (default: True).
31
+ render_loads : bool
32
+ Whether to render applied loads (default: True).
33
+ color_map : str or None
34
+ Type of stress/force contour to display on plates/quads. Options:
35
+ 'Qx', 'Qy', 'Mx', 'My', 'Mxy', 'Sx', 'Sy', 'Txy' (default: None).
36
+ combo_name : str or None
37
+ Name of load combination to visualize. Mutually exclusive with case.
38
+ case : str or None
39
+ Name of load case to visualize. Mutually exclusive with combo_name.
40
+ labels : bool
41
+ Whether to display text labels for elements (default: True).
42
+ scalar_bar : bool
43
+ Whether to display a scalar bar for contour plots (default: False).
44
+ scalar_bar_text_size : int
45
+ Font size for scalar bar text (default: 24).
46
+ theme : str
47
+ Visual theme: 'default' or 'print' (default: 'default').
48
+ window_size : tuple
49
+ Window dimensions as (width, height).
50
+
51
+ Examples
52
+ --------
53
+ >>> from PyNite import FEModel3D
54
+ >>> model = FEModel3D()
55
+ >>> # ... build model ...
56
+ >>> renderer = Renderer(model)
57
+ >>> renderer.annotation_size = 6
58
+ >>> renderer.combo_name = 'Load Combo 1'
59
+ >>> renderer.render_model()
12
60
  """
13
61
 
14
62
  scalar = None
15
63
 
16
64
  def __init__(self, model):
17
-
65
+ """Initialize the renderer with a finite element model.
66
+
67
+ Parameters
68
+ ----------
69
+ model : FEModel3D
70
+ The finite element model to render.
71
+ """
18
72
  self.model = model
19
73
 
20
74
  # Default settings for rendering
21
- self.annotation_size = 5
22
- self.deformed_shape = False
23
- self.deformed_scale = 30
24
- self.render_nodes = True
25
- self.render_loads = True
26
- self.color_map = None
27
- self.combo_name = 'Combo 1'
28
- self.case = None
29
- self.labels = True
30
- self.scalar_bar = False
31
- self.scalar_bar_text_size = 24
32
- self.theme = 'default'
75
+ self._annotation_size = 5
76
+ self._deformed_shape = False
77
+ self._deformed_scale = 30
78
+ self._render_nodes = True
79
+ self._render_loads = True
80
+ self._color_map = None
81
+ self._combo_name = 'Combo 1'
82
+ self._case = None
83
+ self._labels = True
84
+ self._scalar_bar = False
85
+ self._scalar_bar_text_size = 24
86
+ self._theme = 'default'
33
87
 
34
88
  # Initialize VTK objects
35
89
  self.renderer = vtk.vtkRenderer()
@@ -38,62 +92,134 @@ class Renderer():
38
92
  self.window.AddRenderer(self.renderer)
39
93
 
40
94
  @property
41
- def window_width(self):
42
- return self.window.GetSize()[0]
43
-
44
- @window_width.setter
45
- def window_width(self, width):
46
- height = self.window.GetSize()[1]
95
+ def window_size(self):
96
+ """Window size as (width, height) tuple."""
97
+ return self.window.GetSize()
98
+
99
+ @window_size.setter
100
+ def window_size(self, size):
101
+ """Set window size from tuple or list (width, height)."""
102
+ width, height = size
47
103
  self.window.SetSize(width, height)
48
104
 
49
105
  @property
50
- def window_height(self):
51
- return self.window.GetSize()[1]
52
-
53
- @window_height.setter
54
- def window_height(self, height):
55
- width = self.window.GetSize()[0]
56
- self.window.SetSize(width, height)
106
+ def combo_name(self):
107
+ """Load combination name. When set, case is automatically set to None."""
108
+ return self._combo_name
109
+
110
+ @combo_name.setter
111
+ def combo_name(self, value):
112
+ self._combo_name = value
113
+ if value is not None:
114
+ self._case = None
115
+
116
+ @property
117
+ def case(self):
118
+ """Load case name. When set, combo_name is automatically set to None."""
119
+ return self._case
120
+
121
+ @case.setter
122
+ def case(self, value):
123
+ self._case = value
124
+ if value is not None:
125
+ self._combo_name = None
57
126
 
58
- def set_annotation_size(self, size=5):
59
- self.annotation_size = size
127
+ @property
128
+ def annotation_size(self):
129
+ """Size of text annotations and visual elements in model units."""
130
+ return self._annotation_size
131
+
132
+ @annotation_size.setter
133
+ def annotation_size(self, value):
134
+ self._annotation_size = value
60
135
 
61
- def set_deformed_shape(self, deformed_shape=False):
62
- self.deformed_shape = deformed_shape
136
+ @property
137
+ def deformed_shape(self):
138
+ """Whether to render the deformed shape of the model."""
139
+ return self._deformed_shape
140
+
141
+ @deformed_shape.setter
142
+ def deformed_shape(self, value):
143
+ self._deformed_shape = value
63
144
 
64
- def set_deformed_scale(self, scale=30):
65
- self.deformed_scale = scale
145
+ @property
146
+ def deformed_scale(self):
147
+ """Scale factor for deformation visualization."""
148
+ return self._deformed_scale
149
+
150
+ @deformed_scale.setter
151
+ def deformed_scale(self, value):
152
+ self._deformed_scale = value
66
153
 
67
- def set_render_nodes(self, render_nodes=True):
68
- self.render_nodes = render_nodes
154
+ @property
155
+ def render_nodes(self):
156
+ """Whether to render nodes in the visualization."""
157
+ return self._render_nodes
158
+
159
+ @render_nodes.setter
160
+ def render_nodes(self, value):
161
+ self._render_nodes = value
69
162
 
70
- def set_render_loads(self, render_loads=True):
71
- self.render_loads = render_loads
163
+ @property
164
+ def render_loads(self):
165
+ """Whether to render applied loads."""
166
+ return self._render_loads
72
167
 
73
- def set_color_map(self, color_map=None):
74
- """Sets the color map for plate contours.
168
+ @render_loads.setter
169
+ def render_loads(self, value):
170
+ self._render_loads = value
75
171
 
76
- :param color_map: The color map to use: Valid options are 'Qx', Qy', 'Mx', 'My', 'Mxy', 'Sx', 'Sy' 'Txy'. Qx and Qy are out-of-plane shear forces. Mx, My, and Mxy are local out-of-plane bending moments. 'Sx' and 'Sy' are membrane forces, and 'Txy' is an in-plane shear force. Defaults to None.
77
- :type color_map: str, optional
172
+ @property
173
+ def color_map(self):
174
+ """Type of stress/force contour to display on plates/quads.
175
+
176
+ Valid options: 'Qx', 'Qy', 'Mx', 'My', 'Mxy', 'Sx', 'Sy', 'Txy'
177
+ - Qx, Qy: Out-of-plane shear forces
178
+ - Mx, My, Mxy: Local out-of-plane bending moments
179
+ - Sx, Sy: Membrane forces
180
+ - Txy: In-plane shear force
78
181
  """
79
- self.color_map = color_map
80
-
81
- def set_combo_name(self, combo_name='Combo 1'):
82
- self.case = None
83
- self.combo_name = combo_name
182
+ return self._color_map
183
+
184
+ @color_map.setter
185
+ def color_map(self, value):
186
+ self._color_map = value
84
187
 
85
- def set_case(self, case=None):
86
- self.combo_name = None
87
- self.case = case
188
+ @property
189
+ def labels(self):
190
+ """Whether to display text labels for elements."""
191
+ return self._labels
192
+
193
+ @labels.setter
194
+ def labels(self, value):
195
+ self._labels = value
88
196
 
89
- def set_show_labels(self, show_labels=True):
90
- self.labels = show_labels
197
+ @property
198
+ def scalar_bar(self):
199
+ """Whether to display a scalar bar legend for contour plots."""
200
+ return self._scalar_bar
201
+
202
+ @scalar_bar.setter
203
+ def scalar_bar(self, value):
204
+ self._scalar_bar = value
91
205
 
92
- def set_scalar_bar(self, scalar_bar=False):
93
- self.scalar_bar = scalar_bar
206
+ @property
207
+ def scalar_bar_text_size(self):
208
+ """Font size for scalar bar text."""
209
+ return self._scalar_bar_text_size
210
+
211
+ @scalar_bar_text_size.setter
212
+ def scalar_bar_text_size(self, value):
213
+ self._scalar_bar_text_size = value
94
214
 
95
- def set_scalar_bar_text_size(self, text_size=24):
96
- self.scalar_bar_text_size = text_size
215
+ @property
216
+ def theme(self):
217
+ """Visual theme: 'default' (dark background) or 'print' (white background)."""
218
+ return self._theme
219
+
220
+ @theme.setter
221
+ def theme(self, value):
222
+ self._theme = value
97
223
 
98
224
  def render_model(self, interact=True, reset_camera=True):
99
225
  """
@@ -198,11 +324,26 @@ class Renderer():
198
324
  return
199
325
 
200
326
  def update(self, reset_camera=True):
201
- """Builds (or rebuilds) the VTK renderer
202
-
203
- :param reset_camera: Resets the render window's camera position if set to True. Defaults to True.
204
- :type reset_camera: bool, optional
205
- :raises Exception: Visualization failed due to an unexpected error.
327
+ """Build or rebuild the VTK renderer with current settings.
328
+
329
+ This method updates the visualization based on the current renderer settings,
330
+ including deformed shape, loads, contours, and other visual elements. It is
331
+ automatically called by render_model() and screenshot().
332
+
333
+ Parameters
334
+ ----------
335
+ reset_camera : bool, optional
336
+ If True, resets the camera to view the entire model (default: True).
337
+
338
+ Raises
339
+ ------
340
+ Exception
341
+ If the model configuration is invalid for the requested visualization.
342
+
343
+ Notes
344
+ -----
345
+ This method validates that deformed_shape is not used with a load case,
346
+ and that render_loads requires either a load combination or load case.
206
347
  """
207
348
 
208
349
  # Input validation
@@ -67,6 +67,11 @@ Here's a list of projects that use Pynite:
67
67
  * Phaenotyp (https://github.com/bewegende-Architektur/Phaenotyp) (https://youtu.be/shloSw9HjVI)
68
68
 
69
69
  # What's New?
70
+ v2.0.2
71
+ * Added docstrings to the VTK `Renderer` class to help the user.
72
+ * Enforced use of properties instead of attributes in the VTK `Renderer` and added docstrings to properties help the user make decisions.
73
+ * Removed the VTK `Renderer`'s properties that began with "set_". These were redundant and caused confusion. The prefix "set_" is no longer used to access or set any of the `Renderer`'s properties.
74
+
70
75
  v2.0.1
71
76
  * Pynite no longer struggles rendering load cases and combinations when no loads are present. This is especially helpful for rendering modal load combinations, which don't have loads (only masses).
72
77
  * The pyvista plotter's "X" button now works just like pressing "q". This was an annoying pyvista-ism that led to error messages when closing the window with the "X" button.
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name="PyNiteFEA",
8
- version="2.0.1",
8
+ version="2.0.2",
9
9
  author="D. Craig Brinck, PE, SE",
10
10
  author_email="Building.Code@outlook.com",
11
11
  description="A simple elastic 3D structural finite element library for Python.",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes