Skip to content

Commit d0d8c3a

Browse files
committed
Merge branch 'main' into fix-halfedge-before-on-boundary
2 parents 7621ba5 + 15e73fb commit d0d8c3a

File tree

15 files changed

+284
-27
lines changed

15 files changed

+284
-27
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2020
* Added `format` task using `black` formatter.
2121
* Added a `test_intersection_circle_circle_xy` in the `test_intersections`
2222
* Added split operation to `compas_rhino.geometry.Brep`.
23+
* Added a `RhinoArtist` in `compas_rhino`.
24+
* Added a `RhinoArtist` in `compas_ghpython`.
2325

2426
### Changed
2527

2628
* Based all gltf data classes on `BaseGLTFDataClass`
2729
* Fixed `Color.__get___` AttributeError.
2830
* Fixed `cylinder_to_rhino` conversion to match `compas.geometry.Cylinder` location.
31+
* Changed identification of cylinder brep face to non-zero in `compas_rhino.conversions.cylinder.Cylinder`.
2932
* Changed linter to `black`.
3033
* Automatically trigger `invoke format` during `invoke release`.
3134
* Fixed bug in `intersections.intersection_circle_circle_xy` where the Circle's Plane was accessed instead of the centre.
3235
* Fixed bug in `_core.tangent` where the Circle's Plane was accessed instead of the centre.
3336
* Fixed the `test_tangent` to work with a properly defined circle
34-
37+
* `RhinoBrep` serialization works now with surface types other than NURBS.
3538
### Removed
3639

3740

src/compas_ghpython/artists/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
SurfaceArtist
3636
TorusArtist
3737
VectorArtist
38+
BrepArtist
3839
3940
4041
Datastructure Artists
@@ -91,6 +92,7 @@
9192
from compas.geometry import Surface
9293
from compas.geometry import Torus
9394
from compas.geometry import Vector
95+
from compas.geometry import Brep
9496

9597
from compas.datastructures import Mesh
9698
from compas.datastructures import Network
@@ -119,6 +121,7 @@
119121
from .torusartist import TorusArtist
120122
from .vectorartist import VectorArtist
121123
from .volmeshartist import VolMeshArtist
124+
from .brepartist import BrepArtist
122125

123126

124127
ShapeArtist.default_color = (255, 255, 255)
@@ -160,6 +163,7 @@ def register_artists():
160163
Artist.register(Torus, TorusArtist, context="Grasshopper")
161164
Artist.register(Vector, VectorArtist, context="Grasshopper")
162165
Artist.register(VolMesh, VolMeshArtist, context="Grasshopper")
166+
Artist.register(Brep, BrepArtist, context="Grasshopper")
163167
print("GH Artists registered.")
164168

165169

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from compas_ghpython.artists import GHArtist
2+
from compas_ghpython.utilities import draw_brep
3+
4+
5+
class BrepArtist(GHArtist):
6+
"""An artist for drawing a brep in Grasshopper.
7+
8+
Parameters
9+
==========
10+
brep : :class:`~compas_rhino.geometry.RhinoBrep`
11+
The brep to draw.
12+
13+
"""
14+
15+
def __init__(self, brep):
16+
super(BrepArtist, self).__init__()
17+
self._brep = brep
18+
19+
def draw(self):
20+
"""Draw the brep as a Grasshopper geometry.
21+
22+
Returns
23+
-------
24+
:rhino:`Rhino.Geometry.Brep`
25+
The Grasshopper geometry instance.
26+
27+
"""
28+
return draw_brep(self._brep)

src/compas_ghpython/utilities/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
draw_spheres
2424
draw_mesh
2525
draw_network
26+
draw_brep
2627
2728
2829
sets
@@ -69,6 +70,7 @@
6970
draw_mesh,
7071
draw_network,
7172
draw_circles,
73+
draw_brep,
7274
)
7375
from .sets import list_to_ghtree, ghtree_to_list
7476
from .timer import update_component
@@ -87,6 +89,7 @@
8789
"draw_mesh",
8890
"draw_network",
8991
"draw_circles",
92+
"draw_brep",
9093
"list_to_ghtree",
9194
"ghtree_to_list",
9295
"update_component",

src/compas_ghpython/utilities/drawing.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,3 +463,19 @@ def draw_circles(circles):
463463
radius = c["radius"]
464464
rg_circles.append(Circle(Plane(Point3d(*point), Vector3d(*normal)), radius))
465465
return rg_circles
466+
467+
468+
def draw_brep(brep):
469+
"""Draw a RhinoBrep in Grasshopper.
470+
471+
Parameters
472+
----------
473+
brep : :class:`~compas.geometry.RhinoBrep`
474+
The Brep to draw.
475+
476+
Returns
477+
-------
478+
:rhino:`Rhino.Geometry.Brep`
479+
480+
"""
481+
return brep.native_brep

src/compas_rhino/artists/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
PolygonArtist
2222
PolylineArtist
2323
VectorArtist
24+
BrepArtist
2425
2526
2627
Shape Artists
@@ -106,6 +107,7 @@
106107

107108
from compas.geometry import Curve
108109
from compas.geometry import Surface
110+
from compas.geometry import Brep
109111

110112
from compas.datastructures import Mesh
111113
from compas.datastructures import Network
@@ -137,6 +139,7 @@
137139

138140
from .curveartist import CurveArtist
139141
from .surfaceartist import SurfaceArtist
142+
from .brepartist import BrepArtist
140143

141144
BaseArtist = RhinoArtist
142145

@@ -174,6 +177,7 @@ def register_artists():
174177
Artist.register(RobotModel, RobotModelArtist, context="Rhino")
175178
Artist.register(Curve, CurveArtist, context="Rhino")
176179
Artist.register(Surface, SurfaceArtist, context="Rhino")
180+
Artist.register(Brep, BrepArtist, context="Rhino")
177181
print("Rhino Artists registered.")
178182

179183

@@ -201,4 +205,5 @@ def register_artists():
201205
"RobotModelArtist",
202206
"CurveArtist",
203207
"SurfaceArtist",
208+
"BrepArtist",
204209
]
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import compas_rhino
2+
from .artist import RhinoArtist
3+
4+
5+
class BrepArtist(RhinoArtist):
6+
"""An artist for drawing a RhinoBrep.
7+
8+
Parameters
9+
==========
10+
brep : :class:`~compas_rhino.geometry.RhinoBrep`
11+
The Brep to draw.
12+
13+
"""
14+
15+
def __init__(self, brep):
16+
super(BrepArtist, self).__init__()
17+
self._brep = brep
18+
19+
def draw(self, color=None):
20+
"""Bakes the Brep into the current document
21+
22+
Returns
23+
-------
24+
list(:rhino:`System.Guid`)
25+
The guid of the baked Brep.
26+
27+
"""
28+
return [compas_rhino.draw_brep(self._brep, color)]

src/compas_rhino/conversions/cylinder.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ def geometry(self, geometry):
4646
faces = geometry.Faces
4747
geometry = None
4848
for face in faces:
49-
if face.IsCylinder():
49+
# being too strict about what is considered a cylinder
50+
# results in cylinders created by Rhino itself
51+
# to not be recognized...
52+
if face.IsCylinder(0.001):
5053
result, geometry = face.TryGetFiniteCylinder(0.001)
5154
if result:
5255
break

src/compas_rhino/geometry/brep/brep.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def points(self):
103103
@property
104104
def edges(self):
105105
if self._brep:
106-
return [RhinoBrepEdge(edge) for edge in self._brep.Edges]
106+
return [RhinoBrepEdge(trim) for trim in self._brep.Trims]
107107

108108
@property
109109
def loops(self):

src/compas_rhino/geometry/brep/edge.py

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,30 @@
55
from compas_rhino.geometry import RhinoNurbsCurve
66
from compas_rhino.conversions import curve_to_compas_line
77
from compas_rhino.conversions import curve_to_compas_circle
8+
from compas_rhino.conversions import curve_to_compas_ellipse
89
from compas_rhino.conversions import line_to_rhino_curve
910
from compas_rhino.conversions import circle_to_rhino_curve
11+
from compas_rhino.conversions import ellipse_to_rhino_curve
12+
1013

1114
from .vertex import RhinoBrepVertex
1215

1316

1417
class RhinoBrepEdge(BrepEdge):
15-
"""A wrapper for Rhino.Geometry.BrepEdge
18+
"""A wrapper for Rhino.Geometry.BrepEdge.
19+
20+
The expected native type here is a Rhino.Geometry.BrepTrim.
21+
a BrepTrim holds a reference to its associated BrepEdge as well as its start a end vertices
22+
in a correct topological order (!).
1623
1724
Attributes
1825
----------
1926
curve : :class:`Rhino.Geometry.Curve3D`
2027
The underlying geometry of this edge.
2128
start_vertex : :class:`~compas_rhino.geometry.RhinoBrepVertex`, read-only
22-
The start vertex of this edge.
29+
The start vertex of this edge (taken from BrepTrim).
2330
end_vertex : :class:`~compas_rhino.geometry.RhinoBrepVertex`, read-only
24-
The end vertex of this edge.
31+
The end vertex of this edge (taken from BrepTrim).
2532
vertices : list[:class:`~compas_rhino.geometry.RhinoBrepVertex`], read-only
2633
The list of vertices which comprise this edge (start and end)
2734
is_circle : bool, read-only
@@ -31,20 +38,20 @@ class RhinoBrepEdge(BrepEdge):
3138
3239
"""
3340

34-
def __init__(self, rhino_edge=None):
41+
def __init__(self, rhino_trim=None):
3542
super(RhinoBrepEdge, self).__init__()
3643
self._edge = None
3744
self._curve = None
3845
self._start_vertex = None
3946
self._end_vertex = None
40-
if rhino_edge:
41-
self._set_edge(rhino_edge)
47+
if rhino_trim:
48+
self._set_edge(rhino_trim)
4249

43-
def _set_edge(self, native_edge):
44-
self._edge = native_edge
50+
def _set_edge(self, rhino_trim):
51+
self._edge = rhino_trim.Edge
4552
self._curve = self._edge.EdgeCurve
46-
self._start_vertex = RhinoBrepVertex(self._edge.StartVertex)
47-
self._end_vertex = RhinoBrepVertex(self._edge.EndVertex)
53+
self._start_vertex = RhinoBrepVertex(rhino_trim.StartVertex)
54+
self._end_vertex = RhinoBrepVertex(rhino_trim.EndVertex)
4855

4956
# ==============================================================================
5057
# Data
@@ -58,13 +65,16 @@ def data(self):
5865
elif self.is_circle:
5966
type_ = "circle"
6067
curve = curve_to_compas_circle(self._curve)
68+
elif self.is_ellipse:
69+
type_ = "ellipse"
70+
curve = curve_to_compas_ellipse(self._curve)
6171
else:
6272
type_ = "nurbs"
6373
curve = RhinoNurbsCurve.from_rhino(self._curve)
6474
return {
6575
"type": type_,
6676
"value": curve.data,
67-
"points": [self._start_vertex.point.data, self._end_vertex.point.data],
77+
"points": [self.start_vertex.point.data, self.end_vertex.point.data],
6878
}
6979

7080
@data.setter
@@ -78,9 +88,11 @@ def data(self, value):
7888
self._curve = circle_to_rhino_curve(
7989
Circle.from_data(value["value"])
8090
) # this returns a Nurbs Curve, why?
91+
elif curve_type == "ellipse":
92+
self._curve = ellipse_to_rhino_curve(value["value"])
8193
else:
8294
self._curve = RhinoNurbsCurve.from_data(value["value"]).rhino_curve
83-
# TODO: can a single edge be defined with more than start and end vertices?
95+
8496
self._start_vertex, self._end_vertex = RhinoBrepVertex(), RhinoBrepVertex()
8597
self._start_vertex._point = Point.from_data(value["points"][0])
8698
self._end_vertex._point = Point.from_data(value["points"][1])
@@ -103,7 +115,7 @@ def end_vertex(self):
103115

104116
@property
105117
def vertices(self):
106-
return [self._start_vertex, self._end_vertex]
118+
return [self.start_vertex, self.end_vertex]
107119

108120
@property
109121
def is_circle(self):
@@ -112,3 +124,7 @@ def is_circle(self):
112124
@property
113125
def is_line(self):
114126
return self._curve.IsLinear()
127+
128+
@property
129+
def is_ellipse(self):
130+
return self._curve.IsEllipse()

0 commit comments

Comments
 (0)