diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 620ba6b..f73ed6d 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/VolZmap.cpp b/VolZmap.cpp index 2a7c675..8e84e1b 100644 --- a/VolZmap.cpp +++ b/VolZmap.cpp @@ -140,6 +140,9 @@ VolZmap::CopyFrom( const VolZmap& vzmSrc) m_BlockToUpdate.resize( m_nNumBlock) ; m_InterBlockVox.resize( m_nNumBlock) ; m_InterBlockTria.resize( m_nNumBlock) ; + m_SliceXY.resize( m_nNumBlock) ; + m_SliceXZ.resize( m_nNumBlock) ; + m_SliceYZ.resize( m_nNumBlock) ; // imposto ricalcolo grafica ResetGraphics() ; @@ -369,6 +372,9 @@ VolZmap::Load( NgeReader& ngeIn) // per triangoli di feature di frontiera tra blocchi m_InterBlockVox.resize( m_nNumBlock) ; m_InterBlockTria.resize( m_nNumBlock) ; + m_SliceXY.resize( m_nNumBlock) ; + m_SliceXZ.resize( m_nNumBlock) ; + m_SliceYZ.resize( m_nNumBlock) ; m_nStatus = OK ; return true ; @@ -1088,6 +1094,9 @@ VolZmap::ClonePart( int nPart) const pVolume->m_InterBlockVox.resize( pVolume->m_nNumBlock) ; // Dimensiono raccolta triangoli di feature tra blocchi pVolume->m_InterBlockTria.resize( pVolume->m_nNumBlock) ; + pVolume->m_SliceXY.resize( pVolume->m_nNumBlock) ; + pVolume->m_SliceXZ.resize( pVolume->m_nNumBlock) ; + pVolume->m_SliceYZ.resize( pVolume->m_nNumBlock) ; // Sistema di riferimento intrinseco del nuovo solido Point3d ptNewO = m_MapFrame.Orig() + Vector3d( dNewOx, dNewOy, dNewOz) ; diff --git a/VolZmap.h b/VolZmap.h index 349a157..d7f3935 100644 --- a/VolZmap.h +++ b/VolZmap.h @@ -160,6 +160,9 @@ class VolZmap : public IVolZmap, public IGeoObjRW typedef std::vector TriaMatrix ; // Tavola hash di Voxel typedef std::unordered_map VoxelContainer ; + // Unordered map per la coerenza topologica + typedef std::unordered_map InterVoxMatter ; + private : bool CopyFrom( const VolZmap& clSrc) ; @@ -307,6 +310,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW bool SetToModifyDexelBlocks( int nGrid, int nDex, int nInt) ; bool GetAdjBlockToBlock( int nBlockN, int nDeltaI, int nDeltaJ, int nDeltaK, int& nAdjBlockN) const ; bool IsAVoxelOnBoundary( const int nLimits[], const int nIJK[], bool bType) const ; + bool IsAVoxelOnBoundary( const int nLimits[], const int nIJK[], int nDeltaIndex[]) const ; bool IsATriangleOnBorder( const Triangle3dEx& trTria, const Point3d& ptVert, const int nBlockLimits[], const int nVoxIJK[]) const ; // Funzioni per facce canoniche con grandi triangoli @@ -369,6 +373,10 @@ class VolZmap : public IVolZmap, public IGeoObjRW mutable std::vector m_InterBlockVox ; mutable TriaMatrix m_InterBlockTria ; + mutable std::vector m_SliceXY ; + mutable std::vector m_SliceXZ ; + mutable std::vector m_SliceYZ ; + Tool m_Tool ; } ; diff --git a/VolZmapCreation.cpp b/VolZmapCreation.cpp index 4d523f6..b2f2b21 100644 --- a/VolZmapCreation.cpp +++ b/VolZmapCreation.cpp @@ -151,9 +151,12 @@ VolZmap::Create( const Point3d& ptO, double dLengthX, double dLengthY, double dL for ( unsigned int nCount = 0 ; nCount < m_nNumBlock ; ++ nCount) m_BlockToUpdate[nCount] = true ; - // Dimensiono raccolta di voxel e triangoli di feature tra blocchi + // Dimensiono raccolta di voxel, triangoli di feature tra blocchi e di segnalatori di materiale fra voxel m_InterBlockVox.resize( m_nNumBlock) ; m_InterBlockTria.resize( m_nNumBlock) ; + m_SliceXY.resize( m_nNumBlock) ; + m_SliceXZ.resize( m_nNumBlock) ; + m_SliceYZ.resize( m_nNumBlock) ; // Aggiornamento dello stato m_nStatus = OK ; @@ -470,9 +473,12 @@ VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double for ( unsigned int nCount = 0 ; nCount < m_nNumBlock ; ++ nCount) m_BlockToUpdate[nCount] = true ; - // Dimensiono raccolta di voxel e triangoli di feature tra blocchi + // Dimensiono raccolta di voxel, triangoli di feature tra blocchi e di segnalatori di materiale fra voxel m_InterBlockVox.resize( m_nNumBlock) ; m_InterBlockTria.resize( m_nNumBlock) ; + m_SliceXY.resize( m_nNumBlock) ; + m_SliceXZ.resize( m_nNumBlock) ; + m_SliceYZ.resize( m_nNumBlock) ; // Aggiornamento dello stato m_nStatus = OK ; @@ -678,9 +684,12 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dPrec, bool bTriDex for ( unsigned int nCount = 0 ; nCount < m_nNumBlock ; ++ nCount) m_BlockToUpdate[nCount] = true ; - // Dimensiono raccolta di voxel e triangoli di feature tra blocchi - m_InterBlockVox.resize( m_nNumBlock) ; + // Dimensiono raccolta di voxel, triangoli di feature tra blocchi e di segnalatori di materiale fra voxel + m_InterBlockVox.resize( m_nNumBlock) ; m_InterBlockTria.resize( m_nNumBlock) ; + m_SliceXY.resize( m_nNumBlock) ; + m_SliceXZ.resize( m_nNumBlock) ; + m_SliceYZ.resize( m_nNumBlock) ; // Aggiornamento dello stato m_nStatus = OK ; diff --git a/VolZmapGraphics.cpp b/VolZmapGraphics.cpp index 3ffdacd..27b4db6 100644 --- a/VolZmapGraphics.cpp +++ b/VolZmapGraphics.cpp @@ -455,6 +455,82 @@ VolZmap::GetTriangles( bool bAllBlocks, INTVECTOR& nModifiedBlocks, TRIA3DEXLIST TriaMatrix VecTriHold ; VecTriHold.resize( m_nNumBlock) ; + // Ciclo sui blocchi per eliminare le slice fra blocchi da aggiornare + for ( size_t t = 0 ; t < m_nNumBlock ; ++ t) { + for ( auto it = m_SliceXY[t].begin() ; it != m_SliceXY[t].end() ;) { + int nSlIJK[3] ; + if ( GetVoxIJKFromN( it->first, nSlIJK[0], nSlIJK[1], nSlIJK[2])) { + int nBlockIJK[3] ; + if ( GetVoxelBlockIJK( nSlIJK, nBlockIJK)) { + int nLimits[6] ; + int nDeltaIndex[3] ; + if ( GetBlockLimitsIJK( nBlockIJK, nLimits) && + IsAVoxelOnBoundary( nLimits, nSlIJK, nDeltaIndex)) { + for ( int nInd = 0 ; nInd < 3 ; ++ nInd) + nSlIJK[nInd] += nDeltaIndex[nInd] ; + int nAdBlockIJK[3] ; + int nAdBlockNum ; + if ( GetVoxelBlockIJK( nSlIJK, nAdBlockIJK) && + GetBlockNFromIJK( nAdBlockIJK, nAdBlockNum) && + m_BlockToUpdate[nAdBlockNum]) { + it = m_SliceXY[t].erase( it) ; + continue ; + } + } + } + } + ++ it ; + } + for ( auto it = m_SliceXZ[t].begin() ; it != m_SliceXZ[t].end() ;) { + int nSlIJK[3] ; + if ( GetVoxIJKFromN( it->first, nSlIJK[0], nSlIJK[1], nSlIJK[2])) { + int nBlockIJK[3] ; + if ( GetVoxelBlockIJK( nSlIJK, nBlockIJK)) { + int nLimits[6] ; + int nDeltaIndex[3] ; + if ( GetBlockLimitsIJK( nBlockIJK, nLimits) && + IsAVoxelOnBoundary( nLimits, nSlIJK, nDeltaIndex)) { + for ( int nInd = 0 ; nInd < 3 ; ++ nInd) + nSlIJK[nInd] += nDeltaIndex[nInd] ; + int nAdBlockIJK[3] ; + int nAdBlockNum ; + if ( GetVoxelBlockIJK( nSlIJK, nAdBlockIJK) && + GetBlockNFromIJK( nAdBlockIJK, nAdBlockNum) && + m_BlockToUpdate[nAdBlockNum]) { + it = m_SliceXZ[t].erase( it) ; + continue ; + } + } + } + } + ++ it ; + } + for ( auto it = m_SliceYZ[t].begin() ; it != m_SliceYZ[t].end() ;) { + int nSlIJK[3] ; + if ( GetVoxIJKFromN( it->first, nSlIJK[0], nSlIJK[1], nSlIJK[2])) { + int nBlockIJK[3] ; + if ( GetVoxelBlockIJK( nSlIJK, nBlockIJK)) { + int nLimits[6] ; + int nDeltaIndex[3] ; + if ( GetBlockLimitsIJK( nBlockIJK, nLimits) && + IsAVoxelOnBoundary( nLimits, nSlIJK, nDeltaIndex)) { + for ( int nInd = 0 ; nInd < 3 ; ++ nInd) + nSlIJK[nInd] += nDeltaIndex[nInd] ; + int nAdBlockIJK[3] ; + int nAdBlockNum ; + if ( GetVoxelBlockIJK( nSlIJK, nAdBlockIJK) && + GetBlockNFromIJK( nAdBlockIJK, nAdBlockNum) && + m_BlockToUpdate[nAdBlockNum]) { + it = m_SliceYZ[t].erase( it) ; + continue ; + } + } + } + } + ++ it ; + } + } + bool bCalcInterBlock = false ; // Calcolo i triangoli sui blocchi @@ -1221,8 +1297,7 @@ VolZmap::ExtMarchingCubes( int nBlock, TRIA3DEXLIST& lstTria, VoxelContainer& vV FlatVoxelContainer VoxContYZInf( nDim) ; FlatVoxelContainer VoxContYZSup( nDim) ; - // Unordered map per la coerenza topologica - typedef std::unordered_map InterVoxMatter ; + // Unordered map per la coerenza topologica nel blocco InterVoxMatter SliceXY( 200) ; InterVoxMatter SliceXZ( 200) ; InterVoxMatter SliceYZ( 200) ; @@ -1383,34 +1458,60 @@ VolZmap::ExtMarchingCubes( int nBlock, TRIA3DEXLIST& lstTria, VoxelContainer& vV int nCount = 0 ; while ( nIndexConfig3[nCount] != nIndex) ++ nCount ; - int nISl = ( nAdjVox3[nCount] != 1 ? i : i + 1) ; - int nJSl = ( nAdjVox3[nCount] != 2 ? j : j + 1) ; - int nKSl = ( nAdjVox3[nCount] != 3 ? k : k + 1) ; - int nNSl ; - if ( GetVoxNFromIJK( nISl, nJSl, nKSl, nNSl)) { + // Vedo se la topologia è definita: se sì uso l'informazione + // passata dall'altro voxel, altrimenti la calcolo + int nIJKSl[3] = { ( nAdjVox3[nCount] != 1 ? i : i + 1), + ( nAdjVox3[nCount] != 2 ? j : j + 1), + ( nAdjVox3[nCount] != 3 ? k : k + 1)} ; + int nSliceN ; + int nSlBlockN ; + if ( GetVoxNFromIJK( nIJKSl[0], nIJKSl[1], nIJKSl[2], nSliceN)) { + int nSlBlockIJK[3] ; + GetVoxelBlockIJK( nIJKSl, nSlBlockIJK) ; if ( abs( nAdjVox3[nCount]) == 1) { - auto it = SliceYZ.find( nNSl) ; + auto it = SliceYZ.find( nSliceN) ; if ( it != SliceYZ.end()) { bNewTopology = it->second ; bDefTopology = true ; - } + } + if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) { + auto it = m_SliceYZ[nSlBlockN].find( nSliceN) ; + if ( it != m_SliceYZ[nSlBlockN].end()) { + bNewTopology = it->second ; + bDefTopology = true ; + } + } } else if ( abs( nAdjVox3[nCount]) == 2) { - auto it = SliceXZ.find( nNSl) ; + auto it = SliceXZ.find( nSliceN) ; if ( it != SliceXZ.end()) { bNewTopology = it->second ; bDefTopology = true ; + } + if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) { + auto it = m_SliceXZ[nSlBlockN].find( nSliceN); + if ( it != m_SliceXZ[nSlBlockN].end()) { + bNewTopology = it->second ; + bDefTopology = true ; + } } } else if ( abs( nAdjVox3[nCount]) == 3) { - auto it = SliceXY.find( nNSl) ; + auto it = SliceXY.find( nSliceN) ; if ( it != SliceXY.end()) { bNewTopology = it->second ; bDefTopology = true ; + } + if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) { + auto it = m_SliceXY[nSlBlockN].find( nSliceN) ; + if ( it != m_SliceXY[nSlBlockN].end()) { + bNewTopology = it->second ; + bDefTopology = true ; + } } } } - + // La topologia è indefinita: calcolo la topologia if ( ! bDefTopology && bReg) { double dDotSum = 0 ; for ( int nFV = 0 ; nFV < 3 ; ++ nFV) { @@ -1427,17 +1528,31 @@ VolZmap::ExtMarchingCubes( int nBlock, TRIA3DEXLIST& lstTria, VoxelContainer& vV for ( int nTVJ = nTVI + 1 ; nTVJ < 3 ; ++ nTVJ) { dDotSum -= CompoVert[1][nTVI].vtVec * CompoVert[1][nTVJ].vtVec ; } - } + } bNewTopology = dDotSum > - EPS_SMALL ; - if ( GetVoxNFromIJK( nISl, nJSl, nKSl, nNSl)) { - if ( abs( nAdjVox3[nCount]) == 1) - SliceYZ.emplace( nNSl, ! bNewTopology) ; - else if ( abs( nAdjVox3[nCount]) == 2) - SliceXZ.emplace( nNSl, ! bNewTopology) ; - else if ( abs( nAdjVox3[nCount]) == 3) - SliceXY.emplace( nNSl, ! bNewTopology) ; + } + // Conservo l'informazione per i voxel successivi + if ( GetVoxNFromIJK( nIJKSl[0], nIJKSl[1], nIJKSl[2], nSliceN)) { + if ( abs(nAdjVox3[nCount]) == 1) { + if ( nSlBlockN == nBlock) + SliceYZ.emplace( nSliceN, ! bNewTopology) ; + else + m_SliceYZ[nSlBlockN].emplace( nSliceN, ! bNewTopology) ; + } + else if ( abs(nAdjVox3[nCount]) == 2) { + if ( nSlBlockN == nBlock) + SliceXZ.emplace( nSliceN, ! bNewTopology) ; + else + m_SliceXZ[nSlBlockN].emplace( nSliceN, ! bNewTopology) ; } + else if (abs(nAdjVox3[nCount]) == 3) { + if ( nSlBlockN == nBlock) + SliceXY.emplace( nSliceN, ! bNewTopology) ; + else + m_SliceXY[nSlBlockN].emplace( nSliceN, ! bNewTopology) ; + } } + // Si passa alla seconda topologia if ( bNewTopology) { // Ricerca del caso corrispondente della nuova topologia @@ -1478,33 +1593,60 @@ VolZmap::ExtMarchingCubes( int nBlock, TRIA3DEXLIST& lstTria, VoxelContainer& vV int nCount = 0 ; while ( nIndexConfig6[nCount] != nIndex) ++ nCount ; - int nISl = ( nAdjVox6[nCount] != 1 ? i : i + 1) ; - int nJSl = ( nAdjVox6[nCount] != 2 ? j : j + 1) ; - int nKSl = ( nAdjVox6[nCount] != 3 ? k : k + 1) ; - int nNSl ; - if ( GetVoxNFromIJK( nISl, nJSl, nKSl, nNSl)) { + // Vedo se la topologia è definita: se sì uso l'informazione già posseduta, + // altrimenti devo calcolare la topologia + int nIJKSl[3] = { ( nAdjVox6[nCount] != 1 ? i : i + 1), + ( nAdjVox6[nCount] != 2 ? j : j + 1), + ( nAdjVox6[nCount] != 3 ? k : k + 1)} ; + int nSliceN ; + int nSlBlockN ; + if ( GetVoxNFromIJK( nIJKSl[0], nIJKSl[1], nIJKSl[2], nSliceN)) { + int nSlBlockIJK[3] ; + GetVoxelBlockIJK( nIJKSl, nSlBlockIJK) ; if ( abs( nAdjVox6[nCount]) == 1) { - auto it = SliceYZ.find( nNSl) ; + auto it = SliceYZ.find( nSliceN) ; if ( it != SliceYZ.end()) { bNewTopology = it->second ; bDefTopology = true ; } + if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) { + auto it = m_SliceYZ[nSlBlockN].find( nSliceN) ; + if ( it != m_SliceYZ[nSlBlockN].end()) { + bNewTopology = it->second ; + bDefTopology = true ; + } + } } else if ( abs( nAdjVox6[nCount]) == 2) { - auto it = SliceXZ.find( nNSl) ; + auto it = SliceXZ.find( nSliceN) ; if ( it != SliceXZ.end()) { bNewTopology = it->second ; bDefTopology = true ; } + if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) { + auto it = m_SliceXZ[nSlBlockN].find( nSliceN) ; + if ( it != m_SliceXZ[nSlBlockN].end()) { + bNewTopology = it->second ; + bDefTopology = true ; + } + } } else if ( abs( nAdjVox6[nCount]) == 3) { - auto it = SliceXY.find( nNSl) ; + auto it = SliceXY.find( nSliceN) ; if ( it != SliceXY.end()) { bNewTopology = it->second ; bDefTopology = true ; } + if ( GetBlockNFromIJK( nSlBlockIJK, nSlBlockN)) { + auto it = m_SliceXY[nSlBlockN].find( nSliceN) ; + if ( it != m_SliceXY[nSlBlockN].end()) { + bNewTopology = it->second ; + bDefTopology = true ; + } + } } - } + } + // Topologia indefinita: la calcolo if ( ! bDefTopology && bReg) { // Test sulla topologia double dDotSum = 0 ; @@ -1524,15 +1666,29 @@ VolZmap::ExtMarchingCubes( int nBlock, TRIA3DEXLIST& lstTria, VoxelContainer& vV } } bNewTopology = dDotSum > - 4 ; - if ( GetVoxNFromIJK( nISl, nJSl, nKSl, nNSl)) { - if ( abs( nAdjVox6[nCount]) == 1) - SliceYZ.emplace( nNSl, ! bNewTopology) ; - else if ( abs( nAdjVox6[nCount]) == 2) - SliceXZ.emplace( nNSl, ! bNewTopology) ; - else if ( abs( nAdjVox6[nCount]) == 3) - SliceXY.emplace( nNSl, ! bNewTopology) ; + } + // Conservo l'informazione + if ( GetVoxNFromIJK( nIJKSl[0], nIJKSl[1], nIJKSl[2], nSliceN)) { + if ( abs(nAdjVox6[nCount]) == 1) { + if ( nSlBlockN == nBlock) + SliceYZ.emplace( nSliceN, ! bNewTopology) ; + else + m_SliceYZ[nSlBlockN].emplace( nSliceN, ! bNewTopology) ; + } + else if ( abs(nAdjVox6[nCount]) == 2) { + if ( nSlBlockN == nBlock) + SliceXZ.emplace( nSliceN, ! bNewTopology) ; + else + m_SliceXZ[nSlBlockN].emplace( nSliceN, ! bNewTopology) ; } + else if (abs(nAdjVox6[nCount]) == 3) { + if ( nSlBlockN == nBlock) + SliceXY.emplace( nSliceN, ! bNewTopology) ; + else + m_SliceXY[nSlBlockN].emplace( nSliceN, ! bNewTopology) ; + } } + // Si deve passare alla seconda topologia if ( bNewTopology) { // Ricerca del caso corrispondente della nuova topologia @@ -1540,53 +1696,7 @@ VolZmap::ExtMarchingCubes( int nBlock, TRIA3DEXLIST& lstTria, VoxelContainer& vV while ( nIndexVsIndex6[nt][0] != nIndex) ++ nt ; int nRotCase = nIndexVsIndex6[nt][1] ; - - //// Costruzione dei triangoli - //for ( int TriIndex = 0 ; TriIndex < 15 ; TriIndex += 3) { - // // Indici vertici - // int i0 = Cases6Plus[nRotCase][TriIndex + 2] ; - // int i1 = Cases6Plus[nRotCase][TriIndex + 1] ; - // int i2 = Cases6Plus[nRotCase][TriIndex] ; - // // Costruzione triangolo - // Triangle3dEx CurrentTriangle ; - // CurrentTriangle.Set( VecField[i0].ptPApp, VecField[i1].ptPApp, VecField[i2].ptPApp) ; - // CurrentTriangle.Validate( true) ; - // CurrentTriangle.SetVertexNorm( 0, VecField[i0].vtVec) ; - // CurrentTriangle.SetVertexNorm( 1, VecField[i1].vtVec) ; - // CurrentTriangle.SetVertexNorm( 2, VecField[i2].vtVec) ; - // // Setto il numero di utensile (conta solo positivo, nullo o negativo) - // int nTool0 = Clamp( VecField[i0].nPropIndex, -1, 1) ; - // int nTool1 = Clamp( VecField[i1].nPropIndex, -1, 1) ; - // int nTool2 = Clamp( VecField[i2].nPropIndex, -1, 1) ; - // if ( nTool0 == nTool1 || nTool0 == nTool2) - // CurrentTriangle.SetGrade( nTool0) ; - // else if ( nTool1 == nTool2) - // CurrentTriangle.SetGrade( nTool1) ; - // // Valido il triangolo e setto le normali del campo vettoriale ai corrispondenti vertici - // if ( CurrentTriangle.Validate( true)) { - // Vector3d vtVertNorm = VecField[i0].vtVec ; - // if ( CurrentTriangle.GetN() * vtVertNorm > 0.6) - // CurrentTriangle.SetVertexNorm( 0, vtVertNorm) ; - // else - // CurrentTriangle.SetVertexNorm( 0, CurrentTriangle.GetN()) ; - // vtVertNorm = VecField[i1].vtVec ; - // if ( CurrentTriangle.GetN() * vtVertNorm > 0.6) - // CurrentTriangle.SetVertexNorm( 1, vtVertNorm) ; - // else - // CurrentTriangle.SetVertexNorm( 1, CurrentTriangle.GetN()) ; - // vtVertNorm = VecField[i2].vtVec ; - // if ( CurrentTriangle.GetN() * vtVertNorm > 0.6) - // CurrentTriangle.SetVertexNorm( 2, vtVertNorm) ; - // else - // CurrentTriangle.SetVertexNorm( 2, CurrentTriangle.GetN()) ; - // } - // // Riporto il triangolo nel sistema in cui è immerso quello dello Zmap - // CurrentTriangle.ToGlob( m_MapFrame) ; - // // Aggiungo alla lista - // lstTria.emplace_back( CurrentTriangle) ; - //} - //continue ; - + // Aggiorno numero di componenti nComponents = Cases6Plus[nRotCase][1][0] ; // Riaggiorno gli offsets @@ -1615,65 +1725,93 @@ VolZmap::ExtMarchingCubes( int nBlock, TRIA3DEXLIST& lstTria, VoxelContainer& vV // Configurazione 10 else if ( nAllConfig[nIndex] == 10) { // Test sulla topologia - bool bDefTopology = false ; + bool bDefStTopology = false ; bool bNewTopology = false ; int nCount = 0 ; while ( nIndexConfig10[nCount] != nIndex) ++ nCount ; - int nISlSt = i ; - int nJSlSt = j ; - int nKSlSt = k ; - int nISlEn = ( nAdjVox10[nCount] != 1 ? i : i + 1) ; - int nJSlEn = ( nAdjVox10[nCount] != 2 ? j : j + 1) ; - int nKSlEn = ( nAdjVox10[nCount] != 3 ? k : k + 1) ; - int nNSlSt, nNSlEn ; - if ( GetVoxNFromIJK( nISlSt, nJSlSt, nKSlSt, nNSlSt) && - GetVoxNFromIJK( nISlEn, nJSlEn, nKSlEn, nNSlEn)) { + // Vedo se la topologia è definita: se sì uso l'informazione già posseduta, + // altrimenti devo calcolare la topologia + int nIJKSlSt[3] = { i, j, k} ; + int nIJKSlEn[3] = { ( nAdjVox10[nCount] != 1 ? i : i + 1), + ( nAdjVox10[nCount] != 2 ? j : j + 1), + ( nAdjVox10[nCount] != 3 ? k : k + 1)} ; + int nSliceStN, nSliceEnN ; + int nSlBlockEnN ; + if ( GetVoxNFromIJK( nIJKSlSt[0], nIJKSlSt[1], nIJKSlSt[2], nSliceStN) && + GetVoxNFromIJK( nIJKSlEn[0], nIJKSlEn[1], nIJKSlEn[2], nSliceEnN)) { if ( abs( nAdjVox10[nCount]) == 1) { - auto itSt = SliceYZ.find( nNSlSt) ; + auto itSt = SliceYZ.find( nSliceStN) ; if ( itSt != SliceYZ.end()) { bNewTopology = itSt->second ; - bDefTopology = true ; - } + bDefStTopology = true ; + } } else if ( abs( nAdjVox10[nCount]) == 2) { - auto itSt = SliceXZ.find( nNSlSt) ; + auto itSt = SliceXZ.find( nSliceStN) ; if ( itSt != SliceXZ.end()) { bNewTopology = itSt->second ; - bDefTopology = true ; - } + bDefStTopology = true ; + } } else if ( abs( nAdjVox10[nCount]) == 3) { - auto itSt = SliceXY.find( nNSlSt) ; + auto itSt = SliceXY.find( nSliceStN) ; if ( itSt != SliceXY.end()) { bNewTopology = itSt->second ; - bDefTopology = true ; - } + bDefStTopology = true ; + } } - } - if ( ! bDefTopology && bReg) { + } + // La topologia non è definita, la calcolo + if ( ! bDefStTopology && bReg) { // Verifico concordanza tra i versori di una stessa componente // (ogni coppia di vettori di una medesima componente deve avere prodotto scalare non inferiore a 0.0) Vector3d vtCmpAvg0, vtCmpAvg1 ; bool bTest0 = DotTest( CompoVert[0], 4, vtCmpAvg0, 0.0) ; bool bTest1 = DotTest( CompoVert[1], 4, vtCmpAvg1, 0.0) ; bNewTopology = ( ! bTest0 || ! bTest1) ; - if ( GetVoxNFromIJK( nISlSt, nJSlSt, nKSlSt, nNSlSt) && - GetVoxNFromIJK( nISlEn, nJSlEn, nKSlEn, nNSlEn)) { - if ( abs( nAdjVox6[nCount]) == 1) { - SliceYZ.emplace( nNSlSt, bNewTopology) ; - SliceYZ.emplace( nNSlEn, bNewTopology) ; - } - else if ( abs( nAdjVox6[nCount]) == 2) { - SliceXZ.emplace( nNSlSt, bNewTopology) ; - SliceXZ.emplace( nNSlEn, bNewTopology) ; - } - else if ( abs( nAdjVox6[nCount]) == 3) { - SliceXY.emplace( nNSlSt, bNewTopology) ; - SliceXY.emplace( nNSlEn, bNewTopology) ; - } - } + } + // Conservo l'informazioe e la trasmetto al voxel successivo + if ( GetVoxNFromIJK( nIJKSlSt[0], nIJKSlSt[1], nIJKSlSt[2], nSliceStN) && + GetVoxNFromIJK( nIJKSlEn[0], nIJKSlEn[1], nIJKSlEn[2], nSliceEnN)) { + if ( abs( nAdjVox6[nCount]) == 1) { + if ( GetBlockNFromIJK( nIJKSlEn, nSlBlockEnN)) { + auto it = m_SliceYZ[nSlBlockEnN].find( nSliceEnN) ; + if ( it != m_SliceYZ[nSlBlockEnN].end()) { + if ( it->second != bNewTopology) + m_BlockToUpdate[nSlBlockEnN] = true ; + it->second = bNewTopology ; + } + else + m_SliceYZ[nSlBlockEnN].emplace( nSliceEnN, bNewTopology) ; + } + } + else if ( abs( nAdjVox6[nCount]) == 2) { + if ( GetBlockNFromIJK( nIJKSlEn, nSlBlockEnN)) { + auto it = m_SliceXZ[nSlBlockEnN].find( nSliceEnN) ; + if ( it != m_SliceXZ[nSlBlockEnN].end()) { + if ( it->second != bNewTopology) + m_BlockToUpdate[nSlBlockEnN] = true ; + it->second = bNewTopology ; + } + else + m_SliceXZ[nSlBlockEnN].emplace( nSliceEnN, bNewTopology) ; + } + } + else if ( abs( nAdjVox6[nCount]) == 3) { + if ( GetBlockNFromIJK( nIJKSlEn, nSlBlockEnN)) { + auto it = m_SliceXY[nSlBlockEnN].find( nSliceEnN) ; + if ( it != m_SliceXY[nSlBlockEnN].end()) { + if ( it->second != bNewTopology) + m_BlockToUpdate[nSlBlockEnN] = true ; + it->second = bNewTopology ; + } + else + m_SliceXY[nSlBlockEnN].emplace( nSliceEnN, bNewTopology) ; + } + } } + // Si passa alla seconda topologia if ( bNewTopology) { // Ricerca del caso corrispondente della nuova topologia @@ -1690,7 +1828,7 @@ VolZmap::ExtMarchingCubes( int nBlock, TRIA3DEXLIST& lstTria, VoxelContainer& vV nVertComp[nC - 1] = Cases10Plus[nRotCase][1][nC] ; // Matrice dei vertici della base del fan for ( int nFanVert = 0 ; nFanVert < 4 ; ++ nFanVert) - CompoVert[nC - 1][nFanVert] = VecField[Cases10Plus[nRotCase][1][nFanVert + nExtTabOff + 1]] ; + CompoVert[nC - 1][nFanVert] = VecField[Cases10Plus[nRotCase][1][nFanVert + nExtTabOff + 1]] ; // Matrici dei vertici dei triangoli in assenza di sharp feature for ( int nTriVert = 0 ; nTriVert < 6 ; nTriVert += 3) { CompoTriVert[nC - 1][nTriVert] = VecField[Cases10Plus[nRotCase][0][nStdTabOff + nTriVert+2]] ; @@ -3322,6 +3460,45 @@ VolZmap::IsAVoxelOnBoundary( const int nLimits[], const int nIJK[], bool bType) return false ; } +//---------------------------------------------------------------------------- +bool +VolZmap::IsAVoxelOnBoundary( const int nLimits[], const int nIJK[], int nDeltaIndex[]) const +{ + // Calcolo il numero di voxel lungo X,Y e Z + int nVoxNumX = int( m_nNx[0] / N_DEXVOXRATIO + ( m_nNx[0] % N_DEXVOXRATIO == 0 ? 1 : 2)) ; + int nVoxNumY = int( m_nNy[0] / N_DEXVOXRATIO + ( m_nNy[0] % N_DEXVOXRATIO == 0 ? 1 : 2)) ; + int nVoxNumZ = int( m_nNy[1] / N_DEXVOXRATIO + ( m_nNy[1] % N_DEXVOXRATIO == 0 ? 1 : 2)) ; + // Test sulla validità dei limiti + if ( nLimits[0] < - 1 || nLimits[0] > nVoxNumX - 1 || + nLimits[1] < - 1 || nLimits[1] > nVoxNumX - 1 || + nLimits[2] < - 1 || nLimits[2] > nVoxNumY - 1 || + nLimits[3] < - 1 || nLimits[3] > nVoxNumY - 1 || + nLimits[4] < - 1 || nLimits[4] > nVoxNumZ - 1 || + nLimits[5] < - 1 || nLimits[5] > nVoxNumZ - 1 ) + return false ; + // Controllo sull'ammissibilità del voxel + if ( nIJK[0] <= -2 || nIJK[0] > nVoxNumX - 2 || + nIJK[1] <= -2 || nIJK[1] > nVoxNumY - 2 || + nIJK[2] <= -2 || nIJK[2] > nVoxNumZ - 2) + return false ; + nDeltaIndex[0] = 0 ; + nDeltaIndex[1] = 0 ; + nDeltaIndex[2] = 0 ; + if ( nIJK[0] == nLimits[0]) + -- nDeltaIndex[0] ; + else if ( nIJK[0] == nLimits[1] - 1) + ++ nDeltaIndex[0] ; + if ( nIJK[0] == nLimits[0]) + -- nDeltaIndex[1]; + else if ( nIJK[0] == nLimits[1] - 1) + ++ nDeltaIndex[1]; + if ( nIJK[0] == nLimits[0]) + -- nDeltaIndex[2]; + else if ( nIJK[0] == nLimits[1] - 1) + ++ nDeltaIndex[2]; + return ( nDeltaIndex[0] != 0 || nDeltaIndex[1] != 0 || nDeltaIndex[2] != 0) ; +} + //---------------------------------------------------------------------------- bool VolZmap::IsATriangleOnBorder( const Triangle3dEx& trTria, const Point3d& ptVert,