//---------------------------------------------------------------------------- // 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 "GeoConst.h" #include "GeoObjFactory.h" #include "NgeWriter.h" #include "NgeReader.h" #include "/EgtDev/Include/EGnStringUtils.h" #include "/EgtDev/Include/EgtPointerOwner.h" #include "/EgtDev/Include/EGkCurveArc.h" #include "/EgtDev/Include/EGkCurveBezier.h" #include 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)) { 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() ; } } // imposto ricalcolo della grafica m_OGrMgr.Reset() ; 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 ; } //---------------------------------------------------------------------------- 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 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 ; } //---------------------------------------------------------------------------- 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( 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( 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 { // numero di curve sOut += "Num=" + 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 ngeOut.WriteInt( m_nCounter, nullptr, true) ; // 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( pCrvSmpl) ; if ( pCSmplRW == nullptr) return false ; // emetto tipo della curva semplice ngeOut.WriteKey( pCSmplRW->GetNgeId()) ; // assegno ed emetto nome della curva semplice string sCrvName = "#" + ToString( ++i) ; ngeOut.WriteString( sCrvName, nullptr, true) ; // 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( 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) { 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 ; } //---------------------------------------------------------------------------- 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 { // 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) { // 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) ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; 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 ; // 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) ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; 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 ; // 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) ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; return Validate() ; } //---------------------------------------------------------------------------- bool CurveComposite::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) { // verifico validità del piano di specchiatura if ( vtNorm.IsSmall()) return false ; // 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) ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; return true ; } //---------------------------------------------------------------------------- bool CurveComposite::ToGlob( const Frame3d& frRef) { // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; // 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) ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; return true ; } //---------------------------------------------------------------------------- bool CurveComposite::ToLoc( const Frame3d& frRef) { // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; // 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) ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; return true ; } //---------------------------------------------------------------------------- const ICurve* CurveComposite::GetFirstCurve( void) const { // la curva deve essere validata if ( m_nStatus != OK) return nullptr ; // vado all'inizio *(const_cast (&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 (&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 ; } //---------------------------------------------------------------------------- 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 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 ; }