//==== Constructor ====// WingGeom::WingGeom( Vehicle* vehicle_ptr ) : GeomXSec( vehicle_ptr ) { m_Name = "WingGeom"; m_Type.m_Name = "Wing"; m_Type.m_Type = MS_WING_GEOM_TYPE; m_MinActiveXSec = 1; m_Closed = false; m_XSecSurf.SetParentContainer( GetID() ); m_XSecSurf.SetBasicOrientation( vsp::Y_DIR, X_DIR, XS_SHIFT_LE, true ); m_RelativeDihedralFlag.Init("RelativeDihedralFlag", m_Name, this, 0, 0, 1, true ); m_RelativeDihedralFlag.SetDescript( "Relative or Absolute Dihedral" ); m_RelativeTwistFlag.Init("RelativeTwistFlag", m_Name, this, 0, 0, 1, true ); m_RelativeTwistFlag.SetDescript( "Relative or Absolute Twist" ); m_RotateAirfoilMatchDiedralFlag.Init("RotateAirfoilMatchDideralFlag", m_Name, this, 0, 0, 1, true ); m_RotateAirfoilMatchDiedralFlag.SetDescript( "Rotate Airfoil To Stay Tangent To Dihedral (or Not)" ); m_TotalSpan.Init( "TotalSpan", m_Name, this, 1.0, 1e-6, 1000000.0 ); m_TotalSpan.SetDescript( "Total Planform Span" ); m_TotalProjSpan.Init( "TotalProjectedSpan", m_Name, this, 1.0, 1e-6, 1000000.0 ); m_TotalProjSpan.SetDescript( "Total Projected Planform Span" ); m_TotalChord.Init( "TotalChord", m_Name, this, 1.0, 0.0, 1000000.0 ); m_TotalChord.SetDescript( "Total Planform Chord" ); m_TotalArea.Init( "TotalArea", m_Name, this, 1.0, 1e-10, 1.0e12 ); m_TotalArea.SetDescript( "Total Planform Area" ); //==== rename capping controls for wing specific terminology ====// m_CapUMinOption.SetDescript("Type of End Cap on Wing Root"); m_CapUMinOption.Parm::Set(VspSurf::FLAT_END_CAP); m_CapUMinTess.SetDescript("Number of tessellated curves on Wing Root"); m_CapUMaxOption.SetDescript("Type of End Cap on Wing Tip"); m_CapUMaxOption.Parm::Set(VspSurf::FLAT_END_CAP); m_CapUMaxTess.SetDescript("Number of tessellated curves on Wing Tip"); //==== Init Parms ====// m_TessU = 16; m_TessW = 31; m_ActiveXSec = 1; m_ActiveAirfoil = 0; m_SymPlanFlag = SYM_XZ; //==== Wing XSecs ====// m_XSecSurf.SetXSecType( XSEC_WING ); m_XSecSurf.SetCutMinNumXSecs( 2 ); m_XSecSurf.AddXSec( vsp::XS_FOUR_SERIES ); m_XSecSurf.AddXSec( vsp::XS_FOUR_SERIES ); WingSect* ws; ws = ( WingSect* ) m_XSecSurf.FindXSec( 0 ); ws->SetGroupDisplaySuffix( 0 ); ws = ( WingSect* ) m_XSecSurf.FindXSec( 1 ); ws->SetGroupDisplaySuffix( 1 ); ws->m_Sweep = 30.0; ws->m_RootChord = 4.0; ws->m_TipChord = 1.0; ws->m_Span = 9.0; UpdateSurf(); }
//==== Update Wing And Cross Section Placement ====// void WingGeom::UpdateSurf() { //==== Check If Total Span/Chord/Area Has Changed ====// bool total_change_flag = false; if ( UpdatedParm( m_TotalSpan.GetID() ) ) { UpdateTotalSpan(); total_change_flag = true; } if ( UpdatedParm( m_TotalProjSpan.GetID() ) ) { UpdateTotalProjSpan(); total_change_flag = true; } if ( UpdatedParm( m_TotalChord.GetID() ) ) { UpdateTotalChord(); total_change_flag = true; } if ( UpdatedParm( m_TotalArea.GetID() ) ) { UpdateTotalArea(); total_change_flag = true; } int active_sect = GetActiveXSecIndex(); // Save Active Section //==== Set Temp Active XSec Based On Updated Parms ====// if ( total_change_flag ) SetActiveXSecIndex(1); else SetTempActiveXSec(); //==== Make Sure Chord Match For Adjacent Wing Sections ====// MatchWingSections(); SetActiveXSecIndex(active_sect); // Restore Active Section // clear the u tessellation vector m_TessUVec.clear(); vector< VspCurve > crv_vec( m_XSecSurf.NumXSec() ); //==== Compute Parameters For Each Section ====// double total_span = 0.0; double total_sweep_offset = 0.0; double total_dihed_offset = 0.0; double total_twist = 0.0; //==== Load End Points for Each Section ====// for ( int i = 0 ; i < m_XSecSurf.NumXSec() ; i++ ) { WingSect* ws = ( WingSect* ) m_XSecSurf.FindXSec( i ); if ( ws ) { //==== Reset Group Names ====// ws->SetGroupDisplaySuffix( i ); double rad = ws->m_Span(); double ty = rad*cos(GetSumDihedral(i)*DEG_2_RAD); double tz = rad*sin(GetSumDihedral(i)*DEG_2_RAD); double tan_le = ws->GetTanSweepAt( ws->m_Sweep(), 0.0 ); double toff = tan_le*rad; // Tip X Offset if ( i == 0 ) { ty = 0; tz = 0; toff = 0; } total_dihed_offset += tz; total_span += ty; total_sweep_offset += toff; if ( m_RelativeTwistFlag() ) total_twist += ws->m_Twist(); else total_twist = ws->m_Twist(); ws->SetProjectedSpan( ty ); //==== Find Width Parm ====// string width_id = ws->GetXSecCurve()->GetWidthParmID(); Parm* width_parm = ParmMgr.FindParm( width_id ); if ( width_parm ) { width_parm->Deactivate(); width_parm->Set( ws->m_TipChord() ); } double dihead_rot = 0.0; if ( m_RotateAirfoilMatchDiedralFlag() ) { if ( i == 0 ) { dihead_rot = GetSumDihedral( i+1 ); } else if ( i == m_XSecSurf.NumXSec()-1 ) { dihead_rot = GetSumDihedral( i ); } else { dihead_rot = 0.5*( GetSumDihedral( i ) + GetSumDihedral( i+1 ) ); } } //==== Load Transformations =====// ws->m_YDelta = total_span; ws->m_XDelta = total_sweep_offset; ws->m_ZDelta = total_dihed_offset; ws->m_YRotate = total_twist; ws->m_XRotate = dihead_rot; ws->m_XCenterRot = ws->m_XDelta + ws->m_TwistLoc()*ws->m_TipChord(); ws->m_YCenterRot = ws->m_YDelta; ws->m_ZCenterRot = ws->m_ZDelta; crv_vec[i] = ws->GetCurve(); if ( i > 0 ) { m_TessUVec.push_back( ws->m_SectTessU() ); } } } m_MainSurfVec[0].SkinC0( crv_vec, false ); if ( m_XSecSurf.GetFlipUD() ) { m_MainSurfVec[0].FlipNormal(); } m_MainSurfVec[0].SetSurfType( vsp::WING_SURF ); //==== Load Totals ====// m_TotalSpan = ComputeTotalSpan(); m_TotalProjSpan = ComputeTotalProjSpan(); m_TotalChord = ComputeTotalChord(); m_TotalArea = ComputeTotalArea(); }