Skip to content

Commit 0cb1df8

Browse files
committed
pattern commands and pattern constructors
1 parent bca41ad commit 0cb1df8

File tree

4 files changed

+1064
-0
lines changed

4 files changed

+1064
-0
lines changed

src/compas_rv/commands.py

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
from typing import Optional
2+
3+
import rhinoscriptsyntax as rs # type: ignore
4+
from compas_skeleton.datastructures import Skeleton
5+
from compas_triangle.delaunay import conforming_delaunay_triangulation
6+
from compas_triangle.rhino import discretise_boundary
7+
from compas_triangle.rhino import discretise_constraints
8+
9+
import compas_rhino
10+
import compas_rhino.conversions
11+
import compas_rhino.objects
12+
from compas.geometry import NurbsCurve
13+
from compas.geometry import Point
14+
from compas_rv.datastructures import Pattern
15+
16+
17+
def make_pattern_from_rhinolines() -> Optional[Pattern]:
18+
guids = compas_rhino.objects.select_lines("Select lines")
19+
if not guids:
20+
return
21+
22+
lines = compas_rhino.objects.get_line_coordinates(guids)
23+
if not lines:
24+
return
25+
26+
pattern: Pattern = Pattern.from_lines(lines, delete_boundary_face=True) # type: ignore
27+
28+
rs.HideObjects(guids)
29+
30+
return pattern
31+
32+
33+
def make_pattern_from_rhinomesh() -> Optional[Pattern]:
34+
guid = compas_rhino.objects.select_mesh("Select a mesh")
35+
if not guid:
36+
return
37+
38+
obj = compas_rhino.objects.find_object(guid)
39+
pattern: Pattern = compas_rhino.conversions.mesh_to_compas(obj.Geometry, cls=Pattern) # type: ignore
40+
41+
rs.HideObject(guid)
42+
43+
return pattern
44+
45+
46+
def make_pattern_from_rhinosurface() -> Optional[Pattern]:
47+
guid = compas_rhino.objects.select_surface("Select a surface")
48+
if not guid:
49+
return
50+
51+
U = rs.GetInteger(message="U faces", number=16, minimum=2, maximum=64)
52+
if not U:
53+
return
54+
55+
V = rs.GetInteger(message="V faces", number=4, minimum=2, maximum=64)
56+
if not V:
57+
return
58+
59+
obj = compas_rhino.objects.find_object(guid)
60+
brep = obj.Geometry
61+
surface = brep.Surfaces[0]
62+
pattern: Pattern = compas_rhino.conversions.surface_to_compas_mesh(surface, nu=U, nv=V, weld=True, cls=Pattern) # type: ignore
63+
64+
rs.HideObject(guid)
65+
66+
return pattern
67+
68+
69+
def make_pattern_from_meshgrid() -> Optional[Pattern]:
70+
DX = rs.GetInteger(message="X Size", number=10)
71+
if not DX:
72+
return
73+
74+
DY = rs.GetInteger(message="Y Size", number=DX)
75+
if not DY:
76+
return
77+
78+
NX = rs.GetInteger(message="Number of faces in X", number=10)
79+
if not NX:
80+
return
81+
82+
NY = rs.GetInteger(message="Number of faces in Y", number=NX)
83+
if not NY:
84+
return
85+
86+
pattern: Pattern = Pattern.from_meshgrid(dx=DX, nx=NX, dy=DY, ny=NY) # type: ignore
87+
return pattern
88+
89+
90+
def make_pattern_from_triangulation() -> Optional[Pattern]:
91+
boundary_guids = compas_rhino.objects.select_curves("Select outer boundary.")
92+
if not boundary_guids:
93+
return
94+
95+
rs.UnselectAllObjects()
96+
hole_guids = compas_rhino.objects.select_curves("Select inner boundaries.")
97+
98+
rs.UnselectAllObjects()
99+
segments_guids = compas_rhino.objects.select_curves("Select constraint curves.")
100+
101+
rs.UnselectAllObjects()
102+
103+
target_length = rs.GetReal("Specifiy target edge length.", 1.0)
104+
if not target_length:
105+
return
106+
107+
boundary = discretise_boundary(boundary_guids, target_length)
108+
holes = None
109+
segments = None
110+
curves = None # type: ignore
111+
112+
if hole_guids:
113+
holes = discretise_constraints(hole_guids, target_length)
114+
115+
if segments_guids:
116+
segments = discretise_constraints(segments_guids, target_length)
117+
curves: list[NurbsCurve] = [NurbsCurve.from_interpolation(segment) for segment in segments]
118+
119+
points, triangles = conforming_delaunay_triangulation(
120+
boundary,
121+
polylines=segments,
122+
polygons=holes,
123+
area=target_length**2 / 2,
124+
)
125+
pattern = Pattern.from_vertices_and_faces(points, triangles)
126+
127+
fixed = [vertex for boundary in pattern.vertices_on_boundaries() for vertex in boundary]
128+
if curves:
129+
for index, point in enumerate(points):
130+
for curve in curves:
131+
closest: Point = curve.closest_point(point)
132+
if closest.distance_to_point(point) < 0.1 * target_length:
133+
fixed.append(index)
134+
135+
pattern.smooth_area(fixed=fixed)
136+
137+
138+
def make_pattern_from_skeleton() -> Optional[Pattern]:
139+
guids = compas_rhino.objects.select_lines("Select skeleton lines.")
140+
if not guids:
141+
return
142+
143+
rs.UnselectAllObjects()
144+
145+
width = rs.GetReal("Specifiy skeleton width.", 1.0)
146+
if not width:
147+
return
148+
149+
angle = rs.GetReal("Specifiy skeleton leaf angle (degrees).", 30)
150+
if not angle:
151+
return
152+
153+
density = rs.GetInteger("Specifiy skeleton density.", 2)
154+
if not density:
155+
return
156+
157+
objects = [compas_rhino.objects.find_object(guid) for guid in guids]
158+
curves = [obj.Geometry for obj in objects]
159+
lines = [compas_rhino.conversions.curve_to_compas_line(curve) for curve in curves]
160+
161+
skeleton = Skeleton(lines)
162+
skeleton.node_width = width
163+
skeleton.leaf_angle = angle
164+
skeleton.density = density
165+
pattern = skeleton.pattern.copy(cls=Pattern)
166+
167+
return pattern

src/compas_rv/patterns/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)