//---------------------------------------------------------------------------- // EgalTech 2015-2024 //---------------------------------------------------------------------------- // File : RotationMinimizeFrame.cpp Data : 05.03.24 Versione : 2.6c1 // Contenuto : Classe per RotationMinimizeFrame // // // // Modifiche : 05.03.24 RE Creazione modulo. //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "RotationMinimizeFrame.h" #include "GeoConst.h" using namespace std ; RotationMinimizeFrame::RotationMinimizeFrame( const ICurve* pCrv, const Frame3d& fr_Start, const double dStep) { // assegno i parametri m_pCrv = pCrv->Clone() ; m_Frame0 = fr_Start ; m_dStep = dStep ; } RotationMinimizeFrame::RotationMinimizeFrame( const ICurve* pCrv, const Frame3d& fr_Start, const int nStep) { // assegno i parametri if ( nStep < 1) // devo averne almeno 1, altrimenti è automaticamente il fr_Start return ; // recupero la lunghezza della curva double dLen = 0 ; if ( pCrv == nullptr || ! pCrv->IsValid() || ! pCrv->GetLength( dLen)) return ; m_pCrv = pCrv->Clone() ; m_Frame0 = fr_Start ; m_dStep = dLen / nStep ; } //---------------------------------------------------------------------------- RotationMinimizeFrame::~RotationMinimizeFrame( void) { Clear() ; } //---------------------------------------------------------------------------- bool RotationMinimizeFrame::IsValid() { // controllo validità della curva if ( m_pCrv == nullptr || ! m_pCrv->IsValid()) return false ; // controllo del frame iniziale if ( ! m_Frame0.IsValid()) return false ; // controllo sul parametro di discretizzazione if ( m_dStep < EPS_SMALL) return false ; // controllo che il passo non sia superiore alla lunghezza della curva double dLen = 0. ; if ( ! m_pCrv->GetLength( dLen) || m_dStep > dLen) return false ; return true ; } //---------------------------------------------------------------------------- bool RotationMinimizeFrame::Clear( void) { // pulizia della curva if ( m_pCrv != nullptr) delete m_pCrv ; m_pCrv = nullptr ; // reset del frame di partenza m_Frame0.Reset() ; // reset dell'intervallo di discretizzazione m_dStep = 0. ; return true ; } //---------------------------------------------------------------------------- bool RotationMinimizeFrame::GetFrames( FRAME3DVECTOR& vRMFrams) { // controllo validità if ( ! IsValid()) { Clear() ; return false ; } /* Double Reflection Computation of Rotation Minimizing Frame in Computer Graphics Wenping Wang Bert Juttler Dayue Zheng Yang Liu */ // calcolo lunghezza della curva double dLen = 0. ; if ( ! m_pCrv->GetLength( dLen)) return false ; // ricavo il numero degli step int nStep = 1 + ceil( dLen / nStep) ; // frame iniziale, ... frame intermedi ..., frame finale // in prima posizione viene inserito il frame iniziale m_vRMFrams.push_back( m_Frame0) ; // variabili di utilizzo double dLenCurr = 0 ; // lunghezza della curva allo step i-esimo double dLenNext ; // lunghezza della curva allo step (i+1)-esimo double dUCurr = 0. ; // parametro sulla curva allo step i-esimo double dUnext ; // parametro sulla curva allo step (i+1)-esimo Point3d ptCurr ; // punto sulla curva allo step i-esimo if ( ! m_pCrv->GetPointD1D2( dUCurr, ICurve::FROM_MINUS, ptCurr)) return false ; Point3d ptNext ; // punto sulla curva allo step (i+1)-esimo // definizione dei versori r,s,t Vector3d vt_r = m_Frame0.VersX() ; Vector3d vt_s = m_Frame0.VersY() ; Vector3d vt_t = m_Frame0.VersZ() ; // ciclo sugli step in cui la curva è suddivisa for ( int i = 0 ; i <= nStep ; ++ i) { // ricavo la lunghezza della curva nello step successivo dLenNext = min( dLen, ( i + 1) * dLen / nStep) ; // parametro successivo sulla curva if ( ! m_pCrv->GetParamAtLength( dLenNext, dUnext)) return false ; // punto successivo sulla curva if ( ! m_pCrv->GetPointD1D2( dUnext, ICurve::FROM_MINUS, ptNext)) return false ; // ricavo il vettore di riflessione rispetto al piano R1 Vector3d v1 = ptNext - ptCurr ; if ( ! v1.IsValid()) return false ; // parametro di riflessione double c1 = v1 * v1 ; // riflessione rispetto al piano R1 Vector3d vt_r_L = vt_r - ( 2 / c1) * ( v1 * vt_r) * v1 ; Vector3d vt_t_L = vt_t - ( 2 / c1) * ( v1 * vt_t) * v1 ; // vettore tangente al punto successivo Vector3d vt_t_next ; Point3d ptH ; if ( ! m_pCrv->GetPointD1D2( dUnext, ICurve::FROM_MINUS, ptH, &vt_t_next) || ! vt_t_next.IsValid()) return false ; // risplessione rispetto al piano R2 Vector3d v2 = vt_t_next - vt_t ; if ( ! v2.IsValid()) return false ; // parametro di riflessione double c2 = v2 * v2 ; // versore r del nuovo frame Vector3d vt_r_next = vt_r_L - ( 2 / c2) * ( v2 * vt_r_L) * v2 ; // versore t del nuovo frame Vector3d vt_s_next = vt_t_next ^ vt_r_next ; // creazione del nuovo frame Frame3d RMFrame_next ; RMFrame_next.Set( ptNext, vt_r_next, vt_s_next, vt_t_next) ; if ( ! RMFrame_next.IsValid()) return false ; // aggiornamento vettore dei frame m_vRMFrams.push_back( RMFrame_next) ; // aggiornamento dei parametri dLenCurr = dLenNext ; dUCurr = dUnext ; ptCurr = ptNext ; } return true ; }