diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a10422f9ca..1662df044be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Added `compas.tolerance.Tolerance.angulardeflection`. ### Changed - +* Changed and update the `compas_view2` examples into `compas_viewer`. * Changed and updated the `compas_view2` examples into `compas_viewer`. * Changed `compas.scene.Scene` to inherent from `compas.datastructrues.Tree`. * Changed `compas.scene.SceneObject` to inherent from `compas.datastructrues.TreeNode`. @@ -25,6 +25,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Fixed bug in `Mesh.thickened`. * Fixed various bugs in `compas.geometry.Quaternion`. * Changed repo config to `pyproject.toml`. +* `RhinoBrep.trimmed` returns single result or raises `BrepTrimmingError` instead of returning a list. + ### Removed diff --git a/src/compas_rhino/geometry/brep/brep.py b/src/compas_rhino/geometry/brep/brep.py index 3250b0aab83..7c050415015 100644 --- a/src/compas_rhino/geometry/brep/brep.py +++ b/src/compas_rhino/geometry/brep/brep.py @@ -10,6 +10,7 @@ from compas.geometry import BrepError from compas.geometry import Plane from compas.geometry import Point +from compas.tolerance import TOL from compas_rhino.conversions import box_to_rhino from compas_rhino.conversions import transformation_to_rhino @@ -29,8 +30,6 @@ from .vertex import RhinoBrepVertex from .loop import RhinoBrepLoop -TOLERANCE = 1e-6 - class RhinoBrep(Brep): """Rhino Brep backend class. @@ -242,7 +241,7 @@ def from_extrusion(cls, curve, vector, cap_ends=True): raise BrepError("Failed to create extrusion from curve: {} and vector: {}".format(curve, vector)) rhino_brep = extrusion.ToBrep() if cap_ends: - capped = rhino_brep.CapPlanarHoles(TOLERANCE) + capped = rhino_brep.CapPlanarHoles(TOL.absolute) if capped: rhino_brep = capped return cls.from_native(rhino_brep) @@ -327,7 +326,7 @@ def contains(self, object): raise BrepError("Cannot check for containment if brep is not manifold or is not closed") if isinstance(object, Point): - return self._brep.IsPointInside(point_to_rhino(object), TOLERANCE, False) + return self._brep.IsPointInside(point_to_rhino(object), TOL.absolute, False) else: raise NotImplementedError @@ -365,55 +364,78 @@ def transform(self, matrix): """ self._brep.Transform(transformation_to_rhino(matrix)) - def trim(self, plane, tolerance=TOLERANCE): + def trim(self, plane, tolerance=None): """Trim this brep by the given trimming plane. Parameters ---------- plane : :class:`compas.geometry.Frame` or :class:`compas.geometry.Plane` The frame or plane to use when trimming. The discarded bit is in the direction of the frame's normal. + tolerance : float, optional + The precision to use for the trimming operation. Defaults to `TOL.absolute`. - tolerance : float - The precision to use for the trimming operation. + Notes + ----- + Trimming operation may result in multiple results (breps). When trimming, only one is used. + The used bit is the one on the opposite side of the cutting plane's normal. Returns ------- None - """ - results = self.trimmed(plane, tolerance) - if not results: - raise BrepTrimmingError("Trim operation ended with no result") + Raises + ------ + BrepTrimmingError + If the trimming operation ended with no result. + + See Also + -------- + :meth:`compas_rhino.geometry.RhinoBrep.trimmed` - self._brep = results[0].native_brep + """ + result = self.trimmed(plane, tolerance) + self._brep = result.native_brep - def trimmed(self, plane, tolerance=TOLERANCE): + def trimmed(self, plane, tolerance=None): """Returns a trimmed copy of this brep by the given trimming plane. Parameters ---------- plane : :class:`compas.geometry.Frame` or :class:`compas.geometry.Plane` The frame or plane to use when trimming. The discarded bit is in the direction of the plane's normal. + tolerance : float, optional + The precision to use for the trimming operation. Defaults to `TOL.absolute`. - tolerance : float - The precision to use for the trimming operation. + Notes + ----- + Trimming operation may result in multiple results (breps). When trimming, only one is used. + The used bit is the one on the opposite side of the cutting plane's normal. Returns ------- :class:`~compas_rhino.geometry.RhinoBrep` + Raises + ------ + BrepTrimmingError + If the trimming operation ended with no result. + + See Also + -------- + :meth:`compas_rhino.geometry.RhinoBrep.trim` + """ + tolerance = tolerance or TOL.absolute if isinstance(plane, Frame): plane = Plane.from_frame(plane) results = self._brep.Trim(plane_to_rhino(plane), tolerance) - - breps = [] - for result in results: - capped = result.CapPlanarHoles(TOLERANCE) - if capped: - result = capped - breps.append(RhinoBrep.from_native(result)) - return breps + if not results: + raise BrepTrimmingError("Trim operation ended with no result") + result = results[0] + capped = result.CapPlanarHoles(tolerance) + if capped: + result = capped + return RhinoBrep.from_native(result) @classmethod def from_boolean_difference(cls, breps_a, breps_b): @@ -439,7 +461,7 @@ def from_boolean_difference(cls, breps_a, breps_b): resulting_breps = Rhino.Geometry.Brep.CreateBooleanDifference( [b.native_brep for b in breps_a], [b.native_brep for b in breps_b], - TOLERANCE, + TOL.absolute, ) return [RhinoBrep.from_native(brep) for brep in resulting_breps] @@ -465,7 +487,9 @@ def from_boolean_union(cls, breps_a, breps_b): if not isinstance(breps_b, list): breps_b = [breps_b] - resulting_breps = Rhino.Geometry.Brep.CreateBooleanUnion([b.native_brep for b in breps_a + breps_b], TOLERANCE) + resulting_breps = Rhino.Geometry.Brep.CreateBooleanUnion( + [b.native_brep for b in breps_a + breps_b], TOL.absolute + ) return [RhinoBrep.from_native(brep) for brep in resulting_breps] @classmethod @@ -492,7 +516,7 @@ def from_boolean_intersection(cls, breps_a, breps_b): resulting_breps = Rhino.Geometry.Brep.CreateBooleanIntersection( [b.native_brep for b in breps_a], [b.native_brep for b in breps_b], - TOLERANCE, + TOL.absolute, ) return [RhinoBrep.from_native(brep) for brep in resulting_breps] @@ -530,5 +554,5 @@ def split(self, cutter): list of zero or more resulting Breps. """ - resulting_breps = self._brep.Split(cutter.native_brep, TOLERANCE) + resulting_breps = self._brep.Split(cutter.native_brep, TOL.absolute) return [RhinoBrep.from_native(brep) for brep in resulting_breps]