EgtGeomKernel :
- migliorie e correzioni a ZMap da una trimesh con crack.
This commit is contained in:
+147
-51
@@ -22,6 +22,7 @@
|
||||
#include "/EgtDev/Include/EGkIntersLinePlane.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include <future>
|
||||
#include <ranges>
|
||||
|
||||
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<Neigh> 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<Neigh> 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 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user