11from __future__ import annotations
22
3- from typing import TYPE_CHECKING
3+ from typing import TYPE_CHECKING , ClassVar
44import euklid
55import logging
66
77from openglider .airfoil import Profile3D
88from openglider .utils .dataclass import dataclass , Field
9-
109from openglider .mesh import Mesh , triangulate
1110from openglider .vector .unit import Length , Percentage
1211
@@ -20,12 +19,17 @@ class MiniRib:
2019 yvalue : float
2120 front_cut : float
2221 back_cut : float | None = None
22+ chord : float = 0.3
2323 name : str = "unnamed_minirib"
2424 material_code : str = "unnamed_material"
2525 seam_allowance : Length = Length ("10mm" )
2626 trailing_edge_cut : Length = Length ("20mm" )
2727 mrib_num : int = 0
2828 function : euklid .vector .Interpolation = Field (default_factory = lambda : euklid .vector .Interpolation ([]))
29+ hole_num : int = 4
30+ hole_border_side :float = 0.2
31+ hole_border_front_back : float = 0.15
32+
2933
3034 class Config :
3135 arbitrary_types_allowed = True
@@ -58,6 +62,30 @@ def get_multiplier(self, x: float) -> float:
5862 return min (1 , max (0 , self .function .get_value (abs (x ))))
5963 else :
6064 return 1.
65+
66+ def convert_to_percentage (self , value : Percentage | Length ) -> Percentage :
67+ if isinstance (value , Percentage ):
68+ return value
69+
70+ return Percentage (value .si / self .chord )
71+
72+ def get_offset_outline (self , cell :Cell , margin : Percentage | Length ) -> pyfoil .Airfoil :
73+ profile_3d = self .get_profile_3d (cell )
74+ self .profile_2d = profile_3d .flatten ()
75+ if margin == 0. :
76+ return self .profile_2d
77+ else :
78+ if isinstance (margin , Percentage ):
79+ margin = margin / self .chord
80+
81+ envelope = self .profile_2d .curve .offset (- margin .si , simple = False ).nodes
82+
83+ return pyfoil .Airfoil (envelope )
84+
85+ def get_flattened (self , cell :Cell ) -> euklid .vector .PolyLine2D :
86+ profile_3d = self .get_profile_3d (cell )
87+ return profile_3d .flatten ().curve
88+
6189
6290 def get_profile_3d (self , cell : Cell ) -> Profile3D :
6391
@@ -115,6 +143,11 @@ def get_nodes(self, cell: Cell) -> tuple[euklid.vector.PolyLine2D, euklid.vector
115143
116144 return nodes_top , nodes_bottom
117145
146+ def rename_parts (self ) -> None :
147+ for hole_no , hole in enumerate (self .holes ):
148+ hole .name = self .hole_naming_scheme .format (hole_no , rib = self )
149+
150+
118151 def get_hull (self , cell : Cell ) -> euklid .vector .PolyLine2D :
119152 """returns the outer contour of the normalized mesh in form
120153 of a Polyline"""
@@ -136,10 +169,22 @@ def align_all(self, cell: Cell, data: euklid.vector.PolyLine2D) -> euklid.vector
136169
137170 return euklid .vector .PolyLine3D (nodes_3d )
138171
139- def get_mesh (self , cell : Cell , filled : bool = True , max_area : float = None ) -> Mesh :
172+
173+ def get_mesh (self , cell :Cell , filled : bool = True , max_area : float = None , hole_res : int = 40 ) -> Mesh :
140174 vertices = [(p [0 ], p [1 ]) for p in self .get_hull (cell ).nodes [:- 1 ]]
141175 boundary = [list (range (len (vertices ))) + [0 ]]
142- hole_centers : list [tuple [float , float ]] = []
176+
177+
178+ holes , hole_centers = self .get_holes (cell , hole_res )
179+
180+ for curve in holes :
181+ start_index = len (vertices )
182+ hole_vertices = curve .tolist ()[:- 1 ]
183+ hole_indices = list (range (len (hole_vertices ))) + [0 ]
184+ vertices += hole_vertices
185+ boundary .append ([start_index + i for i in hole_indices ])
186+
187+
143188
144189 if not filled :
145190 segments = []
@@ -163,12 +208,77 @@ def get_mesh(self, cell: Cell, filled: bool=True, max_area: float=None) -> Mesh:
163208
164209
165210 minirib_mesh = Mesh .from_indexed (points .nodes , polygons = {"miniribs" : [(tri , {}) for tri in mesh .elements ]} , boundaries = boundaries )
166-
167- #for hole in self.holes:
168- # if hole_mesh := hole.get_mesh(self):
169- # rib_mesh += hole_mesh
211+
170212
171213 return minirib_mesh
172214
173215
174-
216+ def get_holes (self , cell : Cell , points : int = 40 ) -> tuple [list [euklid .vector .PolyLine2D ], list [euklid .vector .Vector2D ]]:
217+
218+ nodes_top , nodes_bottom = self .get_nodes (cell )
219+
220+ len_top = nodes_top .get_length ()
221+ len_bot = nodes_bottom .get_length ()
222+
223+ def get_point (x : float , y : float ) -> euklid .vector .Vector2D :
224+ p1 = nodes_top .get (nodes_top .walk (0 , len_top * x ))
225+ p2 = nodes_bottom .get (nodes_bottom .walk (0 , len_bot * (1 - x )))
226+
227+ return p1 + (p2 - p1 )* y
228+
229+ holes = []
230+ centers = []
231+
232+ if self .hole_num == 4 :
233+ holes = [
234+ euklid .spline .BSplineCurve ([
235+ get_point (0.9 ,0.9 ),
236+ get_point (0.85 ,0.9 ),
237+ get_point (0.85 ,0.1 ),
238+ get_point (0.95 ,0.1 ),
239+ get_point (0.95 ,0.9 ),
240+ get_point (0.9 ,0.9 ),
241+ ]).get_sequence (points ),
242+
243+ euklid .spline .BSplineCurve ([
244+ get_point (0.75 ,0.9 ),
245+ get_point (0.7 ,0.9 ),
246+ get_point (0.7 ,0.1 ),
247+ get_point (0.8 ,0.1 ),
248+ get_point (0.8 ,0.9 ),
249+ get_point (0.75 ,0.9 ),
250+ ]).get_sequence (points ),
251+
252+ euklid .spline .BSplineCurve ([
253+ get_point (0.625 ,0.9 ),
254+ get_point (0.575 ,0.9 ),
255+ get_point (0.575 ,0.1 ),
256+ get_point (0.65 ,0.1 ),
257+ get_point (0.65 ,0.9 ),
258+ get_point (0.625 ,0.9 ),
259+ ]).get_sequence (points ),
260+
261+ euklid .spline .BSplineCurve ([
262+ get_point (0.5 ,0.9 ),
263+ get_point (0.475 ,0.9 ),
264+ get_point (0.475 ,0.1 ),
265+ get_point (0.525 ,0.1 ),
266+ get_point (0.525 ,0.9 ),
267+ get_point (0.5 ,0.9 ),
268+ ]).get_sequence (points ),
269+
270+
271+
272+
273+ ]
274+
275+ centers = [
276+
277+ get_point (0.9 , 0.5 ),
278+ get_point (0.75 , 0.5 ),
279+ get_point (0.625 , 0.5 ),
280+ get_point (0.5 , 0.5 ),
281+ ]
282+
283+ return holes , centers
284+
0 commit comments