diff --git a/VolZmap.cpp b/VolZmap.cpp index 7142e7e..c8cfdff 100644 --- a/VolZmap.cpp +++ b/VolZmap.cpp @@ -21,12 +21,14 @@ #include "DistPointLine.h" #include "GeoConst.h" #include "/EgtDev/Include/EGkIntersLinePlane.h" +#include "/EgtDev/Include/EGkIntersLineSurfTm.h" #include "/EgtDev/Include/EGkUiUnits.h" #include "/EgtDev/Include/EGkIntervals.h" #include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EgtNumUtils.h" #include #include +#include "IntersLineBox.h" using namespace std ; @@ -93,6 +95,54 @@ VolZmap::Clear( void) return true ; } +//---------------------------------------------------------------------------- +bool +VolZmap::IsEmpty( void) +{ + // controllo validità + if ( ! IsValid()) + return false ; + + bool bIsEmpty = true ; // flag + + // ciclo sul numero di mappe + for ( int i = 0 ; bIsEmpty && i < m_nMapNum ; ++ i) { + // ciclo sulle dimensioni di ogni mappa + for ( int j = 0 ; bIsEmpty && j < m_nDim[i] ; ++ j) { + // controllo se esiste un tratto di dexel non vuoto + bIsEmpty = ( int( m_Values[i][j].size()) == 1 && + abs( m_Values[i][j][0].dMin) < EPS_ZERO && + m_Values[i][j][0].nToolMin == 0 && + m_Values[i][j][0].nCompo == 1) ; + + if ( bIsEmpty) { + switch ( i) { + case 0 : + bIsEmpty = ( m_Values[i][j][0].vtMinN.IsZminus() && + abs( m_Values[i][j][0].dMax) < EPS_ZERO && + m_Values[i][j][0].vtMaxN.IsZplus() && + m_Values[i][j][0].nToolMax == 0) ; + break ; + case 1 : + bIsEmpty = ( m_Values[i][j][0].vtMinN.IsZminus() && + abs( m_Values[i][j][0].dMax) < EPS_ZERO && + m_Values[i][j][0].vtMaxN.IsXplus() && + m_Values[i][j][0].nToolMax == 0 ) ; + break ; + case 2 : + bIsEmpty = ( m_Values[i][j][0].vtMinN.IsYminus() && + abs( m_Values[i][j][0].dMax) < EPS_ZERO && + m_Values[i][j][0].vtMaxN.IsYplus() && + m_Values[i][j][0].nToolMax == 0 ) ; + break ; + } + } + } + } + + return bIsEmpty ; +} + //---------------------------------------------------------------------------- VolZmap* VolZmap::Clone( void) const @@ -1657,6 +1707,134 @@ VolZmap::SetToModifyDexelBlocks( int nGrid, int nDex, int nInt) return true ; } +//---------------------------------------------------------------------------- +bool +VolZmap::AddSrfTm( 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 ; + if ( ! pStm->GetLocalBBox( BBox_stm)) + return false ; + BBox3d BBox_curr ; + if ( ! 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 + + // determino i punti estremi del bounding box corrente + BBox3d BBoxCurr ; + if ( ! GetLocalBBox( BBoxCurr)) + return false ; + Point3d ptMapOrig, ptMapEnd ; + BBoxCurr.GetMinMax( ptMapOrig, ptMapEnd) ; + // determino le dimensioni lineari del BBox + Vector3d vtLen = ptMapEnd - ptMapOrig ; + + // creo uno Zmap vuoto per la TriMesh + PtrOwner pZmapStm( CreateBasicVolZmap()) ; + if ( IsNull( pZmapStm) || + ! pZmapStm->CreateEmptyMap( ptMapOrig, BBoxCurr.GetDimX() + 10 * EPS_SMALL, + BBoxCurr.GetDimY() + 10 * EPS_SMALL, + BBoxCurr.GetDimZ() + 10 * EPS_SMALL, + m_dStep, IsTriDexel())) + return false ; + + + // ciclo sulle griglie + bool bCompleted = true ; + for ( int g = 0 ; g < pZmapStm->m_nMapNum ; ++ g) { + // definisco dei sistemi di riferimento ausiliari + Frame3d frMapFrame ; + if ( g == 0) + frMapFrame = m_MapFrame ; + else if ( g == 1) + frMapFrame.Set( ptMapOrig, Y_AX, Z_AX, X_AX) ; + else if ( g == 2) + frMapFrame.Set( ptMapOrig, 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> vRes ; + vRes.resize( nThreadMax) ; + if ( pZmapStm->m_nNx[g] > pZmapStm->m_nNy[g]) { + int nDexNum = pZmapStm->m_nNx[g] / nThreadMax ; + int nRemainder = pZmapStm->m_nNx[g] % nThreadMax ; + int nInfI = 0 ; + int nSupI = 0 ; + for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) { + nInfI = nSupI ; + nSupI = nInfI + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ; + vRes[nThread] = async( launch::async, &VolZmap::CreateMapPart, this, g, + nInfI, nSupI, 0, pZmapStm->m_nNy[g], ref( vtLen), ref( ptMapOrig), ref( *pStm), ref( intPLSTM)) ; + } + } + else { + int nDexNum = pZmapStm->m_nNy[g] / nThreadMax ; + int nRemainder = pZmapStm->m_nNy[g] % nThreadMax ; + int nInfJ = 0 ; + int nSupJ = 0 ; + for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) { + nInfJ = nSupJ ; + nSupJ = nInfJ + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ; + vRes[nThread] = async( launch::async, &VolZmap::CreateMapPart, this, g, + 0, pZmapStm->m_nNx[g], nInfJ, nSupJ, ref( vtLen), ref( ptMapOrig), 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() ; + } + } + } + + // bho ( ???????? ) + if ( ! bCompleted) + return false ; + + // aggiungo ora gli intervalli ricavati allo Zmap corrente ( *this) + // ciclo sui dexel della mappa + for ( int nD = 0 ; nD < int( pZmapStm->m_Values[g].size()) ; ++ nD) { + // se spillone vuoto, passo al successivo + if ( pZmapStm->m_Values[g][nD].empty()) + continue ; + // indici di spillone + int nI = nD % pZmapStm->m_nNx[g] ; + int nJ = nD / pZmapStm->m_nNx[g] ; + // ciclo sui voxel associati + for ( int nV = 0 ; nV < int( pZmapStm->m_Values[g][nD].size()) ; ++ nV) { + // estremi del voxel + double dMin = pZmapStm->m_Values[g][nD][nV].dMin ; + double dMax = pZmapStm->m_Values[g][nD][nV].dMax ; + // vettori associati agli estremi + Vector3d vtMaxN = pZmapStm->m_Values[g][nD][nV].vtMaxN ; + Vector3d vtMinN = pZmapStm->m_Values[g][nD][nV].vtMinN ; + // aggiungo l'intervallo // per ora... (???) + AddIntervals( g, nI, nJ, dMin, dMax, vtMinN, vtMaxN, 0) ; + } + } + + } + + return true ; +} + + //---------------------------------------------------------------------------- bool VolZmap::IsMapPartABox( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, double& dMinZ, double& dMaxZ) diff --git a/VolZmap.h b/VolZmap.h index 17e8656..4a704c1 100644 --- a/VolZmap.h +++ b/VolZmap.h @@ -77,7 +77,9 @@ class VolZmap : public IVolZmap, public IGeoObjRW public : // IVolZmap bool CopyFrom( const IGeoObj* pGObjSrc) override ; bool Clear( void) override ; + bool IsEmpty( void) override ; bool Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ; + bool CreateEmptyMap( const Point3d& ptO, double dLengthX, double dLengthY, double dLengthZ, double dStep, bool bTriDex) override ; bool CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex) override ; bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex) override ; int GetBlockCount( void) const override ; @@ -89,7 +91,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW { return m_nMapNum == 3 ; } bool GetDexelLines( int nDir, int nPos1, int nPos2, POLYLINELIST& lstPL) const override ; int GetResolution( void) const override - { return m_nDexVoxRatio ; } + { return m_nDexVoxRatio ; } bool ChangeResolution( int nDexVoxRatio) override ; void SetShowEdges( bool bShow) override { m_bShowEdges = bShow ; // qui è necessario far ricreare la grafica @@ -140,6 +142,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW VolZmap* ClonePart( int nPart) const override ; bool RemovePart( int nPart) override ; int GetPartMinDistFromPoint( const Point3d& ptP) const override ; + bool AddSrfTm( const ISurfTriMesh* pStm) override ; public : // IGeoObjRW int GetNgeId( void) const override ; @@ -411,6 +414,9 @@ class VolZmap : public IVolZmap, public IGeoObjRW // Funzione per crezione solido in parallelo bool CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig, const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ; + // Funzione per aggiornamento solido in parallelo + bool UpdateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig, + const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ; private : enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ; diff --git a/VolZmapCreation.cpp b/VolZmapCreation.cpp index a0b4a5b..b85ce46 100644 --- a/VolZmapCreation.cpp +++ b/VolZmapCreation.cpp @@ -1,4 +1,4 @@ -//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- // EgalTech 2015-2016 //---------------------------------------------------------------------------- // File : VolZmap.cpp Data : 22.01.15 Versione : 1.6a4 @@ -26,14 +26,124 @@ using namespace std ; // ------------------------- CREAZIONE MAPPA -------------------------------------------------------------------------------------- //---------------------------------------------------------------------------- -bool +bool VolZmap::Create( const Point3d& ptO, double dLengthX, double dLengthY, double dLengthZ, double dStep, bool bTriDex) { - // Controlli sull'ammissibilità delle dimensioni lineari del grezzo e del passo + + // Controlli sull'ammissibilità delle dimensioni lineari del grezzo e del passo if ( dStep < EPS_SMALL || dLengthX < EPS_SMALL || dLengthY < EPS_SMALL || dLengthZ < EPS_SMALL) return false ; - // Il passo di discretizzazione non può essere inferiore a 100 * EPS_SMALL + // Il passo di discretizzazione non può essere inferiore a 100 * EPS_SMALL + m_dStep = max( dStep, 100 * EPS_SMALL) ; + + // Aggiorno la dimensione della mappa 1 o 3 + m_nMapNum = ( bTriDex ? 3 : 1) ; + + // Disponendo i sistemi di riferimento in una successione, le coordinate x,y,z + // di uno si ottengono da una permutazione ciclica di quelle del precedente sistema. + // es: X(n) = Z(n-1), Y(n) = X(n-1), Z(n) = Y(n-1) + + // Definisco il sistema di riferimento intrinseco + m_MapFrame.Set( ptO, X_AX, Y_AX, Z_AX) ; + + // Definisco i vettori dei limiti su indici + m_nNx[0] = max( int( ( dLengthX + EPS_SMALL) / m_dStep + 0.5), 1) ; + m_nNy[0] = max( int( ( dLengthY + EPS_SMALL) / m_dStep + 0.5), 1) ; + + // Numero di componenti connesse + m_nConnectedCompoCount = 1 ; + + // Se tridexel + if ( bTriDex) { + m_nNx[1] = m_nNy[0] ; + m_nNy[1] = max( int( ( dLengthZ + EPS_SMALL) / m_dStep + 0.5), 1) ; + m_nNx[2] = m_nNy[1] ; + m_nNy[2] = m_nNx[0] ; + } + + // altrimenti mono dexel + else { + m_nNx[1] = 0 ; + m_nNy[1] = 0 ; + m_nNx[2] = 0 ; + m_nNy[2] = 0 ; + } + + // Definisco il numero di blocchi lungo x,y e z + if ( ! CalcBlockNum()) + return false ; + + // Definizione della mappa + + // Creazione delle mappe + // Calcolo del numero di celle per ogni mappa + for ( int i = 0 ; i < m_nMapNum ; ++ i) + m_nDim[i] = m_nNx[i] * m_nNy[i] ; + + // Creazione delle celle per ogni mappa + for ( int i = 0 ; i < m_nMapNum ; ++ i) + m_Values[i].resize( m_nDim[i]) ; + + // Riempimento delle celle + for ( int i = 0 ; i < m_nMapNum ; ++ i) { + for ( int j = 0 ; j < m_nDim[i] ; ++ j) { + + // Aggiungo il tratto al dexel vuoto + m_Values[i][j].resize( 1) ; + m_Values[i][j][0].dMin = 0 ; + m_Values[i][j][0].nToolMin = 0 ; + m_Values[i][j][0].nCompo = 1 ; + + switch ( i) { + case 0 : + m_Values[i][j][0].vtMinN = - Z_AX ; + m_Values[i][j][0].dMax = dLengthZ ; + m_Values[i][j][0].vtMaxN = Z_AX ; + m_Values[i][j][0].nToolMax = 0 ; + break ; + case 1 : + m_Values[i][j][0].vtMinN = - X_AX ; + m_Values[i][j][0].dMax = dLengthX ; + m_Values[i][j][0].vtMaxN = X_AX ; + m_Values[i][j][0].nToolMax = 0 ; + break ; + case 2 : + m_Values[i][j][0].vtMinN = - Y_AX ; + m_Values[i][j][0].dMax = dLengthY ; + m_Values[i][j][0].vtMaxN = Y_AX ; + m_Values[i][j][0].nToolMax = 0 ; + break ; + } + } + } + + // Definizione delle limitazioni iniziali in Z per ogni mappa + m_dMinZ[0] = 0 ; + m_dMaxZ[0] = dLengthZ ; + m_dMinZ[1] = 0 ; + m_dMaxZ[1] = ( bTriDex ? dLengthX : 0) ; + m_dMinZ[2] = 0 ; + m_dMaxZ[2] = ( bTriDex ? dLengthY : 0) ; + + // Tipologia + m_nShape = BOX ; + + // Aggiornamento dello stato + m_nStatus = OK ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +VolZmap::CreateEmptyMap( const Point3d& ptO, double dLengthX, double dLengthY, double dLengthZ, double dStep, bool bTriDex) +{ + // Controlli sull'ammissibilità delle dimensioni lineari del grezzo e del passo + if ( dStep < EPS_SMALL || dLengthX < EPS_SMALL || dLengthY < EPS_SMALL || dLengthZ < EPS_SMALL) + return false ; + + // Il passo di discretizzazione non può essere inferiore a 100 * EPS_SMALL m_dStep = max( dStep, 100 * EPS_SMALL) ; // Aggiorno la dimensione della mappa 1 o 3 @@ -73,8 +183,6 @@ VolZmap::Create( const Point3d& ptO, double dLengthX, double dLengthY, double dL if ( ! CalcBlockNum()) return false ; - // Definizione della mappa - // Creazione delle mappe // Calcolo del numero di celle per ogni mappa for ( int i = 0 ; i < m_nMapNum ; ++ i) @@ -84,38 +192,6 @@ VolZmap::Create( const Point3d& ptO, double dLengthX, double dLengthY, double dL for ( int i = 0 ; i < m_nMapNum ; ++ i) m_Values[i].resize( m_nDim[i]) ; - // Riempimento delle celle - for ( int i = 0 ; i < m_nMapNum ; ++ i) - for ( int j = 0 ; j < m_nDim[i] ; ++ j) { - - // Aggiungo il tratto al dexel vuoto - m_Values[i][j].resize( 1) ; - m_Values[i][j][0].dMin = 0 ; - m_Values[i][j][0].nToolMin = 0 ; - m_Values[i][j][0].nCompo = 1 ; - - switch ( i) { - case 0 : - m_Values[i][j][0].vtMinN = - Z_AX ; - m_Values[i][j][0].dMax = dLengthZ ; - m_Values[i][j][0].vtMaxN = Z_AX ; - m_Values[i][j][0].nToolMax = 0 ; - break ; - case 1 : - m_Values[i][j][0].vtMinN = - X_AX ; - m_Values[i][j][0].dMax = dLengthX ; - m_Values[i][j][0].vtMaxN = X_AX ; - m_Values[i][j][0].nToolMax = 0 ; - break ; - case 2 : - m_Values[i][j][0].vtMinN = - Y_AX ; - m_Values[i][j][0].dMax = dLengthY ; - m_Values[i][j][0].vtMaxN = Y_AX ; - m_Values[i][j][0].nToolMax = 0 ; - break ; - } - } - // Definizione delle limitazioni iniziali in Z per ogni mappa m_dMinZ[0] = 0 ; m_dMaxZ[0] = dLengthZ ; @@ -124,8 +200,8 @@ VolZmap::Create( const Point3d& ptO, double dLengthX, double dLengthY, double dL m_dMinZ[2] = 0 ; m_dMaxZ[2] = ( bTriDex ? dLengthY : 0) ; - // Tipologia - m_nShape = BOX ; + // Tipologia + m_nShape = GENERIC ; // Aggiornamento dello stato m_nStatus = OK ; @@ -140,7 +216,7 @@ VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double // Aggiorno la dimensione della mappa 1 o 3 m_nMapNum = ( bTriDex ? 3 : 1) ; - // Il passo di discretizzazione non può essere inferiore a 100 * EPS_SMALL + // Il passo di discretizzazione non può essere inferiore a 100 * EPS_SMALL m_dStep = max( dStep, 100 * EPS_SMALL) ; // Determino il bounding box della flat region @@ -223,11 +299,11 @@ VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double CRVCVECTOR IntersectionResults ; Surf.GetCurveClassification( GridLine, EPS_SMALL, IntersectionResults) ; - // Analizzo le parti in cui la retta è stata divisa + // Analizzo le parti in cui la retta è stata divisa int nPart = int( IntersectionResults.size()) ; for ( int k = 0 ; k < nPart ; ++ k) { - // Se la retta è interna alla regione o coincidente con parte della sua frontiera + // Se la retta è interna alla regione o coincidente con parte della sua frontiera int nType = IntersectionResults[k].nClass ; if ( nType == CRVC_IN || nType == CRVC_ON_P || nType == CRVC_ON_M) { @@ -334,7 +410,7 @@ VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double int nPart = int( IntersectionResults.size()) ; for ( int k = 0 ; k < nPart ; ++ k) { - // Se la retta è interna alla regione o coincidente con parte della sua frontiera + // Se la retta è interna alla regione o coincidente con parte della sua frontiera int nType = IntersectionResults[k].nClass ; if ( nType == CRVC_IN || nType == CRVC_ON_P || nType == CRVC_ON_M) { @@ -471,7 +547,7 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co int nIntType = IntersectionResults[k].nILTT ; - // Se c'è intersezione + // Se c'è intersezione if ( nIntType != ILTT_NO) { double dCos = IntersectionResults[k].dCosDN ; @@ -523,11 +599,115 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co return true ; } +//---------------------------------------------------------------------------- +bool +VolZmap::UpdateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig, + const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) +{ + if ( nMap < 0 || nMap > 2 || + nInfI < 0 || nInfI > m_nNx[nMap] || + nSupI < 0 || nSupI > m_nNx[nMap] || + nInfJ < 0 || nInfJ > m_nNy[nMap] || + nSupJ < 0 || nSupJ > m_nNy[nMap]) + return false ; + + // Determinazione e ridimensionamento dei dexel interni alla trimesh + for ( int i = nInfI ; i < nSupI ; ++ i) { + for ( int j = nInfJ ; j < nSupJ ; ++ j) { + + // Definisco la retta da intersecare con la trimesh + double dX = ( i + 0.5) * m_dStep ; + double dY = ( j + 0.5) * m_dStep ; + Point3d ptP0( dX, dY, 0) ; + + // Determino le intersezioni della retta con la TriMesh + ILSIVECTOR IntersectionResults ; + intPLSTM.GetInters( ptP0, vtLen.v[(nMap+2)%3], IntersectionResults) ; + + for ( int nI = 0 ; nI < int( IntersectionResults.size()) - 3 ; ++ nI) { + int nJ = nI + 1 ; + int nK = nJ + 1 ; + int nT = nK + 1 ; + int nSgnI = IntersectionResults[nI].dCosDN > EPS_SMALL ? 1 : IntersectionResults[nI].dCosDN > -EPS_SMALL ? 0 : - 1 ; + int nSgnJ = IntersectionResults[nJ].dCosDN > EPS_SMALL ? 1 : IntersectionResults[nJ].dCosDN > -EPS_SMALL ? 0 : - 1 ; + int nSgnK = IntersectionResults[nK].dCosDN > EPS_SMALL ? 1 : IntersectionResults[nK].dCosDN > -EPS_SMALL ? 0 : - 1 ; + int nSgnT = IntersectionResults[nT].dCosDN > EPS_SMALL ? 1 : IntersectionResults[nT].dCosDN > -EPS_SMALL ? 0 : - 1 ; + double dUJ = IntersectionResults[nJ].dU ; + double dUK = IntersectionResults[nK].dU ; + if ( nSgnI != 0 && nSgnI == nSgnJ && nSgnK != 0 && nSgnK == nSgnT && nSgnI == - nSgnT && abs( dUJ - dUK) < EPS_SMALL) { + IntersectionResults.erase( IntersectionResults.begin() + nK) ; + IntersectionResults.erase( IntersectionResults.begin() + nJ) ; + } + } + + int nInt = int( IntersectionResults.size()) ; + + int nPos = j * m_nNx[nMap] + i ; + + bool bInside = false ; + Point3d ptIn ; + Vector3d vtInN ; + + for ( int k = 0 ; k < nInt ; ++ k) { + + int nIntType = IntersectionResults[k].nILTT ; + + // Se c'è intersezione + if ( nIntType != ILTT_NO) { + + double dCos = IntersectionResults[k].dCosDN ; + + // entro nella superficie trimesh + if ( dCos < - EPS_SMALL) { + + ptIn = IntersectionResults[k].ptI ; + + int nT = IntersectionResults[k].nT ; + int nF = Surf.GetFacetFromTria( nT) ; + + Surf.GetFacetNormal( nF, vtInN) ; + + bInside = true ; + } + + // esco dalla superficie trimesh + else if ( dCos > EPS_SMALL && bInside) { + + Point3d ptOut = IntersectionResults[k].ptI ; + + int nT = IntersectionResults[k].nT ; + int nF = Surf.GetFacetFromTria( nT) ; + + Vector3d vtOutN ; + Surf.GetFacetNormal( nF, vtOutN) ; + + int nCurrentSize = int( m_Values[nMap][nPos].size()) ; + + // Aggiungo un tratto al dexel + m_Values[nMap][nPos].resize( nCurrentSize + 1) ; + + // Aggiorno dati del tratto di dexel + // Aggiungo un tratto al dexel attuale ( allo spillone ) + AddIntervals( nMap, nInfI, nInfJ, + ptIn.v[(nMap+2)%3] - ptMapOrig.v[(nMap+2)%3], + ptOut.v[(nMap+2)%3] - ptMapOrig.v[(nMap+2)%3], + vtInN, vtOutN, 0) ; + + bInside = false ; + } + } + } + } + } + return true ; + +} + //---------------------------------------------------------------------------- bool VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex) { - // Se la superficie non è chiusa oppure orientata al contrario non ha senso continuare + // Se la superficie non è chiusa oppure orientata al contrario non ha senso continuare double dVol ; if ( ! Surf.IsClosed() || ! Surf.GetVolume( dVol) || dVol < 0) return false ; @@ -543,14 +723,14 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex Point3d ptMapOrig, ptMapEnd ; SurfBBox.GetMinMax( ptMapOrig, ptMapEnd) ; - // Il dexel se parte da un triangolo della trimesh può non trovare l'intersezione, + // Il dexel se parte da un triangolo della trimesh può non trovare l'intersezione, // quindi espandiamo il bounding box per ovviare al problema. SurfBBox.Expand( 100 * EPS_SMALL, 100 * EPS_SMALL, 100 * EPS_SMALL) ; // Sistema di riferimento intrinseco dello Zmap m_MapFrame.Set( ptMapOrig, Frame3d::TOP) ; - // Il passo di discretizzazione non può essere inferiore a 100 * EPS_SMALL + // Il passo di discretizzazione non può essere inferiore a 100 * EPS_SMALL m_dStep = max( dStep, 100 * EPS_SMALL) ; // Determino le dimensioni lineari del BBox diff --git a/VolZmapVolume.cpp b/VolZmapVolume.cpp index ebeeaec..946d17d 100644 --- a/VolZmapVolume.cpp +++ b/VolZmapVolume.cpp @@ -132,10 +132,10 @@ VolZmap::SubtractIntervals( int nGrid, int nI, int nJ, // Imposto ricalcolo della grafica m_OGrMgr.Reset() ; - // Imposto forma generica - m_nShape = GENERIC ; + // Imposto forma generica + m_nShape = GENERIC ; // Imposto ricalcolo numero di componenti connesse - m_nConnectedCompoCount = - 1 ; + m_nConnectedCompoCount = - 1 ; // Passo da indici di dexel a indici di voxel nI /= m_nDexVoxRatio ; @@ -160,7 +160,7 @@ VolZmap::SubtractIntervals( int nGrid, int nI, int nJ, ++ nYStop ; } // Voxel lungo Z - int nVoxNumZ = int( m_nNy[1] / m_nDexVoxRatio + ( m_nNy[1] % m_nDexVoxRatio == 0 ? 1 : 2)) ; + int nVoxNumZ = int( m_nNy[1] / m_nDexVoxRatio + ( m_nNy[1] % m_nDexVoxRatio == 0 ? 1 : 2)) ; int nMinK = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) - EPS_SMALL))), 0, nVoxNumZ - 2) ; int nMaxK = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) + EPS_SMALL))), 0, nVoxNumZ - 2) ; int nMinZBlock = ( m_nMapNum == 1 ? 0 : Clamp( nMinK / int( m_nVoxNumPerBlock), 0, int( m_nFracLin[2] - 1))) ; @@ -227,8 +227,8 @@ VolZmap::SubtractIntervals( int nGrid, int nI, int nJ, nZBlock[1] = nZBlock[0] - 1 ; ++ nZStop ; } - // Voxel lungo Y - int nVoxNumY = int( m_nNy[0] / m_nDexVoxRatio + ( m_nNy[0] % m_nDexVoxRatio == 0 ? 1 : 2)) ; + // Voxel lungo Y + int nVoxNumY = int( m_nNy[0] / m_nDexVoxRatio + ( m_nNy[0] % m_nDexVoxRatio == 0 ? 1 : 2)) ; int nMinJ = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) - EPS_SMALL))), 0, nVoxNumY - 2) ; int nMaxJ = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) + EPS_SMALL))), 0, nVoxNumY - 2) ; int nMinYBlock = Clamp( nMinJ / int( m_nVoxNumPerBlock), 0, int( m_nFracLin[1] - 1)) ; @@ -249,232 +249,355 @@ VolZmap::SubtractIntervals( int nGrid, int nI, int nJ, //---------------------------------------------------------------------------- bool -VolZmap::AddIntervals( int nGrid, int nI, int nJ, - double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax, int nToolNum) +VolZmap::AddIntervals( int nGrid, int nI, int nJ, double dMin, double dMax, const Vector3d& vtNMin, + const Vector3d& vtNMax, int nToolNum) { -// // Controllo che dMin e dMax non siano quasi coincidenti -// if ( abs( dMax - dMin) < EPS_SMALL) -// return true ; -// -// // Controllo che il numero di griglia sia entro i limiti -// if ( nGrid < 0 || nGrid > 2) -// return false ; -// -// // Controllo che dMin < dMax -// if ( dMin > dMax) -// swap( dMin, dMax) ; -// -// // Controllo che indici nI, nJ siano entro i limiti -// if ( nI < 0 && nI >= m_nNx[nGrid] && -// nJ < 0 && nJ >= m_nNy[nGrid]) -// return false ; -// -// // Riporto le coordinate cicliche nell'ordine di partenza -// Vector3d vtNmi = vtNMin ; -// Vector3d vtNma = vtNMax ; -// if ( nGrid == 1) { -// swap( vtNmi.x, vtNmi.z) ; -// swap( vtNmi.y, vtNmi.z) ; -// swap( vtNma.x, vtNma.z) ; -// swap( vtNma.y, vtNma.z) ; -// } -// else if ( nGrid == 2) { -// swap( vtNmi.y, vtNmi.z) ; -// swap( vtNmi.x, vtNmi.z) ; -// swap( vtNma.y, vtNma.z) ; -// swap( vtNma.x, vtNma.z) ; -// } -// -// // Calcolo nPos -// unsigned int nPos = nJ * m_nNx[nGrid] + nI ; -// -// -// // Se spillone vuoto -// if ( m_Values[nGrid][nPos].size() == 0) { -// -// m_Values[nGrid][nPos].resize( 1) ; -// -// m_Values[nGrid][nPos][0].dMin = dMin ; -// m_Values[nGrid][nPos][0].dMax = dMax ; -// -// m_Values[nGrid][nPos][0].vtMinN = vtNmi ; -// m_Values[nGrid][nPos][0].vtMaxN = vtNma ; -// -// if ( dMax > m_dMaxZ[nGrid]) -// m_dMinZ[nGrid] = dMax ; -// -// if ( dMin < m_dMinZ[nGrid]) -// m_dMinZ[nGrid] = dMin ; -// -// m_OGrMgr.Reset() ; -// -// return true ; -// } -// -// // Ciclo sugli intervalli dello spillone -// bool bModified = false ; -// unsigned int i = 0 ; -// while ( i < m_Values[nGrid][nPos].size()) { -// -// // Eventuale aggiustamento di intervalli sovrapposti -// if ( i < m_Values[nGrid][nPos].size() - 1) { -// if ( m_Values[nGrid][nPos][i].dMax > m_Values[nGrid][nPos][i + 1].dMin - EPS_SMALL) { -// -// // Se l'intervallo corrente non è contenuto totalmente si esegue l'istruzione successiva -// if ( m_Values[nGrid][nPos][i].dMin < m_Values[nGrid][nPos][i + 1].dMin + EPS_SMALL) { -// -// m_Values[nGrid][nPos][i].dMax = m_Values[nGrid][nPos][i + 1].dMax ; -// m_Values[nGrid][nPos][i].vtMaxN = m_Values[nGrid][nPos][i + 1].vtMaxN ; -// } -// // altrimenti -// else { -// -// m_Values[nGrid][nPos][i].dMin = m_Values[nGrid][nPos][i].dMin ; -// m_Values[nGrid][nPos][i].vtMinN = m_Values[nGrid][nPos][i].vtMinN ; -// -// m_Values[nGrid][nPos][i].dMax = m_Values[nGrid][nPos][i].dMax ; -// m_Values[nGrid][nPos][i].vtMaxN = m_Values[nGrid][nPos][i].vtMaxN ; -// } -// -// for ( unsigned int j = i + 1 ; j < m_Values[nGrid][nPos].size() - 1 ; ++ j) { -// -// m_Values[nGrid][nPos][j].dMin = m_Values[nGrid][nPos][j + 1].dMin ; -// m_Values[nGrid][nPos][j].vtMinN = m_Values[nGrid][nPos][j + 1].vtMinN ; -// -// m_Values[nGrid][nPos][j].dMax = m_Values[nGrid][nPos][j + 1].dMax ; -// m_Values[nGrid][nPos][j].vtMaxN = m_Values[nGrid][nPos][j + 1].vtMaxN ; -// } -// -// m_Values[nGrid][nPos].resize( m_Values[nGrid][nPos].size() - 1) ; -// -// i = i - 1 ; -// } -// } -// -// -// // Caso in cui devo aggiungere un intervallo a sinistra dell'intervallo corrente -// if ( m_Values[nGrid][nPos][i].dZVal > dMax + EPS_SMALL) { -// -// bModified = true ; -// -// m_Values[nGrid][nPos].resize( m_Values[nGrid][nPos].size() + 2) ; -// -// for ( size_t j = m_Values[nGrid][nPos].size() - 1 ; j >= i + 2 ; -- j) { -// -// m_Values[nGrid][nPos][j].dZVal = m_Values[nGrid][nPos][j - 2].dZVal ; -// m_Values[nGrid][nPos][j].vtN = m_Values[nGrid][nPos][j - 2].vtN ; -// } -// -// -// m_Values[nGrid][nPos][i].dZVal = dMin ; -// m_Values[nGrid][nPos][i + 1].dZVal = dMax ; -// -// m_Values[nGrid][nPos][i].vtN = vtNMin ; -// m_Values[nGrid][nPos][i + 1].vtN = vtNMax ; -// -// i = i + 2 ; -// } -// -// // Casi d'intersezione: -// else if ( m_Values[nGrid][nPos][i + 1].dZVal > dMax - EPS_SMALL) { -// -// // Se l'intervallo da aggiungere sconfina a sinistra modifico il minimo dell'intervalo corrente -// if ( m_Values[nGrid][nPos][i].dZVal > dMin - EPS_SMALL) { -// -// bModified = true ; -// m_Values[nGrid][nPos][i].dZVal = dMin ; -// m_Values[nGrid][nPos][i].vtN = vtNmi ; -// } -// } -// -// else { -// // Se l'intervallo corrente è tutto contenuto nell'intervallo da aggungere modifico gli estremi -// if ( m_Values[nGrid][nPos][i].dZVal > dMin + EPS_SMALL) { -// -// bModified = true ; -// m_Values[nGrid][nPos][i].dZVal = dMin ; -// m_Values[nGrid][nPos][i + 1].dZVal = dMax ; -// m_Values[nGrid][nPos][i].vtN = vtNMin ; -// m_Values[nGrid][nPos][i + 1].vtN = vtNma ; -// } -// // Se l'intervallo da aggiungere sconfina a destra modifico il massimo dell'intervallo corrente -// else if ( m_Values[nGrid][nPos][i + 1].dZVal > dMin - EPS_SMALL) { -// -// bModified = true ; -// m_Values[nGrid][nPos][i + 1].dZVal = dMax ; -// m_Values[nGrid][nPos][i + 1].vtN = vtNma ; -// } -// else { -// // Aggiungo intervallo a destra dell'ultimo intervallo -// if ( i == m_Values[nGrid][nPos].size() - 2) { -// -// bModified = true ; -// m_Values[nGrid][nPos].resize( m_Values[nGrid][nPos].size() + 2) ; -// -// m_Values[nGrid][nPos][i + 2].dZVal = dMin ; -// m_Values[nGrid][nPos][i + 3].dZVal = dMax ; -// m_Values[nGrid][nPos][i + 2].vtN = vtNmi ; -// m_Values[nGrid][nPos][i + 3].vtN = vtNma ; -// -// i = i + 2 ; -// } -// } -// } -// -// i = i + 2 ; -// } -// -// // se eseguita modifica, imposto ricalcolo della grafica -// if ( bModified) { -// -// // Determino quali blocchi sono stati modificati -// int nLayerBlock = m_nFracLin[0] * m_nFracLin[1] ; -// -// if ( nGrid == 0) { -// -// int nXBlock = min( nI / m_nDexNumPBlock, m_nFracLin[0] - 1) ; -// int nYBlock = min( nJ / m_nDexNumPBlock, m_nFracLin[1] - 1) ; -// int nMinZBlock = max( 0, int( floor( ( dMin / m_dStep))) / int( m_nDexNumPBlock)) ; -// int nMaxZBlock = min( int( m_nFracLin[2] - 1), int( floor( ( dMax / m_dStep))) / int( m_nDexNumPBlock)) ; -// -// for ( int k = nMinZBlock ; k <= nMaxZBlock ; ++ k) -// -// m_BlockToUpdate[k * nLayerBlock + nYBlock * m_nFracLin[0] + nXBlock] = true ; -// } -// else if ( nGrid == 1) { -// -// int nYBlock = min( nI / m_nDexNumPBlock, m_nFracLin[1] - 1) ; -// int nZBlock = min( nJ / m_nDexNumPBlock, m_nFracLin[2] - 1) ; -// int nMinXBlock = max( 0, int( floor( ( dMin / m_dStep))) / int( m_nDexNumPBlock)) ; -// int nMaxXBlock = min( int( m_nFracLin[0] - 1), int( floor( ( dMax / m_dStep))) / int( m_nDexNumPBlock)) ; -// -// for ( int k = nMinXBlock ; k <= nMaxXBlock ; ++ k) -// -// m_BlockToUpdate[nZBlock * nLayerBlock + nYBlock * m_nFracLin[0] + k] = true ; -// } -// else if ( nGrid == 2) { -// -// int nXBlock = min( nJ / m_nDexNumPBlock, m_nFracLin[0] - 1) ; -// int nZBlock = min( nI / m_nDexNumPBlock, m_nFracLin[2] - 1) ; -// int nMinYBlock = max( 0, int( floor( ( dMin / m_dStep))) / int( m_nDexNumPBlock)) ; -// int nMaxYBlock = min( int( m_nFracLin[1] - 1), int( floor( ( dMax / m_dStep))) / int( m_nDexNumPBlock)) ; -// -// for ( int k = nMinYBlock ; k <= nMaxYBlock ; ++ k) -// -// m_BlockToUpdate[nZBlock * nLayerBlock + k * m_nFracLin[0] + nXBlock] = true ; -// } -// -// m_OGrMgr.Reset() ; -// -// // Aggiorno massima e minima Z -// // sullo Zmap -// if ( dMax > m_dMaxZ[nGrid]) -// m_dMinZ[nGrid] = dMax ; -// -// if ( dMin < m_dMinZ[nGrid]) -// m_dMinZ[nGrid] = dMin ; -// } -// + // Controllo che il numero di griglia sia entro i limiti + if ( nGrid < 0 || nGrid > 2) + return false ; + + // Controllo che indici nI, nJ siano entro i limiti + if ( nI < 0 && nI >= m_nNx[nGrid] && nJ < 0 && nJ >= m_nNy[nGrid]) + return false ; + + // Controllo che dMin < dMax ( nel caso swap parametri e vettori ) + Vector3d vtNmi = vtNMin ; + Vector3d vtNma = vtNMax ; + if ( dMin > dMax) { + swap( dMin, dMax) ; + swap( vtNmi, vtNma) ; + } + + // Restringo minimo e massimo entro i limiti della mappa + if ( dMin < m_dMinZ[nGrid]) { + dMin = m_dMinZ[nGrid] ; + vtNmi = - Z_AX ; + } + else if ( dMin > m_dMaxZ[nGrid]) { + dMin = m_dMaxZ[nGrid] ; + vtNmi = - Z_AX ; + } + if ( dMax < m_dMinZ[nGrid]) { + dMax = m_dMinZ[nGrid] ; + vtNma = Z_AX ; + } + else if ( dMax > m_dMaxZ[nGrid]) { + dMax = m_dMaxZ[nGrid] ; + vtNma = Z_AX ; + } + + // Controllo che dMin e dMax non siano quasi coincidenti ( la limitazione dei range può + // far collassare gli intervalli ) + if ( abs( dMax - dMin) < EPS_SMALL) + return true ; + + // Riporto le coordinate cicliche nell'ordine di partenza + if ( nGrid == 1) { + swap( vtNmi.x, vtNmi.z) ; + swap( vtNmi.y, vtNmi.z) ; + swap( vtNma.x, vtNma.z) ; + swap( vtNma.y, vtNma.z) ; + } + else if ( nGrid == 2) { + swap( vtNmi.y, vtNmi.z) ; + swap( vtNmi.x, vtNmi.z) ; + swap( vtNma.y, vtNma.z) ; + swap( vtNma.x, vtNma.z) ; + } + + // Calcolo nPos + unsigned int nPos = nJ * m_nNx[nGrid] + nI ; + vector& vDexel = m_Values[nGrid][nPos] ; + + bool bModified = false ; + + // se non esistono segmenti... + if ( int( vDexel.size()) == 0) { // ... definisco il primo + vDexel.emplace_back() ; + vDexel.back().dMin = dMin ; + vDexel.back().vtMinN = vtNmi ; + vDexel.back().nToolMin = nToolNum ; + vDexel.back().dMax = dMax ; + vDexel.back().vtMaxN = vtNma ; + vDexel.back().nToolMax = nToolNum ; + m_OGrMgr.Reset() ; + bModified = true ; // modifica effettuata + } + // se ne esiste almeno uno, devo controllare possibili overlaps + else { + // Cerco l'ultimo intervallo a sinistra e l'ultimo intervallo a destra di quello da aggiungere, + // che non interferiscono con quest'ultimo + auto itLastLeft = vDexel.end() ; + auto itFirstRight = vDexel.end() ; // per bloccare la prima iterazione... + for ( auto it = vDexel.begin() ; it != vDexel.end() ; ++ it) { + // se il minimo attuale è maggiore del massimo it-esimo, l'intervallo it-esimo è a sinistra + if ( dMin > it->dMax + EPS_SMALL) + itLastLeft = it ; // aggiorno + // se il massimo attuale è minore del minimo it-esimo, l'interallo it-esimo è a destra + if ( dMax < it->dMin - EPS_SMALL && itFirstRight == vDexel.end()) + itFirstRight = it ; // aggiorno + } + + // se esistono intervalli a sinistra... ( inizialmente l'iteratore è inizializzato su end()) + if ( itLastLeft != vDexel.end()) { + // prendo il successivo dell'ultimo più vicino + auto itNextToLastLeft = itLastLeft ; + ++ itNextToLastLeft ; + + // e se il successivo a sinistra non esiste... + if ( itNextToLastLeft == vDexel.end()) { + // aggiorno l'ultimo intervallo + vDexel.emplace_back() ; + vDexel.back().dMin = dMin ; + vDexel.back().dMax = dMax ; + vDexel.back().vtMinN = vtNmi ; + vDexel.back().vtMaxN = vtNma; + vDexel.back().nToolMin = nToolNum ; + vDexel.back().nToolMax = nToolNum ; + bModified = true ; + } + // se esiste... + else { + // controllo se coincide con il primo trovato a destra... + if ( itNextToLastLeft == itFirstRight) { + // in questo caso definisco il nuovo intervallo + Data NewSegment ; + NewSegment.dMin = dMin ; + NewSegment.dMax = dMax ; + NewSegment.vtMinN = vtNmi ; + NewSegment.vtMaxN = vtNma ; + NewSegment.nToolMin = nToolNum ; + NewSegment.nToolMax = nToolNum ; + vDexel.insert( itFirstRight, NewSegment) ; // inserimento intervallo + bModified = true ; + } + else { + // se il successivo non esce a sinistra da quello da aggiungere + if ( itNextToLastLeft->dMin > dMin + EPS_SMALL) { + itNextToLastLeft->dMin = dMin ; + itNextToLastLeft->vtMinN = vtNmi ; + itNextToLastLeft->nToolMin = nToolNum ; + } + // cerco poi l'ultimo segmento che interferisce con quello da aggiungere + auto itPrevToFirstRight = vDexel.end() ; + for ( auto it = itNextToLastLeft ; it != itFirstRight ; ++ it) + itPrevToFirstRight = it ; + // anche in qesto caso, se l'ultimo che interferisce non esce a destra da quello da aggiungere + if ( itPrevToFirstRight->dMax < dMax - EPS_SMALL) { + itNextToLastLeft->dMax = dMax ; + itNextToLastLeft->vtMaxN = vtNma ; + itNextToLastLeft->nToolMax = nToolNum ; + bModified = true ; + } + else { + itNextToLastLeft->dMax = itPrevToFirstRight->dMax ; + itNextToLastLeft->vtMaxN = itPrevToFirstRight->vtMaxN ; + itNextToLastLeft->nToolMax = nToolNum ; + bModified = true ; + } + // cancello il successivo... + auto itFirstToCancel = itNextToLastLeft ; + ++ itFirstToCancel ; + vDexel.erase( itFirstToCancel, itFirstRight) ; + } + } + } + // se non esiste da destra ... + else if ( itFirstRight == m_Values[nGrid][nPos].end()) { + // e il primo intervallo non sporge a sinistra ... + if ( vDexel.begin()->dMin > dMin + EPS_SMALL) { + vDexel.begin()->dMin = dMin ; + vDexel.begin()->vtMinN = vtNmi ; + vDexel.begin()->nToolMin = nToolNum ; + bModified = true ; + } + // se sporge da destra + if ( m_Values[nGrid][nPos].back().dMax > dMax + EPS_SMALL) { + // allora ci sono più segmenti, inglobo tutti nel primo + if ( vDexel.back().dMax > vDexel.begin()->dMax + EPS_SMALL) { + vDexel.begin()->dMax = vDexel.back().dMax ; + vDexel.begin()->vtMaxN = vDexel.back().vtMaxN ; + vDexel.begin()->nToolMax = nToolNum ; + bModified = true ; + } + } + // se l'ultimo intervallo non sporge a destra. + else { + vDexel.begin()->dMax = dMax ; + vDexel.begin()->vtMaxN = vtNma ; + vDexel.begin()->nToolMax = nToolNum ; + bModified = true ; + } + // cancello quelli inglobati + vDexel.erase( vDexel.begin() + 1, vDexel.end()) ; + } + // Casi Estremi... + else { + // 1) Tutti i segmenti sono a destra da quello da aggiungere... + if ( itFirstRight == vDexel.begin()) { + // -> inserisco il nuovo intervallo + Data NewSegment ; + NewSegment.dMin = dMin ; + NewSegment.dMax = dMax ; + NewSegment.vtMinN = vtNmi ; + NewSegment.vtMaxN = vtNma ; + NewSegment.nToolMin = nToolNum ; + NewSegment.nToolMax = nToolNum ; + vDexel.insert( vDexel.begin(), NewSegment) ; // posizione iniziale + bModified = true ; + } + else { + // se il primo segmento non esce a sinistra da quello da aggiungere, cambio l'inizio + if ( vDexel.begin()->dMin > dMin + EPS_SMALL) { + vDexel.begin()->dMin = dMin ; + vDexel.begin()->vtMinN = vtNmi ; + vDexel.begin()->nToolMin = nToolNum ; + bModified = true ; + } + // cerco l'ultimo segmento che interferisce con quello da aggiungere + auto itPrevToFirstRight = vDexel.begin() ; + for ( auto it = m_Values[nGrid][nPos].begin() ; it != itFirstRight ; ++ it) + itPrevToFirstRight = it ; + // se l'ultimo che interferisce non esce a destra da quello da aggiungere... + if ( itPrevToFirstRight->dMax < dMax - EPS_SMALL) { + vDexel.begin()->dMax = dMax ; + vDexel.begin()->vtMaxN = vtNma ; + vDexel.begin()->nToolMax = nToolNum ; + bModified = true ; + } + // ... altrimenti + else { + vDexel.begin()->dMax = itPrevToFirstRight->dMax ; + vDexel.begin()->vtMaxN = itPrevToFirstRight->vtMaxN ; + vDexel.begin()->nToolMax = nToolNum ; + bModified = true ; + } + // cancello gli inglobati ( come prima ) + auto itFirstToCancel = vDexel.begin() ; + ++ itFirstToCancel ; + vDexel.erase( itFirstToCancel, itFirstRight) ; + } + } + } + + // Se nessuna modifica, esco + if ( ! bModified) + return true ; + + // Imposto ricalcolo della grafica + m_OGrMgr.Reset() ; + // Imposto forma generica + m_nShape = GENERIC ; + // Imposto ricalcolo numero di componenti connesse + m_nConnectedCompoCount = - 1 ; + + // Passo da indici di dexel a indici di voxel + nI /= m_nDexVoxRatio ; + nJ /= m_nDexVoxRatio ; + + // Determino quali blocchi sono stati modificati a seconda della griglia + if ( nGrid == 0) { + // Voxel lungo X + int nXStop = 1 ; + int nXBlock[2] ; + nXBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[0] - 1) ; + if ( nI % N_VOXBLOCK == 0 && nXBlock[0] > 0) { + nXBlock[1] = nXBlock[0] - 1 ; + ++ nXStop ; + } + // Voxel lungo Y + int nYStop = 1 ; + int nYBlock[2] ; + nYBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[1] - 1) ; + if ( nJ % N_VOXBLOCK == 0 && nYBlock[0] > 0) { + nYBlock[1] = nYBlock[0] - 1 ; + ++ nYStop ; + } + // Voxel lungo Z + int nVoxNumZ = int( m_nNy[1] / m_nDexVoxRatio + ( m_nNy[1] % m_nDexVoxRatio == 0 ? 1 : 2)) ; + int nMinK = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) - EPS_SMALL))), 0, nVoxNumZ - 2) ; + int nMaxK = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) + EPS_SMALL))), 0, nVoxNumZ - 2) ; + int nMinZBlock = ( m_nMapNum == 1 ? 0 : Clamp( nMinK / int( m_nVoxNumPerBlock), 0, int( m_nFracLin[2] - 1))) ; + int nMaxZBlock = min( int( m_nFracLin[2] - 1), nMaxK / int( m_nVoxNumPerBlock)) ; + // Assegno flag ai voxel + for ( int tI = 0 ; tI < nXStop ; ++ tI) { + for ( int tJ = 0 ; tJ < nYStop ; ++ tJ) { + for ( int k = nMinZBlock ; k <= nMaxZBlock ; ++ k) { + int nBlockNum = k * m_nFracLin[0] * m_nFracLin[1] + nYBlock[tJ] * m_nFracLin[0] + nXBlock[tI] ; + m_BlockToUpdate[nBlockNum] = true ; + } + } + } + } + + else if ( nGrid == 1) { + // Voxel lungo Y + int nYStop = 1 ; + int nYBlock[2] ; + nYBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[1] - 1) ; + if ( nI % N_VOXBLOCK == 0 && nYBlock[0] > 0) { + nYBlock[1] = nYBlock[0] - 1 ; + ++ nYStop ; + } + // Voxel lungo Z + int nZStop = 1 ; + int nZBlock[2] ; + nZBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[2] - 1) ; + if ( nJ % N_VOXBLOCK == 0 && nZBlock[0] > 0) { + nZBlock[1] = nZBlock[0] - 1 ; + ++ nZStop ; + } + // Voxel lungo X + int nVoxNumX = int( m_nNx[0] / m_nDexVoxRatio + ( m_nNx[0] % m_nDexVoxRatio == 0 ? 1 : 2)) ; + int nMinI = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) - EPS_SMALL))), 0, nVoxNumX - 2) ; + int nMaxI = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) + EPS_SMALL))), 0, nVoxNumX - 2) ; + int nMinXBlock = Clamp( nMinI / int( m_nVoxNumPerBlock), 0, int( m_nFracLin[0] - 1)) ; + int nMaxXBlock = min( int( m_nFracLin[0] - 1), nMaxI / int( m_nVoxNumPerBlock)) ; + // Assegno flag ai voxel + for ( int tI = 0 ; tI < nYStop ; ++ tI) { + for ( int tJ = 0 ; tJ < nZStop ; ++ tJ) { + for ( int k = nMinXBlock ; k <= nMaxXBlock ; ++ k) { + int nBlockNum = nZBlock[tJ] * m_nFracLin[0] * m_nFracLin[1] + nYBlock[tI] * m_nFracLin[0] + k ; + m_BlockToUpdate[nBlockNum] = true ; + } + } + } + } + + else if ( nGrid == 2) { + // Voxel lungo X + int nXStop = 1 ; + int nXBlock[2] ; + nXBlock[0] = min( nJ / m_nVoxNumPerBlock, m_nFracLin[0] - 1) ; + if ( nJ % N_VOXBLOCK == 0 && nXBlock[0] > 0) { + nXBlock[1] = nXBlock[0] - 1 ; + ++ nXStop ; + } + // Voxel lungo Z + int nZStop = 1 ; + int nZBlock[2] ; + nZBlock[0] = min( nI / m_nVoxNumPerBlock, m_nFracLin[2] - 1) ; + if ( nI % N_VOXBLOCK == 0 && nZBlock[0] > 0) { + nZBlock[1] = nZBlock[0] - 1 ; + ++ nZStop ; + } + // Voxel lungo Y + int nVoxNumY = int( m_nNy[0] / m_nDexVoxRatio + ( m_nNy[0] % m_nDexVoxRatio == 0 ? 1 : 2)) ; + int nMinJ = Clamp( int( floor( ( ( dMin - 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) - EPS_SMALL))), 0, nVoxNumY - 2) ; + int nMaxJ = Clamp( int( floor( ( ( dMax + 0.5 * m_dStep) / ( m_nDexVoxRatio * m_dStep) + EPS_SMALL))), 0, nVoxNumY - 2) ; + int nMinYBlock = Clamp( nMinJ / int( m_nVoxNumPerBlock), 0, int( m_nFracLin[1] - 1)) ; + int nMaxYBlock = min( int( m_nFracLin[1] - 1), nMaxJ / int( m_nVoxNumPerBlock)) ; + // Assegno flag ai voxel + for ( int tI = 0 ; tI < nZStop ; ++ tI) { + for ( int tJ = 0 ; tJ < nXStop ; ++ tJ) { + for ( int k = nMinYBlock ; k <= nMaxYBlock ; ++ k) { + int nBlockNum = nZBlock[tI] * m_nFracLin[0] * m_nFracLin[1] + k * m_nFracLin[0] + nXBlock[tJ] ; + m_BlockToUpdate[nBlockNum] = true ; + } + } + } + } + return true ; }