Files
EgtGeomKernel/SurfFlatRegionOffset.cpp
T
Dario Sassi fce40ffc38 EgtGeomKernel :
- piccole sistemazioni post Vroni (per usarlo in Offset _VRONI, altrimenti NVRONI).
2023-11-24 12:52:27 +01:00

238 lines
8.6 KiB
C++

//----------------------------------------------------------------------------
// 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 "/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
// imposto metodo di calcolo
bool bUseVoronoi = false ;
#ifdef _VRONI
bUseVoronoi = true ;
#endif // _VRONI
// 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<SurfFlatRegion> pSfr( CreateBasicSurfFlatRegion()) ;
if ( IsNull( pSfr))
return nullptr ;
// -------------------- OFFSET STANDARD -------------------------------------
if ( ! bUseVoronoi) {
bool bFirstRegion = true ;
// ciclo sui chunk
for ( int i = 0 ; i < nChunk ; ++ i) {
// creo la regione del chunk
PtrOwner<SurfFlatRegion> 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<ICurve> 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<SurfFlatRegion> 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 ;
if ( vOffs.size() > 0) {
BOOLVECTOR vbAddOrSub( vOffs.size(), true) ;
int nFirstId = -1 ;
for ( int i = 0 ; i < ( int)vOffs.size() ; i ++) {
// porto nel frame della flat region
vOffs[i]->ToLoc( m_frF) ;
// calcolo orientamento della curva
double dAreaXY ;
if ( ! vOffs[i]->GetAreaXY( dAreaXY))
return nullptr ;
vbAddOrSub[i] = ( dAreaXY > SQ_EPS_SMALL) ;
// verifico se è il primo loop esterno
if ( nFirstId == -1 && vbAddOrSub[i])
nFirstId = i ;
}
// inizializzo la superficie
if ( nFirstId != -1 && ! pSfr->AddExtLoop( Release( vOffs[nFirstId])))
return nullptr ;
if ( pSfr->IsValid()) {
for ( int i = 0 ; i < ( int)vOffs.size() ; i ++) {
// verifico non sia il primo loop esterno
if ( i == nFirstId)
continue ;
// costruisco la superficie associata
PtrOwner<SurfFlatRegion> pSrfCrv( CreateBasicSurfFlatRegion()) ;
if ( IsNull( pSrfCrv) || ! pSrfCrv->AddExtLoop( Release( vOffs[i])))
return nullptr ;
if ( ! pSrfCrv->IsValid())
continue ;
// aggiungo o sottraggo
if ( vbAddOrSub[i]) {
if ( ! pSfr->Add( *pSrfCrv))
return nullptr ;
}
else {
pSrfCrv->Invert() ;
if ( ! pSfr->Subtract( *pSrfCrv))
return nullptr ;
}
}
}
}
}
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 this->Clone() ;
// calcolo la superficie di offset
PtrOwner<SurfFlatRegion> 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 ;
}