//---------------------------------------------------------------------------- // EgalTech 2013-2013 //---------------------------------------------------------------------------- // File : Vector3d.cpp Data : 20.11.13 Versione : 1.3a1 // Contenuto : Funzioni della classe Vettore 3d. // // // // Modifiche : 04.01.13 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "\EgtDev\Include\EGkGeoConst.h" #include "\EgtDev\Include\EGkVector3d.h" #include "\EgtDev\Include\EGKFrame3d.h" //---------------------------------------------------------------------------- // Definizione a partire da coordinate sferiche //---------------------------------------------------------------------------- void Vector3d::FromSpherical( double dLen, double dAngVertDeg, double dAngOrizzDeg) { double dAngVertRad ; double dAngOrizzRad ; double dSinAngVert ; dAngVertRad = dAngVertDeg * DEGTORAD ; dAngOrizzRad = dAngOrizzDeg * DEGTORAD ; dSinAngVert = sin( dAngVertRad) ; x = dLen * dSinAngVert * cos( dAngOrizzRad) ; y = dLen * dSinAngVert * sin( dAngOrizzRad) ; z = dLen * cos( dAngVertRad) ; } //---------------------------------------------------------------------------- // Definizione a partire da coordinate polari //---------------------------------------------------------------------------- void Vector3d::FromPolar( double dLen, double dAngDeg) { double dAngRad ; dAngRad = dAngDeg * DEGTORAD ; x = dLen * cos( dAngRad) ; y = dLen * sin( dAngRad) ; z = 0 ; } //---------------------------------------------------------------------------- // Quadrato della lunghezza di un vettore //---------------------------------------------------------------------------- double Vector3d::LenSq( void) const { return ( x * x + y * y + z * z) ; } //---------------------------------------------------------------------------- // Lunghezza di un vettore //---------------------------------------------------------------------------- double Vector3d::Len( void) const { if ( fabs( y) < EPS_ZERO && fabs( z) < EPS_ZERO) return fabs( x) ; if ( fabs( z) < EPS_ZERO && fabs( x) < EPS_ZERO) return fabs( y) ; if ( fabs( x) < EPS_ZERO && fabs( y) < EPS_ZERO) return fabs( z) ; return sqrt( x * x + y * y + z * z) ; } //---------------------------------------------------------------------------- // Ritorna la rappresentazione in coordinate sferiche //---------------------------------------------------------------------------- void Vector3d::ToSpherical( double* pdLen, double* pdAngVertDeg, double* pdAngOrizzDeg) const { double dLen ; double dAngVertDeg ; double dAngOrizzDeg ; // lunghezza dLen = Len() ; // se vettore nullo if ( dLen < EPS_ZERO) { dAngVertDeg = 0 ; dAngOrizzDeg = 0 ; } // altrimenti else { // se diretto come Z if ( fabs( x) < EPS_ZERO && fabs( y) < EPS_ZERO) { dAngVertDeg = (( z > 0) ? 0 : 180) ; dAngOrizzDeg = 0 ; } // se altrimenti nel piano XY else if ( fabs( z) < EPS_ZERO) { dAngVertDeg = 90.0 ; dAngOrizzDeg = atan2( y, x) * RADTODEG ; if ( dAngOrizzDeg < 0) dAngOrizzDeg += 360 ; } // caso generico else { dAngVertDeg = acos( z / dLen) * RADTODEG ; dAngOrizzDeg = atan2( y, x) * RADTODEG ; if ( dAngOrizzDeg < 0) dAngOrizzDeg += 360 ; } } // ritorno i valori if ( pdLen != nullptr) *pdLen = dLen ; if ( pdAngVertDeg != nullptr) *pdAngVertDeg = dAngVertDeg ; if ( pdAngOrizzDeg != nullptr) *pdAngOrizzDeg = dAngOrizzDeg ; } //---------------------------------------------------------------------------- // Normalizzazione di un vettore (trasformazione in versore) //---------------------------------------------------------------------------- bool Vector3d::Normalize( void) { double dSqLen ; double dLen ; // se già normalizzato, ok dSqLen = x * x + y * y + z * z ; if ( fabs( 1.0 - dSqLen) < ( 2 * EPS_ZERO)) return true ; // se troppo piccolo, errore if ( fabs( dSqLen) < ( EPS_SMALL * EPS_SMALL)) return false ; // eseguo la normalizzazione dLen = sqrt( dSqLen) ; *this = *this / dLen ; return true ; } //---------------------------------------------------------------------------- // Rotazione //---------------------------------------------------------------------------- bool Vector3d::Rotate( const Vector3d& vtAx, double dAngRad) { return Rotate( vtAx, cos( dAngRad), sin( dAngRad)) ; } //---------------------------------------------------------------------------- // Rotazione //---------------------------------------------------------------------------- bool Vector3d::Rotate( const Vector3d& vtAx, double dCosAng, double dSinAng) { double dCompPar ; Vector3d vtDirAx ; Vector3d vtCompPar ; Vector3d vtCompPerp ; Vector3d vtPerp2 ; Vector3d vtNewCompPerpX ; Vector3d vtNewCompPerpY ; Vector3d vtNewCompPerp ; // ricavo versore asse di rotazione vtDirAx = vtAx ; if ( ! vtDirAx.Normalize()) return false ; // separazione del vettore nelle componenti parallela e perp. asse dCompPar = *this * vtDirAx ; vtCompPar = vtDirAx * dCompPar ; vtCompPerp = *this - vtCompPar ; // calcolo vettore perp. componente perp. e asse vtPerp2 = vtDirAx ^ vtCompPerp ; // calcolo componenti perp. del vettore ruotato vtNewCompPerpX = dCosAng * vtCompPerp ; vtNewCompPerpY = dSinAng * vtPerp2 ; vtNewCompPerp = vtNewCompPerpX + vtNewCompPerpY ; // calcolo del vettore ruotato *this = vtCompPar + vtNewCompPerp ; return true ; } //---------------------------------------------------------------------------- // Scalatura non uniforme //---------------------------------------------------------------------------- bool Vector3d::Scale( double dCoeffX, double dCoeffY, double dCoeffZ) { x *= dCoeffX ; y *= dCoeffY ; z *= dCoeffZ ; return true ; } //---------------------------------------------------------------------------- // Specchiatura //---------------------------------------------------------------------------- bool Vector3d::Mirror( const Vector3d& vtNorm) { double dCompNorm ; Vector3d vtDirNorm ; // ricavo versore normale al piano di simmetria vtDirNorm = vtNorm ; if ( ! vtDirNorm.Normalize()) return false ; // calcolo la componente parallela alla normale dCompNorm = *this * vtDirNorm ; // il simmetrico è il vettore originale meno il doppio della componente parallela *this = *this - 2 * dCompNorm * vtDirNorm ; return true ; } //---------------------------------------------------------------------------- // Cambio di riferimento : dal riferimento al globale //---------------------------------------------------------------------------- bool Vector3d::ToGlob( const Frame3d& frRef) { Vector3d vtT( x, y, z) ; x = vtT.x * frRef.VersX().x + vtT.y * frRef.VersY().x + vtT.z * frRef.VersZ().x ; y = vtT.x * frRef.VersX().y + vtT.y * frRef.VersY().y + vtT.z * frRef.VersZ().y ; z = vtT.x * frRef.VersX().z + vtT.y * frRef.VersY().z + vtT.z * frRef.VersZ().z ; return true ; } //---------------------------------------------------------------------------- // Cambio di riferimento : dal globale al riferimento //---------------------------------------------------------------------------- bool Vector3d::ToLoc( const Frame3d& frRef) { Vector3d vtT( x, y, z) ; x = vtT.x * frRef.VersX().x + vtT.y * frRef.VersX().y + vtT.z * frRef.VersX().z ; y = vtT.x * frRef.VersY().x + vtT.y * frRef.VersY().y + vtT.z * frRef.VersY().z ; z = vtT.x * frRef.VersZ().x + vtT.y * frRef.VersZ().y + vtT.z * frRef.VersZ().z ; return true ; } //---------------------------------------------------------------------------- // Calcolo angolo di rotazione per portare la componente perpendicolare del // vettore sulla stessa direzione della componente perpendicolare di vtEnd //---------------------------------------------------------------------------- bool Vector3d::GetRotation( const Vector3d& vtEnd, const Vector3d& vtAx, double& dAngDeg, bool& bDet) { double dKcosA ; double dKsinA ; Vector3d vtDirAx ; Vector3d vtPerp ; Vector3d vtPerpE ; Vector3d vtPerp2 ; // ricavo versore asse di rotazione vtDirAx = vtAx ; if ( ! vtDirAx.Normalize()) return false ; // ricavo le componenti perpendicolari all'asse di rotazione vtPerp = *this - vtDirAx * ( *this * vtDirAx) ; vtPerpE = vtEnd - vtDirAx * ( vtEnd * vtDirAx) ; // se sono entrambe non nulle : angolo determinato if ( ! vtPerp.IsZero() && ! vtPerpE.IsZero()) { // secondo vettore perpendicolare ad asse e a componente perpendicolare vtPerp2 = vtDirAx ^ vtPerp ; // proporzionali a seno e coseno del perpendicolare E dKcosA = vtPerpE * vtPerp ; dKsinA = vtPerpE * vtPerp2 ; // angolo di rotazione dAngDeg = atan2( dKsinA, dKcosA) * RADTODEG ; bDet = true ; return true ; } // se comunque sono entrambe molto piccole : angolo indeterminato else if ( vtPerp.IsSmall() && vtPerpE.IsSmall()) { dAngDeg = 0 ; bDet = false ; return true ; } // altrimenti angolo impossibile else return false ; }