79978655d3
- prima versione delle superfici trimesh.
788 lines
22 KiB
C++
788 lines
22 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 "CurveArc.h"
|
|
#include "GeoConst.h"
|
|
#include "GeoObjFactory.h"
|
|
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
|
#include <new>
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
GEOOBJ_REGISTER( CRV_ARC, "C_ARC", CurveArc) ;
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
class ArcApproxer
|
|
{
|
|
public :
|
|
ArcApproxer( double dLinTol, double dAngTolDeg, bool bInside, const CurveArc& arArc) ;
|
|
bool GetPoint( double& dU, Point3d& ptP) ;
|
|
|
|
private :
|
|
Point3d m_PtCen ;
|
|
Vector3d m_VtN ;
|
|
double m_dRad ;
|
|
double m_dDeltaN ;
|
|
Vector3d m_vtA1 ;
|
|
Vector3d m_vtA2 ;
|
|
double m_dCosA ;
|
|
double m_dSinA ;
|
|
int m_nTotPnt ;
|
|
int m_nCurrPnt ;
|
|
bool m_bInside ;
|
|
} ;
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
CurveArc::CurveArc( void)
|
|
: m_nStatus( TO_VERIFY), m_PtCen(), m_VtN(), m_VtS(), m_dRad( 0), m_dAngCenDeg( 0), m_dDeltaN( 0)
|
|
{
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
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() ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
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 ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
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 ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return Validate() ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
CurveArc*
|
|
CurveArc::Clone( void) const
|
|
{
|
|
// alloco oggetto
|
|
CurveArc* pCrv = new(nothrow) CurveArc ;
|
|
if ( pCrv != nullptr) {
|
|
if ( ! pCrv->Copy( *this)) {
|
|
delete pCrv ;
|
|
return nullptr ;
|
|
}
|
|
}
|
|
|
|
return pCrv ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveArc::Copy( const IGeoObj* pGObjSrc)
|
|
{
|
|
const CurveArc* pCA = dynamic_cast<const CurveArc*>( pGObjSrc) ;
|
|
if ( pCA == nullptr)
|
|
return false ;
|
|
return Copy( *pCA) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveArc::Copy( const CurveArc& caSrc)
|
|
{
|
|
if ( &caSrc == this)
|
|
return true ;
|
|
return Set( caSrc.m_PtCen, caSrc.m_VtN, caSrc.m_dRad,
|
|
caSrc.m_VtS, caSrc.m_dAngCenDeg, caSrc.m_dDeltaN) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
const string&
|
|
CurveArc::GetTitle( void) const
|
|
{
|
|
static const string sTitle = "Arc" ;
|
|
return sTitle ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveArc::Dump( string& sOut, const char* szNewLine) const
|
|
{
|
|
// parametri : punti iniziale e finale
|
|
sOut += "C(" + ToString( m_PtCen) + ") " ;
|
|
sOut += "VN(" + ToString( m_VtN) + ") " ;
|
|
sOut += "R=" + ToString( m_dRad) + szNewLine ;
|
|
sOut += "VS(" + ToString( m_VtS) + ") " ;
|
|
sOut += "Ac=" + ToString( m_dAngCenDeg) + " " ;
|
|
sOut += "Dn=" + ToString( m_dDeltaN) + szNewLine ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
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)
|
|
{
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
// leggo la prossima linea
|
|
string sLine ;
|
|
if ( ! TheScanner.GetLine( sLine))
|
|
return false ;
|
|
// la divido in parametri
|
|
STRVECTOR vsParams ;
|
|
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::GetLocalBBox( BBox3d& b3Loc) const
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
// assegno il box in locale
|
|
b3Loc.Reset() ;
|
|
ArcApproxer aAppr( LIN_TOL_APPROX, ANG_TOL_APPROX_DEG, false, *this) ;
|
|
double dU ;
|
|
Point3d ptPos ;
|
|
while ( aAppr.GetPoint( dU, ptPos))
|
|
b3Loc.Add( ptPos) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveArc::GetBBox( const Frame3d& frRef, BBox3d& b3Ref) const
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
// verifico validità del frame
|
|
if ( frRef.GetType() == Frame3d::ERR)
|
|
return false ;
|
|
// assegno il box nel riferimento
|
|
b3Ref.Reset() ;
|
|
ArcApproxer aAppr( LIN_TOL_APPROX, ANG_TOL_APPROX_DEG, false, *this) ;
|
|
double dU ;
|
|
Point3d ptPos ;
|
|
while ( aAppr.GetPoint( dU, ptPos)) {
|
|
ptPos.ToGlob( frRef) ;
|
|
b3Ref.Add( ptPos) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveArc::Validate( void)
|
|
{
|
|
if ( m_nStatus == TO_VERIFY) {
|
|
// limito l'angolo al centro a un giro se è piatto ( non è elica)
|
|
if ( fabs( m_dDeltaN) < EPS_SMALL) {
|
|
if ( m_dAngCenDeg > 360.0)
|
|
m_dAngCenDeg = 360.0 ;
|
|
else if ( m_dAngCenDeg < - 360.0)
|
|
m_dAngCenDeg = - 360.0 ;
|
|
}
|
|
// eseguo il controllo
|
|
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 ;
|
|
if ( fabs( m_dDeltaN) > EPS_ZERO)
|
|
ptEnd += m_dDeltaN * m_VtN ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveArc::GetPointD1D2( double dU, Side nS, Point3d& ptPos, Vector3d* pvtDer1, Vector3d* pvtDer2) const
|
|
{
|
|
// la curva deve essere valida
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// 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)
|
|
double dAng = dU * m_dAngCenDeg * DEGTORAD ;
|
|
Vector3d 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 += ( dU * m_dDeltaN) * m_VtN ;
|
|
|
|
// calcolo della derivata prima
|
|
if ( pvtDer1 != nullptr) {
|
|
*pvtDer1 = ( m_dRad * m_dAngCenDeg * DEGTORAD) * ( m_VtN ^ vtDir) ;
|
|
if ( fabs( m_dDeltaN) > EPS_ZERO)
|
|
*pvtDer1 += m_dDeltaN * m_VtN ;
|
|
}
|
|
|
|
// calcolo della derivata seconda
|
|
if ( pvtDer2 != nullptr && pvtDer1 != nullptr)
|
|
*pvtDer2 = - ( m_dRad * m_dAngCenDeg * DEGTORAD * m_dAngCenDeg * DEGTORAD) * vtDir ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveArc::GetLength( double& dLen) const
|
|
{
|
|
// la curva deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// 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
|
|
{
|
|
ArcApproxer aAppr( dLinTol, dAngTolDeg, true, *this) ;
|
|
double dU ;
|
|
Point3d ptPos ;
|
|
while ( aAppr.GetPoint( dU, ptPos))
|
|
PL.AddUPoint( dU, ptPos) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveArc::Invert( void)
|
|
{
|
|
// la curva deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// il centro va spostato di DeltaN
|
|
if ( m_dDeltaN > EPS_ZERO)
|
|
m_PtCen += m_dDeltaN * m_VtN ;
|
|
// il versore normale rimane inalterato
|
|
// il versore iniziale diventa quello finale
|
|
double 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 ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveArc::TrimStartAtParam( double dUTrim)
|
|
{
|
|
double dLen ;
|
|
|
|
|
|
// riporto i parametri nel loro range
|
|
dUTrim = ( ( dUTrim < 0) ? 0 : (( dUTrim > 1) ? 1 : 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 < 0) ? 0 : (( dUTrim > 1) ? 1 : dUTrim)) ;
|
|
|
|
// recupero lunghezza
|
|
if ( ! GetLength( dLen))
|
|
return false ;
|
|
|
|
// utilizzo il trim sulle lunghezze
|
|
return TrimEndAtLen( dUTrim * dLen) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveArc::TrimStartAtLen( double dLenTrim)
|
|
{
|
|
// lunghezze negative vengono considerate nulle
|
|
dLenTrim = __max( dLenTrim, 0) ;
|
|
|
|
// verifico che sia abbastanza lunga
|
|
double dLen ;
|
|
if ( ! GetLength( dLen))
|
|
return false ;
|
|
if ( ( dLen - dLenTrim) < EPS_SMALL)
|
|
return false ;
|
|
|
|
// eseguo il trim
|
|
if ( dLenTrim > EPS_ZERO) {
|
|
double dAngRot ;
|
|
double dMoveN ;
|
|
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, ma la grafica va ricalcolata
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveArc::TrimEndAtLen( double dLenTrim)
|
|
{
|
|
// lunghezze negative vengono considerate nulle
|
|
dLenTrim = __max( dLenTrim, 0) ;
|
|
|
|
// verifico che sia abbastanza lunga
|
|
double dLen ;
|
|
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, ma la grafica va ricalcolata
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveArc::Translate( const Vector3d& vtMove)
|
|
{
|
|
// la curva deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// traslo il centro
|
|
m_PtCen.Translate( vtMove) ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveArc::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng)
|
|
{
|
|
// la curva deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// 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) ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveArc::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dCoeffZ)
|
|
{
|
|
// la curva deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// 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( frRef, dCoeffX, dCoeffX, dCoeffX) ;
|
|
m_dRad *= fabs( dCoeffX) ;
|
|
m_dDeltaN *= dCoeffX ;
|
|
if ( dCoeffX < 0)
|
|
m_VtS = - m_VtS ;
|
|
m_nStatus = TO_VERIFY ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return Validate() ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveArc::Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
|
|
{
|
|
// la curva deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// 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 ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveArc::ToGlob( const Frame3d& frRef)
|
|
{
|
|
// la curva deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// 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) ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveArc::ToLoc( const Frame3d& frRef)
|
|
{
|
|
// la curva deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// 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) ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Oggetto locale per approssimazione di archi
|
|
// Approx interna è quella cordale standard.
|
|
// Approx esterna è quella tangente a inizio e fine con metà tratto e un punto in più.
|
|
// I punti si calcolano a partire dal triangolo tra due punti consecutivi interni e il centro,
|
|
// usando il versore medio dal centro e moltiplicandolo per il coefficiente ( 2 / ( 1 + cosA)).
|
|
// Il versore dell'ultimo punto è già stato calcolato per il penultimo.
|
|
//----------------------------------------------------------------------------
|
|
ArcApproxer::ArcApproxer( double dLinTol, double dAngTolDeg, bool bInside, const CurveArc& arArc)
|
|
{
|
|
int nStep ;
|
|
double dAngStepDeg ;
|
|
|
|
|
|
// inizializzazioni
|
|
m_nTotPnt = 0 ;
|
|
m_nCurrPnt = - 1 ;
|
|
|
|
// la curva deve essere validata
|
|
if ( ! arArc.IsValid())
|
|
return ;
|
|
|
|
// limiti minimi su tolleranza e deviazione angolare
|
|
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
|
dAngTolDeg = max( dAngTolDeg, ANG_TOL_MIN_DEG) ;
|
|
|
|
// limite massimo su deviazione angolare se approssimazione esterna
|
|
if ( ! bInside)
|
|
dAngTolDeg = min( dAngTolDeg, ANG_TOL_EXT_MAX_DEG) ;
|
|
|
|
// determinazione dello step angolare
|
|
dAngStepDeg = sqrt( 8 * dLinTol / arArc.GetRadius()) * RADTODEG ;
|
|
dAngStepDeg = min( dAngStepDeg, dAngTolDeg) ;
|
|
|
|
// dall'angolo al centro ricavo il numero di passi
|
|
nStep = (int) ( fabs( arArc.GetAngCenter()) / dAngStepDeg + 0.999) ;
|
|
nStep = __max( nStep, 1) ;
|
|
|
|
// sistemo lo step (per il numero intero di passi)
|
|
dAngStepDeg = arArc.GetAngCenter() / nStep ;
|
|
|
|
// versori di riferimento nel piano dell'arco
|
|
m_vtA1 = arArc.GetStartVersor() ;
|
|
m_vtA2 = arArc.GetNormVersor() ^ arArc.GetStartVersor() ;
|
|
|
|
// seno e coseno dell'angolo di step
|
|
m_dCosA = cos( dAngStepDeg * DEGTORAD) ;
|
|
m_dSinA = sin( dAngStepDeg * DEGTORAD) ;
|
|
|
|
// salvo i dati
|
|
m_bInside = bInside ;
|
|
m_nTotPnt = ( m_bInside ? ( nStep + 1) : ( nStep + 2)) ;
|
|
m_PtCen = arArc.GetCenter() ;
|
|
m_VtN = arArc.GetNormVersor() ;
|
|
m_dRad = arArc.GetRadius() ;
|
|
m_dDeltaN = arArc.GetDeltaN() ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ArcApproxer::GetPoint( double& dU, Point3d& ptP)
|
|
{
|
|
Vector3d vtA1p ;
|
|
Vector3d vtA2p ;
|
|
|
|
|
|
// incremento indice punto corrente
|
|
++ m_nCurrPnt ;
|
|
|
|
// se oltrepassata la fine
|
|
if ( m_nCurrPnt >= m_nTotPnt)
|
|
return false ;
|
|
|
|
// primo punto
|
|
if ( m_nCurrPnt == 0) {
|
|
dU = 0 ;
|
|
ptP = m_PtCen + m_vtA1 * m_dRad ;
|
|
return true ;
|
|
}
|
|
|
|
// se approx esterna e ultimo punto (uso rotazione precedente)
|
|
if ( ! m_bInside && m_nCurrPnt == m_nTotPnt - 1) {
|
|
dU = 1 ;
|
|
ptP = m_PtCen + m_vtA1 * m_dRad ;
|
|
if ( fabs( m_dDeltaN) > EPS_ZERO)
|
|
ptP += ( dU * m_dDeltaN) * m_VtN ;
|
|
return true ;
|
|
}
|
|
|
|
// punti successivi
|
|
// calcolo parametro
|
|
if ( m_bInside)
|
|
dU = m_nCurrPnt / (double) ( m_nTotPnt - 1) ;
|
|
else
|
|
dU = ( m_nCurrPnt - 0.5) / (double) ( m_nTotPnt - 2) ;
|
|
// nuovo valore versori
|
|
vtA1p = m_vtA1 ;
|
|
vtA2p = m_vtA2 ;
|
|
m_vtA1 = m_dCosA * vtA1p + m_dSinA * vtA2p ;
|
|
m_vtA2 = - m_dSinA * vtA1p + m_dCosA * vtA2p ;
|
|
// calcolo del punto
|
|
if ( m_bInside)
|
|
ptP = m_PtCen + m_vtA1 * m_dRad ;
|
|
else
|
|
ptP = m_PtCen + ( vtA1p + m_vtA1) * ( m_dRad / ( 1 + m_dCosA)) ;
|
|
if ( fabs( m_dDeltaN) > EPS_ZERO)
|
|
ptP += ( dU * m_dDeltaN) * m_VtN ;
|
|
|
|
return true ;
|
|
}
|