diff --git a/VolZmap.cpp b/VolZmap.cpp index 46d37d0..6f1a4f4 100644 --- a/VolZmap.cpp +++ b/VolZmap.cpp @@ -29,6 +29,15 @@ #include #include +#define DEBUG_REMOVE_FINS 0 +#if DEBUG_REMOVE_FINS + #include "/EgtDev/Include/EGkGeoObjSave.h" + #include "/EgtDev/Include/EGkGeoPoint3d.h" + #include "/EgtDev/Include/EGkGeoVector3d.h" + std::vector VT ; + std::vector VC ; +#endif + using namespace std ; //---------------------------------------------------------------------------- @@ -1889,19 +1898,28 @@ VolZmap::RemoveFins( const Vector3d& vtDir, double dThick) m_dStep, IsTriDexel())) return false ; - const double FIN_ANG_DEG_TOL = 55. ; // approssimazione per eccesso dell'angolo massimo possibile tra una direzione generica + const double FIN_ANG_DEG_TOL = 55. ; // Approssimazione per eccesso dell'angolo massimo possibile tra una direzione generica // e un versore della terna globale ( arccos( 1 / sqrt( 3) ~ 54.375) const double COS_FIN_ANG_DEG_TOL = cos( FIN_ANG_DEG_TOL * DEGTORAD) ; + const int NUM_TOOL = 1000 ; // Identificativo Utensile per riconoscere le parti rimosse // NB. Tutti i parametri sono sempre presi dalla Copia dello ZMap corrente // Ciclo sulle griglie + DBLVECTOR vdThicks ; + if ( IsTriDexel()) + vdThicks = { dThick, dThick, dThick} ; + else + vdThicks = { dThick} ; for ( int nGrid = 0 ; nGrid < pZMapCopy->m_nMapNum ; ++ nGrid) { - // Verifico se l'angolo tra la direzione degli spilloni della griglia corrente è sotto alla tolleranza riseptto alla direzione - double dCosDir = ( nGrid == 0 ? vtMyDir.z : ( nGrid == 1 ? vtMyDir.x : vtMyDir.y)) ; + // Verifico se l'angolo tra la direzione degli spilloni della griglia corrente è sotto alla tolleranza rispetto alla direzione + double dCosDir = ( nGrid == 0 ? vtMyDir.z : + ( nGrid == 1 ? vtMyDir.x : + vtMyDir.y)) ; if ( abs( dCosDir) < COS_FIN_ANG_DEG_TOL + EPS_ANG_SMALL) continue ; // Aggiorno l'effettivo valore dello spessore da considerare - double dCurrThick = dMyThick / abs( dCosDir) ; // sicuramente esiste, essendo 55deg il limite + double dCurrThick = dMyThick / abs( dCosDir) ; // (sicuramente esiste, essendo 55deg il limite) + vdThicks[nGrid] = dCurrThick ; // Ciclo sul numero di dexel presenti nella Copia for ( int nDex = 0 ; nDex < ssize( pZMapCopy->m_Values[nGrid]) ; ++ nDex) { // Se il dexel corrente non ha sotto-intervalli passo al successivo @@ -1921,26 +1939,27 @@ VolZmap::RemoveFins( const Vector3d& vtDir, double dThick) ( Interval.dMax > m_dMaxZ[nGrid] - EPS_SMALL || Interval.dMin < m_dMinZ[nGrid] + EPS_SMALL)) ; if ( ! bAnalyze) continue ; - // if ( Interval.nToolMin != 1 || Interval.nToolMax != 1) - // continue ; - // Se la lunghezza dell'intervallo è supriore allo spessore richiesto, non faccio nulla + // Se la lunghezza dell'intervallo è superiore allo spessore richiesto, non faccio nulla double dLen = Interval.dMax - Interval.dMin ; - if ( dLen > dCurrThick - EPS_SMALL) + if ( dLen > dCurrThick + EPS_ZERO) continue ; // Se ZMap composto da una sola griglia, elimino il contributo lungo la direzione corrente if ( ! IsTriDexel()) { SubtractIntervals( nGrid, nI, nJ, Interval.dMin - EPS_SMALL, Interval.dMax + EPS_SMALL, - Interval.vtMinN, Interval.vtMaxN, 1, true) ; + - Interval.vtMinN, - Interval.vtMaxN, NUM_TOOL, true) ; } // Se Tridexel, aggiungo il contributo del cubetto corrente allo ZMap Extra else - ZMapExtra.AddStripInterval( nGrid, nI, nJ, Interval.dMin - EPS_SMALL, Interval.dMax + EPS_SMALL) ; + ZMapExtra.AddStripInterval( nGrid, nI, nJ, Interval.dMin - EPS_SMALL, Interval.dMax + EPS_SMALL, NUM_TOOL) ; } } } // Se non ho aggiunto alcun elemento allo ZMap Extra, non devo fare nulla if ( ! ZMapExtra.IsValid()) return true ; + #if DEBUG_REMOVE_FINS + SaveGeoObj( ZMapExtra.Clone(), "C:\\Temp\\VolZMapSubt0.nge") ; + #endif // Ciclo sulle griglie dello ZMap Extra for ( int nGrid = 0 ; nGrid < ZMapExtra.m_nMapNum ; ++ nGrid) { @@ -1957,9 +1976,79 @@ VolZmap::RemoveFins( const Vector3d& vtDir, double dThick) double dMin = ZMapExtra.m_Values[nGrid][nDex][nInfo].dMin ; double dMax = ZMapExtra.m_Values[nGrid][nDex][nInfo].dMax ; Vector3d vtNMin = ZMapExtra.m_Values[nGrid][nDex][nInfo].vtMinN ; - Vector3d vtNMax = ZMapExtra.m_Values[nGrid][nDex][nInfo].vtMaxN ; + Vector3d vtNMax = ZMapExtra.m_Values[nGrid][nDex][nInfo].vtMaxN ; // sottraggo tali contributi - SubtractIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, 1, true) ; + SubtractIntervals( nGrid, nI, nJ, dMin, dMax, - vtNMin, - vtNMax, NUM_TOOL, true) ; + } + } + } + if ( ! IsValid()) + return true ; + #if DEBUG_REMOVE_FINS + SaveGeoObj( this->Clone(), "C:\\Temp\\VolZMapSubt1.nge") ; + #endif + + // Sistemo le Normali sullo ZMap ricavato + for ( int nGrid = 0 ; nGrid < m_nMapNum ; ++ nGrid) { + // Ciclo sul numero di dexel presenti + for ( int nDex = 0 ; nDex < ssize( m_Values[nGrid]) ; ++ nDex) { + // Se l'Intervallo è vuoto non faccio nulla + if ( m_Values[nGrid][nDex].empty()) + continue ; + // Indici del dexel + int nI = nDex % m_nNx[nGrid] ; + int nJ = nDex / m_nNx[nGrid] ; + // Scorro gli intervalli dello spillone corrente + for ( int nInfo = 0 ; nInfo < ssize( m_Values[nGrid][nDex]) ; ++ nInfo) { + // Se intervallo con estremo minimo derivante dalla sottrazione con ZMapExtra, medio le normali + int nToolMin = m_Values[nGrid][nDex][nInfo].nToolMin ; + if ( nToolMin == NUM_TOOL) { + // Recupero il valore minimo, se sul bordo dello ZMap corrente non faccio nulla + double dMin = m_Values[nGrid][nDex][nInfo].dMin ; + if ( dMin > m_dMinZ[nGrid] + EPS_SMALL) { + Vector3d vtMinN = V_NULL ; + double dZMin = INFINITO ; + if ( ! pZMapCopy->ComputePointAndNormalForRemovingFins( nGrid, nI, nJ, dMin, vtMyDir, dThick, true, 1, vtMinN, dZMin)) { + vtMinN = - ( nGrid == 0 ? m_MapFrame.VersZ() : nGrid == 1 ? m_MapFrame.VersX() : m_MapFrame.VersY()) ; + dZMin = dMin ; + } + m_Values[nGrid][nDex][nInfo].vtMinN = vtMinN ; + m_Values[nGrid][nDex][nInfo].dMin = dZMin ; + } + } + // Se intervallo con estremo massimo derivante dalla sottrazione con ZMapExtra, medio le normali + int nToolMax = m_Values[nGrid][nDex][nInfo].nToolMax ; + if ( nToolMax == NUM_TOOL) { + // Recupero il valore massimo, se sul bordo dello ZMap corrente non faccio nulla + double dMax = m_Values[nGrid][nDex][nInfo].dMax ; + if ( dMax < m_dMaxZ[nGrid] - EPS_SMALL) { + Vector3d vtMaxN = V_NULL ; + double dZMax = INFINITO ; + if ( ! pZMapCopy->ComputePointAndNormalForRemovingFins( nGrid, nI, nJ, dMax, vtMyDir, dThick, false, 1, vtMaxN, dZMax)) { + vtMaxN = ( nGrid == 0 ? m_MapFrame.VersZ() : nGrid == 1 ? m_MapFrame.VersX() : m_MapFrame.VersY()) ; + dZMax = dMax ; + } + m_Values[nGrid][nDex][nInfo].vtMaxN = vtMaxN ; + m_Values[nGrid][nDex][nInfo].dMax = dZMax ; + } + } + } + } + } + + // Riassegno il Tool dell'utensile alle nuove parti + for ( int nGrid = 0 ; nGrid < m_nMapNum ; ++ nGrid) { + // Ciclo sul numero di dexel presenti + for ( int nDex = 0 ; nDex < ssize( m_Values[nGrid]) ; ++ nDex) { + // Se l'Intervallo è vuoto non faccio nulla + if ( m_Values[nGrid][nDex].empty()) + continue ; + // Scorro gli intervalli dello spillone corrente + for ( int nInfo = 0 ; nInfo < ssize( m_Values[nGrid][nDex]) ; ++ nInfo) { + if ( m_Values[nGrid][nDex][nInfo].nToolMin == NUM_TOOL) + m_Values[nGrid][nDex][nInfo].nToolMin = 1 ; + if ( m_Values[nGrid][nDex][nInfo].nToolMax == NUM_TOOL) + m_Values[nGrid][nDex][nInfo].nToolMax = 1 ; } } } diff --git a/VolZmap.h b/VolZmap.h index 81dbf3e..2f6e098 100644 --- a/VolZmap.h +++ b/VolZmap.h @@ -263,7 +263,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW bool UniformIntervalsInVoxel( int nGrid, int nI, int nJ, double dZMin, double dZMax, double dToler, bool bAdd, int nToolNum, const Vector3d& vtToolMin, const Vector3d& vtToolMax) ; - bool AddStripInterval( int nGrid, int nI, int nJ, double dZMin, double dZMax) ; + bool AddStripInterval( int nGrid, int nI, int nJ, double dZMin, double dZMax, int nToolNum) ; bool ManageSubIntervalInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, int nK, double& dMin, double& dMax, Vector3d& vtMin, Vector3d& vtMax) ; // Spostamenti utensile @@ -488,6 +488,11 @@ class VolZmap : public IVolZmap, public IGeoObjRW // Funzioni per Offset di Zmap bool OffsetFillet( double dOffs) ; bool OffsetSharped( double dOffs, int nType) ; + // Funzione analisi punti/Normali + bool GetLocalPoint( int nGrid, int nI, int nJ, double dZ, Point3d& ptLoc) ; + bool ComputePointAndNormalForRemovingFins( int nGrid, int nI, int nJ, double dZ, + const Vector3d& vtDir, double dThick, bool bMinVsMax, int nTool, + Vector3d& vtN, double& dNewZ) ; private : enum Move5Axis { diff --git a/VolZmapVolume.cpp b/VolZmapVolume.cpp index ed4cc26..5afd9cb 100644 --- a/VolZmapVolume.cpp +++ b/VolZmapVolume.cpp @@ -847,7 +847,7 @@ VolZmap::UniformIntervalsInVoxel( int nGrid, int nI, int nJ, double dZMin, //---------------------------------------------------------------------------- bool -VolZmap::AddStripInterval( int nGrid, int nI, int nJ, double dZMin, double dZMax) +VolZmap::AddStripInterval( int nGrid, int nI, int nJ, double dZMin, double dZMax, int nToolNum) { // Se non Tridex, esco if ( ! IsTriDexel()) @@ -880,7 +880,7 @@ VolZmap::AddStripInterval( int nGrid, int nI, int nJ, double dZMin, double dZMax nMyGrid == 1 ? m_MapFrame.VersX() : m_MapFrame.VersY()) ; Vector3d vtMyMinN = - vtMyMaxN ; - AddIntervals( nMyGrid, nMyI, nMyJ, dMyMinZ - EPS_SMALL, dMyMaxZ + EPS_SMALL, vtMyMinN, vtMyMaxN, 2, true) ; + AddIntervals( nMyGrid, nMyI, nMyJ, dMyMinZ - EPS_SMALL, dMyMaxZ + EPS_SMALL, vtMyMinN, vtMyMaxN, nToolNum, true) ; // Recupero gli indici della griglia precedente nMyGrid = ( nGrid + 2) % 3 ; nMyI = nVox ; @@ -892,7 +892,7 @@ VolZmap::AddStripInterval( int nGrid, int nI, int nJ, double dZMin, double dZMax nMyGrid == 1 ? m_MapFrame.VersX() : m_MapFrame.VersY()) ; vtMyMinN = - vtMyMaxN ; - AddIntervals( nMyGrid, nMyI, nMyJ, dMyMinZ, dMyMaxZ, vtMyMinN, vtMyMaxN, 2, true) ; + AddIntervals( nMyGrid, nMyI, nMyJ, dMyMinZ - EPS_SMALL, dMyMaxZ + EPS_SMALL, vtMyMinN, vtMyMaxN, nToolNum, true) ; } } // Aggiungo l'intervallo corrente @@ -900,11 +900,127 @@ VolZmap::AddStripInterval( int nGrid, int nI, int nJ, double dZMin, double dZMax nGrid == 1 ? m_MapFrame.VersX() : m_MapFrame.VersY()) ; Vector3d vtMyMinN = - vtMyMaxN ; - AddIntervals( nGrid, nI, nJ, dZMin, dZMax, vtMyMaxN, vtMyMinN, 2, true) ; + AddIntervals( nGrid, nI, nJ, dZMin, dZMax, vtMyMinN, vtMyMaxN, nToolNum, true) ; return true ; } +//---------------------------------------------------------------------------- +bool +VolZmap::GetLocalPoint( int nGrid, int nI, int nJ, double dZ, Point3d& ptLoc) +{ + // Verifico che lo ZMap corrente sia valido + if ( ! IsValid()) + return false ; + + // 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 ; + + // Calcolo il punto + ptLoc = m_MapFrame.Orig() ; + if ( nGrid == 0) + ptLoc += ( ( nI + 0.5) * m_dStep * m_MapFrame.VersX() + ( nJ + 0.5) * m_dStep * m_MapFrame.VersY() + dZ * m_MapFrame.VersZ()) ; + else if ( nGrid == 1) + ptLoc += ( ( nI + 0.5) * m_dStep * m_MapFrame.VersY() + ( nJ + 0.5) * m_dStep * m_MapFrame.VersZ() + dZ * m_MapFrame.VersX()) ; + else + ptLoc += ( ( nI + 0.5) * m_dStep * m_MapFrame.VersZ() + ( nJ + 0.5) * m_dStep * m_MapFrame.VersX() + dZ * m_MapFrame.VersY()) ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +VolZmap::ComputePointAndNormalForRemovingFins( int nGrid, int nI, int nJ, double dZ, + const Vector3d& vtDir, double dThick, bool bMinVsMax, int nTool, + Vector3d& vtN, double& dNewZ) +{ + // Verifico che lo ZMap corrente sia valido + if ( ! IsValid()) + return false ; + + // Controllo che il numero di griglia sia entro i limiti + if ( nGrid < 0 || nGrid > 2) + return false ; + + // Inizializzo il vettore da restituire + vtN = V_NULL ; + dNewZ = INFINITO ; + + // Proietto la direzione lungo la mappa della griglia corrente + Vector3d vtDirProj = OrthoCompo( vtDir, ( nGrid == 0 ? m_MapFrame.VersZ() : + nGrid == 1 ? m_MapFrame.VersX() : + m_MapFrame.VersY())) ; + // Sposto il punto corrente nella direzione opposta a quella trovata + Point3d ptLoc ; + if ( ! GetLocalPoint( nGrid, nI, nJ, dZ, ptLoc)) + return false ; + Point3d ptCenterLoc = ptLoc ; + ptCenterLoc.Translate( - vtDirProj * dThick) ; + + // Recupero il Box nel punto + BBox3d BBoxLoc ; BBoxLoc.Add( ptCenterLoc) ; + double dExpandX = ( m_MapFrame.VersX() * X_AX) * dThick * ( vtDirProj * X_AX) ; + double dExpandY = ( m_MapFrame.VersY() * Y_AX) * dThick * ( vtDirProj * Y_AX) ; + double dExpandZ = ( m_MapFrame.VersZ() * Z_AX) * dThick * ( vtDirProj * Z_AX) ; + BBoxLoc.Expand( max( ( m_dStep + EPS_SMALL), dExpandX), + max( ( m_dStep + EPS_SMALL), dExpandY), + max( ( m_dStep + EPS_SMALL), dExpandZ)) ; + + // Porto il Box nel Frame della Mappa corrente + BBox3d BBoxInGrid = GetToLoc( BBoxLoc, m_MapFrame) ; + // Recupero i suoi estremi + Point3d ptBoxLocMax = BBoxInGrid.GetMax() ; + Point3d ptBoxLocMin = BBoxInGrid.GetMin() ; + // Determino gli intervalli locali in X e Y locali alla Griglia correnti + double dMinXLoc = ( nGrid == 0 ? ptBoxLocMin.x : nGrid == 1 ? ptBoxLocMin.y : ptBoxLocMin.z) ; + double dMinYLoc = ( nGrid == 0 ? ptBoxLocMin.y : nGrid == 1 ? ptBoxLocMin.z : ptBoxLocMin.x) ; + double dMaxXLoc = ( nGrid == 0 ? ptBoxLocMax.x : nGrid == 1 ? ptBoxLocMax.y : ptBoxLocMax.z) ; + double dMaxYLoc = ( nGrid == 0 ? ptBoxLocMax.y : nGrid == 1 ? ptBoxLocMax.z : ptBoxLocMax.x) ; + + // Recupero gli Spilloni coinvolti nel Box + int nStartI = max( 0, int( dMinXLoc / m_dStep)) ; + int nEndI = min( m_nNx[nGrid] - 1, int( dMaxXLoc / m_dStep)) ; + int nStartJ = max( 0, int( dMinYLoc / m_dStep)) ; + int nEndJ = min( m_nNy[nGrid] - 1, int( dMaxYLoc / m_dStep)) ; + double dSqMinDist = INFINITO ; + for ( int i = nStartI ; i <= nEndI ; ++ i) { + for ( int j = nStartJ ; j <= nEndJ ; ++ j) { + // Determino la posizione corrente dello Spillone + int nPos = j * m_nNx[nGrid] + i ; + vector& vDexel = m_Values[nGrid][nPos] ; + // Scorro i suoi Intervalli + for ( int nInterval = 0 ; nInterval < ssize( vDexel) ; ++ nInterval) { + // Se l'Intervallo presenta un indice del Tool da evitare, passo al successivo + if ( ( bMinVsMax && vDexel[nInterval].nToolMin != nTool) || + ( ! bMinVsMax && vDexel[nInterval].nToolMax != nTool)) + continue ; + // Recupero l'estremo da analizzare + double dZInterval = ( bMinVsMax ? vDexel[nInterval].dMin : vDexel[nInterval].dMax) ; + // Recupero il punto associato + Point3d ptInterval ; + if ( ! GetLocalPoint( nGrid, i, j, dZInterval, ptInterval)) + return false ; + // Se il punto è dentro nel Box, aggiungo il contributo della normale presente + if ( BBoxLoc.Encloses( ptInterval)) { + double dCurrSqDist = ( SqDist( ptInterval, ptLoc)) ; + if ( dCurrSqDist < dSqMinDist) { + dSqMinDist = dCurrSqDist ; + vtN = ( bMinVsMax ? vDexel[nInterval].vtMinN : vDexel[nInterval].vtMaxN) ; + dNewZ = dZInterval ; + } + } + } + } + } + + return ( ! vtN.IsSmall() && dZ < INFINITO - 1) ; +} + // ------------------------- BOUNDING BOX --------------------------------------------------------------------------------------