Source code for openglider.glider.ballooning

#! /usr/bin/python2
# -*- coding: utf-8; -*-
#
# (c) 2013 booya (http://booya.at)
#
# This file is part of the OpenGlider project.
#
# OpenGlider is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# OpenGlider is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with OpenGlider.  If not, see <http://www.gnu.org/licenses/>.


__author__ = 'simon'

import numpy
from scipy.interpolate import interp1d
from openglider.utils.bezier import BezierCurve
#TODO ballooning -> amount (total(integral),maximal)


[docs]class Ballooning(object): def __init__(self, f_upper, f_lower): self.upper = f_upper self.lower = f_lower def __getitem__(self, xval): """Get Ballooning Value (%) for a certain XValue""" if -1 <= xval < 0: #return self.upper.xpoint(-xval)[1] return self.upper(-xval) elif 0 <= xval <= 1: #return -self.lower.xpoint(xval)[1] return self.lower(xval) else: ValueError("Ballooning only between -1 and 1") def __call__(self, arg): """Get Ballooning Arc (phi) for a certain XValue""" return self.phi(1. / (self[arg] + 1)) def __add__(self, other): """Add another Ballooning to this one, needed for merging purposes""" xup = self.upper.x # This is valid for scipy interpolations, no clue how to do different, if so... xlow = self.lower.x yup = [self.upper(i) + other.upper(i) for i in xup] ylow = [self.lower(i) + other.lower(i) for i in xlow] return Ballooning(interp1d(xup, yup), interp1d(xlow, ylow)) def __mul__(self, other): """Multiply Ballooning With a Value""" up = interp1d(self.upper.x, [i * other for i in self.upper.y]) low = interp1d(self.upper.x, [i * other for i in self.lower.y]) return Ballooning(up, low)
[docs] def copy(self): return Ballooning(self.upper, self.lower)
@staticmethod
[docs] def phi(*baloon): """Return the angle of the piece of cake. b/l=R*phi/(R*Sin(phi)) -> Phi=arsinc(l/b)""" global arsinc if not arsinc: interpolate_asinc() return arsinc(baloon)
[docs] def mapx(self, xvals): return [self[i] for i in xvals]
[docs] def amount_maximal(self): return max(max(self.upper.y), max(self.lower.y))
[docs] def amount_integral(self): # Integration of 2-points allways: amount = 0 for curve in [self.upper, self.lower]: for i in range(len(curve.x) - 2): # points: (x1,y1), (x2,y2) # _ p2 # p1_/ | # | | # |___| amount += (curve.y[i] + (curve.y[i + 1] - curve.y[i]) / 2) * (curve.x[i + 1] - curve.x[i]) return amount / 2
[docs] def amount_set(self, amount): factor = float(amount) / self.Amount self.upper.y = [i * factor for i in self.upper.y] self.lower.y = [i * factor for i in self.lower.y]
Amount = property(amount_maximal, amount_set)
[docs]class BallooningBezier(Ballooning): def __init__(self, points=None): if not points: points = [[[0, 0], [0.1, 0], [0.2, 0.14], [0.8, 0.14], [0.9, 0], [1, 0]], [[0, 0], [0.1, 0], [0.2, 0.14], [0.8, 0.14], [0.9, 0], [1, 0]]] self.upbez = BezierCurve(points[0]) self.lowbez = BezierCurve(points[1]) Ballooning.__init__(self, self.upbez.interpolation(), self.lowbez.interpolation()) def __mul__(self, other): # TODO: Check consistency """Multiplication of BezierBallooning""" # Multiplicate as normal interpolated ballooning, then refit return Ballooning.__mul__(self, other) #self.upper = temp.upper #self.lower = temp.lower #self.upbez.fit(numpy.transpose([self.upper.x, self.upper.y])) #self.lowbez.fit(numpy.transpose([self.lower.x, self.lower.y])) def _setnumpoints(self, numpoints): Ballooning.__init__(self, self.upbez.interpolation(numpoints), self.lowbez.interpolation(numpoints)) def _getnumpoints(self): return len(self.upper) Numpoints = property(_getnumpoints, _setnumpoints)
global arsinc arsinc = None
[docs]def interpolate_asinc(numpoints=1000, phi0=0, phi1=numpy.pi): """Set Global Interpolation Function arsinc""" global arsinc (x, y) = ([], []) for i in range(numpoints + 1): phi = phi1 + (i * 1. / numpoints) * (phi0 - phi1) # reverse for interpolation (increasing x_values) x.append(numpy.sinc(phi / numpy.pi)) y.append(phi) arsinc = interp1d(x, y) # TODO: Do only when needed!
interpolate_asinc()