Files
EgtGeomKernel/Frame3d.cpp
T
Dario Sassi 91d667bcfc EgtGeomKernel :
- modifiche a Zmap per virtual-additive
- modifiche a Frame3d per Set con i tre assi che ora aggiusta errori molto piccoli.
2024-04-26 11:23:56 +02:00

633 lines
18 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2013-2020
//----------------------------------------------------------------------------
// File : Frame3d.cpp Data : 29.09.20 Versione : 2.2i3
// Contenuto : Funzioni della classe Riferimento 3d.
//
//
//
// Modifiche : 06.01.13 DS Creazione modulo.
// 10.03.14 DS Aggiunta Set con metodo OCS.
// 29.09.20 DS Aggiunta GetFixedAxesRotationsABC.
//
//----------------------------------------------------------------------------
//--------------------------- 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 ;
// se ci sono errori molto piccoli di ortogonalità, li correggo
double dOrtXZ = m_vtVersX * m_vtVersZ ;
if ( dOrtXZ > EPS_ZERO && dOrtXZ < 10 * EPS_ZERO) {
m_vtVersX = OrthoCompo( m_vtVersX, m_vtVersZ) ;
m_vtVersX.Normalize() ;
}
double dOrtYX = m_vtVersY * m_vtVersX ;
if ( dOrtYX > EPS_ZERO && dOrtYX < 10 * EPS_ZERO) {
m_vtVersY = OrthoCompo( m_vtVersY, m_vtVersX) ;
m_vtVersY.Normalize() ;
}
double dOrtYZ = m_vtVersY * m_vtVersZ ;
if ( dOrtYZ > EPS_ZERO && dOrtYZ < 10 * EPS_ZERO) {
m_vtVersY = OrthoCompo( m_vtVersY, m_vtVersZ) ;
m_vtVersY.Normalize() ;
}
// 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 ( abs( m_vtVersZ.x) < 1./64. && abs( m_vtVersZ.y) < 1./64.)
m_vtVersX = Y_AX ^ m_vtVersZ ;
else
m_vtVersX = Z_AX ^ m_vtVersZ ;
if ( ! m_vtVersX.Normalize())
return false ;
// 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, 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 ;
// versore 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::Set( const Point3d& ptOrig, double dAngCDeg, double dAngADeg, double dAngC1Deg)
{
// imposto riferimento identità
Reset() ;
// rotazioni attorno ad assi fissi, quindi in ordine inverso
Rotate( ORIG, Z_AX, dAngC1Deg) ;
Rotate( ORIG, X_AX, dAngADeg) ;
Rotate( ORIG, Z_AX, dAngCDeg) ;
// imposto l'origine
m_ptOrig = ptOrig ;
// ne determino il tipo
CalculateType() ;
return true ;
}
//----------------------------------------------------------------------------
bool
Frame3d::Reset( bool bGlob)
{
m_nType = ( bGlob ? TOP : ERR) ;
m_nZType = ( bGlob ? TOP : ERR) ;
m_ptOrig = ORIG ;
m_vtVersX = X_AX ;
m_vtVersY = Y_AX ;
m_vtVersZ = Z_AX ;
return true ;
}
//----------------------------------------------------------------------------
bool
Frame3d::ChangeOrig( const Point3d& ptOrig)
{
// verifico validità riferimento
if ( m_nType == ERR)
return false ;
// assegno la nuova origine
m_ptOrig = ptOrig ;
// il tipo non cambia (dipende dall'orientamento e non dalla posizione)
return true ;
}
//----------------------------------------------------------------------------
bool
Frame3d::Translate( const Vector3d& vtMove)
{
// verifico validità riferimento
if ( m_nType == ERR)
return false ;
// eseguo la traslazione
m_ptOrig.Translate( vtMove) ;
// il tipo non cambia (dipende dall'orientamento e non dalla posizione)
return true ;
}
//----------------------------------------------------------------------------
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 i versori X e Y e ricavare Z di conseguenza
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 origine
if ( ! m_ptOrig.IsValid())
return false ;
// 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 ( abs( dOrtXY) > EPS_ZERO ||
abs( dOrtYZ) > EPS_ZERO ||
abs( 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 ( abs( m_vtVersZ.x) < EPS_ZERO && abs( 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 ( abs( m_vtVersX.y) < EPS_ZERO && abs( 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 ( abs( m_vtVersZ.y) < EPS_ZERO && abs( 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 ( abs( m_vtVersY.x) < EPS_ZERO && abs( 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 ( abs( m_vtVersZ.z) < EPS_ZERO && abs( 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 ( abs( m_vtVersY.x) < EPS_ZERO && abs( 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
{
// verifico validità riferimento
if ( m_nType == ERR)
return false ;
// calcolo angoli sferici del versore Z
double dAngVertDeg, dAngOrizzDeg ;
m_vtVersZ.ToSpherical( nullptr, &dAngVertDeg, &dAngOrizzDeg) ;
dAngADeg = dAngVertDeg ;
// ricavo la prima rotazione attorno a Z
if ( dAngADeg > EPS_ANG_SMALL) {
dAngCDeg = dAngOrizzDeg + ANG_RIGHT ;
if ( dAngCDeg >= ANG_FULL)
dAngCDeg -= ANG_FULL ;
}
else
m_vtVersX.ToSpherical( nullptr, nullptr, &dAngCDeg) ;
// calcolo l'asse X senza la rotazione attorno a C'
Vector3d vtXnoC1 = FromPolar( 1, dAngCDeg) ;
// calcolo la rotazione attorno a C'
bool bDet ;
if ( ! vtXnoC1.GetRotation( m_vtVersX, m_vtVersZ, dAngC1Deg, bDet) || ! bDet)
dAngC1Deg = 0 ;
// annullo esattamente valori praticamente nulli
if ( abs( dAngCDeg) < EPS_ANG_ZERO)
dAngCDeg = 0 ;
if ( abs( dAngADeg) < EPS_ANG_ZERO)
dAngADeg = 0 ;
if ( abs( dAngC1Deg) < EPS_ANG_ZERO)
dAngC1Deg = 0 ;
return true ;
}
//----------------------------------------------------------------------------
bool
Frame3d::GetFixedAxesRotationsABC( double& dAngADeg, double& dAngBDeg, double& dAngCDeg) const
{
// verifico validità riferimento
if ( m_nType == ERR)
return false ;
// casi speciali
if ( abs( m_vtVersX.z) > 1 - EPS_ANG_ZERO) {
if ( m_vtVersX.z > 0) {
dAngADeg = 0 ;
dAngBDeg = - 90 ;
dAngCDeg = atan2( m_vtVersY.x, m_vtVersZ.x) * RADTODEG ;
}
else {
dAngADeg = 0 ;
dAngBDeg = 90 ;
dAngCDeg = atan2( -m_vtVersY.x, -m_vtVersZ.x) * RADTODEG ;
}
}
// caso standard
else {
dAngADeg = atan2( m_vtVersY.z, m_vtVersZ.z) * RADTODEG ;
dAngBDeg = atan2( -m_vtVersX.z, sqrt( m_vtVersY.z * m_vtVersY.z + m_vtVersZ.z * m_vtVersZ.z)) * RADTODEG ;
dAngCDeg = atan2( m_vtVersX.y, m_vtVersX.x) * RADTODEG ;
}
// annullo esattamente valori praticamente nulli
if ( abs( dAngADeg) < EPS_ANG_ZERO)
dAngADeg = 0 ;
if ( abs( dAngBDeg) < EPS_ANG_ZERO)
dAngBDeg = 0 ;
if ( abs( dAngCDeg) < EPS_ANG_ZERO)
dAngCDeg = 0 ;
return true ;
}