EgtGeomkernel :

- correzioni a booleane di TriMesh.
This commit is contained in:
Dario Sassi
2020-04-05 17:09:23 +00:00
parent c341a8d036
commit b23f738bb9
+80 -89
View File
@@ -1,7 +1,7 @@
//----------------------------------------------------------------------------
// EgalTech 2019-2020
//----------------------------------------------------------------------------
// File : SurfTriMeshBooleans.cpp Data : 13.03.20 Versione : 2.2c1
// File : SurfTriMeshBooleans.cpp Data : 04.04.20 Versione : 2.2d1
// Contenuto : Implementazione delle funzioni booleane per SurfFTrimesh.
//
//
@@ -128,7 +128,7 @@ ChangeStart( const Point3d& ptNewStart, PNTVECTOR& Loop)
// Estremi del segmento corrente del loop
Point3d ptSegSt = Loop[nPt] ;
Point3d ptSegEn = Loop[( nPt + 1) % int( Loop.size())] ;
// Vedo se il punto giace sul segmento del loop
// Distanza del punto dal segmento del loop
DistPointLine dDistCalc( ptNewStart, ptSegSt, ptSegEn) ;
double dSqDist ;
dDistCalc.GetSqDist( dSqDist) ;
@@ -185,18 +185,18 @@ ChangeStart( const Point3d& ptNewStart, PNTVECTOR& Loop)
static bool
SplitAtPoint( const Point3d& ptStop, const PNTVECTOR& Loop, PNTVECTOR& Loop1, PNTVECTOR& Loop2)
{
// Cerco il tratto del loop chiuso più vicino al punto
// Cerco il tratto del loop chiuso più vicino al punto
int nMinSeg = -1 ;
double dMinSqDinst = DBL_MAX;
for (int nPt = 0 ; nPt < int(Loop.size()) ; ++ nPt) {
double dMinSqDinst = DBL_MAX ;
for ( int nPt = 0 ; nPt < int( Loop.size()) ; ++ nPt) {
// Estremi del segmento corrente del loop
Point3d ptSegSt = Loop[nPt] ;
Point3d ptSegEn = Loop[(nPt + 1) % int(Loop.size())] ;
// Vedo se il punto giace sul segmento del loop
Point3d ptSegEn = Loop[( nPt + 1) % int(Loop.size())] ;
// Distanza del punto dal segmento del loop
DistPointLine dDistCalc( ptStop, ptSegSt, ptSegEn) ;
double dSqDist ;
dDistCalc.GetSqDist( dSqDist) ;
if (dSqDist < dMinSqDinst) {
if ( dSqDist < dMinSqDinst) {
dMinSqDinst = dSqDist ;
nMinSeg = nPt ;
}
@@ -735,6 +735,12 @@ SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq)
bool
SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMATRIX& cvBoundClosedLoopVec, BOOLVECTOR& vbInOut)
{
// Valuto se esistono loop non degeneri
int nExistNotDeg = 0 ;
for ( int nC = 0 ; nC < int( vnDegVec.size()) ; ++ nC) {
if ( vnDegVec[nC] > 0)
++ nExistNotDeg ;
}
// Divido il loop di partenza in sotto-loop
int nIterationCount = 0 ;
while ( cvOpenChain.size() > 0) {
@@ -887,7 +893,7 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
}
}
}
if ( ! bLoopSplitted) {
if ( ! bLoopSplitted && ( vnDegVec[nLastOpenLoopN] == 1 || nExistNotDeg == 0)) {
int nCurDeg = vnDegVec[nLastOpenLoopN] ;
vnDegVec.emplace( vnDegVec.begin(), nCurDeg) ;
Chain CurChain ;
@@ -1015,6 +1021,71 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
}
}
// Se esistono loop divisi in catene, le unisco
Triangle3d trTria ;
Surf.GetTriangle( it->first, trTria) ;
for ( int nC1 = 0 ; nC1 < nChainCnt - 1 ; ++ nC1) {
int nFirstChainLastSegPos = int( vChain[nC1].size()) - 1 ;
bool bFirstChainInside = nFirstChainLastSegPos >= 0 &&
IsPointInsideTriangle( vChain[nC1][0].ptSt, trTria, TriangleType::OPEN) &&
IsPointInsideTriangle( vChain[nC1][nFirstChainLastSegPos].ptEn, trTria, TriangleType::OPEN) ;
for ( int nC2 = nC1 + 1 ; nC2 < nChainCnt && bFirstChainInside ; ++ nC2) {
int nSecondChainLastSegPos = int( vChain[nC2].size()) - 1 ;
bool bSecondChainInside = nSecondChainLastSegPos >= 0 &&
IsPointInsideTriangle( vChain[nC2][0].ptSt, trTria, TriangleType::OPEN) &&
IsPointInsideTriangle( vChain[nC2][nSecondChainLastSegPos].ptEn, trTria, TriangleType::OPEN) ;
nFirstChainLastSegPos = int( vChain[nC1].size()) - 1 ;
bool bFisrtSecond = AreSamePointEpsilon( vChain[nC1][nFirstChainLastSegPos].ptEn, vChain[nC2][0].ptSt, 10 * EPS_SMALL) ;
for ( int nSeg = 0 ; nSeg <= nSecondChainLastSegPos && bSecondChainInside && bFisrtSecond ; ++ nSeg) {
IntSegment CurSeg ;
CurSeg.ptSt = vChain[nC2][nSeg].ptSt ;
CurSeg.ptEn = vChain[nC2][nSeg].ptEn ;
CurSeg.vtOuter = vChain[nC2][nSeg].vtOuter ;
CurSeg.bDegenerate = vChain[nC2][nSeg].bDegenerate ;
vChain[nC1].emplace_back( CurSeg) ;
}
bool bSecondFirst = AreSamePointEpsilon( vChain[nC1][0].ptSt, vChain[nC2][nSecondChainLastSegPos].ptEn, 10 * EPS_SMALL) ;
for ( int nSeg = 0 ; nSeg <= nFirstChainLastSegPos && bSecondChainInside && bSecondFirst && ! bFisrtSecond ; ++ nSeg) {
IntSegment CurSeg ;
CurSeg.ptSt = vChain[nC1][nSeg].ptSt ;
CurSeg.ptEn = vChain[nC1][nSeg].ptEn ;
CurSeg.vtOuter = vChain[nC1][nSeg].vtOuter ;
CurSeg.bDegenerate = vChain[nC1][nSeg].bDegenerate ;
vChain[nC2].emplace_back( CurSeg) ;
}
if ( bSecondChainInside && bFisrtSecond && nSecondChainLastSegPos >= 0) {
nFirstChainLastSegPos = int( vChain[nC1].size()) - 1 ;
bFirstChainInside = nFirstChainLastSegPos >= 0 &&
IsPointInsideTriangle( vChain[nC1][0].ptSt, trTria, TriangleType::OPEN) &&
IsPointInsideTriangle( vChain[nC1][nFirstChainLastSegPos].ptEn, trTria, TriangleType::OPEN) ;
vChain.erase( vChain.begin() + nC2) ;
-- nChainCnt ;
-- nC2 ;
}
if ( bSecondChainInside && bSecondFirst && ! bFisrtSecond && nFirstChainLastSegPos >= 0) {
vChain.erase( vChain.begin() + nC1) ;
-- nChainCnt ;
-- nC2 ;
nC2 = nC2 == nC1 ? nC2 + 1 : nC2 ;
}
}
}
// Chiudo i loop costruiti a partire dalle catene
for ( int nC = 0 ; nC < nChainCnt ; ++ nC) {
int nChainLastSegPos = int( vChain[nC].size()) - 1 ;
if ( IsPointInsideTriangle( vChain[nC][0].ptSt, trTria, TriangleType::OPEN) &&
IsPointInsideTriangle( vChain[nC][nChainLastSegPos].ptEn, trTria, TriangleType::OPEN) &&
AreSamePointEpsilon( vChain[nC][0].ptSt, vChain[nC][nChainLastSegPos].ptEn, 10 * EPS_SMALL)) {
IntSegment CurSeg ;
CurSeg.ptSt = vChain[nC][nChainLastSegPos].ptEn ;
CurSeg.ptEn = vChain[nC][0].ptSt ;
CurSeg.vtOuter = ( CurSeg.ptEn - CurSeg.ptSt) ^ trTria.GetN() ;
CurSeg.vtOuter.Normalize() ;
CurSeg.bDegenerate = ( CurSeg.ptEn - CurSeg.ptSt).Len() > EPS_SMALL ;
vChain[nC].emplace_back( CurSeg) ;
}
}
// Fra le catene trovate separo le aperte dalle chiuse
int nDegenerateChainNum = 0 ;
INTVECTOR vnDegVec ;
@@ -1071,11 +1142,6 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
// Questo viene diviso in sotto-loop chiusi mediante quelli aperti.
// I loop chiusi trovati precedentemente sono interni a uno dei sotto-loop
// chiusi di cui è formato il perimetro.
// Recupero il triangolo
Triangle3d trTria ;
Surf.GetTriangle( it->first, trTria) ;
PNTVECTOR cvFirstLoop ;
cvFirstLoop.emplace_back( trTria.GetP( 0)) ;
cvFirstLoop.emplace_back( trTria.GetP( 1)) ;
@@ -1137,7 +1203,6 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
}
else {
Surf.m_vTria[it->first].nTempPart = 0 ;
/*Surf.m_vTria[it->first].nTempPart *= 10 ;*/
continue ;
}
}
@@ -2324,77 +2389,3 @@ SurfTriMesh::GetSurfClassification( const ISurfTriMesh& ClassifierSurf,
}
return true ;
}
///////////////////////// DEBUG /////////////////////////////////////////////////////////////////////////////////////////////////
//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 ;
//}
//
//if ( ( AreSamePointApprox(trTriaB.GetP(0), Point3d(76, 40, 30)) &&
// AreSamePointApprox(trTriaB.GetP(1), Point3d(60, 40, 50)) &&
// AreSamePointApprox(trTriaB.GetP(2), Point3d(20, 40, 30))) ||
// ( AreSamePointApprox(trTriaB.GetP(2), Point3d(76, 40, 30)) &&
// AreSamePointApprox(trTriaB.GetP(0), Point3d(60, 40, 50)) &&
// AreSamePointApprox(trTriaB.GetP(1), Point3d(20, 40, 30))) ||
// ( AreSamePointApprox(trTriaB.GetP(1), Point3d(76, 40, 30)) &&
// AreSamePointApprox(trTriaB.GetP(2), Point3d(60, 40, 50)) &&
// AreSamePointApprox(trTriaB.GetP(0), Point3d(20, 40, 30)))) {
// int b = 0 ;
//}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
//if ((AreSamePointApprox(trTriaA.GetP(0), Point3d(20, 40, 46)) &&
// AreSamePointApprox(trTriaA.GetP(1), Point3d(100, 40, 30)) &&
// AreSamePointApprox(trTriaA.GetP(2), Point3d(20, 40, 30))) ||
// (AreSamePointApprox(trTriaA.GetP(2), Point3d(20, 40, 46)) &&
// AreSamePointApprox(trTriaA.GetP(0), Point3d(100, 40, 30)) &&
// AreSamePointApprox(trTriaA.GetP(1), Point3d(20, 40, 30))) ||
// (AreSamePointApprox(trTriaA.GetP(1), Point3d(20, 40, 46)) &&
// AreSamePointApprox(trTriaA.GetP(2), Point3d(100, 40, 30)) &&
// AreSamePointApprox(trTriaA.GetP(0), Point3d(20, 40, 30)))) {
//
// if ((AreSamePointApprox(trTriaB.GetP(0), Point3d(76, 40, 30)) &&
// AreSamePointApprox(trTriaB.GetP(1), Point3d(60, 40, 50)) &&
// AreSamePointApprox(trTriaB.GetP(2), Point3d(20, 40, 30))) ||
// (AreSamePointApprox(trTriaB.GetP(2), Point3d(76, 40, 30)) &&
// AreSamePointApprox(trTriaB.GetP(0), Point3d(60, 40, 50)) &&
// AreSamePointApprox(trTriaB.GetP(1), Point3d(20, 40, 30))) ||
// (AreSamePointApprox(trTriaB.GetP(1), Point3d(76, 40, 30)) &&
// AreSamePointApprox(trTriaB.GetP(2), Point3d(60, 40, 50)) &&
// AreSamePointApprox(trTriaB.GetP(0), Point3d(20, 40, 30)))) {
// int b = 0;
// }
//}
///////////////////////////////////////////////////////////////////////////////////////////////////
//bool
//FacesRetriangulation()
//{
// // Mi assicuro che la trimesh sia ok
// // Assicurarsi che la trimesh sia ok ......
// // Pongo tutti i triangoli come non visitati
// for ( int nT = 0 ; nT < GetTriangleSize() ; ++ nT) {
// m_vTria[nT].nTemp = 0 ;
// }
// // Ciclo sui triangoli
// for ( int nT = 0 ; nT < GetTriangleSize() ; ++ nT) {
// // Se triangolo non visitato
// if ( m_vTria[nT].nTemp == 0) {
// m_vTria[nT].nTemp = 1 ;
// unordered_set<int> TriaIndexSet ;// devi usare stack
// TriaIndexSet.emplace( nT) ;
// while ( ! TriaIndexSet.empty()) {
//
// }
// }
// }
// return true ;
//}