//---------------------------------------------------------------------------- // EgalTech 2015-2015 //---------------------------------------------------------------------------- // File : SurfFlatRegionOffset.cpp Data : 01.11.15 Versione : 1.6k1 // Contenuto : Implementazione della funzione offset per SurfFlatRegion. // // // // Modifiche : 01.11.15 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "GeoConst.h" #include "CurveComposite.h" #include "SurfFlatRegion.h" #include "AdjustLoops.h" #include "Voronoi.h" #include "/EgtDev/Include/EGkOffsetCurve.h" #include "/EgtDev/Include/EGkSfrCreate.h" #include "/EgtDev/Include/EgtPointerOwner.h" using namespace std ; //---------------------------------------------------------------------------- SurfFlatRegion* SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const { // restituisce la superficie offsettata senza modificare la superficie corrente. In caso di errore restituisce nullptr // metodo di calcolo impostato da USE_VORONOI // recupero il numero dei chunk int nChunk = GetChunkCount() ; if ( nChunk == 0) return nullptr ; // se offset nullo, la nuova regione è la copia di quella attuale if ( abs( dDist) < 10 * EPS_SMALL) return this->Clone() ; // creo una nuova regione PtrOwner pSfr( CreateBasicSurfFlatRegion()) ; if ( IsNull( pSfr)) return nullptr ; // -------------------- OFFSET STANDARD ------------------------------------- if ( ! USE_VORONOI) { bool bFirstRegion = true ; // ciclo sui chunk for ( int i = 0 ; i < nChunk ; ++ i) { // creo la regione del chunk PtrOwner pSfrChk( new( nothrow) SurfFlatRegion) ; if ( IsNull( pSfrChk)) return nullptr ; bool bFirstCurve = true ; // ciclo sui loop di ogni chunk int nLoop = GetLoopCount( i) ; for ( int j = 0 ; j < nLoop ; ++ j) { // recupero il loop ICurve* pLoop = GetMyLoop( i, j) ; if ( pLoop == nullptr) return nullptr ; // ne eseguo l'offset OffsetCurve OffsCrv ; bool bOk = OffsCrv.Make( pLoop, dDist, nType) ; // recupero le curve di offset PtrOwner pOffs( OffsCrv.GetLongerCurve()) ; while ( bOk && ! IsNull( pOffs)) { if ( pOffs->GetType() == CRV_COMPO) { CurveComposite* pOffsCompo = GetBasicCurveComposite( pOffs) ; // assegno proprietà pOffsCompo->SetTempProp( j, 1) ; for ( int k = 0 ; k < pOffsCompo->GetCurveCount() ; ++k) pOffsCompo->SetCurveTempProp( k, j, 1) ; // unisco parti allineate if ( ! pOffsCompo->MergeCurves( 10 * EPS_SMALL, ANG_TOL_STD_DEG, true)) return nullptr ; } else pOffs->SetTempProp( j, 1) ; // se prima curva esterna, è il primo contorno esterno della nuova regione if ( j == 0 && bFirstCurve) { if ( ! pSfrChk->AddExtLoop( Release( pOffs))) return nullptr ; bFirstCurve = false ; } // altrimenti aggiungo o sottraggo la regione della curva alla nuova regione else if ( ! bFirstCurve) { // verifico se loop interno o esterno double dArea ; if ( ! pOffs->GetAreaXY( dArea)) return nullptr ; bool bExtLoop = ( dArea > 0) ; // se loop interno, inverto la curva if ( ! bExtLoop) pOffs->Invert() ; // creo la regione PtrOwner pSfr2( new( nothrow) SurfFlatRegion) ; if ( IsNull( pSfr2) || ! pSfr2->AddExtLoop( Release( pOffs))) return nullptr ; // se era loop esterno, lo aggiungo alla nuova regione if ( bExtLoop) { if ( ! pSfrChk->Add( *pSfr2)) return nullptr ; } // altrimenti loop interno, lo sottraggo alla nuova regione else { if ( ! pSfrChk->Subtract( *pSfr2)) return nullptr ; } } // passo alla successiva pOffs.Set( OffsCrv.GetLongerCurve()) ; } } // se regione di chunk valida if ( ! bFirstCurve) { // se prima regione di chunk, ne sposto i dati nella nuova regione if ( bFirstRegion) { pSfr->m_vExtInd = pSfrChk->m_vExtInd ; pSfr->m_vpLoop = pSfrChk->m_vpLoop ; for ( auto& pLoop : pSfrChk->m_vpLoop) pLoop = nullptr ; pSfr->m_nStatus = pSfrChk->m_nStatus ; bFirstRegion = false ; } // altrimenti la aggiungo alla nuova regione else { if ( ! pSfr->Add( *pSfrChk)) return nullptr ; } } } } // -------------------- OFFSET CON VORONOI ------------------------------------- else { // verifico se oggetto Voronoi della superficie è definito if ( m_pVoronoiObj == nullptr) CalcVoronoiObject() ; // calcolo offset ICURVEPOVECTOR vOffs ; if ( ! m_pVoronoiObj->CalcOffset( vOffs, dDist, nType)) return nullptr ; // costruisco la superficie if ( ! vOffs.empty()) { PCRV_DEQUE vLoops ; for ( int i = 0 ; i < int( vOffs.size()) ; i ++) { vOffs[i]->ToLoc( m_frF) ; // rimuovo eventuali sovrapposizioni ICURVEPLIST CrvLst ; AdjustLoops( Release( vOffs[i]), CrvLst, true) ; for ( auto pCrv : CrvLst) { pCrv->SetExtrusion( Z_AX) ; vLoops.emplace_back( pCrv) ; } } // verifico di avere ancora dei loops if ( ! vLoops.empty()) { pSfr.Set( MyNewSurfFromLoops( vLoops)) ; if ( IsNull( pSfr)) { MyTestAndDelete( vLoops) ; return nullptr ; } } } } pSfr->ToGlob( m_frF) ; return Release( pSfr) ; } //---------------------------------------------------------------------------- bool SurfFlatRegion::Offset( double dDist, int nType) { // recupero il numero dei chunk int nChunk = GetChunkCount() ; if ( nChunk == 0) return false ; // se offset nullo, non devo fare alcunchè if ( abs( dDist) < 10 * EPS_SMALL) return true ; // calcolo la superficie di offset PtrOwner pSfr( CreateOffsetSurf( dDist, nType)) ; if ( IsNull( pSfr)) return false ; // pulisco la superficie corrente for ( auto& pLoop : m_vpLoop) delete pLoop ; m_vpLoop.clear() ; // sposto i dati della nuova superficie in quella corrente m_vExtInd = pSfr->m_vExtInd ; m_vpLoop = pSfr->m_vpLoop ; for ( auto& pLoop : pSfr->m_vpLoop) pLoop = nullptr ; m_nStatus = pSfr->m_nStatus ; // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; ResetVoronoiObject() ; return true ; }