//---------------------------------------------------------------------------- // EgalTech 2024-2024 //---------------------------------------------------------------------------- // File : RotationMinimizingFrame.cpp Data : 05.03.24 Versione : 2.6d1 // Contenuto : Classe per RotationMinimizeFrame // // // // Modifiche : 05.03.24 RE Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "GeoConst.h" #include "/EgtDev/Include/EGkRotationMinimizingFrame.h" using namespace std ; //---------------------------------------------------------------------------- bool RotationMinimizingFrame::Set( const ICurve* pCrv, const Frame3d& fr_Start) { // pulisco Clear() ; // verifico i parametri if ( pCrv == nullptr || ! pCrv->IsValid() || ! fr_Start.IsValid()) return false ; // assegno i parametri m_pCrv = pCrv->Clone() ; m_Frame0 = fr_Start ; return true ; } //---------------------------------------------------------------------------- bool RotationMinimizingFrame::Clear( void) { // pulizia della curva if ( m_pCrv != nullptr) delete m_pCrv ; m_pCrv = nullptr ; // reset del frame di partenza m_Frame0.Reset() ; return true ; } //---------------------------------------------------------------------------- bool RotationMinimizingFrame::IsValid( void) { // controllo validità della curva if ( m_pCrv == nullptr || ! m_pCrv->IsValid()) return false ; // controllo del frame iniziale if ( ! m_Frame0.IsValid()) return false ; // controllo che l'origine del frame sia sulla curva e che l'asse Z sia tangente alla curva Point3d ptS ; Vector3d vtZ ; if ( ! m_pCrv->GetPointD1D2( 0., ICurve::FROM_MINUS, ptS, &vtZ) || ! vtZ.Normalize() || ! AreSamePointApprox( ptS, m_Frame0.Orig()) || ! AreSameVectorEpsilon( vtZ, m_Frame0.VersZ(), 5 * EPS_SMALL)) return false ; return true ; } //---------------------------------------------------------------------------- bool RotationMinimizingFrame::GetFrameAtParam( const Frame3d& frAct, const double dParNext, Frame3d& frNext) { /* Double Reflection Computation of Rotation Minimizing Frame in Computer Graphics Wenping Wang Bert Juttler Dayue Zheng Yang Liu */ // ricavo i parametri dal frame if ( ! frAct.IsValid()) return false ; // origine del frame e versori ( ptCurr, [ vtCurrR, vtCurrS, vtCurrT]) Point3d ptCurr = frAct.Orig() ; Vector3d vtCurrR = frAct.VersX() ; Vector3d vtCurrT = frAct.VersZ() ; // punto i-esimo sulla curva e suo vettore tangente Point3d ptNext ; Vector3d vtNextT ; if ( ! m_pCrv->GetPointD1D2( dParNext, ICurve::FROM_MINUS, ptNext, &vtNextT) || ! vtNextT.Normalize()) return false ; // controllo per casi degeneri if ( AreSamePointEpsilon( ptCurr, ptNext, EPS_ZERO) || // non esiste il piano R1 abs( ( ptNext - ptCurr) * ( vtNextT + vtCurrT)) < EPS_ZERO) // non esiste il piano R2 return false ; // ricavo il vettore di riflessione rispetto al piano R1 Vector3d vR1_norm = ptNext - ptCurr ; if ( ! vR1_norm.IsValid()) return false ; // parametro di riflessione per R1 double dPar1 = vR1_norm * vR1_norm ; // riflessione rispetto al piano R1 ( sistema sinistrorso L ) Vector3d vt_r_L = vtCurrR - ( 2 / dPar1) * ( vR1_norm * vtCurrR) * vR1_norm ; Vector3d vt_t_L = vtCurrT - ( 2 / dPar1) * ( vR1_norm * vtCurrT) * vR1_norm ; // ricavo il vettore di riflessione rispetto al piano R1 Vector3d vR2_norm = vtNextT - vt_t_L ; if ( ! vR2_norm.IsValid()) return false ; // parametro di riflessione per R2 double dPar2 = vR2_norm * vR2_norm ; // versore r del nuovo frame Vector3d vt_r_next = vt_r_L - ( 2 / dPar2) * ( vR2_norm * vt_r_L) * vR2_norm ; // imposto il nuovo frame return frNext.Set( ptNext, vtNextT, vt_r_next) ; } //---------------------------------------------------------------------------- bool RotationMinimizingFrame::GetFramesByStep( double dStep, bool bUniform, FRAME3DVECTOR& vRMFrames) { // controllo validità if ( ! IsValid()) return false ; // controllo sullo step dStep = max( 10 * EPS_SMALL, dStep) ; // lunghezza della curva double dCrvLen = 0. ; if ( ! m_pCrv->GetLength( dCrvLen) || dCrvLen < 10 * EPS_SMALL) return false ; // ricavo il numero degli step int nStep = int( ceil( dCrvLen / dStep)) ; double dMyStep = ( bUniform ? dCrvLen / nStep : dStep) ; // inserisco il frame iniziale nel vettore dei riferimenti vRMFrames.clear() ; vRMFrames.reserve( nStep + 1) ; vRMFrames.push_back( m_Frame0) ; // ciclo sugli step in cui la curva è suddivisa for ( int i = 1 ; i <= nStep ; ++ i) { // ricavo il parametro della curva allo step i-esimo double dParNext ; if ( ! m_pCrv->GetParamAtLength( min( i * dMyStep, dCrvLen - EPS_SMALL), dParNext)) return false ; // ricavo il frame alla posizione calcolata Frame3d frNext ; if ( ! GetFrameAtParam( vRMFrames[i-1], dParNext, frNext)) return false ; // inserisco nuovo frame nel vettore dei riferimenti vRMFrames.push_back( frNext) ; } return true ; } //---------------------------------------------------------------------------- bool RotationMinimizingFrame::GetFramesBySplit( int nIntervals, FRAME3DVECTOR& vRMFrames) { // controllo validità if ( ! IsValid()) return false ; // controllo sul numero di intervalli nIntervals = max( 1, nIntervals) ; // ricavo lo step double dLen = 0 ; if ( ! m_pCrv->GetLength( dLen)) return false ; double dStep = dLen / nIntervals ; return GetFramesByStep( dStep, true, vRMFrames) ; } //---------------------------------------------------------------------------- bool RotationMinimizingFrame::GetFramesByTolerance( double dTol, FRAME3DVECTOR& vRMFrames) { // controllo validità if ( ! IsValid()) return false ; // controllo sulla tolleranza dTol = max( EPS_SMALL, dTol) ; // ricavo la PolyLine associata alla curva mediante tale tolleranza PolyLine PL ; if ( ! m_pCrv->ApproxWithLines( dTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL)) return false ; int nStep = PL.GetLineNbr() ; // inserisco il frame iniziale nel vettore dei riferimenti vRMFrames.clear() ; vRMFrames.reserve( nStep + 1) ; vRMFrames.push_back( m_Frame0) ; // eseguo il calcolo dei frame su ogni punto ricavato dall'approssimazione Point3d ptCurr ; PL.GetFirstPoint( ptCurr) ; double dParNext ; Point3d ptNext ; while ( PL.GetNextUPoint( &dParNext, &ptNext)) { // ricavo il Frame associato a questa posizione Frame3d frNext ; if ( ! GetFrameAtParam( vRMFrames.back(), dParNext, frNext)) return false ; vRMFrames.emplace_back( frNext) ; } return true ; }