EgtGeomKernel :

- migliorie per Stm booleans.
This commit is contained in:
Riccardo Elitropi
2024-02-19 13:07:50 +01:00
parent 46b91bb49d
commit 95915b16e5
5 changed files with 253 additions and 122 deletions
+150 -117
View File
@@ -53,9 +53,10 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
if ( vnDegVec[nC] > 0)
++ nExistNotDeg ;
}
// Divido il loop di partenza in sotto-loop
int nIterationCount = 0 ;
while ( cvOpenChain.size() > 0) {
while ( cvOpenChain.size() > 0) { // per ogni catena aperta...
bool bLoopSplitted = false ;
int nLastOpenLoopN = int( cvOpenChain.size()) - 1 ;
if ( vnDegVec[nLastOpenLoopN] == 1) {
@@ -64,13 +65,24 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
int nLastOpenLoopPoint = max( int( cvOpenChain[nLastOpenLoopN].size()) - 1, 0) ;
Point3d ptOpenLoopStP = cvOpenChain[nLastOpenLoopN][0].ptSt ;
Point3d ptOpenLoopEnP = cvOpenChain[nLastOpenLoopN][nLastOpenLoopPoint].ptEn ;
// costruisco il primo e il secondo loop che si generano
// NB. il loop esterno è chiuso, mentre la catena aperta
// è la successione dei tratti lineari dovuti ai triangoli dell'altra superficie
PNTVECTOR Loop1, Loop2 ;
// cambio il punto iniziale del loop di bordo se non coincide già con ptStart della catena aperta
bool bChangedStart = ChangeStart( ptOpenLoopStP, cvBoundClosedLoopVec[nLoop]) ;
// splitto
bool bSplitted = SplitAtPoint( ptOpenLoopEnP, cvBoundClosedLoopVec[nLoop], Loop1, Loop2) ;
if ( ! ( bChangedStart && bSplitted) ||
( nLastOpenLoopPoint == 0 && ( Loop1.size() == 2 || Loop2.size() == 2)))
continue ;
continue ; // la catena aperta non è interna al loop chiuso attuale
// il loop 1 segue sempre la direzione della catena, il loop 2 ha dentro la catena invertita
// Ho sempre che il loop 1 è sempre interno ( la direzione della catena è determinata
// dalla normale dei triangoli che la formano; avendo chimatao la chian senza ammettere inversioni, sono
// curve tutte concordi ) e il loop 2 che è esterno
bLoopSplitted = true ;
// ricostrusico i due loop mediante concatenazione
Chain cvCounterChain ;
for ( int nPt = int( cvOpenChain[nLastOpenLoopN].size()) - 1 ; nPt >= 0 ; -- nPt) {
IntSegment CurSeg ;
@@ -182,7 +194,7 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
// elimino i punti superflui prima
for ( int i = 0 ; i < nCvFirst ; ++ i)
cvBoundClosedLoopVec[nLoop].erase( cvBoundClosedLoopVec[nLoop].begin()) ;
// verifico se questo punto dalla parte valida o no
// verifico se questo punto è dalla parte valida o no
bool bC12 = ( ( ptM12 - ptProva) * vtVecProva < 0) ;
vbInOut[nLoop] = bC12 ;
}
@@ -193,7 +205,7 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
// elimino i punti superflui intermedi
for ( int i = nCvFirst + 2 ; i < nCvSecond ; ++ i)
cvBoundClosedLoopVec[nLoop].erase( cvBoundClosedLoopVec[nLoop].begin() + nCvFirst + 2) ;
// verifico se questo punto dalla parte valida o no
// verifico se questo punto è dalla parte valida o no
bool bC21 = ( ( ptM21 - ptProva) * vtVecProva < 0) ;
vbInOut[nLoop] = bC21 ;
}
@@ -235,9 +247,13 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
// La superficie deve essere valida
if ( ! Surf.IsValid())
return false ;
// Ritriangolarizzo i triangoli
// itero sulla unorderd_map
for ( auto it = LoopLines.begin() ; it != LoopLines.end() ; ++ it) {
// itero sulle catene ( secondo parametro della mappa)
for ( int nS1 = 0 ; nS1 < int( it->second.size()) - 1 ; ++ nS1) {
// tolgo i tratti degeneri ad un punto
for ( int nS2 = nS1 + 1 ; nS2 < int( it->second.size()) ; ++ nS2) {
if ( AreSamePointApprox( it->second[nS1].ptSt, it->second[nS2].ptEn) &&
AreSamePointApprox( it->second[nS1].ptEn, it->second[nS2].ptSt) &&
@@ -249,22 +265,21 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
}
}
}
// se non resta nulla, allora passo alla mappa successiva
if ( int( it->second.size()) == 0)
continue ;
// Se il triangolo è stato sottoposto a ritriangolazione, le sue componenti sono classificabili come dentro-fuori.
// Lo tolgo dall'insieme dei triangoli ambigui (intersezione edge-edge)
else {
auto itS = Ambiguos.find( it->first) ;
if ( itS != Ambiguos.end()) {
Ambiguos.erase( itS) ;
}
}
auto itS = Ambiguos.find( it->first) ;
if ( itS != Ambiguos.end())
Ambiguos.erase( itS) ;
// Creo i loop
// CREAZIONE DEI LOOP ---------------------------------------------
// Chain
ChainCurves LoopCreator ;
LoopCreator.Init( false, 2 * EPS_SMALL, int( it->second.size()), 10 * BOOLEAN_SCALE) ;
// Carico le curve per concatenarle
// Recupero le curve ( gli estremi dei tratti lineari) per concatenarle
for ( int nCv = 0 ; nCv < int( it->second.size()); ++ nCv) {
Point3d ptSt = it->second[nCv].ptSt ;
Point3d ptEn = it->second[nCv].ptEn ;
@@ -278,15 +293,14 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
CHAINVECTOR vChain ;
while ( LoopCreator.GetChainFromNear( ptNearStart, false, vIds)) {
Chain chTemp ;
for ( auto i : vIds) {
// Aggiungo la linea alla curva composta.
for ( auto i : vIds) // Aggiungo la linea alla curva composta
chTemp.emplace_back( it->second[i - 1]) ;
}
vChain.emplace_back( chTemp) ;
}
// Lavoro su loop e catene per regolarizzarle
int nChainCnt = int( vChain.size()) ;
// unisco eventuali catene estreme che sono parte di una stessa catena
// Unisco eventuali catene estreme che sono parte di una stessa catena
if ( nChainCnt > 1) {
if ( AreSamePointApprox( vChain[0].front().ptSt, vChain[nChainCnt - 1].back().ptEn)) {
vChain[0].insert( vChain[0].begin(), vChain[nChainCnt - 1].begin(), vChain[nChainCnt - 1].end()) ;
@@ -299,7 +313,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
-- nChainCnt ;
}
}
// semplifico catene formate da punti degeneri
// Semplifico catene formate da punti degeneri
for ( int nCh = 0 ; nCh < nChainCnt ; ++ nCh) {
if ( vChain[nCh].size() == 2 && ( vChain[nCh][0].bDegenerate || vChain[nCh][1].bDegenerate)) {
vChain[nCh][0].ptEn = vChain[nCh][1].ptEn ;
@@ -378,6 +392,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
}
}
}
// Chiudo i loop costruiti a partire dalle catene
for ( int nC = 0 ; nC < nChainCnt ; ++ nC) {
int nChainLastSegPos = int( vChain[nC].size()) - 1 ;
@@ -464,7 +479,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
Surf.m_vTria[nNewAloneTriaNum].nETempFlag[0] = 0 ;
Surf.m_vTria[nNewAloneTriaNum].nETempFlag[1] = 0 ;
Surf.m_vTria[nNewAloneTriaNum].nETempFlag[2] = 0 ;
Surf.m_vTria[nNewAloneTriaNum].nTempPart = nDist[nAloneVert] ;
Surf.m_vTria[nNewAloneTriaNum].nTempPart = nDist[nAloneVert] ;
bModif = true ;
}
int nNewCoupleId1[3] = { Surf.AddVertex( ptIntSt), Surf.AddVertex( trTria.GetP( ( nAloneVert + 1) % 3)), Surf.AddVertex( trTria.GetP( ( nAloneVert + 2) % 3)) } ;
@@ -473,7 +488,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
Surf.m_vTria[nNewCoupleTriaNum1].nETempFlag[0] = 0 ;
Surf.m_vTria[nNewCoupleTriaNum1].nETempFlag[1] = 0 ;
Surf.m_vTria[nNewCoupleTriaNum1].nETempFlag[2] = 0 ;
Surf.m_vTria[nNewCoupleTriaNum1].nTempPart = - nDist[nAloneVert] ;
Surf.m_vTria[nNewCoupleTriaNum1].nTempPart = - nDist[nAloneVert] ;
bModif = true ;
}
int nNewCoupleId2[3] = { Surf.AddVertex( ptIntSt), Surf.AddVertex( trTria.GetP( ( nAloneVert + 2) % 3)), Surf.AddVertex( ptIntEn) } ;
@@ -482,27 +497,32 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
Surf.m_vTria[nNewCoupleTriaNum2].nETempFlag[0] = 0 ;
Surf.m_vTria[nNewCoupleTriaNum2].nETempFlag[1] = 0 ;
Surf.m_vTria[nNewCoupleTriaNum2].nETempFlag[2] = 0 ;
Surf.m_vTria[nNewCoupleTriaNum2].nTempPart = - nDist[nAloneVert] ;
Surf.m_vTria[nNewCoupleTriaNum2].nTempPart = - nDist[nAloneVert] ;
bModif = true ;
}
continue ;
}
}
}
// -------------------------------------------------------------------------------------------
// Creo il loop chiuso padre di tutti, il perimetro del triangolo.
// 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.
// Creo il loop chiuso padre di tutti, il perimetro del triangolo. 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.
PNTVECTOR cvFirstLoop ;
cvFirstLoop.emplace_back( trTria.GetP( 0)) ;
cvFirstLoop.emplace_back( trTria.GetP( 1)) ;
cvFirstLoop.emplace_back( trTria.GetP( 2)) ;
PNTMATRIX cvBoundClosedLoopVec;
// creo una matrice di punti ; ogni riga corrisponde ad una sequenza di punti che indentificano un loop
PNTMATRIX cvBoundClosedLoopVec ;
cvBoundClosedLoopVec.emplace_back( cvFirstLoop) ;
// vettore per indicare se il loop è interno/esterno all'altra superficie
BOOLVECTOR vbInOut ;
vbInOut.push_back( true) ;
// Divido il loop usando le catene
if ( ! DecomposeLoop( cvOpenChain, vnDegVec, cvBoundClosedLoopVec, vbInOut)) {
if ( cvBoundClosedLoopVec.size() == 1 && cvOpenChain.size() == 2) {
@@ -557,7 +577,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
Surf.m_vTria[it->first].nTempPart = 0 ;
continue ;
}
}
}
// Rimuovo il triangolo corrente
int nOldTriaCol = Surf.m_vTria[it->first].nTFlag ;
Surf.RemoveTriangle( it->first) ;
@@ -565,14 +585,14 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
POLYLINEVECTOR vplPolyVec ;
vplPolyVec.resize( cvBoundClosedLoopVec.size()) ;
for ( int nLoop = 0 ; nLoop < int( vplPolyVec.size()) ; ++ nLoop) {
for ( int nLine = 0 ; nLine < int( cvBoundClosedLoopVec[nLoop].size()) ; ++ nLine) {
for ( int nLine = 0 ; nLine < int( cvBoundClosedLoopVec[nLoop].size()) ; ++ nLine)
vplPolyVec[nLoop].AddUPoint( 0., cvBoundClosedLoopVec[nLoop][nLine]) ;
}
vplPolyVec[nLoop].AddUPoint( 0., cvBoundClosedLoopVec[nLoop][0]) ;
// Assegno ai loop trovati i rispettivi interni
// Assumo che i loop interni a uno dei loop creati fino ad'ora siano tutti sullo stesso livello.
// Il caso generale si risolve con una struttura ad albero in cui il nodi corrispondente a un
// Il caso generale si risolve con una struttura ad albero in cui il nodi corrispondente a un
// loop è figlio del nodo corrispondente al loop che lo contiene.
INTVECTOR vInnerLoop ;
for ( int nCLI = 0 ; nCLI < int( cvClosedChain.size()) ; ++ nCLI) {
@@ -693,7 +713,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
break ;
}
}
if ( vInnerLoop.size() == 0 || bDouble) {
// Eseguo triangolazione
PNTVECTOR vPt ;
@@ -711,7 +731,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
Surf.m_vTria[nNewTriaNum].nETempFlag[1] = 0 ;
Surf.m_vTria[nNewTriaNum].nETempFlag[2] = 0 ;
if ( vbInOut[nLoop])
Surf.m_vTria[nNewTriaNum].nTempPart = 1 ;
Surf.m_vTria[nNewTriaNum].nTempPart = 1 ;
else
Surf.m_vTria[nNewTriaNum].nTempPart = - 1 ;
bModif = true ;
@@ -720,33 +740,32 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
}
}
else {
// se ho più loop, essi descrivono un poligono di n-lati
POLYLINEVECTOR vPolygons ;
vPolygons.emplace_back( vplPolyVec[nLoop]) ;
for ( int nL = 0 ; nL < int( vInnerLoop.size()) ; ++ nL) {
// per ognuno di essi, ricavo la PolyLine dai punti
PolyLine CurLoop ;
for ( int nV = 0 ; nV < int( cvClosedChain[vInnerLoop[nL]].size()) ; ++ nV) {
for ( int nV = 0 ; nV < int( cvClosedChain[vInnerLoop[nL]].size()) ; ++ nV)
CurLoop.AddUPoint( 0., cvClosedChain[vInnerLoop[nL]][nV].ptSt) ;
}
CurLoop.AddUPoint( 0., cvClosedChain[vInnerLoop[nL]][0].ptSt) ;
vPolygons.emplace_back( CurLoop) ;
}
// poligono
Polygon3d pgPol ;
pgPol.FromPolyLine( vPolygons[1]) ;
// controllo direzioni delle normali
bool bCodirectedNormals = trTria.GetN() * pgPol.GetVersN() > 0. ;
//if ( bCodirectedNormals) {
// for ( int nL = 1 ; nL < int( vPolygons.size()) ; ++ nL) {
// vPolygons[nL].Invert() ;
// }
//} pizza
// Aggiungo al loop esterno i punti dei loop interni che si trovano su di esso
PNTULIST& ExternLoopList = vPolygons[0].GetUPointList() ;
// Ciclo sui segmenti del loop esterno
auto itSt = ExternLoopList.begin() ;
auto itEn = itSt ;
++ itEn ;
++ itEn ;
for ( ; itSt != ExternLoopList.end() && itEn != ExternLoopList.end() ; ++ itSt, ++ itEn) {
// Estremi del segmento corrente del loop esterno e scorrispondente vettore
Point3d ptSt = itSt->first ;
@@ -762,7 +781,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
Point3d ptInnPoint ;
bool bIsFirst = true ;
bool bContinue = vPolygons[nInnPoly].GetFirstPoint( ptInnPoint) ;
while ( bContinue) {
while ( bContinue) {
DistPointLine DistCalculator( ptInnPoint, ptSt, ptEn) ;
double dDist ;
DistCalculator.GetDist( dDist) ;
@@ -794,8 +813,9 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
PNTVECTOR vPt ;
INTVECTOR vTr ;
// classifico i loop e ricavo la triangolazione di essi mediante classificazione
if ( Triangulate().MakeAdvanced( vPolygons, vPt, vTr)) {
// Inserisco i nuovi triangoli
// Inserisco i nuovi triangoli
for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
int nNewTriaVertId[3] = { vTr[n], vTr[n + 1], vTr[n + 2]} ;
int nNewId[3] = { Surf.AddVertex( vPt[nNewTriaVertId[0]]),
@@ -818,7 +838,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
// Divido i loop che si autointercettano
int nInitialLoopNum = int( vPolygons.size()) ;
for ( int nL = 1 ; nL < nInitialLoopNum ; ++ nL) {
// Lista dei punti della PolyLine Loop corrente
// Lista dei punti della PolyLine Loop corrente
PNTULIST& LoopPointList = vPolygons[nL].GetUPointList() ;
// Ciclo sui segmenti
auto itSt2 = LoopPointList.begin() ;
@@ -929,31 +949,27 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
}
}
}
// pizza
//for ( int nL = 1 ; nL < int( vPolygons.size()) ; ++ nL) {
// vPolygons[nL].Invert() ;
vPolygons.erase( vPolygons.begin()) ;
if ( Triangulate().MakeAdvanced( vPolygons, vPt, vTr)) {
// Inserisco i nuovi triangoli
for (int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
int nNewTriaVertId[3] = { vTr[n], vTr[n + 1], vTr[n + 2]} ;
int nNewId[3] = { Surf.AddVertex( vPt[nNewTriaVertId[0]]),
Surf.AddVertex( vPt[nNewTriaVertId[1]]),
Surf.AddVertex( vPt[nNewTriaVertId[2]])} ;
int nNewTriaNum = Surf.AddTriangle( nNewId, nOldTriaCol) ;
if ( IsValidSvt( nNewTriaNum)) {
Surf.m_vTria[nNewTriaNum].nETempFlag[0] = 0 ;
Surf.m_vTria[nNewTriaNum].nETempFlag[1] = 0 ;
Surf.m_vTria[nNewTriaNum].nETempFlag[2] = 0 ;
if ( bCodirectedNormals)
Surf.m_vTria[nNewTriaNum].nTempPart = 1 ;
else
Surf.m_vTria[nNewTriaNum].nTempPart = -1 ;
bModif = true ;
}
vPolygons.erase( vPolygons.begin()) ;
if ( Triangulate().MakeAdvanced( vPolygons, vPt, vTr)) {
// Inserisco i nuovi triangoli
for (int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
int nNewTriaVertId[3] = { vTr[n], vTr[n + 1], vTr[n + 2]} ;
int nNewId[3] = { Surf.AddVertex( vPt[nNewTriaVertId[0]]),
Surf.AddVertex( vPt[nNewTriaVertId[1]]),
Surf.AddVertex( vPt[nNewTriaVertId[2]])} ;
int nNewTriaNum = Surf.AddTriangle( nNewId, nOldTriaCol) ;
if ( IsValidSvt( nNewTriaNum)) {
Surf.m_vTria[nNewTriaNum].nETempFlag[0] = 0 ;
Surf.m_vTria[nNewTriaNum].nETempFlag[1] = 0 ;
Surf.m_vTria[nNewTriaNum].nETempFlag[2] = 0 ;
if ( bCodirectedNormals)
Surf.m_vTria[nNewTriaNum].nTempPart = 1 ;
else
Surf.m_vTria[nNewTriaNum].nTempPart = -1 ;
bModif = true ;
}
}
//}
}
}
vInnerLoop.resize( 0) ;
}
@@ -1091,18 +1107,23 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
{
bool bModif = false ;
SurfTriMesh& SurfB = Other ;
// Le superfici devono essere valide
if ( m_nStatus != OK || ! SurfB.IsValid())
return false ;
// Unordered map dei segmenti di intersezione
CHAINMAP LineMapA ;
CHAINMAP LineMapB ;
// Unordered map dei triangoli ambigui (intersezione edge-edge)
TRIA3DVECTORMAP AmbiguosA ;
TRIA3DVECTORMAP AmbiguosB ;
// Ciclo sui triangoli delle mesh
int nTriaNumA = GetTriangleSize() ;
int nTriaNumB = SurfB.GetTriangleSize() ;
// Setto il triangolo come né fuori né dentro
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) {
m_vTria[nTA].nTempPart = 0 ;
@@ -1116,55 +1137,58 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
SurfB.m_vTria[nTB].nETempFlag[1] = 0 ;
SurfB.m_vTria[nTB].nETempFlag[2] = 0 ;
}
// Resetto e ricalcolo la HashGrid della superficie B
SurfB.ResetHashGrids3d() ;
// Scorro i triangoli della superficie A
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) {
// Se il triangolo A non è valido, continuo
Triangle3d trTriaA ;
if ( ! GetTriangle( nTA, trTriaA) || ! trTriaA.Validate( true))
continue ;
// Box del triangolo A
BBox3d b3dTriaA ;
trTriaA.GetLocalBBox( b3dTriaA) ;
// Recupero i triangoli di B che interferiscono col box del triangolo di A
INTVECTOR vNearTria ;
SurfB.GetAllTriaOverlapBox( b3dTriaA, vNearTria) ;
// I scorro tutti i triangoli di B che intersecano il box di A
for ( int nTB = 0 ; nTB < int( vNearTria.size()) ; ++ nTB) {
// Se il triangolo B non è valido, continuo
Triangle3d trTriaB ;
if ( ! SurfB.GetTriangle( vNearTria[nTB], trTriaB) || ! trTriaB.Validate( true))
continue ;
// Interseco i triangoli
Point3d ptSegSt, ptSegEn ;
TRIA3DVECTOR vTria ;
int nIntType = IntersTriaTria( trTriaA, trTriaB, ptSegSt, ptSegEn, vTria) ;
if ( nIntType == ITTT_EDGE_EDGE_SEG ||
nIntType == ITTT_EDGE_INT ||
nIntType == ITTT_INT_EDGE ||
nIntType == ITTT_INT_INT_SEG) {
// Assegno i dati di intersezione
// se l'intersezione è identificabile con un segmento...
if ( nIntType == ITTT_EDGE_EDGE_SEG || nIntType == ITTT_EDGE_INT ||
nIntType == ITTT_INT_EDGE || nIntType == ITTT_INT_INT_SEG) {
// Assegno i dati di intersezione per la superficie A
IntSegment CurInters ;
if ( nIntType == ITTT_EDGE_EDGE_SEG || nIntType == ITTT_EDGE_INT ||
nIntType == ITTT_INT_EDGE || nIntType == ITTT_INT_INT_SEG) {
CurInters.ptSt = ptSegSt ;
CurInters.ptEn = ptSegEn ;
CurInters.bDegenerate = false ;
}
else {
CurInters.ptSt = ptSegSt ;
CurInters.ptEn = ptSegSt ;
CurInters.bDegenerate = true ;
}
CurInters.vtOuter = trTriaB.GetN() ;
CurInters.ptSt = ptSegSt ; // punto iniziale del segmento
CurInters.ptEn = ptSegEn ; // punto finale del segmento
CurInters.bDegenerate = false ; // segmento non degenere
CurInters.vtOuter = trTriaB.GetN() ; // perpendicolare alla tangente ( oritentata )
CurInters.vtOuter -= ( ( CurInters.vtOuter * trTriaA.GetN()) * trTriaA.GetN()) ;
CurInters.vtOuter.Normalize() ;
// Salvo intersezione per superficie A
bool bIntOnEndgeA = false ;
if ( nIntType != ITTT_EDGE_EDGE_SEG && nIntType != ITTT_EDGE_INT) {
// controllo se tale segmento non è già contenuto
auto itA = LineMapA.find( nTA) ;
if ( itA != LineMapA.end()) {
if ( itA != LineMapA.end())
itA->second.emplace_back( CurInters) ;
}
else {
Chain chTemp ;
chTemp.emplace_back( CurInters) ;
@@ -1174,6 +1198,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
else
bIntOnEndgeA = true ;
// Inverto i dati del segmento per intersezione con superficie B
swap( CurInters.ptSt, CurInters.ptEn) ;
CurInters.vtOuter = trTriaA.GetN() ;
CurInters.vtOuter -= ( ( CurInters.vtOuter * trTriaB.GetN()) * trTriaB.GetN()) ;
@@ -1182,10 +1207,10 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
// Salvo intersezione per superficie B
bool bIntOnEndgeB = false ;
if ( nIntType != ITTT_EDGE_EDGE_SEG && nIntType != ITTT_INT_EDGE) {
// controllo se tale segmento non è già contenuto
auto itB = LineMapB.find( vNearTria[nTB]) ;
if ( itB != LineMapB.end()) {
if ( itB != LineMapB.end())
itB->second.emplace_back( CurInters) ;
}
else {
Chain chTemp ;
chTemp.emplace_back( CurInters) ;
@@ -1194,8 +1219,10 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
else
bIntOnEndgeB = true ;
// Intersezione edge-interno
// caso di Intersezione edge-interno ( per superificie A con B)
if ( bIntOnEndgeA && ! bIntOnEndgeB) {
// calcolo la massima distanza e il tratto ad essa associato
double dMaxDist = 0. ;
int nSegMaxDist = - 1 ;
for ( int nVA = 0 ; nVA < 3 ; ++ nVA) {
@@ -1206,7 +1233,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
}
if ( nSegMaxDist >= 0) {
// Cerco qual'è il segmento di contatto per dichiararlo come invalicabile
// Cerco qual è il segmento di contatto per dichiararlo come invalicabile
int nVA ;
for ( nVA = 0 ; nVA < 3 ; ++ nVA) {
if ( abs( ( trTriaA.GetP( nVA) - trTriaB.GetP( 0)) * trTriaB.GetN()) < EPS_SMALL &&
@@ -1218,8 +1245,9 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
m_vTria[nTA].nETempFlag[nVA] = m_vTria[nTA].nTempPart ;
}
}
// Intersezione interno-edge
// caso di Intersezione interno-edge ( per superficie A con B)
else if ( ! bIntOnEndgeA && bIntOnEndgeB) {
// calcolo la massima distanza e il tratto ad essa associato
double dMaxDist = 0. ;
int nSegMaxDist = - 1 ;
for ( int nVB = 0 ; nVB < 3 ; ++ nVB) {
@@ -1230,7 +1258,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
}
if ( nSegMaxDist >= 0) {
// Cerco qual'è il segmento di contatto per dichiararlo come invalicabile
// Cerco qual è il segmento di contatto per dichiararlo come invalicabile
int nVB ;
for ( nVB = 0 ; nVB < 3 ; ++ nVB) {
if ( abs( ( trTriaB.GetP( nVB) - trTriaA.GetP(0)) * trTriaA.GetN()) < EPS_SMALL &&
@@ -1269,11 +1297,14 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
}
}
// Ritriangolarizzo i triangoli delle superfici
RetriangulationForBooleanOperation( LineMapA, AmbiguosA, *this, bModif) ;
RetriangulationForBooleanOperation( LineMapB, AmbiguosB, SurfB, bModif) ;
SaveGeoObj( this->Clone(), "C:\\Users\\riccardo.elitropi\\Desktop\\SurfA.nge") ;
SaveGeoObj( SurfB.Clone(), "C:\\Users\\riccardo.elitropi\\Desktop\\SurfB.nge") ;
// Se i triangoli delle superfici non si intersecano, una delle due è totalmente interna o esterna all'altra.
// non mi basta fare un controllo sulle bbox perché non so come sono orientate le superfici e che potrebbero anche non essere chiuse
bool bRetriangulated = true ;
@@ -1312,7 +1343,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
if ( ( ptFirstV - trTriaB.GetP(0)) * trTriaB.GetN() < - EPS_SMALL) {
if ( nInOutNum == 0)
nInOutNum = 1 ;
else if (nInOutNum == -1) {
else if ( nInOutNum == -1) {
bSame = false ;
break ;
}
@@ -1320,7 +1351,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
else if ( ( ptFirstV - trTriaB.GetP(0)) * trTriaB.GetN() > EPS_SMALL) {
if ( nInOutNum == 0)
nInOutNum = -1 ;
else if (nInOutNum == 1) {
else if ( nInOutNum == 1) {
bSame = false ;
break ;
}
@@ -1328,23 +1359,23 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
// se le informazioni date dalle normali dei triangoli non sono concordi valuto il triangolo più vicino
// e ricalcolo l'informazione che mi dà la sua normale
if ( ! bSame ) {
if ( ! bSame) {
Point3d ptBar_tot ;
for (int nTriaNum : vnTriaNum) {
SurfB.GetTriangle( nTriaNum, trTriaB) ;
ptBar_tot += trTriaB.GetCentroid();
}
ptBar_tot /= (int)vnTriaNum.size() ;
for (int nTriaNum : vnTriaNum) {
ptBar_tot /= int( vnTriaNum.size()) ;
for ( int nTriaNum : vnTriaNum) {
SurfB.GetTriangle( nTriaNum, trTriaB) ;
Point3d ptInters1, ptInters2 ;
int nInters = IntersLineTria(ptFirstV, ptBar_tot, trTriaB, ptInters1, ptInters2, true) ;
if (nInters == ILTT_NO)
int nInters = IntersLineTria( ptFirstV, ptBar_tot, trTriaB, ptInters1, ptInters2, true) ;
if ( nInters == ILTT_NO)
continue ;
else if ( nInters == ILTT_IN ) {
if ( ( ptFirstV - trTriaB.GetP(0)) * trTriaB.GetN() < - EPS_SMALL)
else if ( nInters == ILTT_IN) {
if ( ( ptFirstV - trTriaB.GetP( 0)) * trTriaB.GetN() < - EPS_SMALL)
nInOutNum = 1 ;
else if ( ( ptFirstV - trTriaB.GetP(0)) * trTriaB.GetN() > EPS_SMALL)
else if ( ( ptFirstV - trTriaB.GetP( 0)) * trTriaB.GetN() > EPS_SMALL)
nInOutNum = -1 ;
break ;
}
@@ -1358,9 +1389,10 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
++ nVertNum ;
}
}
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) {
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA)
m_vTria[nTA].nTempPart = nInOutNum ;
}
nVertNum = 0 ;
nCurVert = SurfB.GetFirstVertex( ptFirstV) ;
nInOutNum = 0 ;
@@ -1377,7 +1409,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
DistCalculator.GetDist( dDist) ;
// potrei trovare più triangolo equidistanti, li salvo tutti
if ( DistPointTriangle( ptFirstV, trTriaA).GetDist( dDist)) {
if ( abs(dDist - dMinDist) < EPS_SMALL)
if ( abs( dDist - dMinDist) < EPS_SMALL)
vnTriaNum.push_back( nTA) ;
else if ( dDist < dMinDist){
vnTriaNum.clear() ;
@@ -1395,7 +1427,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
if ( ( ptFirstV - trTriaA.GetP(0)) * trTriaA.GetN() < - EPS_SMALL) {
if ( nInOutNum == 0)
nInOutNum = 1 ;
else if (nInOutNum == -1) {
else if ( nInOutNum == -1) {
bSame = false ;
break ;
}
@@ -1403,7 +1435,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
else if ( ( ptFirstV - trTriaA.GetP(0)) * trTriaA.GetN() > EPS_SMALL) {
if ( nInOutNum == 0)
nInOutNum = -1 ;
else if (nInOutNum == 1) {
else if ( nInOutNum == 1) {
bSame = false ;
break ;
}
@@ -1411,17 +1443,17 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
// se le informazioni date dalle normali dei triangoli non sono concordi valuto il triangolo più vicino
// e ricalcolo l'informazione che mi dà la sua normale
if ( ! bSame ) {
if ( ! bSame) {
Point3d ptBar_tot ;
for (int nTriaNum : vnTriaNum) {
GetTriangle( nTriaNum, trTriaA) ;
ptBar_tot += trTriaA.GetCentroid();
}
ptBar_tot /= (int)vnTriaNum.size() ;
for (int nTriaNum : vnTriaNum) {
for ( int nTriaNum : vnTriaNum) {
GetTriangle( nTriaNum, trTriaA) ;
Point3d ptInters1, ptInters2 ;
int nInters = IntersLineTria(ptFirstV, ptBar_tot, trTriaA, ptInters1, ptInters2, true) ;
int nInters = IntersLineTria( ptFirstV, ptBar_tot, trTriaA, ptInters1, ptInters2, true) ;
if (nInters == ILTT_NO)
continue ;
else if ( nInters == ILTT_IN ) {
@@ -1441,9 +1473,8 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
++ nVertNum ;
}
}
for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB) {
for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB)
SurfB.m_vTria[nTB].nTempPart = nInOutNum ;
}
}
// Se c'è stata una ritriangolazione di almeno un triangolo, NON siamo nel caso di tutto dentro o tutto fuori.
@@ -1452,12 +1483,11 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
AmbiguosTriangleManager( AmbiguosA, *this) ;
AmbiguosTriangleManager( AmbiguosB, SurfB) ;
}
bool bContinue = true ;
// Se avvenuta modifica, aggiorno tutto
if ( bModif)
bContinue = ( AdjustVertices() && DoCompacting() && SurfB.AdjustVertices() && SurfB.DoCompacting()) ;
SaveGeoObj( this, "C:\\Users\\riccardo.elitropi\\Desktop\\PocketingVolumi\\a.nge") ;
// Triangoli sovrapposti
if ( bContinue) {
int nTriaNum2A = GetTriangleSize() ;
@@ -1495,7 +1525,9 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
return true ;
}
SaveGeoObj( this, "C:\\Users\\riccardo.elitropi\\Desktop\\SurfA.nge") ;
SaveGeoObj( SurfB.Clone(), "C:\\Users\\riccardo.elitropi\\Desktop\\SurfB.nge") ;
return true ;
}
@@ -1641,6 +1673,7 @@ SurfTriMesh::Intersect( const ISurfTriMesh& Other)
if ( m_vTria[nTA].nTempPart == - 1 || m_vTria[nTA].nTempPart == - 2)
RemoveTriangle( nTA) ;
}
int nPrevMaxTFlag = m_nMaxTFlag ;
int nTriaNumB = SurfB.GetTriangleSize() ;
for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB) {