EgtGeomKernel 2.2b3 :

- correzioni per triangoli che scompaiono in booleane di trimesh.
This commit is contained in:
Dario Sassi
2020-02-20 08:59:39 +00:00
parent 49f957ced5
commit fd2396fb1b
3 changed files with 171 additions and 37 deletions
+168 -37
View File
@@ -745,7 +745,8 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
PNTVECTOR Loop1, Loop2 ;
bool bChangedStart = ChangeStart( ptOpenLoopStP, cvBoundClosedLoopVec[nLoop]) ;
bool bSplitted = SplitAtPoint( ptOpenLoopEnP, cvBoundClosedLoopVec[nLoop], Loop1, Loop2) ;
if ( ! ( bChangedStart && bSplitted))
if ( ! ( bChangedStart && bSplitted) ||
( nLastOpenLoopPoint == 0 && ( Loop1.size() == 2 || Loop2.size() == 2)))
continue ;
bLoopSplitted = true ;
Chain cvCounterChain ;
@@ -1083,8 +1084,61 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
BOOLVECTOR vbInOut ;
vbInOut.push_back( true) ;
// Divido il loop usando le catene
if ( ! DecomposeLoop( cvOpenChain, vnDegVec, cvBoundClosedLoopVec, vbInOut))
continue ;
if ( ! DecomposeLoop( cvOpenChain, vnDegVec, cvBoundClosedLoopVec, vbInOut)) {
if ( int( cvBoundClosedLoopVec.size()) == 1 && int( cvOpenChain.size()) == 2) {
Point3d ptLink0St = cvOpenChain[0][0].ptSt ;
Point3d ptLink0En = cvOpenChain[0].back().ptEn ;
Point3d ptLink1St = cvOpenChain.back()[0].ptSt ;
Point3d ptLink1En = cvOpenChain.back().back().ptEn ;
double dDist01 = sqrt( ( ptLink0En - ptLink1St) * ( ptLink0En - ptLink1St)) ;
double dDist10 = sqrt( ( ptLink1En - ptLink0St) * ( ptLink1En - ptLink0St)) ;
if ( dDist01 < 2 * EPS_SMALL) {
IntSegment LinkingSeg ;
LinkingSeg.ptSt = ptLink0En ;
LinkingSeg.ptEn = ptLink1St ;
LinkingSeg.vtOuter = cvOpenChain[0].back().vtOuter ;
LinkingSeg.bDegenerate = false ;
cvOpenChain[0].emplace_back( LinkingSeg) ;
for ( int nLinkI = 0 ; nLinkI < int( cvOpenChain.back().size()) ; ++ nLinkI) {
cvOpenChain[0].emplace_back( cvOpenChain.back()[nLinkI]) ;
}
cvOpenChain.resize( 1) ;
int nComplDeg = vnDegVec[0] * vnDegVec[1] ;
vnDegVec[0] = nComplDeg ;
vnDegVec.resize( 1) ;
}
else if ( dDist10 < 2 * EPS_SMALL) {
IntSegment LinkingSeg ;
LinkingSeg.ptSt = cvOpenChain.back().back().ptEn ;
LinkingSeg.ptEn = cvOpenChain[0].back().ptSt ;
LinkingSeg.vtOuter = cvOpenChain.back().back().vtOuter ;
LinkingSeg.bDegenerate = false ;
cvOpenChain.back().emplace_back( LinkingSeg) ;
for ( int nLinkI = 0 ; nLinkI < int( cvOpenChain[0].size()) ; ++ nLinkI) {
cvOpenChain.back().emplace_back( cvOpenChain[0][nLinkI]) ;
}
cvOpenChain.erase( cvOpenChain.begin()) ;
int nComplDeg = vnDegVec[0] * vnDegVec[1] ;
vnDegVec[0] = nComplDeg ;
vnDegVec.resize( 1) ;
}
else {
Surf.m_vTria[it->first].nTempPart = 0 ;
continue ;
}
vbInOut.resize( 1) ;
vbInOut[0] = true ;
if ( ! DecomposeLoop( cvOpenChain, vnDegVec, cvBoundClosedLoopVec, vbInOut)) {
Surf.m_vTria[it->first].nTempPart = 0 ;
continue ;
}
}
else {
Surf.m_vTria[it->first].nTempPart = 0 ;
/*Surf.m_vTria[it->first].nTempPart *= 10 ;*/
continue ;
}
}
// Rimuovo il triangolo corrente
Surf.RemoveTriangle( it->first) ;
// Trasformo i loop compositi in loop polyline
@@ -1203,8 +1257,16 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
vInnerLoop.emplace_back( nCLI) ;
}
}
if ( vInnerLoop.size() == 0) {
// Elimino loop interni non validi
bool bDouble = true ;
for ( int nInnLoop = 0 ; nInnLoop < int( vInnerLoop.size()) ; ++ nInnLoop) {
if ( int( cvClosedChain[vInnerLoop[nInnLoop]].size()) > 2) {
bDouble = false ;
break ;
}
}
if ( vInnerLoop.size() == 0 || bDouble) {
// Eseguo triangolazione
PNTVECTOR vPt ;
INTVECTOR vTr ;
@@ -1297,33 +1359,101 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
//----------------------------------------------------------------------------
bool
SurfTriMesh::AmbiguosTriangleManager( TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Surf)
{
for ( auto it = Ambiguos.begin() ; it != Ambiguos.end() ; ++ it) {
Triangle3d trTria ;
Surf.GetTriangle( it->first, trTria) ;
trTria.Validate() ;
Point3d ptBar = ( trTria.GetP( 0) + trTria.GetP( 1) + trTria.GetP( 2)) / 3 ;
double dMinDist = DBL_MAX ;
int nTriaIndex = - 1 ;
for ( int nOthSurfT = 0 ; nOthSurfT < int( it->second.size()) ; ++ nOthSurfT) {
Triangle3d trOthSurfTria = it->second[nOthSurfT] ;
double dDot = ( ptBar - trOthSurfTria.GetP( 0)) * trOthSurfTria.GetN() ;
if ( abs( dDot) > EPS_SMALL) {
double dDist ;
if ( DistPointTriangle( ptBar, trOthSurfTria).GetDist( dDist) && dDist < dMinDist) {
nTriaIndex = nOthSurfT ;
dMinDist = dDist ;
FindTriaIncidence( const Triangle3d& trTria, const TRIA3DVECTOR& vOthTriaVec, INTMATRIX& vAdjSegToCurTria)
{
int nNumFoundContact = 0 ;
vAdjSegToCurTria.resize( 3) ;
for ( int nEdge = 0 ; nEdge < 3 ; ++ nEdge) {
for ( int nOther = 0 ; nOther < int( vOthTriaVec.size()) ; ++ nOther) {
Triangle3d trOthTria = vOthTriaVec[nOther] ;
Point3d ptSt = trTria.GetP( nEdge) ;
Point3d ptEn = trTria.GetP( ( nEdge + 1) % 3) ;
CurveLine cvEdgeLine ;
cvEdgeLine.Set( ptSt, ptEn) ;
for ( int nOthEdge = 0 ; nOthEdge < 3 ; ++ nOthEdge) {
Point3d ptOthSt = trOthTria.GetP( nOthEdge) ;
Point3d ptOthEn = trOthTria.GetP( ( nOthEdge + 1) % 3) ;
CurveLine cvOthEdgeLine ;
cvOthEdgeLine.Set( ptOthSt, ptOthEn) ;
DistPointLine DistCalculatorCurOth( 0.5 * ( ptSt + ptEn), cvOthEdgeLine, false) ;
double dSqDistCurOth ;
DistCalculatorCurOth.GetSqDist( dSqDistCurOth) ;
DistPointLine DistCalculatorOthCur( 0.5 * ( ptOthSt + ptOthEn), cvEdgeLine, false) ;
double dSqDistOthCur ;
DistCalculatorOthCur.GetSqDist( dSqDistOthCur) ;
if ( dSqDistCurOth < EPS_SMALL * EPS_SMALL && dSqDistOthCur < EPS_SMALL * EPS_SMALL) {
vAdjSegToCurTria[nEdge].emplace_back( nOther) ;
++ nNumFoundContact ;
}
}
}
if ( nTriaIndex != -1) {
Triangle3d trOthSurfTria = it->second[nTriaIndex] ;
trOthSurfTria.Validate() ;
double dDot = ( ptBar - trOthSurfTria.GetP( 0)) * trOthSurfTria.GetN() ;
Surf.m_vTria[it->first].nTempPart = ( dDot < 0 ? 1 : -1) ;
}
if (nNumFoundContact != int(vOthTriaVec.size()))
int dudu = 0 ;
return ( nNumFoundContact == int( vOthTriaVec.size())) ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::AmbiguosTriangleManager( TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Surf)
{
for ( auto it = Ambiguos.begin() ; it != Ambiguos.end() ; ++ it) {
// Se il triangolo ha l'indice diverso da zero vuol dire che oltre a un
// contatto edge-edge ha avuto dei contatti che lo hanno già classificato.
if ( Surf.m_vTria[it->first].nTempPart != 0)
continue ;
// Recupero il triangolo corrente
Triangle3d trTria ;
Surf.GetTriangle( it->first, trTria) ;
trTria.Validate() ;
// Vettore dei triangoli i cui edge incidono su quelli del triangolo corrente
TRIA3DVECTOR& vOthTriaVec = it->second ;
// Vettore degli indici dei segmenti del triangolo adiacenti agli altri triangoli
INTMATRIX vAdjSegToCurTria ;
if ( ! FindTriaIncidence( trTria, vOthTriaVec, vAdjSegToCurTria))
return false ;
// Classifico il triangolo in base ai triangoli che incidono sui suoi edge
int nTriaClassificationByEdges[3] = { 0, 0, 0 } ;
for ( int nEdge = 0 ; nEdge < 3 ; ++ nEdge) {
if ( int( vAdjSegToCurTria[nEdge].size()) == 0)
continue ;
// Calcolo la normale media ai triangoli che incidono sull'edge corrente
Vector3d vtAvVec ;
for ( int nTr = 0 ; nTr < int( vAdjSegToCurTria[nEdge].size()) ; ++ nTr) {
vtAvVec += vOthTriaVec[vAdjSegToCurTria[nEdge][nTr]].GetN() ;
}
// Calcolo il vettore ortogonale all'edge corrente che punta al baricentro del triangolo corrente
Point3d ptBar = ( trTria.GetP(0) + trTria.GetP(1) + trTria.GetP(2)) / 3. ;
Vector3d vtBarVec = ptBar - trTria.GetP( nEdge) ;
Vector3d vtEdgeDir = trTria.GetP( ( nEdge + 1) % 3) - trTria.GetP( nEdge) ;
vtEdgeDir.Normalize() ;
vtBarVec -= ( vtBarVec * vtEdgeDir) * vtEdgeDir ;
// Se entrambi i vettori sono definiti classifico il triangolo in modo opportuno
if ( vtBarVec.Normalize( 0.01 * EPS_SMALL) && vtAvVec.Normalize( 0.01 * EPS_SMALL)) {
if ( vtBarVec * vtAvVec < - EPS_ZERO) {
nTriaClassificationByEdges[nEdge] = 1 ;
}
else if ( vtBarVec * vtAvVec > EPS_ZERO) {
nTriaClassificationByEdges[nEdge] = -1 ;
}
}
}
}
// Verifico che le classificazioni siano coerenti
for ( int i = 0 ; i < 3 ; ++ i) {
if ( nTriaClassificationByEdges[i] == 0)
continue ;
Surf.m_vTria[it->first].nTempPart = nTriaClassificationByEdges[i] ;
int j ;
for ( j = i + 1 ; j < 3 ; ++ j) {
if ( nTriaClassificationByEdges[j] != 0 && nTriaClassificationByEdges[i] != nTriaClassificationByEdges[j]) {
Surf.m_vTria[it->first].nTempPart = 0 ;
break ;
}
}
if ( j < 3)
break ;
}
}
return true ;
}
@@ -2080,15 +2210,16 @@ SurfTriMesh::GetSurfClassification( const ISurfTriMesh& ClassifierSurf,
}
///////////////////////// DEBUG /////////////////////////////////////////////////////////////////////////////////////////////////
//if ( ( AreSamePointApprox(trTriaA.GetP(0), Point3d(0.6312, 42.0801, 100)) &&
// AreSamePointApprox(trTriaA.GetP(1), Point3d(0.3554, 44.0491, 100)) &&
// AreSamePointApprox(trTriaA.GetP(2), Point3d(0.6312, 42.0801, 0))) ||
// ( AreSamePointApprox(trTriaA.GetP(2), Point3d(0.6312, 42.0801, 100)) &&
// AreSamePointApprox(trTriaA.GetP(0), Point3d(0.3554, 44.0491, 100)) &&
// AreSamePointApprox(trTriaA.GetP(1), Point3d(0.6312, 42.0801, 0))) ||
// ( AreSamePointApprox(trTriaA.GetP(1), Point3d(0.6312, 42.0801, 100)) &&
// AreSamePointApprox(trTriaA.GetP(2), Point3d(0.3554, 44.0491, 100)) &&
// AreSamePointApprox(trTriaA.GetP(0), Point3d(0.6312, 42.0801, 0)))) {
//if ( nTriaNumB == 76 &&
// ( AreSamePointApprox(trTriaA.GetP(0), Point3d( 920.5333, 0.0000, 190.5)) &&
// AreSamePointApprox(trTriaA.GetP(1), Point3d( 1150.6666, 0.0000, 190.5)) &&
// AreSamePointApprox(trTriaA.GetP(2), Point3d( 920.5333, 245.89, 190.5))) ||
// ( AreSamePointApprox(trTriaA.GetP(2), Point3d( 920.5333, 0.0000, 190.5)) &&
// AreSamePointApprox(trTriaA.GetP(0), Point3d( 1150.6666, 0.0000, 190.5)) &&
// AreSamePointApprox(trTriaA.GetP(1), Point3d( 920.5333, 245.89, 190.5))) ||
// ( AreSamePointApprox(trTriaA.GetP(1), Point3d( 920.5333, 0.0000, 190.5)) &&
// AreSamePointApprox(trTriaA.GetP(2), Point3d( 1150.6666, 0.0000, 190.5)) &&
// AreSamePointApprox(trTriaA.GetP(0), Point3d( 920.5333, 245.89, 190.5)))) {
// int a = 0 ;
//}
//