//---------------------------------------------------------------------------- // EgalTech 2013-2013 //---------------------------------------------------------------------------- // File : CurveArc.cpp Data : 22.11.13 Versione : 1.3a1 // Contenuto : Implementazione della classe Arco di Circonferenza. // // // // Modifiche : 16.04.13 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include #include "\EgtDev\Include\EGnStringUtils.h" #include "CurveArc.h" #include "GeoObjFactory.h" using namespace std ; //---------------------------------------------------------------------------- GEOOBJ_REGISTER( CRV_ARC, "C_ARC", CurveArc) ; //---------------------------------------------------------------------------- const double CurveArc::PAR_START = 0 ; const double CurveArc::PAR_END = 1 ; //---------------------------------------------------------------------------- CurveArc::CurveArc( void) { m_PtCen.Set( 0, 0, 0) ; m_VtN.Set( 0, 0, 0) ; m_VtS.Set( 0, 0, 0) ; m_dRad = 0 ; m_dAngCenDeg = 0 ; m_dDeltaN = 0 ; m_nStatus = TO_VERIFY ; } //---------------------------------------------------------------------------- CurveArc::~CurveArc( void) { } //---------------------------------------------------------------------------- // Set generico, richiede tutti i parametri //---------------------------------------------------------------------------- bool CurveArc::Set( const Point3d& ptCen, const Vector3d& vtN, double dRad, const Vector3d& vtS, double dAngCenDeg, double dDeltaN) { // assegno i dati m_PtCen = ptCen ; m_VtN = vtN ; m_VtS = vtS ; m_dRad = dRad ; m_dAngCenDeg = dAngCenDeg ; m_dDeltaN = dDeltaN ; m_nStatus = TO_VERIFY ; // sistemo i versori m_VtN.Normalize() ; m_VtS.Normalize() ; return Validate() ; } //---------------------------------------------------------------------------- // Set per arco di circonferenza nel piano XY //---------------------------------------------------------------------------- bool CurveArc::Set( const Point3d& ptCen, double dRad, double dAngIniDeg, double dAngCenDeg, double dDeltaZ) { // assegno e calcolo i dati m_PtCen = ptCen ; m_VtN = Z_AX ; m_VtS.FromPolar( 1, dAngIniDeg) ; m_dRad = dRad ; m_dAngCenDeg = dAngCenDeg ; m_dDeltaN = dDeltaZ ; m_nStatus = TO_VERIFY ; return Validate() ; } //---------------------------------------------------------------------------- // Set per circonferenza completa nel piano XY //---------------------------------------------------------------------------- bool CurveArc::Set( const Point3d& ptCen, double dRad) { // assegno e calcolo i dati m_PtCen = ptCen ; m_VtN = Z_AX ; m_VtS = X_AX ; m_dRad = dRad ; m_dAngCenDeg = 360 ; m_dDeltaN = 0 ; m_nStatus = TO_VERIFY ; return Validate() ; } //---------------------------------------------------------------------------- CurveArc* CurveArc::Clone( void) const { CurveArc* pCrv ; // alloco oggetto pCrv = new(nothrow) CurveArc ; if ( pCrv != nullptr) *pCrv = *(const_cast(this)) ; return pCrv ; } //---------------------------------------------------------------------------- const string& CurveArc::GetKey( void) const { return GEOOBJ_GETKEY( CurveArc) ; } //---------------------------------------------------------------------------- bool CurveArc::Save( ostream& osOut) const { // centro osOut << ToString( m_PtCen) ; // versore Normale osOut << ";" << ToString( m_VtN) ; // raggio osOut << ";" << ToString( m_dRad) ; // versore Iniziale osOut << ";" << ToString( m_VtS) ; // angolo al centro osOut << ";" << ToString( m_dAngCenDeg) ; // deltaN osOut << ";" << ToString( m_dDeltaN) << ";" << endl ; return true ; } //---------------------------------------------------------------------------- bool CurveArc::Load( Scanner& TheScanner) { string sLine ; STRVECTOR vsParams ; // leggo la prossima linea if ( ! TheScanner.GetLine( sLine)) return false ; // la divido in parametri Tokenize( sLine, ";", vsParams) ; // 6 parametri : centro, versore normale, raggio, versore iniziale, angolo al centro e delta Z if ( vsParams.size() != 6) return false ; // recupero il centro if ( ! FromString( vsParams[0], m_PtCen)) return false ; // recupero il versore normale if ( ! FromString( vsParams[1], m_VtN)) return false ; // recupero il raggio if ( ! FromString( vsParams[2], m_dRad)) return false ; // recupero il versore iniziale if ( ! FromString( vsParams[3], m_VtS)) return false ; // recupero l'angolo al centro if ( ! FromString( vsParams[4], m_dAngCenDeg)) return false ; // recupero il delta N if ( ! FromString( vsParams[5], m_dDeltaN)) return false ; // eseguo validazione return Validate() ; } //---------------------------------------------------------------------------- bool CurveArc::Validate( void) { if ( m_nStatus == TO_VERIFY) m_nStatus = ( ( m_VtN.IsNormalized() && m_VtS.IsNormalized() && AreOrthoNear( m_VtN, m_VtS) && m_dRad > EPS_ZERO && fabs( m_dAngCenDeg) > EPS_ANG_ZERO) ? OK : ERR) ; return ( m_nStatus == OK) ; } //---------------------------------------------------------------------------- bool CurveArc::GetStartPoint( Point3d& ptStart) const { // verifico lo stato if ( m_nStatus != OK) return false ; // calcolo il punto ptStart = m_PtCen + m_dRad * m_VtS ; return true ; } //---------------------------------------------------------------------------- bool CurveArc::GetEndPoint( Point3d& ptEnd) const { // verifico lo stato if ( m_nStatus != OK) return false ; // calcolo il punto double dAng = m_dAngCenDeg * DEGTORAD ; Vector3d vtDir = cos( dAng) * m_VtS + sin( dAng) * ( m_VtN ^ m_VtS) ; ptEnd = m_PtCen + m_dRad * vtDir + m_dDeltaN * m_VtN ; return true ; } //---------------------------------------------------------------------------- bool CurveArc::GetDomain( double& dStart, double& dEnd) const { // verifico lo stato if ( m_nStatus != OK) return false ; // assegno gli estremi del dominio dStart = 0 ; dEnd = 1 ; return true ; } //---------------------------------------------------------------------------- bool CurveArc::GetPointD1D2( double dU, Point3d& ptPos, Vector3d& vtDer1, Vector3d& vtDer2) const { double dAng ; Vector3d vtDir ; // il parametro U deve essere compreso tra 0 e 1 if ( dU < 0) dU = 0 ; else if ( dU > 1) dU = 1 ; // versore al punto nel piano della circonferenza (ruoto m_VtS di dU di m_dAngCenDeg attorno a m_VtN) dAng = dU * m_dAngCenDeg * DEGTORAD ; vtDir = cos( dAng) * m_VtS + sin( dAng) * ( m_VtN ^ m_VtS) ; // calcolo del punto ptPos = m_PtCen + m_dRad * vtDir ; if ( fabs( m_dDeltaN) > EPS_ZERO) ptPos = ptPos + ( dU * m_dDeltaN) * m_VtN ; // calcolo della derivata prima vtDer1 = ( m_dRad * m_dAngCenDeg * DEGTORAD) * ( m_VtN ^ vtDir) ; if ( fabs( m_dDeltaN) > EPS_ZERO) vtDer1 = vtDer1 + m_dDeltaN * m_VtN ; // calcolo della derivata seconda vtDer2 = - ( m_dRad * m_dAngCenDeg * DEGTORAD * m_dAngCenDeg * DEGTORAD) * vtDir ; return true ; } //---------------------------------------------------------------------------- bool CurveArc::GetLength( double& dLen) const { // lunghezza dell'arco piano dLen = m_dRad * fabs( m_dAngCenDeg) * DEGTORAD ; // aggiunta eventuale parte ortogonale if ( fabs( m_dDeltaN) > EPS_ZERO) dLen = sqrt( dLen * dLen + m_dDeltaN * m_dDeltaN) ; return ( dLen > EPS_SMALL) ; } //---------------------------------------------------------------------------- bool CurveArc::Reverse( void) { double dAng ; Point3d ptTemp ; // il centro va spostato di DeltaN if ( m_dDeltaN > EPS_ZERO) m_PtCen = m_PtCen + m_dDeltaN * m_VtN ; // il versore normale rimane inalterato // il versore iniziale diventa quello finale dAng = m_dAngCenDeg * DEGTORAD ; m_VtS = cos( dAng) * m_VtS + sin( dAng) * ( m_VtN ^ m_VtS) ; // il raggio non cambia // l'angolo al centro inverte il segno m_dAngCenDeg = - m_dAngCenDeg ; // l'incremento sulla normale inverte il segno m_dDeltaN = - m_dDeltaN ; return true ; } //---------------------------------------------------------------------------- bool CurveArc::TrimStartAtParam( double dUTrim) { double dLen ; // riporto i parametri nel loro range dUTrim = ( ( dUTrim < PAR_START) ? PAR_START : (( dUTrim > PAR_END) ? PAR_END : dUTrim)) ; // recupero lunghezza if ( ! GetLength( dLen)) return false ; // utilizzo il trim sulle lunghezze return TrimStartAtLen( dUTrim * dLen) ; } //---------------------------------------------------------------------------- bool CurveArc::TrimEndAtParam( double dUTrim) { double dLen ; // riporto i parametri nel loro range dUTrim = ( ( dUTrim < PAR_START) ? PAR_START : (( dUTrim > PAR_END) ? PAR_END : dUTrim)) ; // recupero lunghezza if ( ! GetLength( dLen)) return false ; // utilizzo il trim sulle lunghezze return TrimEndAtLen( dUTrim * dLen) ; } //---------------------------------------------------------------------------- bool CurveArc::TrimStartAtLen( double dLenTrim) { double dLen ; double dAngRot ; double dMoveN ; // lunghezze negative vengono considerate nulle dLenTrim = __max( dLenTrim, 0) ; // verifico che sia abbastanza lunga if ( ! GetLength( dLen)) return false ; if ( ( dLen - dLenTrim) < EPS_SMALL) return false ; // eseguo il trim if ( dLenTrim > EPS_ZERO) { dAngRot = m_dAngCenDeg * dLenTrim / dLen ; m_VtS.Rotate( m_VtN, dAngRot * DEGTORAD) ; m_dAngCenDeg -= dAngRot ; if ( fabs( m_dDeltaN) > EPS_ZERO) { dMoveN = m_dDeltaN * dLenTrim / dLen ; m_PtCen.Translate( m_VtN * dMoveN) ; m_dDeltaN -= dMoveN ; } } // con i controlli sopra fatti rimane validata return true ; } //---------------------------------------------------------------------------- bool CurveArc::TrimEndAtLen( double dLenTrim) { double dLen ; // lunghezze negative vengono considerate nulle dLenTrim = __max( dLenTrim, 0) ; // verifico che sia abbastanza lunga if ( ! GetLength( dLen)) return false ; if ( dLenTrim < EPS_SMALL) return false ; // eseguo il trim if ( ( dLen - dLenTrim) > EPS_ZERO) { m_dAngCenDeg *= dLenTrim / dLen ; if ( fabs( m_dDeltaN) > EPS_ZERO) m_dDeltaN *= dLenTrim / dLen ; } // con i controlli sopra fatti rimane validata return true ; } //---------------------------------------------------------------------------- bool CurveArc::Translate( const Vector3d& vtMove) { // traslo il centro m_PtCen.Translate( vtMove) ; return true ; } //---------------------------------------------------------------------------- bool CurveArc::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng) { // verifico validità dell'asse di rotazione if ( vtAx.IsSmall()) return false ; // ruoto il centro e i versori m_PtCen.Rotate( ptAx, vtAx, dCosAng, dSinAng) ; m_VtN.Rotate( vtAx, dCosAng, dSinAng) ; m_VtS.Rotate( vtAx, dCosAng, dSinAng) ; return true ; } //---------------------------------------------------------------------------- bool CurveArc::Scale( const Point3d& ptCen, double dCoeffX, double dCoeffY, double dCoeffZ) { // ammessa solo scalatura uniforme if ( fabs( dCoeffX - dCoeffY) > EPS_SMALL || fabs( dCoeffX - dCoeffZ) > EPS_SMALL) return false ; // verifico non sia nulla if ( fabs( dCoeffX) < EPS_ZERO) return false ; // scalo il centro e le dimensioni lineari m_PtCen.Scale( ptCen, dCoeffX, dCoeffX, dCoeffX) ; m_dRad *= fabs( dCoeffX) ; m_dDeltaN *= dCoeffX ; if ( dCoeffX < 0) m_VtS = - m_VtS ; m_nStatus = TO_VERIFY ; return Validate() ; } //---------------------------------------------------------------------------- bool CurveArc::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) { // verifico validità del piano di specchiatura if ( vtNorm.IsSmall()) return false ; // specchio il centro e i versori, inverto l'angolo al centro m_PtCen.Mirror( ptOn, vtNorm) ; m_VtN.Mirror( vtNorm) ; m_VtS.Mirror( vtNorm) ; m_dAngCenDeg *= -1 ; return true ; } //---------------------------------------------------------------------------- bool CurveArc::ToGlob( const Frame3d& frRef) { // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; // trasformo il centro e i versori m_PtCen.ToGlob( frRef) ; m_VtN.ToGlob( frRef) ; m_VtS.ToGlob( frRef) ; return true ; } //---------------------------------------------------------------------------- bool CurveArc::ToLoc( const Frame3d& frRef) { // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; // trasformo i punti estremi m_PtCen.ToLoc( frRef) ; m_VtN.ToLoc( frRef) ; m_VtS.ToLoc( frRef) ; return true ; }