Skip to content

Commit

Permalink
use ParametricShape and ArcCurve in ParametricGlider
Browse files Browse the repository at this point in the history
  • Loading branch information
hiaselhans committed Jan 7, 2016
1 parent d2a6ba7 commit 3a79a1c
Show file tree
Hide file tree
Showing 14 changed files with 207 additions and 212 deletions.
2 changes: 1 addition & 1 deletion openglider/glider/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from openglider.glider.glider import Glider
from openglider.glider.parametric.glider import Glider2D
from openglider.glider.parametric.glider import ParametricGlider
from openglider.glider.project import GliderProject
from openglider.glider import cell
from openglider.glider import rib
Expand Down
2 changes: 1 addition & 1 deletion openglider/glider/parametric/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from __future__ import division

from openglider.glider.parametric.glider import Glider2D
from openglider.glider.parametric.glider import ParametricGlider
from openglider.glider.parametric.lines import LineSet2D, UpperNode2D
7 changes: 7 additions & 0 deletions openglider/glider/parametric/arc.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,10 @@ def get_rib_angles(self, x_values):
rib_angles.append(cell_angles[-1])

return rib_angles

def rescale(self, x_values):
span = x_values[-1]
arc_pos = self.get_arc_positions(x_values)
arc_length = arc_pos.get_length() + arc_pos[0][0] # add center cell
factor = span/arc_length
self.curve.controlpoints = [p * factor for p in self.curve.controlpoints]
18 changes: 9 additions & 9 deletions openglider/glider/parametric/export_ods.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

def export_ods_2d(glider, filename):
doc = ezodf.newdoc(doctype="ods", filename=filename)
assert isinstance(glider, openglider.glider.parametric.glider.Glider2D)
assert isinstance(glider, openglider.glider.parametric.glider.ParametricGlider)

doc.sheets.append(get_geom_sheet(glider))
doc.sheets.append(get_cell_sheet(glider))
Expand Down Expand Up @@ -46,14 +46,14 @@ def get_airfoil_sheet(glider_2d):


def get_geom_sheet(glider_2d):
geom_page = ezodf.Sheet(name="geometry", size=(glider_2d.half_cell_num + 2, 10))
geom_page = ezodf.Sheet(name="geometry", size=(glider_2d.shape.half_cell_num + 2, 10))

# rib_nos
geom_page[0, 0].set_value("Ribs")
for i in range(1, glider_2d.half_cell_num+2):
for i in range(1, glider_2d.shape.half_cell_num+2):
geom_page[i, 0].set_value(i)

shape = glider_2d.half_shape
shape = glider_2d.shape.get_half_shape()

geom_page[0, 1].set_value("Chord")
for i, chord in enumerate(shape.chords):
Expand All @@ -67,7 +67,7 @@ def get_geom_sheet(glider_2d):

geom_page[0, 4].set_value("Arc")
last_angle = 0
cell_angles = ArcCurve(glider_2d.arc).get_cell_angles(glider_2d.rib_x_values)
cell_angles = glider_2d.arc.get_cell_angles(glider_2d.shape.rib_x_values)
for i, angle in enumerate(cell_angles):
this_angle = angle * 180/math.pi

Expand All @@ -82,7 +82,7 @@ def get_geom_sheet(glider_2d):
aoa_int = glider_2d.aoa.interpolation(num=100)
profile_int = glider_2d.profile_merge_curve.interpolation(num=100)
ballooning_int = glider_2d.ballooning_merge_curve.interpolation(num=100)
for rib_no, x in enumerate(glider_2d.rib_x_values):
for rib_no, x in enumerate(glider_2d.shape.rib_x_values):
geom_page[rib_no+1, 5].set_value(aoa_int(x)*180/math.pi)
geom_page[rib_no+1, 6].set_value(0)
geom_page[rib_no+1, 7].set_value(0)
Expand All @@ -93,7 +93,7 @@ def get_geom_sheet(glider_2d):


def get_cell_sheet(glider):
row_num = glider.half_cell_num
row_num = glider.shape.half_cell_num
sheet_name = "Cell Elements"
sheet = ezodf.Sheet(name=sheet_name, size=(row_num+1, 1))
elems = glider.elements
Expand Down Expand Up @@ -155,7 +155,7 @@ def get_cell_sheet(glider):


def get_rib_sheet(glider):
row_num = glider.half_cell_num + 1
row_num = glider.shape.half_cell_num + 1
sheet_name = "Rib Elements"
sheet = ezodf.Sheet(name=sheet_name, size=(row_num+1, 1))
elems = glider.elements
Expand All @@ -178,7 +178,7 @@ def get_rib_sheet(glider):
column += 2

# attachment points
per_rib = [glider.lineset.get_upper_nodes(rib_no) for rib_no in range(glider.half_rib_num)]
per_rib = [glider.lineset.get_upper_nodes(rib_no) for rib_no in range(glider.shape.half_rib_num)]
max_points = max([len(p) for p in per_rib])

for rib_no, nodes in enumerate(per_rib):
Expand Down
155 changes: 33 additions & 122 deletions openglider/glider/parametric/glider.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@
from openglider.glider.parametric.export_ods import export_ods_2d
from openglider.glider.parametric.import_ods import import_ods_2d
from openglider.glider.parametric.lines import LineSet2D, UpperNode2D
from openglider.glider.parametric.shape import ParametricShape
from openglider.glider.rib import RibHole, RigidFoil, Rib
from openglider.glider.shape import Shape
from openglider.vector import PolyLine2D, Interpolation
from openglider.vector.spline import SymmetricBezier, Bezier


class Glider2D(object):
class ParametricGlider(object):
"""
A parametric (2D) Glider object used for gui input
"""
Expand All @@ -25,15 +26,11 @@ class Glider2D(object):
num_cell_dist = 30
num_depth_integral = 100

def __init__(self, front, back, cell_dist, cell_num,
arc, aoa, profiles, profile_merge_curve,
def __init__(self, shape, arc, aoa, profiles, profile_merge_curve,
balloonings, ballooning_merge_curve, lineset,
speed, glide, zrot, elements=None):
self.zrot = zrot or aoa
self.front = front
self.back = back
self.cell_num = cell_num # updates cell pos
self.cell_dist = cell_dist
self.shape = shape
self.arc = arc
self.aoa = aoa
self.profiles = profiles or []
Expand All @@ -47,10 +44,7 @@ def __init__(self, front, back, cell_dist, cell_num,

def __json__(self):
return {
"front": self.front,
"back": self.back,
"cell_dist": self.cell_dist,
"cell_num": self.cell_num,
"shape": self.shape,
"arc": self.arc,
"aoa": self.aoa,
"zrot": self.zrot,
Expand All @@ -76,23 +70,9 @@ def v_inf(self):
angle = np.arctan(1/self.glide)
return np.array([-np.cos(angle), 0, np.sin(angle)]) * self.speed

@property
def has_center_cell(self):
return self.cell_num % 2

@property
def half_cell_num(self):
return self.cell_num // 2 + self.has_center_cell

@property
def half_rib_num(self):
return self.half_cell_num + 1

@property
def arc_positions(self):
arc_curve = ArcCurve(self.arc)

return arc_curve.get_arc_positions(self.rib_x_values)
return self.arc.get_arc_positions(self.shape.rib_x_values)

def get_arc_angles(self, arc_curve=None):
"""
Expand All @@ -104,70 +84,25 @@ def get_arc_angles(self, arc_curve=None):

return arc_curve.get_rib_angles(self.rib_x_values)

@property
def half_shape(self):
"""
Return shape of the glider:
[ribs, front, back]
"""
num = self.num_shape
front_int = self.front.interpolation(num=num)
back_int = self.back.interpolation(num=num)
dist = self.rib_x_values
front = [[x, front_int(x)] for x in dist]
back = [[x, back_int(x)] for x in dist]

return Shape(PolyLine2D(front), PolyLine2D(back))

@property
def shape(self):
"""
Return shape of the glider:
[ribs, front, back]
"""
return self.half_shape.copy_complete()

@property
def ribs(self):
num = self.num_interpolate_ribs
front_int = self.front.interpolation(num=num)
back_int = self.back.interpolation(num=num)

dist = self.rib_x_values
front = [[x, front_int(x)] for x in dist]
back = [[x, back_int(x)] for x in dist]
if self.has_center_cell:
front.insert(0, [-front[0][0], front[0][1]])
back.insert(0, [-back[0][0], back[0][1]])

return list(zip(front, back))

def get_shape_point(self, rib_no, x):
ribs = list(self.ribs)
rib = ribs[rib_no]
return rib[0][0], rib[0][1] + x * (rib[1][1] - rib[0][1])

def set_span(self, span=None):
"""
rescale BezierCurves to given span (or front-line)
"""
span = span or self.front.controlpoints[-1][0]
span = span or self.span

self.shape.span = span
self.arc.rescale(self.shape.rib_x_values)

def set_span(attribute):
el = getattr(self, attribute)
assert el is not None, "Not a Beziercurve: {}".format(attribute)
factor = span/el.controlpoints[-1][0]
el.controlpoints = [[p[0]*factor, p[1]] for p in el.controlpoints]

for attr in ('back', 'front', 'cell_dist', 'aoa',
'profile_merge_curve', 'ballooning_merge_curve'):
for attr in ('aoa', 'profile_merge_curve', 'ballooning_merge_curve'):
set_span(attr)

arc_pos = self.arc_positions
arc_length = arc_pos.get_length() + arc_pos[0][0] # add center cell
factor = span/arc_length
self.arc.controlpoints = [[p[0]*factor, p[1]*factor]
for p in self.arc.controlpoints]


@property
def cell_dist_controlpoints(self):
Expand All @@ -178,21 +113,6 @@ def cell_dist_controlpoints(self, arr):
x0 = self.front.controlpoints[-1][0]
self.cell_dist.controlpoints = [[0, 0]] + arr + [[x0, 1]]

@property
def cell_dist_interpolation(self):
"""
Interpolate Cell-distribution
"""
data = self.cell_dist.get_sequence(self.num_cell_dist)
interpolation = Interpolation([[p[1], p[0]] for p in data])
start = self.has_center_cell / self.cell_num
num = self.cell_num // 2 + 1
return [[interpolation(i), i] for i in np.linspace(start, 1, num)]

@property
def rib_x_values(self):
return [p[0] for p in self.cell_dist_interpolation]

@property
def depth_integrated(self):
"""
Expand Down Expand Up @@ -383,11 +303,11 @@ def symmetric_fit(polyline, numpoints=numpoints):

# TODO: lineset, dist-curce->xvalues

return cls(front=front_bezier,
back=back_bezier,
cell_dist=rib_distribution,
cell_num=cell_num,
arc=arc_bezier,
parametric_shape = ParametricShape(front, back, rib_distribution, cell_num)
parametric_arc = ArcCurve(arc_bezier)

return cls(shape=parametric_shape,
arc=parametric_arc,
aoa=aoa_bezier,
zrot=zrot,
profiles=profiles,
Expand All @@ -396,28 +316,25 @@ def symmetric_fit(polyline, numpoints=numpoints):
ballooning_merge_curve=ballooning_dist,
glide=glider.glide,
speed=10,
lineset=LineSet2D([]),
zrot=zrot)
lineset=LineSet2D([]))

def get_glider_3d(self, glider=None, num=50):
"""returns a new glider from parametric values"""
glider = glider or Glider()
ribs = []

span = self.front.controlpoints[-1][0]
self.set_span(span)
self.rescale_curves()

x_values = self.rib_x_values
x_values = self.shape.rib_x_values
shape_ribs = self.shape.ribs

front_int = self.front.interpolation(num=num)
back_int = self.back.interpolation(num=num)
profile_merge_curve = self.profile_merge_curve.interpolation(num=num)
ballooning_merge_curve = self.ballooning_merge_curve.interpolation(num=num)
aoa_int = self.aoa.interpolation(num=num)
zrot_int = self.zrot.interpolation(num=num)

arc_pos = list(self.arc_positions)
arc_angles = self.get_arc_angles()
arc_pos = list(self.arc.get_arc_positions(x_values))
rib_angles = self.arc.get_rib_angles(x_values)

profile_x_values = self.profiles[0].x_values

Expand All @@ -427,9 +344,10 @@ def get_glider_3d(self, glider=None, num=50):
cell_centers = [(p1+p2)/2 for p1, p2 in zip(x_values[:-1], x_values[1:])]

for rib_no, pos in enumerate(x_values):
front = front_int(pos)
back = back_int(pos)
front, back = shape_ribs[rib_no]
arc = arc_pos[rib_no]
startpoint = np.array([-front[1], arc[0], arc[1]])
chord = abs(front[1]-back[1])
factor = profile_merge_curve(abs(pos))
profile = self.get_merge_profile(factor)
profile.x_values = profile_x_values
Expand All @@ -439,9 +357,9 @@ def get_glider_3d(self, glider=None, num=50):

ribs.append(Rib(
profile_2d=profile,
startpoint=np.array([-front, arc[0], arc[1]]),
chord=abs(front - back),
arcang=arc_angles[rib_no],
startpoint=startpoint,
chord=chord,
arcang=rib_angles[rib_no],
glide=self.glide,
aoa_absolute=aoa_int(pos),
zrot=zrot_int(pos),
Expand All @@ -451,7 +369,7 @@ def get_glider_3d(self, glider=None, num=50):
))
ribs[-1].aoa_relative = aoa_int(pos)

if self.has_center_cell:
if self.shape.has_center_cell:
ribs.insert(0, ribs[0].copy())
ribs[0].arcang *= -1
ribs[0].pos[1] *= -1
Expand Down Expand Up @@ -494,8 +412,7 @@ def scale(self, x=1, y=1):

def rescale_curves(self):
#span = self.span
#span = self.shape.span
span = self.front.controlpoints[-1][0]
span = self.shape.span

def rescale(curve):
span_orig = curve.controlpoints[-1][0]
Expand All @@ -504,28 +421,22 @@ def rescale(curve):

rescale(self.ballooning_merge_curve)
rescale(self.profile_merge_curve)
rescale(self.cell_dist)
rescale(self.aoa)

@property
def flat_area(self):
return self.shape.area

def set_flat_area(self, value, fixed="aspect_ratio"):
area = self.flat_area
if fixed == "aspect_ratio":
factor = np.sqrt(value/area)
self.scale(x=factor, y=factor)
if fixed == "span":
self.scale(y=value / area)
self.shape.set_area(value, fixed=fixed)

@property
def aspect_ratio(self):
return self.span ** 2 / self.flat_area

@property
def span(self):
return 2 * self.rib_x_values[-1]
return 2 * self.shape.span

def set_aspect_ratio(self, value, fixed="span"):
ar0 = self.aspect_ratio
Expand Down
Loading

0 comments on commit 3a79a1c

Please sign in to comment.