diff --git a/docs/changes.md b/docs/changes.md index bbaecd11..70ccc60d 100644 --- a/docs/changes.md +++ b/docs/changes.md @@ -13,6 +13,15 @@ - add `addons.DrawingWidget` class for tracing on planar props - add `Video(..., scale=1)` keyword in #1168 by @YongcaiHuang - modify `legosurface(boundary=True)` default in #1166 +- make load functions compatible with pathlib #1176 by @Louis-Pujol +- fixed broken link to example #1175 by @jo-mueller +- add documentation to Mesh.boolean() #1173 by @jkunimune +- raise an error when calling cell_normals before compute_normals() #1172 by @jkunimune +- add documentation warning as computing normals can affect appearence of the mesh #1174 by @jkunimune +- add documentation about `Cube` and `Box` having duplicated vertices to allow defining normals #1171 +- add documentation do address the behaviour of `mesh.volume()` and `mesh.is_closed()` wrt duplicated vertices. +- add `plotter.reset_clipping_range()` to reset the camera clipping range based on the bounds of the visible actors #1170 + ## Soft-breaking Changes @@ -41,7 +50,6 @@ Examples that are not fully functional and need some fixing: markpoint.py (misplaced leader indicator) cut_and_cap.py (incomplete capping) tests/issues/discussion_800.py (incomplete capping of tube) -examples/volumetric/numpy2volume1.py () ``` diff --git a/vedo/mesh.py b/vedo/mesh.py index 19b1905a..12bde4f2 100644 --- a/vedo/mesh.py +++ b/vedo/mesh.py @@ -305,6 +305,10 @@ def compute_normals(self, points=True, cells=True, feature_angle=None, consisten .. warning:: If `feature_angle` is set then the Mesh can be modified, and it can have a different nr. of vertices from the original. + + Note that the appearance of the mesh may change if the normals are computed, + as shading is automatically enabled when such information is present. + Use `mesh.flat()` to avoid smoothing effects. """ pdnorm = vtki.new("PolyDataNormals") pdnorm.SetInputData(self.dataset) @@ -357,27 +361,37 @@ def reverse(self, cells=True, normals=False) -> Self: return self def volume(self) -> float: - """Get/set the volume occupied by mesh.""" + """ + Compute the volume occupied by mesh. + The mesh must be triangular for this to work. + To triangulate a mesh use `mesh.triangulate()`. + """ mass = vtki.new("MassProperties") mass.SetGlobalWarningDisplay(0) mass.SetInputData(self.dataset) mass.Update() + mass.SetGlobalWarningDisplay(1) return mass.GetVolume() def area(self) -> float: """ Compute the surface area of the mesh. The mesh must be triangular for this to work. - See also `mesh.triangulate()`. + To triangulate a mesh use `mesh.triangulate()`. """ mass = vtki.new("MassProperties") mass.SetGlobalWarningDisplay(0) mass.SetInputData(self.dataset) mass.Update() + mass.SetGlobalWarningDisplay(1) return mass.GetSurfaceArea() def is_closed(self) -> bool: - """Return `True` if the mesh is watertight.""" + """ + Return `True` if the mesh is watertight. + Note that if the mesh contains coincident points the result may be flase. + Use in this case `mesh.clean()` to merge coincident points. + """ fe = vtki.new("FeatureEdges") fe.BoundaryEdgesOn() fe.FeatureEdgesOff() diff --git a/vedo/plotter.py b/vedo/plotter.py index 3347fd43..b941b368 100644 --- a/vedo/plotter.py +++ b/vedo/plotter.py @@ -1369,6 +1369,17 @@ def reset_camera(self, tight=None) -> Self: cam.SetParallelScale(ps * (1 + tight)) self.renderer.ResetCameraClippingRange(x0, x1, y0, y1, z0, z1) return self + + def reset_clipping_range(self, bounds=None) -> Self: + """ + Reset the camera clipping range to include all visible actors. + If bounds is given, it will be used instead of computing it. + """ + if bounds is None: + self.renderer.ResetCameraClippingRange() + else: + self.renderer.ResetCameraClippingRange(bounds) + return self def reset_viewup(self, smooth=True) -> Self: """ diff --git a/vedo/shapes.py b/vedo/shapes.py index 3cb27697..b48e1435 100644 --- a/vedo/shapes.py +++ b/vedo/shapes.py @@ -3200,6 +3200,10 @@ def __init__( If `pos` is a list of 6 numbers, this will be interpreted as the bounding box: `[xmin,xmax, ymin,ymax, zmin,zmax]` + Note that the shape polygonal data contains duplicated vertices. This is to allow + each face to have its own normal, which is essential for some operations. + Use the `clean()` method to remove duplicate points. + Examples: - [aspring1.py](https://github.com/marcomusy/vedo/tree/master/examples/simulations/aspring1.py) @@ -3262,7 +3266,13 @@ def __init__( class Cube(Box): - """Build a cube.""" + """ + Build a cube shape. + + Note that the shape polygonal data contains duplicated vertices. This is to allow + each face to have its own normal, which is essential for some operations. + Use the `clean()` method to remove duplicate points. + """ def __init__(self, pos=(0, 0, 0), side=1.0, c="g4", alpha=1.0) -> None: """Build a cube of size `side`.""" diff --git a/vedo/utils.py b/vedo/utils.py index 84d28e23..83098d6e 100644 --- a/vedo/utils.py +++ b/vedo/utils.py @@ -1056,7 +1056,7 @@ def is_ragged(arr, deep=False) -> bool: """ A ragged or inhomogeneous array in Python is an array with arrays of different lengths as its elements. - To check if an array is ragged,we iterate through the elements + To check if an array is ragged, we iterate through the elements and check if their lengths are the same. Example: @@ -2095,7 +2095,7 @@ def camera_from_quaternion(pos, quaternion, distance=10000, ngl_correct=True) -> return camera -def camera_from_neuroglancer(state, zoom=300) -> vtki.vtkCamera: +def camera_from_neuroglancer(state, zoom) -> vtki.vtkCamera: """ Define a `vtkCamera` from a neuroglancer state dictionary. @@ -2104,7 +2104,6 @@ def camera_from_neuroglancer(state, zoom=300) -> vtki.vtkCamera: an neuroglancer state dictionary. zoom: (float) how much to multiply zoom by to get camera backoff distance - default = 300 > ngl_zoom = 1 > 300 nm backoff distance. Returns: `vtki.vtkCamera`, a vtk camera setup that matches this state. @@ -2116,7 +2115,7 @@ def camera_from_neuroglancer(state, zoom=300) -> vtki.vtkCamera: return camera_from_quaternion(pos_nm, orient, pzoom * zoom, ngl_correct=True) -def oriented_camera(center=(0, 0, 0), up_vector=(0, 1, 0), backoff_vector=(0, 0, 1), backoff=1.0) -> vtki.vtkCamera: +def oriented_camera(center, up_vector, backoff_vector, backoff) -> vtki.vtkCamera: """ Generate a `vtkCamera` pointed at a specific location, oriented with a given up direction, set to a backoff. diff --git a/vedo/version.py b/vedo/version.py index a5de2d0b..a5d62898 100644 --- a/vedo/version.py +++ b/vedo/version.py @@ -1 +1 @@ -_version = '2024.5.2+dev07' +_version = '2024.5.2+dev08'