EgtGeomKernel :

- correzioni e migliorie a VolZMap da trimesh con crepe.
This commit is contained in:
Daniele Bariletti
2026-07-23 17:37:29 +02:00
parent 07d5b3a110
commit e5117c0453
2 changed files with 279 additions and 145 deletions
+9 -1
View File
@@ -50,6 +50,13 @@ struct IntersToCheck {
typedef std::vector<IntersToCheck> INTTOCHECKVEC ;
struct Neigh { // 6 7 8
double nI ; // 3 s 5
double nJ ; // 0 1 2
int nN ; // n-esimo vicino di uno spillone : numerati così
Neigh( double _nI, double _nJ, int _nN) : nI( _nI), nJ( _nJ), nN( _nN) { ;}
};
//----------------------------------------------------------------------------
class VolZmap : public IVolZmap, public IGeoObjRW
{
@@ -483,7 +490,8 @@ class VolZmap : public IVolZmap, public IGeoObjRW
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ;
bool AdjustDexelThroughCracks( int nG, const Vector3d& vtLen, const INTTOCHECKVEC& vIntToCheck, const Point3d& ptMapOrig,
const ISurfTriMesh& Surf, const IntersParLinesSurfTm& intPLSTM) ;
DBLDBLVECTOR GetNeighbours( int nG, int nI, int nJ, double dPar) ;
bool SearchMissingIntervals( int nMap, INTTOCHECKVEC& vIntToCheck) ;
std::vector<Neigh> GetNeighbours( int nG, int nI, int nJ, double dPar) ;
// Funzioni per Offset di superfici
bool InitVolZMapOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) ;
bool InitVolZMapThickeningOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) ;
+270 -144
View File
@@ -606,8 +606,10 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co
if ( k > 0) {
int z = k - 1 ;
// controllo se l'intersezione corrente è coincidente con la precedente, per esempio se ILTT == 4 ( intersezione su un lato di un triangolo, quindi con 2 triangoli)
// controllo anche che le proiezioni delle normali abbiano lo stesso segno rispetto allo spillone
if ( IntersectionResults[k].dU - IntersectionResults[z].dU < EPS_SMALL &&
IntersectionResults[k].dCosDN - IntersectionResults[z].dCosDN < EPS_SMALL)
IntersectionResults[k].dCosDN - IntersectionResults[z].dCosDN < EPS_SMALL &&
IntersectionResults[k].dCosDN * IntersectionResults[z].dCosDN > 0)
continue ;
}
@@ -634,6 +636,10 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co
Surf.GetFacetNormal( nF, vtInN) ;
bInside = true ;
if ( k == nInt - 1) {
// se ho un ingresso ma è l'ultima intersezione vuol dire che è spaiata
vIntToCheck.emplace_back( IntersectionResults[k].ptI, vtInN, IntersectionResults[k].dU, nMap, i, j) ;
}
}
// esco dalla superficie trimesh
@@ -677,6 +683,10 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co
if ( bForceClosed) {
if ( ! AdjustDexelThroughCracks( nMap, vtLen, vIntToCheck, ptMapOrig, Surf, intPLSTM))
return false ;
vIntToCheck.clear() ;
SearchMissingIntervals( nMap, vIntToCheck) ;
if ( ! AdjustDexelThroughCracks( nMap, vtLen, vIntToCheck, ptMapOrig, Surf, intPLSTM))
return false ;
}
return true ;
@@ -1048,30 +1058,30 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
return bCompleted ;
}
DBLDBLVECTOR
vector<Neigh>
VolZmap::GetNeighbours( int nG, int nI, int nJ, double dPar)
{
DBLDBLVECTOR vNeigh ;
vector<Neigh> vNeigh ;
// parto da in basso a sinistra e procedo per righe, saltando il punto corrente
if ( nI > 0 && nJ > 0)
vNeigh.emplace_back( nI - dPar, nJ - dPar) ;
vNeigh.emplace_back( nI - dPar, nJ - dPar, 0) ;
if ( nJ > 0) {
vNeigh.emplace_back( nI, nJ - dPar) ;
vNeigh.emplace_back( nI, nJ - dPar, 1) ;
if ( nI < m_nNx[nG] - dPar)
vNeigh.emplace_back( nI + dPar, nJ - dPar) ;
vNeigh.emplace_back( nI + dPar, nJ - dPar, 2) ;
}
// passo alla fila contenente il punto corrente
if ( nI > 0)
vNeigh.emplace_back( nI - dPar, nJ) ;
vNeigh.emplace_back( nI - dPar, nJ, 3) ;
if ( nI < m_nNx[nG] - dPar)
vNeigh.emplace_back( nI + dPar, nJ) ;
vNeigh.emplace_back( nI + dPar, nJ, 5) ;
// passo alla fila successiva a quella del corrente
if ( nJ < m_nNy[nG] - dPar) {
if ( nI > 0)
vNeigh.emplace_back( nI - dPar, nJ + dPar) ;
vNeigh.emplace_back( nI, nJ + dPar) ;
if ( nI < m_nNx[nG])
vNeigh.emplace_back( nI + dPar, nJ + dPar) ;
vNeigh.emplace_back( nI - dPar, nJ + dPar, 6) ;
vNeigh.emplace_back( nI, nJ + dPar, 7) ;
if ( nI < m_nNx[nG] - dPar)
vNeigh.emplace_back( nI + dPar, nJ + dPar, 8) ;
}
return vNeigh ;
}
@@ -1095,103 +1105,112 @@ VolZmap::AdjustDexelThroughCracks( int nG, const Vector3d& vtLen, const INTTOCHE
for ( const auto& itc : vIntToCheck) {
int nPos = itc.nJ * m_nNx[nG] + itc.nI ;
double dPosRef = itc.ptInters.v[( nG + 2) % 3] ;
// controllo se esiste già un intervallo con un estremo quasi coincidente a quello segnalato
// ed entrambi sono entrate o uscite
bool bNeedToReconstruct = true ;
for ( const auto& data: m_Values[nG][nPos]) {
if ( (( abs( dPosRef - data.dMin) < 10 * EPS_SMALL && ( itc.vtN * vtAx) * ( data.vtMinN * vtAx) > 0)) ||
(( abs( dPosRef - data.dMax) < 10 * EPS_SMALL && ( itc.vtN * vtAx) * ( data.vtMaxN * vtAx) > 0))) {
bNeedToReconstruct = false ;
break ;
}
bool bUseNeighInfo = true ;
// se il punto di intersezione passato non è valido vuol dire che non ho neanche un'intersezione spaiata da cui partire a cercare
bool bHaveRef = true ;
if ( ! isfinite( dPosRef)) {
bHaveRef = false ;
bUseNeighInfo = false ;
}
if ( ! bNeedToReconstruct)
continue ;
DBLDBLVECTOR vNeigh = GetNeighbours( nG, itc.nI, itc.nJ, m_dStep) ;
PNTVECTOR vNeighInters ;
Vector3d vtMeanN = V_NULL ;
bool bSearchingInOrOut = itc.vtN * vtAx > 0 ;
bool bUseNeighInfo = true ;
for ( const auto& [i,j] : vNeigh) {
double dMinDist = INFINITO ;
double dCorrespInters = INFINITO ;
double dNearestPos = NAN ;
Vector3d vtNearestN ;
int nNeighPos = int( j) * m_nNx[nG] + int( i) ;
for ( const auto& data: m_Values[nG][nNeighPos]) {
double dDist1 = abs( dPosRef - data.dMin) ;
double dDist2 = abs( dPosRef - data.dMax) ;
if ( dDist1 < dMinDist || dDist2 < dMinDist) {
dMinDist = min( dDist1, dDist2) ;
// se sto cercando un ingresso
if ( bSearchingInOrOut) {
if ( data.vtMaxN * vtAx < 0) {
dNearestPos = data.dMax ;
vtNearestN = data.vtMaxN ;
dCorrespInters = data.dMin ;
}
else if ( data.vtMinN * vtAx < 0) {
dNearestPos = data.dMin ;
vtNearestN = data.vtMinN ;
dCorrespInters = data.dMax ;
}
}
// se sto cercando un'uscita
else {
if ( data.vtMaxN * vtAx > 0) {
dNearestPos = data.dMax ;
vtNearestN = data.vtMaxN ;
dCorrespInters = data.dMin ;
}
else if ( data.vtMinN * vtAx > 0) {
dNearestPos = data.dMin ;
vtNearestN = data.vtMinN ;
dCorrespInters = data.dMax ;
}
}
}
}
// verifico che il dNearestPos sia effettivamente associato al tratto che sto cercando di ricostruire
// e non ad un altro presente sullo spillone corrente
bool bAddNearest = true ;
if ( bHaveRef) {
// controllo se esiste già un intervallo con un estremo quasi coincidente a quello segnalato
// ed entrambi sono entrate o uscite
bool bNeedToReconstruct = true ;
for ( const auto& data: m_Values[nG][nPos]) {
double dDist1 = abs( dCorrespInters - data.dMin) ;
double dDist2 = abs( dCorrespInters - data.dMax) ;
if ( dDist1 < dMinDist || dDist2 < dMinDist) {
bAddNearest = false ;
if ( (( abs( dPosRef - data.dMin) < 10 * EPS_SMALL && ( itc.vtN * vtAx) * ( data.vtMinN * vtAx) > 0)) ||
(( abs( dPosRef - data.dMax) < 10 * EPS_SMALL && ( itc.vtN * vtAx) * ( data.vtMaxN * vtAx) > 0))) {
bNeedToReconstruct = false ;
break ;
}
}
}
if ( ! bNeedToReconstruct)
continue ;
vector<Neigh> vNeigh = GetNeighbours( nG, itc.nI, itc.nJ, m_dStep) ;
bool bSearchingInOrOut = itc.vtN * vtAx > 0 ;
for ( const auto& [i, j, n] : vNeigh) {
double dMinDist = INFINITO ;
double dCorrespInters = INFINITO ;
double dNearestPos = NAN ;
Vector3d vtNearestN ;
int nNeighPos = int( j) * m_nNx[nG] + int( i) ;
for ( const auto& data : m_Values[nG][nNeighPos]) {
double dDist1 = abs( dPosRef - data.dMin) ;
double dDist2 = abs( dPosRef - data.dMax) ;
if ( dDist1 < dMinDist || dDist2 < dMinDist) {
dMinDist = min( dDist1, dDist2) ;
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 ;
}) ;
double dAng ;
if ( ! bTooFar) {
// controllo anche che gli angoli delle normali non cambino troppo
// calcolo l'angolo con la media delle precedenti perché il valore oltre cui
// considero le normali diverse è grande
vtNearestN.GetAngle( vtMeanN, dAng) ;
// se sto cercando un ingresso
if ( bSearchingInOrOut) {
if ( data.vtMaxN * vtAx < 0) {
dNearestPos = data.dMax ;
vtNearestN = data.vtMaxN ;
dCorrespInters = data.dMin ;
}
else if ( data.vtMinN * vtAx < 0) {
dNearestPos = data.dMin ;
vtNearestN = data.vtMinN ;
dCorrespInters = data.dMax ;
}
}
// se sto cercando un'uscita
else {
if ( data.vtMaxN * vtAx > 0) {
dNearestPos = data.dMax ;
vtNearestN = data.vtMaxN ;
dCorrespInters = data.dMin ;
}
else if ( data.vtMinN * vtAx > 0) {
dNearestPos = data.dMin ;
vtNearestN = data.vtMinN ;
dCorrespInters = data.dMax ;
}
}
}
}
bAddNearest = ! bTooFar && dAng < dAngSameFace ;
if ( bAddNearest) {
double dX = ( i + 0.5) * m_dStep ;
double dY = ( j + 0.5) * m_dStep ;
vNeighInters.emplace_back( dX, dY, dNearestPos) ;
vtMeanN += vtNearestN ;
// verifico che il dNearestPos sia effettivamente associato al tratto che sto cercando di ricostruire
// e non ad un altro presente sullo spillone corrente
bool bAddNearest = true ;
for ( const auto& data : m_Values[nG][nPos]) {
double dDist1 = abs( dCorrespInters - data.dMin) ;
double dDist2 = abs( dCorrespInters - data.dMax) ;
if ( dDist1 < dMinDist || dDist2 < dMinDist) {
bAddNearest = false ;
break ;
}
}
else {
bUseNeighInfo = false ;
break ;
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 ;
}) ;
double dAng ;
if ( ! bTooFar) {
// controllo anche che gli angoli delle normali non cambino troppo
// calcolo l'angolo con la media delle precedenti perché il valore oltre cui
// considero le normali diverse è grande
vtNearestN.GetAngle( vtMeanN, dAng) ;
}
bAddNearest = ! bTooFar && dAng < dAngSameFace ;
if ( bAddNearest) {
double dX = ( i + 0.5) * m_dStep ;
double dY = ( j + 0.5) * m_dStep ;
vNeighInters.emplace_back( dX, dY, dNearestPos) ;
vtMeanN += vtNearestN ;
}
else {
bUseNeighInfo = false ;
break ;
}
}
}
}
vector<Data> vNewIntervals ;
bool bAddAllIntervals = false ;
Point3d ptInt ;
// se riesco uso i vicini per calcolare l'intersezione mancante
if ( bUseNeighInfo) {
@@ -1233,15 +1252,16 @@ VolZmap::AdjustDexelThroughCracks( int nG, const Vector3d& vtLen, const INTTOCHE
// se ciclando la raggiera non trovo un'intersezione valida allora potrei essermi spostato troppo poco dallo spillone originale e essere caduto ancora nella fessura
// quindi ciclo nuovamente aumentando un poco la distanza dallo spillone originale ( comunque sempre meno della distanza m_dStep)
for ( int c = 0 ; c < ssize( vSmallStep) ; ++c) {
DBLDBLVECTOR vSmallMoveNeigh = GetNeighbours( nG, itc.nI, itc.nJ, vSmallStep[c]) ;
vector<Neigh> vSmallMoveNeigh = GetNeighbours( nG, itc.nI, itc.nJ, vSmallStep[c]) ;
for ( int n = 0 ; n < ssize( vSmallMoveNeigh) ; ++n) {
double dX = ( vSmallMoveNeigh[n].first + 0.5) * m_dStep ;
double dY = ( vSmallMoveNeigh[n].second + 0.5) * m_dStep ;
double dX = ( vSmallMoveNeigh[n].nI + 0.5) * m_dStep ;
double dY = ( vSmallMoveNeigh[n].nJ + 0.5) * m_dStep ;
Point3d ptP0( dX, dY, 0) ;
ILSIVECTOR IntersectionResults ;
intPLSTM.GetInters( ptP0, vtLen.v[(nG+2)%3], IntersectionResults) ;
// intervalli dalle intersezioni
vector<Data> vNewIntervals ;
vNewIntervals.clear() ;
DBLVECTOR vDiscardedInters ;
bool bInside = false ;
Vector3d vtInN ;
Point3d ptIn ;
@@ -1258,6 +1278,10 @@ VolZmap::AdjustDexelThroughCracks( int nG, const Vector3d& vtLen, const INTTOCHE
double dCos = IntersectionResults[i].dCosDN ;
// entro nella superficie trimesh
if ( dCos < - dCosSmall) {
if ( bInside) {
int k = i - 1 ;
vDiscardedInters.push_back( IntersectionResults[k].dU) ;
}
ptIn = IntersectionResults[i].ptI ;
int nT = IntersectionResults[i].nT ;
@@ -1269,7 +1293,11 @@ VolZmap::AdjustDexelThroughCracks( int nG, const Vector3d& vtLen, const INTTOCHE
}
// esco dalla superficie trimesh
else if ( dCos > dCosSmall && bInside) {
else if ( dCos > dCosSmall) {
if ( ! bInside) {
vDiscardedInters.push_back( IntersectionResults[i].dU) ;
continue ;
}
Point3d ptOut = IntersectionResults[i].ptI ;
int nT = IntersectionResults[i].nT ;
@@ -1294,22 +1322,76 @@ VolZmap::AdjustDexelThroughCracks( int nG, const Vector3d& vtLen, const INTTOCHE
}
}
}
// controllo che abbia un intervallo in più rispetto a quelli di prima
if ( ssize( vNewIntervals) == ssize( m_Values[nG][nPos]) + 1) {
// dovrei verificare che quello in più sia effettivamente quello ricercato????
double dMinDist = INFINITO ;
for ( const auto& data : vNewIntervals) {
if ( abs( data.dMin - dPosRef) < dMinDist) {
dMinDist = abs( data.dMin - dPosRef) ;
ptInt.Set( itc.nI + 0.5, itc.nJ + 0.5, data.dMax) ;
vtMeanN = data.vtMaxN ;
bFound = true ;
// controllo che abbia almeno un intervallo in più rispetto a quelli di prima
if ( ssize( vNewIntervals) > ssize( m_Values[nG][nPos])) {
// se avevo un punto disaccoppiato lo uso come riferimento
if ( itc.ptInters.IsValid()) {
// devo controllare se l'intervallo in più è quello che cercavo
// controllo anche tra le intersezioni scartate
double dMinDist = INFINITO ;
for ( const auto& data : vNewIntervals) {
if ( abs( data.dMin - dPosRef) < dMinDist) {
dMinDist = abs( data.dMin - dPosRef) ;
ptInt.Set( itc.nI + 0.5, itc.nJ + 0.5, data.dMax) ;
vtMeanN = data.vtMaxN ;
bFound = true ;
}
if ( abs( data.dMax - dPosRef) < dMinDist) {
dMinDist = abs( data.dMax - dPosRef) ;
ptInt.Set( itc.nI + 0.5, itc.nJ + 0.5, data.dMin) ;
vtMeanN = data.vtMinN ;
bFound = true ;
}
}
if ( abs( data.dMax - dPosRef) < dMinDist) {
dMinDist = abs( data.dMax - dPosRef) ;
ptInt.Set( itc.nI + 0.5, itc.nJ + 0.5, data.dMin) ;
vtMeanN = data.vtMinN ;
for ( const auto& dU : vDiscardedInters) {
if ( abs( dU - dPosRef) < dMinDist) {
bFound = false ;
break ;
}
}
}
else {
// se non avevo intervalli sul corrente tengo tutto quello trovo
if ( ssize( m_Values[nG][nPos]) == 0) {
bFound = true ;
bAddAllIntervals = true ;
}
else {
// altrimenti mi aspetto di aver attrvarsato 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)
++z ;
}
}
}
}
@@ -1323,39 +1405,83 @@ VolZmap::AdjustDexelThroughCracks( int nG, const Vector3d& vtLen, const INTTOCHE
if ( ! bFound)
continue ;
}
double dMin, dMax ;
Vector3d vtMinN, vtMaxN ;
if ( itc.dU < ptInt.z) {
dMin = itc.dU ;
dMax = ptInt.z ;
vtMinN = itc.vtN ;
vtMaxN = vtMeanN ;
if ( ! bAddAllIntervals) {
double dMin, dMax ;
Vector3d vtMinN, vtMaxN ;
if ( itc.dU < ptInt.z) {
dMin = itc.dU ;
dMax = ptInt.z ;
vtMinN = itc.vtN ;
vtMaxN = vtMeanN ;
}
else {
dMin = ptInt.z ;
dMax = itc.dU ;
vtMinN = vtMeanN ;
vtMaxN = itc.vtN ;
}
//// prima di aggiungere il tratto verifico che non si sovrapponga con un tratto già presente
//for ( const auto& data: m_Values[nG][nPos]) {
// if ( ( dMin > data.dMin && dMin < data.dMax) ||
// ( dMax > data.dMin && dMax < data.dMax) ||
// ( dMin < data.dMin && dMax > data.dMax))
// continue ;
//}
m_Values[nG][nPos].emplace_back() ;
m_Values[nG][nPos].back().dMin = dMin;
m_Values[nG][nPos].back().dMax = dMax ;
m_Values[nG][nPos].back().vtMinN = vtMinN ;
m_Values[nG][nPos].back().vtMaxN = vtMaxN ;
m_Values[nG][nPos].back().nToolMin = 0 ;
m_Values[nG][nPos].back().nToolMax = 0 ;
m_Values[nG][nPos].back().nCompo = 0 ;
}
else {
dMin = ptInt.z ;
dMax = itc.dU ;
vtMinN = vtMeanN ;
vtMaxN = itc.vtN ;
for ( const auto& data: vNewIntervals) {
m_Values[nG][nPos].emplace_back() ;
m_Values[nG][nPos].back().dMin = data.dMin;
m_Values[nG][nPos].back().dMax = data.dMax ;
m_Values[nG][nPos].back().vtMinN = data.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 ;
}
}
//// prima di aggiungere il tratto verifico che non si sovrapponga con un tratto già presente
//for ( const auto& data: m_Values[nG][nPos]) {
// if ( ( dMin > data.dMin && dMin < data.dMax) ||
// ( dMax > data.dMin && dMax < data.dMax) ||
// ( dMin < data.dMin && dMax > data.dMax))
// continue ;
//}
m_Values[nG][nPos].emplace_back() ;
m_Values[nG][nPos].back().dMin = dMin;
m_Values[nG][nPos].back().dMax = dMax ;
m_Values[nG][nPos].back().vtMinN = vtMinN ;
m_Values[nG][nPos].back().vtMaxN = vtMaxN ;
m_Values[nG][nPos].back().nToolMin = 0 ;
m_Values[nG][nPos].back().nToolMax = 0 ;
m_Values[nG][nPos].back().nCompo = 0 ;
std::sort( m_Values[nG][nPos].begin(), m_Values[nG][nPos].end(), []( Data& a, Data& b) { return a.dMin < b.dMin ;}) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SearchMissingIntervals( int nMap, INTTOCHECKVEC& vIntToCheck)
{
for ( int nI = 0 ; nI < m_nNx[nMap] ; ++nI) {
for ( int nJ = 0 ; nJ < m_nNy[nMap] ; ++nJ) {
int nPos = int( nJ) * m_nNx[nMap] + int( nI) ;
vector<Neigh> vNeigh = GetNeighbours( nMap, nI, nJ, 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 ;
}
}
}
}
}
}
return true ;
}