Skip to content

Commit 886cd2c

Browse files
committed
add to_compas_mesh and to_compas_quadmesh to RhinoSurface
1 parent c8ba0a6 commit 886cd2c

File tree

2 files changed

+101
-2
lines changed

2 files changed

+101
-2
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313
* Added `draw_circles` and `draw_planes` to `compas_blender`.
1414
* Added `compas_rhino.geometry.curves` plugins for `compas.geometry.curves` pluggables.
1515
* Added `compas_rhino.geometry.RhinoNurbsCurve`.
16+
* Modify `to_compas_mesh` in `compas_rhino.conversions.RhinoSurface` to use brep loops
1617

1718
### Changed
1819

1920
* Replaced implementation of `RGBColour` and `Float` with deprecation warning in `compas.utilities.descriptors`.
2021
* Moved all Rhino geometry and objects wrappers to `compas_rhino.conversions`.
2122
* Fixed bug in `compas_rhino.conversions.RhinoSurface.from_geometry`.
23+
* Rename existing `to_compas_mesh` to `to_compas_quadmesh` to `compas_rhino.conversions.RhinoSurface`.
2224

2325
### Removed
2426

src/compas_rhino/conversions/surface.py

Lines changed: 99 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import Rhino
66
import compas_rhino
77

8-
from compas.utilities import memoize
8+
from compas.utilities import memoize, geometric_key
99
from compas.datastructures import Mesh
1010
from compas.datastructures import meshes_join
1111

@@ -40,7 +40,104 @@ def geometry(self, geometry):
4040
raise TypeError("Geometry cannot be interpreted as a `Rhino.Geometry.Surface`: {}".format(type(geometry)))
4141
self._geometry = geometry
4242

43-
def to_compas_mesh(self, nu, nv=None, weld=False, facefilter=None, cls=None):
43+
def to_compas_mesh(self, cls=None, facefilter=None, cleanup=True):
44+
"""Convert the surface b-rep loops to a COMPAS mesh.
45+
46+
Parameters
47+
----------
48+
cls : :class:`compas.datastructures.Mesh`, optional
49+
The type of COMPAS mesh.
50+
facefilter : callable, optional
51+
A filter for selection which Brep faces to include.
52+
If provided, the filter should return ``True`` or ``False`` per face.
53+
A very simple filter that includes all faces is ``def facefilter(face): return True``.
54+
Default parameter value is ``None`` in which case all faces are included.
55+
cleanup : bool, optional
56+
Flag indicating to clean up the result.
57+
Cleaning up means to remove isolated faces and unused vertices.
58+
Default is ``True``.
59+
60+
Returns
61+
-------
62+
:class:`compas.datastructures.Mesh`
63+
The resulting mesh.
64+
65+
Examples
66+
--------
67+
>>> import compas_rhino
68+
>>> from compas_rhino.geometry import RhinoSurface
69+
>>> from compas_rhino.artists import MeshArtist
70+
71+
>>> def facefilter(face):
72+
... success, w, h = face.GetSurfaceSize()
73+
... if success:
74+
... if w > 10 and h > 10:
75+
... return True
76+
... return False
77+
...
78+
79+
>>> guid = compas_rhino.select_surface()
80+
>>> surf = RhinoSurface.from_guid(guid)
81+
>>> mesh = surf.to_compas(facefilter=facefilter)
82+
83+
>>> artist = MeshArtist(mesh, layer="Blocks")
84+
>>> artist.clear_layer()
85+
>>> artist.draw()
86+
87+
"""
88+
if not self.geometry.HasBrepForm:
89+
return
90+
brep = Rhino.Geometry.Brep.TryConvertBrep(self.geometry)
91+
if facefilter and callable(facefilter):
92+
brepfaces = [face for face in brep.Faces if facefilter(face)]
93+
else:
94+
brepfaces = brep.Faces
95+
# vertex maps and face lists
96+
gkey_xyz = {}
97+
faces = []
98+
for face in brepfaces:
99+
loop = face.OuterLoop
100+
curve = loop.To3dCurve()
101+
segments = curve.Explode()
102+
a = segments[0].PointAtStart
103+
b = segments[0].PointAtEnd
104+
a_gkey = geometric_key(a)
105+
b_gkey = geometric_key(b)
106+
gkey_xyz[a_gkey] = a
107+
gkey_xyz[b_gkey] = b
108+
face = [a_gkey, b_gkey]
109+
for segment in segments[1:-1]:
110+
b = segment.PointAtEnd
111+
b_gkey = geometric_key(b)
112+
face.append(b_gkey)
113+
gkey_xyz[b_gkey] = b
114+
faces.append(face)
115+
# vertices and faces
116+
gkey_index = {gkey: index for index, gkey in enumerate(gkey_xyz)}
117+
vertices = [list(xyz) for gkey, xyz in gkey_xyz.items()]
118+
faces = [[gkey_index[gkey] for gkey in face] for face in faces]
119+
# remove duplicates from vertexlist
120+
polygons = []
121+
for temp in faces:
122+
face = []
123+
for vertex in temp:
124+
if vertex not in face:
125+
face.append(vertex)
126+
polygons.append(face)
127+
# define mesh type
128+
cls = cls or Mesh
129+
# create mesh
130+
mesh = cls.from_vertices_and_faces(vertices, polygons)
131+
mesh.name = self.name
132+
# remove isolated faces
133+
if cleanup:
134+
for face in list(mesh.faces()):
135+
if not mesh.face_neighbors(face):
136+
mesh.delete_face(face)
137+
mesh.remove_unused_vertices()
138+
return mesh
139+
140+
def to_compas_quadmesh(self, nu, nv=None, weld=False, facefilter=None, cls=None):
44141
"""Convert the surface to a COMPAS mesh.
45142
46143
Parameters

0 commit comments

Comments
 (0)