1- from typing import Any
1+ from typing import Any , ClassVar
22
33import euklid
44import enum
55
66from openglider .glider .shape import Shape
77from openglider .utils .cache import cached_property
8+ from openglider .utils .dataclass import BaseModel
9+ from openglider .vector .unit import Angle , Length , Percentage , Quantity
810
9- class FreeCurve :
11+ class CurveBase (BaseModel ):
12+ unit : str | None = None
13+ interpolation : euklid .vector .Interpolation
14+ shape : Shape
15+
16+ def to_unit (self , value : float ) -> Quantity | float :
17+ if self .unit is None :
18+ return value
19+
20+ if self .unit in Angle .unit_variants or self .unit == Angle .unit :
21+ return Angle (value , unit = self .unit )
22+ if self .unit in Length .unit_variants or self .unit == Length .unit :
23+ return Length (value , unit = self .unit )
24+ if self .unit in Percentage .unit_variants :
25+ return Percentage (value , self .unit )
26+
27+ raise ValueError ()
28+
29+ class FreeCurve (CurveBase ):
1030 def __init__ (self , points : list [euklid .vector .Vector2D ], shape : Shape ):
11- self .shape = shape
12- self .interpolation = euklid .vector .Interpolation (points )
31+ super ().__init__ (
32+ shape = shape ,
33+ interpolation = euklid .vector .Interpolation (points )
34+ )
1335
1436 @property
1537 def controlpoints (self ) -> list [euklid .vector .Vector2D ]:
@@ -67,11 +89,12 @@ def to_controlpoints(self, points: list[euklid.vector.Vector2D]) -> list[euklid.
6789 def points_2d (self ) -> list [euklid .vector .Vector2D ]:
6890 return self .to_2d (self .interpolation .nodes )
6991
70- def get (self , rib_no : int ) -> float :
92+ def get (self , rib_no : int ) -> float | Quantity :
7193 if rib_no == 0 and self .shape .has_center_cell :
7294 rib_no = 1
7395
74- return self .interpolation .get_value (rib_no )
96+ value = self .interpolation .get_value (rib_no )
97+ return self .to_unit (value )
7598
7699 def draw (self ) -> euklid .vector .PolyLine2D :
77100 x_values = [p [0 ] for p in self .controlpoints ]
@@ -92,11 +115,12 @@ def draw(self) -> euklid.vector.PolyLine2D:
92115 return euklid .vector .PolyLine2D (self .to_2d ([euklid .vector .Vector2D ([x , self .interpolation .get_value (x )]) for x in x_values_lst ]))
93116
94117
95- class Curve :
96- upper = False
118+ class Curve (CurveBase ):
97119 def __init__ (self , points : list [euklid .vector .Vector2D ], shape : Shape ):
98- self .interpolation = euklid .vector .Interpolation (points )
99- self .shape = shape
120+ super ().__init__ (
121+ interpolation = euklid .vector .Interpolation (points ),
122+ shape = shape
123+ )
100124
101125 @property
102126 def controlpoints (self ) -> list [euklid .vector .Vector2D ]:
@@ -154,16 +178,13 @@ def points_2d(self) -> euklid.vector.PolyLine2D:
154178 self .shape .get_point (* p ) for p in self .interpolation .nodes
155179 ])
156180
157- def get (self , rib_no : int ) -> float :
181+ def get (self , rib_no : int ) -> float | Quantity :
158182 if rib_no == 0 and self .shape .has_center_cell :
159183 rib_no = 1
160184
161185 y = self .interpolation .get_value (rib_no )
162186
163- if self .upper :
164- y = - y
165-
166- return y
187+ return self .to_unit (y )
167188
168189 def draw (self ) -> euklid .vector .PolyLine2D :
169190 x_values = [p [0 ] for p in self .controlpoints ]
@@ -181,7 +202,19 @@ def draw(self) -> euklid.vector.PolyLine2D:
181202 if end % 1 :
182203 x_values_lst .append (end )
183204
184- points = [self .shape .get_point (x , self .get (x )) for x in x_values_lst ]
205+ percentage_lst : list [Percentage | float ] = []
206+ for x in x_values_lst :
207+ y = self .get (x )
208+ if not isinstance (y , (Percentage , float )):
209+ raise ValueError ()
210+
211+ percentage_lst .append (y )
212+
213+ for p in percentage_lst :
214+ if not isinstance (p , (Percentage , float )):
215+ raise ValueError ()
216+
217+ points = [self .shape .get_point (x , y ) for x , y in zip (x_values_lst , percentage_lst )]
185218
186219 if start == 1 and self .shape .has_center_cell :
187220 points .insert (0 , points [0 ] * euklid .vector .Vector2D ([- 1 ,1 ]))
@@ -191,8 +224,7 @@ def draw(self) -> euklid.vector.PolyLine2D:
191224
192225
193226class ShapeCurve (Curve ):
194-
195- def get (self , rib_no : int ) -> float :
227+ def get (self , rib_no : int ) -> float | Quantity :
196228 if rib_no == 0 and self .shape .has_center_cell :
197229 rib_no = 1
198230
@@ -203,17 +235,11 @@ def get(self, rib_no: int) -> float:
203235 if len (results ) != 1 :
204236 raise Exception (f"wrong number of cut results: { len (results )} " )
205237
206- return results [0 ][1 ]
238+ return self . to_unit ( results [0 ][1 ])
207239
208240
209241class ShapeBSplineCurve (ShapeCurve ):
210- curve_cls = euklid .spline .BSplineCurve
211-
212- def __init__ (self , points : list [euklid .vector .Vector2D ], shape : Shape , curve_cls : Any = None ):
213- if curve_cls is not None :
214- self .curve_cls = curve_cls
215-
216- super ().__init__ (points , shape )
242+ curve_cls : ClassVar [type ] = euklid .spline .BSplineCurve
217243
218244 @cached_property ('shape' , 'interpolation' )
219245 def points_2d (self ) -> euklid .vector .PolyLine2D :
0 commit comments