4097bcd178
- gestione salvataggio in modalità testo compresso - aggiunto controlli in scritture per salvataggio.
1307 lines
38 KiB
C++
1307 lines
38 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2013-2013
|
|
//----------------------------------------------------------------------------
|
|
// File : CurveComposite.cpp Data : 23.11.13 Versione : 1.3a1
|
|
// Contenuto : Implementazione della classe CCurveComposite.
|
|
//
|
|
//
|
|
//
|
|
// Modifiche : 26.04.13 DS Creazione modulo.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "CurveComposite.h"
|
|
#include "DistPointCrvComposite.h"
|
|
#include "GeoConst.h"
|
|
#include "GeoObjFactory.h"
|
|
#include "NgeWriter.h"
|
|
#include "NgeReader.h"
|
|
#include "/EgtDev/Include/EGnStringUtils.h"
|
|
#include "/EgtDev/Include/EgtPointerOwner.h"
|
|
#include "/EgtDev/Include/EGkCurveLine.h"
|
|
#include "/EgtDev/Include/EGkCurveArc.h"
|
|
#include "/EgtDev/Include/EGkCurveBezier.h"
|
|
#include <algorithm>
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
GEOOBJ_REGISTER( CRV_COMPO, NGE_C_CMP, CurveComposite) ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
CurveComposite::CurveComposite( void)
|
|
: m_nStatus( TO_VERIFY), m_nCounter( 0), m_bClosed( false)
|
|
{
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
CurveComposite::~CurveComposite( void)
|
|
{
|
|
Clear() ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::Clear( void)
|
|
{
|
|
// ciclo di pulizia
|
|
PCRVSMPL_LIST::iterator Iter ;
|
|
for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter)
|
|
delete (*Iter) ;
|
|
|
|
m_CrvSmplS.clear() ;
|
|
|
|
m_nStatus = TO_VERIFY ;
|
|
m_nCounter = 0 ;
|
|
m_bClosed = false ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::AddCurve( const ICurve& cCrv)
|
|
{
|
|
// se curva semplice
|
|
if ( cCrv.IsSimple()) {
|
|
// creo una copia della curva
|
|
ICurve* pSmplCrv = GetCurve( cCrv.Clone()) ;
|
|
if ( pSmplCrv == nullptr)
|
|
return false ;
|
|
// inserisco la curva
|
|
if ( ! AddSimpleCurve( pSmplCrv))
|
|
return false ;
|
|
}
|
|
// altrimenti curva composta, devo aggiungere le singole curve semplici
|
|
else {
|
|
const ICurveComposite* pCrvCompo ;
|
|
const ICurve* pCrvOri ;
|
|
ICurve* pSmplCrv ;
|
|
// recupero le curve componenti e le inserisco nella lista
|
|
pCrvCompo = GetCurveComposite( &cCrv) ;
|
|
if ( pCrvCompo == nullptr)
|
|
return false ;
|
|
pCrvOri = pCrvCompo->GetFirstCurve() ;
|
|
while ( pCrvOri != nullptr) {
|
|
// creo una copia della curva
|
|
pSmplCrv = GetCurve( pCrvOri->Clone()) ;
|
|
if ( pSmplCrv == nullptr)
|
|
return false ;
|
|
// inserisco la curva
|
|
if ( ! AddSimpleCurve( pSmplCrv))
|
|
return false ;
|
|
// passo alla prossima curva componente
|
|
pCrvOri = pCrvCompo->GetNextCurve() ;
|
|
}
|
|
}
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::AddCurve( ICurve* pCrv)
|
|
{
|
|
// se curva semplice
|
|
if ( pCrv->IsSimple()) {
|
|
// inserisco la curva
|
|
if ( ! AddSimpleCurve( pCrv))
|
|
return false ;
|
|
}
|
|
// altrimenti curva composta, devo aggiungere le singole curve semplici
|
|
else {
|
|
// puntatore alla curva composita originaria
|
|
CurveComposite* pCrvCompo = dynamic_cast<CurveComposite*>( pCrv) ;
|
|
if ( pCrvCompo == nullptr)
|
|
return false ;
|
|
// recupero le curve componenti e le inserisco nella lista
|
|
ICurve* pSmplCrv ;
|
|
while ( ( pSmplCrv = pCrvCompo->RemoveFirstCurve()) != nullptr) {
|
|
// inserisco la curva
|
|
if ( ! AddSimpleCurve( pSmplCrv))
|
|
return false ;
|
|
}
|
|
// cancello la curva composita originaria
|
|
delete pCrvCompo ;
|
|
}
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::AddSimpleCurve( ICurve* pSmplCrv)
|
|
{
|
|
Point3d ptStart ;
|
|
Point3d ptEnd ;
|
|
|
|
|
|
// prendo la proprietà del puntatore
|
|
PtrOwner<ICurve> pCrv( pSmplCrv) ;
|
|
if ( ! ::IsValid( pCrv))
|
|
return false ;
|
|
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK && ! ( m_nCounter == 0 && m_nStatus == TO_VERIFY))
|
|
return false ;
|
|
|
|
// verifico che il parametro sia una curva semplice
|
|
if ( ! pCrv->IsSimple())
|
|
return false ;
|
|
|
|
// recupero i punti iniziali e finali della curva
|
|
if ( ! pCrv->GetStartPoint( ptStart) || ! pCrv->GetEndPoint( ptEnd))
|
|
return false ;
|
|
|
|
// se non è la prima, verifico sia in continuità con il finale corrente
|
|
if ( m_nCounter > 0 && ! AreSamePointNear( ptStart, m_PtEnd))
|
|
return false ;
|
|
|
|
// se prima curva, assegno il punto iniziale
|
|
if ( m_nCounter == 0)
|
|
m_PtStart = ptStart ;
|
|
|
|
// inserisco la curva nella lista
|
|
m_CrvSmplS.push_back( ::Release( pCrv)) ;
|
|
m_nCounter ++ ;
|
|
|
|
// assegno il punto finale
|
|
m_PtEnd = ptEnd ;
|
|
|
|
// aggiorno il flag di curva chiusa
|
|
m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ;
|
|
|
|
// aggiorno lo stato
|
|
m_nStatus = OK ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::FromSplit( const ICurve& cCrv, int nParts)
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nCounter != 0 || m_nStatus != TO_VERIFY)
|
|
return false ;
|
|
|
|
// deve essere valida e semplice
|
|
if ( ! cCrv.IsValid() || ! cCrv.IsSimple())
|
|
return false ;
|
|
|
|
// se 1 parte o meno, non fa alcunchè
|
|
if ( nParts <= 1)
|
|
return true ;
|
|
|
|
// calcolo la lunghezza della curva
|
|
double dTotLen ;
|
|
if ( ! cCrv.GetLength( dTotLen))
|
|
return false ;
|
|
|
|
// ciclo di inserimento delle parti
|
|
double dStartLen = 0 ;
|
|
double dEndLen = 0 ;
|
|
for ( int i = 1 ; i <= nParts ; ++ i) {
|
|
dStartLen = dEndLen ;
|
|
dEndLen = dTotLen * i / (double) nParts ;
|
|
PtrOwner<ICurve> pSmplCrv( GetCurve( cCrv.Clone())) ;
|
|
if ( ! ::IsValid( pSmplCrv))
|
|
return false ;
|
|
if ( ! pSmplCrv->TrimEndAtLen( dEndLen) ||
|
|
! pSmplCrv->TrimStartAtLen( dStartLen))
|
|
return false ;
|
|
if ( ! AddSimpleCurve( Release( pSmplCrv)))
|
|
return false ;
|
|
}
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::FromPointVector( const PNTVECTOR& vPnt)
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nCounter != 0 || m_nStatus != TO_VERIFY)
|
|
return false ;
|
|
// devono essere almeno 2 punti
|
|
if ( vPnt.size() < 2)
|
|
return false ;
|
|
|
|
// ciclo di inserimento dei segmenti che uniscono i punti
|
|
int iPrev = 0 ;
|
|
for ( int i = 1 ; i < int( vPnt.size()) ; ++ i) {
|
|
// se i punti della coppia coincidono, passo alla coppia successiva
|
|
if ( AreSamePointNear( vPnt[iPrev], vPnt[i]))
|
|
continue ;
|
|
// creo il segmento di retta
|
|
PtrOwner<ICurveLine> pCrvLine( CreateCurveLine()) ;
|
|
if ( ! ::IsValid( pCrvLine))
|
|
return false ;
|
|
// assegno i punti estremi
|
|
if ( ! pCrvLine->Set( vPnt[iPrev], vPnt[i]))
|
|
return false ;
|
|
// aggiungo la retta alla curva composita
|
|
if ( ! AddSimpleCurve( Release( pCrvLine)))
|
|
return false ;
|
|
// aggiorno indice punto ultimo inserito
|
|
iPrev = i ;
|
|
}
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::FromPointBulgeVector( const UPNTVECTOR& vUPnt, const Vector3d& vtN)
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nCounter != 0 || m_nStatus != TO_VERIFY)
|
|
return false ;
|
|
// devono essere almeno 2 punti
|
|
if ( vUPnt.size() < 2)
|
|
return false ;
|
|
|
|
// Creo le diverse curve semplici e le inserisco in quella composita
|
|
int iPrev = 0 ;
|
|
for ( int i = 1 ; i < int( vUPnt.size()) ; ++i) {
|
|
// se i punti della coppia coincidono, passo alla coppia successiva
|
|
if ( AreSamePointNear( vUPnt[iPrev].second, vUPnt[i].second))
|
|
continue ;
|
|
// se retta
|
|
if ( fabs( vUPnt[i-1].first) < EPS_SMALL) {
|
|
// creo la retta
|
|
PtrOwner<ICurveLine> pCrvLine( CreateCurveLine()) ;
|
|
if ( ! ::IsValid( pCrvLine))
|
|
return false ;
|
|
// setto la linea
|
|
if ( ! pCrvLine->Set( vUPnt[iPrev].second, vUPnt[i].second))
|
|
return false ;
|
|
// inserisco la linea nella curva composta
|
|
if ( ! AddSimpleCurve( ::Release( pCrvLine)))
|
|
return false ;
|
|
}
|
|
// altrimenti arco
|
|
else {
|
|
// creo l'arco
|
|
PtrOwner<ICurveArc> pCrvArc( CreateCurveArc()) ;
|
|
if ( ! ::IsValid( pCrvArc))
|
|
return false ;
|
|
// setto l'arco
|
|
if ( ! pCrvArc->Set2PNB( vUPnt[iPrev].second, vUPnt[i].second, vtN, vUPnt[i-1].first))
|
|
return false ;
|
|
// inserisco l'arco nella curva composta
|
|
if ( ! AddSimpleCurve( Release( pCrvArc)))
|
|
return false ;
|
|
}
|
|
// aggiorno indice punto ultimo inserito
|
|
iPrev = i ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
CurveComposite*
|
|
CurveComposite::Clone( void) const
|
|
{
|
|
// alloco oggetto
|
|
CurveComposite* pCrv = new(nothrow) CurveComposite ;
|
|
if ( pCrv != nullptr) {
|
|
if ( ! pCrv->Copy( *this)) {
|
|
delete pCrv ;
|
|
return nullptr ;
|
|
}
|
|
}
|
|
|
|
return pCrv ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::Copy( const IGeoObj* pGObjSrc)
|
|
{
|
|
const CurveComposite* pCC = dynamic_cast<const CurveComposite*>( pGObjSrc) ;
|
|
if ( pCC == nullptr)
|
|
return false ;
|
|
return Copy( *pCC) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::Copy( const CurveComposite& ccSrc)
|
|
{
|
|
if ( &ccSrc == this)
|
|
return true ;
|
|
Clear() ;
|
|
PCRVSMPL_LIST::const_iterator Iter ;
|
|
for ( Iter = ccSrc.m_CrvSmplS.begin() ; Iter != ccSrc.m_CrvSmplS.end() ; ++Iter) {
|
|
if ( ! AddCurve( **Iter))
|
|
return false ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
GeoObjType
|
|
CurveComposite::GetType( void) const
|
|
{
|
|
return static_cast<GeoObjType>( GEOOBJ_GETTYPE( CurveComposite)) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
const string&
|
|
CurveComposite::GetTitle( void) const
|
|
{
|
|
static const string sTitle = "CComposite" ;
|
|
return sTitle ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::Dump( string& sOut, const char* szNewLine) const
|
|
{
|
|
// se curva aperta o chiusa
|
|
sOut += ( IsClosed() ? "Closed" : "Open") ;
|
|
// numero di curve
|
|
sOut += " CrvNbr=" + ToString( m_nCounter) + szNewLine ;
|
|
// ciclo sulle curve componenti
|
|
int i = 0 ;
|
|
const ICurve* pCrvSmpl = GetFirstCurve() ;
|
|
while ( pCrvSmpl != nullptr) {
|
|
// assegno ed emetto nome e tipo della curva semplice
|
|
sOut += "#" + ToString( ++i) + " " + pCrvSmpl->GetTitle() + szNewLine ;
|
|
// salvataggio della curva semplice
|
|
if ( ! pCrvSmpl->Dump( sOut, szNewLine))
|
|
return false ;
|
|
// passo alla successiva
|
|
pCrvSmpl = GetNextCurve() ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
CurveComposite::GetNgeId( void) const
|
|
{
|
|
return GEOOBJ_GETNGEID( CurveComposite) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::Save( NgeWriter& ngeOut) const
|
|
{
|
|
// numero di curve
|
|
if ( ! ngeOut.WriteInt( m_nCounter, nullptr, true))
|
|
return false ;
|
|
// ciclo sulle curve componenti
|
|
int i = 0 ;
|
|
const ICurve* pCrvSmpl = GetFirstCurve() ;
|
|
while ( pCrvSmpl != nullptr) {
|
|
// recupero il gestore di lettura/scrittura delle curve
|
|
const IGeoObjRW* pCSmplRW = dynamic_cast<const IGeoObjRW*>( pCrvSmpl) ;
|
|
if ( pCSmplRW == nullptr)
|
|
return false ;
|
|
// emetto tipo della curva semplice
|
|
if ( ! ngeOut.WriteKey( pCSmplRW->GetNgeId()))
|
|
return false ;
|
|
// assegno ed emetto nome della curva semplice
|
|
string sCrvName = "#" + ToString( ++i) ;
|
|
if ( ! ngeOut.WriteString( sCrvName, nullptr, true))
|
|
return false ;
|
|
// salvataggio della curva semplice
|
|
if ( ! pCSmplRW->Save( ngeOut))
|
|
return false ;
|
|
// passo alla successiva
|
|
pCrvSmpl = GetNextCurve() ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::Load( NgeReader& ngeIn)
|
|
{
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
// leggo la prossima linea ( 1 parametro)
|
|
// recupero il numero di curve componenti
|
|
int nCounter ;
|
|
if ( ! ngeIn.ReadInt( nCounter, nullptr, true))
|
|
return false ;
|
|
// leggo le curve componenti
|
|
for ( int i = 0 ; i < nCounter ; ++ i) {
|
|
// recupero la prossima linea (con il tipo di oggetto)
|
|
int nNgeId ;
|
|
if ( ! ngeIn.ReadKey( nNgeId))
|
|
return false ;
|
|
// creo l'oggetto
|
|
int nType = GEOOBJ_NGEIDTOTYPE( nNgeId) ;
|
|
IGeoObj* pGeoO = GEOOBJ_CREATE( nType) ;
|
|
if ( pGeoO == nullptr)
|
|
return false ;
|
|
// recupero la linea con il nome
|
|
string sName ;
|
|
bool bOk = ngeIn.ReadString( sName, nullptr, true) ;
|
|
// ne leggo i dati
|
|
IGeoObjRW* pGObjRW = dynamic_cast<IGeoObjRW*>( pGeoO) ;
|
|
bOk = bOk && ( pGObjRW != nullptr && pGObjRW->Load( ngeIn)) ;
|
|
// verifico sia una curva
|
|
ICurve* pCrv = ::GetCurve( pGeoO) ;
|
|
bOk = bOk && ( pCrv != nullptr && pCrv->IsSimple()) ;
|
|
// aggiungo questa curva (sicuramente semplice)
|
|
bOk = bOk && AddSimpleCurve( pCrv) ;
|
|
// se errore
|
|
if ( ! bOk)
|
|
return false ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::GetLocalBBox( BBox3d& b3Loc) const
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
// inizializzo il box
|
|
b3Loc.Reset() ;
|
|
// ciclo sulle curve componenti
|
|
const ICurve* pCrvSmpl ;
|
|
pCrvSmpl = GetFirstCurve() ;
|
|
while ( pCrvSmpl != nullptr) {
|
|
BBox3d b3Crv ;
|
|
// recupero il box della curva
|
|
pCrvSmpl->GetLocalBBox( b3Crv) ;
|
|
// aggiorno il box
|
|
b3Loc.Add( b3Crv) ;
|
|
// passo alla curva successiva
|
|
pCrvSmpl = GetNextCurve() ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::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 ;
|
|
// inizializzo il box
|
|
b3Ref.Reset() ;
|
|
// ciclo sulle curve componenti
|
|
const ICurve* pCrvSmpl ;
|
|
pCrvSmpl = GetFirstCurve() ;
|
|
while ( pCrvSmpl != nullptr) {
|
|
BBox3d b3Crv ;
|
|
// recupero il box della curva
|
|
pCrvSmpl->GetBBox( frRef, b3Crv) ;
|
|
// aggiorno il box
|
|
b3Ref.Add( b3Crv) ;
|
|
// passo alla curva successiva
|
|
pCrvSmpl = GetNextCurve() ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::Validate( void)
|
|
{
|
|
if ( m_nStatus == TO_VERIFY) {
|
|
int nCount ;
|
|
Point3d ptPrevEnd ;
|
|
Point3d ptStart ;
|
|
PCRVSMPL_LIST::const_iterator Iter ;
|
|
// ciclo su tutte le curve
|
|
nCount = 0 ;
|
|
for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) {
|
|
// verifico validità della curva e sua semplicità
|
|
if ( ! (*Iter)->IsValid() || (*Iter)->GetType() == CRV_COMPO) {
|
|
m_nStatus = ERR ;
|
|
return false ;
|
|
}
|
|
// incremento contatore
|
|
++ nCount ;
|
|
// verifico continuità con la precedente (se non è la prima)
|
|
if ( nCount > 1) {
|
|
(*Iter)->GetStartPoint( ptStart) ;
|
|
if ( ! AreSamePointNear( ptPrevEnd, ptStart)) {
|
|
m_nStatus = ERR ;
|
|
return false ;
|
|
}
|
|
}
|
|
// recupero il punto finale
|
|
(*Iter)->GetEndPoint( ptPrevEnd) ;
|
|
}
|
|
// aggiorno
|
|
m_nStatus = OK ;
|
|
m_nCounter = nCount ;
|
|
m_CrvSmplS.front()->GetStartPoint( m_PtStart) ;
|
|
m_CrvSmplS.back()->GetEndPoint( m_PtEnd) ;
|
|
m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ;
|
|
}
|
|
|
|
return ( m_nStatus == OK) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::GetStartPoint( Point3d& ptStart) const
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// assegno il punto
|
|
ptStart = m_PtStart ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::GetEndPoint( Point3d& ptEnd) const
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// assegno il punto
|
|
ptEnd = m_PtEnd ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::GetMidPoint( Point3d& ptMid) const
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// determino il valore medio del parametro della curva
|
|
double dStart, dEnd, dMid ;
|
|
GetDomain( dStart, dEnd) ;
|
|
dMid = 0.5 * ( dStart + dEnd) ;
|
|
|
|
// calcolo il punto
|
|
return GetPointD1D2( dMid, FROM_MINUS, ptMid) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::GetDomain( double& dStart, double& dEnd) const
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// assegno gli estremi del dominio
|
|
dStart = 0 ;
|
|
dEnd = m_nCounter ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::GetPointD1D2( double dU, Side nS, Point3d& ptPos, Vector3d* pvtDer1, Vector3d* pvtDer2) const
|
|
{
|
|
PCRVSMPL_LIST::const_iterator Iter ;
|
|
|
|
|
|
// il parametro U deve essere compreso tra 0 e m_nCounter
|
|
if ( dU < ( 0 + EPS_ZERO)) {
|
|
dU = 0 ;
|
|
nS = ICurve::FROM_PLUS ;
|
|
}
|
|
else if ( dU > ( m_nCounter - EPS_ZERO)) {
|
|
dU = m_nCounter ;
|
|
nS = ICurve::FROM_MINUS ;
|
|
}
|
|
|
|
// determino la curva di appartenenza e faccio eseguire il calcolo
|
|
for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) {
|
|
// ogni curva semplice ha parametro compreso tra 0 e 1
|
|
// se nella parametrizzazione della curva semplice, oppure all'estremo superiore e dal basso
|
|
if ( dU < ( 1 - EPS_ZERO) ||
|
|
( fabs( dU - 1) < EPS_ZERO && nS == ICurve::FROM_MINUS))
|
|
return (*Iter)->GetPointD1D2( dU, ICurve::FROM_MINUS, ptPos, pvtDer1, pvtDer2) ;
|
|
else
|
|
dU -= 1 ;
|
|
}
|
|
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::GetLength( double& dLen) const
|
|
{
|
|
double dLenCrvSmpl ;
|
|
PCRVSMPL_LIST::const_iterator Iter ;
|
|
|
|
|
|
// ciclo di calcolo
|
|
dLen = 0 ;
|
|
for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) {
|
|
if ( (*Iter)->GetLength( dLenCrvSmpl))
|
|
dLen += dLenCrvSmpl ;
|
|
else
|
|
return false ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::IsPointOn( const Point3d& ptP, double dTol) const
|
|
{
|
|
double dSqDist ;
|
|
dTol = max( dTol, EPS_ZERO) ;
|
|
return ( DistPointCrvComposite( ptP, *this).GetSqDist( dSqDist) && dSqDist < dTol * dTol) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const
|
|
{
|
|
// pulisco la polilinea
|
|
PL.Clear() ;
|
|
|
|
// la curva deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// eseguo approssimazione
|
|
bool bFirst = true ;
|
|
double dStartPar = 0 ;
|
|
PolyLine PLSmpl ;
|
|
PCRVSMPL_LIST::const_iterator Iter ;
|
|
for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) {
|
|
// recupero approssimazione per curva semplice
|
|
if ( ! (*Iter)->ApproxWithLines( dLinTol, dAngTolDeg, PLSmpl))
|
|
return false ;
|
|
// la accodo opportunamente a quella della curva composita
|
|
if ( bFirst) {
|
|
PL.Splice( PLSmpl) ;
|
|
bFirst = false ;
|
|
}
|
|
else {
|
|
PLSmpl.EraseFirstUPoint() ;
|
|
PLSmpl.AddOffsetToU( dStartPar) ;
|
|
PL.Splice( PLSmpl) ;
|
|
}
|
|
// incremento inizio parametro per prossima curva semplice
|
|
dStartPar += 1 ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::Invert( void)
|
|
{
|
|
// inverto le singole curve
|
|
PCRVSMPL_LIST::iterator Iter ;
|
|
for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter)
|
|
(*Iter)->Invert() ;
|
|
|
|
// inverto l'ordine della lista
|
|
m_CrvSmplS.reverse() ;
|
|
|
|
// scambio punti iniziale e finale
|
|
swap( m_PtStart, m_PtEnd) ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::TrimStartAtParam( double dUTrim)
|
|
{
|
|
double dParStart ;
|
|
double dParEnd ;
|
|
double dUToTrim ;
|
|
PCRVSMPL_LIST::iterator Iter ;
|
|
|
|
|
|
// ciclo sulle diverse curve dall'inizio
|
|
dUToTrim = dUTrim ;
|
|
for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ;) {
|
|
// dominio parametrico della curva semplice
|
|
(*Iter)->GetDomain( dParStart, dParEnd) ;
|
|
// lunghezza parametrica progressiva
|
|
dUToTrim -= ( dParEnd - dParStart) ;
|
|
// se lunghezza ancora da tagliare non nulla
|
|
if ( dUToTrim > EPS_ZERO) {
|
|
delete (*Iter) ;
|
|
Iter ++ ;
|
|
m_CrvSmplS.pop_front() ;
|
|
m_nCounter -- ;
|
|
}
|
|
// se lunghezza ancora da tagliare nulla (entro la tolleranza)
|
|
else if ( dUToTrim > - EPS_ZERO) {
|
|
delete (*Iter) ;
|
|
Iter ++ ;
|
|
m_CrvSmplS.pop_front() ;
|
|
m_nCounter -- ;
|
|
if ( m_nCounter == 0)
|
|
return false ;
|
|
(*Iter)->GetStartPoint( m_PtStart) ;
|
|
m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ;
|
|
break ;
|
|
}
|
|
// altrimenti superata lunghezza ancora da tagliare
|
|
else {
|
|
if ( ! (*Iter)->TrimStartAtParam( 1 + dUToTrim)) {
|
|
m_nStatus = ERR ;
|
|
return false ;
|
|
}
|
|
(*Iter)->GetStartPoint( m_PtStart) ;
|
|
m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ;
|
|
break ;
|
|
}
|
|
}
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::TrimEndAtParam( double dUTrim)
|
|
{
|
|
bool bToErase ;
|
|
double dParStart ;
|
|
double dParEnd ;
|
|
double dUToTrim ;
|
|
PCRVSMPL_LIST::iterator Iter ;
|
|
|
|
|
|
// ciclo sulle diverse curve dalla fine
|
|
bToErase = false ;
|
|
dUToTrim = dUTrim ;
|
|
for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ;) {
|
|
// dominio parametrico della curva semplice
|
|
(*Iter)->GetDomain( dParStart, dParEnd) ;
|
|
// lunghezza parametrica progressiva
|
|
dUToTrim -= ( dParEnd - dParStart) ;
|
|
// se da cancellare
|
|
if ( bToErase) {
|
|
// cancello l'entità, la tolgo dalla lista e passo alla successiva
|
|
delete (*Iter) ;
|
|
Iter = m_CrvSmplS.erase( Iter) ;
|
|
// decremento il numero di entità
|
|
m_nCounter -- ;
|
|
}
|
|
// se lunghezza parametrica ancora da tagliare non nulla
|
|
else if ( dUToTrim > EPS_ZERO) {
|
|
Iter ++ ;
|
|
}
|
|
// se lunghezza parametrica ancora da tagliare nulla (entro la tolleranza)
|
|
else if ( dUToTrim > - EPS_ZERO) {
|
|
// imposto punto finale e verifico curva chiusa
|
|
(*Iter)->GetEndPoint( m_PtEnd) ;
|
|
m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ;
|
|
// passo alla entità successiva
|
|
++ Iter ;
|
|
// dichiaro ingresso in zona da cancellare
|
|
bToErase = true ;
|
|
}
|
|
// altrimenti superata lunghezza parametrica ancora da tagliare
|
|
else {
|
|
// trimmo la curva semplice
|
|
if ( ! (*Iter)->TrimEndAtParam( 1 + dUToTrim)) {
|
|
m_nStatus = ERR ;
|
|
return false ;
|
|
}
|
|
// imposto punto finale e verifica curva chiusa
|
|
(*Iter)->GetEndPoint( m_PtEnd) ;
|
|
m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ;
|
|
// passo alla entità successiva
|
|
++ Iter ;
|
|
// dichiaro ingresso in zona da cancellare
|
|
bToErase = true ;
|
|
}
|
|
}
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::TrimStartAtLen( double dLenTrim)
|
|
{
|
|
double dLenToTrim ;
|
|
double dCrvLen ;
|
|
PCRVSMPL_LIST::iterator Iter ;
|
|
|
|
|
|
// ciclo sulle diverse curve dall'inizio
|
|
dLenToTrim = dLenTrim ;
|
|
for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ;) {
|
|
// lunghezza della curva
|
|
if ( ! (*Iter)->GetLength( dCrvLen))
|
|
return false ;
|
|
// lunghezza progressiva
|
|
dLenToTrim -= dCrvLen ;
|
|
// se lunghezza ancora da tagliare non nulla
|
|
if ( dLenToTrim > EPS_SMALL) {
|
|
delete (*Iter) ;
|
|
Iter ++ ;
|
|
m_CrvSmplS.pop_front() ;
|
|
m_nCounter -- ;
|
|
}
|
|
// se lunghezza ancora da tagliare nulla (entro la tolleranza)
|
|
else if ( dLenToTrim > - EPS_SMALL) {
|
|
delete (*Iter) ;
|
|
Iter ++ ;
|
|
m_CrvSmplS.pop_front() ;
|
|
m_nCounter -- ;
|
|
if ( m_nCounter == 0)
|
|
return false ;
|
|
(*Iter)->GetStartPoint( m_PtStart) ;
|
|
m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ;
|
|
break ;
|
|
}
|
|
// altrimenti superata lunghezza ancora da tagliare
|
|
else {
|
|
if ( ! (*Iter)->TrimStartAtLen( dCrvLen + dLenToTrim)) {
|
|
m_nStatus = ERR ;
|
|
return false ;
|
|
}
|
|
(*Iter)->GetStartPoint( m_PtStart) ;
|
|
m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ;
|
|
break ;
|
|
}
|
|
}
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::TrimEndAtLen( double dLenTrim)
|
|
{
|
|
bool bToErase ;
|
|
double dLenToTrim ;
|
|
double dCrvLen ;
|
|
PCRVSMPL_LIST::iterator Iter ;
|
|
|
|
|
|
// ciclo sulle diverse curve dalla fine
|
|
bToErase = false ;
|
|
dLenToTrim = dLenTrim ;
|
|
for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ;) {
|
|
// se non sono già nella zona da cancellare, aggiorno lunghezze
|
|
if ( ! bToErase) {
|
|
// lunghezza della curva
|
|
if ( ! (*Iter)->GetLength( dCrvLen))
|
|
return false ;
|
|
// lunghezza progressiva
|
|
dLenToTrim -= dCrvLen ;
|
|
}
|
|
// se da cancellare
|
|
if ( bToErase) {
|
|
// cancello l'entità, la tolgo dalla lista e passo alla successiva
|
|
delete (*Iter) ;
|
|
Iter = m_CrvSmplS.erase( Iter) ;
|
|
// decremento il numero di entità
|
|
m_nCounter -- ;
|
|
}
|
|
// se lunghezza ancora da tagliare non nulla
|
|
else if ( dLenToTrim > EPS_SMALL) {
|
|
// passo alla entità successiva
|
|
++ Iter ;
|
|
}
|
|
// se lunghezza ancora da tagliare nulla (entro la tolleranza)
|
|
else if ( dLenToTrim > - EPS_SMALL) {
|
|
// imposto punto finale e verifica curva chiusa
|
|
(*Iter)->GetEndPoint( m_PtEnd) ;
|
|
m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ;
|
|
// passo alla entità successiva
|
|
++ Iter ;
|
|
// dichiaro ingresso in zona da cancellare
|
|
bToErase = true ;
|
|
}
|
|
// altrimenti superata lunghezza ancora da tagliare
|
|
else {
|
|
// trimmo la curva semplice
|
|
if ( ! (*Iter)->TrimEndAtLen( dCrvLen + dLenToTrim)) {
|
|
m_nStatus = ERR ;
|
|
return false ;
|
|
}
|
|
// imposto punto finale e verifica curva chiusa
|
|
(*Iter)->GetEndPoint( m_PtEnd) ;
|
|
m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ;
|
|
// passo alla entità successiva
|
|
++ Iter ;
|
|
// dichiaro ingresso in zona da cancellare
|
|
bToErase = true ;
|
|
}
|
|
}
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::Translate( const Vector3d& vtMove)
|
|
{
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
// traslo le singole curve
|
|
PCRVSMPL_LIST::iterator Iter ;
|
|
for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter)
|
|
(*Iter)->Translate( vtMove) ;
|
|
|
|
// traslo i punti estremi
|
|
m_PtStart.Translate( vtMove) ;
|
|
m_PtEnd.Translate( vtMove) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng)
|
|
{
|
|
// verifico validità dell'asse di rotazione
|
|
if ( vtAx.IsSmall())
|
|
return false ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
// ruoto le singole curve
|
|
PCRVSMPL_LIST::iterator Iter ;
|
|
for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter)
|
|
(*Iter)->Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
|
|
|
|
// ruoto i punti estremi
|
|
m_PtStart.Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
|
|
m_PtEnd.Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dCoeffZ)
|
|
{
|
|
// verifico non sia nulla
|
|
if ( fabs( dCoeffX) < EPS_ZERO && fabs( dCoeffY) < EPS_ZERO && fabs( dCoeffZ) < EPS_ZERO)
|
|
return false ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
// se scalatura non omogenea, devo trasformare tutti gli archi in curve di Bezier
|
|
if ( fabs( dCoeffX - dCoeffY) > EPS_SMALL || fabs( dCoeffX - dCoeffZ) > EPS_SMALL) {
|
|
if ( ! ArcsToBezierCurves())
|
|
return false ;
|
|
}
|
|
|
|
// scalo le singole curve
|
|
PCRVSMPL_LIST::iterator Iter ;
|
|
for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) {
|
|
// eseguo la scalatura
|
|
if ( ! (*Iter)->Scale( frRef, dCoeffX, dCoeffY, dCoeffZ))
|
|
return false ;
|
|
}
|
|
|
|
// scalo i punti estremi
|
|
m_PtStart.Scale( frRef, dCoeffX, dCoeffY, dCoeffZ) ;
|
|
m_PtEnd.Scale( frRef, dCoeffX, dCoeffY, dCoeffZ) ;
|
|
|
|
return Validate() ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
|
|
{
|
|
// verifico validità del piano di specchiatura
|
|
if ( vtNorm.IsSmall())
|
|
return false ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
// specchio le singole curve
|
|
PCRVSMPL_LIST::iterator Iter ;
|
|
for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter)
|
|
(*Iter)->Mirror( ptOn, vtNorm) ;
|
|
|
|
// specchio i punti estremi
|
|
m_PtStart.Mirror( ptOn, vtNorm) ;
|
|
m_PtEnd.Mirror( ptOn, vtNorm) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& vtDir, double dCoeff)
|
|
{
|
|
// verifico validità dei parametri
|
|
if ( vtNorm.IsSmall() || vtDir.IsSmall())
|
|
return false ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
// trasformo tutti gli archi in curve di Bezier (potrei controllare gli archi uno ad uno...)
|
|
if ( ! ArcsToBezierCurves())
|
|
return false ;
|
|
|
|
// eseguo scorrimento delle singole curve
|
|
PCRVSMPL_LIST::iterator Iter ;
|
|
for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter)
|
|
(*Iter)->Shear( ptOn, vtNorm, vtDir, dCoeff) ;
|
|
|
|
// eseguo scorrimento dei punti estremi
|
|
m_PtStart.Shear( ptOn, vtNorm, vtDir, dCoeff) ;
|
|
m_PtEnd.Shear( ptOn, vtNorm, vtDir, dCoeff) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::ToGlob( const Frame3d& frRef)
|
|
{
|
|
// verifico validità del frame
|
|
if ( frRef.GetType() == Frame3d::ERR)
|
|
return false ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
// trasformo le singole curve
|
|
PCRVSMPL_LIST::iterator Iter ;
|
|
for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter)
|
|
(*Iter)->ToGlob( frRef) ;
|
|
|
|
// trasformo i punti estremi
|
|
m_PtStart.ToGlob( frRef) ;
|
|
m_PtEnd.ToGlob( frRef) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::ToLoc( const Frame3d& frRef)
|
|
{
|
|
// verifico validità del frame
|
|
if ( frRef.GetType() == Frame3d::ERR)
|
|
return false ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
// trasformo le singole curve
|
|
PCRVSMPL_LIST::iterator Iter ;
|
|
for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter)
|
|
(*Iter)->ToLoc( frRef) ;
|
|
|
|
// trasformo i punti estremi
|
|
m_PtStart.ToLoc( frRef) ;
|
|
m_PtEnd.ToLoc( frRef) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
|
|
{
|
|
// verifico validità dei frame
|
|
if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR)
|
|
return false ;
|
|
|
|
// se i due riferimenti coincidono, non devo fare alcunché
|
|
if ( AreSameFrame( frOri, frDest))
|
|
return true ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
// trasformo le singole curve
|
|
PCRVSMPL_LIST::iterator Iter ;
|
|
for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) {
|
|
(*Iter)->LocToLoc( frOri, frDest) ;
|
|
}
|
|
|
|
// trasformo i punti estremi
|
|
m_PtStart.LocToLoc( frOri, frDest) ;
|
|
m_PtEnd.LocToLoc( frOri, frDest) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
const ICurve*
|
|
CurveComposite::GetFirstCurve( void) const
|
|
{
|
|
// la curva deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return nullptr ;
|
|
|
|
// vado all'inizio
|
|
*(const_cast<PCRVSMPL_LIST::const_iterator*> (&m_Iter)) = m_CrvSmplS.begin() ;
|
|
|
|
// recupero la curva
|
|
if ( m_Iter != m_CrvSmplS.end())
|
|
return (*m_Iter) ;
|
|
else
|
|
return nullptr ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
const ICurve*
|
|
CurveComposite::GetNextCurve( void) const
|
|
{
|
|
// la curva deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return nullptr ;
|
|
|
|
// vado al successivo
|
|
(*(const_cast<PCRVSMPL_LIST::const_iterator*> (&m_Iter))) ++ ;
|
|
|
|
// recupero la curva
|
|
if ( m_Iter != m_CrvSmplS.end())
|
|
return (*m_Iter) ;
|
|
else
|
|
return nullptr ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
ICurve*
|
|
CurveComposite::RemoveFirstCurve( void)
|
|
{
|
|
// la curva composita deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return nullptr ;
|
|
|
|
// recupero la curva semplice iniziale e la tolgo dalla lista
|
|
if ( ! m_CrvSmplS.empty()) {
|
|
ICurve* pCrv = *(m_CrvSmplS.begin()) ;
|
|
m_CrvSmplS.pop_front() ;
|
|
return pCrv ;
|
|
}
|
|
else
|
|
return nullptr ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::IsParamAtJoint( double dU) const
|
|
{
|
|
// se all'inizio, alla fine o lontano dagli interi
|
|
if ( fabs( dU) < EPS_ZERO ||
|
|
fabs( dU - m_nCounter) < EPS_ZERO ||
|
|
fabs( dU - (int) ( dU + EPS_ZERO)) > EPS_ZERO)
|
|
return false ;
|
|
else
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::ArcsToBezierCurves( void)
|
|
{
|
|
// verifico le singole curve
|
|
PCRVSMPL_LIST::iterator Iter ;
|
|
for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) {
|
|
// se arco, devo trasformare in una o più curve di Bezier
|
|
if ( (*Iter)->GetType() == CRV_ARC) {
|
|
const ICurveArc* pArc = GetCurveArc( (*Iter)) ;
|
|
// se angolo al centro sotto il limite, basta una curva
|
|
if ( fabs( pArc->GetAngCenter()) <= BEZARC_ANG_CEN_MAX + EPS_ANG_SMALL) {
|
|
// creo la curva di Bezier
|
|
PtrOwner<ICurveBezier> pCrvBez( CreateCurveBezier()) ;
|
|
if ( ! ::IsValid( pCrvBez))
|
|
return false ;
|
|
if ( ! pCrvBez->FromArc( *pArc))
|
|
return false ;
|
|
// elimino l'arco e lo sostituisco con la curva di Bezier
|
|
delete (*Iter) ;
|
|
(*Iter) = Release( pCrvBez) ;
|
|
}
|
|
// altrimenti ne servono diverse
|
|
else {
|
|
// divido in parti
|
|
CurveComposite cCompo ;
|
|
int nParts = (int) ceil( fabs( pArc->GetAngCenter()) / BEZARC_ANG_CEN_MAX) ;
|
|
if ( ! cCompo.FromSplit( *pArc, nParts))
|
|
return false ;
|
|
// trasformo le parti in curve di Bezier
|
|
if ( ! cCompo.ArcsToBezierCurves() || cCompo.GetCurveNumber() != nParts)
|
|
return false ;
|
|
// inserisco le curve prima dell'arco
|
|
m_CrvSmplS.splice( Iter, cCompo.m_CrvSmplS) ;
|
|
// elimino l'arco (e sposto l'iteratore alla curva precedente)
|
|
delete (*Iter) ;
|
|
PCRVSMPL_LIST::iterator ToErase = Iter ;
|
|
-- Iter ;
|
|
m_CrvSmplS.erase( ToErase) ;
|
|
// aggiorno il numero di curve
|
|
m_nCounter += nParts - 1 ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|