diff --git a/VolZmap.cpp b/VolZmap.cpp index cb1b028..352d434 100644 --- a/VolZmap.cpp +++ b/VolZmap.cpp @@ -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 #include @@ -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> 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 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 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 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) diff --git a/VolZmap.h b/VolZmap.h index 85034ef..c7fcb86 100644 --- a/VolZmap.h +++ b/VolZmap.h @@ -143,6 +143,8 @@ 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 AddSurfTm( const ISurfTriMesh* pStm) override ; + bool MakeUniform( double dToler) override ; public : // IGeoObjRW int GetNgeId( void) const override ; @@ -243,9 +245,15 @@ class VolZmap : public IVolZmap, public IGeoObjRW INTVECTOR& vAdjBlockVoxComp, INTVECTOR& vAdjBordBlockVoxComp) const ; // OPERAZIONI SU INTERVALLI bool SubtractIntervals( int nGrid, int nI, int nJ, - double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax, int nToolNum) ; + double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax, + int nToolNum, bool bSkipSwap = false) ; bool AddIntervals( int nGrid, int nI, int nJ, - double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax, int nToolNum) ; + double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax, + int nToolNum, bool bSkipSwap = false) ; + bool AddMissingIntervalsInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, double dZ, double dToler, + Vector3d vtToolMin, Vector3d vtToolMax, int nToolNum) ; + bool AddSubIntervalInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, int nK, double& dMin, double& dMax, + Vector3d& vtMin, Vector3d& vtMax) ; // Spostamenti utensile bool MillingTranslationStep( const Point3d& ptPs, const Point3d& ptPe, const Vector3d& vtD, const Vector3d& vtA) ; bool MillingGeneralMotionStep( const Point3d& ptPs, const Vector3d& vtDs, const Vector3d& vtAs, @@ -422,6 +430,8 @@ 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) ; + bool AddMapPart( 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} ; @@ -455,6 +465,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW } ; std::vector> m_Values[N_MAPS] ; // dexel delle 3 griglie + int m_nShape ; // Forma : 0 generica, 1 box, 2 estrusione int m_nVoxNumPerBlock ; // Numero di voxel per blocco diff --git a/VolZmapCreation.cpp b/VolZmapCreation.cpp index a6a9d6a..b5abb62 100644 --- a/VolZmapCreation.cpp +++ b/VolZmapCreation.cpp @@ -597,6 +597,99 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co return true ; } +bool +VolZmap::AddMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig, + const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) +{ + // controllo sui parametri + 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) ; + + // intersezioni della retta con la TriMesh + ILSIVECTOR IntersectionResults ; + intPLSTM.GetInters( ptP0, vtLen.v[(nMap+2)%3], IntersectionResults) ; + + // rimuovo le intersezioni in eccesso + for ( int nI = 0 ; nI < int( IntersectionResults.size()) - 3 ; ++ nI) { + int nJ = nI + 1 ; // prima successiva + int nK = nJ + 1 ; // seconda successiva + int nT = nK + 1 ; // terza successiva + // determino i segni delle 4 intersezioni tra la linea e il trangolo della TriMesh + 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 ; + // parametri dell'intersezione sulla linea + double dUJ = IntersectionResults[nJ].dU ; + double dUK = IntersectionResults[nK].dU ; + // controllo coerenza con segni... + if ( nSgnI != 0 && nSgnI == nSgnJ && + nSgnK != 0 && nSgnK == nSgnT && + nSgnI == - nSgnT && + abs( dUJ - dUK) < EPS_SMALL) { + // ... ed elimino le intersezioni in eccesso... + IntersectionResults.erase( IntersectionResults.begin() + nK) ; + IntersectionResults.erase( IntersectionResults.begin() + nJ) ; + } + } + + int nInt = int( IntersectionResults.size()) ; // numero di intersezioni valide + int nPos = j * m_nNx[nMap] + i ; // posizione del dexel corrente + bool bInside = false ; // Flag entrata/uscita per tratto di retta + Point3d ptIn ; Vector3d vtInN ; + + // per ogni intersezione valida trovata... + for ( int k = 0 ; k < nInt ; ++ k) { + // ricavo il tipo di intersezione + int nIntType = IntersectionResults[k].nILTT ; + // se c'è intersezione + if ( nIntType != ILTT_NO) { + // ricavo il cos tra i vettori ( normale del triangolo e tangente alla retta) + double dCos = IntersectionResults[k].dCosDN ; + + // se entro nella superficie trimesh... + if ( dCos < - EPS_SMALL) { + ptIn = IntersectionResults[k].ptI ; // punto di intersezione + int nT = IntersectionResults[k].nT ; // triangolo di interesse + int nF = Surf.GetFacetFromTria( nT) ; // faccia di interesse + Surf.GetFacetNormal( nF, vtInN) ; + bInside = true ; // entrata + } + // ...se esco dalla superficie trimesh ( prima sono per forza entrato) + else if ( dCos > EPS_SMALL && bInside) { + Point3d ptOut = IntersectionResults[k].ptI ; // punto di intersezione + int nT = IntersectionResults[k].nT ; // triangolo di interesse + int nF = Surf.GetFacetFromTria( nT) ; // faccia di interesse + Vector3d vtOutN ; Surf.GetFacetNormal( nF, vtOutN) ; // vettore d'uscita + + // Aggiungo un tratto al dexel + AddIntervals( nMap, i, j, + ptIn.v[(nMap+2)%3] - ptMapOrig.v[(nMap+2)%3], + ptOut.v[(nMap+2)%3] - ptMapOrig.v[(nMap+2)%3], + vtInN, vtOutN, 0, true) ; + bInside = false ; // uscita + } + } + } + } + } + + return true ; +} + //---------------------------------------------------------------------------- bool VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex) diff --git a/VolZmapGraphics.cpp b/VolZmapGraphics.cpp index d79817f..001a6aa 100644 --- a/VolZmapGraphics.cpp +++ b/VolZmapGraphics.cpp @@ -3327,12 +3327,12 @@ VolZmap::IsThereMat( int nI, int nJ, int nK) const nK *= m_nDexVoxRatio ; // Se l'indice è alla frontiera del reticolo non vi è materiale - if ( nI <= - 1 || nI >= int( m_nNx[0]) || + if ( nI <= - 1 || nI >= int( m_nNx[0]) || nJ <= - 1 || nJ >= int( m_nNy[0]) || - nK <= - 1 || nK >= int( m_nNy[1])) + nK <= - 1 || nK >= int( m_nNy[1])) return false ; - // ciclo sulle griglie + // ciclo sulle griglie int nCount = 0 ; int nMinPos[3] = { -1, -1, -1} ; int nMinIndex[3] ; @@ -3361,18 +3361,22 @@ VolZmap::IsThereMat( int nI, int nJ, int nK) const } // verifica spillone su vertice double dMinDist = INFINITO ; - int nIndex = 0 ; + int nIndex = 0 ; int nPos = nGrJ * m_nNx[nGrid] + nGrI ; nDexSize[nGrid] = int( m_Values[nGrid][nPos].size()) ; + // scorro i sotto-interalli dello spillone while ( nIndex < nDexSize[nGrid]) { + // distanza tra la "Z" attuale e il parametro minimo e massimo dell'intervallo nIndex-esimo double dDistInf = dZ[nGrid] - m_Values[nGrid][nPos][nIndex].dMin + 2 * EPS_SMALL ; double dDistSup = dZ[nGrid] - m_Values[nGrid][nPos][nIndex].dMax - 2 * EPS_SMALL ; + // se "Z" attuale a cavallo tra queste due distanze... if ( dDistInf > 0. && dDistSup < 0.) { - nMinIndex[nGrid] = nIndex ; + nMinIndex[nGrid] = nIndex ; // aggiorno l'indice ++ nCount ; - bInterOnNode[nGrid] = true ; + bInterOnNode[nGrid] = true ; // flag T per griglia zero break ; } + // se "Z" attuale tutta sopra o tutta sotto else { double dDist = min( abs( dDistInf), abs( dDistSup)) ; if ( dDist < dMinDist) { @@ -3380,16 +3384,22 @@ VolZmap::IsThereMat( int nI, int nJ, int nK) const nMinIndex[nGrid] = nIndex ; dMinDist = dDist ; } - } + } + // sotto-intervallo successivo nIndex += 1 ; } - } - if ( nCount == 3) + } // fine ciclo sulle griglie + + if ( nCount == 3) // ... se interno a tutte e 3 le griglie, allora c'è materiale ... return true ; - else if ( nCount == 2) { + else if ( nCount == 2) { // ... se interno solo a 2 griglie ... + // recupero la griglia sulla quale è esterno int nGrid = ( bInterOnNode[0] ? ( bInterOnNode[1] ? 2 : 1) : 0) ; + // se tale griglia non ha sotto-intervalli allora non c'è materiale if ( nDexSize[nGrid] == 0) return false ; + // se il valore in "Z" dello spillone è vicino al punto ( 1/10 dello step), aggiorno il + // parametro minimo e massimo e considero la presenza di materiale if ( dZ[nGrid] > m_Values[nGrid][nMinPos[nGrid]][nMinIndex[nGrid]].dMin - 0.1 * m_dStep && dZ[nGrid] < m_Values[nGrid][nMinPos[nGrid]][nMinIndex[nGrid]].dMax + 0.1 * m_dStep) { double dDistInf = abs( dZ[nGrid] - m_Values[nGrid][nMinPos[nGrid]][nMinIndex[nGrid]].dMin) ; @@ -3401,9 +3411,9 @@ VolZmap::IsThereMat( int nI, int nJ, int nK) const return true ; } else - return false ; + return false ; } - else + else // ... se invece interno a 1 o a nessuna delle griglie, allora non c'è materiale return false ; } diff --git a/VolZmapVolume.cpp b/VolZmapVolume.cpp index 03f5561..9466788 100644 --- a/VolZmapVolume.cpp +++ b/VolZmapVolume.cpp @@ -30,7 +30,8 @@ using namespace std ; //---------------------------------------------------------------------------- bool VolZmap::SubtractIntervals( int nGrid, int nI, int nJ, - double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax, int nToolNum) + double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax, + int nToolNum, bool bSkipSwap) { // Controllo che dMin e dMax non siano quasi coincidenti if ( abs( dMax - dMin) < EPS_ZERO) @@ -54,13 +55,13 @@ VolZmap::SubtractIntervals( int nGrid, int nI, int nJ, } // Riporto le coordinate cicliche delle normali nell'ordine di partenza (da griglia a sistema intrinseco) - if ( nGrid == 1) { + if ( !bSkipSwap && 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) { + else if ( !bSkipSwap && nGrid == 2) { swap( vtNmi.y, vtNmi.z) ; swap( vtNmi.x, vtNmi.z) ; swap( vtNma.y, vtNma.z) ; @@ -250,7 +251,8 @@ 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) + double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax, + int nToolNum, bool bSkipSwap) { // Controllo che il numero di griglia sia entro i limiti if ( nGrid < 0 || nGrid > 2) @@ -272,19 +274,23 @@ VolZmap::AddIntervals( int nGrid, int nI, int nJ, // Restringo minimo e massimo entro i limiti della mappa if ( dMin < m_dMinZ[nGrid]) { dMin = m_dMinZ[nGrid] ; - vtNmi = - Z_AX ; + if ( ! bSkipSwap) + vtNmi = - Z_AX ; } else if ( dMin > m_dMaxZ[nGrid]) { dMin = m_dMaxZ[nGrid] ; - vtNmi = - Z_AX ; + if ( ! bSkipSwap) + vtNmi = - Z_AX ; } if ( dMax < m_dMinZ[nGrid]) { dMax = m_dMinZ[nGrid] ; - vtNma = Z_AX ; + if ( ! bSkipSwap) + vtNma = Z_AX ; } else if ( dMax > m_dMaxZ[nGrid]) { dMax = m_dMaxZ[nGrid] ; - vtNma = Z_AX ; + if ( ! bSkipSwap) + vtNma = Z_AX ; } // Controllo che dMin e dMax non siano quasi coincidenti @@ -292,13 +298,13 @@ VolZmap::AddIntervals( int nGrid, int nI, int nJ, return true ; // Riporto le coordinate cicliche nell'ordine di partenza - if ( nGrid == 1) { + if ( !bSkipSwap && 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) { + else if ( !bSkipSwap && nGrid == 2) { swap( vtNmi.y, vtNmi.z) ; swap( vtNmi.x, vtNmi.z) ; swap( vtNma.y, vtNma.z) ; @@ -600,6 +606,213 @@ VolZmap::AddIntervals( int nGrid, int nI, int nJ, return true ; } +//---------------------------------------------------------------------------- +bool +VolZmap::AddSubIntervalInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, int nK, + double& dMin, double& dMax, Vector3d& vtMin, Vector3d& vtMax) +{ + // se non Tridex, esco + if ( ! IsTriDexel()) + return true ; + + // 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 ; + + // valori di default + vector vTdMin = { -1., -1., -1., -1.} ; + vector vTdMax = { -1., -1., -1., -1.} ; + VCT3DVECTOR vtNMin = { V_INVALID, V_INVALID, V_INVALID, V_INVALID} ; + VCT3DVECTOR vtNMax = { V_INVALID, V_INVALID, V_INVALID, V_INVALID} ; + + // se esiste un precedente lungo x-locale + if ( nI != 0) { + int nPos = nJ * m_nNx[nGrid] + ( nI - 1) ; // recupero posizione dexel + // cerco l'intervallo corretto sullo Zmap di riferimento + for ( int it = 0 ; it < int( VolZmapRef->m_Values[nGrid][nPos].size()) ; ++ it) { + if ( VolZmapRef->m_Values[nGrid][nPos][it].dMax + EPS_SMALL > nK * m_dStep && + VolZmapRef->m_Values[nGrid][nPos][it].dMax - EPS_SMALL < ( nK + 1) * m_dStep) { + vtNMax[0] = VolZmapRef->m_Values[nGrid][nPos][it].vtMaxN ; + vTdMax[0] = VolZmapRef->m_Values[nGrid][nPos][it].dMax ; + } + if ( VolZmapRef->m_Values[nGrid][nPos][it].dMin + EPS_SMALL > nK * m_dStep && + VolZmapRef->m_Values[nGrid][nPos][it].dMin - EPS_SMALL < ( nK + 1) * m_dStep) { + vtNMin[0] = VolZmapRef->m_Values[nGrid][nPos][it].vtMinN ; + vTdMin[0] = VolZmapRef->m_Values[nGrid][nPos][it].dMin ; + } + } + } + // se esiste il successivo lungo x-locale + if ( nI != m_dMaxZ[( nGrid + 2) % 3]) { + int nPos = nJ * m_nNx[nGrid] + ( nI + 1) ; // recupero posizione dexel + for ( int it = 0 ; it < int( VolZmapRef->m_Values[nGrid][nPos].size()) ; ++ it) { + // cerco l'intervallo corretto sullo Zmap di riferimento + if ( VolZmapRef->m_Values[nGrid][nPos][it].dMax + EPS_SMALL > nK * m_dStep && + VolZmapRef->m_Values[nGrid][nPos][it].dMax - EPS_SMALL < ( nK + 1) * m_dStep) { + vtNMax[1] = VolZmapRef->m_Values[nGrid][nPos][it].vtMaxN ; + vTdMax[1] = VolZmapRef->m_Values[nGrid][nPos][it].dMax ; + } + if ( VolZmapRef->m_Values[nGrid][nPos][it].dMin + EPS_SMALL > nK * m_dStep && + VolZmapRef->m_Values[nGrid][nPos][it].dMin - EPS_SMALL < ( nK + 1) * m_dStep) { + vtNMin[1] = VolZmapRef->m_Values[nGrid][nPos][it].vtMinN ; + vTdMin[1] = VolZmapRef->m_Values[nGrid][nPos][it].dMin ; + } + } + } + // se esiste il precedente lungo y-locale + if ( nJ != 0) { + int nPos = ( nJ - 1) * m_nNx[nGrid] + nI ; // recupero posizione dexel + for ( int it = 0 ; it < int( VolZmapRef->m_Values[nGrid][nPos].size()) ; ++ it) { + // cerco l'intervallo corretto sullo Zmap di riferimento + if ( VolZmapRef->m_Values[nGrid][nPos][it].dMax + EPS_SMALL > nK * m_dStep && + VolZmapRef->m_Values[nGrid][nPos][it].dMax - EPS_SMALL < ( nK + 1) * m_dStep) { + vtNMax[2] = VolZmapRef->m_Values[nGrid][nPos][it].vtMaxN ; + vTdMax[2] = VolZmapRef->m_Values[nGrid][nPos][it].dMax ; + } + if ( VolZmapRef->m_Values[nGrid][nPos][it].dMin + EPS_SMALL > nK * m_dStep && + VolZmapRef->m_Values[nGrid][nPos][it].dMin - EPS_SMALL < ( nK + 1) * m_dStep) { + vtNMin[2] = VolZmapRef->m_Values[nGrid][nPos][it].vtMinN ; + vTdMin[2] = VolZmapRef->m_Values[nGrid][nPos][it].dMin ; + } + } + } + // se esiste il successivo lungo y-locale + if ( nJ != m_dMaxZ[( nGrid + 1) % 3]) { + int nPos = ( nJ + 1) * m_nNx[nGrid] + nI ; // recupero posizione dexel + // cerco l'intervallo corretto sullo Zmap di riferimento + for ( int it = 0 ; it < int( VolZmapRef->m_Values[nGrid][nPos].size()) ; ++ it) { + if ( VolZmapRef->m_Values[nGrid][nPos][it].dMax + EPS_SMALL > nK * m_dStep && + VolZmapRef->m_Values[nGrid][nPos][it].dMax - EPS_SMALL < ( nK + 1) * m_dStep) { + vtNMax[3] = VolZmapRef->m_Values[nGrid][nPos][it].vtMaxN ; + vTdMax[3] = VolZmapRef->m_Values[nGrid][nPos][it].dMax ; + } + if ( VolZmapRef->m_Values[nGrid][nPos][it].dMin + EPS_SMALL > nK * m_dStep && + VolZmapRef->m_Values[nGrid][nPos][it].dMin - EPS_SMALL < ( nK + 1) * m_dStep) { + vtNMin[3] = VolZmapRef->m_Values[nGrid][nPos][it].vtMinN ; + vTdMin[3] = VolZmapRef->m_Values[nGrid][nPos][it].dMin ; + } + } + } + + // scelgo le normali che si discostano il meno possibile dalla normale della faccia del voxel + + // analisi dei massimi e delle normali --------------------------- + // 1) angolo minimo tra la normale trovata la faccia del voxel + double dMinAngle = ANG_FULL ; + // 2) vettore di riferimento per la direzione della normale + vtMax = ( nGrid == 0 ? m_MapFrame.VersZ() : + ( nGrid == 1 ? m_MapFrame.VersX() : m_MapFrame.VersY())) ; + Vector3d vtRef = vtMax ; + // 3) determino il massimo per questo intervallo + dMax = ( nK + 1) * m_dStep ; + for ( int i = 0 ; i < 4 ; ++ i) { // scorro le normali + if ( vtNMax[i].IsValid()) { // se normale trovata, quindi valida... + double dCurrAngle ; // angolo corrente tra la normale della TriMesh e quella della faccia del voxel + vtNMax[i].GetAngle( vtRef, dCurrAngle) ; + if ( abs( dCurrAngle) < dMinAngle) { // se angolo minore del minimo trovato... + // aggiorno i parametri + dMinAngle = dCurrAngle ; + vtMax = vtNMax[i] ; + dMax = vTdMax[i] ; + } + } + } + + // analisi dei minimi e delle normali --------------------------- + dMinAngle = ANG_FULL ; + vtRef.Invert() ; + dMin = nK * m_dStep ; + vtMin = vtRef ; + for ( int i = 0 ; i < 4 ; ++ i) { + if ( vtNMin[i].IsValid()) { + double dCurrAngle ; + vtNMin[i].GetAngle( vtRef, dCurrAngle) ; + if ( abs( dCurrAngle) < dMinAngle) { + dMinAngle = dCurrAngle ; + vtMin = vtNMin[i] ; + dMin = vTdMin[i] ; + } + } + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +VolZmap::AddMissingIntervalsInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, double dZ, double dToler, + Vector3d vtToolMin, Vector3d vtToolMax, int nToolNum) +{ + + // se non Tridex, esco + if ( ! IsTriDexel()) + return true ; + + // 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 ; + + // passo da indici di dexel a indici di voxel + nI /= m_nDexVoxRatio ; + nJ /= m_nDexVoxRatio ; + + // numero di voxel nel dexel corrente + int nVoxNum = int( m_nNy[(( nGrid+1) % 3)] / m_nDexVoxRatio + + ( m_nNy[(( nGrid+1) % 3)] % m_nDexVoxRatio == 0 ? 1 : 2)) ; + + int nK = 0 ; + for ( int i = 0 ; i < nVoxNum ; ++ i) { + // controllo se sono nel voxel corrente + if ( i * m_dStep < dZ && ( i + 1) * m_dStep > dZ) { + nK = i ; + break ; + } + } + + // ----------- griglia successiva ----------- + { + int nMyGrid = ( nGrid + 1) % 3 ; + int nMyI = nJ ; + int nMyJ = nK ; + int nMyK = nI ; + double dMyMin ; + double dMyMax ; + Vector3d vtMyMin ; + Vector3d vtMyMax ; + AddSubIntervalInVoxel( VolZmapRef, nMyGrid, nMyI, nMyJ, nMyK, dMyMin, dMyMax, vtMyMin, vtMyMax) ; + AddIntervals( nMyGrid, nMyI, nMyJ, dMyMin - EPS_SMALL, dMyMax + EPS_SMALL, vtMyMin, vtMyMax, + nToolNum, true) ; + } + + // ----------- griglia precedente ----------- + { + int nMyGrid = ( nGrid + 2) % 3 ; + int nMyI = nK ; + int nMyJ = nI ; + int nMyK = nJ ; + double dMyMin ; + double dMyMax ; + Vector3d vtMyMin ; + Vector3d vtMyMax ; + AddSubIntervalInVoxel( VolZmapRef, nMyGrid, nMyI, nMyJ, nMyK, dMyMin, dMyMax, vtMyMin, vtMyMax) ; + AddIntervals( nMyGrid, nMyI, nMyJ, dMyMin - EPS_SMALL, dMyMax + EPS_SMALL, vtMyMin, vtMyMax, + nToolNum, true) ; + } + + return true ; + +} + // ------------------------- LAVORAZIONI -------------------------------------------------------------------------------------- //----------------------------------------------------------------------------