//---------------------------------------------------------------------------- // EgalTech 2013-2023 //---------------------------------------------------------------------------- // File : EGkVector3d.h Data : 23.08.23 Versione : 2.5h2 // Contenuto : Dichiarazione della classe Vettore 3d. // // // // Modifiche : 31.12.13 DS Creazione modulo. // 14.12.19 DS Aggiunti confronti con Epsilon. // 23.08.23 DS Aggiunto V_INVALID. // //---------------------------------------------------------------------------- #pragma once #include "/EgtDev/Include/EGkGeoConst.h" #include #include //----------------------- Macro per import/export ----------------------------- #undef EGK_EXPORT #if defined( I_AM_EGK) // da definirsi solo nella DLL #define EGK_EXPORT __declspec( dllexport) #else #define EGK_EXPORT __declspec( dllimport) #endif //-------------------------- Forward Definition ------------------------------- class Frame3d ; //----------------------------------------------------------------------------- class EGK_EXPORT Vector3d { public : //! Costruttore del vettore con tre componenti X, Y e Z Vector3d( double dX, double dY, double dZ) : x( dX), y( dY), z( dZ) {} //! Costruttore del vettore da un array di tre componenti Vector3d( const double V[3]) : x( V[0]), y( V[1]), z( V[2]) {} //! Costruttore del vettore con due componenti X e Y, Z = 0 Vector3d( double dX, double dY) : x( dX), y( dY), z( 0) {} //! Costruttore del vettore nullo X = Y = Z = 0 Vector3d( void) : x( 0), y( 0), z( 0) {} //! Assegnazione delle componenti X, Y e Z al vettore void Set( double dX, double dY, double dZ) { x = dX ; y = dY ; z = dZ ; } public : //! Verifica la validità delle coordinate del vettore bool IsValid( void) const { return ( std::isfinite( x) && std::isfinite( y) && std::isfinite( z)) ; } //! Quadrato della lunghezza del vettore double SqLen( void) const { return ( x * x + y * y + z * z) ; } //! Lunghezza del vettore double Len( void) const ; //! Quadrato della lunghezza del vettore nel piano XY double SqLenXY( void) const { return ( x * x + y * y ) ; } //! Lunghezza del vettore nel piano XY double LenXY( void) const ; //! Verifica se il vettore è quasi nullo bool IsSmall( void) const { return ( ( x * x + y * y + z * z) < SQ_EPS_SMALL) ; } //! Verifica se il vettore è esattamente nullo bool IsZero( void) const { return ( ( x * x + y * y + z * z) < SQ_EPS_ZERO) ; } //! Verifica se il vettore è quasi nullo nel piano XY bool IsSmallXY( void) const { return ( ( x * x + y * y) < SQ_EPS_SMALL) ; } //! Verifica se il vettore è esattamente nullo nel piano XY bool IsZeroXY( void) const { return ( ( x * x + y * y) < SQ_EPS_ZERO) ; } //! Verifica se il vettore è normalizzato (è un versore) bool IsNormalized( void) const { return ( abs( 1.0 - (x * x + y * y + z * z)) < ( 2 * EPS_ZERO)) ; } //! Verifica se il vettore è parallelo ed equiverso con X+ bool IsXplus( void) const { double dMO = std::max( abs( y), abs( z)) ; return ( x > EPS_ZERO && dMO < 10 * EPS_ZERO && x > KV_BIG * dMO) ; } //! Verifica se il vettore è parallelo ed equiverso con X- bool IsXminus( void) const { double dMO = std::max( abs( y), abs( z)) ; return ( x < -EPS_ZERO && dMO < 10 * EPS_ZERO && x < -KV_BIG * dMO) ; } //! Verifica se il vettore è parallelo a X bool IsX( void) const { double dMO = std::max( abs( y), abs( z)) ; return ( abs( x) > EPS_ZERO && dMO < 10 * EPS_ZERO && abs( x) > KV_BIG * dMO) ; } //! Verifica se il vettore è parallelo ed equiverso con Y+ bool IsYplus( void) const { double dMO = std::max( abs( z), abs( x)) ; return ( y > EPS_ZERO && dMO < 10 * EPS_ZERO && y > KV_BIG * dMO) ; } //! Verifica se il vettore è parallelo ed equiverso con Y- bool IsYminus( void) const { double dMO = std::max( abs( z), abs( x)) ; return ( y < -EPS_ZERO && dMO < 10 * EPS_ZERO && y < -KV_BIG * dMO) ; } //! Verifica se il vettore è parallelo a Y bool IsY( void) const { double dMO = std::max( abs( z), abs( x)) ; return ( abs( y) > EPS_ZERO && dMO < 10 * EPS_ZERO && abs( y) > KV_BIG * dMO) ; } //! Verifica se il vettore è parallelo ed equiverso con Z+ bool IsZplus( void) const { double dMO = std::max( abs( x), abs( y)) ; return ( z > EPS_ZERO && dMO < 10 * EPS_ZERO && z > KV_BIG * dMO) ; } //! Verifica se il vettore è parallelo ed equiverso con Z- bool IsZminus( void) const { double dMO = std::max( abs( x), abs( y)) ; return ( z < -EPS_ZERO && dMO < 10 * EPS_ZERO && z < -KV_BIG * dMO) ; } //! Verifica se il vettore è parallelo a Z bool IsZ( void) const { double dMO = std::max( abs( x), abs( y)) ; return ( abs( z) > EPS_ZERO && dMO < 10 * EPS_ZERO && abs( z) > KV_BIG * dMO) ; } //! Verifica se il vettore è generico bool IsGeneric( void) const { return ( ! IsX() && ! IsY() && ! IsZ()) ; } //! Somma sul posto con altro vettore Vector3d& operator +=( const Vector3d& vtV) { x += vtV.x ; y += vtV.y ; z += vtV.z ; return *this ; } //! Sottrazione sul posto con altro vettore Vector3d& operator -=( const Vector3d& vtV) { x -= vtV.x ; y -= vtV.y ; z -= vtV.z ; return *this ; } //! Moltiplicazione sul posto con un numero Vector3d& operator *=( double dMul) { x *= dMul ; y *= dMul ; z *= dMul ; return *this ; } //! Divisione sul posto con un numero Vector3d& operator /=( double dDiv) { double dMul = 1 / dDiv ; x *= dMul ; y *= dMul ; z *= dMul ; return *this ; } //! Ritorna la rappresentazione in coordinate sferiche void ToSpherical( double* pdLen, double* pdAngVertDeg, double* pdAngOrizzDeg) const ; //! Inversione del vettore void Invert( void) { x = -x ; y = -y ; z = -z ; } //! Normalizzazione del vettore (trasformazione in versore) bool Normalize( double dEps = EPS_SMALL) ; //! Rotazione attorno ad un asse, dato l'angolo in gradi bool Rotate( const Vector3d& vtAx, double dAngDeg) ; //! Rotazione attorno ad un asse, dati coseno e seno dell'angolo di rotazione bool Rotate( const Vector3d& vtAx, double dCosAng, double dSinAng) ; //! Scalatura non uniforme bool Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dCoeffZ) ; //! Specchiatura bool Mirror( const Vector3d& vtNorm) ; //! Scorrimento bool Shear( const Vector3d& vtNorm, const Vector3d& vtDir, double dCoeff) ; //! Cambio di riferimento : dal riferimento al globale bool ToGlob( const Frame3d& frRef) ; //! Cambio di riferimento : dal globale al riferimento bool ToLoc( const Frame3d& frRef) ; //! Cambio di riferimento : dal primo riferimento al secondo bool LocToLoc( const Frame3d& frOri, const Frame3d& frDest) ; //! Calcolo dell'angolo tra il vettore e un altro bool GetAngle( const Vector3d& vtEnd, double& dAngDeg) const ; //! Calcolo dell'angolo tra il vettore e un altro nel piano XY bool GetAngleXY( const Vector3d& vtEnd, double& dAngDeg) const ; //! \brief Calcolo angolo di rotazione per portare la componente del vettore perpendicolare //! all'asse di rotazione sulla stessa direzione della componente perpendicolare di vtEnd bool GetRotation( const Vector3d& vtEnd, const Vector3d& vtAx, double dEpsZero, double& dAngDeg, bool& bDet) const ; bool GetRotation( const Vector3d& vtEnd, const Vector3d& vtAx, double& dAngDeg, bool& bDet) const { return GetRotation( vtEnd, vtAx, EPS_ZERO, dAngDeg, bDet) ;} public : union { struct { double x ; //!< componente sull'asse X double y ; //!< componente sull'asse Y double z ; //!< componente sull'asse Z } ; double v[3] ; //!< equivalente vettoriale delle tre componenti } ; } ; //---------------------------------------------------------------------------- // Vettori notevoli //---------------------------------------------------------------------------- //! Vettore non valido const Vector3d V_INVALID( NAN, NAN, NAN) ; //! Vettore nullo const Vector3d V_NULL( 0, 0, 0) ; //! Versore asse X const Vector3d X_AX( 1, 0, 0) ; //! Versore asse Y const Vector3d Y_AX( 0, 1, 0) ; //! Versore asse Z const Vector3d Z_AX( 0, 0, 1) ; //---------------------------------------------------------------------------- //! Definizione a partire da coordinate sferiche //---------------------------------------------------------------------------- EGK_EXPORT Vector3d FromSpherical( double dLen, double dAngVertDeg, double dAngOrizzDeg) ; //---------------------------------------------------------------------------- //! Definizione a partire da coordinate polari ( nel piano XY, Z = 0) //---------------------------------------------------------------------------- EGK_EXPORT Vector3d FromPolar( double dLen, double dAngDeg) ; //---------------------------------------------------------------------------- //! Definizione come più verticale dei vettori ortogonali a quello ricevuto //---------------------------------------------------------------------------- EGK_EXPORT Vector3d FromUprightOrtho( const Vector3d& vtV) ; //---------------------------------------------------------------------------- //! Definizione come ortogonale al primo ricevuto, orizzontale e più vicino al secondo //---------------------------------------------------------------------------- EGK_EXPORT Vector3d FromNearestHorizontalOrtho( const Vector3d& vtV, const Vector3d& vtNear) ; //---------------------------------------------------------------------------- //! Opposto di un vettore //---------------------------------------------------------------------------- inline const Vector3d operator-( const Vector3d& vtV) { return ( Vector3d( - vtV.x, - vtV.y, - vtV.z)) ; } //---------------------------------------------------------------------------- //! Somma di due vettori //---------------------------------------------------------------------------- inline const Vector3d operator+( const Vector3d& vtV1, const Vector3d& vtV2) { return ( Vector3d( vtV1.x + vtV2.x, vtV1.y + vtV2.y, vtV1.z + vtV2.z)) ; } //---------------------------------------------------------------------------- //! Sottrazione di due vettori //---------------------------------------------------------------------------- inline const Vector3d operator-( const Vector3d& vtV1, const Vector3d& vtV2) { return ( Vector3d( vtV1.x - vtV2.x, vtV1.y - vtV2.y, vtV1.z - vtV2.z)) ; } //---------------------------------------------------------------------------- //! Prodotto con uno scalare //---------------------------------------------------------------------------- inline const Vector3d operator*( const Vector3d& vtV, double dMul) { return ( Vector3d( vtV.x * dMul, vtV.y * dMul, vtV.z * dMul)) ; } //---------------------------------------------------------------------------- //! Prodotto di uno scalare con un vettore //---------------------------------------------------------------------------- inline const Vector3d operator*( double dMul, const Vector3d& vtV) { return ( Vector3d( vtV.x * dMul, vtV.y * dMul, vtV.z * dMul)) ; } //---------------------------------------------------------------------------- //! Divisione con uno scalare //---------------------------------------------------------------------------- inline const Vector3d operator/( const Vector3d& vtV, double dDiv) { double dMul = 1 / dDiv ; return ( Vector3d( vtV.x * dMul, vtV.y * dMul, vtV.z * dMul)) ; } //---------------------------------------------------------------------------- //! Prodotto scalare //---------------------------------------------------------------------------- inline double operator*( const Vector3d& vtV1, const Vector3d& vtV2) { return ( vtV1.x * vtV2.x + vtV1.y * vtV2.y + vtV1.z * vtV2.z) ; } //---------------------------------------------------------------------------- //! Prodotto scalare nel piano XY //---------------------------------------------------------------------------- inline double ScalarXY( const Vector3d& vtV1, const Vector3d& vtV2) { return ( vtV1.x * vtV2.x + vtV1.y * vtV2.y) ; } //---------------------------------------------------------------------------- //! Prodotto vettoriale //---------------------------------------------------------------------------- inline const Vector3d operator^( const Vector3d& vtV1, const Vector3d& vtV2) { return ( Vector3d( vtV1.y * vtV2.z - vtV1.z * vtV2.y, vtV1.z * vtV2.x - vtV1.x * vtV2.z, vtV1.x * vtV2.y - vtV1.y * vtV2.x)) ; } //---------------------------------------------------------------------------- //! Prodotto vettoriale nel piano XY //---------------------------------------------------------------------------- inline double CrossXY( const Vector3d& vtV1, const Vector3d& vtV2) { return ( vtV1.x * vtV2.y - vtV1.y * vtV2.x) ; } //---------------------------------------------------------------------------- //! Somma mediata di due vettori (baricentrica) //---------------------------------------------------------------------------- inline const Vector3d Media( const Vector3d& vtV1, const Vector3d& vtV2, double dCoeff = 0.5) { return ( Vector3d( ( 1 - dCoeff) * vtV1.x + dCoeff * vtV2.x, ( 1 - dCoeff) * vtV1.y + dCoeff * vtV2.y, ( 1 - dCoeff) * vtV1.z + dCoeff * vtV2.z)) ; } //---------------------------------------------------------------------------- //! Restituisce il componente del vettore parallelo a quello di riferimento //---------------------------------------------------------------------------- inline const Vector3d ParallCompo( const Vector3d& vtV, const Vector3d& vtRef) { if ( vtRef.IsNormalized()) return ( ( vtV * vtRef) * vtRef) ; else return ( ( vtV * vtRef) * vtRef / vtRef.SqLen()) ; } //---------------------------------------------------------------------------- //! Restituisce il componente del vettore ortogonale a quello di riferimento //---------------------------------------------------------------------------- inline const Vector3d OrthoCompo( const Vector3d& vtV, const Vector3d& vtRef) { if ( vtRef.IsNormalized()) return ( vtV - ( vtV * vtRef) * vtRef) ; else return ( vtV - ( vtV * vtRef) * vtRef / vtRef.SqLen()) ; } //---------------------------------------------------------------------------- //! Verifica se due vettori sono quasi coincidenti (tolleranza come parametro) //---------------------------------------------------------------------------- inline bool AreSameVectorEpsilon( const Vector3d& vtV1, const Vector3d& vtV2, double dToler) { return ( ( vtV1 - vtV2).SqLen() < ( dToler * dToler)) ; } //---------------------------------------------------------------------------- //! Verifica se due vettori sono quasi coincidenti (Small error -> Approx) //---------------------------------------------------------------------------- inline bool AreSameVectorApprox( const Vector3d& vtV1, const Vector3d& vtV2) { return ( ( vtV1 - vtV2).IsSmall()) ; } //---------------------------------------------------------------------------- //! Verifica se due vettori sono esattamente coincidenti (Zero error -> Exact) //---------------------------------------------------------------------------- inline bool AreSameVectorExact( const Vector3d& vtV1, const Vector3d& vtV2) { return ( ( vtV1 - vtV2).IsZero()) ; } //---------------------------------------------------------------------------- //! Verifica se due vettori sono quasi opposti (tolleranza come parametro) //---------------------------------------------------------------------------- inline bool AreOppositeVectorEpsilon( const Vector3d& vtV1, const Vector3d& vtV2, double dToler) { return ( ( vtV1 + vtV2).SqLen() < ( dToler * dToler)) ; } //---------------------------------------------------------------------------- //! Verifica se due vettori sono quasi opposti (Small error -> Approx) //---------------------------------------------------------------------------- inline bool AreOppositeVectorApprox( const Vector3d& vtV1, const Vector3d& vtV2) { return ( ( vtV1 + vtV2).IsSmall()) ; } //---------------------------------------------------------------------------- //! Verifica se due vettori sono esattamente opposti (Zero error -> Exact) //---------------------------------------------------------------------------- inline bool AreOppositeVectorExact( const Vector3d& vtV1, const Vector3d& vtV2) { return ( ( vtV1 + vtV2).IsZero()) ; } //---------------------------------------------------------------------------- //! Verifica se due vettori sono quasi coincidenti o opposti (tolleranza come parametro) //---------------------------------------------------------------------------- inline bool AreSameOrOppositeVectorEpsilon( const Vector3d& vtV1, const Vector3d& vtV2, double dToler) { return ( ( vtV1 - vtV2).SqLen() < ( dToler * dToler) || ( vtV1 + vtV2).SqLen() < ( dToler * dToler)) ; } //---------------------------------------------------------------------------- //! Verifica se due vettori sono quasi coincidenti o opposti (Small error -> Approx) //---------------------------------------------------------------------------- inline bool AreSameOrOppositeVectorApprox( const Vector3d& vtV1, const Vector3d& vtV2) { return ( ( vtV1 - vtV2).IsSmall() || ( vtV1 + vtV2).IsSmall()) ; } //---------------------------------------------------------------------------- //! Verifica se due vettori sono esattamente coincidenti o opposti (Zero error -> Exact) //---------------------------------------------------------------------------- inline bool AreSameOrOppositeVectorExact( const Vector3d& vtV1, const Vector3d& vtV2) { return ( ( vtV1 - vtV2).IsZero() || ( vtV1 + vtV2).IsZero()) ; } //---------------------------------------------------------------------------- //! Verifica se due versori sono ortogonali (Small error -> Approx) //---------------------------------------------------------------------------- inline bool AreOrthoApprox( const Vector3d& vtV1, const Vector3d& vtV2) { return ( abs( vtV1 * vtV2) < COS_ORTO_ANG_SMALL) ; } //---------------------------------------------------------------------------- //! Verifica se due versori sono ortogonali (Zero error -> Exact) //---------------------------------------------------------------------------- inline bool AreOrthoExact( const Vector3d& vtV1, const Vector3d& vtV2) { return ( abs( vtV1 * vtV2) < COS_ORTO_ANG_ZERO) ; } //---------------------------------------------------------------------------- //! Restituisce una copia in locale del vettore passato //---------------------------------------------------------------------------- inline const Vector3d GetToLoc( const Vector3d& vtV, const Frame3d& frRef) { Vector3d vtW = vtV ; vtW.ToLoc( frRef) ; return vtW ; } //---------------------------------------------------------------------------- //! Restituisce una copia in globale del vettore passato //---------------------------------------------------------------------------- inline const Vector3d GetToGlob( const Vector3d& vtV, const Frame3d& frRef) { Vector3d vtW = vtV ; vtW.ToGlob( frRef) ; return vtW ; } //---------------------------------------------------------------------------- //! Restituisce una copia dal primo al secondo riferimento del vettore passato //---------------------------------------------------------------------------- inline const Vector3d GetLocToLoc( const Vector3d& vtV, const Frame3d& frOri, const Frame3d& frDest) { Vector3d vtW = vtV ; vtW.LocToLoc( frOri, frDest) ; return vtW ; }