Files
EgtGeomKernel/CurveArc.cpp
T
2013-12-24 22:09:55 +00:00

575 lines
15 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2013-2013
//----------------------------------------------------------------------------
// File : CurveArc.cpp Data : 22.11.13 Versione : 1.3a1
// Contenuto : Implementazione della classe Arco di Circonferenza.
//
//
//
// Modifiche : 16.04.13 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include <new>
#include "\EgtDev\Include\EGnStringUtils.h"
#include "CurveArc.h"
#include "GeoObjFactory.h"
using namespace std ;
//----------------------------------------------------------------------------
GEOOBJ_REGISTER( CRV_ARC, "C_ARC", CurveArc) ;
//----------------------------------------------------------------------------
const double CurveArc::PAR_START = 0 ;
const double CurveArc::PAR_END = 1 ;
//----------------------------------------------------------------------------
CurveArc::CurveArc( void)
{
m_PtCen.Set( 0, 0, 0) ;
m_VtN.Set( 0, 0, 0) ;
m_VtS.Set( 0, 0, 0) ;
m_dRad = 0 ;
m_dAngCenDeg = 0 ;
m_dDeltaN = 0 ;
m_nStatus = TO_VERIFY ;
}
//----------------------------------------------------------------------------
CurveArc::~CurveArc( void)
{
}
//----------------------------------------------------------------------------
// Set generico, richiede tutti i parametri
//----------------------------------------------------------------------------
bool
CurveArc::Set( const Point3d& ptCen, const Vector3d& vtN, double dRad,
const Vector3d& vtS, double dAngCenDeg, double dDeltaN)
{
// assegno i dati
m_PtCen = ptCen ;
m_VtN = vtN ;
m_VtS = vtS ;
m_dRad = dRad ;
m_dAngCenDeg = dAngCenDeg ;
m_dDeltaN = dDeltaN ;
m_nStatus = TO_VERIFY ;
// sistemo i versori
m_VtN.Normalize() ;
m_VtS.Normalize() ;
return Validate() ;
}
//----------------------------------------------------------------------------
// Set per arco di circonferenza nel piano XY
//----------------------------------------------------------------------------
bool
CurveArc::Set( const Point3d& ptCen, double dRad, double dAngIniDeg, double dAngCenDeg, double dDeltaZ)
{
// assegno e calcolo i dati
m_PtCen = ptCen ;
m_VtN = Z_AX ;
m_VtS.FromPolar( 1, dAngIniDeg) ;
m_dRad = dRad ;
m_dAngCenDeg = dAngCenDeg ;
m_dDeltaN = dDeltaZ ;
m_nStatus = TO_VERIFY ;
return Validate() ;
}
//----------------------------------------------------------------------------
// Set per circonferenza completa nel piano XY
//----------------------------------------------------------------------------
bool
CurveArc::Set( const Point3d& ptCen, double dRad)
{
// assegno e calcolo i dati
m_PtCen = ptCen ;
m_VtN = Z_AX ;
m_VtS = X_AX ;
m_dRad = dRad ;
m_dAngCenDeg = 360 ;
m_dDeltaN = 0 ;
m_nStatus = TO_VERIFY ;
return Validate() ;
}
//----------------------------------------------------------------------------
CurveArc*
CurveArc::Clone( void) const
{
CurveArc* pCrv ;
// alloco oggetto
pCrv = new(nothrow) CurveArc ;
if ( pCrv != nullptr)
*pCrv = *(const_cast<CurveArc*>(this)) ;
return pCrv ;
}
//----------------------------------------------------------------------------
const string&
CurveArc::GetKey( void) const
{
return GEOOBJ_GETKEY( CurveArc) ;
}
//----------------------------------------------------------------------------
bool
CurveArc::Save( ostream& osOut) const
{
// centro
osOut << ToString( m_PtCen) ;
// versore Normale
osOut << ";" << ToString( m_VtN) ;
// raggio
osOut << ";" << ToString( m_dRad) ;
// versore Iniziale
osOut << ";" << ToString( m_VtS) ;
// angolo al centro
osOut << ";" << ToString( m_dAngCenDeg) ;
// deltaN
osOut << ";" << ToString( m_dDeltaN) << ";" << endl ;
return true ;
}
//----------------------------------------------------------------------------
bool
CurveArc::Load( Scanner& TheScanner)
{
string sLine ;
STRVECTOR vsParams ;
// leggo la prossima linea
if ( ! TheScanner.GetLine( sLine))
return false ;
// la divido in parametri
Tokenize( sLine, ";", vsParams) ;
// 6 parametri : centro, versore normale, raggio, versore iniziale, angolo al centro e delta Z
if ( vsParams.size() != 6)
return false ;
// recupero il centro
if ( ! FromString( vsParams[0], m_PtCen))
return false ;
// recupero il versore normale
if ( ! FromString( vsParams[1], m_VtN))
return false ;
// recupero il raggio
if ( ! FromString( vsParams[2], m_dRad))
return false ;
// recupero il versore iniziale
if ( ! FromString( vsParams[3], m_VtS))
return false ;
// recupero l'angolo al centro
if ( ! FromString( vsParams[4], m_dAngCenDeg))
return false ;
// recupero il delta N
if ( ! FromString( vsParams[5], m_dDeltaN))
return false ;
// eseguo validazione
return Validate() ;
}
//----------------------------------------------------------------------------
bool
CurveArc::Validate( void)
{
if ( m_nStatus == TO_VERIFY)
m_nStatus = ( ( m_VtN.IsNormalized() && m_VtS.IsNormalized() &&
AreOrthoNear( m_VtN, m_VtS) &&
m_dRad > EPS_ZERO && fabs( m_dAngCenDeg) > EPS_ANG_ZERO) ? OK : ERR) ;
return ( m_nStatus == OK) ;
}
//----------------------------------------------------------------------------
bool
CurveArc::GetStartPoint( Point3d& ptStart) const
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// calcolo il punto
ptStart = m_PtCen + m_dRad * m_VtS ;
return true ;
}
//----------------------------------------------------------------------------
bool
CurveArc::GetEndPoint( Point3d& ptEnd) const
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// calcolo il punto
double dAng = m_dAngCenDeg * DEGTORAD ;
Vector3d vtDir = cos( dAng) * m_VtS + sin( dAng) * ( m_VtN ^ m_VtS) ;
ptEnd = m_PtCen + m_dRad * vtDir + m_dDeltaN * m_VtN ;
return true ;
}
//----------------------------------------------------------------------------
bool
CurveArc::GetDomain( double& dStart, double& dEnd) const
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// assegno gli estremi del dominio
dStart = PAR_START ;
dEnd = PAR_END ;
return true ;
}
//----------------------------------------------------------------------------
bool
CurveArc::GetPointD1D2( double dU, Point3d& ptPos, Vector3d& vtDer1, Vector3d& vtDer2) const
{
double dAng ;
Vector3d vtDir ;
// il parametro U deve essere compreso tra 0 e 1
if ( dU < 0)
dU = 0 ;
else if ( dU > 1)
dU = 1 ;
// versore al punto nel piano della circonferenza (ruoto m_VtS di dU di m_dAngCenDeg attorno a m_VtN)
dAng = dU * m_dAngCenDeg * DEGTORAD ;
vtDir = cos( dAng) * m_VtS + sin( dAng) * ( m_VtN ^ m_VtS) ;
// calcolo del punto
ptPos = m_PtCen + m_dRad * vtDir ;
if ( fabs( m_dDeltaN) > EPS_ZERO)
ptPos = ptPos + ( dU * m_dDeltaN) * m_VtN ;
// calcolo della derivata prima
vtDer1 = ( m_dRad * m_dAngCenDeg * DEGTORAD) * ( m_VtN ^ vtDir) ;
if ( fabs( m_dDeltaN) > EPS_ZERO)
vtDer1 = vtDer1 + m_dDeltaN * m_VtN ;
// calcolo della derivata seconda
vtDer2 = - ( m_dRad * m_dAngCenDeg * DEGTORAD * m_dAngCenDeg * DEGTORAD) * vtDir ;
return true ;
}
//----------------------------------------------------------------------------
bool
CurveArc::GetLength( double& dLen) const
{
// lunghezza dell'arco piano
dLen = m_dRad * fabs( m_dAngCenDeg) * DEGTORAD ;
// aggiunta eventuale parte ortogonale
if ( fabs( m_dDeltaN) > EPS_ZERO)
dLen = sqrt( dLen * dLen + m_dDeltaN * m_dDeltaN) ;
return ( dLen > EPS_SMALL) ;
}
//----------------------------------------------------------------------------
bool
CurveArc::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const
{
int i ;
int nStep ;
double dAngStepDeg ;
double dCosA ;
double dSinA ;
double dU ;
Point3d ptPos ;
Vector3d vtA1 ;
Vector3d vtA2 ;
Vector3d vtA1p ;
Vector3d vtA2p ;
// la curva deve essere validata
if ( m_nStatus != OK)
return false ;
// limiti minimi su tolleranza e deviazione angolare
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
dAngTolDeg = max( dAngTolDeg, ANG_TOL_MIN_DEG) ;
// determinazione dello step angolare
dAngStepDeg = sqrt( 8 * dLinTol / m_dRad) * RADTODEG ;
dAngStepDeg = min( dAngStepDeg, dAngTolDeg) ;
// dall'angolo al centro ricavo il numero di passi
nStep = (int) ( fabs( m_dAngCenDeg) / dAngStepDeg + 0.999) ;
// sistemo lo step (per il numero intero di passi)
dAngStepDeg = m_dAngCenDeg / nStep ;
// versori di riferimento nel piano dell'arco
vtA1 = m_VtS ;
vtA2 = m_VtN ^ m_VtS ;
// seno e coseno dell'angolo di step
dCosA = cos( dAngStepDeg * DEGTORAD) ;
dSinA = sin( dAngStepDeg * DEGTORAD) ;
// primo punto
ptPos = m_PtCen + vtA1 * m_dRad ;
PL.AddUPoint( 0, ptPos) ;
// ciclo per i punti successivi
for ( i = 1 ; i <= nStep ; ++ i) {
// parametro del punto
dU = i / (double) nStep ;
// nuovo valore versori
vtA1p = vtA1 ;
vtA2p = vtA2 ;
vtA1 = dCosA * vtA1p + dSinA * vtA2p ;
vtA2 = - dSinA * vtA1p + dCosA * vtA2p ;
// calcolo del punto
ptPos = m_PtCen + vtA1 * m_dRad ;
if ( fabs( m_dDeltaN) > EPS_ZERO)
ptPos = ptPos + ( dU * m_dDeltaN) * m_VtN ;
PL.AddUPoint( dU, ptPos) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
CurveArc::Reverse( void)
{
double dAng ;
Point3d ptTemp ;
// il centro va spostato di DeltaN
if ( m_dDeltaN > EPS_ZERO)
m_PtCen = m_PtCen + m_dDeltaN * m_VtN ;
// il versore normale rimane inalterato
// il versore iniziale diventa quello finale
dAng = m_dAngCenDeg * DEGTORAD ;
m_VtS = cos( dAng) * m_VtS + sin( dAng) * ( m_VtN ^ m_VtS) ;
// il raggio non cambia
// l'angolo al centro inverte il segno
m_dAngCenDeg = - m_dAngCenDeg ;
// l'incremento sulla normale inverte il segno
m_dDeltaN = - m_dDeltaN ;
return true ;
}
//----------------------------------------------------------------------------
bool
CurveArc::TrimStartAtParam( double dUTrim)
{
double dLen ;
// riporto i parametri nel loro range
dUTrim = ( ( dUTrim < PAR_START) ? PAR_START : (( dUTrim > PAR_END) ? PAR_END : dUTrim)) ;
// recupero lunghezza
if ( ! GetLength( dLen))
return false ;
// utilizzo il trim sulle lunghezze
return TrimStartAtLen( dUTrim * dLen) ;
}
//----------------------------------------------------------------------------
bool
CurveArc::TrimEndAtParam( double dUTrim)
{
double dLen ;
// riporto i parametri nel loro range
dUTrim = ( ( dUTrim < PAR_START) ? PAR_START : (( dUTrim > PAR_END) ? PAR_END : dUTrim)) ;
// recupero lunghezza
if ( ! GetLength( dLen))
return false ;
// utilizzo il trim sulle lunghezze
return TrimEndAtLen( dUTrim * dLen) ;
}
//----------------------------------------------------------------------------
bool
CurveArc::TrimStartAtLen( double dLenTrim)
{
double dLen ;
double dAngRot ;
double dMoveN ;
// lunghezze negative vengono considerate nulle
dLenTrim = __max( dLenTrim, 0) ;
// verifico che sia abbastanza lunga
if ( ! GetLength( dLen))
return false ;
if ( ( dLen - dLenTrim) < EPS_SMALL)
return false ;
// eseguo il trim
if ( dLenTrim > EPS_ZERO) {
dAngRot = m_dAngCenDeg * dLenTrim / dLen ;
m_VtS.Rotate( m_VtN, dAngRot * DEGTORAD) ;
m_dAngCenDeg -= dAngRot ;
if ( fabs( m_dDeltaN) > EPS_ZERO) {
dMoveN = m_dDeltaN * dLenTrim / dLen ;
m_PtCen.Translate( m_VtN * dMoveN) ;
m_dDeltaN -= dMoveN ;
}
}
// con i controlli sopra fatti rimane validata
return true ;
}
//----------------------------------------------------------------------------
bool
CurveArc::TrimEndAtLen( double dLenTrim)
{
double dLen ;
// lunghezze negative vengono considerate nulle
dLenTrim = __max( dLenTrim, 0) ;
// verifico che sia abbastanza lunga
if ( ! GetLength( dLen))
return false ;
if ( dLenTrim < EPS_SMALL)
return false ;
// eseguo il trim
if ( ( dLen - dLenTrim) > EPS_ZERO) {
m_dAngCenDeg *= dLenTrim / dLen ;
if ( fabs( m_dDeltaN) > EPS_ZERO)
m_dDeltaN *= dLenTrim / dLen ;
}
// con i controlli sopra fatti rimane validata
return true ;
}
//----------------------------------------------------------------------------
bool
CurveArc::Translate( const Vector3d& vtMove)
{
// traslo il centro
m_PtCen.Translate( vtMove) ;
return true ;
}
//----------------------------------------------------------------------------
bool
CurveArc::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng)
{
// verifico validità dell'asse di rotazione
if ( vtAx.IsSmall())
return false ;
// ruoto il centro e i versori
m_PtCen.Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
m_VtN.Rotate( vtAx, dCosAng, dSinAng) ;
m_VtS.Rotate( vtAx, dCosAng, dSinAng) ;
return true ;
}
//----------------------------------------------------------------------------
bool
CurveArc::Scale( const Point3d& ptCen, double dCoeffX, double dCoeffY, double dCoeffZ)
{
// ammessa solo scalatura uniforme
if ( fabs( dCoeffX - dCoeffY) > EPS_SMALL || fabs( dCoeffX - dCoeffZ) > EPS_SMALL)
return false ;
// verifico non sia nulla
if ( fabs( dCoeffX) < EPS_ZERO)
return false ;
// scalo il centro e le dimensioni lineari
m_PtCen.Scale( ptCen, dCoeffX, dCoeffX, dCoeffX) ;
m_dRad *= fabs( dCoeffX) ;
m_dDeltaN *= dCoeffX ;
if ( dCoeffX < 0)
m_VtS = - m_VtS ;
m_nStatus = TO_VERIFY ;
return Validate() ;
}
//----------------------------------------------------------------------------
bool
CurveArc::Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
{
// verifico validità del piano di specchiatura
if ( vtNorm.IsSmall())
return false ;
// specchio il centro e i versori, inverto l'angolo al centro
m_PtCen.Mirror( ptOn, vtNorm) ;
m_VtN.Mirror( vtNorm) ;
m_VtS.Mirror( vtNorm) ;
m_dAngCenDeg *= -1 ;
return true ;
}
//----------------------------------------------------------------------------
bool
CurveArc::ToGlob( const Frame3d& frRef)
{
// verifico validità del frame
if ( frRef.GetType() == Frame3d::ERR)
return false ;
// trasformo il centro e i versori
m_PtCen.ToGlob( frRef) ;
m_VtN.ToGlob( frRef) ;
m_VtS.ToGlob( frRef) ;
return true ;
}
//----------------------------------------------------------------------------
bool
CurveArc::ToLoc( const Frame3d& frRef)
{
// verifico validità del frame
if ( frRef.GetType() == Frame3d::ERR)
return false ;
// trasformo i punti estremi
m_PtCen.ToLoc( frRef) ;
m_VtN.ToLoc( frRef) ;
m_VtS.ToLoc( frRef) ;
return true ;
}