diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 1e80fcf..74abd8d 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/SurfTriMeshBooleans.cpp b/SurfTriMeshBooleans.cpp index c3f97eb..33ebac6 100644 --- a/SurfTriMeshBooleans.cpp +++ b/SurfTriMeshBooleans.cpp @@ -24,86 +24,106 @@ #include "/EgtDev/Include/EgkIntersLineTria.h" #include "/EgtDev/Include/EgkIntersTriaTria.h" #include "/EgtDev/Include/EGkChainCurves.h" +#include "/EgtDev/Include/EGkGeoCollection.h" #include -//---------------------------------------------------------------------------- -struct TriaInOut { - Triangle3d trTria ; - bool bTriaInside ; -} ; +using namespace std ; //---------------------------------------------------------------------------- -bool -FindRectangleTriangleIntersectionSegment(const Point3d ptP1, const Point3d ptP2, const Point3d ptP3, const Point3d ptP4, - const Triangle3d& trTria, Point3d& ptStSeg, Point3d& ptEnSeg) +// Struttura segmento di intersezione +struct IntSegment { + Point3d ptSt ; + Point3d ptEn ; + Vector3d vtOuter ; + bool bDegenerate ; +} ; +// Tipo chain +typedef vector Chain ; +// Tipo vettore di Chain +typedef vector CHAINVECTOR ; + +//---------------------------------------------------------------------------- +int +IntersRectangleTriangle( const Point3d& ptP, const Vector3d& vtL1, const Vector3d& vtL2, + const Triangle3d& trTria, Point3d& ptStSeg, Point3d& ptEnSeg) { // Definisco i due triangoli formanti il rettangolo - Triangle3d trTria1, trTria2 ; - trTria1.Set( ptP1, ptP2, ptP4) ; - trTria2.Set( ptP2, ptP3, ptP4) ; - trTria1.Validate() ; - trTria2.Validate() ; - Vector3d vtSeg = ptP2 - ptP1 ; - vtSeg.Normalize() ; - // Interseco il triangolo corrente col primo dei due triangoli del rettangolo - Point3d ptIntA1, ptIntB1 ; - TRIA3DVECTOR vTria1 ; - int nIntType1 = IntersTriaTria( trTria1, trTria, ptIntA1, ptIntB1, vTria1) ; - if ( nIntType1 == ITTT_YES) { - if ( ( ptIntB1 - ptIntA1) * vtSeg < 0.) - std::swap( ptIntA1, ptIntB1) ; - ptStSeg = ptIntA1 ; - ptEnSeg = ptIntB1 ; + Triangle3d trTriaA ; + trTriaA.Set( ptP, ptP + vtL1, ptP + vtL2) ; + if ( ! trTriaA.Validate()) + return -1 ; + Triangle3d trTriaB ; + trTriaB.Set( ptP + vtL1, ptP + vtL1 + vtL2, ptP + vtL2) ; + if ( ! trTriaB.Validate()) + return -1 ; + // Interseco il triangolo con il primo dei due triangoli del rettangolo + int nIntA = 0 ; + Point3d ptIntA1, ptIntA2 ; + TRIA3DVECTOR vTriaA ; + int nIntTypeA = IntersTriaTria( trTria, trTriaA, ptIntA1, ptIntA2, vTriaA) ; + if ( nIntTypeA == ITTT_PNT || nIntTypeA == ITTT_VERT) + nIntA = 1 ; + else if ( nIntTypeA == ITTT_YES || nIntTypeA == ITTT_EDGE) { + nIntA = 2 ; } - // Interseco il triangolo corrente con il secondo dei due triangoli del rettangolo - Point3d ptIntA2, ptIntB2 ; - TRIA3DVECTOR vTria2 ; - int nIntType2 = IntersTriaTria( trTria2, trTria, ptIntA2, ptIntB2, vTria2) ; - if ( nIntType2 == ITTT_YES) { - if ( ( ptIntB2 - ptIntA2) * vtSeg < 0.) - std::swap( ptIntA2, ptIntB2) ; - ptEnSeg = ptIntB2 ; - if ( ! ( nIntType1 == ITTT_YES)) - ptStSeg = ptIntA2 ; + // Interseco il triangolo con il secondo dei due triangoli del rettangolo + int nIntB = 0 ; + Point3d ptIntB1, ptIntB2 ; + TRIA3DVECTOR vTriaB ; + int nIntTypeB = IntersTriaTria( trTria, trTriaB, ptIntB1, ptIntB2, vTriaB) ; + if ( nIntTypeB == ITTT_PNT || nIntTypeB == ITTT_VERT) + nIntB = 1 ; + else if ( nIntTypeB == ITTT_YES || nIntTypeB == ITTT_EDGE) { + nIntB = 2 ; } - return ( nIntType1 == ITTT_YES || nIntType2 == ITTT_YES) ; -} - -//---------------------------------------------------------------------------- -bool -FindRectangleTriangleIntersectionSegment2( const Point3d ptP1, const Point3d ptP2, const Point3d ptP3, const Point3d ptP4, - const Triangle3d& trTria, Point3d& ptStSeg, Point3d& ptEnSeg) -{ - // Definisco i due triangoli formanti il rettangolo - Triangle3d trTria1, trTria2; - trTria1.Set(ptP1, ptP2, ptP4); - trTria2.Set(ptP2, ptP3, ptP4); - trTria1.Validate(); - trTria2.Validate(); - Vector3d vtSeg = ptP3 - ptP1; - vtSeg.Normalize(); - // Interseco il triangolo corrente col primo dei due triangoli del rettangolo - Point3d ptIntA1, ptIntB1; - TRIA3DVECTOR vTria1; - int nIntType1 = IntersTriaTria(trTria1, trTria, ptIntA1, ptIntB1, vTria1); - if ( nIntType1 == ITTT_YES) { - if ((ptIntB1 - ptIntA1) * vtSeg < 0.) - std::swap(ptIntA1, ptIntB1); - ptStSeg = ptIntA1; - ptEnSeg = ptIntB1; + // Unisco le due intersezioni + int nIntTot = nIntA + nIntB ; + if ( nIntTot == 4) { + if ( AreSamePointApprox( ptIntA2, ptIntB1)) { + ptStSeg = ptIntA1 ; + ptEnSeg = ptIntB2 ; + } + else { + ptStSeg = ptIntB1 ; + ptEnSeg = ptIntA2 ; + } + return 2 ; } - // Interseco il triangolo corrente con il secondo dei due triangoli del rettangolo - Point3d ptIntA2, ptIntB2; - TRIA3DVECTOR vTria2; - int nIntType2 = IntersTriaTria(trTria2, trTria, ptIntA2, ptIntB2, vTria2); - if ( nIntType2 == ITTT_YES) { - if ((ptIntB2 - ptIntA2) * vtSeg < 0.) - std::swap(ptIntA2, ptIntB2); - ptEnSeg = ptIntB2; - if ( !( nIntType1 == ITTT_YES)) - ptStSeg = ptIntA2; + else if ( nIntTot == 3) { + if ( nIntA == 2) { + ptStSeg = ptIntA1 ; + ptEnSeg = ptIntA2 ; + } + else { + ptStSeg = ptIntB1 ; + ptEnSeg = ptIntB2 ; + } + return 2 ; } - return ( nIntType1 == ITTT_YES || nIntType2 == ITTT_YES); + else if ( nIntTot == 2) { + if ( nIntA == 2) { + ptStSeg = ptIntA1 ; + ptEnSeg = ptIntA2 ; + } + else if ( nIntA == 1) { + ptStSeg = ptIntA1 ; + ptEnSeg = ptIntB1 ; + } + else { + ptStSeg = ptIntB1 ; + ptEnSeg = ptIntB2 ; + } + return 2 ; + } + else if ( nIntTot == 1) { + if ( nIntA == 1) + ptStSeg = ptIntA1 ; + else + ptStSeg = ptIntB1 ; + return 1 ; + } + else + return 0 ; } //---------------------------------------------------------------------------- @@ -113,24 +133,27 @@ SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq) // La superficie deve essere valida if ( m_nStatus != OK) return false ; - // La curva deve essere valida e chiusa; il vettore estrusione deve essere non nullo + // La curva deve essere valida e chiusa, il vettore estrusione deve essere non nullo Vector3d vtExtr ; - if ( ( ! cvCurve.GetExtrusion( vtExtr)) || ( ! cvCurve.IsClosed()) || vtExtr.IsSmall()) + if ( ! cvCurve.GetExtrusion( vtExtr) || vtExtr.IsSmall() || ! cvCurve.IsClosed()) return false ; // Approssimo la curva con segmenti - PolyLine plLine ; - cvCurve.ApproxWithLines( LIN_TOL_FINE, ANG_TOL_STD_DEG, ICurve::APL_STD, plLine) ; + CurveComposite cvCompo ; + PolyLine PL ; + if ( ! cvCurve.ApproxWithLines( LIN_TOL_FINE, ANG_TOL_STD_DEG, ICurve::APL_STD, PL) || ! cvCompo.FromPolyLine( PL)) + return false ; // Appiattisco la polilinea nel piano perpendicolare all'estrusione Frame3d frCurve ; - Point3d ptStart ; cvCurve.GetStartPoint( ptStart) ; + Point3d ptStart ; cvCompo.GetStartPoint( ptStart) ; frCurve.Set( ptStart, vtExtr) ; - plLine.ToLoc( frCurve) ; - plLine.Flatten() ; + cvCompo.ToLoc( frCurve) ; + if ( ! cvCompo.Scale( GLOB_FRM, 1, 1, 0)) + return false ; double dArea ; - plLine.GetAreaXY( dArea) ; + cvCompo.GetAreaXY( dArea) ; BBox3d b3Crv ; - plLine.GetLocalBBox( b3Crv) ; - plLine.ToGlob( frCurve) ; + cvCompo.GetLocalBBox( b3Crv) ; + cvCompo.ToGlob( frCurve) ; // Assegno il senso di rotazione della curva (visto dalla punta del vettore estrusione) bool bCCW = ( dArea > 0) ; // Recupero Bounding-box della trimesh @@ -142,167 +165,196 @@ SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq) b3SurfBox.GetMinMax( ptMin, ptMax) ; Vector3d vtMax = ( ptMax.z + 10) * vtExtr ; Vector3d vtMin = ( ptMin.z - 10) * vtExtr ; + // Ciclo sui triangoli bool bModif = false ; int nNumTria = GetTriangleSize() ; for ( int nT = 0 ; nT < nNumTria ; ++ nT) { // Recupero il triangolo Triangle3d trTria ; - GetTriangle( nT, trTria) ; + if ( ! GetTriangle( nT, trTria)) + continue ; + // Ne calcolo una copia proiettata sul piano della curva + // Box del triangolo nel riferimento locale della curva BBox3d b3Tria ; trTria.GetLocalBBox( b3Tria) ; b3Tria.ToLoc( frCurve) ; - // Se il box del triangolo non interseca quello della curva + // Se il box del triangolo non interseca quello locale della curva if ( ! b3Crv.OverlapsXY( b3Tria)) { + // Se la parte da conservare è quella all'interno della curva, elimino il triangolo if ( bCCW) { RemoveTriangle( nT) ; bModif = true ; } continue ; } - // Determino il numero di vertici che cadono nella curva + // Determino il numero di vertici del triangolo che cadono all'interno della curva int nVertInside = 0 ; - // Ciclo sui vertici del triangolo for ( int nV = 0 ; nV < 3 ; ++ nV) { - // Vertice del triangolo e sua proiezione sul piano della curva - Point3d ptVert ; - if ( ! GetVertex( m_vTria[nT].nIdVert[nV], ptVert)) - continue ; - double dDistVertPlane = ( ptVert - ptStart) * vtExtr ; - Point3d ptVertOnPlane = ptVert - dDistVertPlane * vtExtr ; - // Ciclo sui segmenti della curva, per determinare se la proiezione sulla curva di almeno un vertice - // del triangolo è all'interno del loop oppure un punto della curva, spostandosi lungo una - // retta parallela al versore di estrusione, interseca il triangolo. - double dSqDistVertCurve = DBL_MAX ; - Point3d ptStMin, ptEnMin ; - Point3d ptSt, ptEn ; - bool bContinue = plLine.GetFirstLine( ptSt, ptEn) ; - while ( bContinue) { - CurveLine cvLine ; - cvLine.Set( ptSt, ptEn) ; - // Calcolo della distanza del vertice proiettato sul piano della curva - // dal segmento corrente - DistPointLine dCurDistCalc( ptVertOnPlane, cvLine) ; - double dCurSqDist ; - // Se tale distanza è minore della minima distanza attuale, la aggiorno insieme con gli estremi - // del segmento a distanza minima - if ( dCurDistCalc.GetSqDist( dCurSqDist) && dCurSqDist < dSqDistVertCurve) { - dSqDistVertCurve = dCurSqDist ; - ptStMin = ptSt ; - ptEnMin = ptEn ; - } - bContinue = plLine.GetNextLine( ptSt, ptEn) ; - } - // Direzione del segmento a minima distanza dal vertice corrente proiettato sul piano della curva - Vector3d vtTan = ptEnMin - ptStMin ; - vtTan.Normalize() ; - // Se punto proiettato nella curva aumentiamo il numero di punti interni - if ( ( ptVertOnPlane - ptStMin) * ( vtTan ^ vtExtr) < EPS_SMALL) + // Determino se il vertice cade dentro la curva + DistPointCurve dstPC( trTria.GetP( nV), cvCompo) ; + int nSide ; + dstPC.GetSideAtMinDistPoint( 0, vtExtr, nSide) ; + if ( nSide == MDS_LEFT || nSide == MDS_ON) ++ nVertInside ; } - - // Casi in cui l'orientamento della curva stabilisce la parti interne ed esterne del triangolo - if ( abs( trTria.GetN() * vtExtr) > EPS_ZERO) { - // Vettore di segmenti - std::vector vLine ; - // Ciclo sui segmenti - Point3d ptSt, ptEn ; - bool bContinue = plLine.GetFirstLine( ptSt, ptEn) ; - while ( bContinue) { - Point3d ptSegSt, ptSegEn ; - // C'è interferenza fra il rettangolo, ottenuto dall'estrusione del segmento corrente, e il triangolo - if ( FindRectangleTriangleIntersectionSegment( ptSt + vtMin, ptEn + vtMin, ptEn + vtMax, ptSt + vtMax, - trTria, ptSegSt, ptSegEn)) { - // Costruisco il tratto di curva - CurveLine cvLine ; - if ( cvLine.Set( ptSegSt, ptSegEn)) - vLine.emplace_back( cvLine) ; + // Vettore di catene di punti + CHAINVECTOR vChain ; + // Ciclo sui segmenti + bool bStartInside = false ; + int nChainCnt = 0 ; + bool bChain = false ; + Point3d ptChSt, ptChEn ; + const ICurve* pCrv = cvCompo.GetFirstCurve() ; + while ( pCrv != nullptr) { + // estremi del segmento + Point3d ptSt ; pCrv->GetStartPoint( ptSt) ; + Point3d ptEn ; pCrv->GetEndPoint( ptEn) ; + // Intersezione fra il rettangolo (ottenuto dall'estrusione del segmento corrente) e il triangolo + Point3d ptSegSt, ptSegEn ; + int nInt = IntersRectangleTriangle( ptSt + vtMin, ptEn - ptSt, vtMax - vtMin, trTria, ptSegSt, ptSegEn) ; + if ( nInt != 0) { + // Creo nuova catena se non c'è già o se discontinuità + if ( ! bChain || ( ! AreSamePointApprox( ptSegSt, ptChEn) && ! AreSamePointApprox( ptSegEn, ptChSt))) { + ++ nChainCnt ; + vChain.resize( nChainCnt) ; + bChain = false ; } - bContinue = plLine.GetNextLine( ptSt, ptEn) ; + // Assegno i dati di intersezione + IntSegment CurInters ; + if ( nInt == 2) { + CurInters.ptSt = ptSegSt ; + CurInters.ptEn = ptSegEn ; + CurInters.bDegenerate = false ; + } + else { + CurInters.ptSt = ptSegSt ; + CurInters.ptEn = ptSegSt ; + CurInters.bDegenerate = true ; + } + CurInters.vtOuter = ( ptEn - ptSt) ^ vtExtr ; + CurInters.vtOuter.Normalize() ; + // Inserisco nella catena + if ( ! bChain) { + vChain[nChainCnt - 1].emplace_back( CurInters) ; + ptChSt = CurInters.ptSt ; + ptChEn = CurInters.ptEn ; + } + else if ( AreSamePointApprox( ptSegSt, ptChEn)) { + vChain[nChainCnt - 1].emplace_back( CurInters) ; + ptChEn = CurInters.ptEn ; + } + else { + vChain[nChainCnt - 1].insert( vChain[nChainCnt - 1].begin(), CurInters) ; + ptChSt = CurInters.ptSt ; + } + bChain = true ; } - // Creo i loop - ChainCurves LoopCreator ; - LoopCreator.Init( false, EPS_SMALL, int( vLine.size())) ; - // Carico le curve per concatenarle - for ( int nCv = 0 ; nCv < int( vLine.size()) ; ++ nCv) { - Point3d ptSt = vLine[nCv].GetStart() ; - Point3d ptEn = vLine[nCv].GetEnd() ; - Vector3d vtDir; vLine[nCv].GetStartDir( vtDir) ; - LoopCreator.AddCurve( nCv + 1, ptSt, vtDir, ptEn, vtDir) ; + else { + bChain = false ; } - // Recupero i concatenamenti - INTVECTOR vIds ; - Point3d ptNearStart ; - std::vector cvLoopVec ; - while ( LoopCreator.GetChainFromNear( ptNearStart, false, vIds)) { - CurveComposite cvLoop ; - for ( auto i : vIds) { - // Aggiungo la linea alla curva composta. - if ( ! cvLoop.AddCurve( vLine[i - 1], true, 10 * EPS_SMALL)) - return false ; - } - cvLoop.MergeCurves( 10 * EPS_SMALL, ANG_TOL_STD_DEG) ; - cvLoopVec.emplace_back( cvLoop) ; + pCrv = cvCompo.GetNextCurve() ; + } + // 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 ; } - - // Fra i loop trovati separo gli aperti dai chiusi - std::vector cvInnerClosedLoopVec ; - std::vector cvOpenLoopVec ; - for ( int nL = 0 ; nL < int( cvLoopVec.size()) ; ++ nL) { - if ( cvLoopVec[nL].IsClosed()) - cvInnerClosedLoopVec.emplace_back( cvLoopVec[nL]) ; + 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 - cvOpenLoopVec.emplace_back( cvLoopVec[nL]) ; + vnDegVec.emplace_back( 1) ; } - - // Se contemporaneamente c'è almeno un loop chiuso e almeno uno aperto, - // oppure c'è più di un loop chiuso, vi è un errore. - if ( ( cvInnerClosedLoopVec.size() > 0 && cvOpenLoopVec.size() > 0.) || - cvInnerClosedLoopVec.size() > 1) - return false ; - // Se c'è un loop chiuso - if ( cvInnerClosedLoopVec.size() == 1) { - // Passo da curva composita a PolyLine - PolyLine plInnerLoop ; - const ICurve* pCv = cvInnerClosedLoopVec[0].GetFirstCurve() ; - while ( pCv != nullptr) { - // Estremi del segmento corrente del loop chiuso corrente - Point3d ptSegSt, ptSegEn ; - pCv->GetStartPoint( ptSegSt) ; - pCv->GetEndPoint( ptSegEn) ; - plInnerLoop.AddUPoint( 0., ptSegSt) ; - plInnerLoop.AddUPoint( 0., ptSegEn) ; - pCv = cvInnerClosedLoopVec[0].GetNextCurve() ; - } - // Se necessario inverto il loop trovato - if ( trTria.GetN() * vtExtr < - EPS_ZERO) - plInnerLoop.Invert() ; - // Tre vertici dentro la curva - if ( nVertInside == 3) { - // Accedo agli indici del triangolo - int nTriaVertId[3] ; - GetTriangle( nT, nTriaVertId) ; - PolyLine plExternalLoop ; - Point3d ptTriaVert0, ptTriaVert1, ptTriaVert2 ; - GetVertex( nTriaVertId[0], ptTriaVert0) ; - GetVertex( nTriaVertId[1], ptTriaVert1) ; - GetVertex( nTriaVertId[2], ptTriaVert2) ; - // Rimuovo il triangolo corrente - RemoveTriangle( nT) ; - plExternalLoop.AddUPoint( 0., ptTriaVert0) ; - plExternalLoop.AddUPoint( 0., ptTriaVert1) ; - plExternalLoop.AddUPoint( 0., ptTriaVert2) ; - plExternalLoop.AddUPoint( 0., ptTriaVert0) ; - // Poligonalizzo il loop - Triangulate CreateTriangulation ; - PNTVECTOR vPt ; - INTVECTOR vTr ; - POLYLINEVECTOR vPL ; - vPL.emplace_back( plExternalLoop) ; - vPL.emplace_back( plInnerLoop) ; - CreateTriangulation.Make( vPL, vPt, vTr) ; - // Aggiungo i triangoli + } + + // Se più di una catena chiusa oppure catene chiuse e aperte, errore + if ( cvClosedChain.size() > 1 || + ( cvClosedChain.size() > 0 && int( cvOpenChain.size()) > nDegenerateChainNum)) + return false ; + + // Se c'è una catena chiusa + if ( cvClosedChain.size() == 1) { + // Ne ricavo una PolyLine + PolyLine plInLoop ; + for ( int nLine = 0 ; nLine < int( cvClosedChain[0].size()) ; ++ nLine) { + plInLoop.AddUPoint( 0., cvClosedChain[0][nLine].ptSt) ; + plInLoop.AddUPoint( 0., cvClosedChain[0][nLine].ptEn) ; + } + // I tre vertici sono dalla parte interna della curva (triangolo con buco) + if ( ! bCCW) { + // Rimuovo il triangolo corrente + RemoveTriangle( nT) ; + // Definisco il loop esterno (è il triangolo) + PolyLine plExtLoop ; + plExtLoop.AddUPoint( 0., trTria.GetP( 0)) ; + plExtLoop.AddUPoint( 0., trTria.GetP( 1)) ; + plExtLoop.AddUPoint( 0., trTria.GetP( 2)) ; + plExtLoop.AddUPoint( 0., trTria.GetP( 0)) ; + // Eseguo triangolazione + POLYLINEVECTOR vPL ; + vPL.emplace_back( plExtLoop) ; + vPL.emplace_back( plInLoop) ; + PNTVECTOR vPt ; + INTVECTOR vTr ; + if ( Triangulate().Make( vPL, 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]]), @@ -312,16 +364,16 @@ SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq) bModif = true ; } } - // Se nessun vertice dentro (Con un loop chiuso o ci sono tre vertici dentro alla curva o nessuno) - else { - // Rimuovo il triangolo corrente - RemoveTriangle( nT) ; - // Poligonalizzo il loop - Triangulate CreateTriangulation ; - PNTVECTOR vPt ; - INTVECTOR vTr ; - CreateTriangulation.Make( plInnerLoop, vPt, vTr) ; - // Aggiungo i triangoli + } + // Se nessun vertice dalla parte interna della curva (rimane solo l'area della curva) + else { + // Rimuovo il triangolo corrente + RemoveTriangle( nT) ; + // Eseguo triangolazione + PNTVECTOR vPt ; + INTVECTOR vTr ; + if ( Triangulate().Make( plInLoop, 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]]), @@ -332,575 +384,443 @@ SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq) } } } - // Loop aperti, devo chiuderli - else if ( cvOpenLoopVec.size() > 0) { - // 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. - std::vector cvBoundClosedLoopVec ; - CurveComposite cvFirstLoop ; - CurveLine cvEdge ; - cvEdge.Set( trTria.GetP( 0), trTria.GetP( 1)) ; - cvFirstLoop.AddCurve( cvEdge, true, 10 * EPS_SMALL) ; - cvEdge.Set( trTria.GetP( 1), trTria.GetP( 2)) ; - cvFirstLoop.AddCurve( cvEdge, true, 10 * EPS_SMALL) ; - cvEdge.Set( trTria.GetP( 2), trTria.GetP( 0)) ; - cvFirstLoop.AddCurve( cvEdge, true, 10 * EPS_SMALL) ; - cvBoundClosedLoopVec.emplace_back( cvFirstLoop) ; - std::vector vbInOut ; - vbInOut.push_back( true) ; - // Divido il loop di partenza in sotto-loop - while ( cvOpenLoopVec.size() > 0) { - int nLastOpenLoopN = int( cvOpenLoopVec.size()) - 1 ; - for ( int nL = 0 ; nL < int( cvBoundClosedLoopVec.size()) ; ++ nL) { + } + + // Loop aperti, devo chiuderli + else if ( cvOpenChain.size() > 0) { + + // 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( 1)) ; + cvFirstLoop.emplace_back( trTria.GetP( 2)) ; + cvFirstLoop.emplace_back( trTria.GetP( 2)) ; + cvFirstLoop.emplace_back( trTria.GetP( 0)) ; + + vector cvBoundClosedLoopVec ; + cvBoundClosedLoopVec.emplace_back(cvFirstLoop); + vector vbInOut ; + vbInOut.push_back( true) ; + // Divido il loop di partenza in sotto-loop + while ( cvOpenChain.size() > 0) { + int nLastOpenLoopN = int( cvOpenChain.size()) - 1 ; + if ( vnDegVec[nLastOpenLoopN] == 1) { + + for ( int nLoop = 0 ; nLoop < int( cvBoundClosedLoopVec.size()) ; ++ nLoop) { // Estremi del loop aperto - Point3d ptOpenLoopStP, ptOpenLoopEnP ; - cvOpenLoopVec[nLastOpenLoopN].GetStartPoint( ptOpenLoopStP) ; - cvOpenLoopVec[nLastOpenLoopN].GetEndPoint( ptOpenLoopEnP) ; + int nLastOpenLoopPoint = max( int( cvOpenChain[nLastOpenLoopN].size()) - 1, 0) ; + Point3d ptOpenLoopStP = cvOpenChain[nLastOpenLoopN][0].ptSt ; + Point3d ptOpenLoopEnP = cvOpenChain[nLastOpenLoopN][nLastOpenLoopPoint].ptEn ; // Cerco se esistono dei tratti del loop chiuso corrente che sono - // toccati dagli estremi del loop aperto corrente - const ICurve* pCvSt = nullptr ; - const ICurve* pCvEn = nullptr ; - const ICurve* pCv = cvBoundClosedLoopVec[nL].GetFirstCurve() ; - while ( pCv != nullptr && ( pCvSt == nullptr || pCvEn == nullptr)) { - // Estremi del segmento corrente del loop chiuso corrente - Point3d ptSegSt, ptSegEn ; - pCv->GetStartPoint( ptSegSt) ; - pCv->GetEndPoint( ptSegEn) ; - // Vedo se gli estremi del loop aperto stanno su un segmento del chiuso + // toccati dagli estremi del loop aperto corrente + int nCvSt = -1 ; + int nCvEn = -1 ; + for ( int nLine = 0 ; nLine < int( cvBoundClosedLoopVec[nLoop].size()) - 1 && ( nCvSt == -1 || nCvEn == -1) ; nLine += 2) { + // Estremi del segmento corrente del loop chiuso corrente + Point3d ptSegSt = cvBoundClosedLoopVec[nLoop][nLine] ; + Point3d ptSegEn = cvBoundClosedLoopVec[nLoop][nLine + 1] ; + // Vedo se gli estremi del loop aperto stanno su un segmento del chiuso DistPointLine dStDistCalc( ptOpenLoopStP, ptSegSt, ptSegEn) ; DistPointLine dEnDistCalc( ptOpenLoopEnP, ptSegSt, ptSegEn) ; double dSqDistSt ; - dStDistCalc.GetSqDist( dSqDistSt) ; - if ( SqDist( ptOpenLoopStP, ptSegSt) < EPS_SMALL * EPS_SMALL || - SqDist( ptOpenLoopStP, ptSegEn) < EPS_SMALL * EPS_SMALL) - dSqDistSt = 1. ; - if ( dSqDistSt < EPS_SMALL * EPS_SMALL) - pCvSt = pCv ; + dStDistCalc.GetSqDist(dSqDistSt) ; + if ( dSqDistSt < SQ_EPS_SMALL) { + nCvSt = nLine ; + } double dSqDistEn ; - dEnDistCalc.GetSqDist( dSqDistEn) ; - if ( SqDist( ptOpenLoopEnP, ptSegSt) < EPS_SMALL * EPS_SMALL || - SqDist( ptOpenLoopEnP, ptSegEn) < EPS_SMALL * EPS_SMALL) - dSqDistEn = 1. ; - if ( dSqDistEn < EPS_SMALL * EPS_SMALL) - pCvEn = pCv ; - pCv = cvBoundClosedLoopVec[nL].GetNextCurve() ; + dEnDistCalc.GetSqDist(dSqDistEn) ; + if ( dSqDistEn < SQ_EPS_SMALL) { + nCvEn = nLine ; + } } // Se entrambi gli estremi del loop aperto sono su un segmento del loop chiuso devo dividere il loop in due - if ( pCvSt != nullptr && pCvEn != nullptr) { + if ( nCvSt != - 1 && nCvEn != - 1) { // Entrambi gli estremi del loop aperto sono su uno stesso segmento del loop chiuso - if ( pCvSt == pCvEn) { + if ( nCvSt == nCvEn) { bool bFirstInside ; bool bFirstSt ; - CurveComposite cvSplitLoop1, cvSplitLoop2 ; - // Creo primo loop - pCv = cvBoundClosedLoopVec[nL].GetFirstCurve() ; - while ( pCv != nullptr) { + PNTVECTOR cvSplitLoop1, cvSplitLoop2 ; + // Creo primo loop + for ( int nLine = 0 ; nLine < int( cvBoundClosedLoopVec[nLoop].size()) - 1 ; nLine += 2) { // Segmenti loop chiuso - if ( pCv != pCvSt && pCv != pCvEn) { - Point3d ptSegSt, ptSegEn ; - pCv->GetStartPoint( ptSegSt) ; - pCv->GetEndPoint( ptSegEn) ; - CurveLine cvSeg ; - cvSeg.Set( ptSegSt, ptSegEn) ; - cvSplitLoop1.AddCurve( cvSeg) ; + if ( nLine != nCvSt && nLine != nCvEn) { + cvSplitLoop1.emplace_back( cvBoundClosedLoopVec[nLoop][nLine]) ; + cvSplitLoop1.emplace_back( cvBoundClosedLoopVec[nLoop][nLine+1]) ; } // Dal chiuso all'aperto - else if ( pCv == pCvSt) { + else if ( nLine == nCvSt) { // Distanze degli estremi del loop aperto dal punto iniziale del segmento corrente Point3d ptSegSt, ptSegEn ; - pCv->GetStartPoint( ptSegSt) ; + ptSegSt = cvBoundClosedLoopVec[nLoop][nLine] ; double dDistStSt = SqDist( ptSegSt, ptOpenLoopStP) ; double dDistStEn = SqDist( ptSegSt, ptOpenLoopEnP) ; // Devo percorrere il loop aperto nel suo verso if ( dDistStSt < dDistStEn) { // Dall'inizio del segmento corrente fino all'inizio del loop aperto - ptSegEn = ptOpenLoopStP ; - CurveLine cvSeg ; - cvSeg.Set( ptSegSt, ptSegEn) ; - cvSplitLoop1.AddCurve( cvSeg) ; - // Loop aperto - const ICurve* pOpenStart = cvOpenLoopVec[nLastOpenLoopN].GetFirstCurve() ; - const ICurve* pOpen = pOpenStart ; - while ( pOpen != nullptr) { - Point3d ptOpenSt, ptOpenEn ; - pOpen->GetStartPoint( ptOpenSt) ; - pOpen->GetEndPoint( ptOpenEn) ; - CurveLine cvOpenSeg ; - cvOpenSeg.Set( ptOpenSt, ptOpenEn) ; - cvSplitLoop1.AddCurve( cvOpenSeg) ; - if ( pOpen == pOpenStart) { + ptSegEn = ptOpenLoopStP ; + cvSplitLoop1.emplace_back( ptSegSt) ; + cvSplitLoop1.emplace_back( ptSegEn) ; + // Loop aperto + for ( int nOpenLine = 0 ; nOpenLine < int( cvOpenChain[nLastOpenLoopN].size()) ; ++ nOpenLine) { + Point3d ptOpenSt = cvOpenChain[nLastOpenLoopN][nOpenLine].ptSt ; + Point3d ptOpenEn = cvOpenChain[nLastOpenLoopN][nOpenLine].ptEn ; + cvSplitLoop1.emplace_back( ptOpenSt) ; + cvSplitLoop1.emplace_back( ptOpenEn) ; + if ( nOpenLine == 0) { Vector3d vtLast = ptSegSt - ptSegEn ; - vtLast.Normalize() ; - Vector3d vtFirst = ptOpenEn - ptOpenSt ; - vtFirst.Normalize() ; - bFirstInside = vtLast * ( vtFirst ^ vtExtr) < 0. ; + vtLast.Normalize() ; + bFirstInside = vtLast * cvOpenChain[nLastOpenLoopN][nOpenLine].vtOuter < 0. ; } - pOpen = cvOpenLoopVec[nLastOpenLoopN].GetNextCurve() ; } // Dalla fine del loop aperto alla fine del segmento corrente ptSegSt = ptOpenLoopEnP ; - pCv->GetEndPoint( ptSegEn) ; - cvSeg ; - cvSeg.Set( ptSegSt, ptSegEn) ; - cvSplitLoop1.AddCurve( cvSeg) ; + ptSegEn = cvBoundClosedLoopVec[nLoop][nLine+1] ; + cvSplitLoop1.emplace_back( ptSegSt) ; + cvSplitLoop1.emplace_back( ptSegEn) ; bFirstSt = true ; } // Devo percorrere il loop aperto contro il suo verso else { // Dall'inizio del segmento corrente fino alla fine del loop aperto - ptSegEn = ptOpenLoopEnP ; - CurveLine cvSeg ; - cvSeg.Set( ptSegSt, ptSegEn) ; - cvSplitLoop1.AddCurve( cvSeg) ; - // Loop aperto - const ICurve* pOpenLast = cvOpenLoopVec[nLastOpenLoopN].GetLastCurve() ; - const ICurve* pOpen = pOpenLast ; - while ( pOpen != nullptr) { - Point3d ptOpenSt, ptOpenEn ; - pOpen->GetStartPoint( ptOpenSt) ; - pOpen->GetEndPoint( ptOpenEn) ; - CurveLine cvOpenSeg ; - cvOpenSeg.Set( ptOpenEn, ptOpenSt) ; - cvSplitLoop1.AddCurve( cvOpenSeg) ; - if ( pOpen == pOpenLast) { + ptSegEn = ptOpenLoopEnP ; + cvSplitLoop1.emplace_back( ptSegSt) ; + cvSplitLoop1.emplace_back( ptSegEn) ; + // Loop aperto + for ( int nOpenLine = int( cvOpenChain[nLastOpenLoopN].size()) - 1 ; nOpenLine >= 0 ; -- nOpenLine) { + Point3d ptOpenSt = cvOpenChain[nLastOpenLoopN][nOpenLine].ptEn ; + Point3d ptOpenEn = cvOpenChain[nLastOpenLoopN][nOpenLine].ptSt ; + cvSplitLoop1.emplace_back( ptOpenSt) ; + cvSplitLoop1.emplace_back( ptOpenEn) ; + if ( nOpenLine == int( cvOpenChain[nLastOpenLoopN].size()) - 1) { Vector3d vtLast = ptSegSt - ptSegEn ; - vtLast.Normalize() ; - Vector3d vtFirst = ptOpenEn - ptOpenSt ; - vtFirst.Normalize() ; - bFirstInside = vtLast * ( vtFirst ^ vtExtr) < 0. ; + vtLast.Normalize() ; + bFirstInside = vtLast * cvOpenChain[nLastOpenLoopN][nOpenLine].vtOuter < 0. ; } - pOpen = cvOpenLoopVec[nLastOpenLoopN].GetPrevCurve() ; } // Dall'inizio del loop aperto fino alla fine del segmento corrente ptSegSt = ptOpenLoopStP ; - pCv->GetEndPoint( ptSegEn) ; - cvSeg ; - cvSeg.Set( ptSegSt, ptSegEn) ; - cvSplitLoop1.AddCurve( cvSeg) ; + ptSegEn = cvBoundClosedLoopVec[nLoop][nLine+1] ; + cvSplitLoop1.emplace_back( ptSegSt) ; + cvSplitLoop1.emplace_back( ptSegEn) ; bFirstSt = false ; } - } - pCv = cvBoundClosedLoopVec[nL].GetNextCurve() ; + } } // Creo secondo loop if ( bFirstSt) { - // Tratto segmento ove cadono gli estremi del loop aperto - CurveLine cvSeg ; - cvSeg.Set( ptOpenLoopStP, ptOpenLoopEnP) ; - cvSplitLoop2.AddCurve( cvSeg) ; - // Loop aperto - const ICurve* pOpen = cvOpenLoopVec[nLastOpenLoopN].GetLastCurve(); - while (pOpen != nullptr) { - Point3d ptOpenSt, ptOpenEn; - pOpen->GetStartPoint(ptOpenSt); - pOpen->GetEndPoint(ptOpenEn); - CurveLine cvOpenSeg; - cvOpenSeg.Set(ptOpenEn, ptOpenSt); - cvSplitLoop2.AddCurve(cvOpenSeg); - pOpen = cvOpenLoopVec[nLastOpenLoopN].GetPrevCurve(); + // Tratto segmento ove cadono gli estremi del loop aperto + cvSplitLoop2.emplace_back( ptOpenLoopStP) ; + cvSplitLoop2.emplace_back( ptOpenLoopEnP) ; + // Loop aperto + for ( int nOpenLine = int( cvOpenChain[nLastOpenLoopN].size()) - 1 ; nOpenLine >= 0 ; -- nOpenLine) { + Point3d ptOpenSt = cvOpenChain[nLastOpenLoopN][nOpenLine].ptEn ; + Point3d ptOpenEn = cvOpenChain[nLastOpenLoopN][nOpenLine].ptSt ; + cvSplitLoop2.emplace_back( ptOpenSt) ; + cvSplitLoop2.emplace_back( ptOpenEn) ; } } else { - // Tratto segmento ove cadono gli estremi del loop aperto - CurveLine cvSeg ; - cvSeg.Set( ptOpenLoopEnP, ptOpenLoopStP) ; - cvSplitLoop2.AddCurve( cvSeg) ; - // Loop aperto - const ICurve* pOpen = cvOpenLoopVec[nLastOpenLoopN].GetFirstCurve() ; - while ( pOpen != nullptr) { - Point3d ptOpenSt, ptOpenEn ; - pOpen->GetStartPoint( ptOpenSt) ; - pOpen->GetEndPoint( ptOpenEn) ; - CurveLine cvOpenSeg ; - cvOpenSeg.Set( ptOpenSt, ptOpenEn) ; - cvSplitLoop2.AddCurve( cvOpenSeg); - pOpen = cvOpenLoopVec[nLastOpenLoopN].GetNextCurve() ; + // Tratto segmento ove cadono gli estremi del loop aperto + cvSplitLoop2.emplace_back( ptOpenLoopEnP) ; + cvSplitLoop2.emplace_back( ptOpenLoopStP) ; + // Loop aperto + for ( int nOpenLine = 0 ; nOpenLine < int( cvOpenChain[nLastOpenLoopN].size()) ; ++ nOpenLine) { + Point3d ptOpenSt = cvOpenChain[nLastOpenLoopN][nOpenLine].ptSt ; + Point3d ptOpenEn = cvOpenChain[nLastOpenLoopN][nOpenLine].ptEn ; + cvSplitLoop2.emplace_back( ptOpenSt) ; + cvSplitLoop2.emplace_back( ptOpenEn) ; } } - // Aggiungo i nuovi loop nel vettore - cvBoundClosedLoopVec[nL] = cvSplitLoop1 ; - cvBoundClosedLoopVec.emplace_back( cvSplitLoop2) ; - vbInOut[nL] = bFirstInside ; - vbInOut.push_back( ! bFirstInside) ; + // Aggiungo i nuovi loop nel vettore + int nCurSize = int(cvBoundClosedLoopVec.size()); + cvBoundClosedLoopVec.resize(nCurSize + 1); + vbInOut.resize(nCurSize + 1); + for (int nCL = nCurSize - 1; nCL > nLoop; --nCL) { + cvBoundClosedLoopVec[nCL + 1] = cvBoundClosedLoopVec[nCL]; + vbInOut[nCL + 1] = vbInOut[nCL]; + } + cvBoundClosedLoopVec[nLoop] = cvSplitLoop1 ; + cvBoundClosedLoopVec[nLoop + 1] = cvSplitLoop2; + vbInOut[nLoop] = bFirstInside; + vbInOut[nLoop + 1] = !bFirstInside; + ++ nLoop ; } // Estremi dell'aperto su due diversi segmenti del chiuso else { bool bFirstInside ; bool bFirstSt ; - CurveComposite cvSplitLoop1, cvSplitLoop2 ; - // Creo primo loop - pCv = cvBoundClosedLoopVec[nL].GetFirstCurve() ; - while ( pCv != nullptr) { + PNTVECTOR cvSplitLoop1, cvSplitLoop2 ; + for ( int nLine = 0 ; nLine < int( cvBoundClosedLoopVec[nLoop].size()) - 1 ; nLine += 2) { // Segmento su cui non incide nessun estremo del loop aperto - if ( pCv != pCvSt && pCv != pCvEn) { - Point3d ptSegSt, ptSegEn ; - pCv->GetStartPoint( ptSegSt) ; - pCv->GetEndPoint( ptSegEn) ; - CurveLine cvSeg ; - cvSeg.Set( ptSegSt, ptSegEn) ; - cvSplitLoop1.AddCurve( cvSeg) ; + if ( nLine != nCvSt && nLine != nCvEn) { + cvSplitLoop1.emplace_back( cvBoundClosedLoopVec[nLoop][nLine]) ; + cvSplitLoop1.emplace_back( cvBoundClosedLoopVec[nLoop][nLine + 1]) ; } // Segmento su cui incide l'estremo iniziale del loop aperto - else if ( pCv == pCvSt) { + else if ( nLine == nCvSt) { // Dall'inizio del segmento corrente fino all'inizio del loop aperto - Point3d ptSegSt ; - pCv->GetStartPoint( ptSegSt) ; - CurveLine cvSeg ; - cvSeg.Set( ptSegSt, ptOpenLoopStP) ; - cvSplitLoop1.AddCurve( cvSeg) ; - // Loop aperto - const ICurve* pOpenFirst = cvOpenLoopVec[nLastOpenLoopN].GetFirstCurve(); - const ICurve* pOpen = pOpenFirst ; - while ( pOpen != nullptr) { + Point3d ptSegSt = cvBoundClosedLoopVec[nLoop][nLine] ; + Point3d ptSegEn = ptOpenLoopStP ; + cvSplitLoop1.emplace_back( ptSegSt) ; + cvSplitLoop1.emplace_back( ptSegEn) ; + // Loop aperto + for ( int nOpenLine = 0 ; nOpenLine < int( cvOpenChain[nLastOpenLoopN].size()) ; ++ nOpenLine) { // Valuto se cvSplitLoop1 è interno o esterno - Point3d ptOpenSt, ptOpenEn ; - pOpen->GetStartPoint( ptOpenSt) ; - pOpen->GetEndPoint( ptOpenEn) ; - CurveLine cvOpenSeg ; - cvOpenSeg.Set( ptOpenSt, ptOpenEn) ; - cvSplitLoop1.AddCurve( cvOpenSeg) ; - if ( pOpen == pOpenFirst) { + Point3d ptOpenSt = cvOpenChain[nLastOpenLoopN][nOpenLine].ptSt ; + Point3d ptOpenEn = cvOpenChain[nLastOpenLoopN][nOpenLine].ptEn ; + cvSplitLoop1.emplace_back( ptOpenSt) ; + cvSplitLoop1.emplace_back( ptOpenEn) ; + if ( nOpenLine == 0) { Vector3d vtLast = ptSegSt - ptOpenLoopStP ; - vtLast.Normalize() ; - Vector3d vtFirst = ptOpenEn - ptOpenSt ; - vtFirst.Normalize() ; - bFirstInside = vtLast * ( vtFirst ^ vtExtr) < 0. ; + if ( vtLast.Normalize()) { + bFirstInside = vtLast * cvOpenChain[nLastOpenLoopN][nOpenLine].vtOuter < 0. ; + } + else { + vtLast = cvBoundClosedLoopVec[nLoop][nLine + 1] - ptOpenLoopStP ; + vtLast.Normalize() ; + bFirstInside = vtLast * cvOpenChain[nLastOpenLoopN][nOpenLine].vtOuter > 0. ; + } } - pOpen = cvOpenLoopVec[nLastOpenLoopN].GetNextCurve() ; } // Dalla fine del loop aperto fino alla fine del segmento ove arriva il loop aperto - while ( pCv != pCvEn) - pCv = cvBoundClosedLoopVec[nL].GetNextCurve() ; - Point3d ptSegEn ; - pCv->GetEndPoint( ptSegEn) ; - cvSeg ; - cvSeg.Set( ptOpenLoopEnP, ptSegEn) ; - cvSplitLoop1.AddCurve( cvSeg) ; + nLine = nCvEn ; + ptSegEn = cvBoundClosedLoopVec[nLoop][nLine+1] ; + cvSplitLoop1.emplace_back( ptOpenLoopEnP) ; + cvSplitLoop1.emplace_back( ptSegEn) ; bFirstSt = true ; } // Segmento su cui incide l'estremo finale del loop aperto else { // Dall'inizio del segmento corrente fino alla fine del loop aperto - Point3d ptSegSt ; - pCv->GetStartPoint( ptSegSt) ; - CurveLine cvSeg ; - cvSeg.Set( ptSegSt, ptOpenLoopEnP) ; - cvSplitLoop1.AddCurve( cvSeg) ; - // Loop aperto - const ICurve* pOpenLast = cvOpenLoopVec[nLastOpenLoopN].GetLastCurve() ; - const ICurve* pOpen = pOpenLast ; - while ( pOpen != nullptr) { - Point3d ptOpenSt , ptOpenEn ; - pOpen->GetStartPoint( ptOpenSt) ; - pOpen->GetEndPoint( ptOpenEn) ; - CurveLine cvOpenSeg ; - cvOpenSeg.Set( ptOpenEn, ptOpenSt) ; - cvSplitLoop1.AddCurve( cvOpenSeg) ; - if ( pOpen == pOpenLast) { + Point3d ptSegSt = cvBoundClosedLoopVec[nLoop][nLine] ; + cvSplitLoop1.emplace_back( ptSegSt) ; + cvSplitLoop1.emplace_back( ptOpenLoopEnP) ; + // Loop aperto + for ( int nOpenLine = int( cvOpenChain[nLastOpenLoopN].size()) - 1 ; nOpenLine >= 0 ; -- nOpenLine) { + Point3d ptOpenSt = cvOpenChain[nLastOpenLoopN][nOpenLine].ptEn ; + Point3d ptOpenEn = cvOpenChain[nLastOpenLoopN][nOpenLine].ptSt ; + cvSplitLoop1.emplace_back( ptOpenSt) ; + cvSplitLoop1.emplace_back( ptOpenEn) ; + if ( nOpenLine == int( cvOpenChain[nLastOpenLoopN].size()) - 1) { Vector3d vtLast = ptSegSt - ptOpenLoopEnP ; - vtLast.Normalize() ; - Vector3d vtFirst = ptOpenEn - ptOpenSt ; - vtFirst.Normalize() ; - bFirstInside = vtLast * ( vtFirst ^ vtExtr) < 0. ; + if ( vtLast.Normalize()) { + bFirstInside = vtLast * cvOpenChain[nLastOpenLoopN][nOpenLine].vtOuter < 0. ; + } + else { + bFirstInside = vtLast * cvOpenChain[nLastOpenLoopN][nOpenLine].vtOuter > 0. ; + } } - pOpen = cvOpenLoopVec[nLastOpenLoopN].GetPrevCurve() ; } - // Dalla fine del loop aperto fino alla fine del segmento ove arriva il loop aperto - while ( pCv != pCvSt) - pCv = cvBoundClosedLoopVec[nL].GetNextCurve() ; - Point3d ptSegEn ; - pCv->GetEndPoint( ptSegEn) ; - cvSeg.Set( ptOpenLoopStP, ptSegEn) ; - cvSplitLoop1.AddCurve( cvSeg) ; - bFirstSt = false ; + // Dalla fine del loop aperto fino alla fine del segmento ove arriva il loop aperto + nLine = nCvSt ; + Point3d ptSegEn = cvBoundClosedLoopVec[nLoop][nLine + 1] ; + cvSplitLoop1.emplace_back( ptOpenLoopStP) ; + cvSplitLoop1.emplace_back( ptSegEn) ; + bFirstSt = false; } - pCv = cvBoundClosedLoopVec[nL].GetNextCurve() ; } // Creo secondo loop - if ( bFirstSt) { - // Individuo il segmento ove incide l'estremo iniziale del loop aperto - pCv = cvBoundClosedLoopVec[nL].GetFirstCurve() ; - while ( pCv != pCvSt) - pCv = cvBoundClosedLoopVec[nL].GetNextCurve() ; - // Dall'estremo finale del loop aperto alla fine del segmento su cui giace + if ( bFirstSt) { + // Dall'estremo inizinale del loop aperto alla fine del segmento su cui giace Point3d ptSegSt, ptSegEn ; ptSegSt = ptOpenLoopStP ; - pCv->GetEndPoint( ptSegEn) ; - CurveLine cvSeg ; - cvSeg.Set( ptSegSt, ptSegEn) ; - cvSplitLoop2.AddCurve( cvSeg) ; - // Loop chiuso fino a segmento ove cade l'estremo finale dell'aperto - const ICurve* pCvStop = pCvEn ; - pCv = cvBoundClosedLoopVec[nL].GetNextCurve() ; - if ( pCv == nullptr) - pCv = cvBoundClosedLoopVec[nL].GetFirstCurve() ; - while ( pCv != pCvStop) { - if ( pCv == nullptr) - pCv = cvBoundClosedLoopVec[nL].GetFirstCurve() ; - pCv->GetStartPoint( ptSegSt) ; - pCv->GetEndPoint( ptSegEn) ; - CurveLine cvSeg ; - cvSeg.Set( ptSegSt, ptSegEn) ; - cvSplitLoop2.AddCurve( cvSeg) ; - pCv = cvBoundClosedLoopVec[nL].GetNextCurve() ; + ptSegEn = cvBoundClosedLoopVec[nLoop][nCvSt+1] ; + cvSplitLoop2.emplace_back( ptSegSt) ; + cvSplitLoop2.emplace_back( ptSegEn) ; + // Loop chiuso fino a segmento ove cade l'estremo finale dell'aperto + for (int nLine = (nCvSt + 2) % int(cvBoundClosedLoopVec[nLoop].size()); nLine != nCvEn; nLine += 2) { + ptSegSt = cvBoundClosedLoopVec[nLoop][nLine % int(cvBoundClosedLoopVec[nLoop].size())]; + ptSegEn = cvBoundClosedLoopVec[nLoop][(nLine + 1) % int(cvBoundClosedLoopVec[nLoop].size())]; + cvSplitLoop2.emplace_back(ptSegSt); + cvSplitLoop2.emplace_back(ptSegEn); } // Dall'inizio del segmento del loop chiuso ove cade l'estremo finale del loop aperto // a quest'ultimo - pCv->GetStartPoint( ptSegSt) ; + ptSegSt = cvBoundClosedLoopVec[nLoop][nCvEn] ; ptSegEn = ptOpenLoopEnP ; - cvSeg.Set( ptSegSt, ptOpenLoopEnP) ; - cvSplitLoop2.AddCurve( cvSeg) ; - // Loop aperto - const ICurve* pOpen = cvOpenLoopVec[nLastOpenLoopN].GetLastCurve() ; - while ( pOpen != nullptr) { - Point3d ptOpenSt, ptOpenEn ; - pOpen->GetStartPoint( ptOpenSt) ; - pOpen->GetEndPoint( ptOpenEn) ; - CurveLine cvOpenSeg ; - cvOpenSeg.Set( ptOpenEn, ptOpenSt) ; - cvSplitLoop2.AddCurve( cvOpenSeg) ; - pOpen = cvOpenLoopVec[nLastOpenLoopN].GetPrevCurve() ; + cvSplitLoop2.emplace_back( ptSegSt) ; + cvSplitLoop2.emplace_back( ptSegEn) ; + // Loop aperto + for ( int nOpenLine = int( cvOpenChain[nLastOpenLoopN].size()) - 1 ; nOpenLine >= 0 ; -- nOpenLine) { + Point3d ptOpenSt = cvOpenChain[nLastOpenLoopN][nOpenLine].ptEn ; + Point3d ptOpenEn = cvOpenChain[nLastOpenLoopN][nOpenLine].ptSt ; + cvSplitLoop2.emplace_back( ptOpenSt) ; + cvSplitLoop2.emplace_back( ptOpenEn) ; } } - else { - // Individuo il segmento ove incide l'estremo finale del loop aperto - pCv = cvBoundClosedLoopVec[nL].GetFirstCurve() ; - while ( pCv != pCvEn) - pCv = cvBoundClosedLoopVec[nL].GetNextCurve() ; + else { // Dall'estremo finale del loop aperto alla fine del segmento su cui giace - Point3d ptSegSt, ptSegEn ; - ptSegSt = ptOpenLoopEnP ; - pCv->GetEndPoint( ptSegEn) ; - CurveLine cvSeg ; - cvSeg.Set( ptSegSt, ptSegEn) ; - cvSplitLoop2.AddCurve( cvSeg) ; - // Loop chiuso fino al segmento ove cade l'inizio del loop aperto - const ICurve* pCvStop = pCvSt ; - pCv = cvBoundClosedLoopVec[nL].GetNextCurve() ; - if ( pCv == nullptr) - pCv = cvBoundClosedLoopVec[nL].GetFirstCurve() ; - while ( pCv != pCvStop) { - if ( pCv == nullptr) - pCv = cvBoundClosedLoopVec[nL].GetFirstCurve() ; - pCv->GetStartPoint( ptSegSt) ; - pCv->GetEndPoint( ptSegEn) ; - CurveLine cvSeg ; - cvSeg.Set( ptSegSt, ptSegEn) ; - cvSplitLoop2.AddCurve( cvSeg) ; - pCv = cvBoundClosedLoopVec[nL].GetNextCurve() ; + Point3d ptSegSt = ptOpenLoopEnP ; + Point3d ptSegEn = cvBoundClosedLoopVec[nLoop][nCvEn+1] ; + cvSplitLoop2.emplace_back( ptSegSt) ; + cvSplitLoop2.emplace_back( ptSegEn) ; + // Loop chiuso fino al segmento ove cade l'inizio del loop aperto + for (int nLine = (nCvEn + 2) % int(cvBoundClosedLoopVec[nLoop].size()); nLine != nCvSt; nLine += 2) { + ptSegSt = cvBoundClosedLoopVec[nLoop][nLine % int(cvBoundClosedLoopVec[nLoop].size())]; + ptSegEn = cvBoundClosedLoopVec[nLoop][(nLine + 1) % int(cvBoundClosedLoopVec[nLoop].size())]; + cvSplitLoop2.emplace_back(ptSegSt); + cvSplitLoop2.emplace_back(ptSegEn); } // Dall'inizio del segmento del loop chiuso ove cade l'estremo iniziale del loop aperto - // a quest'ultimo - pCv->GetStartPoint( ptSegSt) ; - ptSegEn = ptOpenLoopStP ; - cvSeg.Set( ptSegSt, ptOpenLoopStP) ; - cvSplitLoop2.AddCurve( cvSeg) ; - // Loop aperto - const ICurve* pOpen = cvOpenLoopVec[nLastOpenLoopN].GetFirstCurve() ; - while ( pOpen != nullptr) { - Point3d ptOpenSt, ptOpenEn ; - pOpen->GetStartPoint( ptOpenSt); - pOpen->GetEndPoint( ptOpenEn); - CurveLine cvOpenSeg ; - cvOpenSeg.Set( ptOpenSt, ptOpenEn) ; - cvSplitLoop2.AddCurve( cvOpenSeg) ; - pOpen = cvOpenLoopVec[nLastOpenLoopN].GetNextCurve() ; + // a quest'ultimo + ptSegSt = cvBoundClosedLoopVec[nLoop][nCvSt] ; + ptSegEn = ptOpenLoopStP ; + cvSplitLoop2.emplace_back( ptSegSt) ; + cvSplitLoop2.emplace_back( ptSegEn) ; + // Loop aperto + for ( int nOpenLoop = 0 ; nOpenLoop < int( cvOpenChain[nLastOpenLoopN].size()) ; ++ nOpenLoop) { + Point3d ptOpenSt = cvOpenChain[nLastOpenLoopN][nOpenLoop].ptSt ; + Point3d ptOpenEn = cvOpenChain[nLastOpenLoopN][nOpenLoop].ptEn ; + cvSplitLoop2.emplace_back( ptOpenSt) ; + cvSplitLoop2.emplace_back( ptOpenEn) ; } } // Aggiungo i nuovi loop nel vettore - cvBoundClosedLoopVec[nL] = cvSplitLoop1 ; - cvBoundClosedLoopVec.emplace_back( cvSplitLoop2) ; - vbInOut[nL] = bFirstInside ; - vbInOut.push_back( ! bFirstInside) ; + int nCurSize = int( cvBoundClosedLoopVec.size()) ; + cvBoundClosedLoopVec.resize( nCurSize + 1) ; + vbInOut.resize( nCurSize + 1) ; + for ( int nCL = nCurSize - 1 ; nCL > nLoop ; -- nCL) { + cvBoundClosedLoopVec[nCL + 1] = cvBoundClosedLoopVec[nCL] ; + vbInOut[nCL + 1] = vbInOut[nCL] ; + } + cvBoundClosedLoopVec[nLoop] = cvSplitLoop1 ; + cvBoundClosedLoopVec[nLoop + 1] = cvSplitLoop2 ; + vbInOut[nLoop] = bFirstInside ; + vbInOut[nLoop + 1] = ! bFirstInside ; + ++ nLoop ; + } + } + } + } + // Degenere + else { + Point3d ptProva = 0.5 * ( cvOpenChain[nLastOpenLoopN][0].ptSt + cvOpenChain[nLastOpenLoopN][0].ptEn) ; + Vector3d vtVecProva = cvOpenChain[nLastOpenLoopN][0].vtOuter ; + vtVecProva.Normalize( EPS_ZERO) ; + for ( int nLoop = 0 ; nLoop < int( cvBoundClosedLoopVec.size()) ; ++ nLoop) { + // Estremi del loop aperto + int nLastOpenLoopPoint = max(int(cvOpenChain[nLastOpenLoopN].size()) - 1, 0) ; + Point3d ptOpenLoopStP = cvOpenChain[nLastOpenLoopN][0].ptSt ; + Point3d ptOpenLoopEnP = cvOpenChain[nLastOpenLoopN][0].ptEn ; + // Cerco se esistono dei tratti del loop chiuso corrente che sono + // toccati dagli estremi del loop aperto corrente + int nCvFirst = -1 ; + int nCvSecond = -1 ; + for ( int nLine = 0 ; nLine < int( cvBoundClosedLoopVec[nLoop].size()) - 1 && nCvSecond == -1 ; nLine += 2) { + // Estremi del segmento corrente del loop chiuso corrente + Point3d ptSegSt = cvBoundClosedLoopVec[nLoop][nLine] ; + Point3d ptSegEn = cvBoundClosedLoopVec[nLoop][nLine + 1] ; + // Vettore congiungente i su definiti punti + Vector3d vtClosedLoopSeg = ptSegEn - ptSegSt ; + vtClosedLoopSeg.Normalize() ; + // Vedo se gli estremi del loop aperto stanno su un segmento del chiuso + DistPointLine DistCalc( ptProva, ptSegSt, ptSegEn) ; + double dSqDist ; + DistCalc.GetSqDist( dSqDist) ; + if ( dSqDist < 2 * SQ_EPS_SMALL) { + if ( nCvFirst == -1) + nCvFirst = nLine ; + else + nCvSecond = nLine ; } } - } - cvOpenLoopVec.resize( nLastOpenLoopN) ; - } - RemoveTriangle( nT) ; - // Trasformo i loop compositi in loop polyline - std::vector vplPolyVec ; - vplPolyVec.resize( cvBoundClosedLoopVec.size()) ; - for ( int nL = 0 ; nL < int( vplPolyVec.size()) ; ++ nL) { - const ICurve* pCv = cvBoundClosedLoopVec[nL].GetFirstCurve() ; - while ( pCv != nullptr) { - // Estremi del segmento corrente del loop chiuso corrente - Point3d ptSegSt, ptSegEn ; - pCv->GetStartPoint( ptSegSt) ; - pCv->GetEndPoint( ptSegEn) ; - vplPolyVec[nL].AddUPoint( 0., ptSegSt) ; - vplPolyVec[nL].AddUPoint( 0., ptSegEn) ; - pCv = cvBoundClosedLoopVec[nL].GetNextCurve() ; - } - if ( vbInOut[nL]) { - // Poligonalizzo il loop - Triangulate CreateTriangulation ; - PNTVECTOR vPt ; - INTVECTOR vTr ; - CreateTriangulation.Make( vplPolyVec[nL], vPt, vTr) ; - // Aggiungo i 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]]) } ; - AddTriangle( nNewId) ; - bModif = true ; + if ( nCvFirst != nCvSecond && nCvSecond != -1) { + // li ordino in senso crescente + if ( nCvFirst > nCvSecond) + swap( nCvFirst, nCvSecond) ; + // punto medio tra primo e secondo + int nCount = 0 ; + Point3d ptM12 ; + for ( int i = nCvFirst + 1 ; i < nCvSecond ; i += 2) { + ptM12 += cvBoundClosedLoopVec[nLoop][i] ; + ++ nCount ; + } + ptM12 /= nCount ; + // verifico se questo punto è dalla parte valida o no + bool bC12 = ( ( ptM12 - ptProva) * vtVecProva < 0) ; + // numero totale di punti + int nPntTot = int( cvBoundClosedLoopVec[nLoop].size()) ; + // elimino i punti dalla parte non valida + if ( bC12) { + // assegno i nuovi valori + cvBoundClosedLoopVec[nLoop][nCvFirst] = ptProva ; + cvBoundClosedLoopVec[nLoop][nCvSecond+1] = ptProva ; + // elimino i punti superflui dopo + for ( int i = nPntTot - 1 ; i > nCvSecond+1 ; -- i) + cvBoundClosedLoopVec[nLoop].pop_back() ; + // elimino i punti superflui prima + for ( int i = 0 ; i < nCvFirst ; ++ i) + cvBoundClosedLoopVec[nLoop].erase( cvBoundClosedLoopVec[nLoop].begin()) ; + } + else { + // assegno i nuovi valori + cvBoundClosedLoopVec[nLoop][nCvFirst+1] = ptProva ; + cvBoundClosedLoopVec[nLoop][nCvSecond] = ptProva ; + // elimino i punti superflui intermedi + for ( int i = nCvFirst+2 ; i < nCvSecond ; ++ i) + cvBoundClosedLoopVec[nLoop].erase( cvBoundClosedLoopVec[nLoop].begin()+nCvFirst+2) ; + } + vbInOut[nLoop] = true ; + + // PNTVECTOR cvSplitLoop; + // for (int nLine = 0; nLine < nCvFirst; nLine += 2) { + // cvSplitLoop.emplace_back(cvBoundClosedLoopVec[nLoop][nLine]); + // cvSplitLoop.emplace_back(cvBoundClosedLoopVec[nLoop][nLine + 1]); + // } + // cvSplitLoop.emplace_back(cvBoundClosedLoopVec[nLoop][nCvFirst]); + // cvSplitLoop.emplace_back(ptProva); + // cvSplitLoop.emplace_back(ptProva); + // cvSplitLoop.emplace_back(cvBoundClosedLoopVec[nLoop][nCvSecond + 1]); + // for (int nLine = nCvSecond + 2; nLine < int(cvBoundClosedLoopVec[nLoop].size()) - 1; nLine += 2) { + // cvSplitLoop.emplace_back(cvBoundClosedLoopVec[nLoop][nLine]); + // cvSplitLoop.emplace_back(cvBoundClosedLoopVec[nLoop][nLine + 1]); + // } + // cvBoundClosedLoopVec[nLoop] = cvSplitLoop; + // if ((cvBoundClosedLoopVec[nLoop][nCvFirst] - ptProva) * vtVecProva < 0.) + // vbInOut[nLoop] = true; + // else + // vbInOut[nLoop] = false; } } } + vnDegVec.resize( nLastOpenLoopN) ; + cvOpenChain.resize( nLastOpenLoopN) ; } - else if ( nVertInside == 0) - RemoveTriangle( nT) ; - } - // L'orientamento del loop non stabilise i vertici dentro e fuori - else { - std::vector vTriaVec ; - TriaInOut trStartTria ; - trStartTria.trTria = trTria ; - trStartTria.bTriaInside = true ; - vTriaVec.emplace_back( trStartTria) ; - vTriaVec.resize( 1) ; - // Ciclo sui segmenti - Point3d ptSt, ptEn ; - bool bContinue = plLine.GetFirstLine( ptSt, ptEn) ; - while ( bContinue) { - for ( int nTr = 0 ; nTr < int( vTriaVec.size()) ; ++ nTr) { - Point3d ptSegSt, ptSegEn ; - // C'è interferenza fra il rettangolo, ottenuto dall'estrusione del segmento corrente, e il triangolo - if ( FindRectangleTriangleIntersectionSegment2( ptSt + vtMin, ptEn + vtMin, ptEn + vtMax, ptSt + vtMax, - vTriaVec[nTr].trTria, ptSegSt, ptSegEn)) { - // Stabilisco su quali lati del triangolo cadono gli estremi del segmento intersezione - int nStEdge = -1 ; - int nEnEdge = -1 ; - for ( int nV = 0 ; nV < 3 ; ++ nV) { - int nW = (nV + 1) % 3 ; - Point3d ptVertV = vTriaVec[nTr].trTria.GetP( nV) ; - Point3d ptVertW = vTriaVec[nTr].trTria.GetP( nW) ; - DistPointLine dStDistCalc( ptSegSt, ptVertV, ptVertW) ; - DistPointLine dEnDistCalc( ptSegEn, ptVertV, ptVertW) ; - double dSqDistSt ; - dStDistCalc.GetSqDist( dSqDistSt) ; - if ( dSqDistSt < EPS_SMALL * EPS_SMALL) - nStEdge = nV ; - double dSqDistEn ; - dEnDistCalc.GetSqDist( dSqDistEn) ; - if ( dSqDistEn < EPS_SMALL * EPS_SMALL) - nEnEdge = nV ; - } - int nMinInd, nMaxInd ; - Point3d ptMin, ptMax ; - if ( nStEdge < nEnEdge) { - nMinInd = nStEdge ; - nMaxInd = nEnEdge ; - ptMin = ptSegSt ; - ptMax = ptSegEn ; - } - else { - nMinInd = nEnEdge ; - nMaxInd = nStEdge ; - ptMin = ptSegEn ; - ptMax = ptSegSt ; - } - TriaInOut trSingleTria ; - PolyLine plInnerLoop ; - bool bLoopInside ; - if ( nMaxInd == ( nMinInd + 1) % 3) { - trSingleTria.trTria.SetP( 0, ptMin) ; - trSingleTria.trTria.SetP( 1, vTriaVec[nTr].trTria.GetP( ( nMinInd + 1) % 3)) ; - trSingleTria.trTria.SetP( 2, ptMax) ; - Vector3d vtTan = ptEn - ptSt ; - vtTan.Normalize() ; - if ( ( trSingleTria.trTria.GetP(1) - trSingleTria.trTria.GetP(0)) * ( vtTan ^ vtExtr) < 0.) - trSingleTria.bTriaInside = true ; - else - trSingleTria.bTriaInside = false ; - trSingleTria.trTria.Validate( true) ; - plInnerLoop.AddUPoint( 0., ptMin) ; - plInnerLoop.AddUPoint( 0., ptMax) ; - plInnerLoop.AddUPoint( 0., vTriaVec[nTr].trTria.GetP( ( nMinInd + 2) % 3)) ; - plInnerLoop.AddUPoint( 0., vTriaVec[nTr].trTria.GetP( nMinInd)) ; - plInnerLoop.AddUPoint( 0., ptMin) ; - if ( ( vTriaVec[nTr].trTria.GetP( nMinInd) - ptMin) * ( vtTan ^ vtExtr) < 0.) - bLoopInside = true ; - else - bLoopInside = false ; - } - else { - trSingleTria.trTria.SetP( 0, ptMin) ; - trSingleTria.trTria.SetP( 1, ptMax) ; - trSingleTria.trTria.SetP( 2, vTriaVec[nTr].trTria.GetP( nMinInd)) ; - Vector3d vtTan = ptEn - ptSt ; - vtTan.Normalize() ; - if ( ( trSingleTria.trTria.GetP( 2) - trSingleTria.trTria.GetP( 0)) * ( vtTan ^ vtExtr) < 0.) - trSingleTria.bTriaInside = true ; - else - trSingleTria.bTriaInside = false ; - trSingleTria.trTria.Validate( true) ; - plInnerLoop.AddUPoint( 0., ptMin) ; - plInnerLoop.AddUPoint( 0., vTriaVec[nTr].trTria.GetP( ( nMinInd + 1) % 3)) ; - plInnerLoop.AddUPoint( 0., vTriaVec[nTr].trTria.GetP( ( nMinInd + 2) % 3)) ; - plInnerLoop.AddUPoint( 0., ptMax) ; - plInnerLoop.AddUPoint( 0., ptMin) ; - if ( ( vTriaVec[nTr].trTria.GetP( ( nMinInd + 1) % 3) - ptMin) * ( vtTan ^ vtExtr) < 0.) - bLoopInside = true ; - else - bLoopInside = false ; - } - // Poligonalizzo il loop - Triangulate CreateTriangulation ; - PNTVECTOR vPt ; - INTVECTOR vTr ; - CreateTriangulation.Make( plInnerLoop, vPt, vTr) ; - // Aggiungo i triangoli al vettore - int nOldSize = int( vTriaVec.size()) ; - int nAddSize = int( vTr.size() / 3) ; - vTriaVec.resize( nOldSize + nAddSize) ; - for ( int m = nOldSize - 1 ; m > nTr ; -- m) { - vTriaVec[m + nAddSize] = vTriaVec[m] ; - } - vTriaVec[nTr] = trSingleTria ; - for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) { - int nNewTriaVertId[3] = { vTr[n], vTr[n + 1], vTr[n + 2] } ; - TriaInOut trNewTria ; - trNewTria.trTria.SetP( 0, vPt[nNewTriaVertId[0]]) ; - trNewTria.trTria.SetP( 1, vPt[nNewTriaVertId[1]]) ; - trNewTria.trTria.SetP( 2, vPt[nNewTriaVertId[2]]) ; - trNewTria.trTria.Validate( true) ; - trNewTria.bTriaInside = bLoopInside ; - vTriaVec[nTr + 1 + (n / 3)] = trNewTria ; - } - -- nTr ; - } - } - bContinue = plLine.GetNextLine( ptSt, ptEn) ; - } - // Se non sono state trovate intersezioni col triangolo - if ( vTriaVec.size() == 1) { - // Se almeno un punto interno (sotto l'ipotesi di nessuna intersezione - // equivale a tre punti interni) deve essere conservato così com'è. - if ( nVertInside > 0) - continue ; - // Altrimenti il triangolo deve essere eliminato - else { - RemoveTriangle( nT) ; - continue ; - } - } + // Rimuovo il triangolo corrente RemoveTriangle( nT) ; - bModif = true ; - // Aggiungo i triangoli alla trimesh - for ( int n = 0 ; n < int( vTriaVec.size()) ; ++ n) { - if ( vTriaVec[n].bTriaInside) { - int nNewId[3] = { AddVertex(vTriaVec[n].trTria.GetP( 0)), - AddVertex(vTriaVec[n].trTria.GetP( 1)), - AddVertex(vTriaVec[n].trTria.GetP( 2)) } ; - AddTriangle( nNewId) ; + // 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()) - 1 ; nLine += 2) { + vplPolyVec[nLoop].AddUPoint( 0., cvBoundClosedLoopVec[nLoop][nLine]) ; + vplPolyVec[nLoop].AddUPoint( 0., cvBoundClosedLoopVec[nLoop][nLine + 1]) ; } - } + if ( vbInOut[nLoop]) { + // Eseguo triangolazione + Triangulate CreateTriangulation ; + 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]]) } ; + AddTriangle( nNewId) ; + bModif = true ; + } + } + } + } } + else if ( nVertInside == 0) + RemoveTriangle( nT) ; } // Se avvenuta modifica, aggiorno tutto