//---------------------------------------------------------------------------- // EgalTech 2013-2014 //---------------------------------------------------------------------------- // File : Frame3d.cpp Data : 10.03.14 Versione : 1.5c4 // Contenuto : Funzioni della classe Riferimento 3d. // // // // Modifiche : 06.01.13 DS Creazione modulo. // 10.03.14 DS Aggiunta Set con metodo OCS. // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "\EgtDev\Include\EGkFrame3d.h" //---------------------------------------------------------------------------- bool Frame3d::Set( const Point3d& ptOrig, const Vector3d& vtDirX, const Vector3d& vtDirY, const Vector3d& vtDirZ) { // lo inizializzo come errato m_nType = ERR ; m_nZType = ERR ; // assegnazione dell'origine e delle direzioni m_ptOrig = ptOrig ; m_vtVersX = vtDirX ; m_vtVersY = vtDirY ; m_vtVersZ = vtDirZ ; // se le direzioni non sono normalizzabili, errore if ( ! m_vtVersX.Normalize() || ! m_vtVersY.Normalize() || ! m_vtVersZ.Normalize()) return false ; // verifica della ortogonalità dei versori e del senso destrorso if ( ! Verify()) return false ; // ne determino il tipo CalculateType() ; return true ; } //---------------------------------------------------------------------------- bool Frame3d::Set( const Point3d& ptOrig, const Point3d& ptOnX, const Point3d& ptNearY) { // lo inizializzo come errato m_nType = ERR ; m_nZType = ERR ; // origine m_ptOrig = ptOrig ; // calcolo il versore X m_vtVersX = ptOnX - ptOrig ; if ( ! m_vtVersX.Normalize()) return false ; // calcolo il vettore che rappresenta un asse nel piano Vector3d vtTemp = ptNearY - ptOrig ; // calcolo il versore Z m_vtVersZ = m_vtVersX ^ vtTemp ; if ( ! m_vtVersZ.Normalize()) return false ; // calcolo il versore Y m_vtVersY = m_vtVersZ ^ m_vtVersX ; if ( ! m_vtVersY.Normalize()) return false ; // verifica della ortogonalità dei versori e del senso destrorso if ( ! Verify()) return false ; // ne determino il tipo CalculateType() ; return true ; } //---------------------------------------------------------------------------- bool Frame3d::Set( const Point3d& ptOrig, const Vector3d& vtDirZ) { // lo inizializzo come errato m_nType = ERR ; m_nZType = ERR ; // origine m_ptOrig = ptOrig ; // versore Z m_vtVersZ = vtDirZ ; if ( ! m_vtVersZ.Normalize()) return false ; // versore X (metodo OCS di DXF) if ( fabs( m_vtVersZ.x) < 1./64. && fabs( m_vtVersZ.y) < 1./64.) m_vtVersX = Y_AX ^ m_vtVersZ ; else m_vtVersX = Z_AX ^ m_vtVersZ ; if ( ! m_vtVersX.Normalize()) return false ; // verzsore Y m_vtVersY = m_vtVersZ ^ m_vtVersX ; if ( ! m_vtVersY.Normalize()) return false ; // verifica della ortogonalità dei versori e del senso destrorso if ( ! Verify()) return false ; // ne determino il tipo CalculateType() ; return true ; } //---------------------------------------------------------------------------- bool Frame3d::Set( const Point3d& ptOrig, const Vector3d& vtDirZ, const Vector3d& vtNearDirX) { // lo inizializzo come errato m_nType = ERR ; m_nZType = ERR ; // origine m_ptOrig = ptOrig ; // versore Z m_vtVersZ = vtDirZ ; if ( ! m_vtVersZ.Normalize()) return false ; // versore Y m_vtVersY = m_vtVersZ ^ vtNearDirX ; if ( ! m_vtVersY.Normalize()) return false ; // verzsore X m_vtVersX = m_vtVersY ^ m_vtVersZ ; if ( ! m_vtVersX.Normalize()) return false ; // verifica della ortogonalità dei versori e del senso destrorso if ( ! Verify()) return false ; // ne determino il tipo CalculateType() ; return true ; } //---------------------------------------------------------------------------- bool Frame3d::Set( const Point3d& ptOrig, Type nType) { // origine m_ptOrig = ptOrig ; // orientamento switch ( nType) { case TOP : m_nType = TOP ; m_vtVersX = X_AX ; m_vtVersY = Y_AX ; m_vtVersZ = Z_AX ; break ; case BOTTOM : m_nType = BOTTOM ; m_vtVersX = X_AX ; m_vtVersY = - Y_AX ; m_vtVersZ = - Z_AX ; break ; case FRONT : m_nType = FRONT ; m_vtVersX = X_AX ; m_vtVersY = Z_AX ; m_vtVersZ = - Y_AX ; break ; case BACK : m_nType = BACK ; m_vtVersX = - X_AX ; m_vtVersY = Z_AX ; m_vtVersZ = Y_AX ; break ; case LEFT : m_nType = LEFT ; m_vtVersX = - Y_AX ; m_vtVersY = Z_AX ; m_vtVersZ = - X_AX ; break ; case RIGHT : m_nType = RIGHT ; m_vtVersX = Y_AX ; m_vtVersY = Z_AX ; m_vtVersZ = X_AX ; break ; default : m_nType = ERR ; break ; } // orientamento di Z coincide con quello generale m_nZType = m_nType ; return ( m_nType != ERR) ; } //---------------------------------------------------------------------------- bool Frame3d::Reset( void) { m_nType = TOP ; m_nZType = TOP ; m_ptOrig = ORIG ; m_vtVersX = X_AX ; m_vtVersY = Y_AX ; m_vtVersZ = Z_AX ; return true ; } //---------------------------------------------------------------------------- void Frame3d::Translate( const Vector3d& vtMove) { // verifico validità riferimento if ( m_nType == ERR) return ; // eseguo la traslazione m_ptOrig.Translate( vtMove) ; // il tipo non cambia (dipende dall'orientamento e non dalla posizione) } //---------------------------------------------------------------------------- bool Frame3d::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg) { double dAngRad = dAngDeg * DEGTORAD ; return Rotate( ptAx, vtAx, cos( dAngRad), sin( dAngRad)) ; } //---------------------------------------------------------------------------- bool Frame3d::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng) { // verifico validità riferimento if ( m_nType == ERR) return false ; // controllo solo la prima rotazione, per le altre è lo stesso if ( ! m_ptOrig.Rotate( ptAx, vtAx, dCosAng, dSinAng)) { m_nType = ERR ; m_nZType = ERR ; return false ; } m_vtVersX.Rotate( vtAx, dCosAng, dSinAng) ; m_vtVersY.Rotate( vtAx, dCosAng, dSinAng) ; m_vtVersZ.Rotate( vtAx, dCosAng, dSinAng) ; // ricalcolo il tipo CalculateType() ; return true ; } //---------------------------------------------------------------------------- bool Frame3d::PseudoScale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dCoeffZ) { const double AXIS_LEN = 100 ; // verifico validità dei frame if ( m_nType == ERR || frRef.GetType() == ERR) return false ; // scalatura dell'origine Point3d ptOrigS = m_ptOrig ; ptOrigS.Scale( frRef, dCoeffX, dCoeffY, dCoeffZ) ; // calcolo trasformazione del versore Z Point3d ptDirZS = m_ptOrig + AXIS_LEN * m_vtVersZ ; ptDirZS.Scale( frRef, dCoeffX, dCoeffY, dCoeffZ) ; Vector3d vtVersZS = ptDirZS - ptOrigS ; vtVersZS.Normalize() ; // se il versore Z non cambia, basta applicare l'origine scalata if ( AreSameVectorExact( m_vtVersZ, vtVersZS)) { m_ptOrig = ptOrigS ; return true ; } // altrimenti, devo scalare anche i versori X e Y Point3d ptDirXS = m_ptOrig + AXIS_LEN * m_vtVersX ; ptDirXS.Scale( frRef, dCoeffX, dCoeffY, dCoeffZ) ; Point3d ptDirYS = m_ptOrig + AXIS_LEN * m_vtVersY ; ptDirYS.Scale( frRef, dCoeffX, dCoeffY, dCoeffZ) ; Frame3d frRefS ; if ( ! frRefS.Set( ptOrigS, ptDirXS, ptDirYS)) return false ; *this = frRefS ; return true ; } //---------------------------------------------------------------------------- bool Frame3d::PseudoMirror( const Point3d& ptOn, const Vector3d& vtNorm) { // verifico validità riferimento if ( m_nType == ERR) return false ; // mirror dell'origine m_ptOrig.Mirror( ptOn, vtNorm) ; // mirror dei versori Y e Z m_vtVersY.Mirror( vtNorm) ; m_vtVersZ.Mirror( vtNorm) ; // ricalcolo del versore X (per mantenere il senso destrorso) m_vtVersX = m_vtVersY ^ m_vtVersZ ; // ne determino il tipo CalculateType() ; return true ; } //---------------------------------------------------------------------------- bool Frame3d::PseudoShear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& vtDir, double dCoeff) { const double AXIS_LEN = 100 ; // verifico validità riferimento if ( m_nType == ERR) return false ; // shear dell'origine e di due punti sugli assi X e Y Point3d ptOrigS = m_ptOrig ; ptOrigS.Shear( ptOn, vtNorm, vtDir, dCoeff) ; Point3d ptDirXS = m_ptOrig + AXIS_LEN * m_vtVersX ; ptDirXS.Shear( ptOn, vtNorm, vtDir, dCoeff) ; Point3d ptDirYS = m_ptOrig + AXIS_LEN * m_vtVersY ; ptDirYS.Shear( ptOn, vtNorm, vtDir, dCoeff) ; // calcolo di un nuovo riferimento Frame3d frRefS ; if ( ! frRefS.Set( ptOrigS, ptDirXS, ptDirYS)) return false ; // assegnazione del risultato *this = frRefS ; return true ; } //---------------------------------------------------------------------------- bool Frame3d::Invert( void) { Frame3d frInv = GLOB_FRM ; if ( frInv.ToLoc( *this)) { *this = frInv ; return true ; } else return false ; } //---------------------------------------------------------------------------- // Cambio di riferimento : dal riferimento al globale //---------------------------------------------------------------------------- bool Frame3d::ToGlob( const Frame3d& frRef) { // verifico validità del frame if ( GetType() == ERR || frRef.GetType() == ERR) return false ; // eseguo la trasformazione m_ptOrig.ToGlob( frRef) ; m_vtVersX.ToGlob( frRef) ; m_vtVersY.ToGlob( frRef) ; m_vtVersZ.ToGlob( frRef) ; // ricalcolo il tipo CalculateType() ; return true ; } //---------------------------------------------------------------------------- // Cambio di riferimento : dal globale al riferimento //---------------------------------------------------------------------------- bool Frame3d::ToLoc( const Frame3d& frRef) { // verifico validità dei frame if ( GetType() == ERR || frRef.GetType() == ERR) return false ; // eseguo la trasformazione m_ptOrig.ToLoc( frRef) ; m_vtVersX.ToLoc( frRef) ; m_vtVersY.ToLoc( frRef) ; m_vtVersZ.ToLoc( frRef) ; // ricalcolo il tipo CalculateType() ; return true ; } //---------------------------------------------------------------------------- // Cambio di riferimento : dal primo riferimento al secondo //---------------------------------------------------------------------------- bool Frame3d::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) { // se i due riferimenti coincidono, non devo fare alcunché if ( AreSameFrame( frOri, frDest)) return true ; return ( ToGlob( frOri) && ToLoc( frDest)) ; } //---------------------------------------------------------------------------- bool Frame3d::Verify( void) { // verifica della ortogonalità dei versori e del senso destrorso double dOrtXY = m_vtVersX * m_vtVersY ; double dOrtYZ = m_vtVersY * m_vtVersZ ; double dOrtZX = m_vtVersZ * m_vtVersX ; Vector3d vtTmp = m_vtVersX ^ m_vtVersY ; double dRight = vtTmp * m_vtVersZ ; if ( fabs( dOrtXY) > EPS_ZERO || fabs( dOrtYZ) > EPS_ZERO || fabs( dOrtZX) > EPS_ZERO || dRight < EPS_ZERO) return false ; else return true ; } //---------------------------------------------------------------------------- void Frame3d::CalculateType( void) { // riferimento errato m_nType = ERR ; m_nZType = ERR ; // se la Zloc non ha componenti x e y globali allora é diretta come Zglob if ( fabs( m_vtVersZ.x) < EPS_ZERO && fabs( m_vtVersZ.y) < EPS_ZERO) { // se inoltre ha lo stesso verso di Zglob if ( m_vtVersZ.z > 0) m_nZType = TOP ; else m_nZType = BOTTOM ; // se la Xloc coincide con Xglob Type coincide con ZType if ( fabs( m_vtVersX.y) < EPS_ZERO && fabs( m_vtVersX.z) < EPS_ZERO && m_vtVersX.x > 0) m_nType = m_nZType ; else m_nType = GEN ; } // se la Zloc non ha componenti y e z globali allora é diretta come Xglob else if ( fabs( m_vtVersZ.y) < EPS_ZERO && fabs( m_vtVersZ.z) < EPS_ZERO) { // se inoltre ha lo stesso verso di Xglob if ( m_vtVersZ.x > 0) m_nZType = RIGHT ; else m_nZType = LEFT ; // se la Yloc coincide con Zglob Type coincide con ZType if ( fabs( m_vtVersY.x) < EPS_ZERO && fabs( m_vtVersY.y) < EPS_ZERO && m_vtVersY.z > 0) m_nType = m_nZType ; else m_nType = GEN ; } // se la Zloc non ha componenti z e x globali allora é diretta come Yglob else if ( fabs( m_vtVersZ.z) < EPS_ZERO && fabs( m_vtVersZ.x) < EPS_ZERO) { // se inoltre ha lo stesso verso di Yglob if ( m_vtVersZ.y > 0) m_nZType = BACK ; else m_nZType = FRONT ; // se la Yloc coincide con Zglob Type coincide con ZType if ( fabs( m_vtVersY.x) < EPS_ZERO && fabs( m_vtVersY.y) < EPS_ZERO && m_vtVersY.z > 0) m_nType = m_nZType ; else m_nType = GEN ; } // altrimenti é generico else { m_nZType = GEN ; m_nType = GEN ; } } //---------------------------------------------------------------------------- bool Frame3d::GetRotationsCAC1( double& dAngCDeg, double& dAngADeg, double& dAngC1Deg) const { bool bDet ; double dAngVertDeg ; double dAngOrizzDeg ; Vector3d vtXnoC1 ; // verifico validità riferimento if ( m_nType == ERR) return false ; // calcolo angoli sferici del versore Z m_vtVersZ.ToSpherical( nullptr, &dAngVertDeg, &dAngOrizzDeg) ; dAngADeg = dAngVertDeg ; // ricavo la prima rotazione attorno a Z if ( dAngADeg > EPS_ANG_SMALL) dAngCDeg = dAngOrizzDeg + 90 ; else m_vtVersX.ToSpherical( nullptr, nullptr, &dAngCDeg) ; // calcolo l'asse X senza la rotazione attorno a C' vtXnoC1.FromPolar( 1, dAngCDeg) ; // calcolo la rotazione attorno a C' if ( ! vtXnoC1.GetRotation( m_vtVersX, m_vtVersZ, dAngC1Deg, bDet) || ! bDet) dAngC1Deg = 0 ; return true ; }