From 773c5fbffa5e208cb7bd3ba7c3801c4939c0021b Mon Sep 17 00:00:00 2001 From: tomvanmele Date: Thu, 4 Jul 2024 21:48:02 +0200 Subject: [PATCH 1/5] Explicit methods for geometry and separate methods for doc objects --- CHANGELOG.md | 17 +- src/compas_rhino/conversions/__init__.py | 22 +- src/compas_rhino/conversions/breps.py | 113 ++++++- src/compas_rhino/conversions/curves.py | 101 +------ src/compas_rhino/conversions/docobjects.py | 148 ++++++++++ src/compas_rhino/conversions/meshes.py | 2 +- src/compas_rhino/conversions/surfaces.py | 326 +++------------------ 7 files changed, 342 insertions(+), 387 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index efe65f58ae54..11c1134bf02f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Added `compas.geometry.curves.curve.Curve.from_native`. * Added `compas_rhino.geometry.curves.curve.Curve.from_native`. * Added `compas_rhino.geometry.curves.nurbs.NurbsCurve.from_native`. +* Added `compas_rhino.conversions.breps.brep_to_compas_mesh`. +* Added `compas_rhino.conversions.docobjects.brepobject_to_compas`. +* Added `compas_rhino.conversions.docobjects.curveobject_to_compas`. +* Added `compas_rhino.conversions.docobjects.meshobject_to_compas`. +* Added `compas_rhino.conversions.docobjects.pointobject_to_compas`. +* Added `compas_rhino.conversions.docobjects.surfaceobject_to_compas`. ### Changed @@ -46,7 +52,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Changed `compas.geometry.curves.nurbs.NurbsCurve.__new__` to prevent instantiation of `NurbsCurve` directly. * Changed `compas_rhino.geometry.curves.new_nurbscurve_from_...` to `nurbscurve_from_...`. * Fixed `compas_ghpython` Grasshopper components not included in published pakcage. -* Chnaged `compas.colors.Color.coerce` to take color as is, if it is already aninstance of `compas.colors.Color`. +* Changed `compas.colors.Color.coerce` to take color as is, if it is already aninstance of `compas.colors.Color`. +* Changed `compas_rhino.conversions.surfaces.surface_to_compas` to work only with surface geometry. +* Changed `compas_rhino.conversions.curves.curve_to_compas_line` to work only with geometry. +* Changed `compas_rhino.conversions.curves.curve_to_compas_circle` to work only with geometry. +* Changed `compas_rhino.conversions.curves.curve_to_compas_ellipse` to work only with geometry. +* Changed `compas_rhino.conversions.curves.curve_to_compas_polyline` to work only with geometry. ### Removed @@ -75,6 +86,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Removed `compas.geometry.curves.curve.new_nurbscurve`. * Removed `compas_rhino.geometry.curves.new_curve`. * Removed `compas_rhino.geometry.curves.new_nurbscurve`. +* Removed `compas_rhino.conversions.surfaces.data_to_rhino_surface`. +* Removed `compas_rhino.conversions.surfaces.surface_to_compas_data`. +* Removed `compas_rhino.conversions.surfaces.surface_to_compas_quadmesh`. +* Removed `compas_rhino.conversions.curves.curve_to_compas_data`. ## [2.2.1] 2024-06-25 diff --git a/src/compas_rhino/conversions/__init__.py b/src/compas_rhino/conversions/__init__.py index ee610f2a17db..d621a7611459 100644 --- a/src/compas_rhino/conversions/__init__.py +++ b/src/compas_rhino/conversions/__init__.py @@ -43,11 +43,8 @@ ) from .surfaces import ( surface_to_rhino, - data_to_rhino_surface, - surface_to_compas_data, surface_to_compas, surface_to_compas_mesh, - surface_to_compas_quadmesh, ) from .shapes import ( box_to_rhino, @@ -77,6 +74,7 @@ brep_to_compas_cone, brep_to_compas_cylinder, brep_to_compas_sphere, + brep_to_compas_mesh, ) from .extrusions import ( extrusion_to_compas_box, @@ -89,6 +87,14 @@ transformation_matrix_to_rhino, ) +from .docobjects import ( + brepobject_to_compas, + curveobject_to_compas, + meshobject_to_compas, + pointobject_to_compas, + surfaceobject_to_compas, +) + __all__ = [ "ConversionError", @@ -127,11 +133,8 @@ "curve_to_compas", # surfaces "surface_to_rhino", - "surface_to_compas_data", - "data_to_rhino_surface", "surface_to_compas", "surface_to_compas_mesh", - "surface_to_compas_quadmesh", # shapes "box_to_rhino", "sphere_to_rhino", @@ -158,6 +161,7 @@ "brep_to_compas_cone", "brep_to_compas_cylinder", "brep_to_compas_sphere", + "brep_to_compas_mesh", # extrusions "extrusion_to_compas_box", "extrusion_to_compas_cylinder", @@ -165,4 +169,10 @@ # transformations "transformation_to_rhino", "transformation_matrix_to_rhino", + # docobjects + "brepobject_to_compas", + "curveobject_to_compas", + "meshobject_to_compas", + "pointobject_to_compas", + "surfaceobject_to_compas", ] diff --git a/src/compas_rhino/conversions/breps.py b/src/compas_rhino/conversions/breps.py index 8d4c32affe7a..415e2325b7fc 100644 --- a/src/compas_rhino/conversions/breps.py +++ b/src/compas_rhino/conversions/breps.py @@ -4,7 +4,12 @@ import scriptcontext as sc # type: ignore +from compas.datastructures import Mesh +from compas.geometry import Brep +from compas.tolerance import TOL + from .exceptions import ConversionError +from .geometry import point_to_compas from .shapes import cone_to_compas from .shapes import cylinder_to_compas from .shapes import sphere_to_compas @@ -15,7 +20,7 @@ def brep_to_rhino(brep): - """Convert a COMPAS brep to a Rhino brep. + """Convert a COMPAS Brep to a Rhino Brep. Parameters ---------- @@ -34,6 +39,26 @@ def brep_to_rhino(brep): # ============================================================================= +def brep_to_compas(brep): + """Convert a Rhino Brep to a COMPAS Brep. + + Parameters + ---------- + brep : :rhino:`Rhino.Geometry.Brep` + + Returns + ------- + :class:`compas.geometry.Brep` + + """ + return Brep.from_native(brep) + + +# ============================================================================= +# To COMPAS Shapes +# ============================================================================= + + def brep_to_compas_box(brep): """Convert a Rhino brep to a COMPAS box. @@ -120,3 +145,89 @@ def brep_to_compas_sphere(brep): result, sphere = face.TryGetSphere() if result: return sphere_to_compas(sphere) + + +# ============================================================================= +# To COMPAS Mesh +# ============================================================================= + + +def brep_to_compas_mesh(brep, facefilter=None, cleanup=False, cls=None): + """Convert the face loops of a Rhino brep to a COMPAS mesh. + + Parameters + ---------- + brep : :class:`Rhino.Geometry.Brep` + A Rhino brep. + facefilter : callable, optional + A filter for selection which Brep faces to include. + If provided, the filter should return True or False per face. + A very simple filter that includes all faces is ``def facefilter(face): return True``. + Default parameter value is None in which case all faces are included. + cleanup : bool, optional + Flag indicating to clean up the result. + Cleaning up means to remove isolated faces and unused vertices. + Default is False. + cls : :class:`compas.datastructures.Mesh`, optional + The type of COMPAS mesh. + + Returns + ------- + :class:`compas.datastructures.Mesh` + The resulting mesh. + + """ + if facefilter and callable(facefilter): + brepfaces = [face for face in brep.Faces if facefilter(face)] + else: + brepfaces = brep.Faces + + # vertex maps and face lists + gkey_xyz = {} + faces = [] + for face in brepfaces: + loop = face.OuterLoop + curve = loop.To3dCurve() + segments = list(curve.Explode()) + a = point_to_compas(segments[0].PointAtStart) + b = point_to_compas(segments[0].PointAtEnd) + a_gkey = TOL.geometric_key(a) + b_gkey = TOL.geometric_key(b) + gkey_xyz[a_gkey] = a + gkey_xyz[b_gkey] = b + face = [a_gkey, b_gkey] + for segment in segments[1:-1]: + b = point_to_compas(segment.PointAtEnd) + b_gkey = TOL.geometric_key(b) + face.append(b_gkey) + gkey_xyz[b_gkey] = b + faces.append(face) + + # vertices and faces + gkey_index = {gkey: index for index, gkey in enumerate(gkey_xyz)} + vertices = [list(xyz) for gkey, xyz in gkey_xyz.items()] + faces = [[gkey_index[gkey] for gkey in face] for face in faces] + + # remove duplicates from vertexlist + polygons = [] + for temp in faces: + face = [] + for vertex in temp: + if vertex not in face: + face.append(vertex) + polygons.append(face) + + # define mesh type + cls = cls or Mesh + # create mesh + mesh = cls.from_vertices_and_faces(vertices, polygons) + + # remove isolated faces + if cleanup: + if mesh.number_of_faces() > 1: + for face in list(mesh.faces()): + if not mesh.face_neighbors(face): + mesh.delete_face(face) + mesh.remove_unused_vertices() + + return mesh diff --git a/src/compas_rhino/conversions/curves.py b/src/compas_rhino/conversions/curves.py index fc1335f58991..902ba06ffefc 100644 --- a/src/compas_rhino/conversions/curves.py +++ b/src/compas_rhino/conversions/curves.py @@ -7,6 +7,7 @@ from compas.geometry import Arc from compas.geometry import Circle +from compas.geometry import Curve from compas.geometry import Ellipse from compas.geometry import Line from compas.geometry import NurbsCurve @@ -25,33 +26,6 @@ # ============================================================================= -def data_to_rhino_curve(data): - """Convert a COMPAS curve to a Rhino curve. - - Parameters - ---------- - data : dict - - Returns - ------- - :rhino:`Rhino.Geometry.NurbsCurve` - - """ - nurbs = Rhino.Geometry.NurbsCurve(data["degree"], len(data["points"])) - - for index, xyz in enumerate(data["points"]): - nurbs.Points.SetPoint(index, *xyz) - - knotvector = [] - for knot, mult in zip(data["knots"], data["multiplicities"]): - for i in range(mult): - knotvector.append(knot) - - for index, knot in enumerate(knotvector): - nurbs.Knots.Item[index] = knot - return nurbs - - def line_to_rhino(line): """Convert a COMPAS line to a Rhino line. @@ -308,8 +282,6 @@ def curve_to_compas_line(curve): :class:`compas.geometry.Line` """ - if isinstance(curve, Rhino.DocObjects.RhinoObject): - curve = curve.Geometry return Line(point_to_compas(curve.PointAtStart), point_to_compas(curve.PointAtEnd)) @@ -330,8 +302,6 @@ def curve_to_compas_circle(curve): If the curve cannot be converted to a circle. """ - if isinstance(curve, Rhino.DocObjects.RhinoObject): - curve = curve.Geometry result, circle = curve.TryGetCircle() if not result: raise ConversionError("The curve cannot be converted to a circle.") @@ -355,8 +325,6 @@ def curve_to_compas_ellipse(curve): If the curve cannot be converted to an ellipse. """ - if isinstance(curve, Rhino.DocObjects.RhinoObject): - curve = curve.Geometry result, ellipse = curve.TryGetEllipse() if not result: raise ConversionError("The curve cannot be converted to an ellipse.") @@ -380,74 +348,29 @@ def curve_to_compas_polyline(curve): If the curve cannot be converted to a polyline. """ - if isinstance(curve, Rhino.DocObjects.RhinoObject): - curve = curve.Geometry result, polyline = curve.TryGetPolyline() if not result: raise ConversionError("The curve cannot be converted to a polyline.") return polyline_to_compas(polyline) -def curve_to_compas_data(curve): - """Convert a Rhino curve to a COMPAS data dict. +def curve_to_compas(curve, try_nurbs=True): + """Convert a Rhino curve to a COMPAS curve. Parameters ---------- curve : :rhino:`Rhino.Geometry.Curve` + A Rhino curve. + try_nurbs : bool, optional + Try to convert the curve to a NURBS curve. Returns ------- - dict - - """ - if isinstance(curve, Rhino.DocObjects.RhinoObject): - curve = curve.Geometry - - nurbs = curve.ToNurbsCurve() - points = [] - weights = [] - knots = [] - multiplicities = [] - degree = nurbs.Degree - is_periodic = nurbs.IsPeriodic - - for index in range(nurbs.Points.Count): - point = nurbs.Points.Item[index] - points.append(point_to_compas(point.Location)) - weights.append(point.Weight) - - for index in range(nurbs.Knots.Count): - knots.append(nurbs.Knots.Item[index]) - multiplicities.append(nurbs.Knots.KnotMultiplicity(index)) - - return { - "points": [point.data for point in points], - "weights": weights, - "knots": knots, - "multiplicities": multiplicities, - "degree": degree, - "is_periodic": is_periodic, - } - - -def curve_to_compas(curve): - """Convert a Rhino (Nurbs) curve to a COMPAS curve. - - Parameters - ---------- - curve : :rhino:`Rhino.Geometry.Curve` - - Returns - ------- - :class:`compas.geometry.NurbsCurve` - - Raises - ------ - ConversionError - If the curve cannot be converted to a COMPAS curve. + :class:`compas.geometry.Curve` | :class:`compas.geometry.NurbsCurve` + If `try_nurbs` is `True`, and the geometry has a NURBS representation, return a NURBS curve. + Otherwise return a general curve. """ - if isinstance(curve, Rhino.DocObjects.RhinoObject): - curve = curve.Geometry - nurbs = curve.ToNurbsCurve() - return NurbsCurve.from_native(nurbs) + if try_nurbs and curve.HasNurbsForm(): + return NurbsCurve.from_native(curve.ToNurbsCurve()) + return Curve.from_native(curve) diff --git a/src/compas_rhino/conversions/docobjects.py b/src/compas_rhino/conversions/docobjects.py index e69de29bb2d1..a4a978052618 100644 --- a/src/compas_rhino/conversions/docobjects.py +++ b/src/compas_rhino/conversions/docobjects.py @@ -0,0 +1,148 @@ +from __future__ import absolute_import # noqa: I001 +from __future__ import division +from __future__ import print_function + +import Rhino.Geometry # type: ignore # noqa: F401 + +from .exceptions import ConversionError + +from .breps import brep_to_compas +from .curves import curve_to_compas +from .geometry import point_to_compas +from .meshes import mesh_to_compas +from .surfaces import surface_to_compas + + +def brepobject_to_compas(obj): + """Convert a Rhino BrepObject to a COMPAS Brep. + + Parameters + ---------- + obj : Rhino.DocObjects.BrepObject + + Returns + ------- + :class:`compas.geometry.Brep` + + Raises + ------ + ConversionError + + """ + try: + geometry = obj.BrepGeometry + brep = brep_to_compas(geometry) + except Exception: + raise ConversionError("Rhino Object of type {} cannot be converted to a COMPAS Brep.".format(type(obj))) + + return brep + + +def curveobject_to_compas(obj, try_nurbs=True): + """Convert a Rhino CurveObject to a COMPAS Curve. + + Parameters + ---------- + obj : Rhino.DocObjects.CurveObject + The Rhino Object. + try_nurbs : bool, optional + Try to convert the curve to a NURBS curve. + + Returns + ------- + :class:`compas.geometry.Curve` | :class:`compas.geometry.NurbsCurve` + If `try_nurbs` is `True`, and the geometry of the object has a NURBS representation, return a NURBS curve. + Otherwise return a general curve. + + Raises + ------ + ConversionError + + """ + try: + geometry = obj.CurveGeometry + curve = curve_to_compas(geometry, try_nurbs=try_nurbs) + except Exception: + raise ConversionError("Rhino Object of type {} cannot be converted to a COMPAS Curve.".format(type(obj))) + + return curve + + +def meshobject_to_compas(obj): + """Convert a Rhino MeshObject to a COMPAS Mesh. + + Parameters + ---------- + obj : Rhino.DocObjects.MeshObject + + Returns + ------- + :class:`compas.datastructures.Mesh` + + Raises + ------ + ConversionError + + """ + try: + geometry = obj.MeshGeometry + mesh = mesh_to_compas(geometry) + except Exception: + raise ConversionError("Rhino Object of type {} cannot be converted to a COMPAS Mesh.".format(type(obj))) + + return mesh + + +def pointobject_to_compas(obj): + """Convert a Rhino PointObject to a COMPAS Point. + + Parameters + ---------- + obj : Rhino.DocObjects.PointObject + + Returns + ------- + :class:`compas.geometry.Point` + + Raises + ------ + ConversionError + + """ + try: + geometry = obj.PointGeometry + point = point_to_compas(geometry) + except Exception: + raise ConversionError("Rhino Object of type {} cannot be converted to a COMPAS Point.".format(type(obj))) + + return point + + +def surfaceobject_to_compas(obj, try_nurbs=True): + """Convert a Rhino SurfaceObject to a COMPAS Surface. + + Parameters + ---------- + obj : Rhino.DocObjects.SurfaceObject + The surface object. + try_nurbs : bool, optional + Try to convert the surface to a NURBS surface. + + Returns + ------- + :class:`compas.geometry.Surface` | :class:`compas.geometry.NurbsSurface` + If `try_nurbs` is `True`, and the geometry of the object has a NURBS representation, return a NURBS surface. + Otherwise return a general surface. + + Raises + ------ + ConversionError + + """ + try: + geometry = obj.SurfaceGeometry + surface = surface_to_compas(geometry, try_nurbs=try_nurbs) + except Exception: + raise ConversionError("Rhino Object of type {} cannot be converted to a COMPAS Surface.".format(type(obj))) + + return surface diff --git a/src/compas_rhino/conversions/meshes.py b/src/compas_rhino/conversions/meshes.py index bd9370cca579..82c89ed4ea56 100644 --- a/src/compas_rhino/conversions/meshes.py +++ b/src/compas_rhino/conversions/meshes.py @@ -120,7 +120,7 @@ def vertices_and_faces_to_rhino( vertexcolors=None, facecolors=None, disjoint=True, - face_callback=None, + face_callback=None, # type: ignore ): """Convert COMPAS vertices and faces to a Rhino mesh object. diff --git a/src/compas_rhino/conversions/surfaces.py b/src/compas_rhino/conversions/surfaces.py index fbb84010aed5..219e401a924e 100644 --- a/src/compas_rhino/conversions/surfaces.py +++ b/src/compas_rhino/conversions/surfaces.py @@ -2,21 +2,15 @@ from __future__ import division from __future__ import print_function -import Rhino # type: ignore - +# import Rhino # type: ignore from compas.datastructures import Mesh from compas.geometry import NurbsSurface -from compas.geometry import Point -from compas.tolerance import TOL +from compas.geometry import Surface + +# from compas.tolerance import TOL from compas.utilities import memoize -from .exceptions import ConversionError from .geometry import point_to_compas -from .geometry import point_to_rhino - -# ============================================================================= -# To Rhino -# ============================================================================= def surface_to_rhino(surface): @@ -32,255 +26,37 @@ def surface_to_rhino(surface): Rhino.Geometry.Surface """ - return surface.rhino_surface - - -def data_to_rhino_surface(data): - """Convert a COMPAS surface to a Rhino surface. - - Parameters - ---------- - data: dict - - Returns - ------- - :rhino:`Rhino.Geometry.NurbsSurface` - - """ - points = [[Point.__from_data__(point) for point in row] for row in data["points"]] - - nu = len(points[0]) - nv = len(points) - - nurbs = Rhino.Geometry.NurbsSurface.Create(3, False, data["u_degree"] + 1, data["v_degree"] + 1, nu, nv) - for i in range(nu): - for j in range(nv): - nurbs.Points.SetPoint(i, j, point_to_rhino(points[j][i])) - nurbs.Points.SetWeight(i, j, data["weights"][j][i]) - - u_knotvector = [] - for knot, mult in zip(data["u_knots"], data["u_mults"]): - for i in range(mult): - u_knotvector.append(knot) - - for index, knot in enumerate(u_knotvector): - nurbs.KnotsU.Item[index] = knot - - v_knotvector = [] - for knot, mult in zip(data["v_knots"], data["v_mults"]): - for i in range(mult): - v_knotvector.append(knot) - - for index, knot in enumerate(v_knotvector): - nurbs.KnotsV.Item[index] = knot - - return nurbs - - -# ============================================================================= -# To COMPAS -# ============================================================================= - - -def surface_to_compas_data(surface): - """Convert a Rhino surface to a COMPAS surface. - - Parameters - ---------- - surface: :rhino:`Rhino.Geometry.Surface` - - Returns - ------- - dict - - """ - surface = surface.ToNurbsSurface() - - points = [] - weights = [] - for j in range(surface.Points.VCount): - _points = [] - _weights = [] - for i in range(surface.Points.UCount): - point = surface.Points.GetPoint(i, j) - weight = surface.Points.GetWeight(i, j) - _points.append(point_to_compas(point)) - _weights.append(weight) - points.append(_points) - weights.append(_weights) - - u_knots = [] - u_mults = [] - for index in range(surface.KnotsU.Count): - u_knots.append(surface.KnotsU.Item[index]) - u_mults.append(surface.KnotsU.KnotMultiplicity(index)) + return surface.native_surface - v_knots = [] - v_mults = [] - for index in range(surface.KnotsV.Count): - v_knots.append(surface.KnotsV.Item[index]) - v_mults.append(surface.KnotsV.KnotMultiplicity(index)) - u_degree = surface.OrderU - 1 - v_degree = surface.OrderV - 1 - - is_u_periodic = False - is_v_periodic = False - - return { - "points": [[point.data for point in row] for row in points], - "weights": weights, - "u_knots": u_knots, - "v_knots": v_knots, - "u_mults": u_mults, - "v_mults": v_mults, - "u_degree": u_degree, - "v_degree": v_degree, - "is_u_periodic": is_u_periodic, - "is_v_periodic": is_v_periodic, - } - - -def surface_to_compas(surface): +def surface_to_compas(surface, try_nurbs=True): """Convert a Rhino surface to a COMPAS surface. Parameters ---------- surface: :rhino:`Rhino.Geometry.Surface` + A Rhino surface geometry. + try_nurbs : bool, optional + Try to convert the surface to a NURBS surface. Returns ------- - :class:`compas.geometry.Surface` + :class:`compas.geometry.Surface` | :class:`compas.geometry.NurbsSurface` + If `try_nurbs` is `True`, and the geometry of the object has a NURBS representation, return a NURBS surface. + Otherwise return a general surface. """ - if isinstance(surface, Rhino.DocObjects.RhinoObject): - surface = surface.Geometry - - if not isinstance(surface, Rhino.Geometry.Brep): - brep = Rhino.Geometry.Brep.TryConvertBrep(surface) - else: - brep = surface - - if brep.Surfaces.Count > 1: # type: ignore - raise ConversionError("Conversion of a Brep with multiple underlying surface is currently not supported.") - - return NurbsSurface.from_native(brep.Surfaces[0]) - - -def surface_to_compas_mesh(surface, facefilter=None, cleanup=False, cls=None): - """Convert the surface b-rep loops to a COMPAS mesh. - - Parameters - ---------- - surface : :class:`Rhino.Geometry.Surface` - A Rhino surface. - facefilter : callable, optional - A filter for selection which Brep faces to include. - If provided, the filter should return True or False per face. - A very simple filter that includes all faces is ``def facefilter(face): return True``. - Default parameter value is None in which case all faces are included. - cleanup : bool, optional - Flag indicating to clean up the result. - Cleaning up means to remove isolated faces and unused vertices. - Default is False. - cls : :class:`compas.datastructures.Mesh`, optional - The type of COMPAS mesh. - - Returns - ------- - :class:`compas.datastructures.Mesh` - The resulting mesh. - - Examples - -------- - >>> import compas_rhino - >>> from compas_rhino8.geometry import RhinoSurface - >>> from compas.scene import Scene - - >>> def facefilter(face): - ... success, w, h = face.GetSurfaceSize() - ... if success: - ... if w > 10 and h > 10: - ... return True - ... return False - - >>> guid = compas_rhino.select_surface() - >>> surf = Rhino.Geometry.Surface.from_guid(guid) - >>> mesh = surf.to_compas(facefilter=facefilter) + if try_nurbs and surface.HasNurbsForm(): + return NurbsSurface.from_native(surface.ToNurbsSurface()) + return Surface.from_native(surface) - >>> scene = Scene() - >>> scene.add(mesh, layer="Blocks") - >>> scene.draw() - """ - if isinstance(surface, Rhino.DocObjects.RhinoObject): - surface = surface.Geometry - - if not surface.HasBrepForm: - return - - if not isinstance(surface, Rhino.Geometry.Brep): - brep = Rhino.Geometry.Brep.TryConvertBrep(surface) - else: - brep = surface - - if facefilter and callable(facefilter): - brepfaces = [face for face in brep.Faces if facefilter(face)] - else: - brepfaces = brep.Faces - - # vertex maps and face lists - gkey_xyz = {} - faces = [] - for face in brepfaces: - loop = face.OuterLoop - curve = loop.To3dCurve() - segments = list(curve.Explode()) - a = point_to_compas(segments[0].PointAtStart) - b = point_to_compas(segments[0].PointAtEnd) - a_gkey = TOL.geometric_key(a) - b_gkey = TOL.geometric_key(b) - gkey_xyz[a_gkey] = a - gkey_xyz[b_gkey] = b - face = [a_gkey, b_gkey] - for segment in segments[1:-1]: - b = point_to_compas(segment.PointAtEnd) - b_gkey = TOL.geometric_key(b) - face.append(b_gkey) - gkey_xyz[b_gkey] = b - faces.append(face) - - # vertices and faces - gkey_index = {gkey: index for index, gkey in enumerate(gkey_xyz)} - vertices = [list(xyz) for gkey, xyz in gkey_xyz.items()] - faces = [[gkey_index[gkey] for gkey in face] for face in faces] - - # remove duplicates from vertexlist - polygons = [] - for temp in faces: - face = [] - for vertex in temp: - if vertex not in face: - face.append(vertex) - polygons.append(face) - - # define mesh type - cls = cls or Mesh - # create mesh - mesh = cls.from_vertices_and_faces(vertices, polygons) - - # remove isolated faces - if cleanup: - if mesh.number_of_faces() > 1: - for face in list(mesh.faces()): - if not mesh.face_neighbors(face): - mesh.delete_face(face) - mesh.remove_unused_vertices() - - return mesh +# ============================================================================= +# To Mesh +# ============================================================================= -def surface_to_compas_quadmesh(surface, nu, nv=None, weld=False, facefilter=None, cls=None): +def surface_to_compas_mesh(surface, nu, nv=None, weld=False, cls=None): """Convert the surface to a COMPAS mesh. Parameters @@ -295,61 +71,33 @@ def surface_to_compas_quadmesh(surface, nu, nv=None, weld=False, facefilter=None weld: bool, optional Weld the vertices of the mesh. Default is False. - facefilter: callable, optional - A filter for selection which Brep faces to include. - If provided, the filter should return True or False per face. - A very simple filter that includes all faces is ``def facefilter(face): return True``. - Default parameter value is None in which case all faces are included. - cls: :class:`compas.geometry.Mesh`, optional + cls: :class:`compas.datastructures.Mesh`, optional The type of COMPAS mesh. Returns ------- - :class:`compas.geometry.Mesh` + :class:`compas.datastructures.Mesh` """ nv = nv or nu cls = cls or Mesh - if isinstance(surface, Rhino.DocObjects.RhinoObject): - surface = surface.Geometry - - if not surface.HasBrepForm: - return - - if not isinstance(surface, Rhino.Geometry.Brep): - brep = Rhino.Geometry.Brep.TryConvertBrep(surface) - else: - brep = surface + domain_u = surface.Domain(0) + domain_v = surface.Domain(1) + du = (domain_u[1] - domain_u[0]) / (nu) + dv = (domain_v[1] - domain_v[0]) / (nv) - if facefilter and callable(facefilter): - faces = [face for face in brep.Faces if facefilter(face)] - else: - faces = brep.Faces + @memoize + def point_at(i, j): + return point_to_compas(surface.PointAt(i, j)) - meshes = [] - for face in faces: - domain_u = face.Domain(0) - domain_v = face.Domain(1) - du = (domain_u[1] - domain_u[0]) / (nu) - dv = (domain_v[1] - domain_v[0]) / (nv) - - @memoize - def point_at(i, j): - return point_to_compas(face.PointAt(i, j)) - - quads = [] - for i in range(nu): - for j in range(nv): - a = point_at(domain_u[0] + (i + 0) * du, domain_v[0] + (j + 0) * dv) - b = point_at(domain_u[0] + (i + 1) * du, domain_v[0] + (j + 0) * dv) - c = point_at(domain_u[0] + (i + 1) * du, domain_v[0] + (j + 1) * dv) - d = point_at(domain_u[0] + (i + 0) * du, domain_v[0] + (j + 1) * dv) - quads.append([a, b, c, d]) - - meshes.append(cls.from_polygons(quads)) + quads = [] + for i in range(nu): + for j in range(nv): + a = point_at(domain_u[0] + (i + 0) * du, domain_v[0] + (j + 0) * dv) + b = point_at(domain_u[0] + (i + 1) * du, domain_v[0] + (j + 0) * dv) + c = point_at(domain_u[0] + (i + 1) * du, domain_v[0] + (j + 1) * dv) + d = point_at(domain_u[0] + (i + 0) * du, domain_v[0] + (j + 1) * dv) + quads.append([a, b, c, d]) - mesh = meshes[0] - for other in meshes[1:]: - mesh.join(other) - return mesh + return cls.from_polygons(quads) From 6c37fc252060b73e8bf8692c481f2b34cc657af8 Mon Sep 17 00:00:00 2001 From: tomvanmele Date: Fri, 5 Jul 2024 15:56:50 +0200 Subject: [PATCH 2/5] deprecation warnings --- CHANGELOG.md | 4 + src/compas_rhino/objects.py | 387 +++++++++++++++++++----------------- 2 files changed, 212 insertions(+), 179 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11c1134bf02f..b3adb52dee2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Changed `compas_rhino.conversions.curves.curve_to_compas_circle` to work only with geometry. * Changed `compas_rhino.conversions.curves.curve_to_compas_ellipse` to work only with geometry. * Changed `compas_rhino.conversions.curves.curve_to_compas_polyline` to work only with geometry. +* Changed `compas_rhino.objects.get_point_coordinates` to deprecated (removed in v2.3). +* Changed `compas_rhino.objects.get_line_coordinates` to deprecated (removed in v2.3). +* Changed `compas_rhino.objects.get_polyline_coordinates` to deprecated (removed in v2.3). +* Changed `compas_rhino.objects.get_polygon_coordinates` to deprecated (removed in v2.3). ### Removed diff --git a/src/compas_rhino/objects.py b/src/compas_rhino/objects.py index 2601f3836a2b..533bedadb66d 100644 --- a/src/compas_rhino/objects.py +++ b/src/compas_rhino/objects.py @@ -3,6 +3,7 @@ from __future__ import print_function import json +import warnings import Rhino # type: ignore import rhinoscriptsyntax as rs # type: ignore @@ -454,12 +455,19 @@ def get_point_coordinates(guids): list[[float, float, float]] The location coordinates of the points. + Warnings + -------- + .. deprecated:: 2.3 + Use `compas_rhino.conversions` instead. + """ + warnings.warn("This function will be removed in v2.3. Please use `compas_rhino.conversions` instead.", DeprecationWarning, stacklevel=2) + points = [] for guid in guids: point = rs.PointCoordinates(guid) if point: - points.append(map(float, point)) + points.append(point) return points @@ -796,16 +804,23 @@ def get_line_coordinates(guids): list[tuple[[float, float, float], [float, float, float]]] A start and end point per line. + Warnings + -------- + .. deprecated:: 2.3 + Use `compas_rhino.conversions` instead. + """ + warnings.warn("This function will be removed in v2.3. Please use `compas_rhino.conversions` instead.", DeprecationWarning, stacklevel=2) + if isinstance(guids, System.Guid): - sp = map(float, rs.CurveStartPoint(guids)) - ep = map(float, rs.CurveEndPoint(guids)) - return sp, ep + sp = rs.CurveStartPoint(guids) + ep = rs.CurveEndPoint(guids) + return [sp.X, sp.Y, sp.Z], [ep.X, ep.Y, ep.Z] lines = [] for guid in guids: - sp = map(float, rs.CurveStartPoint(guid)) - ep = map(float, rs.CurveEndPoint(guid)) - lines.append((sp, ep)) + sp = rs.CurveStartPoint(guid) + ep = rs.CurveEndPoint(guid) + lines.append(([sp.X, sp.Y, sp.Z], [ep.X, ep.Y, ep.Z])) return lines @@ -822,7 +837,14 @@ def get_polyline_coordinates(guids): list[list[[float, float, float]]] A list of point coordinates per polyline. + Warnings + -------- + .. deprecated:: 2.3 + Use `compas_rhino.conversions` instead. + """ + warnings.warn("This function will be removed in v2.3. Please use `compas_rhino.conversions` instead.", DeprecationWarning, stacklevel=2) + if isinstance(guids, System.Guid): points = rs.PolylineVertices(guids) coords = [] @@ -852,7 +874,14 @@ def get_polygon_coordinates(guids): list[list[[float, float, float]]] A list of point coordinates per polygon. + Warnings + -------- + .. deprecated:: 2.3 + Use `compas_rhino.conversions` instead. + """ + warnings.warn("This function will be removed in v2.3. Please use `compas_rhino.conversions` instead.", DeprecationWarning, stacklevel=2) + if isinstance(guids, System.Guid): points = rs.CurvePoints(guids) coords = [] @@ -967,175 +996,175 @@ def select_meshes(message="Select multiple meshes."): return guids -def get_meshes(layer=None): - if layer: - rs.EnableRedraw(False) - # Argument names for LayerVisible command are not the same for Rhino5 and Rhino6 - # that is why we use positional instead of named arguments - visible = rs.LayerVisible(layer, True, True) - guids = rs.ObjectsByType(rs.filter.mesh) - guids = list(set(guids) & set(rs.ObjectsByLayer(layer))) - rs.LayerVisible(layer, visible, True) - rs.EnableRedraw(True) - else: - guids = rs.ObjectsByType(rs.filter.mesh) - return guids - - -def get_mesh_border(guid): - return rs.DuplicateMeshBorder(guid) - - -def get_mesh_face_vertices(guid): - faces = [] - if guid: - temp = rs.MeshFaceVertices(guid) - faces = map(list, temp) - return faces - - -def get_mesh_vertex_coordinates(guid): - vertices = [] - if guid: - vertices = [map(float, vertex) for vertex in rs.MeshVertices(guid)] - return vertices - - -def get_mesh_vertex_colors(guid): - colors = [] - if guid: - temp = rs.MeshVertexColors(guid) - if temp: - colors = map(list, temp) - return colors - - -def set_mesh_vertex_colors(guid, colors): - if not guid: - return - return rs.MeshVertexColors(guid, colors) - - -def get_mesh_vertices_and_faces(guid): - if not guid: - return - vertices = [map(float, vertex) for vertex in rs.MeshVertices(guid)] - faces = map(list, rs.MeshFaceVertices(guid)) - return vertices, faces - - -def get_mesh_vertex_index(guid): - class CustomGetObject(Rhino.Input.Custom.GetObject): - def CustomGeometryFilter(self, rhino_object, geometry, component_index): - return guid == rhino_object.Id - - go = CustomGetObject() - go.SetCommandPrompt("Select one vertex of the mesh.") - go.GeometryFilter = Rhino.DocObjects.ObjectType.MeshVertex - go.AcceptNothing(True) - if go.Get() != Rhino.Input.GetResult.Object: - return None - objref = go.Object(0) - if not objref: - return None - tvindex = objref.GeometryComponentIndex.Index - mobj = sc.doc.Objects.Find(guid) - mgeo = mobj.Geometry - temp = mgeo.TopologyVertices.MeshVertexIndices(tvindex) - vindex = temp[0] - go.Dispose() - return vindex - - -def get_mesh_face_index(guid): - class CustomGetObject(Rhino.Input.Custom.GetObject): - def CustomGeometryFilter(self, rhino_object, geometry, component_index): - return guid == rhino_object.Id - - go = CustomGetObject() - go.SetCommandPrompt("Select one face of the mesh.") - go.GeometryFilter = Rhino.DocObjects.ObjectType.MeshFace - go.AcceptNothing(True) - if go.Get() != Rhino.Input.GetResult.Object: - return None - objref = go.Object(0) - if not objref: - return None - findex = objref.GeometryComponentIndex.Index - go.Dispose() - return findex - - -def get_mesh_edge_index(guid): - class CustomGetObject(Rhino.Input.Custom.GetObject): - def CustomGeometryFilter(self, rhino_object, geometry, component_index): - return guid == rhino_object.Id - - go = CustomGetObject() - go.SetCommandPrompt("Select an edge of the mesh.") - go.GeometryFilter = Rhino.DocObjects.ObjectType.MeshEdge - go.AcceptNothing(True) - if go.Get() != Rhino.Input.GetResult.Object: - return None - objref = go.Object(0) - if not objref: - return None - eindex = objref.GeometryComponentIndex.Index - go.Dispose() - return eindex - - -def get_mesh_vertex_indices(guid): - tvindices = rs.GetMeshVertices(guid, "Select mesh vertices.") - if not tvindices: - return - mobj = sc.doc.Objects.Find(guid) - mgeo = mobj.Geometry - vindices = [] - for tvindex in tvindices: - temp = mgeo.TopologyVertices.MeshVertexIndices(tvindex) - vindices.append(temp[0]) - return vindices - - -def get_mesh_face_indices(guid): - return rs.GetMeshFaces(guid, "Select mesh faces.") - - -def get_mesh_vertex_face_indices(guid): - vindex = get_mesh_vertex_index(guid) - if vindex is None: - return - mobj = sc.doc.Objects.Find(guid) - mgeo = mobj.Geometry - findices = mgeo.TopologyVertices.ConnectedFaces(vindex) - return findices - - -def get_mesh_face_vertex_indices(guid): - findex = get_mesh_face_index(guid) - if findex is None: - return - mobj = sc.doc.Objects.Find(guid) - mgeo = mobj.Geometry - tvertices = mgeo.Faces.GetTopologicalVertices(findex) - vindices = [] - for tvertex in tvertices: - temp = mgeo.TopologyVertices.MeshVertexIndices(tvertex) - vindices.append(temp[0]) - return vindices - - -def get_mesh_edge_vertex_indices(guid): - eindex = get_mesh_edge_index(guid) - if eindex is None: - return - mobj = sc.doc.Objects.Find(guid) - mgeo = mobj.Geometry - temp = mgeo.TopologyEdges.GetTopologyVertices(eindex) - tvindices = temp.I, temp.J - vindices = [] - for tvindex in tvindices: - temp = mgeo.TopologyVertices.MeshVertexIndices(tvindex) - vindices.append(temp[0]) - return vindices +# def get_meshes(layer=None): +# if layer: +# rs.EnableRedraw(False) +# # Argument names for LayerVisible command are not the same for Rhino5 and Rhino6 +# # that is why we use positional instead of named arguments +# visible = rs.LayerVisible(layer, True, True) +# guids = rs.ObjectsByType(rs.filter.mesh) +# guids = list(set(guids) & set(rs.ObjectsByLayer(layer))) +# rs.LayerVisible(layer, visible, True) +# rs.EnableRedraw(True) +# else: +# guids = rs.ObjectsByType(rs.filter.mesh) +# return guids + + +# def get_mesh_border(guid): +# return rs.DuplicateMeshBorder(guid) + + +# def get_mesh_face_vertices(guid): +# faces = [] +# if guid: +# temp = rs.MeshFaceVertices(guid) +# faces = map(list, temp) +# return faces + + +# def get_mesh_vertex_coordinates(guid): +# vertices = [] +# if guid: +# vertices = [map(float, vertex) for vertex in rs.MeshVertices(guid)] +# return vertices + + +# def get_mesh_vertex_colors(guid): +# colors = [] +# if guid: +# temp = rs.MeshVertexColors(guid) +# if temp: +# colors = map(list, temp) +# return colors + + +# def set_mesh_vertex_colors(guid, colors): +# if not guid: +# return +# return rs.MeshVertexColors(guid, colors) + + +# def get_mesh_vertices_and_faces(guid): +# if not guid: +# return +# vertices = [map(float, vertex) for vertex in rs.MeshVertices(guid)] +# faces = map(list, rs.MeshFaceVertices(guid)) +# return vertices, faces + + +# def get_mesh_vertex_index(guid): +# class CustomGetObject(Rhino.Input.Custom.GetObject): +# def CustomGeometryFilter(self, rhino_object, geometry, component_index): +# return guid == rhino_object.Id + +# go = CustomGetObject() +# go.SetCommandPrompt("Select one vertex of the mesh.") +# go.GeometryFilter = Rhino.DocObjects.ObjectType.MeshVertex +# go.AcceptNothing(True) +# if go.Get() != Rhino.Input.GetResult.Object: +# return None +# objref = go.Object(0) +# if not objref: +# return None +# tvindex = objref.GeometryComponentIndex.Index +# mobj = sc.doc.Objects.Find(guid) +# mgeo = mobj.Geometry +# temp = mgeo.TopologyVertices.MeshVertexIndices(tvindex) +# vindex = temp[0] +# go.Dispose() +# return vindex + + +# def get_mesh_face_index(guid): +# class CustomGetObject(Rhino.Input.Custom.GetObject): +# def CustomGeometryFilter(self, rhino_object, geometry, component_index): +# return guid == rhino_object.Id + +# go = CustomGetObject() +# go.SetCommandPrompt("Select one face of the mesh.") +# go.GeometryFilter = Rhino.DocObjects.ObjectType.MeshFace +# go.AcceptNothing(True) +# if go.Get() != Rhino.Input.GetResult.Object: +# return None +# objref = go.Object(0) +# if not objref: +# return None +# findex = objref.GeometryComponentIndex.Index +# go.Dispose() +# return findex + + +# def get_mesh_edge_index(guid): +# class CustomGetObject(Rhino.Input.Custom.GetObject): +# def CustomGeometryFilter(self, rhino_object, geometry, component_index): +# return guid == rhino_object.Id + +# go = CustomGetObject() +# go.SetCommandPrompt("Select an edge of the mesh.") +# go.GeometryFilter = Rhino.DocObjects.ObjectType.MeshEdge +# go.AcceptNothing(True) +# if go.Get() != Rhino.Input.GetResult.Object: +# return None +# objref = go.Object(0) +# if not objref: +# return None +# eindex = objref.GeometryComponentIndex.Index +# go.Dispose() +# return eindex + + +# def get_mesh_vertex_indices(guid): +# tvindices = rs.GetMeshVertices(guid, "Select mesh vertices.") +# if not tvindices: +# return +# mobj = sc.doc.Objects.Find(guid) +# mgeo = mobj.Geometry +# vindices = [] +# for tvindex in tvindices: +# temp = mgeo.TopologyVertices.MeshVertexIndices(tvindex) +# vindices.append(temp[0]) +# return vindices + + +# def get_mesh_face_indices(guid): +# return rs.GetMeshFaces(guid, "Select mesh faces.") + + +# def get_mesh_vertex_face_indices(guid): +# vindex = get_mesh_vertex_index(guid) +# if vindex is None: +# return +# mobj = sc.doc.Objects.Find(guid) +# mgeo = mobj.Geometry +# findices = mgeo.TopologyVertices.ConnectedFaces(vindex) +# return findices + + +# def get_mesh_face_vertex_indices(guid): +# findex = get_mesh_face_index(guid) +# if findex is None: +# return +# mobj = sc.doc.Objects.Find(guid) +# mgeo = mobj.Geometry +# tvertices = mgeo.Faces.GetTopologicalVertices(findex) +# vindices = [] +# for tvertex in tvertices: +# temp = mgeo.TopologyVertices.MeshVertexIndices(tvertex) +# vindices.append(temp[0]) +# return vindices + + +# def get_mesh_edge_vertex_indices(guid): +# eindex = get_mesh_edge_index(guid) +# if eindex is None: +# return +# mobj = sc.doc.Objects.Find(guid) +# mgeo = mobj.Geometry +# temp = mgeo.TopologyEdges.GetTopologyVertices(eindex) +# tvindices = temp.I, temp.J +# vindices = [] +# for tvindex in tvindices: +# temp = mgeo.TopologyVertices.MeshVertexIndices(tvindex) +# vindices.append(temp[0]) +# return vindices From d01f5b09ab1fad8f9ceff8d1c91e923a80cc0a8f Mon Sep 17 00:00:00 2001 From: Tom Van Mele Date: Sat, 6 Jul 2024 07:42:37 +0200 Subject: [PATCH 3/5] Update CHANGELOG.md Co-authored-by: Chen Kasirer --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0217bf41fbe..0f2ad555cc2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,7 +53,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Changed `compas.geometry.curves.nurbs.NurbsCurve.__new__` to prevent instantiation of `NurbsCurve` directly. * Changed `compas_rhino.geometry.curves.new_nurbscurve_from_...` to `nurbscurve_from_...`. * Fixed `compas_ghpython` Grasshopper components not included in published pakcage. -* Changed `compas.colors.Color.coerce` to take color as is, if it is already aninstance of `compas.colors.Color`. +* Changed `compas.colors.Color.coerce` to take color as is, if it is already an instance of `compas.colors.Color`. * Changed `compas_rhino.conversions.surfaces.surface_to_compas` to work only with surface geometry. * Changed `compas_rhino.conversions.curves.curve_to_compas_line` to work only with geometry. * Changed `compas_rhino.conversions.curves.curve_to_compas_circle` to work only with geometry. From d1d8c61e78ae300f5657e42e49adf6d6c38cda89 Mon Sep 17 00:00:00 2001 From: tomvanmele Date: Sat, 6 Jul 2024 08:09:31 +0200 Subject: [PATCH 4/5] clean up and structure --- CHANGELOG.md | 1 - src/compas_rhino/conversions/surfaces.py | 3 - src/compas_rhino/drawing.py | 4 +- src/compas_rhino/objects.py | 1051 +++++++++------------- 4 files changed, 434 insertions(+), 625 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0217bf41fbe..1cd88e2dc00b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -107,7 +107,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Removed - ## [2.2.0] 2024-06-24 ### Added diff --git a/src/compas_rhino/conversions/surfaces.py b/src/compas_rhino/conversions/surfaces.py index 219e401a924e..ada0588f315a 100644 --- a/src/compas_rhino/conversions/surfaces.py +++ b/src/compas_rhino/conversions/surfaces.py @@ -2,12 +2,9 @@ from __future__ import division from __future__ import print_function -# import Rhino # type: ignore from compas.datastructures import Mesh from compas.geometry import NurbsSurface from compas.geometry import Surface - -# from compas.tolerance import TOL from compas.utilities import memoize from .geometry import point_to_compas diff --git a/src/compas_rhino/drawing.py b/src/compas_rhino/drawing.py index e5245353821a..1158d93796a3 100644 --- a/src/compas_rhino/drawing.py +++ b/src/compas_rhino/drawing.py @@ -781,7 +781,7 @@ def populate_vertexcolors(face): if guid != System.Guid.Empty: if vertexcolors: try: - compas_rhino.objects.set_mesh_vertex_colors(guid, vertexcolors) + rs.MeshVertexColors(guid, vertexcolors) except Exception: pass @@ -859,7 +859,7 @@ def draw_faces(faces, **kwargs): if vertexcolors: try: - compas_rhino.objects.set_mesh_vertex_colors(guid, vertexcolors) + rs.MeshVertexColors(guid, vertexcolors) except Exception: pass diff --git a/src/compas_rhino/objects.py b/src/compas_rhino/objects.py index 533bedadb66d..dae80f58712c 100644 --- a/src/compas_rhino/objects.py +++ b/src/compas_rhino/objects.py @@ -5,7 +5,6 @@ import json import warnings -import Rhino # type: ignore import rhinoscriptsyntax as rs # type: ignore import scriptcontext as sc # type: ignore import System # type: ignore @@ -21,7 +20,148 @@ # ============================================================================== -# Objects +# Deprecated +# ============================================================================== + + +def get_point_coordinates(guids): + """Get the coordintes of the locations of point objects. + + Parameters + ---------- + guids : list[System.Guid] + + Returns + ------- + list[[float, float, float]] + The location coordinates of the points. + + Warnings + -------- + .. deprecated:: 2.3 + Use `compas_rhino.conversions` instead. + + """ + warnings.warn("This function will be removed in v2.3. Please use `compas_rhino.conversions` instead.", DeprecationWarning, stacklevel=2) + + points = [] + for guid in guids: + point = rs.PointCoordinates(guid) + if point: + points.append(point) + return points + + +def get_line_coordinates(guids): + """Get the start and end point coordinates of line curves. + + Parameters + ---------- + guids : list[System.Guid] + Line curve identifiers. + + Returns + ------- + list[tuple[[float, float, float], [float, float, float]]] + A start and end point per line. + + Warnings + -------- + .. deprecated:: 2.3 + Use `compas_rhino.conversions` instead. + + """ + warnings.warn("This function will be removed in v2.3. Please use `compas_rhino.conversions` instead.", DeprecationWarning, stacklevel=2) + + if isinstance(guids, System.Guid): + sp = rs.CurveStartPoint(guids) + ep = rs.CurveEndPoint(guids) + return [sp.X, sp.Y, sp.Z], [ep.X, ep.Y, ep.Z] + lines = [] + for guid in guids: + sp = rs.CurveStartPoint(guid) + ep = rs.CurveEndPoint(guid) + lines.append(([sp.X, sp.Y, sp.Z], [ep.X, ep.Y, ep.Z])) + return lines + + +def get_polyline_coordinates(guids): + """Get the point coordinates of polylines. + + Parameters + ---------- + guids : list[System.Guid] + Polyline curve identifiers. + + Returns + ------- + list[list[[float, float, float]]] + A list of point coordinates per polyline. + + Warnings + -------- + .. deprecated:: 2.3 + Use `compas_rhino.conversions` instead. + + """ + warnings.warn("This function will be removed in v2.3. Please use `compas_rhino.conversions` instead.", DeprecationWarning, stacklevel=2) + + if isinstance(guids, System.Guid): + points = rs.PolylineVertices(guids) + coords = [] + if points: + coords = [map(float, point) for point in points] + return coords + polylines = [] + for guid in guids: + points = rs.PolylineVertices(guid) + coords = [] + if points: + coords = [map(float, point) for point in points] + polylines.append(coords) + return polylines + + +def get_polygon_coordinates(guids): + """Get the point coordinates of polygons. + + Parameters + ---------- + guids : list[System.Guid] + Polygon curve identifiers. + + Returns + ------- + list[list[[float, float, float]]] + A list of point coordinates per polygon. + + Warnings + -------- + .. deprecated:: 2.3 + Use `compas_rhino.conversions` instead. + + """ + warnings.warn("This function will be removed in v2.3. Please use `compas_rhino.conversions` instead.", DeprecationWarning, stacklevel=2) + + if isinstance(guids, System.Guid): + points = rs.CurvePoints(guids) + coords = [] + if points: + coords = [list(point) for point in points] + return coords + polygons = [] + if guids: + for guid in guids: + points = rs.CurvePoints(guid) + coords = [] + if points: + coords = map(list, points) + polygons.append(coords) + return polygons + + +# ============================================================================== +# Get objects by filtering # ============================================================================== @@ -44,147 +184,196 @@ def get_objects(name=None, color=None, layer=None, type=None): list[System.Guid] The System.Guids of the objects matching the filter parameters. - Examples - -------- - .. code-block:: python - - import compas_rhino + """ + guids = rs.AllObjects() + if name: + guids = list(set(guids) & set(rs.ObjectsByName(name))) + if color: + guids = list(set(guids) & set(rs.ObjectsByColor(color))) + if layer: + guids = list(set(guids) & set(rs.ObjectsByLayer(layer))) + if type: + guids = list(set(guids) & set(rs.ObjectsByType(type))) + return guids - guids_all = compas_rhino.get_objects() - guids_compas = compas_rhino.get_objects(name="COMPAS.*") - guids_red = compas_rhino.get_objects(color=(255, 0, 0)) - guids_points = compas_rhino.get_objects(type=compas_rhino.rs.filter.point) - guids_redpoints = compas_rhino.get_objects(color=(255, 0, 0), type=compas_rhino.rs.filter.point) - .. code-block:: python +def get_points(layer=None): + """Get all points. - guids_all = set(compas_rhino.get_objects()) - guids_compas = set(compas_rhino.get_objects(name='COMPAS.*')) - guids_red = set(compas_rhino.get_objects(color=(255, 0, 0))) - guids_points = set(compas_rhino.get_objects(type=compas_rhino.rs.filter.point)) - guids_redpoints = set(compas_rhino.get_objects(color=(255, 0, 0), type=compas_rhino.rs.filter.point)) + Parameters + ---------- + layer : str, optional + Name of a layer containing the points. - print guids_compas.issubset(guids_all) - print guids_all.issubset(guids_compas) + Returns + ------- + list[System.Guid] + The identifiers of the points. - # True, False + """ + if layer: + rs.EnableRedraw(False) + # Argument names for LayerVisible command are not the same for Rhino5 and Rhino6 + # that is why we use positional instead of named arguments + visible = rs.LayerVisible(layer, True, True) + guids = rs.ObjectsByType(rs.filter.point) + guids = list(set(guids) & set(rs.ObjectsByLayer(layer))) + rs.LayerVisible(layer, visible, True) + rs.EnableRedraw(True) + else: + guids = rs.ObjectsByType(rs.filter.point) + return guids - print guids_red.issubset(guids_all) - print guids_points.issubset(guids_all) - print guids_redpoints.issubset(guids_all) - # True, True, True +def get_curves(layer=None): + """Get all curves. - print guids_redpoints.issubset(guids_points) - print guids_redpoints.issubset(guids_red) - print guids_points.issubset(guids_red) + Parameters + ---------- + layer : str, optional + Name of a layer containing the curves. - # True, True, False + Returns + ------- + list[System.Guid] + The identifiers of the curves. """ - guids = rs.AllObjects() - if name: - guids = list(set(guids) & set(rs.ObjectsByName(name))) - if color: - guids = list(set(guids) & set(rs.ObjectsByColor(color))) if layer: + rs.EnableRedraw(False) + # Argument names for LayerVisible command are not the same for Rhino5 and Rhino6 + # that is why we use positional instead of named arguments + visible = rs.LayerVisible(layer, True, True) + guids = rs.ObjectsByType(rs.filter.curve) guids = list(set(guids) & set(rs.ObjectsByLayer(layer))) - if type: - guids = list(set(guids) & set(rs.ObjectsByType(type))) + rs.LayerVisible(layer, visible, True) + rs.EnableRedraw(True) + else: + guids = rs.ObjectsByType(rs.filter.curve) return guids -def delete_object(guid, purge=None, redraw=True): - """Delete Rhino object. +def get_lines(layer=None): + """Get all lines. Parameters ---------- - guid : System.Guid - Object identifier. - purge : None or bool, optional - If None, the value of the global purge setting (:obj:`compas_rhino.PURGE_ON_DELETE`) will be used. - If True, purge the object from history after deleting. - If False, delete but don't purge. - redraw : bool, optional - If True, redrawing will be enabled and enacted. - If False, redrawing will be disabled. + layer : str, optional + Name of a layer containing the lines. Returns ------- - None + list[System.Guid] + The identifiers of the lines. """ - if purge is None: - purge = compas_rhino.PURGE_ON_DELETE - if purge and purge_object: - purge_objects([guid], redraw=redraw) + if layer: + rs.EnableRedraw(False) + # Argument names for LayerVisible command are not the same for Rhino5 and Rhino6 + # that is why we use positional instead of named arguments + visible = rs.LayerVisible(layer, True, True) + guids = rs.ObjectsByType(rs.filter.curve) + guids = [guid for guid in guids if is_curve_line(guid)] + guids = list(set(guids) & set(rs.ObjectsByLayer(layer))) + rs.LayerVisible(layer, visible, True) + rs.EnableRedraw(True) else: - delete_objects([guid], purge, redraw=redraw) + guids = rs.ObjectsByType(rs.filter.curve) + guids = [guid for guid in guids if is_curve_line(guid)] + return guids -def delete_objects(guids, purge=None, redraw=True): - """Delete multiple Rhino objects. +def get_polylines(layer=None): + """Get all polylines. Parameters ---------- - guids : list[System.Guid] - Object identifiers. - purge : None or bool, optional - If None, the value of the global purge setting (:obj:`compas_rhino.PURGE_ON_DELETE`) will be used. - If True, purge the objects from history after deleting. - If False, delete but don't purge. - redraw : bool, optional - If True, redrawing will be enabled and enacted. - If False, redrawing will be disabled. + layer : str, optional + Name of a layer containing the polylines. Returns ------- - None + list[System.Guid] + The identifiers of the polylines. """ - if purge is None: - purge = compas_rhino.PURGE_ON_DELETE - if purge and purge_object: - purge_objects(guids, redraw=redraw) + if layer: + rs.EnableRedraw(False) + # Argument names for LayerVisible command are not the same for Rhino5 and Rhino6 + # that is why we use positional instead of named arguments + visible = rs.LayerVisible(layer, True, True) + guids = rs.ObjectsByType(rs.filter.curve) + guids = [guid for guid in guids if is_curve_polyline(guid)] + guids = list(set(guids) & set(rs.ObjectsByLayer(layer))) + rs.LayerVisible(layer, visible, True) + rs.EnableRedraw(True) else: + guids = rs.ObjectsByType(rs.filter.curve) + guids = [guid for guid in guids if is_curve_polyline(guid)] + return guids + + +def get_polygons(layer=None): + """Get all polygons. + + Parameters + ---------- + layer : str, optional + Name of a layer containing the polygons. + + Returns + ------- + list[System.Guid] + The identifiers of the polygons. + + """ + if layer: rs.EnableRedraw(False) - for guid in guids: - if rs.IsObjectHidden(guid): - rs.ShowObject(guid) - rs.DeleteObjects(guids) - if redraw: - rs.EnableRedraw(True) - sc.doc.Views.Redraw() + # Argument names for LayerVisible command are not the same for Rhino5 and Rhino6 + # that is why we use positional instead of named arguments + visible = rs.LayerVisible(layer, True, True) + guids = rs.ObjectsByType(rs.filter.curve) + guids = [guid for guid in guids if is_curve_polygon(guid)] + guids = list(set(guids) & set(rs.ObjectsByLayer(layer))) + rs.LayerVisible(layer, visible, True) + rs.EnableRedraw(True) + else: + guids = rs.ObjectsByType(rs.filter.curve) + guids = [guid for guid in guids if is_curve_polygon(guid)] + return guids -def purge_objects(guids, redraw=True): - """Purge objects from memory. +def get_meshes(layer=None): + """Get (all) meshes. Parameters ---------- - guids : list[System.Guid] - Object identifiers. - redraw : bool, optional - If True, redrawing will be enabled and enacted. - If False, redrawing will be disabled. + layer : str, optional + Name of a layer containing the meshes. Returns ------- - None + list[System.Guid] + The identifiers of the meshes. """ - if not purge_object: - raise RuntimeError("Cannot purge outside Rhino script context") - rs.EnableRedraw(False) - for guid in guids: - if rs.IsObject(guid): - if rs.IsObjectHidden(guid): - rs.ShowObject(guid) - o = find_object(guid) - purge_object(o.RuntimeSerialNumber) - if redraw: + if layer: + rs.EnableRedraw(False) + # Argument names for LayerVisible command are not the same for Rhino5 and Rhino6 + # that is why we use positional instead of named arguments + visible = rs.LayerVisible(layer, True, True) + guids = rs.ObjectsByType(rs.filter.mesh) + guids = list(set(guids) & set(rs.ObjectsByLayer(layer))) + rs.LayerVisible(layer, visible, True) rs.EnableRedraw(True) - sc.doc.Views.Redraw() + else: + guids = rs.ObjectsByType(rs.filter.mesh) + return guids + + +# ============================================================================== +# Object info +# ============================================================================== def get_object_layers(guids): @@ -334,172 +523,229 @@ def get_object_attributes_from_name(guids, prefix=None): return attrs -def select_object(message="Select an object."): - """Select one object in the Rhino view. +def is_curve_line(guid): + """Verify that a curve is really a line. Parameters ---------- - message : str, optional - Instruction for the user. + guid : System.Guid + The identifier of the curve. Returns ------- - System.Guid - The identifer of the selected object. + bool + True if the curve is a line. + False otherwise. """ - return rs.GetObject(message) + return rs.IsCurve(guid) and rs.IsLine(guid) and rs.CurveDegree(guid) == 1 and len(rs.CurvePoints(guid)) == 2 -def select_objects(message="Select multiple objects."): - """Select multiple objects in the Rhino view. +def is_curve_polyline(guid): + """Verify that a curve is really a polyline. Parameters ---------- - message : str, optional - Instruction for the user. + guid : System.Guid + The identifier of the curve. Returns ------- - list[System.Guid] - The identifers of the selected objects. + bool + True if the curve is a polyline. + False otherwise. """ - guids = [] - temp = rs.GetObjects(message) - if temp: - return temp - return guids + return rs.IsCurve(guid) and rs.IsPolyline(guid) and rs.CurveDegree(guid) == 1 and len(rs.CurvePoints(guid)) > 2 + + +def is_curve_polygon(guid): + """Verify that a curve is really a polygon. + + Parameters + ---------- + guid : System.Guid + The identifier of the curve. + + Returns + ------- + bool + True if the curve is a polygon. + False otherwise. + + """ + return rs.IsCurve(guid) and rs.IsCurveClosed(guid) and rs.CurveDegree(guid) == 1 and len(rs.CurvePoints(guid)) > 2 # ============================================================================== -# Points +# Delete objects # ============================================================================== -def select_point(message="Select one point."): - """Select one point in the Rhino view. +def delete_object(guid, purge=None, redraw=True): + """Delete Rhino object. Parameters ---------- - message : str, optional - Instruction for the user. + guid : System.Guid + Object identifier. + purge : None or bool, optional + If None, the value of the global purge setting (:obj:`compas_rhino.PURGE_ON_DELETE`) will be used. + If True, purge the object from history after deleting. + If False, delete but don't purge. + redraw : bool, optional + If True, redrawing will be enabled and enacted. + If False, redrawing will be disabled. Returns ------- - System.Guid - The identifer of the selected point. + None """ - return rs.GetObject(message, preselect=True, select=True, filter=rs.filter.point) + if purge is None: + purge = compas_rhino.PURGE_ON_DELETE + if purge and purge_object: + purge_objects([guid], redraw=redraw) + else: + delete_objects([guid], purge, redraw=redraw) -def select_points(message="Select multiple points."): - """Select multiple points in the Rhino view. +def delete_objects(guids, purge=None, redraw=True): + """Delete multiple Rhino objects. Parameters ---------- - message : str, optional - Instruction for the user. + guids : list[System.Guid] + Object identifiers. + purge : None or bool, optional + If None, the value of the global purge setting (:obj:`compas_rhino.PURGE_ON_DELETE`) will be used. + If True, purge the objects from history after deleting. + If False, delete but don't purge. + redraw : bool, optional + If True, redrawing will be enabled and enacted. + If False, redrawing will be disabled. Returns ------- - list[System.Guid] - The identifers of the selected points. + None """ - guids = [] - temp = rs.GetObjects(message, preselect=True, select=True, group=False, filter=rs.filter.point) - if temp: - guids = temp - return guids + if purge is None: + purge = compas_rhino.PURGE_ON_DELETE + if purge and purge_object: + purge_objects(guids, redraw=redraw) + else: + rs.EnableRedraw(False) + for guid in guids: + if rs.IsObjectHidden(guid): + rs.ShowObject(guid) + rs.DeleteObjects(guids) + if redraw: + rs.EnableRedraw(True) + sc.doc.Views.Redraw() -def get_points(layer=None): - """Get all points. +def purge_objects(guids, redraw=True): + """Purge objects from memory. Parameters ---------- - layer : str, optional - Name of a layer containing the points. + guids : list[System.Guid] + Object identifiers. + redraw : bool, optional + If True, redrawing will be enabled and enacted. + If False, redrawing will be disabled. Returns ------- - list[System.Guid] - The identifiers of the points. + None """ - if layer: - rs.EnableRedraw(False) - # Argument names for LayerVisible command are not the same for Rhino5 and Rhino6 - # that is why we use positional instead of named arguments - visible = rs.LayerVisible(layer, True, True) - guids = rs.ObjectsByType(rs.filter.point) - guids = list(set(guids) & set(rs.ObjectsByLayer(layer))) - rs.LayerVisible(layer, visible, True) + if not purge_object: + raise RuntimeError("Cannot purge outside Rhino script context") + rs.EnableRedraw(False) + for guid in guids: + if rs.IsObject(guid): + if rs.IsObjectHidden(guid): + rs.ShowObject(guid) + o = find_object(guid) + purge_object(o.RuntimeSerialNumber) + if redraw: rs.EnableRedraw(True) - else: - guids = rs.ObjectsByType(rs.filter.point) - return guids + sc.doc.Views.Redraw() -def get_point_coordinates(guids): - """Get the coordintes of the locations of point objects. +# ============================================================================== +# Select objects +# ============================================================================== + + +def select_object(message="Select an object."): + """Select one object in the Rhino view. Parameters ---------- - guids : list[System.Guid] + message : str, optional + Instruction for the user. Returns ------- - list[[float, float, float]] - The location coordinates of the points. - - Warnings - -------- - .. deprecated:: 2.3 - Use `compas_rhino.conversions` instead. + System.Guid + The identifer of the selected object. """ - warnings.warn("This function will be removed in v2.3. Please use `compas_rhino.conversions` instead.", DeprecationWarning, stacklevel=2) + return rs.GetObject(message) - points = [] - for guid in guids: - point = rs.PointCoordinates(guid) - if point: - points.append(point) - return points +def select_objects(message="Select multiple objects."): + """Select multiple objects in the Rhino view. -# ============================================================================== -# Curves -# ============================================================================== + Parameters + ---------- + message : str, optional + Instruction for the user. + + Returns + ------- + list[System.Guid] + The identifers of the selected objects. + """ + return rs.GetObjects(message) -def is_curve_line(guid): - """Verify that a curve is a line. + +def select_point(message="Select one point."): + """Select one point in the Rhino view. Parameters ---------- - guid : System.Guid - The identifier of the curve. + message : str, optional + Instruction for the user. Returns ------- - bool - True if the curve is a line. - False otherwise. + System.Guid + The identifer of the selected point. """ - return rs.IsCurve(guid) and rs.IsLine(guid) and rs.CurveDegree(guid) == 1 and len(rs.CurvePoints(guid)) == 2 + return rs.GetObject(message, preselect=True, select=True, filter=rs.filter.point) -def is_curve_polyline(guid): - return rs.IsCurve(guid) and rs.IsPolyline(guid) and rs.CurveDegree(guid) == 1 and len(rs.CurvePoints(guid)) > 2 +def select_points(message="Select multiple points."): + """Select multiple points in the Rhino view. + Parameters + ---------- + message : str, optional + Instruction for the user. -def is_curve_polygon(guid): - return rs.IsCurve(guid) and rs.IsCurveClosed(guid) and rs.CurveDegree(guid) == 1 and len(rs.CurvePoints(guid)) > 2 + Returns + ------- + list[System.Guid] + The identifers of the selected points. + + """ + return rs.GetObjects(message, preselect=True, select=True, group=False, filter=rs.filter.point) def select_curve(message="Select one curve."): @@ -533,11 +779,7 @@ def select_curves(message="Select multiple curves."): The identifers of the selected curves. """ - guids = [] - temp = rs.GetObjects(message, preselect=True, select=True, group=False, filter=rs.filter.curve) - if temp: - guids = temp - return guids + return rs.GetObjects(message, preselect=True, select=True, group=False, filter=rs.filter.curve) def select_line(message="Select line."): @@ -574,13 +816,8 @@ def select_lines(message="Select multiple lines."): The identifers of the selected lines. """ - guids = [] temp = rs.GetObjects(message, preselect=True, select=True, group=False, filter=rs.filter.curve) - if temp: - for guid in temp: - if is_curve_line(guid): - guids.append(guid) - return guids + return [guid for guid in temp if is_curve_line(guid)] def select_polyline( @@ -621,13 +858,8 @@ def select_polylines( The identifers of the selected polylines. """ - guids = [] temp = rs.GetObjects(message, preselect=True, select=True, group=False, filter=rs.filter.curve) - if temp: - for guid in temp: - if is_curve_polyline(guid): - guids.append(guid) - return guids + return [guid for guid in temp if is_curve_polyline(guid)] def select_polygon(message="Select one polygon (closed curve with degree = 1)"): @@ -664,244 +896,8 @@ def select_polygons(message="Select multiple polygons (closed curves with degree The identifers of the selected polygons. """ - guids = [] temp = rs.GetObjects(message, preselect=True, select=True, group=False, filter=rs.filter.curve) - if temp: - for guid in temp: - if is_curve_polygon(guid): - guids.append(guid) - return guids - - -def get_curves(layer=None): - """Get all curves. - - Parameters - ---------- - layer : str, optional - Name of a layer containing the curves. - - Returns - ------- - list[System.Guid] - The identifiers of the curves. - - """ - if layer: - rs.EnableRedraw(False) - # Argument names for LayerVisible command are not the same for Rhino5 and Rhino6 - # that is why we use positional instead of named arguments - visible = rs.LayerVisible(layer, True, True) - guids = rs.ObjectsByType(rs.filter.curve) - guids = list(set(guids) & set(rs.ObjectsByLayer(layer))) - rs.LayerVisible(layer, visible, True) - rs.EnableRedraw(True) - else: - guids = rs.ObjectsByType(rs.filter.curve) - return guids - - -def get_lines(layer=None): - """Get all lines. - - Parameters - ---------- - layer : str, optional - Name of a layer containing the lines. - - Returns - ------- - list[System.Guid] - The identifiers of the lines. - - """ - if layer: - rs.EnableRedraw(False) - # Argument names for LayerVisible command are not the same for Rhino5 and Rhino6 - # that is why we use positional instead of named arguments - visible = rs.LayerVisible(layer, True, True) - guids = rs.ObjectsByType(rs.filter.curve) - guids = [guid for guid in guids if is_curve_line(guid)] - guids = list(set(guids) & set(rs.ObjectsByLayer(layer))) - rs.LayerVisible(layer, visible, True) - rs.EnableRedraw(True) - else: - guids = rs.ObjectsByType(rs.filter.curve) - guids = [guid for guid in guids if is_curve_line(guid)] - return guids - - -def get_polylines(layer=None): - """Get all polylines. - - Parameters - ---------- - layer : str, optional - Name of a layer containing the polylines. - - Returns - ------- - list[System.Guid] - The identifiers of the polylines. - - """ - if layer: - rs.EnableRedraw(False) - # Argument names for LayerVisible command are not the same for Rhino5 and Rhino6 - # that is why we use positional instead of named arguments - visible = rs.LayerVisible(layer, True, True) - guids = rs.ObjectsByType(rs.filter.curve) - guids = [guid for guid in guids if is_curve_polyline(guid)] - guids = list(set(guids) & set(rs.ObjectsByLayer(layer))) - rs.LayerVisible(layer, visible, True) - rs.EnableRedraw(True) - else: - guids = rs.ObjectsByType(rs.filter.curve) - guids = [guid for guid in guids if is_curve_polyline(guid)] - return guids - - -def get_polygons(layer=None): - """Get all polygons. - - Parameters - ---------- - layer : str, optional - Name of a layer containing the polygons. - - Returns - ------- - list[System.Guid] - The identifiers of the polygons. - - """ - if layer: - rs.EnableRedraw(False) - # Argument names for LayerVisible command are not the same for Rhino5 and Rhino6 - # that is why we use positional instead of named arguments - visible = rs.LayerVisible(layer, True, True) - guids = rs.ObjectsByType(rs.filter.curve) - guids = [guid for guid in guids if is_curve_polygon(guid)] - guids = list(set(guids) & set(rs.ObjectsByLayer(layer))) - rs.LayerVisible(layer, visible, True) - rs.EnableRedraw(True) - else: - guids = rs.ObjectsByType(rs.filter.curve) - guids = [guid for guid in guids if is_curve_polygon(guid)] - return guids - - -def get_line_coordinates(guids): - """Get the start and end point coordinates of line curves. - - Parameters - ---------- - guids : list[System.Guid] - Line curve identifiers. - - Returns - ------- - list[tuple[[float, float, float], [float, float, float]]] - A start and end point per line. - - Warnings - -------- - .. deprecated:: 2.3 - Use `compas_rhino.conversions` instead. - - """ - warnings.warn("This function will be removed in v2.3. Please use `compas_rhino.conversions` instead.", DeprecationWarning, stacklevel=2) - - if isinstance(guids, System.Guid): - sp = rs.CurveStartPoint(guids) - ep = rs.CurveEndPoint(guids) - return [sp.X, sp.Y, sp.Z], [ep.X, ep.Y, ep.Z] - lines = [] - for guid in guids: - sp = rs.CurveStartPoint(guid) - ep = rs.CurveEndPoint(guid) - lines.append(([sp.X, sp.Y, sp.Z], [ep.X, ep.Y, ep.Z])) - return lines - - -def get_polyline_coordinates(guids): - """Get the point coordinates of polylines. - - Parameters - ---------- - guids : list[System.Guid] - Polyline curve identifiers. - - Returns - ------- - list[list[[float, float, float]]] - A list of point coordinates per polyline. - - Warnings - -------- - .. deprecated:: 2.3 - Use `compas_rhino.conversions` instead. - - """ - warnings.warn("This function will be removed in v2.3. Please use `compas_rhino.conversions` instead.", DeprecationWarning, stacklevel=2) - - if isinstance(guids, System.Guid): - points = rs.PolylineVertices(guids) - coords = [] - if points: - coords = [map(float, point) for point in points] - return coords - polylines = [] - for guid in guids: - points = rs.PolylineVertices(guid) - coords = [] - if points: - coords = [map(float, point) for point in points] - polylines.append(coords) - return polylines - - -def get_polygon_coordinates(guids): - """Get the point coordinates of polygons. - - Parameters - ---------- - guids : list[System.Guid] - Polygon curve identifiers. - - Returns - ------- - list[list[[float, float, float]]] - A list of point coordinates per polygon. - - Warnings - -------- - .. deprecated:: 2.3 - Use `compas_rhino.conversions` instead. - - """ - warnings.warn("This function will be removed in v2.3. Please use `compas_rhino.conversions` instead.", DeprecationWarning, stacklevel=2) - - if isinstance(guids, System.Guid): - points = rs.CurvePoints(guids) - coords = [] - if points: - coords = [list(point) for point in points] - return coords - polygons = [] - if guids: - for guid in guids: - points = rs.CurvePoints(guid) - coords = [] - if points: - coords = map(list, points) - polygons.append(coords) - return polygons - - -# ============================================================================== -# Surfaces -# ============================================================================== + return [guid for guid in temp if is_curve_polygon(guid)] def select_surface(message="Select one surface."): @@ -940,22 +936,13 @@ def select_surfaces(message="Select multiple surfaces."): The identifers of the selected surfaces. """ - guids = [] - temp = rs.GetObjects( + return rs.GetObjects( message, preselect=True, select=True, group=False, filter=rs.filter.surface | rs.filter.polysurface, ) - if temp: - guids = temp - return guids - - -# ============================================================================== -# Meshes -# ============================================================================== def select_mesh(message="Select one mesh."): @@ -994,177 +981,3 @@ def select_meshes(message="Select multiple meshes."): if temp: guids = temp return guids - - -# def get_meshes(layer=None): -# if layer: -# rs.EnableRedraw(False) -# # Argument names for LayerVisible command are not the same for Rhino5 and Rhino6 -# # that is why we use positional instead of named arguments -# visible = rs.LayerVisible(layer, True, True) -# guids = rs.ObjectsByType(rs.filter.mesh) -# guids = list(set(guids) & set(rs.ObjectsByLayer(layer))) -# rs.LayerVisible(layer, visible, True) -# rs.EnableRedraw(True) -# else: -# guids = rs.ObjectsByType(rs.filter.mesh) -# return guids - - -# def get_mesh_border(guid): -# return rs.DuplicateMeshBorder(guid) - - -# def get_mesh_face_vertices(guid): -# faces = [] -# if guid: -# temp = rs.MeshFaceVertices(guid) -# faces = map(list, temp) -# return faces - - -# def get_mesh_vertex_coordinates(guid): -# vertices = [] -# if guid: -# vertices = [map(float, vertex) for vertex in rs.MeshVertices(guid)] -# return vertices - - -# def get_mesh_vertex_colors(guid): -# colors = [] -# if guid: -# temp = rs.MeshVertexColors(guid) -# if temp: -# colors = map(list, temp) -# return colors - - -# def set_mesh_vertex_colors(guid, colors): -# if not guid: -# return -# return rs.MeshVertexColors(guid, colors) - - -# def get_mesh_vertices_and_faces(guid): -# if not guid: -# return -# vertices = [map(float, vertex) for vertex in rs.MeshVertices(guid)] -# faces = map(list, rs.MeshFaceVertices(guid)) -# return vertices, faces - - -# def get_mesh_vertex_index(guid): -# class CustomGetObject(Rhino.Input.Custom.GetObject): -# def CustomGeometryFilter(self, rhino_object, geometry, component_index): -# return guid == rhino_object.Id - -# go = CustomGetObject() -# go.SetCommandPrompt("Select one vertex of the mesh.") -# go.GeometryFilter = Rhino.DocObjects.ObjectType.MeshVertex -# go.AcceptNothing(True) -# if go.Get() != Rhino.Input.GetResult.Object: -# return None -# objref = go.Object(0) -# if not objref: -# return None -# tvindex = objref.GeometryComponentIndex.Index -# mobj = sc.doc.Objects.Find(guid) -# mgeo = mobj.Geometry -# temp = mgeo.TopologyVertices.MeshVertexIndices(tvindex) -# vindex = temp[0] -# go.Dispose() -# return vindex - - -# def get_mesh_face_index(guid): -# class CustomGetObject(Rhino.Input.Custom.GetObject): -# def CustomGeometryFilter(self, rhino_object, geometry, component_index): -# return guid == rhino_object.Id - -# go = CustomGetObject() -# go.SetCommandPrompt("Select one face of the mesh.") -# go.GeometryFilter = Rhino.DocObjects.ObjectType.MeshFace -# go.AcceptNothing(True) -# if go.Get() != Rhino.Input.GetResult.Object: -# return None -# objref = go.Object(0) -# if not objref: -# return None -# findex = objref.GeometryComponentIndex.Index -# go.Dispose() -# return findex - - -# def get_mesh_edge_index(guid): -# class CustomGetObject(Rhino.Input.Custom.GetObject): -# def CustomGeometryFilter(self, rhino_object, geometry, component_index): -# return guid == rhino_object.Id - -# go = CustomGetObject() -# go.SetCommandPrompt("Select an edge of the mesh.") -# go.GeometryFilter = Rhino.DocObjects.ObjectType.MeshEdge -# go.AcceptNothing(True) -# if go.Get() != Rhino.Input.GetResult.Object: -# return None -# objref = go.Object(0) -# if not objref: -# return None -# eindex = objref.GeometryComponentIndex.Index -# go.Dispose() -# return eindex - - -# def get_mesh_vertex_indices(guid): -# tvindices = rs.GetMeshVertices(guid, "Select mesh vertices.") -# if not tvindices: -# return -# mobj = sc.doc.Objects.Find(guid) -# mgeo = mobj.Geometry -# vindices = [] -# for tvindex in tvindices: -# temp = mgeo.TopologyVertices.MeshVertexIndices(tvindex) -# vindices.append(temp[0]) -# return vindices - - -# def get_mesh_face_indices(guid): -# return rs.GetMeshFaces(guid, "Select mesh faces.") - - -# def get_mesh_vertex_face_indices(guid): -# vindex = get_mesh_vertex_index(guid) -# if vindex is None: -# return -# mobj = sc.doc.Objects.Find(guid) -# mgeo = mobj.Geometry -# findices = mgeo.TopologyVertices.ConnectedFaces(vindex) -# return findices - - -# def get_mesh_face_vertex_indices(guid): -# findex = get_mesh_face_index(guid) -# if findex is None: -# return -# mobj = sc.doc.Objects.Find(guid) -# mgeo = mobj.Geometry -# tvertices = mgeo.Faces.GetTopologicalVertices(findex) -# vindices = [] -# for tvertex in tvertices: -# temp = mgeo.TopologyVertices.MeshVertexIndices(tvertex) -# vindices.append(temp[0]) -# return vindices - - -# def get_mesh_edge_vertex_indices(guid): -# eindex = get_mesh_edge_index(guid) -# if eindex is None: -# return -# mobj = sc.doc.Objects.Find(guid) -# mgeo = mobj.Geometry -# temp = mgeo.TopologyEdges.GetTopologyVertices(eindex) -# tvindices = temp.I, temp.J -# vindices = [] -# for tvindex in tvindices: -# temp = mgeo.TopologyVertices.MeshVertexIndices(tvindex) -# vindices.append(temp[0]) -# return vindices From 994703753aae791af7950cefad645679807021ce Mon Sep 17 00:00:00 2001 From: tomvanmele Date: Sat, 6 Jul 2024 12:28:01 +0200 Subject: [PATCH 5/5] smal l fixes and docs --- CHANGELOG.md | 1 - docs/userguide/cad.rhino.rst | 173 +++++++++++++++++++++ src/compas_rhino/conversions/__init__.py | 4 +- src/compas_rhino/conversions/breps.py | 76 ++++++++- src/compas_rhino/conversions/docobjects.py | 56 +++---- src/compas_rhino/conversions/geometry.py | 11 +- 6 files changed, 272 insertions(+), 49 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff4c7f0b72a6..ad6359f06ff4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,7 +37,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Added `compas_rhino.conversions.docobjects.curveobject_to_compas`. * Added `compas_rhino.conversions.docobjects.meshobject_to_compas`. * Added `compas_rhino.conversions.docobjects.pointobject_to_compas`. -* Added `compas_rhino.conversions.docobjects.surfaceobject_to_compas`. * Added `compas.datastructures.HashTree` and `compas.datastructures.HashNode`. ### Changed diff --git a/docs/userguide/cad.rhino.rst b/docs/userguide/cad.rhino.rst index 55fe9d4316b6..495e4f95575c 100644 --- a/docs/userguide/cad.rhino.rst +++ b/docs/userguide/cad.rhino.rst @@ -88,10 +88,183 @@ For more information on visualisation scenes, see :doc:`/userguide/basics.visual Conversions =========== +For conversion between Rhino objects and COMPAS objects, different scenarios exist. + +Rhino Geometry to COMPAS +------------------------ + +Conversions of geometry is straightforward and explicit. + +.. code-block:: python + + import Rhino.Geometry + import compas_rhino.conversions + + point = Rhino.Geometry.Point3d(...) + point = compas_rhino.conversions.point_to_compas(point) + + line = Rhino.Geometry.Line(...) + line = compas_rhino.conversions.line_to_compas(line) + + plane = Rhino.Geometry.Plane(...) + plane = compas_rhino.conversions.plane_to_compas(plane) + + box = Rhino.Geometry.Box(...) + box = compas_rhino.conversions.box_to_compas(box) + + mesh = Rhino.Geometry.Mesh(...) + mesh = compas_rhino.conversions.mesh_to_compas(mesh) + + curve = Rhino.Geometry.Curve(...) + curve = compas_rhino.conversions.curve_to_compas(curve) + + surface = Rhino.Geometry.Surface(...) + surface = compas_rhino.conversions.surface_to_compas(surface) + + brep = Rhino.Geometry.Brep(...) + brep = compas_rhino.conversions.brep_to_compas(brep) + + +Note that Rhino doen't distinguish between a frame and a plane. +Therefore, to convert `Rhino.Geometry.Plane` to :class:`compas.geometry.Frame`. + +.. code-block:: python + + plane = Rhino.Geometry.Plane(...) + frame = compas_rhino.conversions.plane_to_compas_frame(plane) + + +Rhino Object to COMPAS +---------------------- + +A Rhino Document contains Rhino Object instead of Rhino Geometry. +The geometry of a Rhino Object is stored in the corresponding attribute (`obj.Geometry`). + +Converting point, curve, and mesh objects is straightforward. + +.. code-block:: python + + import compas_rhino.objects + import compas_rhino.conversions + + guid = compas_rhino.objects.select_point() + point = compas_rhino.conversions.pointobject_to_compas(guid) + + guid = compas_rhino.objects.select_curve() + curve = compas_rhino.conversions.curveobject_to_compas(guid) + + guid = compas_rhino.objects.select_mesh() + mesh = compas_rhino.conversions.meshobject_to_compas(guid) + + +In the case of curve objects, note that the conversion function will return a NurbsCurve in almost all cases. +If the curve has a specific geometry, it can be converted explicitly using the corresponding geomtry conversion function. +For example, if the curve is a circle. + +.. code-block:: python + + import compas_rhino.objects + import compas_rhino.conversions + + guid = compas_rhino.objects.select_curve() + obj = compas_rhino.objects.find_object(guid) + + circle = compas_rhino.conversions.curve_to_compas_circle(obj.Geometry) + + +In the case of all other objects, conversions are a bit trickier. +This is because in a Rhino Document, almost all other geometries are represented by a BrepObject regardless of the actual geometry type. +For example, when you add a sphere to a model, the DocObject is a BrepObject, and the geometry of the object is a Brep. +Therefore, conversions of other objects have to be done more carefully. + +.. code-block:: python + + import compas_rhino.objects + import compas_rhino.conversions + + guid = compas_rhino.objects.select_object() + brep = compas_rhino.conversions.brepobject_to_compas(guid) + + +Also here, if the object is (supposed to be) a specific type of geometry, +conversion can be done more explicitly using the geometry conversion functions instead. +For example, if the geometry of the object is a Rhino Cylinder. + +.. code-block:: python + + import compas_rhino.objects + import compas_rhino.conversions + + guid = compas_rhino.objects.select_object() + obj = compas_rhino.objects.find_object(guid) + + cylinder = compas_rhino.conversions.brep_to_compas_cylinder(obj.Geometry) + + +COMPAS to Rhino Geometry +------------------------ + +.. code-block:: python + + import compas.geometry + import compas_rhino.conversions + + point = compas.geometry.Point(...) + point = compas_rhino.conversions.point_to_rhino(point) + + line = compas.geometry.Line(...) + line = compas_rhino.conversions.line_to_rhino(line) + + plane = compas.geometry.Plane(...) + plane = compas_rhino.conversions.plane_to_rhino(plane) + + box = compas.geometry.Box(...) + box = compas_rhino.conversions.box_to_rhino(box) + + curve = compas.geometry.Curve(...) + curve = compas_rhino.conversions.curve_to_rhino(curve) + + surface = compas.geometry.Surface(...) + surface = compas_rhino.conversions.surface_to_rhino(surface) + + brep = compas.geometry.Brep(...) + brep = compas_rhino.conversions.brep_to_rhino(brep) + + +To convert a :class:`compas.geometry.Frame`. + +.. code-block:: python + + frame = compas.geometry.Frame(...) + plane = compas_rhino.conversions.frame_to_rhino_plane(frame) + + +COMPAS to Rhino Object +---------------------- + +COMPAS objects are converted to Rhino Objects implicitly, by placing them into a visualisation scene. +However, you can create a Rhino Object in a Rhino Dcocument explicitly from a COMPAS object. + +.. code-block:: python + + import scriptcontext as sc + import compas.geometry + import compas_rhino_conversions + + point = compas.geometry.Point(...) + geometry = compas_rhino.conversions.point_to_rhino(point) + + guid = sc.doc.Objects.AddPoint(geometry) + Data Exchange ============= +JSON +---- + +rhino3dm +-------- Remote Procedure Calls ====================== diff --git a/src/compas_rhino/conversions/__init__.py b/src/compas_rhino/conversions/__init__.py index d621a7611459..a80dbb921d08 100644 --- a/src/compas_rhino/conversions/__init__.py +++ b/src/compas_rhino/conversions/__init__.py @@ -70,6 +70,7 @@ ) from .breps import ( brep_to_rhino, + brep_to_compas, brep_to_compas_box, brep_to_compas_cone, brep_to_compas_cylinder, @@ -92,7 +93,6 @@ curveobject_to_compas, meshobject_to_compas, pointobject_to_compas, - surfaceobject_to_compas, ) @@ -157,6 +157,7 @@ "mesh_to_compas", # breps "brep_to_rhino", + "brep_to_compas", "brep_to_compas_box", "brep_to_compas_cone", "brep_to_compas_cylinder", @@ -174,5 +175,4 @@ "curveobject_to_compas", "meshobject_to_compas", "pointobject_to_compas", - "surfaceobject_to_compas", ] diff --git a/src/compas_rhino/conversions/breps.py b/src/compas_rhino/conversions/breps.py index 415e2325b7fc..51ee2714e4f4 100644 --- a/src/compas_rhino/conversions/breps.py +++ b/src/compas_rhino/conversions/breps.py @@ -2,8 +2,11 @@ from __future__ import division from __future__ import print_function +import Rhino.Geometry # type: ignore # noqa: F401 import scriptcontext as sc # type: ignore +import compas +import compas.geometry # noqa: F401 from compas.datastructures import Mesh from compas.geometry import Brep from compas.tolerance import TOL @@ -13,6 +16,11 @@ from .shapes import cone_to_compas from .shapes import cylinder_to_compas from .shapes import sphere_to_compas +from .surfaces import surface_to_compas + +if not compas.IPY: + from typing import Callable # noqa: F401 + from typing import Type # noqa: F401 # ============================================================================= # To Rhino @@ -20,6 +28,7 @@ def brep_to_rhino(brep): + # type: (Brep) -> Rhino.Geometry.Brep """Convert a COMPAS Brep to a Rhino Brep. Parameters @@ -40,6 +49,7 @@ def brep_to_rhino(brep): def brep_to_compas(brep): + # type: (Rhino.Geometry.Brep) -> Brep """Convert a Rhino Brep to a COMPAS Brep. Parameters @@ -60,6 +70,7 @@ def brep_to_compas(brep): def brep_to_compas_box(brep): + # type: (Rhino.Geometry.Brep) -> compas.geometry.Box """Convert a Rhino brep to a COMPAS box. Parameters @@ -75,6 +86,7 @@ def brep_to_compas_box(brep): def brep_to_compas_cone(brep): + # type: (Rhino.Geometry.Brep) -> compas.geometry.Cone """Convert a Rhino brep to a COMPAS cone. Parameters @@ -85,9 +97,13 @@ def brep_to_compas_cone(brep): ------- :class:`compas.geometry.Cone` + Raises + ------ + ConversionError + """ if brep.Faces.Count > 2: - raise ConversionError("Object brep cannot be converted to a cone.") + raise ConversionError("Brep cannot be converted to a cone.") for face in brep.Faces: if face.IsCone(): @@ -95,8 +111,11 @@ def brep_to_compas_cone(brep): if result: return cone_to_compas(cone) + raise ConversionError("Brep cannot be converted to a cone.") + def brep_to_compas_cylinder(brep, tol=None): + # type: (Rhino.Geometry.Brep, float | None) -> compas.geometry.Cylinder """Convert a Rhino brep to a COMPAS cylinder. Parameters @@ -107,11 +126,15 @@ def brep_to_compas_cylinder(brep, tol=None): ------- :class:`compas.geometry.Cylinder` + Raises + ------ + ConversionError + """ tol = tol or sc.doc.ModelAbsoluteTolerance if brep.Faces.Count > 3: - raise ConversionError("Object brep cannot be converted to a cylinder.") + raise ConversionError("Brep cannot be converted to a cylinder.") for face in brep.Faces: # being too strict about what is considered a cylinder @@ -122,8 +145,11 @@ def brep_to_compas_cylinder(brep, tol=None): if result: return cylinder_to_compas(cylinder) + raise ConversionError("Brep cannot be converted to a cylinder.") + def brep_to_compas_sphere(brep): + # type: (Rhino.Geometry.Brep) -> compas.geometry.Sphere """Convert a Rhino brep to a COMPAS sphere. Parameters @@ -134,6 +160,10 @@ def brep_to_compas_sphere(brep): ------- :class:`compas.geometry.Sphere` + Raises + ------ + ConversionError + """ if brep.Faces.Count != 1: raise ConversionError("Brep cannot be converted to a sphere.") @@ -146,6 +176,47 @@ def brep_to_compas_sphere(brep): if result: return sphere_to_compas(sphere) + raise ConversionError("Brep cannot be converted to a sphere.") + + +# ============================================================================= +# To COMPAS Surface +# ============================================================================= + + +def brep_to_compas_surface(brep, tol=None): + # type: (Rhino.Geometry.Brep, float | None) -> compas.geometry.NurbsSurface + """Convert a Rhino brep to a COMPAS surface. + + Parameters + ---------- + brep : :rhino:`Rhino.Geometry.Brep` + + Returns + ------- + :class:`compas.geometry.NurbsSurface` + + Raises + ------ + ConversionError + + """ + tol = tol or sc.doc.ModelAbsoluteTolerance + + if brep.Faces.Count != 1: + raise ConversionError("Brep cannot be converted to a surface.") + + face = brep.Faces.Item[0] + + if not face.HasNurbsForm(): + raise ConversionError("Brep cannot be converted to a surface.") + + result, surface = face.ToNurbsSurface(tol) + if result: + return surface_to_compas(surface) + + raise ConversionError("Brep cannot be converted to a surface.") + # ============================================================================= # To COMPAS Mesh @@ -153,6 +224,7 @@ def brep_to_compas_sphere(brep): def brep_to_compas_mesh(brep, facefilter=None, cleanup=False, cls=None): + # type: (Rhino.Geometry.Brep, Callable | None, bool, Type[Mesh] | None) -> Mesh """Convert the face loops of a Rhino brep to a COMPAS mesh. Parameters diff --git a/src/compas_rhino/conversions/docobjects.py b/src/compas_rhino/conversions/docobjects.py index a4a978052618..a6d827a6ffcb 100644 --- a/src/compas_rhino/conversions/docobjects.py +++ b/src/compas_rhino/conversions/docobjects.py @@ -3,6 +3,9 @@ from __future__ import print_function import Rhino.Geometry # type: ignore # noqa: F401 +import System # type: ignore + +import compas_rhino.objects from .exceptions import ConversionError @@ -10,7 +13,6 @@ from .curves import curve_to_compas from .geometry import point_to_compas from .meshes import mesh_to_compas -from .surfaces import surface_to_compas def brepobject_to_compas(obj): @@ -18,7 +20,7 @@ def brepobject_to_compas(obj): Parameters ---------- - obj : Rhino.DocObjects.BrepObject + obj : Rhino.DocObjects.BrepObject | System.Guid Returns ------- @@ -29,8 +31,11 @@ def brepobject_to_compas(obj): ConversionError """ + if isinstance(obj, System.Guid): + obj = compas_rhino.objects.find_object(obj) + try: - geometry = obj.BrepGeometry + geometry = Rhino.Geometry.Brep.TryConvertBrep(obj.Geometry) brep = brep_to_compas(geometry) except Exception: raise ConversionError("Rhino Object of type {} cannot be converted to a COMPAS Brep.".format(type(obj))) @@ -43,7 +48,7 @@ def curveobject_to_compas(obj, try_nurbs=True): Parameters ---------- - obj : Rhino.DocObjects.CurveObject + obj : Rhino.DocObjects.CurveObject | System.Guid The Rhino Object. try_nurbs : bool, optional Try to convert the curve to a NURBS curve. @@ -59,6 +64,9 @@ def curveobject_to_compas(obj, try_nurbs=True): ConversionError """ + if isinstance(obj, System.Guid): + obj = compas_rhino.objects.find_object(obj) + try: geometry = obj.CurveGeometry curve = curve_to_compas(geometry, try_nurbs=try_nurbs) @@ -73,7 +81,7 @@ def meshobject_to_compas(obj): Parameters ---------- - obj : Rhino.DocObjects.MeshObject + obj : Rhino.DocObjects.MeshObject | System.Guid Returns ------- @@ -84,6 +92,9 @@ def meshobject_to_compas(obj): ConversionError """ + if isinstance(obj, System.Guid): + obj = compas_rhino.objects.find_object(obj) + try: geometry = obj.MeshGeometry mesh = mesh_to_compas(geometry) @@ -98,7 +109,7 @@ def pointobject_to_compas(obj): Parameters ---------- - obj : Rhino.DocObjects.PointObject + obj : Rhino.DocObjects.PointObject | System.Guid Returns ------- @@ -109,6 +120,9 @@ def pointobject_to_compas(obj): ConversionError """ + if isinstance(obj, System.Guid): + obj = compas_rhino.objects.find_object(obj) + try: geometry = obj.PointGeometry point = point_to_compas(geometry) @@ -116,33 +130,3 @@ def pointobject_to_compas(obj): raise ConversionError("Rhino Object of type {} cannot be converted to a COMPAS Point.".format(type(obj))) return point - - -def surfaceobject_to_compas(obj, try_nurbs=True): - """Convert a Rhino SurfaceObject to a COMPAS Surface. - - Parameters - ---------- - obj : Rhino.DocObjects.SurfaceObject - The surface object. - try_nurbs : bool, optional - Try to convert the surface to a NURBS surface. - - Returns - ------- - :class:`compas.geometry.Surface` | :class:`compas.geometry.NurbsSurface` - If `try_nurbs` is `True`, and the geometry of the object has a NURBS representation, return a NURBS surface. - Otherwise return a general surface. - - Raises - ------ - ConversionError - - """ - try: - geometry = obj.SurfaceGeometry - surface = surface_to_compas(geometry, try_nurbs=try_nurbs) - except Exception: - raise ConversionError("Rhino Object of type {} cannot be converted to a COMPAS Surface.".format(type(obj))) - - return surface diff --git a/src/compas_rhino/conversions/geometry.py b/src/compas_rhino/conversions/geometry.py index cceb72bbe7e2..584790e9bf5f 100644 --- a/src/compas_rhino/conversions/geometry.py +++ b/src/compas_rhino/conversions/geometry.py @@ -3,7 +3,6 @@ from __future__ import print_function import Rhino # type: ignore -from System import MissingMemberException # type: ignore from compas.geometry import Frame from compas.geometry import Plane @@ -111,13 +110,9 @@ def point_to_compas(point): :class:`compas.geometry.Point` """ - try: - return Point(point.X, point.Y, point.Z) - except MissingMemberException: - try: - return Point(point.Location.X, point.Location.Y, point.Location.Z) - except MissingMemberException: - raise TypeError("Unexpected point type, got: {}".format(type(point))) + if hasattr(point, "Location"): + return Point(point.Location.X, point.Location.Y, point.Location.Z) + return Point(point.X, point.Y, point.Z) def vector_to_compas(vector):