Esempio n. 1
0
    def blend(self, eps=1.0, show=True):
        ''' Blend all boundary and inner Curves to produce N smooth
        Surfaces.

        Parameters
        ----------
        eps = the tolerance on geometric continuity (in degrees)
        show = whether or not to draw the blended Surfaces

        Returns
        -------
        fig = a Figure

        '''

        if not self.CIk:
            raise UndesignedFiller(self)
        self.BLRk = generate_inner_cross_deriv_nsided_region(
            self.CN.xyz, self.CIk, self.CLRk)
        self.nurbs = make_nsided_region(self.CLRk, self.DLRk, self.CIk,
                                        self.BLRk, eps)

        self.glue()
        O = self.O
        self.O = None
        if O is not None:
            self.C.translate(O)
        self.unglue()

        self.colorize()
        if show:
            return draw(self)
Esempio n. 2
0
 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
Esempio n. 3
0
    def trim(self, show=True):

        '''

        '''

        if not any(self.ICs):
            raise Exception

        for half, h, IC in zip((0, 1), self.wing.halves, self.ICs):
            if not self.half in (2, half):
                continue
            U, V = h.U
            if not self.tip:
                jnc1 = self.wing.junctions[1]
                if (not jnc1) or (jnc1 and not jnc1.ICs[half]):
                    P0 = IC.cobj.cpts[ 0]
                    P1 = IC.cobj.cpts[-1]
                    P2 = Point(U[-1], V[-1])
                    P3 = Point(U[ 0], V[-1])
                    C0 = IC
                    C1 = make_linear_curve(P1, P2)
                    C2 = make_linear_curve(P2, P3)
                    C3 = make_linear_curve(P3, P0)
                else:
                    IC1 = jnc1.ICs[half]
                    P0 = IC.cobj.cpts[ 0]
                    P1 = IC.cobj.cpts[-1]
                    P2 = IC1.cobj.cpts[-1]
                    P3 = IC1.cobj.cpts[ 0]
                    C0 = IC
                    C1 = make_linear_curve(P1, P2)
                    C2 = IC1.reverse()
                    C3 = make_linear_curve(P3, P0)
            else:
                jnc0 = self.wing.junctions[0]
                if (not jnc0) or (jnc0 and not jnc0.ICs[half]):
                    P0 = Point(U[ 0], V[0])
                    P1 = Point(U[-1], V[0])
                    P2 = IC.cobj.cpts[-1]
                    P3 = IC.cobj.cpts[ 0]
                    C0 = make_linear_curve(P0, P1)
                    C1 = make_linear_curve(P1, P2)
                    C2 = IC
                    C3 = make_linear_curve(P3, P0)
                else:
                    IC0 = jnc0.ICs[half]
                    P0 = IC0.cobj.cpts[ 0]
                    P1 = IC0.cobj.cpts[-1]
                    P2 = IC.cobj.cpts[-1]
                    P3 = IC.cobj.cpts[ 0]
                    C0 = IC0
                    C1 = make_linear_curve(P1, P2)
                    C2 = IC.reverse()
                    C3 = make_linear_curve(P3, P0)
            IC = make_composite_curve([C0, C1, C2, C3], remove=False)
            h.trim(IC)

        if show:
            return draw(self.S, self.wing)
Esempio n. 4
0
    def finalize(self, d=1e-2, show=True):
        ''' Perform some post-processing steps on the OML Surface.  This
        should only be called after having applied all molders (but
        obviously before creating other objects that depend on the final
        Fuselage's shape, such as Junctions).

        For now, this method is just a wrapper around
        nurbs.surface.Surface.removes, which removes as many control
        points as possible up to a given tolerance.

        Parameters
        ----------
        d = the maximum deviation allowed from the current OML Surface
        show = whether or not to draw the new, simplified OML Surface

        Returns
        -------
        fig = a Figure

        '''

        if self._nurbs:
            n = self._nurbs
        else:
            n = self.nurbs
            self._nurbs = n.copy()
        e, n = n.removes(2, d=d)
        print('geom.fuselage.Fuselage.finalize :: '
              '{} control points removed (u, v)'.format(e))
        self.nurbs = n
        self.clamp()
        if show:
            return draw(self)
Esempio n. 5
0
    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)
Esempio n. 6
0
    def revolve(self, D, ang=0.0, show=True):

        n = self.airfoil.nurbs.reverse()
        n.mirror(N=[0, 0, 1])
        n.translate([0, 0, -D / 2.0])

        S, T = [0, 0, 0], [-1, 0, 0]
        nurbs = make_revolved_surface_rat(n, S, T, 360)
        #nurbs = make_revolved_surface_nrat(n, S, T, 360)
        #if ang != 0.0:
        #    rad = np.deg2rad(ang)
        #    N = [np.cos(rad), 0, np.sin(rad)]
        #    n, dummy = nurbs.cobj.n
        #    for i in xrange(n + 1):
        #        Pw = nurbs.cobj.Pw[i]
        #        L0 = Pw[0,:3]
        #        P = intersect_line_plane(L0, [1,0,0], [0,0,0], N)
        #        sf = (L0[0] - P[0]) / L0[0]
        #        scale(Pw, sf, L0, (1,0,0))
        hs = nurbs.split(0.5, 1)

        self.nurbs = nurbs
        self.halves = hs
        self.D = D
        if show:
            return draw(self)
Esempio n. 7
0
    def read_patch(self, patch_file='patch.con', show=True):

        ''' Pre: Grid, Map '''

        self.ptch = []
        self.stch = []

        with open(patch_file) as fh:

            fh.readline()
            fh.readline()
            nptch = int(fh.readline())
            fh.readline()
            fh.readline()

            for ip in xrange(nptch):
                line = read_line_split(fh)
                im, side, dof = line[1:]
                map, udi = self.blk[im-1].map, self.EXTRACTMAP[side]
                ptch = map.extract(*udi)
                ptch = Patch(ptch.cobj, ptch.p, ptch.U)
                ptch.indx = ip + 1
                ptch.map = im
                ptch.side = side
                ptch.dof = dof
                self.ptch.append(ptch)

            fh.readline()
            fh.readline()
            nstch = int(fh.readline())
            fh.readline()
            fh.readline()

            for i in xrange(nstch):
                line = read_line_split(fh)
                ip, edge, di = (np.zeros(2, dtype='i'),
                                np.zeros(2, dtype='i'),
                                np.zeros(2, dtype='i'))
                typ, dof, conty, ip[0], edge[0], di[0] = line[1:]
                if typ == 0:
                    line = read_line_split(fh)
                    ip[1], edge[1], di[1] = line
                ptch, udi = self.ptch[ip[0]-1], self.EXTRACTMAP[edge[0]]
                stch = ptch.extract(*udi)
                stch = Stitch(stch.cobj, stch.p, stch.U)
                stch.indx = i + 1
                stch.joined = True if typ == 0 else False
                stch.dof = dof
                stch.conty = conty
                stch.ptch = ip
                stch.edge = edge
                stch.dir = di
                self.stch.append(stch)

        self._colorize()
        if show:
            return draw(*(self.stch+self.ptch))
Esempio n. 8
0
    def orient(self, T, Tw=None, m=10, show=True):

        ''' Generate an orientation function to the trajectory Curve T.

        An orientation function is one that, as its name suggests,
        orients the root/tip Airfoils along T during the sweeping
        process (see nurbs.surface.make_swept_surface and Wing.fit).

        It is initialized via the projection normal method located in
        nurbs.surface.get_sweep_orient_func.  Note that here this
        function is restricted in such a way that the Airfoil instances
        taken along T (once translated) are only allowed to rotate about
        the X axis (plus twist, if any).  This is to ensure that
        ultimately each spanwise cross-section of a fitted Wing lies in
        its own plane whose normal has no X component.

        Parameters
        ----------
        T = the trajectory Curve
        Tw = the B-spline twisting function, if any
        m = the number of points to construct the orientation function
            with
        show = whether or not to draw the orientation vectors

        Returns
        -------
        fig = a Figure

        Examples
        --------
        >>> T = nurbs.tb.make_linear_curve(Point(), Point(y=3))
        >>> tw = BSplineFunctionCreator1(end=(0.0,90.0)).fit()
        >>> wi.orient(T, Tw=tw)

        '''

        T = T.copy()
        if Tw:
            Tw = Tw.copy()

        U, = T.U; normalize_knot_vec(U)
        T0 = T.eval_derivatives(0, 1)[1]; T0[0] = 0
        B0 = np.cross(T0, (-1,0,0))
        Bv = get_sweep_orient_func(B0, T, (1,0,0), Tw, m)

        self.T, self.Tw, self.Bv = T, Tw, Bv
        if show:
            vb = np.linspace(0, 1, m)
            O, B = np.zeros((2, m, 3))
            for i, v in enumerate(vb):
                O[i], B[i] = T.eval_point(v), Bv.eval_point(v)
            V = O + 0.2 * B # knob
            O = obj_mat_to_points(obj_mat_to_4D(O)).tolist()
            V = obj_mat_to_points(obj_mat_to_4D(V)).tolist()
            for v in V:
                v.color = (0, 255, 255, 255)
            return draw(T, *(O + V))
Esempio n. 9
0
    def read_connectivity(self, con_file='grid.con', show=True):

        ''' Pre: Grid '''

        def read_line(query_type=True):
            line = read_line_split(fh)
            dit = np.array(line[-6:]).reshape((2,3))
            typ = line[-9] if query_type else 0
            blk, side = line[-8:-6]
            return typ, blk, side, dit

        self.iface = []
        self.bcface = []

        with open(con_file) as fh:

            fh.readline()
            fh.readline()
            nblk = int(fh.readline()); fh.readline()
            nsfc = int(fh.readline()); fh.readline()
            nifc = int(fh.readline())
            fh.readline()
            fh.readline()

            assert nblk == len(self.blk)

            i0, i1 = 1, 1
            for i in xrange(nsfc):
                typ, ib, side, dit = read_line()
                blk, udi = self.blk[ib-1], self.EXTRACTMAP[side]
                face = blk.extract(*udi)
                if typ > 0:
                    bcface = Boundary(face.cobj, face.p, face.U)
                    bcface.indx = i0; i0 += 1
                    bcface.type = typ
                    bcface.blk  = ib
                    bcface.side = side
                    bcface.dit  = dit
                    self.bcface.append(bcface)
                    continue
                dummy, ib1, side1, dit1 = read_line(False)
                iface = Interface(face.cobj, face.p, face.U)
                iface.indx = i1; i1 += 1
                iface.type = 0
                iface.blk  = np.array([ib, ib1])
                iface.side = np.array([side, side1])
                iface.dit1 = dit
                iface.dit2 = dit1
                self.iface.append(iface)

        assert((nsfc == len(self.bcface) + len(self.iface)) and
               (nifc == len(self.iface)))

        self._colorize()
        if show:
            return draw(self)
Esempio n. 10
0
    def setup(self, nlcpt=50, cap=True, show=True):
        ''' Setup the NURBS representation of the initial bullet head
        cylinder.  Analogous to modelling clay, it is this NURBS Surface
        that will be successively shaped by molders.

        Parameters
        ----------
        nlcpt = the number of longitudinal control points used to
                represent the cylinder with
        cap = whether or not to close the rear-end gap with a rounded
              Surface; for geometries destined for inviscid flow
              simulations this flag should be set to False
        show = whether or not to draw the newly setup cylinder

        Returns
        -------
        fig = a Figure

        '''

        R, BL, NL = self.R, self.BL, self.NL

        O, X, Y = [0, 0, 0], [-1, 0, 0], [0, 0, -1]
        args = (O, X, Y, NL, R, 0, np.pi / 2.0)
        P0, P1 = Point(0, 0, -R), Point(BL, 0, -R)

        nose = make_ellipse(*args)
        body = make_linear_curve(P0, P1)
        for c in nose, body:
            reparam_arc_length_curve(c)

        n = make_composite_curve([nose, body])
        n = refit_curve(n, nlcpt, num=50000)
        n2, = n.cobj.n
        for i in xrange(n2 + 1):
            Pw = n.cobj.Pw[i]
            if Pw[0] > 0 or Pw[2] < -R:
                Pw[2] = -R

        if cap:
            P2 = Point(BL, 0, 0)
            rear = make_linear_curve(P1, P2)
            reparam_arc_length_curve(rear)
            n = make_composite_curve([n, rear])

        n = make_revolved_surface_nrat(n, O, [1, 0, 0], 180)

        if not cap:
            n.cobj.Pw[:, -1, 1] = 0.0

        self.nurbs = n
        self.molders = []
        self.clamp()
        if show:
            return draw(self)
Esempio n. 11
0
    def fill(self, l=5.0, dl=2.0, xb=0.35, ntip=20, show=True):
        ''' Fill the Wingtip with a Gordon Surface.

        The Gordon Surface (see nurbs.surface.make_gordon_surface) is
        interpolated from an automatically generated bi-directional
        Curve network.

        Aside from the number of v-directional Curves to compose the
        network with, ntip, the user is free to vary any of the other
        three shape parameters: l, dl and xb.

                  \                                 /
                   \             Wing              /
                    \                             /
                     \________ tip chord ________/_
                      \  \  \      |      /  /  / |
             ntip = 7  \  \  \  Wingtip  /  /  /  | l
                        \__\__\____|____/__/__/   v
                                                  | dl
                                       xb <-----| v

        Parameters
        ----------
        l = the length of the Wingtip extension, in tip chord
            percentage
        dl = the delta, in tip chord percentage, to supplement l with;
             this actually varies according to the smooth funtion:

             [ x ** 2*xb ] * [ (1.0 - x) ** (2.0 - 2*xb) ]

        xb = the location, between 0 and 1, where that function takes on
             a maximum
        ntip = the number of v-directional cross-sections used to
               construct the Curve network; in the u-direction, that
               number is fixed to 3
        show = whether or not to draw the filled Wingtip

        Returns
        -------
        fig = a Figure

        '''

        ul = np.linspace(0, 1, ntip)
        vk = np.linspace(0, 1, 3)
        Ck, Cl = self._network(l, dl, xb, ul, vk)
        nurbs = make_gordon_surface(Ck, Cl, ul, vk)
        nurbs = nurbs.reverse(0)
        self._halve(nurbs)
        self._hs = [h.copy() for h in self.halves]
        self.Ck, self.Cl = Ck, Cl
        if show:
            return draw(self, self.wing, *(Ck + Cl))
Esempio n. 12
0
    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
Esempio n. 13
0
    def attach(self):

        '''

        '''

        wing, S = self.wing, self.S
        U, V = S.U
        b0 = S.extract(U[ 0], 0)
        b1 = S.extract(U[-1], 0)
        b2 = S.extract(V[ 0], 1)
        b3 = S.extract(V[-1], 1)
        fig = draw(b0, b1, b2, b3, wing)
        fig.m.toggle_mode('_AttachWingJunctionMode')
        fig.m.mode.junction = self
        return fig
Esempio n. 14
0
    def extend(self, l=0.0, show=True):

        '''

        '''

        wing, nurbs = self.wing, self._nurbs
        if l != 0.0:
            u = arc_length_to_param(wing.QC, l)
            ne = nurbs.extend(u, 1, end=self.tip)
            nn = (ne, nurbs) if not self.tip else (nurbs, ne)
            nc = make_composite_surface(nn, reorient=False)
            normalize_knot_vec(nc.U[1])
            wing._halve(nc)
        if show:
            return draw(self.S, self.wing)
Esempio n. 15
0
    def design(self):

        ''' Design a Wing's planform by manipulating the TE Curve in the
        XY plane (and/or the YZ plane if vertical scaling is desired).
        The LE Curve should remain untouched.

        '''

        T0, T1 = self.Ts
        cpts = [cpt for T in (T0, T1) for cpt in T.cobj.cpts]
        for cpt in cpts:
            if hasattr(cpt, 'line'):
                del cpt.line
            cpt.plane = cpt.xyz, (0,1,0)
        T1.colorize()
        fig = draw(T0, T1)
        fig.c.setup_preset('xy')
        return fig
Esempio n. 16
0
    def design(self, show=True):
        ''' Design the Filler's default entities, i.e. its inner Curves,
        its central Point and/or normal vector.  All of these will have
        a direct impact on the shape of the resultant blended NURBS
        patches.  Choose them wisely!

        Parameters
        ----------
        show = whether or not to interactively design the Filler

        Returns
        -------
        fig = a Figure

        '''

        self.nurbs = []
        self.unglue()
        self._originate()
        if show:
            return draw(self, self.C, self.CN, *self.CIk)
Esempio n. 17
0
    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)
Esempio n. 18
0
    def merge(self, hf, reverse, l=None, show=True):

        ''' Similar to WingMerger.  The idea here is however to merge
        only one half of each Wing, thus allowing the other half of a
        merged Wing to be reused in a subsequent merge with another
        HalfWingMerger.  This design allows to build Wings of virtually
        any topology.

        By default each Wing's root is merged at the tip of the previous
        Wing's tip; if this is not possible or the present Wings'
        orientation do not allow for it, the user can specify so by
        means of the `reverse` list (see example below).

        Parameters
        ----------
        hf = the half of the Wings to be merged (0 for lower or 1 for
             upper)
        reverse = the boolean list specifying whether or not a Wing's
                  orientation should be temporarily reversed
        l = same as WingMerger
        show = same as WingMerger

        Returns
        -------
        fig = a Figure

        Examples
        --------
        >>> w1 = w0.copy() # w0 being a Wing object
        >>> w2 = w0.copy()
        >>> w1.glue(); w1.dihedral = 90; w1.unglue()

        >>> hwm = HalfWingMerger(w0, w1)
        >>> hwm.merge(0, [False, True], None)
        >>> w0m, w1m = hwm.merged_wings

        >>> hwm = HalfWingMerger(w1m, w2)
        >>> hwm.merge(0, [False, False], None)
        >>> w1m, w2m = hwm.merged_wings

        '''

        self.merged_wings = []

        Cas, hfo = [], np.mod(hf + 1, 2)
        for w1, r in zip(self.wings, reverse):

            h1s = w1.halves
            w1._halve(w1.nurbs)

            hf1 = hf if r else hfo
            w1.halves[hf1] = h1s[hf1]

            if not self.merged_wings:
                if r:
                    self._reverse_half(w1, hfo if r else hf1)
                self.merged_wings.append(w1)
                continue

            w0 = self.merged_wings[-1]
            self.merged_wings.append(w1)

            afr0, aft0 = w0.airfoils
            afr1, aft1 = w1.airfoils

            af0 = aft0 if aft0 else afr0
            af1 = afr1

            if not (af0.issymmetric or af1.issymmetric):
                print('geom.wing.WingMerger.merge :: '
                      'warning, tip airfoil(s) not symmetric')

            hf0 = hfo if (w1 is self.wings[1] and reverse[0]) else hf
            hf1 = hfo if r else hf

            if r: self._reverse_half(w1, hf1)

            # Step 1: translate w1, if necessary
            self._translate(w0, w1)

            # Step 2: force the approximation to stay within l (wrt the QC)
            Cas += self._segment(w0, w1, hf0, hf1, l)

            # Step 3: shear w0 and w1 equally, if necessary
            self._shear(w0, w1, hf0, hf1)

            if r: self._reverse_half(w1, hf1)

        Ns = []
        for mw, r in zip(self.merged_wings, reverse):
            Ns.append(mw.halves[hfo if r else hf])

        Ns = make_surfaces_compatible3(Ns, di=0)

        for mw, r, N in zip(self.merged_wings, reverse, Ns):
            mw.halves[hfo if r else hf] = N

        if reverse[0]:
            w0 = self.merged_wings[0]
            self._reverse_half(w0, hfo)

        if show:
            return draw(self, *Cas)
Esempio n. 19
0
    def merge(self, l=None, show=True):

        ''' Merge all Wings in sequential order.

        This is done by first forcing the to-be merged Wing to be
        spatially compatible with the last merged Wing, and then by
        finding the intersection Curve between the two.  In general,
        such an intersection Curve does not exist, and thus an
        approximation to the Wing's Surfaces immediately before and
        after the intersection is built.  Outside that interval
        (delimited by the Curves drawn if letting show=True) the Wing's
        Surfaces are kept intact.

        Note that the merged Wings are *copies* of those used to
        instantiate the WingMerger; they are however stored in the same
        order.

        Parameters
        ----------
        l = if not None, the (approximate) length before and after which
            two merged Wings are approximated
        show = whether or not to draw the merged Wings with Curves
               delimiting their reapproximations

        Returns
        -------
        fig = a Figure

        '''

        self.merged_wings = []

        Cas = []
        for w1 in self.wings:

            w1._halve(w1.nurbs)

            if not self.merged_wings:
                self.merged_wings.append(w1)
                continue

            w0 = self.merged_wings[-1]
            self.merged_wings.append(w1)

            afr0, aft0 = w0.airfoils
            afr1, aft1 = w1.airfoils

            n0 = aft0.nurbs if aft0 else afr0.nurbs
            n1 = afr1.nurbs

            for hf in (0, 1):

                # Step 1: translate w1, if necessary
                self._translate(w0, w1)

                # Step 2: force the approximation to stay within l (wrt the QC)
                Cas += self._segment(w0, w1, hf, hf, l)

                # Step 3: shear w0 and w1 equally, if necessary
                self._shear(w0, w1, hf, hf)

        for hf in (0, 1):
            Ns = [mw.halves[hf] for mw in self.merged_wings]
            Ns = make_surfaces_compatible3(Ns, di=0)
            for mw, N in zip(self.merged_wings, Ns):
                mw.halves[hf] = N

        for mw in self.merged_wings:
            mw._size()

        if show:
            return draw(self, *Cas)
Esempio n. 20
0
    def fit(self, K=1, scs=(None, None, None), show=True):

        ''' Fit (sweep) the root/tip Airfoils along the Wing's
        trajectory Curve T with optional scaling.

        Use BSplineFunctionCreators if you do end up applying scaling.
        Recall that an Airfoil is defined in the XZ plane only,
        therefore applying Y-directional scaling won't affect the Wing.
        This method also uses the orientation function previously
        determined by Wing.orient.

        Note that for nonlinear Wings (in sweep, dihedral, twist, etc.),
        only an approximation is constructed.  As explained in
        nurbs.surface.make_swept_surface, a better approximation can be
        obtained by increasing the value of K.  As a rule of thumb, a
        fit is considered good when, while facing the YZ plane, each
        spanwise row of control points of the Wing falls on a straight
        line.

        Parameters
        ----------
        K + 1 = the (minimum) number of Airfoil instances taken along T
        scs = the B-spline scaling functions, if any (a 3-tuple
              corresponding to scaling in X, Y and Z, respectively)
        show = whether or not to draw the swept Wing

        Returns
        -------
        fig = a Figure

        Examples
        --------
        >>> sc = BSplineFunctionCreator1(end=(2.0,1.0)).fit()
        >>> wi.fit(K=5, scs=(sc,None,sc))

        '''

        if not self.T:
            raise UnorientedWing()

        scs = [(sc.copy() if sc else None) for sc in scs]
        if any(scs):
            q, = self.T.p
            if q == 1:
                q = np.array([sc.p[0] for sc in scs if sc])
                if (q > 1).any():
                    print('geom.wing.Wing.fit :: '
                          'warning, linear sweep with nonlinear scaling')

        self.tip = None
        self.junctions = [None, None]
        self.structure = None

        afr, aft = self.airfoils
        args = afr.nurbs, self.T, self.Bv, K, scs
        if aft:
            args += aft.nurbs,
        nurbs = make_swept_surface(*args, local=get_sweep_local_sys_proj)
        self._halve(nurbs)

        self.scs = scs
        if show:
            return draw(self, self.T)