//---------------------------------------------------------------------------- // 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. ; // pulizia del vettore dei frames m_vRMFrames.clear() ; 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 = ceil( dLen / m_dStep) ; // in prima posizione viene inserito il frame iniziale m_vRMFrames.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->GetStartPoint( 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 - EPS_SMALL, ( i + 1) * dLen / nStep) ; // parametro successivo sulla curva if ( ! m_pCrv->GetParamAtLength( dLenNext, dUNext)) return false ; // punto successivo sulla curva e suo vettore tangente Vector3d vt_t_next ; if ( ! m_pCrv->GetPointD1D2( dUNext, ICurve::FROM_MINUS, ptNext, &vt_t_next) || ! vt_t_next.IsValid() /*|| ! vt_t_next.Normalize()*/) return false ; // controllo per caso degenere if ( AreSamePointEpsilon( ptCurr, ptNext, EPS_ZERO) || // non esiste R1 abs(( ptNext - ptCurr) * ( vt_t_next + vt_t)) < EPS_ZERO) // non esiste R2 return false ; // ricavo il vettore di riflessione rispetto al piano R1 Vector3d v1 = ptNext - ptCurr ; if ( ! v1.IsValid()) return false ; // parametro di riflessione per R1 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 ; // ricavo il vettore di riflessione rispetto al piano R1 Vector3d v2 = vt_t_next - vt_t_L ; if ( ! v2.IsValid()) return false ; // parametro di riflessione per R2 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()) { // sistemo... RMFrame_next.Set( ptNext, vt_t_next, vt_r_next) ; if ( ! RMFrame_next.IsValid()) return false ; } // aggiornamento vettore dei frame m_vRMFrames.push_back( RMFrame_next) ; // aggiornamento dei parametri dLenCurr = dLenNext ; dUCurr = dUNext ; ptCurr = ptNext ; } // restituisco il vettore di Frame vRMFrams.resize( int( m_vRMFrames.size())) ; // oriento i frames ottenuti in modo da avere il versore X tangente alla curva for ( int i = 0 ; i < int( m_vRMFrames.size()) ; ++ i) { vRMFrams[i].Set( m_vRMFrames[i].Orig(), m_vRMFrames[i].VersY(), m_vRMFrames[i].VersZ()) ; if ( ! vRMFrams[i].IsValid()) return false ; } return true ; }