Files
EgtGeomKernel/Vector3d.cpp
T
Dario Sassi 41a38fef3b EgtGeomKernel 1.5f1 :
- aggiunta entità testo (con font Nfe e di sistema)
- in tutte le rotate ora l'angolo è in gradi
- aggiunta trasformazione Shear (scorrimento)
- aggiunta trsformazione LocToLoc
- Set/GetInfo specializzate per i diversi tipi di informazioni
- Copy e Relocate con possibilità di indicare l'entità di riferimento rispetto a cui inserire
- aggiunte trasformazioni a PolyLine.
2014-06-03 13:19:54 +00:00

361 lines
12 KiB
C++

//----------------------------------------------------------------------------
// 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 = dAngVertDeg * DEGTORAD ;
double dAngOrizzRad = dAngOrizzDeg * DEGTORAD ;
double 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 = dAngDeg * DEGTORAD ;
x = dLen * cos( dAngRad) ;
y = dLen * sin( dAngRad) ;
z = 0 ;
}
//----------------------------------------------------------------------------
// Quadrato della lunghezza di un vettore
//----------------------------------------------------------------------------
double
Vector3d::SqLen( 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( double dEps)
{
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) < ( dEps * dEps))
return false ;
// eseguo la normalizzazione
dLen = sqrt( dSqLen) ;
*this = *this / dLen ;
return true ;
}
//----------------------------------------------------------------------------
// Rotazione
//----------------------------------------------------------------------------
bool
Vector3d::Rotate( const Vector3d& vtAx, double dAngDeg)
{
double dAngRad = dAngDeg * DEGTORAD ;
return Rotate( vtAx, cos( dAngRad), sin( dAngRad)) ;
}
//----------------------------------------------------------------------------
// Rotazione
//----------------------------------------------------------------------------
bool
Vector3d::Rotate( const Vector3d& vtAx, double dCosAng, double dSinAng)
{
// ricavo versore asse di rotazione
Vector3d vtDirAx = vtAx ;
if ( ! vtDirAx.Normalize())
return false ;
// separazione del vettore nelle componenti parallela e perp. asse
double dCompPar = *this * vtDirAx ;
Vector3d vtCompPar = vtDirAx * dCompPar ;
Vector3d vtCompPerp = *this - vtCompPar ;
// calcolo vettore perp. componente perp. e asse
Vector3d vtPerp2 = vtDirAx ^ vtCompPerp ;
// calcolo componenti perp. del vettore ruotato
Vector3d vtNewCompPerpX = dCosAng * vtCompPerp ;
Vector3d vtNewCompPerpY = dSinAng * vtPerp2 ;
Vector3d vtNewCompPerp = vtNewCompPerpX + vtNewCompPerpY ;
// calcolo del vettore ruotato
*this = vtCompPar + vtNewCompPerp ;
return true ;
}
//----------------------------------------------------------------------------
// Scalatura non uniforme
//----------------------------------------------------------------------------
bool
Vector3d::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dCoeffZ)
{
// verifico validità del frame
if ( frRef.GetType() == Frame3d::ERR)
return false ;
// ricavo le componenti sugli assi di scalatura, le scalo e riassemblo il vettore completo
*this = ( (*this) * frRef.VersX() * dCoeffX) * frRef.VersX() +
( (*this) * frRef.VersY() * dCoeffY) * frRef.VersY() +
( (*this) * frRef.VersZ() * dCoeffZ) * frRef.VersZ() ;
return true ;
}
//----------------------------------------------------------------------------
// Specchiatura
//----------------------------------------------------------------------------
bool
Vector3d::Mirror( const Vector3d& vtNorm)
{
// ricavo versore normale al piano di simmetria
Vector3d vtDirNorm = vtNorm ;
if ( ! vtDirNorm.Normalize())
return false ;
// calcolo la componente parallela alla normale
double dCompNorm = *this * vtDirNorm ;
// il simmetrico è il vettore originale meno il doppio della componente parallela
*this = *this - 2 * dCompNorm * vtDirNorm ;
return true ;
}
//----------------------------------------------------------------------------
// Scorrimento
//----------------------------------------------------------------------------
bool
Vector3d::Shear( const Vector3d& vtNorm, const Vector3d& vtDir, double dCoeff)
{
// costruisco il vettore
*this += dCoeff * ( *this * vtNorm) * vtDir ;
return true ;
}
//----------------------------------------------------------------------------
// Cambio di riferimento : dal riferimento al globale
//----------------------------------------------------------------------------
bool
Vector3d::ToGlob( const Frame3d& frRef)
{
// verifico validità del frame
if ( frRef.GetType() == Frame3d::ERR)
return false ;
// eseguo trasformazione
if ( frRef.GetType() != Frame3d::TOP) {
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)
{
// verifico validità del frame
if ( frRef.GetType() == Frame3d::ERR)
return false ;
// eseguo trasformazione
if ( frRef.GetType() != Frame3d::TOP) {
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 ;
}
//----------------------------------------------------------------------------
// Cambio di riferimento : dal primo riferimento al secondo
//----------------------------------------------------------------------------
bool
Vector3d::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)) ;
}
//----------------------------------------------------------------------------
// Calcolo dell'angolo tra il vettore e un altro
//----------------------------------------------------------------------------
bool
Vector3d::GetAngle( const Vector3d& vtEnd, double& dAngDeg) const
{
double dProSca ;
double dProVett ;
// quantità ugualmente proporzionali a coseno e seno
dProSca = *this * vtEnd ;
dProVett = ( *this ^ vtEnd).Len() ;
// se entrambe nulle
if ( fabs( dProSca) < EPS_ZERO && fabs( dProVett) < EPS_ZERO) {
dAngDeg = 0 ;
return false ;
}
dAngDeg = atan2( dProVett, dProSca) * RADTODEG ;
return true ;
}
//----------------------------------------------------------------------------
// Calcolo angolo di rotazione per portare la componente del vettore perpendicolare
// all'asse di rotazione sulla stessa direzione della componente perpendicolare di vtEnd
//----------------------------------------------------------------------------
bool
Vector3d::GetRotation( const Vector3d& vtEnd, const Vector3d& vtAx, double& dAngDeg, bool& bDet) const
{
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 ;
}