@@ -43,7 +43,7 @@ def __setstate__(self, state: typing.Dict):
4343 self .__dict__ .update (state )
4444
4545 def __repr__ (self ):
46- return f"Vertex : X={ self .x } , Y={ self .y } , Z={ self .z } "
46+ return f"DFVertex : X={ self .x } , Y={ self .y } , Z={ self .z } "
4747
4848 def __hash__ (self ):
4949 return hash ((self .x , self .y , self .z ))
@@ -97,6 +97,7 @@ def __post_init__(self):
9797 # if df_face is created from a rhino brep face, we store the rhino brep face
9898 self ._rh_brepface : rg .BrepFace = None
9999 self .is_roundwood = False
100+ self ._center : DFVertex = None
100101
101102 def __getstate__ (self ):
102103 state = self .__dict__ .copy ()
@@ -123,7 +124,6 @@ def __setstate__(self, state: typing.Dict):
123124 if self ._rh_brepface is not None :
124125 self .from_brep_face (self ._rh_brepface , self .joint_id )
125126
126-
127127 def __repr__ (self ):
128128 return f"Face id: { (self .id )} , IsJoint: { self .is_joint } Loops: { len (self .all_loops )} "
129129
@@ -240,6 +240,13 @@ def is_joint(self):
240240 def uuid (self ):
241241 return self .__uuid
242242
243+ @property
244+ def center (self ):
245+ if self ._center is None :
246+ vertices = [vertex .to_rg_point3d () for vertex in self .all_loops [0 ]]
247+ self ._center = DFVertex .from_rg_point3d (rg .BoundingBox (vertices ).Center )
248+ return self ._center
249+
243250@dataclass
244251class DFJoint :
245252 """
@@ -257,6 +264,8 @@ def __post_init__(self):
257264 # this is an automatic identifier
258265 self .__uuid = uuid .uuid4 ().int
259266
267+ self ._center : DFVertex = None
268+
260269 def __getstate__ (self ):
261270 state = self .__dict__ .copy ()
262271 if "faces" in state and state ["faces" ] is not None :
@@ -313,6 +322,16 @@ def uuid(self):
313322 """ It retrives the automatic identifier, not the one of the joint in the beam """
314323 return self .__uuid
315324
325+ @property
326+ def center (self ):
327+ if self ._center is None :
328+ vertices = []
329+ for face in self .faces :
330+ vertices .extend (face .all_loops [0 ])
331+ vertices = [vertex .to_rg_point3d () for vertex in vertices ]
332+ self ._center = DFVertex .from_rg_point3d (rg .BoundingBox (vertices ).Center )
333+ return self ._center
334+
316335@dataclass
317336class DFBeam :
318337 """
@@ -339,6 +358,8 @@ def __post_init__(self):
339358 self ._index_assembly : int = None
340359
341360 self ._center : rg .Point3d = None
361+ self ._axis : rg .Vector3d = self .compute_axis ()
362+
342363 self .__id = uuid .uuid4 ().int
343364
344365 def __getstate__ (self ):
@@ -355,6 +376,8 @@ def __getstate__(self):
355376 state ["_joints" ] = [joint .__getstate__ () for joint in state ["_joints" ]]
356377 if "_center" in state and state ["_center" ] is not None :
357378 state ["_center" ] = self ._center .ToJSON (SerializationOptions ())
379+ if "_axis" in state and state ["_axis" ] is not None :
380+ state ["_axis" ] = self ._axis .ToJSON (SerializationOptions ())
358381 return state
359382
360383 def __setstate__ (self , state : typing .Dict ):
@@ -395,6 +418,8 @@ def __setstate__(self, state: typing.Dict):
395418 state ["_joints" ] = joints
396419 if "_center" in state and state ["_center" ] is not None :
397420 state ["_center" ] = rg .Point3d .FromJSON (state ["_center" ])
421+ if "_axis" in state and state ["_axis" ] is not None :
422+ state ["_axis" ] = rg .Vector3d .FromJSON (state ["_axis" ])
398423 self .__dict__ .update (state )
399424
400425 def __repr__ (self ):
@@ -403,6 +428,39 @@ def __repr__(self):
403428 def deepcopy (self ):
404429 return DFBeam (self .name , [face .deepcopy () for face in self .faces ])
405430
431+ def compute_axis (self , is_unitized : bool = True ) -> rg .Vector3d :
432+ """
433+ This is an utility function that computes the axis of the beam.
434+ The axis is calculated as the vector passing through the two most distance joint's centroids.
435+
436+ :param is_unitized: If True, the beam's axis is unitized
437+ :return axis: The axis of the beam
438+ """
439+ joints = self .joints
440+ joint1 = joints [0 ]
441+ joint2 = joints [1 ]
442+ max_distance = 0
443+ if len (joints ) > 2 :
444+ for j1 in joints :
445+ for j2 in joints :
446+ distance = rg .Point3d .DistanceTo (
447+ j1 .center .to_rg_point3d (),
448+ j2 .center .to_rg_point3d ())
449+ if distance > max_distance :
450+ max_distance = distance
451+ joint1 = j1
452+ joint2 = j2
453+
454+ axis = rg .Vector3d (
455+ joint1 .center .to_rg_point3d (),
456+ joint2 .center .to_rg_point3d ()
457+ )
458+
459+ if is_unitized :
460+ axis .Unitize ()
461+
462+ return axis
463+
406464 @classmethod
407465 def from_brep_face (cls , brep , is_roundwood = False ):
408466 """
@@ -498,6 +556,11 @@ def vertices(self):
498556 self ._vertices .extend (loop )
499557 return self ._vertices
500558
559+ @property
560+ def axis (self ):
561+ self ._axis = self .compute_axis ()
562+ return self ._axis
563+
501564
502565@dataclass
503566class DFAssembly :
0 commit comments