diff --git a/CHANGELOG.md b/CHANGELOG.md index 47a47f357fc..843ba2cb81a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +* Added `compas.colors.Color.contrast`. +* Added `compas.geometry.Brep.from_plane`. +* Added `compas.tolerance.Tolerance.angulardeflection`. + ### Changed * Changed and updated the `compas_view2` examples into `compas_viewer`. diff --git a/src/compas/colors/color.py b/src/compas/colors/color.py index 43255d6d920..61d71986139 100644 --- a/src/compas/colors/color.py +++ b/src/compas/colors/color.py @@ -90,6 +90,8 @@ class Color(Data): The perceived freedom of whiteness. is_light : bool If True, the color is considered light. + contrast : :class:`compas.colors.Color` + The contrasting color to the current color. Examples -------- @@ -311,6 +313,10 @@ def saturation(self): minval = min(self.r, self.g, self.b) return (maxval - minval) / maxval + @property + def contrast(self): + return self.darkened(25) if self.is_light else self.lightened(50) + # -------------------------------------------------------------------------- # Constructors # -------------------------------------------------------------------------- diff --git a/src/compas/geometry/brep/__init__.py b/src/compas/geometry/brep/__init__.py index 54185d363e2..5abec46e466 100644 --- a/src/compas/geometry/brep/__init__.py +++ b/src/compas/geometry/brep/__init__.py @@ -72,6 +72,11 @@ def from_pipe(*args, **kwargs): raise PluginNotInstalledError +@pluggable(category="factories") +def from_plane(*args, **kwargs): + raise PluginNotInstalledError + + @pluggable(category="factories") def from_planes(*args, **kwargs): raise PluginNotInstalledError diff --git a/src/compas/geometry/brep/brep.py b/src/compas/geometry/brep/brep.py index 5466895fd67..3952eae5f95 100644 --- a/src/compas/geometry/brep/brep.py +++ b/src/compas/geometry/brep/brep.py @@ -16,6 +16,7 @@ from . import from_boolean_union from . import from_curves from . import from_pipe +from . import from_plane from . import from_planes from . import from_polygons from . import from_step @@ -23,9 +24,6 @@ from . import from_native -LINEAR_DEFLECTION = 1e-3 - - class BrepType(object): """Possible types of a Brep @@ -489,6 +487,26 @@ def from_pipe(cls, curve, radius, thickness=None): """ return from_pipe(curve, radius, thickness=thickness) + @classmethod + def from_plane(cls, plane, domain_u=(-1, +1), domain_v=(-1, +1)): + """Construct a Brep from one plane and its u and v domains. + + Parameters + ---------- + plane : :class:`~compas.geometry.Plane` + A plane. + domain_u : tuple[float, float], optional + The surface domain in the u direction. + domain_v : tuple[float, float], optional + The surface domain in the v direction. + + Returns + ------- + :class:`compas.geometry.Brep` + + """ + return from_plane(plane, domain_u=domain_u, domain_v=domain_v) + @classmethod def from_planes(cls, planes): """Construct a Brep from a set of planes. @@ -768,7 +786,7 @@ def to_stl(self, filepath): """ raise NotImplementedError - def to_tesselation(self, linear_deflection=LINEAR_DEFLECTION): + def to_tesselation(self, linear_deflection=None): """Create a tesselation of the shape for visualisation. Parameters @@ -1093,7 +1111,7 @@ def split(self, cutter): """ raise NotImplementedError - def overlap(self, other, deflection=LINEAR_DEFLECTION, tolerance=0.0): + def overlap(self, other, deflection=None, tolerance=0.0): """Compute the overlap between this BRep and another. Parameters diff --git a/src/compas/tolerance.py b/src/compas/tolerance.py index 7e4a3bfbcaa..4a0b619cdd0 100644 --- a/src/compas/tolerance.py +++ b/src/compas/tolerance.py @@ -94,7 +94,14 @@ class Tolerance(Data): """ LINEARDEFLECTION = 1e-3 - """float: The maximum distance between a curve or surface and its polygonal approximation. + """float: The maximum "distance" deviation between a curve or surface and its polygonal approximation. + + This is used by the viewer to determine the mesh and polyline resolution of curves and surfaces for visualisation. + + """ + + ANGULARDEFLECTION = 1e-1 + """float: The maximum "curvature" deviation between a curve or surface and its polygonal approximation. This is used by the viewer to determine the mesh and polyline resolution of curves and surfaces for visualisation. @@ -115,6 +122,7 @@ def __data__(self): "approximation": self.approximation, "precision": self.precision, "lineardeflection": self.lineardeflection, + "angulardeflection": self.angulardeflection, } @classmethod @@ -127,6 +135,7 @@ def __from_data__(cls, data): tol.approximation = data["approximation"] tol.precision = data["precision"] tol.lineardeflection = data["lineardeflection"] + tol.angulardeflection = data["angulardeflection"] return tol def __init__( @@ -138,6 +147,7 @@ def __init__( approximation=None, precision=None, lineardflection=None, + angulardflection=None, name=None, ): super(Tolerance, self).__init__(name=name) @@ -148,6 +158,7 @@ def __init__( self._approximation = None self._precision = None self._lineardeflection = None + self._angulardeflection = None self.unit = unit self.absolute = absolute self.relative = relative @@ -155,11 +166,13 @@ def __init__( self.approximation = approximation self.precision = precision self.lineardeflection = lineardflection + self.angulardeflection = angulardflection # this can be autogenerated if we use slots # __repr__: return f"{__class__.__name__}({', '.join(f'{k}={v!r}' for k, v in self.__dict__.items())})}" + def __repr__(self): - return "Tolerance(unit='{}', absolute={}, relative={}, angular={}, approximation={}, precision={}, lineardeflection={})".format( + return "Tolerance(unit='{}', absolute={}, relative={}, angular={}, approximation={}, precision={}, lineardeflection={}, angulardeflection={})".format( self.unit, self.absolute, self.relative, @@ -167,6 +180,7 @@ def __repr__(self): self.approximation, self.precision, self.lineardeflection, + self.angulardeflection, ) def reset(self): @@ -177,6 +191,7 @@ def reset(self): self._approximation = None self._precision = None self._lineardeflection = None + self._angulardeflection = None @property def units(self): @@ -250,6 +265,16 @@ def lineardeflection(self): def lineardeflection(self, value): self._lineardeflection = value + @property + def angulardeflection(self): + if not self._angulardeflection: + return self.ANGULARDEFLECTION + return self._angulardeflection + + @angulardeflection.setter + def angulardeflection(self, value): + self._angulardeflection = value + def tolerance(self, truevalue, rtol, atol): """Compute the tolerance for a comparison.