Skip to content

Commit cf1f005

Browse files
committed
add holes to miniribs
1 parent 7169319 commit cf1f005

File tree

3 files changed

+114
-109
lines changed

3 files changed

+114
-109
lines changed

openglider/glider/parametric/table/cell/miniribs.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,19 @@ class MiniRibDTO(DTO):
1212
trailing_edge_cut: Length | Percentage
1313
material_code: str
1414

15-
def get_object(self) -> Any:
15+
def get_object(self) -> MiniRib:
1616
return MiniRib(yvalue=self.y_value.si, front_cut=self.front_cut.si, back_cut=self.back_cut.si, trailing_edge_cut=self.trailing_edge_cut, material_code=self.material_code)
17+
18+
class MiniRibWithHoles(MiniRibDTO):
19+
hole_num: int
20+
def get_object(self) -> MiniRib:
21+
result = super().get_object()
22+
result.hole_num = self.hole_num
23+
24+
return result
1725

1826
class MiniRibTable(CellTable):
1927
dtos = {
20-
"MINIRIB": MiniRibDTO
28+
"MINIRIB": MiniRibDTO,
29+
"MINIRIB6": MiniRibWithHoles
2130
}

openglider/glider/rib/crossports.py

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,41 @@ def get_centers(self, rib: Rib, scale: bool=False) -> list[euklid.vector.Vector2
116116
return [self._get_points(rib)[0]]
117117

118118

119+
def polygon(points: list[euklid.vector.Vector2D], corner_size: float, num_points) -> euklid.vector.PolyLine2D:
120+
segments = []
121+
122+
def get_point(index: int) -> euklid.vector.Vector2D:
123+
if index >= len(points):
124+
index -= len(points)
125+
126+
return points[index]
127+
128+
for i in range(len(points)):
129+
p1 = get_point(i)
130+
p2 = get_point(i+1)
131+
p3 = get_point(i+2)
132+
133+
segments.append([
134+
p1 + (p2-p1) * (1-corner_size/2),
135+
p2,
136+
p2 + (p3-p2) * (corner_size/2)
137+
])
138+
139+
sequence = []
140+
for i, segment in enumerate(segments):
141+
sequence += euklid.spline.BSplineCurve(segment).get_sequence(num_points).nodes
142+
143+
if corner_size < 1:
144+
if i+1 >= len(segments):
145+
segment2 = segments[0]
146+
else:
147+
segment2 = segments[i+1]
148+
149+
sequence += [segment[-1], segment2[0]]
150+
151+
return euklid.vector.PolyLine2D(sequence).resample(num_points)
152+
153+
119154
class PolygonHole(RibHoleBase):
120155
points: list[euklid.vector.Vector2D]
121156
corner_size: float=1
@@ -130,45 +165,14 @@ def get_centers(self, rib: Rib, scale: bool=False) -> list[euklid.vector.Vector2
130165
return centers
131166

132167
def _get_curves(self, rib: Rib, num: int=160) -> list[euklid.vector.PolyLine2D]:
133-
segments = []
134-
135-
def get_point(index: int) -> euklid.vector.Vector2D:
136-
if index >= len(self.points):
137-
index -= len(self.points)
138-
139-
return self.points[index]
140-
141-
for i in range(len(self.points)):
142-
p1 = get_point(i)
143-
p2 = get_point(i+1)
144-
p3 = get_point(i+2)
145-
146-
segments.append([
147-
p1 + (p2-p1) * (1-self.corner_size/2),
148-
p2,
149-
p2 + (p3-p2) * (self.corner_size/2)
150-
])
151-
152-
sequence = []
153-
for i, segment in enumerate(segments):
154-
sequence += euklid.spline.BSplineCurve(segment).get_sequence(num).nodes
155-
156-
if self.corner_size < 1:
157-
if i+1 >= len(segments):
158-
segment2 = segments[0]
159-
else:
160-
segment2 = segments[i+1]
161-
162-
sequence += [segment[-1], segment2[0]]
163-
164-
return [euklid.vector.PolyLine2D(sequence).resample(num)]
168+
return [polygon(self.points, self.corner_size, num)]
165169

166170

167171
class RibSquareHole(RibHoleBase):
168172
x: Percentage
169173
width: Percentage | Length
170174
height: Percentage
171-
corner_size: float = 1
175+
corner_size: float = 1
172176

173177
def get_centers(self, rib: Rib, scale: bool=False) -> list[euklid.vector.Vector2D]:
174178
width = rib.convert_to_percentage(self.width)

openglider/glider/rib/minirib.py

Lines changed: 66 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
from __future__ import annotations
22

3-
from typing import TYPE_CHECKING, ClassVar
3+
from typing import TYPE_CHECKING
44
import euklid
55
import logging
6+
import pyfoil
67

78
from openglider.airfoil import Profile3D
89
from openglider.utils.dataclass import dataclass, Field
910
from openglider.mesh import Mesh, triangulate
1011
from openglider.vector.unit import Length, Percentage
12+
from openglider.glider.rib.crossports import polygon
1113

1214
if TYPE_CHECKING:
1315
from openglider.glider.cell import Cell
@@ -26,9 +28,10 @@ class MiniRib:
2628
trailing_edge_cut: Length = Length("20mm")
2729
mrib_num: int = 0
2830
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
31+
hole_num: int = 0
32+
hole_border_side : Length | Percentage = Length("2cm")
33+
hole_border_panel: Length | Percentage = Length("2cm")
34+
hole_curve_factor: float = 0.5
3235

3336

3437
class Config:
@@ -63,11 +66,14 @@ def get_multiplier(self, x: float) -> float:
6366
else:
6467
return 1.
6568

66-
def convert_to_percentage(self, value: Percentage | Length) -> Percentage:
69+
def rib_chord(self, cell: Cell) -> float:
70+
return cell.rib1.chord*(1-self.yvalue) + cell.rib2.chord*self.yvalue
71+
72+
def convert_to_percentage(self, value: Percentage | Length, cell: Cell) -> Percentage:
6773
if isinstance(value, Percentage):
6874
return value
6975

70-
return Percentage(value.si/self.chord)
76+
return Percentage(value.si/self.rib_chord(cell))
7177

7278
def get_offset_outline(self, cell:Cell, margin: Percentage | Length) -> pyfoil.Airfoil:
7379
profile_3d = self.get_profile_3d(cell)
@@ -91,21 +97,11 @@ def get_profile_3d(self, cell: Cell) -> Profile3D:
9197

9298
return cell.rib_profiles_3d[self.mrib_num+1]
9399

94-
95-
96-
def convert_to_percentage(self, value: Percentage | Length, cell:Cell) -> Percentage:
97-
if isinstance(value, Percentage):
98-
return value
99-
chord = cell.rib1.chord*(1-self.yvalue) + cell.rib2.chord*self.yvalue
100-
return Percentage(value.si/chord)
101-
102100
def convert_to_chordlength(self, value: Percentage | Length, cell:Cell) -> Length:
103101
if isinstance(value, Length):
104102
return value
105103

106-
chord = cell.rib1.chord*(1-self.yvalue) + cell.rib2.chord*self.yvalue
107-
108-
return Length(value.si*chord)
104+
return Length(value.si*self.rib_chord(cell))
109105

110106
def _get_lengths(self, cell: Cell) -> tuple[float, float]:
111107
flattened_cell = cell.get_flattened_cell()
@@ -184,8 +180,6 @@ def get_mesh(self, cell:Cell, filled: bool=True, max_area: float=None, hole_res:
184180
vertices+= hole_vertices
185181
boundary.append([start_index + i for i in hole_indices])
186182

187-
188-
189183
if not filled:
190184
segments = []
191185
for lst in boundary:
@@ -213,72 +207,70 @@ def get_mesh(self, cell:Cell, filled: bool=True, max_area: float=None, hole_res:
213207
return minirib_mesh
214208

215209

216-
def get_holes(self, cell: Cell, points: int=40) -> tuple[list[euklid.vector.PolyLine2D], list[euklid.vector.Vector2D]]:
217-
210+
def get_holes(self, cell: Cell, num_points: int=140) -> tuple[list[euklid.vector.PolyLine2D], list[euklid.vector.Vector2D]]:
211+
if self.hole_num < 1:
212+
return [], []
218213
nodes_top, nodes_bottom = self.get_nodes(cell)
219214

220-
len_top=nodes_top.get_length()
221-
len_bot=nodes_bottom.get_length()
215+
# add border on top / bottom
216+
offset = self.convert_to_chordlength(self.hole_border_panel, cell)
217+
top_curve = nodes_top.reverse().offset(offset)
218+
bottom_curve = nodes_bottom.offset(-offset)
219+
220+
# check for intersection between offset lines
221+
try:
222+
cut = top_curve.cut(bottom_curve, len(top_curve.nodes)-1)
223+
top_curve = top_curve.get(0, cut[0])
224+
bottom_curve = bottom_curve.get(0, cut[1])
225+
except RuntimeError:
226+
pass
222227

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)))
228+
# helper functions to get points on minirib
229+
len_top=top_curve.get_length()
230+
len_bot=bottom_curve.get_length()
226231

227-
return p1 + (p2-p1)*y
232+
def to_percentage(length: Length | Percentage):
233+
if isinstance(length, Percentage):
234+
return length
235+
236+
return Percentage(length.si/len_top)
237+
238+
def get_top(x: float) -> euklid.vector.Vector2D:
239+
return top_curve.get(top_curve.walk(0, len_top*x))
228240

241+
def get_bottom(x: float) -> euklid.vector.Vector2D:
242+
return bottom_curve.get(bottom_curve.walk(0, len_bot*x))
243+
229244
holes = []
230245
centers = []
246+
247+
end = self.back_cut if self.back_cut is not None else 1.
231248

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-
249+
if self.trailing_edge_cut is not None:
250+
end -= to_percentage(self.trailing_edge_cut).si
272251

273-
]
252+
border_holes = to_percentage(self.hole_border_side).si
274253

275-
centers = [
254+
total_border = (self.hole_num + 1) * border_holes
255+
hole_width = (1 - total_border) / self.hole_num
276256

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),
257+
x_left = border_holes
258+
259+
# draw holes
260+
for _ in range(self.hole_num):
261+
x_right = x_left + hole_width
262+
x_center = (x_left+x_right)/2
263+
264+
points = [
265+
get_bottom(x_left),
266+
get_bottom(x_right),
267+
get_top(x_right),
268+
get_top(x_left)
281269
]
282270

283-
return holes, centers
271+
holes.append(polygon(points, self.hole_curve_factor, num_points))
272+
centers.append((get_top(x_center) + get_bottom(x_center))* 0.5)
284273

274+
x_left = x_right + border_holes
275+
276+
return holes, centers

0 commit comments

Comments
 (0)