|
5 | 5 | import Rhino |
6 | 6 | import compas_rhino |
7 | 7 |
|
8 | | -from compas.utilities import memoize |
| 8 | +from compas.utilities import memoize, geometric_key |
9 | 9 | from compas.datastructures import Mesh |
10 | 10 | from compas.datastructures import meshes_join |
11 | 11 |
|
@@ -40,7 +40,104 @@ def geometry(self, geometry): |
40 | 40 | raise TypeError("Geometry cannot be interpreted as a `Rhino.Geometry.Surface`: {}".format(type(geometry))) |
41 | 41 | self._geometry = geometry |
42 | 42 |
|
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): |
44 | 141 | """Convert the surface to a COMPAS mesh. |
45 | 142 |
|
46 | 143 | Parameters |
|
0 commit comments