def _fit(self, func, p, xargs, show): ''' Fit a pth-degree Curve through the data Points using the approximation function func and the extra argument xargs. ''' lo, up = [points_to_obj_mat(self.data[si]) for si in ('lo', 'up')] Q = np.vstack((lo[-1:0:-1], up)) i = self.intersection if i: xyzw = i.xyzw[np.newaxis, :] Q = np.vstack((xyzw, Q, xyzw)) r = Q.shape[0] - 1 args = (r, Q, p) + xargs U, Pw = func(*args) nurbs = Curve(ControlPolygon(Pw=Pw), (p, ), (U, )) print('geom.airfoil.Airfoil.fit :: ' 'fit with {} control points'.format(Pw.shape[0])) self._halve(nurbs) if not self.issharp: print('geom.airfoil.Airfoil.fit :: ' 'warning, fit but blunt airfoil') if show: d = self.get_curvature_cplots() d += self.data['lo'] + self.data['up'] if i: d += [i] fig = draw(self, *d, stride=0.1) fig.c.setup_preset('xz') return fig
def fit(self, r=100, n=50): ''' Sample and fit a B-spline function that shall fit a Wing such that it smoothly connects two other closely distanced Wings. Parameters ---------- r = the number of points to sample the Curves extensions with n = the number of control points to fit the sampled points with Returns ------- T = the trajectory Curve to use for the Wing transition B = the B-spline function B(v) ''' T0, T1 = self.Ts T = T0.copy() #T.cobj.Pw[:] = 0.75 * T0.cobj.Pw + 0.25 * T1.cobj.Pw us = np.linspace(0, 1, r) Q0 = T0.eval_points(us).T Q1 = T1.eval_points(us).T Q = np.zeros_like(Q0) Q[:,0] = Q1[:,0] - Q0[:,0] U, Pw = global_curve_approx_fixedn(r - 1, Q, 3, n, us) return T, Curve(ControlPolygon(Pw=Pw), (3,), (U,))
def fit(self, r=100, n=50, di=0): ''' Sample and fit a B-spline function that shall scale a Wing such that its XY planform view matches exactly the previously designed LE and TE Curves. Parameters ---------- r = the number of points to sample the LE and TE Curves with n = the number of control points to fit the sampled points with di = the sampling direction (0 or 2) Returns ------- B = the B-spline function B(v) ''' T0, T1 = self.Ts us = np.linspace(0, 1, r) Q0 = T0.eval_points(us).T Q1 = T1.eval_points(us).T Q = np.zeros_like(Q0) Q[:,0] = Q1[:,di] - Q0[:,di] U, Pw = global_curve_approx_fixedn(r - 1, Q, T0.p[0], n, us) return Curve(ControlPolygon(Pw=Pw), (T0.p[0],), (U,))
def intersect(self, CRT=5e-3, ANT=1e-2, show=True): ''' ''' P0 = find_LE_starting_point(self.wing.LE, self.S) print('geom.junction.TrimmedJunction.intersect :: ' 'LE starting point found: {}'.format(P0)) IP = [] for half, h in zip((0, 1), self.wing.halves): if self.half in (2, half): args = h, self.S, P0, CRT, ANT Q, stuv = surface_surface_intersect(*args) if show: Qw = obj_mat_to_4D(Q) IP += obj_mat_to_points(Qw).tolist() n = stuv.shape[0] - 1 z = np.zeros((n + 1, 1)) st = stuv[:,:2] Q = np.hstack((st, z)) U, Pw = local_curve_interp(n, Q) IC = Curve(ControlPolygon(Pw=Pw), (3,), (U,)) self.ICs[half] = IC if show: return draw(self.S, self.wing, *IP)
def __init__(self, end=(1.0, 1.0), p=1, n=2): ''' Instantiate a default representation Curve that linearly interpolates the end point values. Parameters ---------- end = the end point values p, n = the degree and number of control points to define the representation Curve with ''' Pw = np.zeros((n, 4)); Pw[:,-1] = 1.0 Pw[ 0,1] = end[0] Pw[-1,1] = end[1]; Pw[-1,0] = 1.0 if n > 2: xs = np.linspace(0, 1, n) ys = np.linspace(end[0], end[1], n) Pw[1:-1,0] = xs[1:-1] Pw[1:-1,1] = ys[1:-1] self.R = Curve(ControlPolygon(Pw=Pw), (p,)) self._p = p
def design(self): ''' Automatically create LE and TE Curve extensions attaching the two Wings. If not satisfied, the Wing objects can be repositioned before repeating the process. ''' w0, w1 = self.ws Q0, D0 = w0.LE.eval_derivatives(1, 1) Q1, D1 = w1.LE.eval_derivatives(0, 1) U, Pw = local_curve_interp(1, (Q0, Q1), D0, D1) T0 = Curve(ControlPolygon(Pw=Pw), (3,), (U,)) Q0, D0 = w0.TE.eval_derivatives(1, 1) Q1, D1 = w1.TE.eval_derivatives(0, 1) U, Pw = local_curve_interp(1, (Q0, Q1), D0, D1) T1 = Curve(ControlPolygon(Pw=Pw), (3,), (U,)) self.Ts = [T0, T1] return draw(w0, w1, T0, T1)
def fit(self, r=100, n=50): ''' Sample and fit the representation Curve. Parameters ---------- r = the number of points to sample the representation Curve with n = the number of control points to fit the sampled points with Returns ------- B = the B-spline function B(v) ''' us = np.linspace(0, 1, r) Q0 = self.R.eval_points(us).T Q = np.zeros_like(Q0) uk, Q[:,0] = Q0[:,0], Q0[:,1] U, Pw = global_curve_approx_fixedn(r - 1, Q, self._p, n, uk) return Curve(ControlPolygon(Pw=Pw), (self._p,), (U,))
def get_curvature_cplots(self, npt=500): ''' Get the curvature Curve plots corresponding to the lower and upper halves of the Airfoil. To ease inspection each Curve plot is clamped chordwise and vertically between 0 and 1. Parameters ---------- npt = the number of points to sample each halve with Returns ------- [Curve, Curve] = the lower and upper curvature Curve plots ''' if not self.nurbs: raise UnfitAirfoil() us = np.linspace(0, 1, npt) Cs = [] for h in self.halves: Q = np.zeros((npt, 3)) Q[:, 0] = us for i, u in enumerate(us): Q[i, 2] = h.eval_curvature(u) U, Pw = global_curve_interp(npt - 1, Q, 1, uk=us) c = Curve(ControlPolygon(Pw=Pw), (1, ), (U, )) sf1 = self.chord sf2 = 1.0 / max(c.cobj.Pw[:, 2]) w = self.nurbs.eval_point(0.5) w[1:] = 0.0 c.scale(sf1, L=(1, 0, 0)) c.scale(sf2, L=(0, 0, 1)) c.translate(w) c.visible.pop('cobj') Cs.append(c) Cs[0].mirror(N=(0, 0, 1)) return Cs
def _network(self, l, dl, xb, ul, vk): ''' Populate a smooth network of Curves suitable for interpolation in the Gordon sense. ''' wi = self.wing wh0, wh1 = wi.halves l *= wi.chords[1] / 100.0 dl *= wi.chords[1] / 100.0 xb *= 2.0 def fnc(x): return x**xb * (1 - x)**(2 - xb) mfnc = fnc(xb / 2.0) pairs = [(wh0.extract(u, 0), wh1.extract(u, 0)) for u in ul] Cl = [] for ip, pair in enumerate(pairs): P0, D0 = pair[0].eval_derivatives(1, 1) P2, D2 = pair[1].eval_derivatives(1, 1) Pm = (P0 + P2) / 2.0 W = normalize((D0 + D2) / 2.0) dli = fnc(ul[ip]) / mfnc * dl Pmi = Pm + (l + dli) * W Pw = obj_mat_to_4D(np.array((P0, Pmi, P2))) C = Curve(ControlPolygon(Pw=Pw), (1, )) if pair not in (pairs[0], pairs[-1]): N = np.cross(P2 - P0, W) D0 = point_to_plane((0, 0, 0), N, D0) D2 = point_to_plane((0, 0, 0), N, D2) P1, w1 = make_one_arc(P0, D0, P2, D2, Pmi) Pw = obj_mat_to_4D(np.array((P0, P1, P2))) if w1 != 0.0: Pw[1, :] *= w1 else: # infinite point Pw[1, -1] = 0.0 C2 = Curve(ControlPolygon(Pw=Pw), (2, )) C2 = refit_curve(C2, 15) #knob n, dummy, dummy, CC2 = make_curves_compatible1([C, C2]) C, C2 = CC2 # linear morphing for i in xrange(1, n): lmy = np.sin(np.pi * float(i - 1) / float(n - 2)) cpt, cpt2 = [c.cobj.cpts[i].xyz for c in C, C2] x, y, z = lmy * cpt + (1.0 - lmy) * cpt2 C.cobj.cpts[i].xyzw = x, y, z, 1.0 Cl.append(C) Ck0 = wh0.extract(1, 1) Ck2 = wh1.extract(1, 1) Q = np.array([C.eval_point(0.5) for C in Cl]) r = Q.shape[0] - 1 U, Pw = global_curve_interp(r, Q, 3, ul) Ck1 = Curve(ControlPolygon(Pw=Pw), (3, ), (U, )) Ck = [Ck0, Ck1, Ck2] return Ck, Cl
class BSplineFunctionCreator1(BSplineFunctionCreator): ''' Create a Type 1 B-spline function B(v). Just like any y = f(x) function, a Type 1 B-spline scaling function is best visualized in a XY coordinate system; here the X axis refers to v, (0 <= v <= 1), and the Y axis to B. The idea is to design a so-called "representation Curve" in this plane, sample it at evenly spaced parameter values, and then finally fit the sampled points to retrieve the actual B(v). The best way to understand this is to simply try it. Intended usage -------------- >>> Bs = BSplineFunctionCreator1(end=(1.0,2.0)) >>> Bs.design() # optional >>> B = Bs.fit() ''' def __init__(self, end=(1.0, 1.0), p=1, n=2): ''' Instantiate a default representation Curve that linearly interpolates the end point values. Parameters ---------- end = the end point values p, n = the degree and number of control points to define the representation Curve with ''' Pw = np.zeros((n, 4)); Pw[:,-1] = 1.0 Pw[ 0,1] = end[0] Pw[-1,1] = end[1]; Pw[-1,0] = 1.0 if n > 2: xs = np.linspace(0, 1, n) ys = np.linspace(end[0], end[1], n) Pw[1:-1,0] = xs[1:-1] Pw[1:-1,1] = ys[1:-1] self.R = Curve(ControlPolygon(Pw=Pw), (p,)) self._p = p def design(self): ''' Design the representation Curve interactively. The first and last control points are constrained to the (x = 0) and (x = 1) lines, respectively. ''' cpts = self.R.cobj.cpts cpt0, cpt1 = cpts[0], cpts[-1] cpt0.line = (0,0,0), (0,1,0) cpt1.line = (1,0,0), (0,1,0) fig = draw(self.R) fig.c.setup_preset(r=(0,0,0)) return fig def fit(self, r=100, n=50): ''' Sample and fit the representation Curve. Parameters ---------- r = the number of points to sample the representation Curve with n = the number of control points to fit the sampled points with Returns ------- B = the B-spline function B(v) ''' us = np.linspace(0, 1, r) Q0 = self.R.eval_points(us).T Q = np.zeros_like(Q0) uk, Q[:,0] = Q0[:,0], Q0[:,1] U, Pw = global_curve_approx_fixedn(r - 1, Q, self._p, n, uk) return Curve(ControlPolygon(Pw=Pw), (self._p,), (U,))