From b2b3e4a2da7726e219617e309ee2b5d32cbab015 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 5 Aug 2026 17:17:16 +0200 Subject: [PATCH] EgtGeomKernel : - migliorie e correzioni a ZMap da una trimesh con crack. --- VolZmapCreation.cpp | 198 ++++++++++++++++++++++++++++++++------------ 1 file changed, 147 insertions(+), 51 deletions(-) diff --git a/VolZmapCreation.cpp b/VolZmapCreation.cpp index 0b10444..46193e7 100644 --- a/VolZmapCreation.cpp +++ b/VolZmapCreation.cpp @@ -22,6 +22,7 @@ #include "/EgtDev/Include/EGkIntersLinePlane.h" #include "/EgtDev/Include/EgtNumUtils.h" #include +#include using namespace std ; @@ -1093,6 +1094,7 @@ VolZmap::AdjustDexelThroughCracks( int nG, const Vector3d& vtLen, const INTTOCHE { double dAngSameFace = 45 ; double dCosSmall = sin( EPS_ANG_SMALL * DEGTORAD) ; + double dMaxDistTol = 3 * m_dStep ; // per ogni intersezione segnalata devo cercare sugli spilloni vicini l'intervallo con l'estremo più vicino a questa intersezione // e usare l'altro estremo, insieme a quello degli altri spilloni vicini, per estrapolare quello mancante sullo spillone corrente Vector3d vtAx ; @@ -1183,10 +1185,9 @@ VolZmap::AdjustDexelThroughCracks( int nG, const Vector3d& vtLen, const INTTOCHE if ( bAddNearest && isfinite( dNearestPos)) { // controllo anche che i punti non siano troppo lontani tra loro, altrimenti // il piano calcolato potrebbe essere una media troppo grezza - double dMaxDist = 3 * m_dStep ; const bool bTooFar = any_of( vNeighInters.begin(), vNeighInters.end(), - [dNearestPos, dMaxDist](const Point3d& pt) { - return abs( pt.z - dNearestPos) > dMaxDist ; + [dNearestPos, dMaxDistTol](const Point3d& pt) { + return abs( pt.z - dNearestPos) > dMaxDistTol ; }) ; double dAng ; if ( ! bTooFar) { @@ -1243,6 +1244,15 @@ VolZmap::AdjustDexelThroughCracks( int nG, const Vector3d& vtLen, const INTTOCHE } // altrimenti sposto di poco lo spillone e ricalcolo le intersezioni con la superficie, finché trovo l'intersezione mancante else { + // controllo quanti intervalli hanno i vicini + vector vNeigh = GetNeighbours( nG, itc.nI, itc.nJ, m_dStep) ; + int nMinIntervals = 0 ; + for ( const auto& [i, j, n] : vNeigh) { + int nNeighPos = int( j) * m_nNx[nG] + int( i) ; + if ( ssize(m_Values[nG][nNeighPos]) > nMinIntervals) + nMinIntervals = ssize(m_Values[nG][nNeighPos]) ; + } + bool bFound = false ; DBLVECTOR vSmallStep ; vSmallStep.push_back( Clamp( 0.05 * m_dStep, 50 * EPS_SMALL, 1.)) ; @@ -1323,9 +1333,12 @@ VolZmap::AdjustDexelThroughCracks( int nG, const Vector3d& vtLen, const INTTOCHE } } // controllo che abbia almeno un intervallo in più rispetto a quelli di prima - if ( ssize( vNewIntervals) > ssize( m_Values[nG][nPos])) { + bool bValidNewIntrerval = ssize( vNewIntervals) > ssize( m_Values[nG][nPos]) ; + if ( ! bHaveRef) + bValidNewIntrerval = bValidNewIntrerval && ssize( vNewIntervals) >= nMinIntervals ; + if ( bValidNewIntrerval) { // se avevo un punto disaccoppiato lo uso come riferimento - if ( itc.ptInters.IsValid()) { + if ( bHaveRef) { // devo controllare se l'intervallo in più è quello che cercavo // controllo anche tra le intersezioni scartate double dMinDist = INFINITO ; @@ -1351,48 +1364,73 @@ VolZmap::AdjustDexelThroughCracks( int nG, const Vector3d& vtLen, const INTTOCHE } } else { - // se non avevo intervalli sul corrente tengo tutto quello trovo - if ( ssize( m_Values[nG][nPos]) == 0) { - bFound = true ; + bFound = true ; + // cerco se ho delle corrispondenza tra gli intervalli che avevo già sul corrente + // e quelli che ho trovato ora + bool bSplit = false ; + INTINTVECTOR vMatch ; + int nCurr = 0 ; + for ( auto& dataCurr : m_Values[nG][nPos]) { + // se ho una sovrapposizione tra intervalli ho una corrispondenza + int nNew = 0 ; + for ( auto& dataNew : vNewIntervals) { + if ( dataCurr.dMin < dataNew.dMax && dataNew.dMin < dataCurr.dMax) { + if ( ! vMatch.empty() && nCurr == vMatch.back().first) + bSplit = true ; + vMatch.emplace_back( nCurr, nNew) ; + } + ++ nNew ; + } + ++nCurr ; + } + if ( ssize( m_Values[nG][nPos]) == 0 || ! bSplit) { + // se non avevo intervalli sul corrente tengo tutto quello trovo bAddAllIntervals = true ; } else { - // altrimenti mi aspetto di aver attrvarsato due fessure e quindi di avere sullo spillone corrente un + // altrimenti mi aspetto di aver attraversato due fessure e quindi di avere sullo spillone corrente un // intervallo il cui inizio e fine corrispondono a inizio di un intervallo e fine del successivo - for ( int z = 0 ; z < ssize( vNewIntervals) - 1 ; ++z) { - Data& data = vNewIntervals[z] ; - Data& dataNext = vNewIntervals[z+1] ; - bool bSkipNext = false ; - for ( int w = 0 ; w < ssize( m_Values[nG][nPos]) ; ++w) { - Data& dataCurr = m_Values[nG][nPos][w] ; - if ( abs( data.dMin - dataCurr.dMin) < m_dStep && abs( dataNext.dMax - dataCurr.dMax) < m_dStep) { - m_Values[nG][nPos].emplace_back() ; - m_Values[nG][nPos].back().dMin = dataCurr.dMin; - m_Values[nG][nPos].back().dMax = data.dMax ; - m_Values[nG][nPos].back().vtMinN = dataCurr.vtMinN ; - m_Values[nG][nPos].back().vtMaxN = data.vtMaxN ; - m_Values[nG][nPos].back().nToolMin = 0 ; - m_Values[nG][nPos].back().nToolMax = 0 ; - m_Values[nG][nPos].back().nCompo = 0 ; - //secondo - m_Values[nG][nPos].emplace_back() ; - m_Values[nG][nPos].back().dMin = dataNext.dMin; - m_Values[nG][nPos].back().dMax = dataCurr.dMax ; - m_Values[nG][nPos].back().vtMinN = dataNext.vtMinN ; - m_Values[nG][nPos].back().vtMaxN = dataCurr.vtMaxN ; - m_Values[nG][nPos].back().nToolMin = 0 ; - m_Values[nG][nPos].back().nToolMax = 0 ; - m_Values[nG][nPos].back().nCompo = 0 ; - // cancello quello che era - m_Values[nG][nPos].erase( m_Values[nG][nPos].begin() + w) ; - bSkipNext = true ; - break ; - } - } - if ( bSkipNext) + INTVECTOR vErase ; + for ( int z = 1 ; z < ssize( vMatch) ; ++z) { + if ( vMatch[z].first == vMatch[z-1].first) { + vErase.push_back( vMatch[z].first) ; + Data& data = vNewIntervals[vMatch[z-1].second] ; + Data& dataNext = vNewIntervals[vMatch[z].second] ; + m_Values[nG][nPos].emplace_back() ; + m_Values[nG][nPos].emplace_back() ; + Data& dataCurr = m_Values[nG][nPos][vMatch[z].first] ; + // primo + m_Values[nG][nPos].end()[-2].dMin = dataCurr.dMin; + m_Values[nG][nPos].end()[-2].dMax = data.dMax ; + m_Values[nG][nPos].end()[-2].vtMinN = dataCurr.vtMinN ; + m_Values[nG][nPos].end()[-2].vtMaxN = data.vtMaxN ; + m_Values[nG][nPos].end()[-2].nToolMin = 0 ; + m_Values[nG][nPos].end()[-2].nToolMax = 0 ; + m_Values[nG][nPos].end()[-2].nCompo = 0 ; + // secondo + m_Values[nG][nPos].end()[-1].dMin = dataNext.dMin; + m_Values[nG][nPos].end()[-1].dMax = dataCurr.dMax ; + m_Values[nG][nPos].end()[-1].vtMinN = dataNext.vtMinN ; + m_Values[nG][nPos].end()[-1].vtMaxN = dataCurr.vtMaxN ; + m_Values[nG][nPos].end()[-1].nToolMin = 0 ; + m_Values[nG][nPos].end()[-1].nToolMax = 0 ; + m_Values[nG][nPos].end()[-1].nCompo = 0 ; ++z ; + } } + // cancello gli intervalli che sono stati splittati + for ( int z : views::reverse( vErase)) + m_Values[nG][nPos].erase( m_Values[nG][nPos].begin() + z) ; } + // cancello gli intervalli per cui avevo già un corrispettivo sul corrente, a meno che non sia una doppia corrispondenza + // in quel caso devo spezzare l'intervallo sul corrente + // prima elimino i doppioni da vMatch + for ( int z = ssize( vMatch) - 1 ; z > 0; --z) { + if ( vMatch[z].second == vMatch[z-1].second) + vMatch.erase( vMatch.begin() + z) ; + } + for ( auto [ nCurr, nNew] : views::reverse( vMatch)) + vNewIntervals.erase( vNewIntervals.begin() + nNew) ; } } if ( bFound) @@ -1401,13 +1439,13 @@ VolZmap::AdjustDexelThroughCracks( int nG, const Vector3d& vtLen, const INTTOCHE if ( bFound) break ; } - // se cercando nei d'intorni dello spillone non ho trovato l'intersezione mancante, mi arrendo + // se cercando nei dintorni dello spillone non ho trovato l'intersezione mancante, mi arrendo if ( ! bFound) continue ; } - if ( ! bAddAllIntervals) { + if ( ! bAddAllIntervals && bHaveRef) { double dMin, dMax ; Vector3d vtMinN, vtMaxN ; if ( itc.dU < ptInt.z) { @@ -1457,6 +1495,67 @@ VolZmap::AdjustDexelThroughCracks( int nG, const Vector3d& vtLen, const INTTOCHE return true ; } +// ad ogni lato assegno un bit +enum NeighSide { + BOTTOM = 1 << 0, + RIGHT = 1 << 1, + TOP = 1 << 2, + LEFT = 1 << 3 +}; + +// con una mask verifico se due punti stanno sullo stesso lato +bool AreOnSameEdge( int a, int b) +{ + static const int mask[9] = { + BOTTOM | LEFT, // 0 + BOTTOM, // 1 + BOTTOM | RIGHT, // 2 + LEFT, // 3 + 0, // 4 (centro) + RIGHT, // 5 + TOP | LEFT, // 6 + TOP, // 7 + TOP | RIGHT // 8 + }; + + return ( mask[a] & mask[b]) != 0 ; +} + +constexpr int border[8] = { 0, 1, 2, 5, 8, 7, 6, 3} ; + +constexpr int position[9] = +{ + 0, // 0 + 1, // 1 + 2, // 2 + 7, // 3 + -1, // 4 (centro) + 3, // 5 + 6, // 6 + 5, // 7 + 4 // 8 +} ; + +bool AreOpposite( int a, int b) +{ + // a partire da un punto cosidero suoi opposti l'opposto geometrico e i suoi vicini + // quindi i punti a distanza 3,4,5 salti dal punto di partenza + int pa = position[a] ; + int pb = position[b] ; + + if ( pa == -1 || pb == -1) + return false ; + + int d = ( pb - pa + 8) % 8 ; + + return d == 3 || d == 4 || d == 5 ; +} + +bool AreOpposite2( int a, int b) +{ + return a + b == 8 ; +} + //---------------------------------------------------------------------------- bool VolZmap::SearchMissingIntervals( int nMap, INTTOCHECKVEC& vIntToCheck) @@ -1466,18 +1565,15 @@ VolZmap::SearchMissingIntervals( int nMap, INTTOCHECKVEC& vIntToCheck) for ( int nJ = 0 ; nJ < m_nNy[nMap] ; ++nJ) { int nPos = int( nJ) * m_nNx[nMap] + int( nI) ; vector vNeigh = GetNeighbours( nMap, nI, nJ, 1) ; + int nLastNeighTrig = -1 ; for ( const auto& [i,j,n] : vNeigh) { int nNeighPos = int( j) * m_nNx[nMap] + int( i) ; if ( ssize( m_Values[nMap][nNeighPos]) > ssize( m_Values[nMap][nPos])) { - int nNeigh = 8 - n ; - auto itOpp = find_if( vNeigh.begin(), vNeigh.end(), [nNeigh]( const Neigh& a) { return a.nN == nNeigh ;}) ; - int nIndOpp = distance( begin( vNeigh), itOpp) ; - if ( itOpp != vNeigh.end()) { - int nOppNeighPos = int( vNeigh[nIndOpp].nJ) * m_nNx[nMap] + int( vNeigh[nIndOpp].nI) ; - if ( ssize( m_Values[nMap][nOppNeighPos]) == ssize( m_Values[nMap][nNeighPos])) { - vIntToCheck.emplace_back( P_INVALID, V_INVALID, double( NAN), nMap, nI, nJ) ; - break ; - } + if ( nLastNeighTrig == - 1) + nLastNeighTrig = n ; + else if ( AreOpposite2( nLastNeighTrig, n)) { + vIntToCheck.emplace_back( P_INVALID, V_INVALID, double( NAN), nMap, nI, nJ) ; + break ; } } }