33import logging
44import math
55from collections .abc import Sequence
6- from typing import ClassVar
6+ from typing import ClassVar , Literal
77
88import euklid
99import openglider .utils
@@ -43,23 +43,19 @@ def at_position(self, y: Percentage) -> euklid.vector.PolyLine2D:
4343class Cell (BaseModel ):
4444 rib1 : Rib
4545 rib2 : Rib
46+
4647 ballooning : BallooningBase
47- attachment_points : list [CellAttachmentPoint ] = Field (default_factory = list )
48- miniribs : list [MiniRib ] = Field (default_factory = list )
48+ ballooning_modifiers : list [BallooningModifier ] = Field (default_factory = list )
49+ ballooning_reference : Literal ["local" , "cell" ] = "local"
50+
4951 panels : list [Panel ] = Field (default_factory = list )
5052 diagonals : list [DiagonalRib ] = Field (default_factory = list )
5153 straps : list [TensionStrap ] = Field (default_factory = list )
5254 rigidfoils : list [PanelRigidFoil ] = Field (default_factory = list )
53- name : str = "unnamed"
54-
55- ballooning_modifiers : list [BallooningModifier ] = Field (default_factory = list )
55+ attachment_points : list [CellAttachmentPoint ] = Field (default_factory = list )
56+ miniribs : list [MiniRib ] = Field (default_factory = list )
5657
57- diagonal_naming_scheme : ClassVar [str ] = "{cell.name}d{diagonal_no}"
58- strap_naming_scheme : ClassVar [str ] = "{cell.name}s{side}{diagonal_no}"
59- panel_naming_scheme : ClassVar [str ] = "{cell.name}p{panel_no}"
60- panel_naming_scheme_upper : ClassVar [str ] = "{cell.name}pu{panel_no}"
61- panel_naming_scheme_lower : ClassVar [str ] = "{cell.name}pl{panel_no}"
62- minirib_naming_scheme : ClassVar [str ] = "{cell.name}mr{minirib_no}"
58+ name : str = "unnamed"
6359
6460 def __hash__ (self ) -> int :
6561 return hash_list (self .rib1 , self .rib2 , * self .miniribs , * self .diagonals )
@@ -74,18 +70,18 @@ def sort_func(panel: Panel) -> float:
7470 lower .sort (key = sort_func )
7571
7672 for panel_no , panel in enumerate (upper ):
77- panel .name = self . panel_naming_scheme_upper . format ( cell = self , panel_no = panel_no + 1 )
73+ panel .name = f" { cell_no } pu { panel_no + 1 } "
7874 for panel_no , panel in enumerate (lower ):
79- panel .name = self . panel_naming_scheme_lower . format ( cell = self , panel_no = panel_no + 1 )
75+ panel .name = f" { cell_no } pl { panel_no + 1 } "
8076
8177 else :
8278 self .panels .sort (key = lambda panel : panel .mean_x ())
8379 for panel_no , panel in enumerate (self .panels ):
84- panel .name = self . panel_naming_scheme . format ( cell = self , panel = panel , panel_no = panel_no + 1 )
80+ panel .name = f" { cell_no } p { panel_no + 1 } "
8581
8682 def rename_diagonals (self , diagonals : Sequence [DiagonalRib | TensionStrap ], cell_no : int , naming_scheme : str ) -> None :
87- upper = []
88- lower = []
83+ upper : list [ DiagonalRib | TensionStrap ] = []
84+ lower : list [ DiagonalRib | TensionStrap ] = []
8985
9086 for diagonal in diagonals :
9187 if diagonal .get_average_x () > 0 :
@@ -105,14 +101,24 @@ def rename_diagonals(self, diagonals: Sequence[DiagonalRib | TensionStrap], cell
105101
106102
107103 def rename_parts (self , cell_no : int , seperate_upper_lower : bool = False ) -> None :
108- self .rename_diagonals (self .diagonals , cell_no , self . diagonal_naming_scheme )
109- self .rename_diagonals (self .straps , cell_no , self . strap_naming_scheme )
104+ self .rename_diagonals (self .diagonals , cell_no , "{cell.name}d{diagonal_no}" )
105+ self .rename_diagonals (self .straps , cell_no , "{cell.name}s{side}{diagonal_no}" )
110106
111107 for minirib_no , minirib in enumerate (self .miniribs ):
112- minirib .name = self .minirib_naming_scheme . format ( cell = self , minirib = minirib , minirib_no = minirib_no + 1 )
108+ minirib .name = f" { self .name } mr { minirib_no + 1 } "
113109
114110 self .rename_panels (cell_no , seperate_upper_lower = seperate_upper_lower )
115111
112+ @cached_property ('prof1' , 'prof2' )
113+ def width (self ) -> float :
114+ # get the distance between the two profiles
115+ # project the base point of prof2 on the line of prof1
116+
117+ diff = self .rib2 .pos - self .rib1 .pos
118+ rib1_chord_line = self .rib1 .rotation_matrix .apply (euklid .vector .Vector2D ([1 , 0 ]))
119+
120+ return diff .cross (rib1_chord_line ).length ()
121+
116122 @cached_property ('rib1' , 'rib2' , 'ballooning_phi' )
117123 def basic_cell (self ) -> BasicCell :
118124 profile1 = self .rib1 .profile_3d
@@ -300,10 +306,19 @@ def ballooning_modified(self) -> BallooningBase:
300306 return ballooning
301307
302308 @cached_property ('ballooning_modified' )
303- def ballooning_phi (self ) -> HashedList :
309+ def ballooning_phi (self ) -> HashedList [float ]:
310+ # get ballooning arc angles for each x value of the profiles
311+
304312 x_values = [max (- 1 , min (1 , x )) for x in self .rib1 .profile_2d .x_values ]
305- balloon = [self .ballooning_modified [i ] for i in x_values ]
306- return HashedList ([BallooningBase .arcsinc (1. / (1 + bal )) if bal > 0 else 0 for bal in balloon ])
313+ balloon = [max (0. , self .ballooning_modified [i ]) for i in x_values ]
314+
315+ if self .ballooning_reference == "cell" :
316+ lengths = [(p1 - p2 ).length () for p1 , p2 in zip (self .rib1 .profile_3d .curve .nodes , self .rib2 .profile_3d .curve .nodes )]
317+ width = self .width
318+ sinc = [length / (length + width * bal ) for length , bal in zip (lengths , balloon )]
319+ else :
320+ sinc = [1. / (1 + bal ) for bal in balloon ]
321+ return HashedList ([BallooningBase .arcsinc (x ) if x < 1. else 0. for x in sinc ])
307322
308323 @cached_property ('ballooning' , '_child_cells' )
309324 def ballooning_tension_factors (self ) -> list [float ]:
0 commit comments