4ebb43bf1e
aggiunto comando COUNTER in tsc.
900 lines
25 KiB
C++
900 lines
25 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 "GeoObjFactory.h"
|
|
#include "\EgtDev\Include\EGnStringUtils.h"
|
|
#include <algorithm>
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
GEOOBJ_REGISTER( CRV_COMPO, "C_CMP", CurveComposite) ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
CurveComposite::CurveComposite( void)
|
|
: m_nStatus( TO_VERIFY), m_nCounter( 0), m_bClosed( false)
|
|
{
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
CurveComposite::~CurveComposite( void)
|
|
{
|
|
Clear() ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::Clear( void)
|
|
{
|
|
PCRVSMPL_LIST::iterator Iter ;
|
|
|
|
|
|
// ciclo di pulizia
|
|
for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter)
|
|
delete (*Iter) ;
|
|
|
|
m_CrvSmplS.clear() ;
|
|
|
|
m_nCounter = 0 ;
|
|
m_bClosed = false ;
|
|
|
|
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)) {
|
|
delete 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)) {
|
|
delete pSmplCrv ;
|
|
return false ;
|
|
}
|
|
// passo alla prossima curva componente
|
|
pCrvOri = pCrvCompo->GetNextCurve() ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::AddSimpleCurve( ICurve* pSmplCrv)
|
|
{
|
|
Point3d ptStart ;
|
|
Point3d ptEnd ;
|
|
|
|
|
|
// 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 ( ! pSmplCrv->IsSimple())
|
|
return false ;
|
|
|
|
// recupero i punti iniziali e finali della curva
|
|
if ( ! pSmplCrv->GetStartPoint( ptStart) || ! pSmplCrv->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( pSmplCrv) ;
|
|
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 ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
CurveComposite*
|
|
CurveComposite::Clone( void) const
|
|
{
|
|
CurveComposite* pCrv ;
|
|
|
|
// alloco oggetto
|
|
pCrv = new(nothrow) CurveComposite ;
|
|
if ( pCrv != nullptr)
|
|
*pCrv = *(const_cast<CurveComposite*>(this)) ;
|
|
|
|
return pCrv ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
const string&
|
|
CurveComposite::GetKey( void) const
|
|
{
|
|
return GEOOBJ_GETKEY( CurveComposite) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::Save( ostream& osOut) const
|
|
{
|
|
int i ;
|
|
string sCrvName ;
|
|
const ICurve* pCrvSmpl ;
|
|
|
|
|
|
// numero di curve
|
|
osOut << ToString( m_nCounter) << endl ;
|
|
// ciclo sulle curve componenti
|
|
i = 0 ;
|
|
pCrvSmpl = GetFirstCurve() ;
|
|
while ( pCrvSmpl != nullptr) {
|
|
// emetto tipo della curva semplice
|
|
osOut << pCrvSmpl->GetKey() << endl ;
|
|
// assegno ed emetto nome della curva semplice
|
|
sCrvName = "#" + ToString( ++i) ;
|
|
osOut << sCrvName << endl ;
|
|
// salvataggio della curva semplice
|
|
if ( ! pCrvSmpl->Save( osOut))
|
|
return false ;
|
|
// passo alla successiva
|
|
pCrvSmpl = GetNextCurve() ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::Load( Scanner& TheScanner)
|
|
{
|
|
int nType ;
|
|
string sLine ;
|
|
STRVECTOR vsParams ;
|
|
bool bOk ;
|
|
int i ;
|
|
int nCounter ;
|
|
IGeoObj* pGeoO ;
|
|
ICurve* pCrv ;
|
|
|
|
|
|
// leggo la prossima linea
|
|
if ( ! TheScanner.GetLine( sLine))
|
|
return false ;
|
|
// la divido in parametri
|
|
Tokenize( sLine, ",", vsParams) ;
|
|
// 1 parametro : numero di curve componenti
|
|
if ( vsParams.size() != 1)
|
|
return false ;
|
|
// recupero il numero di curve componenti
|
|
if ( ! FromString( vsParams[0], nCounter))
|
|
return false ;
|
|
// leggo le curve componenti
|
|
for ( i = 0 ; i < nCounter ; ++ i) {
|
|
// recupero la prossima linea (con il tipo di oggetto)
|
|
if ( ! TheScanner.GetLine( sLine))
|
|
return false ;
|
|
// creo l'oggetto
|
|
nType = GEOOBJ_KEYTOTYPE( sLine) ;
|
|
pGeoO = GEOOBJ_CREATE( nType) ;
|
|
if ( pGeoO == nullptr)
|
|
return false ;
|
|
// recupero la linea con il nome
|
|
bOk = TheScanner.GetLine( sLine) ;
|
|
// ne leggo i dati
|
|
bOk = bOk && pGeoO->Load( TheScanner) ;
|
|
// verifico sia una curva
|
|
pCrv = ::GetCurve( pGeoO) ;
|
|
bOk = bOk && ( pCrv != nullptr && pCrv->IsSimple()) ;
|
|
// aggiungo questa curva (sicuramente semplice)
|
|
bOk = bOk && AddSimpleCurve( pCrv) ;
|
|
// se errore
|
|
if ( ! bOk) {
|
|
delete pGeoO ;
|
|
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 ;
|
|
|
|
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::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::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const
|
|
{
|
|
bool bFirst ;
|
|
double dStartPar ;
|
|
Point3d ptP ;
|
|
PolyLine PLSmpl ;
|
|
PCRVSMPL_LIST::const_iterator Iter ;
|
|
|
|
|
|
bFirst = true ;
|
|
dStartPar = 0 ;
|
|
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)
|
|
{
|
|
PCRVSMPL_LIST::iterator Iter ;
|
|
|
|
|
|
// inverto le singole curve
|
|
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) ;
|
|
|
|
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 ;
|
|
}
|
|
}
|
|
|
|
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 ;
|
|
}
|
|
}
|
|
|
|
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 ;
|
|
}
|
|
}
|
|
|
|
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 ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::Translate( const Vector3d& vtMove)
|
|
{
|
|
PCRVSMPL_LIST::iterator Iter ;
|
|
|
|
|
|
// traslo le singole curve
|
|
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)
|
|
{
|
|
PCRVSMPL_LIST::iterator Iter ;
|
|
|
|
|
|
// verifico validità dell'asse di rotazione
|
|
if ( vtAx.IsSmall())
|
|
return false ;
|
|
|
|
// ruoto le singole curve
|
|
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)
|
|
{
|
|
PCRVSMPL_LIST::iterator Iter ;
|
|
|
|
|
|
// ammessa solo scalatura uniforme (per la presenza di archi)
|
|
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 le singole curve
|
|
for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter)
|
|
(*Iter)->Scale( frRef, dCoeffX, dCoeffX, dCoeffX) ;
|
|
|
|
// scalo i punti estremi
|
|
m_PtStart.Scale( frRef, dCoeffX, dCoeffX, dCoeffX) ;
|
|
m_PtEnd.Scale( frRef, dCoeffX, dCoeffX, dCoeffX) ;
|
|
|
|
return Validate() ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
|
|
{
|
|
PCRVSMPL_LIST::iterator Iter ;
|
|
|
|
|
|
// verifico validità del piano di specchiatura
|
|
if ( vtNorm.IsSmall())
|
|
return false ;
|
|
|
|
// specchio le singole curve
|
|
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::ToGlob( const Frame3d& frRef)
|
|
{
|
|
PCRVSMPL_LIST::iterator Iter ;
|
|
|
|
|
|
// verifico validità del frame
|
|
if ( frRef.GetType() == Frame3d::ERR)
|
|
return false ;
|
|
|
|
// trasformo le singole curve
|
|
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)
|
|
{
|
|
PCRVSMPL_LIST::iterator Iter ;
|
|
|
|
|
|
// verifico validità del frame
|
|
if ( frRef.GetType() == Frame3d::ERR)
|
|
return false ;
|
|
|
|
// trasformo le singole curve
|
|
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 ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
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 ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
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 ;
|
|
}
|