EgtGeomKernel :

- creazione Zmap aggiungendo TriMesh.
This commit is contained in:
Riccardo Elitropi
2024-05-15 10:57:37 +02:00
parent 34089648b0
commit 3e6aa0d81b
5 changed files with 534 additions and 25 deletions
+183 -1
View File
@@ -25,6 +25,8 @@
#include "/EgtDev/Include/EGkIntervals.h"
#include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
#include <thread>
#include <future>
@@ -1500,7 +1502,187 @@ VolZmap::GetPartMinDistFromPoint( const Point3d& ptP) const
//----------------------------------------------------------------------------
bool
VolZmap::SetToModifyDexelBlocks( int nGrid, int nDex, int nInt)
VolZmap::AddSurfTm( const ISurfTriMesh* pStm)
{
// controllo sulla superficie
double dVol ;
if ( pStm == nullptr || ! pStm->IsValid() || ! pStm->IsClosed() ||
! pStm->GetVolume( dVol) || dVol < 0)
return false ;
// controllo se il Box3d della superficie si interseca con il Box3d dello Zmap corrente
BBox3d BBox_stm, BBox_curr ;
if ( ! pStm->GetLocalBBox( BBox_stm) || ! GetLocalBBox( BBox_curr))
return false ;
BBox3d BBox_inters ;
if ( BBox_stm.FindIntersection( BBox_curr, BBox_inters) && BBox_inters.IsEmpty())
return true ; // se non ci sono intersezioni, la superficie non influenza lo Zmap
Vector3d vtLen = BBox_curr.GetMax() - BBox_curr.GetMin() ; // dimensione massima dello spillone
// ciclo sulle griglie
bool bCompleted = true ;
for ( int g = 0 ; g < m_nMapNum ; ++ g) {
// definisco dei sistemi di riferimento ausiliari
Frame3d frMapFrame ;
if ( g == 0)
frMapFrame = m_MapFrame ;
else if ( g == 1)
frMapFrame.Set( m_MapFrame.Orig(), Y_AX, Z_AX, X_AX) ;
else if ( g == 2)
frMapFrame.Set( m_MapFrame.Orig(), Z_AX, X_AX, Y_AX) ;
// oggetto per calcolo massivo intersezioni
IntersParLinesSurfTm intPLSTM( frMapFrame, *pStm) ;
// numero massimo di thread
int nThreadMax = max( 1, int( thread::hardware_concurrency()) - 1) ;
vector<future<bool>> vRes ;
vRes.resize( nThreadMax) ;
// se dimensione griglia in X maggiore di dimensione Y
if ( m_nNx[g] > m_nNy[g]) {
int nDexNum = m_nNx[g] / nThreadMax ;
int nRemainder = m_nNx[g] % nThreadMax ;
int nInfI = 0 ;
int nSupI = 0 ;
// aggiungo le parti interessate alla mappa
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
nInfI = nSupI ;
nSupI = nInfI + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
vRes[nThread] = async( launch::async, &VolZmap::AddMapPart, this, g,
nInfI, nSupI, 0, m_nNy[g], ref( vtLen), ref( m_MapFrame.Orig()),
ref( *pStm), ref( intPLSTM)) ;
}
}
// se dimensione griglia in Y maggiore di dimensione X
else {
int nDexNum = m_nNy[g] / nThreadMax ;
int nRemainder = m_nNy[g] % nThreadMax ;
int nInfJ = 0 ;
int nSupJ = 0 ;
// aggiungo le parti interessate alla mappa
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
nInfJ = nSupJ ;
nSupJ = nInfJ + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
vRes[nThread] = async( launch::async, &VolZmap::AddMapPart, this, g,
0, m_nNx[g], nInfJ, nSupJ, ref( vtLen), ref( m_MapFrame.Orig()),
ref( *pStm), ref( intPLSTM)) ;
}
}
// ciclo per attendere che tutti gli async abbiano terminato.
int nTerminated = 0 ;
while ( nTerminated < nThreadMax) {
for ( int nL = 0 ; nL < nThreadMax ; ++ nL) {
// async terminato
if ( vRes[nL].valid() && vRes[nL].wait_for( chrono::microseconds{ 1}) == future_status::ready) {
++ nTerminated ;
bCompleted = bCompleted && vRes[nL].get() ;
}
}
}
if ( ! bCompleted)
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::MakeUniform( double dToler)
{
// controllo validità dello Zmap
if ( ! IsValid())
return false ;
// la tolleranza deve essere minore dello step
dToler = min( dToler, 0.95 * m_dStep) ;
// creo lo Zmpa che andrà a sostituire il corrente
PtrOwner<VolZmap> pOldVolZmap( CloneBasicVolZmap( this)) ;
if ( IsNull( pOldVolZmap))
return false ;
// ciclo sulle griglie
for ( int nGrid = 0 ; nGrid < m_nMapNum ; ++ nGrid) {
// salvo lo Zmap prima di modificare gli spilloni
PtrOwner<VolZmap> pVolZMapCurrGrid( CloneBasicVolZmap( this)) ;
if ( IsNull( pVolZMapCurrGrid))
return false ;
// ciclo sul numero di dexel presenti
for ( int nDex = 0 ; nDex < int( m_Values[nGrid].size()) ; ++ nDex) {
// se il dexel corrente non ha sotto-intervalli passo al successivo
if ( int( m_Values[nGrid][nDex].size()) == 0)
continue ;
// indici del dexel
int nI = nDex % m_nNx[nGrid] ;
int nJ = nDex / m_nNx[nGrid] ;
// salvo le informazioni dei sotto-intervalli del dexel corrente
vector<Data> vInfo ;
for ( int nExtr = 0 ; nExtr < int( m_Values[nGrid][nDex].size()) ; ++ nExtr)
vInfo.push_back( m_Values[nGrid][nDex][nExtr]) ;
// per ogni sotto-intervallo, estendo a destra e a sinistra della tolleranza
int nSub_intervals = int( vInfo.size()) ;
// scorro gli intervalli
for ( int nInfo = 0 ; nInfo < int( pVolZMapCurrGrid->m_Values[nGrid][nDex].size()) ; ++ nInfo) {
// estremo inferiore
if ( vInfo[nInfo].dMin - dToler > m_dMinZ[nGrid]) {
AddIntervals( nGrid, nI, nJ,
vInfo[nInfo].dMin - dToler,
vInfo[nInfo].dMin + dToler,
vInfo[nInfo].vtMinN, vInfo[nInfo].vtMinN, vInfo[nInfo].nToolMin,
true) ;
// se si sono uniti degli intervalli, potrei dover aggiungere degli spilloni nelle altre due
// direzioni nel voxel corrispondente
if ( IsTriDexel() && dToler > 0.5 * m_dStep - EPS_SMALL &&
nSub_intervals != int( m_Values[nGrid][nDex].size())) {
nSub_intervals = int( m_Values[nGrid][nDex].size()) ; // aggiorno gli intervalli correnti
// l'intervallo corrente si è unito con il precedente...
AddMissingIntervalsInVoxel( pOldVolZmap, nGrid, nI, nJ, vInfo[nInfo].dMin, dToler,
vInfo[nInfo].vtMinN, vInfo[nInfo].vtMinN,
vInfo[nInfo].nToolMin) ;
}
}
// estremo superiore
if ( vInfo[nInfo].dMax + dToler < m_dMaxZ[nGrid]) {
AddIntervals( nGrid, nI, nJ,
vInfo[nInfo].dMax - dToler,
vInfo[nInfo].dMax + dToler,
vInfo[nInfo].vtMaxN, vInfo[nInfo].vtMaxN, vInfo[nInfo].nToolMax,
true) ;
if ( IsTriDexel() && dToler > 0.5 * m_dStep - EPS_SMALL &&
nSub_intervals != int( m_Values[nGrid][nDex].size())) {
nSub_intervals = int( m_Values[nGrid][nDex].size()) ; // aggiorno gli intervalli correnti
AddMissingIntervalsInVoxel( pOldVolZmap, nGrid, nI, nJ, vInfo[nInfo].dMax, dToler,
vInfo[nInfo].vtMaxN, vInfo[nInfo].vtMaxN,
vInfo[nInfo].nToolMax) ;
}
}
}
// per ogni sotto-intervallo ricavato fino ad ora, restringo della tolleranza
// ( NB. avendo aggiunto intervalli, il dexel può modificare la sua struttura interna )
for ( int nInfo = 0 ; nInfo < int( m_Values[nGrid][nDex].size()) ; ++ nInfo) {
// ( NB. la rimozione di un intervallo ora va definita per intervalli a destra e a sinistra,
// altrimenti rimuovo parti in eccesso )
if ( ! pVolZMapCurrGrid->m_Values[nGrid][nDex].empty()) {
if ( nInfo != 0 ||
pVolZMapCurrGrid->m_Values[nGrid][nDex][0].dMin - dToler > m_dMinZ[nGrid])
m_Values[nGrid][nDex][nInfo].dMin += dToler ;
if ( nInfo != int( m_Values[nGrid][nDex].size()) - 1 ||
pVolZMapCurrGrid->m_Values[nGrid][nDex].back().dMax + dToler < m_dMaxZ[nGrid])
m_Values[nGrid][nDex][nInfo].dMax -= dToler ;
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SetToModifyDexelBlocks( int nGrid, int nDex, int nInt)
{
// Controllo sulla validità della griglia
if ( nGrid < 0 || nGrid > 2)