11from __future__ import annotations
22
33import math
4- from typing import TYPE_CHECKING
4+ from typing import TYPE_CHECKING , Literal
55from collections .abc import Callable
66
77import euklid
@@ -33,80 +33,109 @@ class RigidFoilPlot:
3333 rigidfoil : RigidFoilBase
3434 ribplot : RibPlot
3535
36+ drawing : PlotPart
3637 inner_curve : euklid .vector .PolyLine2D | None = None
3738 outer_curve : euklid .vector .PolyLine2D | None = None
39+ center_curve : euklid .vector .PolyLine2D | None = None
3840
3941 def __init__ (self , rigidfoil : RigidFoilBase , ribplot : RibPlot ) -> None :
4042 self .rigidfoil = rigidfoil
4143 self .ribplot = ribplot
44+ self .drawing = PlotPart ()
4245
43- def add_text (self , plotpart : PlotPart ) -> None :
44- (_ , p1 ), (_ , p2 ) = self .get_cap (- 1 , True )
46+ def add_text (self ) -> None :
47+ (_ , p1 ), (_ , p2 ) = self .get_cap ("back" )
4548
46- plotpart .layers [self .ribplot .layer_name_text ] += Text (
49+ self . drawing .layers [self .ribplot .layer_name_text ] += Text (
4750 self .rigidfoil .name , p1 , p2 , align = "center" , valign = 0.6
4851 ).get_vectors ()
4952
50- def get_cap (self , position : int , rear : bool ) -> tuple [tuple [Vector2D , Vector2D ], tuple [Vector2D , Vector2D ]]:
51- assert self .inner_curve is not None and self .outer_curve is not None
53+ def get_cap (self , side : Literal ["front" , "back" ], outer_distance : float | None = None ) -> tuple [tuple [Vector2D , Vector2D ], tuple [Vector2D , Vector2D ]]:
54+ if side == "front" :
55+ position = 0
56+ angle = math .pi / 2
57+ elif side == "back" :
58+ position = - 1
59+ angle = - math .pi / 2
60+ else :
61+ raise ValueError ("side must be 'front' or 'back'" )
62+
63+ if self .center_curve is None :
64+ raise ValueError ("Setup not called" )
65+
66+ if outer_distance is None :
67+ outer_distance = self .get_outer_distance ().si
68+ inner_distance = self .get_inner_distance ().si
5269
70+ center_point = self .center_curve .nodes [position ]
71+ normal = self .center_curve .normvectors ().nodes [position ]
72+
73+ outer_point = center_point + normal * outer_distance
74+ inner_point = center_point - normal * inner_distance
5375 # back cap
54- p1 = self .inner_curve .nodes [position ]
55- p2 = self .outer_curve .nodes [position ]
56- angle = math .pi / 2
57- if rear :
58- angle = - angle
59- diff = euklid .vector .Rotation2D (angle ).apply (p1 - p2 ).normalized () * self .rigidfoil .cap_length .si
76+ diff = euklid .vector .Rotation2D (angle ).apply (inner_point - outer_point ).normalized () * self .rigidfoil .cap_length .si
6077
6178 return (
62- (p1 , p2 ),
63- (p1 + diff , p2 + diff )
79+ (inner_point , outer_point ),
80+ (inner_point + diff , outer_point + diff )
6481 )
6582
66- def _get_inner_outer (self , glider : Glider ) -> tuple [euklid .vector .PolyLine2D , euklid .vector .PolyLine2D ]:
67- curve = self .rigidfoil .get_flattened (self .ribplot .rib , glider )
68-
83+ def get_outer_distance (self ) -> Length :
6984 distance = self .ribplot .rib .convert_to_chordlength (self .rigidfoil .distance )
70- d_outer = self .ribplot .rib .seam_allowance .si + distance .si
71-
85+ return self .ribplot .rib .seam_allowance + distance + self .rigidfoil .diameter / 2
86+
87+ def get_inner_distance (self ) -> Length :
7288 if self .rigidfoil .inner_allowance :
7389 allowance = self .rigidfoil .inner_allowance
7490 else :
7591 allowance = self .ribplot .rib .seam_allowance
7692
77- inner_curve = curve .offset (- (distance + allowance ).si ).fix_errors ()
78- outer_curve = curve .offset (d_outer ).fix_errors ()
93+ return (self .rigidfoil .diameter / 2 + allowance )
94+
95+ def setup (self , glider : Glider ) -> tuple [euklid .vector .PolyLine2D , euklid .vector .PolyLine2D , euklid .vector .PolyLine2D ]:
96+ if any ([x is None for x in [self .inner_curve , self .outer_curve , self .center_curve ]]):
97+ curve = self .rigidfoil .get_center_line (self .ribplot .rib , glider )
98+
99+ d_outer = self .get_outer_distance ()
100+ d_inner = self .get_inner_distance ()
79101
80- return inner_curve , outer_curve
102+
103+ self .center_curve = curve
104+ self .inner_curve = curve .offset (- d_inner .si )
105+ self .outer_curve = curve .offset (d_outer .si )
106+
107+ return self .center_curve , self .inner_curve , self .outer_curve # type: ignore
108+
109+ def insert_mark (self ) -> None :
110+ assert self .center_curve is not None
111+
112+ rigidfoil_outline = self .rigidfoil .get_flattened (self .center_curve )
113+
114+ self .drawing .layers [self .ribplot .layer_name_marks ].append (rigidfoil_outline )
115+ self .ribplot .plotpart .layers [self .ribplot .layer_name_rigidfoils ].append (rigidfoil_outline )
81116
82117 def flatten (self , glider : Glider ) -> PlotPart :
83- plotpart = PlotPart ()
118+ curve , inner_curve , outer_curve = self .setup (glider )
119+ plotpart = self .drawing
84120
85121 controlpoints : list [tuple [float , list [euklid .vector .PolyLine2D ]]] = []
86122 for x in self .ribplot .config .get_controlpoints (self .ribplot .rib ):
87123 for mark in self .ribplot .insert_mark (x , self .ribplot .config .marks_controlpoint , insert = False ):
88124 controlpoints .append ((x , mark ))
89125
90- curve = self .rigidfoil .get_flattened (self .ribplot .rib , glider )
91-
92126 # add marks into the profile
93- self .ribplot .plotpart .layers [self .ribplot .layer_name_rigidfoils ].append (curve )
94127 self .ribplot .plotpart .layers [self .ribplot .layer_name_laser_dots ].append (euklid .vector .PolyLine2D ([curve .get (0 )]))
95128 self .ribplot .plotpart .layers [self .ribplot .layer_name_laser_dots ].append (euklid .vector .PolyLine2D ([curve .get (len (curve )- 1 )]))
96129
97- self .inner_curve , self .outer_curve = self ._get_inner_outer (glider )
98-
99- plotpart .layers [self .ribplot .layer_name_marks ].append (curve )
100-
101- back_cap = self .get_cap (- 1 , True )
130+ back_cap = self .get_cap ("back" )
102131 plotpart .layers [self .ribplot .layer_name_marks ].append (euklid .vector .PolyLine2D (list (back_cap [0 ])))
103132
104- front_cap = self .get_cap (0 , False )
133+ front_cap = self .get_cap ("front" )
105134 plotpart .layers [self .ribplot .layer_name_marks ].append (euklid .vector .PolyLine2D (list (front_cap [0 ])))
106135
107- outline = self . inner_curve
136+ outline = inner_curve
108137 outline += euklid .vector .PolyLine2D (list (back_cap [1 ]))
109- outline += self . outer_curve .reverse ()
138+ outline += outer_curve .reverse ()
110139 outline += euklid .vector .PolyLine2D (list (front_cap [1 ])).reverse ()
111140
112141 for x , controlpoint in controlpoints :
@@ -117,7 +146,7 @@ def flatten(self, glider: Glider) -> PlotPart:
117146
118147 plotpart .layers [self .ribplot .layer_name_outline ].append (outline .fix_errors ().close ())
119148
120- self .add_text (plotpart )
149+ self .add_text ()
121150
122151 return plotpart
123152
0 commit comments