//---------------------------------------------------------------------------- // EgalTech 2013-2023 //---------------------------------------------------------------------------- // File : EGkPoint3d.h Data : 23.08.23 Versione : 2.5h2 // Contenuto : Dichiarazione della classe Punto 3d. // // // // Modifiche : 30.12.12 DS Creazione modulo. // 23.08.23 DS Aggiunto P_INVALID. // // //---------------------------------------------------------------------------- #pragma once #include "/EgtDev/Include/EGkVector3d.h" //----------------------- 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 Point3d { public : //! Costruttore del punto con tre componenti X, Y e Z Point3d( double dX, double dY, double dZ) : x( dX), y( dY), z( dZ) {} //! Costruttore del punto da un array di tre componenti Point3d( const double V[3]) : x( V[0]), y( V[1]), z( V[2]) {} //! Costruttore del punto con due componenti X e Y, Z = 0 Point3d( double dX, double dY) : x( dX), y( dY), z( 0) {} //! Costruttore del punto origine X = Y = Z = 0 Point3d( void) : x( 0), y( 0), z( 0) {} //! Assegnazione delle componenti X, Y e Z al punto void Set( double dX, double dY, double dZ) { x = dX ; y = dY ; z = dZ ;} public : //! Verifica la validità delle coordinate del punto bool IsValid( void) const { return ( std::isfinite( x) && std::isfinite( y) && std::isfinite( z)) ; } //! Verifica se il punto è quasi l'origine bool IsSmall( void) const { return ( ( x * x + y * y + z * z) < SQ_EPS_SMALL) ; } //! Verifica se il punto è esattamente l'origine bool IsZero( void) const { return ( ( x * x + y * y + z * z) < SQ_EPS_ZERO) ; } //! Somma sul posto con un vettore Point3d& operator +=( const Vector3d& vtV) { x += vtV.x ; y += vtV.y ; z += vtV.z ; return *this ; } //! Sottrazione sul posto con un vettore Point3d& operator -=( const Vector3d& vtV) { x -= vtV.x ; y -= vtV.y ; z -= vtV.z ; return *this ; } //! Somma sul posto con un altro punto (valida solo se equivalente ad una combinazione baricentrica) Point3d& operator +=( const Point3d& ptP) { x += ptP.x ; y += ptP.y ; z += ptP.z ; return *this ; } //! Moltiplicazione sul posto con un numero Point3d& operator *=( double dMul) { x *= dMul ; y *= dMul ; z *= dMul ; return *this ; } //! Divisione sul posto con un numero Point3d& operator /=( double dDiv) { double dMul = 1 / dDiv ; x *= dMul ; y *= dMul ; z *= dMul ; return *this ; } //! Traslazione dato il vettore di movimento void Translate( const Vector3d& vtMove) ; //! Rotazione attorno ad un asse per un punto, dato l'angolo in gradi bool Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg) ; //! Rotazione attorno ad un asse per un punto, dati coseno e seno dell'angolo di rotazione bool Rotate( const Point3d& ptAx, 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 Point3d& ptOn, const Vector3d& vtNorm) ; //! Scorrimento bool Shear( const Point3d& ptOn, 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) ; public : union { struct { double x ; //!< coordinata sull'asse X double y ; //!< coordinata sull'asse Y double z ; //!< coordinata sull'asse Z } ; double v[3] ; //!< equivalente vettoriale delle tre coordinate } ; } ; //---------------------------------------------------------------------------- // Punti notevoli //---------------------------------------------------------------------------- //! Punto non valido const Point3d P_INVALID( NAN, NAN, NAN) ; //! Punto origine const Point3d ORIG( 0, 0, 0) ; //---------------------------------------------------------------------------- //! Somma di due punti (valida solo se equivalente ad una combinazione baricentrica) //---------------------------------------------------------------------------- inline const Point3d operator+( const Point3d& ptP1, const Point3d& ptP2) { return Point3d( ptP1.x + ptP2.x, ptP1.y + ptP2.y, ptP1.z + ptP2.z) ; } //---------------------------------------------------------------------------- //! Somma di un punto e un vettore //---------------------------------------------------------------------------- inline const Point3d operator+( const Point3d& ptP1, const Vector3d& vtV2) { return Point3d( ptP1.x + vtV2.x, ptP1.y + vtV2.y, ptP1.z + vtV2.z) ; } //---------------------------------------------------------------------------- //! Opposto di un punto, genera un vettore //---------------------------------------------------------------------------- inline const Vector3d operator-( const Point3d& ptP) { return Vector3d( - ptP.x, - ptP.y, - ptP.z) ; } //---------------------------------------------------------------------------- //! Differenza di due punti, genera un vettore //---------------------------------------------------------------------------- inline const Vector3d operator-( const Point3d& ptP1, const Point3d& ptP2) { return Vector3d( ptP1.x - ptP2.x, ptP1.y - ptP2.y, ptP1.z - ptP2.z) ; } //---------------------------------------------------------------------------- //! Sottrazione di un punto e un vettore //---------------------------------------------------------------------------- inline const Point3d operator-( const Point3d& ptP1, const Vector3d& vtV2) { return Point3d( ptP1.x - vtV2.x, ptP1.y - vtV2.y, ptP1.z - vtV2.z) ; } //---------------------------------------------------------------------------- //! Prodotto con uno scalare //---------------------------------------------------------------------------- inline const Point3d operator*( const Point3d& ptP, double dMul) { return Point3d( ptP.x * dMul, ptP.y * dMul, ptP.z * dMul) ; } //---------------------------------------------------------------------------- //! Prodotto di uno scalare con un punto //---------------------------------------------------------------------------- inline const Point3d operator*( double dMul, const Point3d& ptP) { return Point3d( ptP.x * dMul, ptP.y * dMul, ptP.z * dMul) ; } //---------------------------------------------------------------------------- //! Divisione per uno scalare //---------------------------------------------------------------------------- inline const Point3d operator/( const Point3d& ptP, double dDiv) { double dMul ; dMul = 1 / dDiv ; return ( Point3d( ptP.x * dMul, ptP.y * dMul, ptP.z * dMul)) ; } //---------------------------------------------------------------------------- //! Somma mediata di due punti (baricentrica) //---------------------------------------------------------------------------- inline const Point3d Media( const Point3d& ptP1, const Point3d& ptP2, double dCoeff = 0.5) { return Point3d( ( 1 - dCoeff) * ptP1.x + dCoeff * ptP2.x, ( 1 - dCoeff) * ptP1.y + dCoeff * ptP2.y, ( 1 - dCoeff) * ptP1.z + dCoeff * ptP2.z) ; } //---------------------------------------------------------------------------- //! Approssimazione della distanza tra due punti (errore <= 8%) // ( vedi Graphics Gem I pag 432 ) //---------------------------------------------------------------------------- inline double ApproxDist( const Point3d& ptP1, const Point3d& ptP2) { double dMax = abs( ptP1.x - ptP2.x) ; double dMed = abs( ptP1.y - ptP2.y) ; double dMin = abs( ptP1.z - ptP2.z) ; if ( dMax < dMed) { double dTmp = dMax ; dMax = dMed ; dMed = dTmp ; } if ( dMax < dMin) { double dTmp = dMax ; dMax = dMin ; dMin = dTmp ; } if ( dMed < dMin) { double dTmp = dMed ; dMed = dMin ; dMin = dTmp ; } return ( dMax + 0.34375 * dMed + 0.25 * dMin) ; } //---------------------------------------------------------------------------- //! Approssimazione della distanza tra due punti nel piano XY (errore <= 5%) // ( vedi Graphics Gem I pag 427 + articolo di R. Baptista su FlipCode ) //---------------------------------------------------------------------------- inline double ApproxDistXY( const Point3d& ptP1, const Point3d& ptP2) { double dMax = abs( ptP1.x - ptP2.x) ; double dMin = abs( ptP1.y - ptP2.y) ; if ( dMax < dMin) { double dTmp = dMax ; dMax = dMin ; dMin = dTmp ; } return ( 0.9833984375 * dMax + 0.4306640625 * dMin) ; } //---------------------------------------------------------------------------- //! Quadrato della distanza tra due punti //---------------------------------------------------------------------------- inline double SqDist( const Point3d& ptP1, const Point3d& ptP2) { double dX = ptP1.x - ptP2.x ; double dY = ptP1.y - ptP2.y ; double dZ = ptP1.z - ptP2.z ; return ( dX * dX + dY * dY + dZ * dZ) ; } //---------------------------------------------------------------------------- //! Quadrato della distanza tra due punti nel piano XY //---------------------------------------------------------------------------- inline double SqDistXY( const Point3d& ptP1, const Point3d& ptP2) { double dX = ptP1.x - ptP2.x ; double dY = ptP1.y - ptP2.y ; return ( dX * dX + dY * dY) ; } //---------------------------------------------------------------------------- //! Distanza tra due punti //---------------------------------------------------------------------------- inline double Dist( const Point3d& ptP1, const Point3d& ptP2) { double dX = ptP1.x - ptP2.x ; double dY = ptP1.y - ptP2.y ; double dZ = ptP1.z - ptP2.z ; if ( abs( dY) < EPS_ZERO && abs( dZ) < EPS_ZERO) return abs( dX) ; if ( abs( dZ) < EPS_ZERO && abs( dX) < EPS_ZERO) return abs( dY) ; if ( abs( dX) < EPS_ZERO && abs( dY) < EPS_ZERO) return abs( dZ) ; return sqrt( dX * dX + dY * dY + dZ * dZ) ; } //---------------------------------------------------------------------------- //! Distanza tra due punti nel piano XY //---------------------------------------------------------------------------- inline double DistXY( const Point3d& ptP1, const Point3d& ptP2) { double dX = ptP1.x - ptP2.x ; double dY = ptP1.y - ptP2.y ; if ( abs( dY) < EPS_ZERO) return abs( dX) ; if ( abs( dX) < EPS_ZERO) return abs( dY) ; return sqrt( dX * dX + dY * dY) ; } //---------------------------------------------------------------------------- //! Direzione e distanza tra due punti ( P1 -> P2) //---------------------------------------------------------------------------- inline bool DirDist( const Point3d& ptP1, const Point3d& ptP2, Vector3d& vtDir, double& dDist) { dDist = Dist( ptP1, ptP2) ; // se distanza significativa if ( dDist > EPS_SMALL) { vtDir = ( ptP2 - ptP1) / dDist ; return true ; } // punti praticamente coincidenti vtDir.Set( 0, 0, 0) ; return false ; } //---------------------------------------------------------------------------- //! Verifica se due punti sono quasi coincidenti (tolleranza come parametro) //---------------------------------------------------------------------------- inline bool AreSamePointEpsilon( const Point3d& ptP1, const Point3d& ptP2, double dToler) { return ( SqDist( ptP1, ptP2) < ( dToler * dToler)) ; } //---------------------------------------------------------------------------- //! Verifica se due punti sono quasi coincidenti nel piano XY (tolleranza come parametro) //---------------------------------------------------------------------------- inline bool AreSamePointXYEpsilon( const Point3d& ptP1, const Point3d& ptP2, double dToler) { return ( SqDistXY( ptP1, ptP2) < ( dToler * dToler)) ; } //---------------------------------------------------------------------------- //! Verifica se due punti sono quasi coincidenti (Small error -> Approx) //---------------------------------------------------------------------------- inline bool AreSamePointApprox( const Point3d& ptP1, const Point3d& ptP2) { return ( SqDist( ptP1, ptP2) < SQ_EPS_SMALL) ; } //---------------------------------------------------------------------------- //! Verifica se due punti sono quasi coincidenti nel piano XY (Small error -> Approx) //---------------------------------------------------------------------------- inline bool AreSamePointXYApprox( const Point3d& ptP1, const Point3d& ptP2) { return ( SqDistXY( ptP1, ptP2) < SQ_EPS_SMALL) ; } //---------------------------------------------------------------------------- //! Verifica se due punti sono esattamente coincidenti (Zero error -> Exact) //---------------------------------------------------------------------------- inline bool AreSamePointExact( const Point3d& ptP1, const Point3d& ptP2) { return ( SqDist( ptP1, ptP2) < SQ_EPS_ZERO) ; } //---------------------------------------------------------------------------- //! Verifica se due punti sono esattamente coincidenti nel piano XY (Zero error -> Exact) //---------------------------------------------------------------------------- inline bool AreSamePointXYExact( const Point3d& ptP1, const Point3d& ptP2) { return ( SqDistXY( ptP1, ptP2) < SQ_EPS_ZERO) ; } //---------------------------------------------------------------------------- //! Restituisce una copia in locale del punto passato //---------------------------------------------------------------------------- inline const Point3d GetToLoc( const Point3d& ptP, const Frame3d& frRef) { Point3d ptQ = ptP ; ptQ.ToLoc( frRef) ; return ptQ ; } //---------------------------------------------------------------------------- //! Restituisce una copia in globale del punto passato //---------------------------------------------------------------------------- inline const Point3d GetToGlob( const Point3d& ptP, const Frame3d& frRef) { Point3d ptQ = ptP ; ptQ.ToGlob( frRef) ; return ptQ ; } //---------------------------------------------------------------------------- //! Restituisce una copia dal primo al secondo riferimento del punto passato //---------------------------------------------------------------------------- inline const Point3d GetLocToLoc( const Point3d& ptP, const Frame3d& frOri, const Frame3d& frDest) { Point3d ptQ = ptP ; ptQ.LocToLoc( frOri, frDest) ; return ptQ ; }