@@ -50,15 +50,82 @@ def break_boundary(mesh: Mesh, breakpoints: list[int]) -> tuple[list[list[int]],
5050 return borders , breakpoints
5151
5252
53- def make_block ():
54- pass
53+ def make_block (basemesh : Mesh , idos : Mesh , face : int ) -> Mesh :
54+ vertices = basemesh .face_vertices (face )
55+ normals = [basemesh .vertex_normal (vertex ) for vertex in vertices ]
56+ thickness = basemesh .vertices_attribute ("thickness" , keys = vertices )
5557
58+ bottom = idos .vertices_points (vertices )
59+ top = [point + vector * t for point , vector , t in zip (bottom , normals , thickness )]
60+
61+ frame = Frame (* bestfit_frame_numpy (top ))
62+ plane = Plane .from_frame (frame )
63+
64+ flattop = []
65+ for a , b in zip (bottom , top ):
66+ b = plane .intersection_with_line (Line (a , b ))
67+ flattop .append (b )
68+
69+ sides = []
70+ for (a , b ), (aa , bb ) in zip (pairwise (bottom + bottom [:1 ]), pairwise (flattop + flattop [:1 ])):
71+ sides .append ([a , b , bb , aa ])
72+
73+ polygons = [bottom [::- 1 ], flattop ] + sides
74+
75+ block : Mesh = Mesh .from_polygons (polygons )
76+ block .update_default_face_attributes (is_support = False , is_interface = False )
77+ block .attributes ["frame" ] = frame
78+ block .attributes ["is_support" ] = False
79+
80+ return block
81+
82+
83+ def make_block_referenced (basemesh : Mesh , idos : Mesh , face : int ) -> Mesh :
84+ N = basemesh ._max_vertex + 1
85+
86+ vertices = basemesh .face_vertices (face )
87+ normals = [basemesh .vertex_normal (vertex ) for vertex in vertices ]
88+ thickness = basemesh .vertices_attribute ("thickness" , keys = vertices )
89+
90+ bottom = idos .vertices_points (vertices )
91+ top = [point + vector * t for point , vector , t in zip (bottom , normals , thickness )]
92+
93+ frame = Frame (* bestfit_frame_numpy (top ))
94+ plane = Plane .from_frame (frame )
95+
96+ flattop = []
97+ for a , b in zip (bottom , top ):
98+ b = plane .intersection_with_line (Line (a , b ))
99+ flattop .append (b )
100+
101+ block : Mesh = Mesh ()
102+
103+ for vertex , point in zip (vertices , bottom ):
104+ # use the same identifiers for the vertices of the bottom face
105+ key = vertex
106+ block .add_vertex (key = key , x = point [0 ], y = point [1 ], z = point [2 ])
107+
108+ for vertex , point in zip (vertices , flattop ):
109+ # offset the identifiers of the top face by "N"
110+ key = vertex + N
111+ block .add_vertex (key = key , x = point [0 ], y = point [1 ], z = point [2 ])
112+
113+ block .add_face (vertices [::- 1 ])
114+ block .add_face ([vertex + N for vertex in vertices ])
115+
116+ for u , v in pairwise (vertices + vertices [:1 ]):
117+ block .add_face ([u , v , v + N , u + N ])
118+
119+ block .update_default_face_attributes (is_support = False , is_interface = False )
120+
121+ block .attributes ["n" ] = N
122+ block .attributes ["frame" ] = frame
123+ block .attributes ["is_support" ] = False
56124
57- def make_block_referenced ():
58- pass
125+ return block
59126
60127
61- def trimesh_remesh_python_with_projection (trimesh : Mesh ) :
128+ def trimesh_remesh_python_with_projection (trimesh : Mesh , target_length : float , kmax : int = 300 ) -> None :
62129 def project (mesh : Mesh , k : int , args ) -> None :
63130 for vertex in mesh .vertices ():
64131 if mesh .is_vertex_on_boundary (vertex ):
@@ -82,8 +149,8 @@ def project(mesh: Mesh, k: int, args) -> None:
82149
83150 trimesh_remesh_python (
84151 trimesh ,
85- length ,
86- kmax = 300 ,
152+ target_length ,
153+ kmax = kmax ,
87154 callback = project ,
88155 )
89156
@@ -100,6 +167,23 @@ def project(mesh: Mesh, k: int, args) -> None:
100167thrustobject = rv_scene .find_by_name ("ThrustDiagram" )
101168thrustdiagram : FormDiagram = thrustobject .mesh
102169
170+ # =============================================================================
171+ # Global Parameters
172+ # =============================================================================
173+
174+ THICKNESS_SUPPORTS1 = 30
175+ THICKNESS_SUPPORTS2 = 20
176+ THICKNESS_BORDER = 10
177+ THICKNESS_TOP = 10
178+
179+ LENGTH_FACTOR = 0.9
180+
181+ MAX_CHAMFER_ANGLE = 145
182+ CHAMFER_OFFSET = 2
183+
184+ SUPPORT_PADDING = 5
185+ SUPPORT_DEPTH = 70
186+
103187# =============================================================================
104188# Mesh
105189#
@@ -113,7 +197,7 @@ def project(mesh: Mesh, k: int, args) -> None:
113197for face in list (mesh .faces_where (_is_loaded = False )):
114198 mesh .delete_face (face )
115199
116- length = sum (mesh .edge_length (edge ) for edge in mesh .edges ()) / mesh .number_of_edges ()
200+ average_length = sum (mesh .edge_length (edge ) for edge in mesh .edges ()) / mesh .number_of_edges ()
117201
118202# =============================================================================
119203# Mesh: Borders
@@ -142,16 +226,24 @@ def project(mesh: Mesh, k: int, args) -> None:
142226# - use a percentage of the average edge length of the original mesh as target length
143227# =============================================================================
144228
229+ target_edge_length = LENGTH_FACTOR * average_length
230+
145231M = trimesh .to_vertices_and_faces ()
146- V , F = trimesh_remesh (M , target_edge_length = 0.9 * length , number_of_iterations = 100 )
232+ V , F = trimesh_remesh (
233+ M ,
234+ target_edge_length = target_edge_length ,
235+ number_of_iterations = 100 ,
236+ )
147237
148238trimesh = Mesh .from_vertices_and_faces (V , F )
149239
150240# =============================================================================
151241# Trimesh: Remeshing w/o CGAL
152242# =============================================================================
153243
154- # trimesh_remesh_python_with_projection(trimesh)
244+ # target_edge_length = 1.0 * average_length
245+
246+ # trimesh_remesh_python_with_projection(trimesh, target_edge_length)
155247
156248# =============================================================================
157249# Dual
@@ -298,23 +390,23 @@ def project(mesh: Mesh, k: int, args) -> None:
298390
299391for support in supports_by_height [:4 ]:
300392 points .append (mesh .vertex_attributes (support , "xy" ))
301- values .append (50 )
393+ values .append (THICKNESS_SUPPORTS1 )
302394
303395for support in supports_by_height [4 :]:
304396 points .append (mesh .vertex_attributes (support , "xy" ))
305- values .append (30 )
397+ values .append (THICKNESS_SUPPORTS2 )
306398
307399for border in mesh .attributes ["borders" ]:
308400 if len (border ) > 4 :
309401 midspan = border [len (border ) // 2 ]
310402 points .append (mesh .vertex_attributes (midspan , "xy" ))
311- values .append (15 )
403+ values .append (THICKNESS_BORDER )
312404
313405vertices_by_height = sorted (mesh .vertices (), key = lambda v : mesh .vertex_attribute (v , "z" ))
314406
315407for vertex in vertices_by_height [- 5 :]:
316408 points .append (mesh .vertex_attributes (vertex , "xy" ))
317- values .append (10 )
409+ values .append (THICKNESS_TOP )
318410
319411# =============================================================================
320412# Blocks: Thickness interpolation sampling
@@ -327,7 +419,7 @@ def project(mesh: Mesh, k: int, args) -> None:
327419 dual .vertex_attribute (vertex , "thickness" , t )
328420
329421# =============================================================================
330- # Blocks
422+ # Blocks: Idos
331423# =============================================================================
332424
333425idos : Mesh = dual .copy ()
@@ -337,79 +429,31 @@ def project(mesh: Mesh, k: int, args) -> None:
337429 thickness = dual .vertex_attribute (vertex , name = "thickness" )
338430 idos .vertex_attributes (vertex , names = "xyz" , values = point - normal * (0.5 * thickness ))
339431
432+ # =============================================================================
433+ # Blocks
434+ # =============================================================================
435+
340436blocks : list [Mesh ] = []
341437
342438for face in dual .faces ():
343- vertices = dual .face_vertices (face )
344- normals = [dual .vertex_normal (vertex ) for vertex in vertices ]
345- thickness = dual .vertices_attribute ("thickness" , keys = vertices )
346-
347- bottom = idos .vertices_points (vertices )
348- top = [point + vector * t for point , vector , t in zip (bottom , normals , thickness )]
349-
350- frame = Frame (* bestfit_frame_numpy (top ))
351- plane = Plane .from_frame (frame )
352-
353- flattop = []
354- for a , b in zip (bottom , top ):
355- b = plane .intersection_with_line (Line (a , b ))
356- flattop .append (b )
357-
358- # make the block
359- # this is a more complicated version of making a block
360- # it keeps the vertex keys of the bottom face the same as the ones of the corresponding face of the dual
361- # and uses vertex + max_vertex + 1 for the top
362- n = dual ._max_vertex + 1
363-
364- block : Mesh = Mesh ()
365-
366- for vertex , point in zip (vertices , bottom ):
367- key = block .add_vertex (key = vertex , x = point [0 ], y = point [1 ], z = point [2 ])
368-
369- for vertex , point in zip (vertices , flattop ):
370- key = block .add_vertex (key = vertex + n , x = point [0 ], y = point [1 ], z = point [2 ])
371-
372- block .add_face (vertices [::- 1 ])
373- block .add_face ([vertex + n for vertex in vertices ])
374- for u , v in pairwise (vertices + vertices [:1 ]):
375- uu = u + n
376- vv = v + n
377- block .add_face ([u , v , vv , uu ])
378-
379- block .update_default_edge_attributes (is_vertical = False )
380- block .update_default_face_attributes (is_support = False , is_interface = False )
381- block .attributes ["n" ] = n
382- block .attributes ["frame" ] = frame
383- block .attributes ["is_support" ] = False
384-
439+ block = make_block (dual , idos , face )
385440 dual .face_attribute (face , name = "block" , value = block )
386441
387- # identify support faces
442+ # identify support faces and interfaces
443+ vertices = dual .face_vertices (face )
388444 for index , (u , v ) in enumerate (pairwise (vertices + vertices [:1 ])):
389- is_support = dual .edge_attribute ((u , v ), name = "is_support" )
390- if is_support :
391- face = 2 + index
392- block .face_attribute (face , name = "is_support" , value = True )
393- block .attributes ["is_support" ] = True
445+ # the first two faces are bottom and top
446+ # then come the side faces in same order as the cycle of pairwise vertices
447+ # => face = index + 2
448+ face = index + 2
394449
395- # identify interfaces
396- for index , (u , v ) in enumerate (pairwise (vertices + vertices [:1 ])):
450+ is_support = dual .edge_attribute ((u , v ), name = "is_support" )
397451 is_interface = dual .edge_attribute ((u , v ), name = "is_interface" )
398- if is_interface :
399- face = 2 + index
400- block .face_attribute (face , name = "is_interface" , value = True )
401-
402- # identify vertical edges
403- vertices = block .face_vertices (0 )
404- for vertex in vertices :
405- nbrs = block .vertex_neighbors (vertex )
406- nbr = None
407- for test in nbrs :
408- if test not in vertices :
409- nbr = test
410- break
411- if nbr is not None :
412- block .edge_attribute ((vertex , nbr ), name = "is_vertical" , value = True )
452+
453+ block .face_attribute (face , name = "is_support" , value = is_support )
454+ block .face_attribute (face , name = "is_interface" , value = is_interface )
455+
456+ block .attributes ["is_support" ] = True
413457
414458 blocks .append (block )
415459
@@ -435,11 +479,11 @@ def project(mesh: Mesh, k: int, args) -> None:
435479 right = plane .projected_point (dual .vertex_point (nbr ))
436480 v1 = (left - plane .point ).unitized ()
437481 v2 = (right - plane .point ).unitized ()
438- if v1 .angle (v2 , degrees = True ) > 120 :
482+ if v1 .angle (v2 , degrees = True ) > MAX_CHAMFER_ANGLE :
439483 continue
440484
441485 direction = (v1 + v2 ).unitized ()
442- cutter = Plane (plane .point , direction ).offset (1 )
486+ cutter = Plane (plane .point , direction ).offset (CHAMFER_OFFSET )
443487
444488 face = dual .halfedge_face ((vertex , nbr ))
445489 temp : Mesh = face_block [face ]
@@ -490,15 +534,15 @@ def project(mesh: Mesh, k: int, args) -> None:
490534 yaxis = zaxis .cross (xaxis )
491535 frame = Frame (point , xaxis , yaxis )
492536 plane = Plane .from_frame (frame )
493- offset = plane .offset (70 )
537+ offset = plane .offset (SUPPORT_DEPTH )
494538
495539 bottom = [
496540 P0 + dual .vertex_normal (border [0 ]) * 0.5 * dual .vertex_attribute (border [0 ], name = "thickness" ),
497541 P1 + dual .vertex_normal (border [- 1 ]) * 0.5 * dual .vertex_attribute (border [- 1 ], name = "thickness" ),
498542 P1 - dual .vertex_normal (border [- 1 ]) * 0.5 * dual .vertex_attribute (border [- 1 ], name = "thickness" ),
499543 P0 - dual .vertex_normal (border [0 ]) * 0.5 * dual .vertex_attribute (border [0 ], name = "thickness" ),
500544 ]
501- bottom = offset_polygon (bottom , - 5 )
545+ bottom = offset_polygon (bottom , - SUPPORT_PADDING )
502546 top = [
503547 offset .intersection_with_line (Line .from_point_and_vector (bottom [0 ], R0 )),
504548 offset .intersection_with_line (Line .from_point_and_vector (bottom [1 ], R1 )),
@@ -539,11 +583,15 @@ def project(mesh: Mesh, k: int, args) -> None:
539583# Viz: Reactions
540584# =============================================================================
541585
586+ reactions = []
587+
542588for vertex in mesh .vertices_where (is_support = True ):
543589 point = mesh .vertex_point (vertex )
544590 residual = Vector (* mesh .vertex_attributes (vertex , names = ["_rx" , "_ry" , "_rz" ]))
545591 reaction = Line .from_point_and_vector (point , residual * 0.001 )
546- viewer .scene .add (reaction , linewidth = 5 , linecolor = Color .green ())
592+ reactions .append (reaction )
593+
594+ viewer .scene .add (reactions , linewidth = 5 , linecolor = Color .green (), name = "Reactions" )
547595
548596# =============================================================================
549597# Viz: Blocks
@@ -574,7 +622,7 @@ def project(mesh: Mesh, k: int, args) -> None:
574622# Viz: Cut blocks
575623# =============================================================================
576624
577- viewer .scene .add (list (face_block .values ()))
625+ viewer .scene .add (list (face_block .values ()), name = "Chamfered Blocks" )
578626
579627# =============================================================================
580628# Viz: Show
0 commit comments