-
Notifications
You must be signed in to change notification settings - Fork 113
Feature/rhino object functions #256
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -65,6 +65,17 @@ def from_selection(cls): | |
| guid = compas_rhino.select_curve() | ||
| return cls(guid) | ||
|
|
||
| def length(self): | ||
| """Return the length of the curve. | ||
|
|
||
| Returns | ||
| ------- | ||
| float | ||
| The curve's length. | ||
|
|
||
| """ | ||
| return rs.CurveLength(self.guid) | ||
|
|
||
| def is_line(self): | ||
| """Determine if the curve is a line. | ||
|
|
||
|
|
@@ -101,6 +112,18 @@ def is_polyline(self): | |
| rs.CurveDegree(self.guid) == 1 and | ||
| len(rs.CurvePoints(self.guid)) > 2) | ||
|
|
||
| def is_closed(self): | ||
| """Assess if the curve is closed. | ||
|
|
||
| Returns | ||
| ------- | ||
| bool | ||
| True if the curve is closed. False otherwise. | ||
|
|
||
| """ | ||
|
|
||
| return rs.IsCurveClosed(self.guid) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| def control_points(self): | ||
| """Get the control points of a curve. | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,8 +6,13 @@ | |
| import compas_rhino | ||
|
|
||
| from compas_rhino.geometry import RhinoGeometry | ||
| from compas_rhino.geometry import RhinoCurve | ||
|
|
||
| from compas_rhino.utilities import delete_objects | ||
|
|
||
| from compas.geometry import subtract_vectors | ||
| from compas.geometry import angle_vectors | ||
|
|
||
|
|
||
| try: | ||
| import rhinoscriptsyntax as rs | ||
|
|
@@ -229,6 +234,32 @@ def borders(self, type=1): | |
| curves = rs.ExplodeCurves(border, delete_input=True) | ||
| return curves | ||
|
|
||
| def kinks(self, threshold=1e-3): | ||
| """Return the XYZ coordinates of kinks, i.e. tangency discontinuities, along the surface's boundaries. | ||
|
|
||
| Returns | ||
| ------- | ||
| list | ||
| The list of XYZ coordinates of surface boundary kinks. | ||
|
|
||
| """ | ||
| kinks = [] | ||
| borders = self.borders(type=0) | ||
|
|
||
| for border in borders: | ||
| border = RhinoCurve(border) | ||
| extremities = map(lambda x: rs.EvaluateCurve(border.guid, rs.CurveParameter(border.guid, x)), [0., 1.]) | ||
|
|
||
| if border.is_closed(): | ||
| start_tgt, end_tgt = border.tangents(extremities) | ||
| if angle_vectors(start_tgt, end_tgt) > threshold: | ||
| kinks += extremities | ||
|
|
||
| else: | ||
| kinks += extremities | ||
|
|
||
| return list(set(kinks)) | ||
|
|
||
| def project_point(self, point, direction=(0, 0, 1)): | ||
| projections = rs.ProjectPointToSurface(point, self.guid, direction) | ||
| if not projections: | ||
|
|
@@ -242,13 +273,6 @@ def project_points(self, points, direction=(0, 0, 1), include_none=True): | |
| projections[:] = [self.closest_point(point) if not point else point for point in projections] | ||
| return map(list, projections) | ||
|
|
||
| def closest_point(self, point, maxdist=None): | ||
| point = self.geometry.ClosestPoint(Point3d(*point)) | ||
| return list(point) | ||
|
|
||
| def closest_points(self, points, maxdist=None): | ||
| return [self.closest_point(point) for point in points] | ||
|
|
||
| def pull_point(self, point): | ||
| pass | ||
|
|
||
|
|
@@ -278,13 +302,143 @@ def pull_mesh(self, mesh, fixed=None, d=1.0): | |
| def pull_meshes(self, meshes): | ||
| pass | ||
|
|
||
| def closest_point(self, xyz): | ||
| """Return the XYZ coordinates of the closest point on the surface from input XYZ-coordinates. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| xyz : list | ||
| XYZ coordinates. | ||
|
|
||
| Returns | ||
| ------- | ||
| list | ||
| The XYZ coordinates of the closest point on the surface. | ||
|
|
||
| """ | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. blank line |
||
| return rs.EvaluateSurface(self.guid, *rs.SurfaceClosestPoint(self.guid, xyz)) | ||
|
|
||
| def closest_points(self, points): | ||
| return [self.closest_point(point) for point in points] | ||
|
|
||
| def closest_point_on_boundaries(self, xyz): | ||
| """Return the XYZ coordinates of the closest point on the boundaries of the surface from input XYZ-coordinates. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| xyz : list | ||
| XYZ coordinates. | ||
|
|
||
| Returns | ||
| ------- | ||
| list | ||
| The XYZ coordinates of the closest point on the boundaries of the surface. | ||
|
|
||
| """ | ||
| borders = self.borders(type=0) | ||
| proj_dist = {tuple(proj_xyz): distance_point_point(xyz, proj_xyz) for proj_xyz in [RhinoCurve(border).closest_point(xyz) for border in borders]} | ||
| delete_objects(borders) | ||
| return min(proj_dist, key=proj_dist.get) | ||
|
|
||
| def closest_points_on_boundaries(self, points): | ||
| return [self.closest_point_on_boundaries(point) for point in points] | ||
|
|
||
| # -------------------------------------------------------------------------- | ||
| # mapping | ||
| # -------------------------------------------------------------------------- | ||
|
|
||
| def point_xyz_to_uv(self, xyz): | ||
| """Return the UV point from the mapping of a XYZ point based on the UV parameterisation of the surface. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| xyz : list | ||
| (x, y, z) coordinates. | ||
|
|
||
| Returns | ||
| ------- | ||
| list | ||
| The (u, v, 0) coordinates of the mapped point. | ||
|
|
||
| """ | ||
| return rs.SurfaceClosestPoint(self.guid, xyz) + (0.,) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure i understand what this function does
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. blank line |
||
|
|
||
| def point_uv_to_xyz(self, uv): | ||
| """Return the XYZ point from the inverse mapping of a UV point based on the UV parameterisation of the surface. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| uv : list | ||
| (u, v, 0) coordinates. | ||
|
|
||
| Returns | ||
| ------- | ||
| list | ||
| The (x, y, z) coordinates of the inverse-mapped point. | ||
|
|
||
| """ | ||
| return tuple(rs.EvaluateSurface(self.guid, *uv)) | ||
|
|
||
| def line_uv_to_xyz(self, line): | ||
| """Return the XYZ points from the inverse mapping of a UV line based on the UV parameterisation of the surface. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| uv : list | ||
| List of (u, v, 0) coordinates. | ||
|
|
||
| Returns | ||
| ------- | ||
| list | ||
| The list of XYZ coordinates of the inverse-mapped line. | ||
|
|
||
| """ | ||
| return (self.point_uv_to_xyz(line[0][:2]), self.point_uv_to_xyz(line[1][:2])) | ||
|
|
||
| def polyline_uv_to_xyz(self, polyline): | ||
| """Return the XYZ points from the inverse mapping of a UV polyline based on the UV parameterisation of the surface. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| uv : list | ||
| List of (u, v, 0) coordinates. | ||
|
|
||
| Returns | ||
| ------- | ||
| list | ||
| The list of (x, y, z) coordinates of the inverse-mapped polyline. | ||
|
|
||
| """ | ||
| return [self.point_uv_to_xyz(vertex[:2]) for vertex in polyline] | ||
|
|
||
| def mesh_uv_to_xyz(self, mesh, cls=None): | ||
| """Return the mesh from the inverse mapping of a UV mesh based on the UV parameterisation of the surface. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| mesh : Mesh | ||
| A mesh. | ||
|
|
||
| Returns | ||
| ------- | ||
| Mesh, cls | ||
| The inverse-mapped mesh. | ||
|
|
||
| """ | ||
| if cls is None: | ||
| cls = type(mesh) | ||
|
|
||
| vertices, faces = mesh.to_vertices_and_faces() | ||
| vertices = [self.point_uv_to_xyz(uv0[:2]) for uv0 in vertices] | ||
| return cls.from_vertices_and_faces(vertices, faces) | ||
|
|
||
| # ============================================================================== | ||
| # Main | ||
| # ============================================================================== | ||
|
|
||
| if __name__ == '__main__': | ||
|
|
||
| surface = RhinoSurface.from_selection() | ||
|
|
||
| points = [] | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the object is also stored, and there is a method of the object for getting the length...
https://developer.rhino3d.com/api/RhinoCommon/html/M_Rhino_Geometry_Curve_GetLength_2.htm