1-
21import Rhino
32import scriptcontext as sc
43import Rhino .Geometry as rg
98import diffCheck .df_util
109import diffCheck .df_transformations
1110
12- from Grasshopper .Kernel import GH_RuntimeMessageLevel as RML
13-
1411import numpy as np
1512
1613
@@ -19,31 +16,39 @@ class JointDetector:
1916 """
2017 This class is responsible for detecting joints in a brep
2118 """
22- brep : Rhino .Geometry .Brep
19+ brep : Rhino .Geometry .Brep
20+
2321 def __post_init__ (self ):
24- self .brep = self .brep or None
25- # list of straight cuts
26- self ._cuts : typing .List [rg .Brep ] = []
27- # list of holes
28- self ._holes : typing .List [rg .Brep ] = []
29- # list of mixed joints (cuts+holes)
30- self ._mix : typing .List [rg .Brep ]= []
31-
32- # list of DFFaces from joints and sides
3322 self ._faces = []
3423
35- def _compute_mass_center (self , b_face : rg .BrepFace ) -> rg .Point3d :
36- """
37- Compute the mass center of a brep face
38- :param b_face: The brep face to compute the mass center from
39- :return mass_center: The mass center of the brep face
40- """
41- amp = rg .AreaMassProperties .Compute (b_face )
42- if amp :
43- return amp .Centroid
44- return None
24+ def _assign_ids (self , joint_face_ids ):
25+ """ Return the extended joint ids for each face in the brep """
26+ joint_ids_is_found = [False ] * len (joint_face_ids )
27+ joint_ids = [None ] * len (joint_face_ids )
28+ id_counter = 0
29+
30+ for idx_1 , joint_face_id_1 in enumerate (joint_face_ids ):
31+ if joint_ids_is_found [idx_1 ]:
32+ continue
33+
34+ joint_ids_is_found [idx_1 ] = True
35+ joint_ids [idx_1 ] = id_counter
4536
46- def run (self ) :
37+ for idx_2 , joint_face_id_2 in enumerate (joint_face_ids ):
38+ if any (item in joint_face_id_1 for item in joint_face_id_2 ):
39+ joint_ids_is_found [idx_2 ] = True
40+ joint_ids [idx_2 ] = id_counter
41+
42+ id_counter += 1
43+
44+ extended_ids = [None ] * self .brep .Faces .Count
45+ for idx , joint_id in enumerate (joint_ids ):
46+ for joint_face_id in joint_face_ids [idx ]:
47+ extended_ids [joint_face_id ] = joint_id
48+
49+ return extended_ids
50+
51+ def run (self ):
4752 """
4853 Run the joint detector. We use a dictionary to store the faces of the cuts based wethear they are cuts or holes.
4954 - for cuts: If it is a cut we return the face, and the id of the joint the faces belongs to.
@@ -53,59 +58,35 @@ def run(self) :
5358 """
5459 # brep vertices to cloud
5560 df_cloud = diffCheck .diffcheck_bindings .dfb_geometry .DFPointCloud ()
56- brep_vertices = []
57- for vertex in self .brep .Vertices :
58- brep_vertices .append (np .array ([vertex .Location .X , vertex .Location .Y , vertex .Location .Z ]).reshape (3 , 1 ))
59- df_cloud .points = brep_vertices
61+ df_cloud .points = [np .array ([vertex .Location .X , vertex .Location .Y , vertex .Location .Z ]).reshape (3 , 1 ) for vertex in self .brep .Vertices ]
6062
61- df_OBB = df_cloud .get_tight_bounding_box ()
62- rh_OBB = diffCheck .df_cvt_bindings .cvt_dfOBB_2_rhbrep (df_OBB )
63+ rh_OBB = diffCheck .df_cvt_bindings .cvt_dfOBB_2_rhbrep (df_cloud .get_tight_bounding_box ())
6364
6465 # scale the box in the longest edge direction by 1.5 from center on both directions
6566 rh_OBB_center = rh_OBB .GetBoundingBox (True ).Center
6667 edges = rh_OBB .Edges
6768 edge_lengths = [edge .GetLength () for edge in edges ]
6869 longest_edge = edges [edge_lengths .index (max (edge_lengths ))]
69- shortest_edge = edges [edge_lengths .index (min (edge_lengths ))]
7070
7171 rh_OBB_zaxis = rg .Vector3d (longest_edge .PointAt (1 ) - longest_edge .PointAt (0 ))
7272 rh_OBB_plane = rg .Plane (rh_OBB_center , rh_OBB_zaxis )
7373 scale_factor = 0.09
7474 xform = rg .Transform .Scale (
7575 rh_OBB_plane ,
76- 1 - scale_factor ,
77- 1 - scale_factor ,
78- 1 + scale_factor
76+ 1 - scale_factor ,
77+ 1 - scale_factor ,
78+ 1 + scale_factor
7979 )
8080 rh_OBB .Transform (xform )
8181
8282 # check if face's centers are inside the OBB
83- faces = {}
84- for idx , face in enumerate (self .brep .Faces ):
85- face_center = rg .AreaMassProperties .Compute (face ).Centroid
86- if rh_OBB .IsPointInside (face_center , sc .doc .ModelAbsoluteTolerance , True ):
87- faces [idx ] = (face , True )
88- else :
89- faces [idx ] = (face , False )
90-
91- face_jointid = {} # face : joint id (int) or None
92- joint_counter = 0
93- for key , value in faces .items ():
94- if value [1 ]:
95- face_jointid [key ] = joint_counter
96- adjacent_faces = value [0 ].AdjacentFaces ()
97- for adj_face in adjacent_faces :
98- if faces [adj_face ][1 ]:
99- face_jointid [value ] = joint_counter
100- joint_counter += 1
101- else :
102- face_jointid [value ] = None
103-
104- o_sides = [faces [key ][0 ] for key , value in faces .items () if not value [1 ]]
105- o_joints = [faces [key ][0 ] for key , value in faces .items () if value [1 ]]
106-
107- # create the faces
108- # self._faces = [(face, face_jointid[idx]) for idx, face in faces.items()]
109- # self._faces = [DFFace.from_brep(face, face_jointid[idx]) for idx, face in faces.items()]
83+ faces = {idx : (face , rh_OBB .IsPointInside (rg .AreaMassProperties .Compute (face ).Centroid , sc .doc .ModelAbsoluteTolerance , True )) for idx , face in enumerate (self .brep .Faces )}
84+
85+ # get the proximity faces of the joint faces
86+ joint_face_ids = [[key ] + [adj_face for adj_face in value [0 ].AdjacentFaces () if faces [adj_face ][1 ] and adj_face != key ] for key , value in faces .items () if value [1 ]]
87+
88+ face_ids = self ._assign_ids (joint_face_ids )
89+
90+ self ._faces = [(face , face_ids [idx ]) for idx , face in enumerate (self .brep .Faces )]
11091
11192 return self ._faces
0 commit comments