Esempio n. 1
0
string PropGeom::BuildBEMResults()
{
    // Calculate prop center and normal vector
    vec3d cen = m_ModelMatrix.xform( vec3d( 0, 0, 0 ) );
    vec3d norm = m_ModelMatrix.xform( vec3d( -1.0, 0, 0 ) ) - cen;

    int n = m_TessU();

    //==== Create Results ====//
    Results* res = ResultsMgr.CreateResults( "PropBEM" );
    res->Add( NameValData( "Num_Sections", n ) );
    res->Add( NameValData( "Num_Blade", m_Nblade() ) );
    res->Add( NameValData( "Diameter", m_Diameter() ) );
    res->Add( NameValData( "Beta34", m_Beta34() ) );
    res->Add( NameValData( "Feather", m_Feather() ) );
    res->Add( NameValData( "Center", cen ) );
    res->Add( NameValData( "Normal", norm ) );

    double rfirst = m_ChordCurve.GetRFirst();
    double rlast = m_ChordCurve.GetRLast();

    // Establish points to evaluate sections at.
    vector < double > vtess;
    m_MainSurfVec[0].MakeVTess( m_TessW(), vtess, m_CapUMinTess(), false );

    vector < double > r_vec(n);
    vector < double > chord_vec(n);
    vector < double > twist_vec(n);
    vector < double > rake_vec(n);
    vector < double > skew_vec(n);

    double rspan = rlast - rfirst;
    for ( int i = 0; i < n; i++ )
    {
        double t = static_cast < double > ( i ) / ( n - 1 );
        double r = rfirst + rspan * Cluster( t, m_RootCluster(), m_TipCluster() );
        double u = m_rtou.CompPnt( r );

        VspCurve c;
        m_FoilSurf.GetUConstCurve( c, u );
        vec3d v = c.CompPnt( 0 );
        c.OffsetZ( -v.z() );

        vector < vec3d > pts;
        c.Tesselate( vtess, pts );

        vector < double > xpts( pts.size() );
        vector < double > ypts( pts.size() );

        for ( int j = 0; j < pts.size(); j++ )
        {
            xpts[j] = pts[j].x();
            ypts[j] = pts[j].y();
        }

        char str[255];
        sprintf( str, "%03d", i );
        res->Add( NameValData( "XSection_" + string( str ), xpts ) );
        res->Add( NameValData( "YSection_" + string( str ), ypts ) );

        r_vec[i] = r;
        chord_vec[i] = m_ChordCurve.Comp( r );
        twist_vec[i] = m_TwistCurve.Comp( r );
        rake_vec[i] = m_RakeCurve.Comp( r );
        skew_vec[i] = m_SkewCurve.Comp( r );
    }

    res->Add( NameValData( "Radius", r_vec ) );
    res->Add( NameValData( "Chord", chord_vec ) );
    res->Add( NameValData( "Twist", twist_vec ) );
    res->Add( NameValData( "Rake", rake_vec ) );
    res->Add( NameValData( "Skew", skew_vec ) );

    return res->GetID();
}
Esempio n. 2
0
//==== Update Fuselage And Cross Section Placement ====//
void PropGeom::UpdateSurf()
{
    int nxsec = m_XSecSurf.NumXSec();

    double radius = m_Diameter() / 2.0;

    double rfirst = 0.0;
    double rlast = 1.0;

    vector < double > uvec( nxsec );
    vector < double > rvec( nxsec );

    double rev = 1.0;
    if ( m_ReverseFlag() )
    {
        rev = -1.0;
    }

    //==== Update XSec Location/Rotation ====//
    for ( int i = 0 ; i < nxsec ; i++ )
    {
        PropXSec* xs = ( PropXSec* ) m_XSecSurf.FindXSec( i );

        if ( xs )
        {
            if ( xs->GetXSecCurve()->GetType() == XS_POINT )
            {
                printf( "Warning: XS_POINT type not valid for propellers\n" );
                // Propellers are constructed in two phases.  The first phase stacks
                // all the XSecs with unit chord.  Intermediate curves are extracted
                // from that surface and are scaled to match the required chord.
                // Since XS_POINT XSecs already have zero chord, they mess up this
                // process.
            }

            //==== Reset Group Names ====//
            xs->SetGroupDisplaySuffix( i );

            //==== Set X Limits ====//
            EnforceOrder( xs, i );

            xs->SetRefLength( radius );

            bool first = false;
            bool last = false;

            if( i == 0 ) first = true;
            else if( i == (nxsec-1) ) last = true;

            if ( first )
            {
                rfirst = xs->m_RadiusFrac();
            }
            if ( last )
            {
                rlast = xs->m_RadiusFrac();
            }

            uvec[i] = i;
            rvec[i] = xs->m_RadiusFrac();
        }
    }

    m_rtou = Vsp1DCurve();
    m_rtou.InterpolateLinear( uvec, rvec, false );

    EnforcePCurveOrder( rfirst, rlast );

    // Set lower limit for activity factor integration limit
    m_AFLimit.SetLowerLimit( rfirst );
    // Integrate activity factor.
    m_AF.Set( m_ChordCurve.IntegrateAF( m_AFLimit() ) );
    m_AF.Deactivate();

    if ( m_UseBeta34Flag() == 1 )
    {
        if ( rfirst <= 0.75 )
        {
            double theta34 = m_TwistCurve.Comp( 0.75 );
            m_Feather = m_Beta34() - theta34;
        }
        else
        {
            m_Feather = m_Beta34();
        }
        m_Beta34.Activate();
        m_Feather.Deactivate();
    }
    else
    {
        if ( rfirst <= 0.75 )
        {
            double theta34 = m_TwistCurve.Comp( 0.75 );
            m_Beta34 = m_Feather() + theta34;
        }
        else
        {
            m_Beta34 = m_Feather();
        }
        m_Beta34.Deactivate();
        m_Feather.Activate();
    }

    // Set up fold axis & store for visualization.
    Matrix4d fold, foldrot;
    fold.loadIdentity();
    fold.rotateY( m_AzimuthFoldDir() );
    fold.rotateX( m_ElevationFoldDir() );
    m_FoldAxDirection = fold.xform( vec3d( 0, 0, 1 ) );
    m_FoldAxOrigin = vec3d( m_AxialFoldAxis() * radius, m_RadFoldAxis() * radius, m_OffsetFoldAxis() * radius );

    //==== Cross Section Curves & joint info ====//
    vector< VspCurve > crv_vec;
    crv_vec.resize( nxsec );

    //==== Update XSec Location/Rotation ====//
    for ( int i = 0 ; i < nxsec ; i++ )
    {
        PropXSec* xs = ( PropXSec* ) m_XSecSurf.FindXSec( i );

        if ( xs )
        {
            XSecCurve* xsc = xs->GetXSecCurve();

            double r = xs->m_RadiusFrac();
            double w = m_ChordCurve.Comp( r ) * radius;

            if ( xsc )
            {
                //==== Find Width Parm ====//
                string width_id = xsc->GetWidthParmID();
                Parm* width_parm = ParmMgr.FindParm( width_id );

                piecewise_curve_type pwc;

                if ( width_parm )
                {
                    width_parm->Deactivate();

                    Airfoil* af = dynamic_cast < Airfoil* > ( xsc );
                    if ( af )
                    {
                        width_parm->Set( 1.0 );
                        xs->GetXSecCurve()->SetFakeWidth( w );
                        xs->GetXSecCurve()->SetUseFakeWidth( true );
                        pwc = xs->GetCurve().GetCurve();
                        xs->GetXSecCurve()->SetUseFakeWidth( false );
                        width_parm->Set( w );
                    }
                    else
                    {
                        CircleXSec* cir = dynamic_cast < CircleXSec* > ( xsc );
                        if ( cir )
                        {
                            width_parm->Set( 1.0 );
                            pwc = xs->GetCurve().GetCurve();
                            width_parm->Set( w );
                        }
                        else
                        {
                            double h = xs->GetXSecCurve()->GetHeight();
                            xsc->SetWidthHeight( 1.0, h/w );
                            pwc = xs->GetCurve().GetCurve();
                            xsc->SetWidthHeight( w, h );
                        }
                    }

                }
                else
                {
                    pwc = xs->GetCurve().GetCurve();
                }

                // Set up prop positioner for highlight curves - not lofting.
                xs->m_PropPos.m_ParentProp = GetXSecSurf( 0 );
                xs->m_PropPos.m_Radius = r * radius;
                xs->m_PropPos.m_Chord = w;
                xs->m_PropPos.m_Twist = m_TwistCurve.Comp( r );
                xs->m_PropPos.m_XRotate = 0.0;
                xs->m_PropPos.m_ZRotate = atan( -m_RakeCurve.Compdt( r ) ) * 180.0 / PI;

                xs->m_PropPos.m_Rake = m_RakeCurve.Comp( r ) * radius;
                xs->m_PropPos.m_Skew = m_SkewCurve.Comp( r ) * radius;
                xs->m_PropPos.m_PropRot = m_Rotate();
                xs->m_PropPos.m_Feather = m_Feather();

                xs->m_PropPos.m_FoldOrigin = m_FoldAxOrigin;
                xs->m_PropPos.m_FoldDirection = m_FoldAxDirection;
                xs->m_PropPos.m_FoldAngle = m_FoldAngle();

                xs->m_PropPos.m_Reverse = rev;

                crv_vec[i].SetCurve( pwc );
            }
        }
    }

    // This surface linearly interpolates the airfoil sections without
    // any other transformations.
    // These sections can be extracted (as u-const curves) and then
    // transformed to their final position before skinning.
    m_FoilSurf = VspSurf();
    m_FoilSurf.SkinC0( crv_vec, false );

    // Find the union of stations required to approximate the blade parameters
    // with cubic functions.
    vector < double > tmap = rvec;  // Initialize with specified XSecs.
    vector < double > tdisc;
    tdisc.push_back( rfirst );
    tdisc.push_back( rlast );
    for ( int i = 0; i < m_pcurve_vec.size(); i++ )
    {
        vector < double > tm;
        vector < double > tmout;
        vector < double > td;
        m_pcurve_vec[i]->GetTMap( tm, td );

        std::set_union( tmap.begin(), tmap.end(), tm.begin(), tm.end(), std::back_inserter(tmout), &aboutcomp );
        std::swap( tmout, tmap );
    }

    // Not sure why above set_union leaves duplicate entries, but
    // sort and force unique just to be sure.
    std::sort( tmap.begin(), tmap.end() );
    auto tmit = std::unique( tmap.begin(), tmap.end(), &abouteq );
    tmap.erase( tmit, tmap.end() );

    // Treat all control points as possible discontinuities.
    tdisc = tmap;

    // Refine by adding two intermediate points to each cubic section
    // this is needed because the adaptive algorithm above uses derivatives
    // while our later reconstruction does not.
    vector < double > tref( ( tmap.size() - 1 ) * 3 + 1 );
    for ( int i = 0; i < tmap.size() - 1; i++ )
    {
        int iref = 3*i;
        double t = tmap[i];
        double tnxt = tmap[i+1];
        double dt = (tnxt-t)/3.0;

        tref[iref] = t;
        tref[iref+1] = t + dt;
        tref[iref+2] = t + 2 * dt;
    }
    tref.back() = tmap.back();
    std::swap( tmap, tref );

    // Convert tdisc to final parameterization.
    for ( int i = 0; i < tdisc.size(); i++ )
    {
        tdisc[i] = ( tdisc[i] - rfirst ) / ( rlast - rfirst );
    }

    // Pseudo cross sections
    // Not directly user-controlled, but an intermediate step in lofting the
    // surface.
    int npseudo = tmap.size();

    vector < rib_data_type > rib_vec( npseudo );
    vector < double > u_pseudo( npseudo );
    for ( int i = 0; i < npseudo; i++ )
    {
        // Assume linear interpolation means linear u/r relationship.
        double r = tmap[i];
        double u = m_rtou.CompPnt( r );

        VspCurve c;
        m_FoilSurf.GetUConstCurve( c, u );
        vec3d v = c.CompPnt( 0 );
        c.OffsetZ( -v.z() );

        PropPositioner pp;

        pp.m_ParentProp = this->GetXSecSurf( 0 );
        pp.m_Radius = r * radius;

        pp.m_Chord = m_ChordCurve.Comp( r ) * radius;
        pp.m_Twist = m_TwistCurve.Comp( r );

        pp.m_XRotate = 0.0;
        pp.m_ZRotate = atan( -m_RakeCurve.Compdt( r ) ) * 180.0 / PI;

        pp.m_Rake = m_RakeCurve.Comp( r ) * radius;
        pp.m_Skew = m_SkewCurve.Comp( r ) * radius;

        pp.m_PropRot = m_Rotate();
        pp.m_Feather = m_Feather();

        pp.m_FoldOrigin = m_FoldAxOrigin;
        pp.m_FoldDirection = m_FoldAxDirection;
        pp.m_FoldAngle = m_FoldAngle();

        pp.m_Reverse = rev;

        // Set a bunch of other pp variables.
        pp.SetCurve( c );
        pp.Update();

        rib_vec[i].set_f( pp.GetCurve().GetCurve() );
        u_pseudo[i] = ( r - rfirst ) / ( rlast - rfirst );
    }

    m_MainSurfVec.resize( 1 );
    m_MainSurfVec.reserve( m_Nblade() );

    m_MainSurfVec[0].SetMagicVParm( false );
    m_MainSurfVec[0].SkinCubicSpline( rib_vec, u_pseudo, tdisc, false );

    m_MainSurfVec[0].SetMagicVParm( true );
    m_MainSurfVec[0].SetSurfType( PROP_SURF );
    m_MainSurfVec[0].SetClustering( m_LECluster(), m_TECluster() );
    m_MainSurfVec[0].SetFoilSurf( &m_FoilSurf );

    if ( m_XSecSurf.GetFlipUD() )
    {
        m_MainSurfVec[0].FlipNormal();
    }

    if ( this->m_ReverseFlag() )
    {
        m_MainSurfVec[0].FlipNormal();
    }

    // UpdateEndCaps here so we only have to cap one blade.
    UpdateEndCaps();

    m_MainSurfVec.resize( m_Nblade(), m_MainSurfVec[0] );

    // Duplicate capping variables
    m_CapUMinSuccess.resize( m_Nblade(), m_CapUMinSuccess[0] );
    m_CapUMaxSuccess.resize( m_Nblade(), m_CapUMaxSuccess[0] );
    m_CapWMinSuccess.resize( m_Nblade(), m_CapWMinSuccess[0] );
    m_CapWMaxSuccess.resize( m_Nblade(), m_CapWMaxSuccess[0] );

    Matrix4d rot;
    for ( int i = 1; i < m_Nblade(); i++ )
    {
        double theta = 360.0 * i / ( double )m_Nblade();
        rot.loadIdentity();
        rot.rotateX( theta );

        m_MainSurfVec[i].Transform( rot );
    }

    CalculateMeshMetrics( u_pseudo );
}
Esempio n. 3
0
//==== Update Method ===//
void SSControlSurf::Update()
{
    // Build Control Surface as a rectangle with the points counter clockwise

    vec3d c_uws_upper, c_uws_lower, c_uwe_upper, c_uwe_lower;
    vector< vec3d > pnt_vec;
    double u, w;

    Geom* geom = VehicleMgr.GetVehicle()->FindGeom( m_CompID );
    if ( !geom ) { return; }

    VspSurf* surf = geom->GetSurfPtr();
    if ( !surf ) { return; }


    VspCurve startcrv;
    surf->GetU01ConstCurve( startcrv, m_UStart() );

    piecewise_curve_type c = startcrv.GetCurve();

    double vmin = c.get_parameter_min(); // Really must be 0.0
    double vmax = c.get_parameter_max(); // Really should be 4.0

    double vle = ( vmin + vmax ) * 0.5;

    double vtelow = vmin + TMAGIC;
    double vteup = vmax - TMAGIC;

    curve_point_type te, le;
    te = c.f( vmin );
    le = c.f( vle );

    double chord, d;
    chord = dist( le, te );

    if ( m_AbsRelFlag() == vsp::REL )
    {
        d = chord * m_StartLenFrac();
        m_StartLength.Set( d );
    }
    else
    {
        d = m_StartLength();
        m_StartLenFrac.Set( d / chord );
    }

    if ( m_ConstFlag.Get() )
    {
        if ( m_AbsRelFlag() == vsp::REL )
        {
            m_EndLenFrac.Set( d / chord );
        }
        else
        {
            m_EndLength.Set( d );
        }
    }

    // Mid-curve points on upper and lower surface.  To serve as initial guess.
    double vlowmid, vupmid;

    vlowmid = vtelow + m_StartLenFrac() * ( vle - vtelow );
    vupmid = vle + ( 1.0 - m_StartLenFrac() ) * ( vteup - vle );


    curve_point_type telow, teup;
    telow = c.f( vtelow );
    teup = c.f( vteup );

    piecewise_curve_type clow, cup;
    c.split( clow, cup, vle );


    double vlow, vup;

    if ( m_SurfType() != LOWER_SURF )
    {
        eli::geom::intersect::specified_distance( vup, cup, teup, d, vupmid );
        c_uws_upper = vec3d( m_UStart(), vup / vmax, 0 );
    }

    if ( m_SurfType() != UPPER_SURF )
    {
        eli::geom::intersect::specified_distance( vlow, clow, telow, d, vlowmid );
        c_uws_lower = vec3d( m_UStart(), vlow / vmax, 0 );
    }


    VspCurve endcrv;
    surf->GetU01ConstCurve( endcrv, m_UEnd() );
    c = endcrv.GetCurve();

    te = c.f( vmin );
    le = c.f( vle );

    chord = dist( le, te );


    if ( m_AbsRelFlag() == vsp::REL )
    {
        d = chord * m_EndLenFrac();
        m_EndLength.Set( d );
    }
    else
    {
        d = m_EndLength();
        m_EndLenFrac.Set( d / chord );
    }

    vlowmid = vtelow + m_EndLenFrac() * ( vle - vtelow );
    vupmid = vle + ( 1.0 - m_EndLenFrac() ) * ( vteup - vle );

    telow = c.f( vtelow );
    teup = c.f( vteup );

    c.split( clow, cup, vle );

    if ( m_SurfType() != LOWER_SURF )
    {
        eli::geom::intersect::specified_distance( vup, cup, teup, d, vupmid );
        c_uwe_upper = vec3d( m_UEnd(), vup / vmax, 0 );
    }

    if ( m_SurfType() != UPPER_SURF )
    {
        eli::geom::intersect::specified_distance( vlow, clow, telow, d, vlowmid );
        c_uwe_lower = vec3d( m_UEnd(), vlow / vmax, 0 );
    }

    // Build Control Surface

    if ( m_SurfType() == UPPER_SURF )
    {
        pnt_vec.resize( 4 );
        pnt_vec[0] = vec3d( m_UStart(), 1, 0 );
        pnt_vec[1] = c_uws_upper;
        pnt_vec[2] = c_uwe_upper;
        pnt_vec[3] = vec3d( m_UEnd(), 1, 0 );
    }
    else if ( m_SurfType() == LOWER_SURF )
    {
        pnt_vec.resize( 4 );
        pnt_vec[0] = vec3d( m_UStart(), 0, 0 );
        pnt_vec[1] = c_uws_lower;
        pnt_vec[2] = c_uwe_lower;
        pnt_vec[3] = vec3d( m_UEnd(), 0, 0 );
    }
    else
    {
        pnt_vec.resize( 8 );
        pnt_vec[0] = vec3d( m_UStart(), 1, 0 );
        pnt_vec[1] = c_uws_upper;
        pnt_vec[2] = c_uwe_upper;
        pnt_vec[3] = pnt_vec[3] = vec3d( m_UEnd(), 1, 0 );
        pnt_vec[4] = vec3d( m_UEnd(), 0, 0 );
        pnt_vec[5] = c_uwe_lower;
        pnt_vec[6] = c_uws_lower;
        pnt_vec[7] = vec3d( m_UStart(), 0, 0 );
    }
    //  pnt_vec[3] = pnt_vec[0];

    int pind = 0;
    int num_segs = pnt_vec.size() - 1;

    if ( m_SurfType() == BOTH_SURF )
    {
        num_segs--;
    }


    m_LVec.resize( num_segs );

    for ( int i = 0; i < num_segs; i++ )
    {
        if ( m_SurfType() == BOTH_SURF && i == 3 )
        {
            pind++;
        }
        m_LVec[i].SetSP0( pnt_vec[pind] );
        pind++;
        m_LVec[i].SetSP1( pnt_vec[pind] );
        m_LVec[i].Update( geom );
    }

    SubSurface::Update();
}