diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index fd21844..fdba162 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/SurfTriMesh.h b/SurfTriMesh.h index 27805ac..a3746bc 100644 --- a/SurfTriMesh.h +++ b/SurfTriMesh.h @@ -82,6 +82,10 @@ struct IntSegment { typedef std::vector Chain ; // Tipo vettore di Chain typedef std::vector CHAINVECTOR ; +// Tipo unordered map di Chain +typedef std::unordered_map< int, Chain> CHAINMAP ; +// Tipo unordered map di TRIA3DVECTOR +typedef std::unordered_map< int, TRIA3DVECTOR> TRIA3DVECTORMAP ; //---------------------------------------------------------------------------- // Struttura per la ricerca delle T-Junction @@ -292,6 +296,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW bool VerifyHashGrids3d( void) const ; bool VerifyConnection( void) const ; bool DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMATRIX& cvBoundClosedLoopVec, BOOLVECTOR& vbInOut) ; + bool RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Surf, bool& bModif) ; bool IntersectTriMeshTriangle( SurfTriMesh& Other) ; bool IdentifyParts( void) const ; bool RemoveTJunction( void) ; diff --git a/SurfTriMeshBooleans.cpp b/SurfTriMeshBooleans.cpp index 278393a..e4428bf 100644 --- a/SurfTriMeshBooleans.cpp +++ b/SurfTriMeshBooleans.cpp @@ -910,6 +910,421 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA return true ; } +//---------------------------------------------------------------------------- +bool +SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECTORMAP& Ambiguos, + SurfTriMesh& Surf, bool& bModif) +{ + // La superficie deve essere valida + if ( ! Surf.IsValid()) + return false ; + // Ritriangolarizzo i triangoli + for ( auto it = LoopLines.begin() ; it != LoopLines.end() ; ++ it) { + for ( int nS1 = 0 ; nS1 < int( it->second.size()) - 1 ; ++ nS1) { + 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) && + it->second[nS1].vtOuter * it->second[nS2].vtOuter < - EPS_SMALL) { + it->second.erase( it->second.begin() + nS2) ; + it->second.erase( it->second.begin() + nS1) ; + -- nS1 ; + break ; + } + } + } + + 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) ; + } + } + + // Recupero il triangolo + Triangle3d trTria ; + Surf.GetTriangle( it->first, trTria) ; + // Lo rimuovo dalla mesh + Surf.RemoveTriangle( it->first) ; + bModif = true ; + CHAINVECTOR vChain ; + // Creo i loop + ChainCurves LoopCreator ; + LoopCreator.Init( false, EPS_SMALL, int( it->second.size())) ; + // Carico le curve per concatenarle + for ( int nCv = 0 ; nCv < int( it->second.size()); ++ nCv) { + Point3d ptSt = it->second[nCv].ptSt ; + Point3d ptEn = it->second[nCv].ptEn ; + Vector3d vtDir = ptEn - ptSt ; + vtDir.Normalize() ; + LoopCreator.AddCurve( nCv + 1, ptSt, vtDir, ptEn, vtDir) ; + } + // Recupero i concatenamenti + INTVECTOR vIds ; + Point3d ptNearStart ; + while ( LoopCreator.GetChainFromNear( ptNearStart, false, vIds)) { + Chain chTemp ; + 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 + 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()) ; + vChain.pop_back() ; + -- nChainCnt ; + } + else if ( AreSamePointApprox( vChain[0].back().ptEn, vChain[nChainCnt - 1].front().ptSt)) { + vChain[0].insert( vChain[0].end(), vChain[nChainCnt - 1].begin(), vChain[nChainCnt - 1].end()) ; + vChain.pop_back() ; + -- nChainCnt ; + } + } + // 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 ; + vChain[nCh][0].vtOuter = ( vChain[nCh][0].bDegenerate ? vChain[nCh][1].vtOuter : vChain[nCh][0].vtOuter) ; + vChain[nCh][0].bDegenerate = AreSamePointApprox( vChain[nCh][0].ptSt, vChain[nCh][0].ptEn) ; + vChain[nCh].resize( 1) ; + } + } + // Elimino la seconda copia di catene doppie + for ( int nI = 0 ; nI < nChainCnt ; ++ nI) { + for ( int nJ = nI + 1 ; nJ < nChainCnt ; ++ nJ) { + if ( vChain[nI].size() == vChain[nJ].size()) { + bool bSame = true ; + for ( int nK = 0 ; nK < int( vChain[nI].size()) ; ++ nK) { + if ( ! AreSamePointApprox( vChain[nI][nK].ptSt, vChain[nJ][nK].ptSt) || + ! AreSamePointApprox( vChain[nI][nK].ptEn, vChain[nJ][nK].ptEn)) { + bSame = false ; + break ; + } + } + if ( bSame) { + vChain.erase( vChain.begin() + nJ) ; + -- nChainCnt ; + -- nJ ; + } + } + } + } + + // Fra le catene trovate separo le aperte dalle chiuse + int nDegenerateChainNum = 0 ; + INTVECTOR vnDegVec ; + CHAINVECTOR cvClosedChain ; + CHAINVECTOR cvOpenChain ; + for ( int nL = 0 ; nL < int( vChain.size()) ; ++ nL) { + bool bChainDegenerate = false ; + if ( vChain[nL].size() == 1 && AreSamePointApprox( vChain[nL][0].ptSt, vChain[nL][0].ptEn)) { + bChainDegenerate = true ; + } + + if ( bChainDegenerate) + ++ nDegenerateChainNum ; + int nCurLoopLast = max( int( vChain[nL].size()) - 1, 0) ; + if ( ( ! bChainDegenerate) && AreSamePointApprox( vChain[nL][0].ptSt, vChain[nL][nCurLoopLast].ptEn)) + cvClosedChain.emplace_back( vChain[nL]) ; + else { + cvOpenChain.emplace_back( vChain[nL]) ; + if ( bChainDegenerate) + vnDegVec.emplace_back( 0) ; + else + vnDegVec.emplace_back( 1) ; + } + } + + for ( int nCh1 = 0 ; nCh1 < int( cvOpenChain.size()) - 1 ; ++ nCh1) { + for ( int nCh2 = nCh1 + 1 ; nCh2 < int( cvOpenChain.size()) ; ++ nCh2) { + int nChainSize1 = int( cvOpenChain[nCh1].size()) ; + int nChainSize2 = int( cvOpenChain[nCh2].size()) ; + int nSameSeg = 0 ; + for ( int nSeg1 = 0 ; nSeg1 < nChainSize1 ; ++ nSeg1) { + for ( int nSeg2 = 0 ; nSeg2 < nChainSize2 ; ++ nSeg2) { + if ( AreSamePointExact( cvOpenChain[nCh1][nSeg1].ptSt, cvOpenChain[nCh2][nSeg2].ptSt) && + AreSamePointExact( cvOpenChain[nCh1][nSeg1].ptEn, cvOpenChain[nCh2][nSeg2].ptEn) && + AreSameVectorExact( cvOpenChain[nCh1][nSeg1].vtOuter, cvOpenChain[nCh2][nSeg2].vtOuter)) { + ++ nSameSeg ; + } + } + } + if ( nChainSize1 == nSameSeg) { + cvOpenChain.erase( cvOpenChain.begin() + nCh1) ; + vnDegVec.erase( vnDegVec.begin() + nCh1) ; + } + else if ( nChainSize2 == nSameSeg) { + cvOpenChain.erase( cvOpenChain.begin() + nCh2) ; + vnDegVec.erase( vnDegVec.begin() + nCh2) ; + } + } + } + + // 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; + cvBoundClosedLoopVec.emplace_back( cvFirstLoop) ; + BOOLVECTOR vbInOut ; + vbInOut.push_back( true) ; + // Divido il loop usando le catene + bool bDecomposed = DecomposeLoop( cvOpenChain, vnDegVec, cvBoundClosedLoopVec, vbInOut) ; + // Rimuovo il triangolo corrente + Surf.RemoveTriangle( it->first) ; + // Trasformo i loop compositi in loop polyline + 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) { + 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 + // loop è figlio del nodo corrispondente al loop che lo contiene. + INTVECTOR vInnerLoop ; + for ( int nCLI = 0 ; nCLI < int( cvClosedChain.size()) ; ++ nCLI) { + Point3d ptLoopStart = cvClosedChain[nCLI][0].ptSt ; + double dMinDist = DBL_MAX ; + Point3d ptMinDist ; + bool bPointOnSt = false ; + bool bPointOnEn = false ; + int nSegNum = 0 ; + int nSegMin ; + Point3d ptS, ptE ; + bool bContinueS = vplPolyVec[nLoop].GetFirstPoint( ptS) ; + bool bContinueE = vplPolyVec[nLoop].GetNextPoint( ptE) ; + while ( bContinueS && bContinueE) { + ++ nSegNum ; + DistPointLine DistCalculator( ptLoopStart, ptS, ptE) ; + double dDist ; + DistCalculator.GetDist( dDist) ; + if ( dDist < dMinDist) { + DistCalculator.GetMinDistPoint( ptMinDist) ; + bPointOnSt = AreSamePointExact( ptMinDist, ptS) ; + bPointOnEn = AreSamePointExact( ptMinDist, ptE) ; + dMinDist = dDist ; + nSegMin = nSegNum ; + } + ptS = ptE ; + bContinueS = bContinueE ; + bContinueE = vplPolyVec[nLoop].GetNextPoint( ptE) ; + } + if ( ! ( bPointOnSt || bPointOnEn)) { + vplPolyVec[nLoop].GetFirstPoint( ptS) ; + vplPolyVec[nLoop].GetNextPoint( ptE) ; + for ( int nSeg = 1 ; nSeg < nSegMin ; ++ nSeg) { + ptS = ptE ; + vplPolyVec[nLoop].GetNextPoint( ptE) ; + } + Vector3d vtTan = ptE - ptS ; + vtTan.Normalize() ; + Vector3d vtOut = vtTan ^ trTria.GetN() ; + Point3d ptMinDist ; + DistPointLine DistCalculator( ptLoopStart, ptS, ptE) ; + DistCalculator.GetMinDistPoint( ptMinDist) ; + double dMinDistDot = ( ptLoopStart - ptMinDist) * vtOut ; + if ( dMinDistDot < 0.) + vInnerLoop.emplace_back( nCLI) ; + } + else if ( bPointOnSt) { + Point3d ptPrevS, ptPrevE ; + if ( nSegMin == 1) { + vplPolyVec[nLoop].GetFirstPoint( ptS) ; + vplPolyVec[nLoop].GetNextPoint( ptE) ; + vplPolyVec[nLoop].GetLastPoint( ptPrevE) ; + vplPolyVec[nLoop].GetPrevPoint( ptPrevS) ; + } + else { + -- nSegMin ; + vplPolyVec[nLoop].GetFirstPoint( ptPrevS) ; + vplPolyVec[nLoop].GetNextPoint( ptPrevE) ; + for ( int nSeg = 1 ; nSeg < nSegMin ; ++ nSeg) { + ptPrevS = ptPrevE ; + vplPolyVec[nLoop].GetNextPoint( ptPrevE) ; + } + ptS = ptPrevE ; + vplPolyVec[nLoop].GetNextPoint( ptE) ; + } + Vector3d vtTan = ptE - ptS ; + vtTan.Normalize() ; + Vector3d vtTanPrev = ptPrevE - ptPrevS ; + vtTanPrev.Normalize() ; + Vector3d vtBisector = 0.5 * ( vtTan + vtTanPrev) ^ trTria.GetN() ; + vtBisector.Normalize() ; + double dMinDistDot = ( ptLoopStart - ptMinDist) * vtBisector ; + if ( dMinDistDot < 0.) + vInnerLoop.emplace_back( nCLI) ; + } + else if ( bPointOnEn) { + Point3d ptLast ; + vplPolyVec[nLoop].GetLastPoint( ptLast) ; + vplPolyVec[nLoop].GetFirstPoint( ptS) ; + vplPolyVec[nLoop].GetNextPoint( ptE) ; + for ( int nSeg = 1 ; nSeg < nSegMin ; ++ nSeg) { + ptS = ptE ; + vplPolyVec[nLoop].GetNextPoint( ptE) ; + } + Point3d ptNextS, ptNextE ; + if ( AreSamePointExact( ptE, ptLast)) { + vplPolyVec[nLoop].GetFirstPoint( ptNextS) ; + vplPolyVec[nLoop].GetNextPoint( ptNextE) ; + } + else { + vplPolyVec[nLoop].GetNextPoint( ptNextS) ; + vplPolyVec[nLoop].GetNextPoint( ptNextE) ; + } + Vector3d vtTan = ptE - ptS ; + vtTan.Normalize() ; + Vector3d vtTanNext = ptNextE - ptNextS ; + vtTanNext.Normalize() ; + Vector3d vtBisector = 0.5 * ( vtTan + vtTanNext) ^ trTria.GetN() ; + vtBisector.Normalize() ; + double dMinDistDot = ( ptLoopStart - ptMinDist) * vtBisector ; + if ( dMinDistDot < 0.) + vInnerLoop.emplace_back( nCLI) ; + } + } + + if ( vInnerLoop.size() == 0) { + // Eseguo triangolazione + PNTVECTOR vPt ; + INTVECTOR vTr ; + if ( Triangulate().Make( vplPolyVec[nLoop], 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) ; + if ( IsValidSvt( nNewTriaNum)) { + if ( vbInOut[nLoop]) + Surf.m_vTria[nNewTriaNum].nTempPart = 1 ; + else + Surf.m_vTria[nNewTriaNum].nTempPart = - 1 ; + bModif = true ; + } + } + } + } + else { + POLYLINEVECTOR vPolygons ; + vPolygons.emplace_back( vplPolyVec[nLoop]) ; + if ( vbInOut[nLoop]) { + for ( int nL = 0 ; nL < int( vInnerLoop.size()) ; ++ nL) { + PolyLine CurLoop ; + 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) ; + } + + PNTVECTOR vPt ; + INTVECTOR vTr ; + if ( Triangulate().Make( 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) ; + if ( IsValidSvt( nNewTriaNum)) { + Surf.m_vTria[nNewTriaNum].nTempPart = 1 ; + bModif = true ; + } + } + } + + for ( int nL = 1 ; nL < int( vPolygons.size()) ; ++ nL) { + vPolygons[nL].Invert() ; + if ( Triangulate().Make( vPolygons[nL], 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) ; + if (IsValidSvt( nNewTriaNum)) { + Surf.m_vTria[nNewTriaNum].nTempPart = - 1 ; + bModif = true ; + } + } + } + } + } + else { + for ( int nL = 0 ; nL < int( vInnerLoop.size()) ; ++ nL) { + PolyLine CurLoop ; + 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) ; + CurLoop.Invert() ; + vPolygons.emplace_back( CurLoop) ; + } + + PNTVECTOR vPt ; + INTVECTOR vTr ; + if ( Triangulate().Make( 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) ; + if ( IsValidSvt( nNewTriaNum)) { + Surf.m_vTria[nNewTriaNum].nTempPart = 1 ; + bModif = true ; + } + } + } + + for ( int nL = 1 ; nL < int( vPolygons.size()); ++ nL) { + vPolygons[nL].Invert() ; + if ( Triangulate().Make( vPolygons[nL], 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) ; + if (IsValidSvt( nNewTriaNum)) { + Surf.m_vTria[nNewTriaNum].nTempPart = - 1 ; + bModif = true ; + } + } + } + } + } + } + vInnerLoop.resize( 0) ; + } + } + return true ; +} + //---------------------------------------------------------------------------- bool SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) @@ -920,11 +1335,11 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) if ( m_nStatus != OK || ! SurfB.IsValid()) return false ; // Unordered map dei segmenti di intersezione - unordered_map< int, Chain> LineMapA ; - unordered_map< int, Chain> LineMapB ; + CHAINMAP LineMapA ; + CHAINMAP LineMapB ; // Unordered map dei triangoli ambigui (intersezione edge-edge) - unordered_map< int, TRIA3DVECTOR> AmbiguosA ; - unordered_map< int, TRIA3DVECTOR> AmbiguosB ; + TRIA3DVECTORMAP AmbiguosA ; + TRIA3DVECTORMAP AmbiguosB ; // Ciclo sui triangoli delle mesh int nTriaNumA = GetTriangleSize() ; int nTriaNumB = SurfB.GetTriangleSize() ; @@ -1070,814 +1485,10 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) } } - // Ritriangolarizzo i triangoli della superficie A - for ( auto it = LineMapA.begin() ; it != LineMapA.end() ; ++ it) { - for ( int nS1 = 0 ; nS1 < int( it->second.size()) - 1 ; ++ nS1) { - 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) && - it->second[nS1].vtOuter * it->second[nS2].vtOuter < - EPS_SMALL) { - it->second.erase( it->second.begin() + nS2) ; - it->second.erase( it->second.begin() + nS1) ; - -- nS1 ; - break ; - } - } - } - 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 itA = AmbiguosA.find( it->first) ; - if ( itA != AmbiguosA.end()) { - AmbiguosA.erase( itA) ; - } - } - - // Recupero il triangolo - Triangle3d trTriaA ; - GetTriangle( it->first, trTriaA) ; - // Lo rimuovo dalla mesh - RemoveTriangle( it->first) ; - bModif = true ; - CHAINVECTOR vChain ; - // Creo i loop - ChainCurves LoopCreator ; - LoopCreator.Init( false, EPS_SMALL, int( it->second.size())) ; - // Carico le curve per concatenarle - for ( int nCv = 0 ; nCv < int( it->second.size()) ; ++ nCv) { - Point3d ptSt = it->second[nCv].ptSt ; - Point3d ptEn = it->second[nCv].ptEn ; - Vector3d vtDir = ptEn - ptSt ; - vtDir.Normalize() ; - LoopCreator.AddCurve( nCv + 1, ptSt, vtDir, ptEn, vtDir) ; - } - // Recupero i concatenamenti - INTVECTOR vIds ; - Point3d ptNearStart ; - while ( LoopCreator.GetChainFromNear( ptNearStart, false, vIds)) { - Chain chTemp ; - 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 - 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()) ; - vChain.pop_back() ; - -- nChainCnt ; - } - else if ( AreSamePointApprox(vChain[0].back().ptEn, vChain[nChainCnt - 1].front().ptSt)) { - vChain[0].insert(vChain[0].end(), vChain[nChainCnt - 1].begin(), vChain[nChainCnt - 1].end()) ; - vChain.pop_back() ; - -- nChainCnt ; - } - } - // 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 ; - vChain[nCh][0].vtOuter = ( vChain[nCh][0].bDegenerate ? vChain[nCh][1].vtOuter : vChain[nCh][0].vtOuter) ; - vChain[nCh][0].bDegenerate = AreSamePointApprox( vChain[nCh][0].ptSt, vChain[nCh][0].ptEn) ; - vChain[nCh].resize( 1) ; - } - } - // Elimino la seconda copia di catene doppie - for ( int nI = 0 ; nI < nChainCnt ; ++ nI) { - for ( int nJ = nI + 1 ; nJ < nChainCnt ; ++ nJ) { - if ( vChain[nI].size() == vChain[nJ].size()) { - bool bSame = true ; - for ( int nK = 0 ; nK < int( vChain[nI].size()) ; ++ nK) { - if ( ! AreSamePointApprox( vChain[nI][nK].ptSt, vChain[nJ][nK].ptSt) || - ! AreSamePointApprox( vChain[nI][nK].ptEn, vChain[nJ][nK].ptEn)) { - bSame = false ; - break ; - } - } - if ( bSame) { - vChain.erase( vChain.begin() + nJ) ; - -- nChainCnt ; - -- nJ ; - } - } - } - } - - // Fra le catene trovate separo le aperte dalle chiuse - int nDegenerateChainNum = 0 ; - INTVECTOR vnDegVec ; - CHAINVECTOR cvClosedChain ; - CHAINVECTOR cvOpenChain ; - for ( int nL = 0 ; nL < int( vChain.size()) ; ++ nL) { - bool bChainDegenerate = false ; - if ( vChain[nL].size() == 1 && AreSamePointApprox( vChain[nL][0].ptSt, vChain[nL][0].ptEn)) { - bChainDegenerate = true ; - } - - if ( bChainDegenerate) - ++ nDegenerateChainNum ; - int nCurLoopLast = max( int( vChain[nL].size()) - 1, 0) ; - if ( ( ! bChainDegenerate) && AreSamePointApprox( vChain[nL][0].ptSt, vChain[nL][nCurLoopLast].ptEn)) - cvClosedChain.emplace_back( vChain[nL]) ; - else { - cvOpenChain.emplace_back( vChain[nL]) ; - if ( bChainDegenerate) - vnDegVec.emplace_back( 0) ; - else - vnDegVec.emplace_back( 1) ; - } - } - for ( int nCh1 = 0 ; nCh1 < int( cvOpenChain.size()) - 1 ; ++ nCh1) { - for ( int nCh2 = nCh1 + 1 ; nCh2 < int( cvOpenChain.size()) ; ++ nCh2) { - int nChainSize1 = int( cvOpenChain[nCh1].size()) ; - int nChainSize2 = int( cvOpenChain[nCh2].size()) ; - int nSameSeg = 0 ; - for ( int nSeg1 = 0 ; nSeg1 < nChainSize1 ; ++ nSeg1) { - for ( int nSeg2 = 0 ; nSeg2 < nChainSize2 ; ++ nSeg2) { - if ( AreSamePointExact( cvOpenChain[nCh1][nSeg1].ptSt, cvOpenChain[nCh2][nSeg2].ptSt) && - AreSamePointExact( cvOpenChain[nCh1][nSeg1].ptEn, cvOpenChain[nCh2][nSeg2].ptEn) && - AreSameVectorExact( cvOpenChain[nCh1][nSeg1].vtOuter, cvOpenChain[nCh2][nSeg2].vtOuter)) { - ++ nSameSeg ; - } - } - } - if ( nChainSize1 == nSameSeg) { - cvOpenChain.erase( cvOpenChain.begin() + nCh1) ; - vnDegVec.erase( vnDegVec.begin() + nCh1) ; - -- nCh1 ; - } - else if ( nChainSize2 == nSameSeg) { - cvOpenChain.erase( cvOpenChain.begin() + nCh2) ; - vnDegVec.erase( vnDegVec.begin() + nCh2) ; - -- nCh2 ; - } - } - } - // 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( trTriaA.GetP( 0)) ; - cvFirstLoop.emplace_back( trTriaA.GetP( 1)) ; - cvFirstLoop.emplace_back( trTriaA.GetP( 2)) ; - - PNTMATRIX cvBoundClosedLoopVec ; - cvBoundClosedLoopVec.emplace_back( cvFirstLoop) ; - BOOLVECTOR vbInOut ; - vbInOut.push_back( true) ; - - // Divido il loop usando le catene - bool bDecomposed = DecomposeLoop( cvOpenChain, vnDegVec, cvBoundClosedLoopVec, vbInOut) ; - // Trasformo i loop compositi in loop polyline - 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) { - 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 - // loop è figlio del nodo corrispondente al loop che lo contiene. - INTVECTOR vInnerLoop ; - for ( int nCLI = 0 ; nCLI < int( cvClosedChain.size()) ; ++ nCLI) { - Point3d ptLoopStart = cvClosedChain[nCLI][0].ptSt ; - double dMinDist = DBL_MAX ; - Point3d ptMinDist ; - bool bPointOnSt = false ; - bool bPointOnEn = false ; - int nSegNum = 0 ; - int nSegMin ; - Point3d ptS, ptE ; - bool bContinueS = vplPolyVec[nLoop].GetFirstPoint( ptS) ; - bool bContinueE = vplPolyVec[nLoop].GetNextPoint( ptE) ; - while ( bContinueS && bContinueE) { - ++ nSegNum ; - DistPointLine DistCalculator( ptLoopStart, ptS, ptE) ; - double dDist ; - DistCalculator.GetDist( dDist) ; - if ( dDist < dMinDist) { - DistCalculator.GetMinDistPoint( ptMinDist) ; - bPointOnSt = AreSamePointExact( ptMinDist, ptS) ; - bPointOnEn = AreSamePointExact( ptMinDist, ptE) ; - dMinDist = dDist ; - nSegMin = nSegNum ; - } - ptS = ptE ; - bContinueS = bContinueE ; - bContinueE = vplPolyVec[nLoop].GetNextPoint( ptE) ; - } - if ( ! ( bPointOnSt || bPointOnEn)) { - vplPolyVec[nLoop].GetFirstPoint( ptS) ; - vplPolyVec[nLoop].GetNextPoint( ptE) ; - for ( int nSeg = 1 ; nSeg < nSegMin ; ++ nSeg) { - ptS = ptE ; - vplPolyVec[nLoop].GetNextPoint( ptE) ; - } - Vector3d vtTan = ptE - ptS ; - vtTan.Normalize() ; - Vector3d vtOut = vtTan ^ trTriaA.GetN() ; - Point3d ptMinDist ; - DistPointLine DistCalculator( ptLoopStart, ptS, ptE) ; - DistCalculator.GetMinDistPoint( ptMinDist) ; - double dMinDistDot = ( ptLoopStart - ptMinDist) * vtOut ; - if ( dMinDistDot < 0.) - vInnerLoop.emplace_back( nCLI) ; - } - else if ( bPointOnSt) { - Point3d ptPrevS, ptPrevE ; - if ( nSegMin == 1) { - vplPolyVec[nLoop].GetFirstPoint( ptS) ; - vplPolyVec[nLoop].GetNextPoint( ptE) ; - vplPolyVec[nLoop].GetLastPoint( ptPrevE) ; - vplPolyVec[nLoop].GetPrevPoint( ptPrevS) ; - } - else { - -- nSegMin ; - vplPolyVec[nLoop].GetFirstPoint( ptPrevS) ; - vplPolyVec[nLoop].GetNextPoint( ptPrevE) ; - for ( int nSeg = 1 ; nSeg < nSegMin ; ++ nSeg) { - ptPrevS = ptPrevE ; - vplPolyVec[nLoop].GetNextPoint( ptPrevE) ; - } - ptS = ptPrevE ; - vplPolyVec[nLoop].GetNextPoint( ptE) ; - } - Vector3d vtTan = ptE - ptS ; - vtTan.Normalize() ; - Vector3d vtTanPrev = ptPrevE - ptPrevS ; - vtTanPrev.Normalize() ; - Vector3d vtBisector = 0.5 * ( vtTan + vtTanPrev) ^ trTriaA.GetN() ; - vtBisector.Normalize() ; - double dMinDistDot = ( ptLoopStart - ptMinDist) * vtBisector ; - if ( dMinDistDot < 0.) - vInnerLoop.emplace_back(nCLI) ; - } - else if ( bPointOnEn) { - Point3d ptLast ; - vplPolyVec[nLoop].GetLastPoint( ptLast) ; - vplPolyVec[nLoop].GetFirstPoint( ptS) ; - vplPolyVec[nLoop].GetNextPoint( ptE) ; - for ( int nSeg = 1 ; nSeg < nSegMin ; ++ nSeg) { - ptS = ptE ; - vplPolyVec[nLoop].GetNextPoint( ptE) ; - } - Point3d ptNextS, ptNextE ; - if ( AreSamePointExact( ptE, ptLast)) { - vplPolyVec[nLoop].GetFirstPoint( ptNextS) ; - vplPolyVec[nLoop].GetNextPoint( ptNextE) ; - } - else { - vplPolyVec[nLoop].GetNextPoint( ptNextS) ; - vplPolyVec[nLoop].GetNextPoint( ptNextE) ; - } - Vector3d vtTan = ptE - ptS ; - vtTan.Normalize() ; - Vector3d vtTanNext = ptNextE - ptNextS ; - vtTanNext.Normalize() ; - Vector3d vtBisector = 0.5 * ( vtTan + vtTanNext) ^ trTriaA.GetN() ; - vtBisector.Normalize() ; - double dMinDistDot = ( ptLoopStart - ptMinDist) * vtBisector ; - if ( dMinDistDot < 0.) - vInnerLoop.emplace_back( nCLI) ; - } - } - - if ( vInnerLoop.size() == 0) { - // Eseguo triangolazione - PNTVECTOR vPt ; - INTVECTOR vTr ; - if ( Triangulate().Make( vplPolyVec[nLoop], 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] = { AddVertex( vPt[nNewTriaVertId[0]]), - AddVertex( vPt[nNewTriaVertId[1]]), - AddVertex( vPt[nNewTriaVertId[2]]) } ; - int nNewTriaNum = AddTriangle( nNewId) ; - if ( IsValidSvt( nNewTriaNum)) { - if ( vbInOut[nLoop]) - m_vTria[nNewTriaNum].nTempPart = 1 ; - else - m_vTria[nNewTriaNum].nTempPart = - 1 ; - bModif = true ; - } - } - } - } - else { - - POLYLINEVECTOR vPolygons ; - vPolygons.emplace_back( vplPolyVec[nLoop]) ; - - for ( int nL = 0 ; nL < int( vInnerLoop.size()) ; ++ nL) { - PolyLine CurLoop ; - 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) ; - } - - Polygon3d pgPol ; - pgPol.FromPolyLine( vPolygons[1]) ; - - if ( trTriaA.GetN() * pgPol.GetVersN() > 0.) { - for ( int nL = 1 ; nL < int(vPolygons.size()) ; ++nL) { - vPolygons[nL].Invert() ; - } - - PNTVECTOR vPt ; - INTVECTOR vTr ; - if ( Triangulate().Make( 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] = { AddVertex(vPt[nNewTriaVertId[0]]), - AddVertex(vPt[nNewTriaVertId[1]]), - AddVertex(vPt[nNewTriaVertId[2]])} ; - int nNewTriaNum = AddTriangle( nNewId) ; - if ( IsValidSvt( nNewTriaNum)) { - m_vTria[nNewTriaNum].nTempPart = -1 ; - bModif = true ; - } - } - } - - for ( int nL = 1 ; nL < int(vPolygons.size()) ; ++nL) { - vPolygons[nL].Invert() ; - if ( Triangulate().Make( vPolygons[nL], 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] = { AddVertex(vPt[nNewTriaVertId[0]]), - AddVertex(vPt[nNewTriaVertId[1]]), - AddVertex(vPt[nNewTriaVertId[2]])} ; - int nNewTriaNum = AddTriangle( nNewId) ; - if ( IsValidSvt( nNewTriaNum)) { - m_vTria[nNewTriaNum].nTempPart = 1 ; - bModif = true ; - } - } - } - } - } - else { - PNTVECTOR vPt ; - INTVECTOR vTr ; - if ( Triangulate().Make( 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] = { AddVertex(vPt[nNewTriaVertId[0]]), - AddVertex(vPt[nNewTriaVertId[1]]), - AddVertex(vPt[nNewTriaVertId[2]])} ; - int nNewTriaNum = AddTriangle( nNewId) ; - if ( IsValidSvt( nNewTriaNum)) { - m_vTria[nNewTriaNum].nTempPart = 1 ; - bModif = true ; - } - } - } - - for ( int nL = 1 ; nL < int(vPolygons.size()) ; ++nL) { - vPolygons[nL].Invert() ; - if ( Triangulate().Make( vPolygons[nL], 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] = { AddVertex(vPt[nNewTriaVertId[0]]), - AddVertex(vPt[nNewTriaVertId[1]]), - AddVertex(vPt[nNewTriaVertId[2]])} ; - int nNewTriaNum = AddTriangle( nNewId) ; - if ( IsValidSvt( nNewTriaNum)) { - m_vTria[nNewTriaNum].nTempPart = -1 ; - bModif = true ; - } - } - } - } - } - } - vInnerLoop.resize( 0) ; - } - } - - // Ritriangolarizzo i triangoli della superficie B - for ( auto it = LineMapB.begin() ; it != LineMapB.end() ; ++ it) { - for ( int nS1 = 0 ; nS1 < int( it->second.size()) - 1 ; ++ nS1) { - 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) && - it->second[nS1].vtOuter * it->second[nS2].vtOuter < - EPS_SMALL) { - it->second.erase( it->second.begin() + nS2) ; - it->second.erase( it->second.begin() + nS1) ; - -- nS1 ; - break ; - } - } - } - - 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 itB = AmbiguosB.find( it->first) ; - if ( itB != AmbiguosB.end()) { - AmbiguosB.erase( itB) ; - } - } - - // Recupero il triangolo - Triangle3d trTriaB ; - SurfB.GetTriangle( it->first, trTriaB) ; - // Lo rimuovo dalla mesh - SurfB.RemoveTriangle( it->first) ; - bModif = true ; - CHAINVECTOR vChain ; - // Creo i loop - ChainCurves LoopCreator ; - LoopCreator.Init( false, EPS_SMALL, int( it->second.size())) ; - // Carico le curve per concatenarle - for ( int nCv = 0 ; nCv < int( it->second.size()) ; ++ nCv) { - Point3d ptSt = it->second[nCv].ptSt ; - Point3d ptEn = it->second[nCv].ptEn ; - Vector3d vtDir = ptEn - ptSt ; - vtDir.Normalize() ; - LoopCreator.AddCurve( nCv + 1, ptSt, vtDir, ptEn, vtDir) ; - } - // Recupero i concatenamenti - INTVECTOR vIds ; - Point3d ptNearStart ; - while ( LoopCreator.GetChainFromNear( ptNearStart, false, vIds)) { - Chain chTemp ; - 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 - 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()) ; - vChain.pop_back() ; - -- nChainCnt ; - } - else if ( AreSamePointApprox( vChain[0].back().ptEn, vChain[nChainCnt - 1].front().ptSt)) { - vChain[0].insert( vChain[0].end(), vChain[nChainCnt - 1].begin(), vChain[nChainCnt - 1].end()) ; - vChain.pop_back() ; - -- nChainCnt ; - } - } - // 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 ; - vChain[nCh][0].vtOuter = ( vChain[nCh][0].bDegenerate ? vChain[nCh][1].vtOuter : vChain[nCh][0].vtOuter) ; - vChain[nCh][0].bDegenerate = AreSamePointApprox( vChain[nCh][0].ptSt, vChain[nCh][0].ptEn) ; - vChain[nCh].resize( 1) ; - } - } - // Elimino la seconda copia di catene doppie - for ( int nI = 0 ; nI < nChainCnt ; ++ nI) { - for ( int nJ = nI + 1 ; nJ < nChainCnt ; ++ nJ) { - if ( vChain[nI].size() == vChain[nJ].size()) { - bool bSame = true ; - for ( int nK = 0 ; nK < int( vChain[nI].size()) ; ++ nK) { - if ( ! AreSamePointApprox( vChain[nI][nK].ptSt, vChain[nJ][nK].ptSt) || - ! AreSamePointApprox( vChain[nI][nK].ptEn, vChain[nJ][nK].ptEn)) { - bSame = false ; - break ; - } - } - if ( bSame) { - vChain.erase( vChain.begin() + nJ) ; - -- nChainCnt ; - -- nJ ; - } - } - } - } - - // Fra le catene trovate separo le aperte dalle chiuse - int nDegenerateChainNum = 0 ; - INTVECTOR vnDegVec ; - CHAINVECTOR cvClosedChain ; - CHAINVECTOR cvOpenChain ; - for ( int nL = 0 ; nL < int( vChain.size()) ; ++ nL) { - bool bChainDegenerate = false ; - if ( vChain[nL].size() == 1 && AreSamePointApprox( vChain[nL][0].ptSt, vChain[nL][0].ptEn)) { - bChainDegenerate = true ; - } - - if ( bChainDegenerate) - ++ nDegenerateChainNum ; - int nCurLoopLast = max( int( vChain[nL].size()) - 1, 0) ; - if ( ( ! bChainDegenerate) && AreSamePointApprox( vChain[nL][0].ptSt, vChain[nL][nCurLoopLast].ptEn)) - cvClosedChain.emplace_back( vChain[nL]) ; - else { - cvOpenChain.emplace_back( vChain[nL]) ; - if ( bChainDegenerate) - vnDegVec.emplace_back( 0) ; - else - vnDegVec.emplace_back( 1) ; - } - } - - for ( int nCh1 = 0 ; nCh1 < int( cvOpenChain.size()) - 1 ; ++ nCh1) { - for ( int nCh2 = nCh1 + 1 ; nCh2 < int( cvOpenChain.size()) ; ++ nCh2) { - int nChainSize1 = int( cvOpenChain[nCh1].size()) ; - int nChainSize2 = int( cvOpenChain[nCh2].size()) ; - int nSameSeg = 0 ; - for ( int nSeg1 = 0 ; nSeg1 < nChainSize1 ; ++ nSeg1) { - for ( int nSeg2 = 0 ; nSeg2 < nChainSize2 ; ++ nSeg2) { - if ( AreSamePointExact( cvOpenChain[nCh1][nSeg1].ptSt, cvOpenChain[nCh2][nSeg2].ptSt) && - AreSamePointExact( cvOpenChain[nCh1][nSeg1].ptEn, cvOpenChain[nCh2][nSeg2].ptEn) && - AreSameVectorExact( cvOpenChain[nCh1][nSeg1].vtOuter, cvOpenChain[nCh2][nSeg2].vtOuter)) { - ++ nSameSeg ; - } - } - } - if ( nChainSize1 == nSameSeg) { - cvOpenChain.erase( cvOpenChain.begin() + nCh1) ; - vnDegVec.erase( vnDegVec.begin() + nCh1) ; - } - else if ( nChainSize2 == nSameSeg) { - cvOpenChain.erase( cvOpenChain.begin() + nCh2) ; - vnDegVec.erase( vnDegVec.begin() + nCh2) ; - } - } - } - - // 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( trTriaB.GetP( 0)) ; - cvFirstLoop.emplace_back( trTriaB.GetP( 1)) ; - cvFirstLoop.emplace_back( trTriaB.GetP( 2)) ; - - PNTMATRIX cvBoundClosedLoopVec ; - cvBoundClosedLoopVec.emplace_back( cvFirstLoop) ; - BOOLVECTOR vbInOut ; - vbInOut.push_back( true) ; - // Divido il loop usando le catene - bool bDecomposed = DecomposeLoop( cvOpenChain, vnDegVec, cvBoundClosedLoopVec, vbInOut) ; - // Rimuovo il triangolo corrente - SurfB.RemoveTriangle( it->first) ; - // Trasformo i loop compositi in loop polyline - 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) { - 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 - // loop è figlio del nodo corrispondente al loop che lo contiene. - INTVECTOR vInnerLoop ; - for ( int nCLI = 0 ; nCLI < int( cvClosedChain.size()) ; ++ nCLI) { - Point3d ptLoopStart = cvClosedChain[nCLI][0].ptSt ; - double dMinDist = DBL_MAX ; - Point3d ptMinDist ; - bool bPointOnSt = false ; - bool bPointOnEn = false ; - int nSegNum = 0 ; - int nSegMin ; - Point3d ptS, ptE ; - bool bContinueS = vplPolyVec[nLoop].GetFirstPoint( ptS) ; - bool bContinueE = vplPolyVec[nLoop].GetNextPoint( ptE) ; - while ( bContinueS && bContinueE) { - ++ nSegNum ; - DistPointLine DistCalculator( ptLoopStart, ptS, ptE) ; - double dDist ; - DistCalculator.GetDist( dDist) ; - if ( dDist < dMinDist) { - DistCalculator.GetMinDistPoint( ptMinDist) ; - bPointOnSt = AreSamePointExact( ptMinDist, ptS) ; - bPointOnEn = AreSamePointExact( ptMinDist, ptE) ; - dMinDist = dDist ; - nSegMin = nSegNum ; - } - ptS = ptE ; - bContinueS = bContinueE ; - bContinueE = vplPolyVec[nLoop].GetNextPoint( ptE) ; - } - if ( ! ( bPointOnSt || bPointOnEn)) { - vplPolyVec[nLoop].GetFirstPoint( ptS) ; - vplPolyVec[nLoop].GetNextPoint( ptE) ; - for ( int nSeg = 1 ; nSeg < nSegMin ; ++ nSeg) { - ptS = ptE ; - vplPolyVec[nLoop].GetNextPoint( ptE) ; - } - Vector3d vtTan = ptE - ptS ; - vtTan.Normalize() ; - Vector3d vtOut = vtTan ^ trTriaB.GetN() ; - Point3d ptMinDist ; - DistPointLine DistCalculator( ptLoopStart, ptS, ptE) ; - DistCalculator.GetMinDistPoint( ptMinDist) ; - double dMinDistDot = ( ptLoopStart - ptMinDist) * vtOut ; - if ( dMinDistDot < 0.) - vInnerLoop.emplace_back( nCLI) ; - } - else if ( bPointOnSt) { - Point3d ptPrevS, ptPrevE ; - if ( nSegMin == 1) { - vplPolyVec[nLoop].GetFirstPoint( ptS) ; - vplPolyVec[nLoop].GetNextPoint( ptE) ; - vplPolyVec[nLoop].GetLastPoint( ptPrevE) ; - vplPolyVec[nLoop].GetPrevPoint( ptPrevS) ; - } - else { - -- nSegMin ; - vplPolyVec[nLoop].GetFirstPoint( ptPrevS) ; - vplPolyVec[nLoop].GetNextPoint( ptPrevE) ; - for ( int nSeg = 1 ; nSeg < nSegMin ; ++ nSeg) { - ptPrevS = ptPrevE ; - vplPolyVec[nLoop].GetNextPoint( ptPrevE) ; - } - ptS = ptPrevE ; - vplPolyVec[nLoop].GetNextPoint( ptE) ; - } - Vector3d vtTan = ptE - ptS ; - vtTan.Normalize() ; - Vector3d vtTanPrev = ptPrevE - ptPrevS ; - vtTanPrev.Normalize() ; - Vector3d vtBisector = 0.5 * ( vtTan + vtTanPrev) ^ trTriaB.GetN() ; - vtBisector.Normalize() ; - double dMinDistDot = ( ptLoopStart - ptMinDist) * vtBisector ; - if ( dMinDistDot < 0.) - vInnerLoop.emplace_back( nCLI) ; - } - else if ( bPointOnEn) { - Point3d ptLast ; - vplPolyVec[nLoop].GetLastPoint( ptLast) ; - vplPolyVec[nLoop].GetFirstPoint( ptS) ; - vplPolyVec[nLoop].GetNextPoint( ptE) ; - for ( int nSeg = 1 ; nSeg < nSegMin ; ++ nSeg) { - ptS = ptE ; - vplPolyVec[nLoop].GetNextPoint( ptE) ; - } - Point3d ptNextS, ptNextE ; - if ( AreSamePointExact( ptE, ptLast)) { - vplPolyVec[nLoop].GetFirstPoint( ptNextS) ; - vplPolyVec[nLoop].GetNextPoint( ptNextE) ; - } - else { - vplPolyVec[nLoop].GetNextPoint( ptNextS) ; - vplPolyVec[nLoop].GetNextPoint( ptNextE) ; - } - Vector3d vtTan = ptE - ptS ; - vtTan.Normalize() ; - Vector3d vtTanNext = ptNextE - ptNextS ; - vtTanNext.Normalize() ; - Vector3d vtBisector = 0.5 * ( vtTan + vtTanNext) ^ trTriaB.GetN() ; - vtBisector.Normalize() ; - double dMinDistDot = ( ptLoopStart - ptMinDist) * vtBisector ; - if ( dMinDistDot < 0.) - vInnerLoop.emplace_back( nCLI) ; - } - } - - if ( vInnerLoop.size() == 0) { - // Eseguo triangolazione - PNTVECTOR vPt ; - INTVECTOR vTr ; - if ( Triangulate().Make( vplPolyVec[nLoop], 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] = { SurfB.AddVertex(vPt[nNewTriaVertId[0]]), - SurfB.AddVertex(vPt[nNewTriaVertId[1]]), - SurfB.AddVertex(vPt[nNewTriaVertId[2]])} ; - int nNewTriaNum = SurfB.AddTriangle( nNewId) ; - if ( IsValidSvt( nNewTriaNum)) { - if ( vbInOut[nLoop]) - SurfB.m_vTria[nNewTriaNum].nTempPart = 1 ; - else - SurfB.m_vTria[nNewTriaNum].nTempPart = - 1 ; - bModif = true ; - } - } - } - } - else { - POLYLINEVECTOR vPolygons ; - vPolygons.emplace_back( vplPolyVec[nLoop]) ; - if ( vbInOut[nLoop]) { - for ( int nL = 0 ; nL < int( vInnerLoop.size()) ; ++ nL) { - PolyLine CurLoop ; - 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) ; - } - - PNTVECTOR vPt ; - INTVECTOR vTr ; - if ( Triangulate().Make( 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] = { SurfB.AddVertex(vPt[nNewTriaVertId[0]]), - SurfB.AddVertex(vPt[nNewTriaVertId[1]]), - SurfB.AddVertex(vPt[nNewTriaVertId[2]])} ; - int nNewTriaNum = SurfB.AddTriangle( nNewId) ; - if ( IsValidSvt( nNewTriaNum)) { - SurfB.m_vTria[nNewTriaNum].nTempPart = 1 ; - bModif = true ; - } - } - } - - for ( int nL = 1 ; nL < int( vPolygons.size()) ; ++ nL) { - vPolygons[nL].Invert() ; - if ( Triangulate().Make( vPolygons[nL], 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] = { SurfB.AddVertex(vPt[nNewTriaVertId[0]]), - SurfB.AddVertex(vPt[nNewTriaVertId[1]]), - SurfB.AddVertex(vPt[nNewTriaVertId[2]])} ; - int nNewTriaNum = SurfB.AddTriangle( nNewId) ; - if ( IsValidSvt( nNewTriaNum)) { - SurfB.m_vTria[nNewTriaNum].nTempPart = - 1 ; - bModif = true ; - } - } - } - } - - } - else { - for ( int nL = 0 ; nL < int( vInnerLoop.size()); ++ nL) { - PolyLine CurLoop ; - 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) ; - CurLoop.Invert() ; - vPolygons.emplace_back( CurLoop) ; - } - - PNTVECTOR vPt ; - INTVECTOR vTr ; - if ( Triangulate().Make( 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] = { SurfB.AddVertex(vPt[nNewTriaVertId[0]]), - SurfB.AddVertex(vPt[nNewTriaVertId[1]]), - SurfB.AddVertex(vPt[nNewTriaVertId[2]])} ; - int nNewTriaNum = SurfB.AddTriangle( nNewId) ; - if ( IsValidSvt( nNewTriaNum)) { - SurfB.m_vTria[nNewTriaNum].nTempPart = 1 ; - bModif = true ; - } - } - } - - for ( int nL = 1 ; nL < int( vPolygons.size()) ; ++ nL) { - vPolygons[nL].Invert() ; - if ( Triangulate().Make( vPolygons[nL], 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] = { SurfB.AddVertex(vPt[nNewTriaVertId[0]]), - SurfB.AddVertex(vPt[nNewTriaVertId[1]]), - SurfB.AddVertex(vPt[nNewTriaVertId[2]])} ; - int nNewTriaNum = SurfB.AddTriangle( nNewId) ; - if ( IsValidSvt( nNewTriaNum)) { - SurfB.m_vTria[nNewTriaNum].nTempPart = - 1 ; - bModif = true ; - } - } - } - } - } - } - vInnerLoop.resize( 0) ; - } - } - + // Ritriangolarizzo i triangoli della superfici + RetriangulationForBooleanOperation( LineMapA, AmbiguosA, *this, bModif) ; + RetriangulationForBooleanOperation( LineMapB, AmbiguosB, SurfB, bModif) ; + // Se i triangoli delle superfici non si intersecano, una delle due è totalmente interna o esterna all'altra. bool bRetriangulated = true ; if ( ! bModif) {