From 470455472891290cc564e65c3c2a1410221fd5ea Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Tue, 30 May 2023 09:05:26 +0200 Subject: [PATCH] EgtGeomKernel : - aggiunta la gestione delle aree di trim nested Da aggiungere : - gestione delle celle non intersecate dai loop --- Tree.cpp | 966 +++++++++++++++++++++++++++++-------------------------- Tree.h | 8 +- 2 files changed, 522 insertions(+), 452 deletions(-) diff --git a/Tree.cpp b/Tree.cpp index 21a8aa1..8bbe74e 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -25,12 +25,10 @@ #include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EGkCurve.h" -using namespace std ; - //---------------------------------------------------------------------------- Cell::Cell( void) : m_nId( -1),m_nTop ( -2), m_nBottom( -2), m_nLeft( -2), m_nRight ( -2), m_nParent( -2), m_nDepth( 0), - m_nChild1( -2), m_nChild2( -2), m_nFlag( 0), m_nRightEdgeIn( 0), m_ptPbl(ORIG), m_ptPtr(), m_bProcessed(false), m_bSplitVert(true) + m_nChild1( -2), m_nChild2( -2), m_nFlag( 0), m_nFlag2( 0), m_nRightEdgeIn( 0), m_ptPbl(ORIG), m_ptPtr(), m_bProcessed(false), m_bSplitVert(true) { Point3d ptTr ( 1, 1) ; m_ptPtr = ptTr ; @@ -40,7 +38,7 @@ Cell::Cell( void) //---------------------------------------------------------------------------- Cell::Cell( Point3d& ptBL, Point3d& ptTR) : m_nId( -1),m_nTop ( -2), m_nBottom( -2), m_nLeft( -2), m_nRight ( -2), m_nParent( -2), m_nDepth( 0), - m_nChild1( -2), m_nChild2( -2), m_nFlag( 0), m_nRightEdgeIn( 0), m_ptPbl(ptBL), m_ptPtr(ptTR), m_bProcessed(false), m_bSplitVert(true) + m_nChild1( -2), m_nChild2( -2), m_nFlag( 0), m_nFlag2( 0), m_nRightEdgeIn( 0), m_ptPbl(ptBL), m_ptPtr(ptTR), m_bProcessed(false), m_bSplitVert(true) {} @@ -75,7 +73,7 @@ Tree::Tree( void) { Point3d ptBl( 0, 0), ptTr ( 1, 1) ; Cell cRoot( ptBl, ptTr) ; - m_mTree.insert( pair< int, Cell>( -1, cRoot)) ; + m_mTree.insert( std::pair< int, Cell>( -1, cRoot)) ; } //---------------------------------------------------------------------------- @@ -160,7 +158,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches) Point3d ptBottom ( 0, 0) ; Point3d ptTop( nSpanU, nSpanV) ; Cell cRoot( ptBottom, ptTop) ; - m_mTree.insert( pair< int, Cell>( -1, cRoot)) ; + m_mTree.insert( std::pair< int, Cell>( -1, cRoot)) ; Point3d ptP00, ptP10, ptP11, ptP01 ; bool bOk = false ; PNTVECTOR vVert ; @@ -172,7 +170,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches) vVert.push_back( ptP11) ; ptP01 = m_pSrfBz->GetControlPoint( ( nDegU * nSpanU + 1 ) * ( nDegV * nSpanV), &bOk) ; vVert.push_back( ptP01) ; - m_mVert.insert( pair( -1, vVert)) ; + m_mVert.insert( std::pair( -1, vVert)) ; // se richiesto divido preliminarmente le patches if ( bSplitPatches && ( nSpanU > 1 || nSpanV > 1)) { int nId = -1 ; @@ -291,12 +289,12 @@ Tree::Split( int nId, double dSplitValue) m_mTree[nId].m_nChild1 = nNodes - 1 ; cChild2.m_nId = nNodes ; m_mTree[nId].m_nChild2 = nNodes ; - m_mTree.insert( pair( nNodes - 1, cChild1)) ; - m_mTree.insert( pair( nNodes, cChild2)) ; + m_mTree.insert( std::pair( nNodes - 1, cChild1)) ; + m_mTree.insert( std::pair( nNodes, cChild2)) ; Point3d ptVert1, ptVert2 ; PNTVECTOR vVert ; - m_mVert.insert( pair( nNodes - 1, vVert)) ; - m_mVert.insert( pair( nNodes, vVert)) ; + m_mVert.insert( std::pair( nNodes - 1, vVert)) ; + m_mVert.insert( std::pair( nNodes, vVert)) ; if ( ! m_mTree[nId].IsSplitVert()) { // la cella figlio 1 è quella sopra @@ -825,7 +823,7 @@ Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const } } } - vector vCells ; + std::vector vCells ; for ( int k : vTopNeighs) vCells.push_back( m_mTree.at(k)) ; std::sort( vCells.begin(), vCells.end(), Cell::minorX) ; @@ -905,7 +903,7 @@ Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const } } } - vector vCells ; + std::vector vCells ; for ( int k : vBottomNeighs) vCells.push_back( m_mTree.at(k)) ; std::sort( vCells.begin(), vCells.end(), Cell::minorX) ; @@ -985,7 +983,7 @@ Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const } } } - vector vCells ; + std::vector vCells ; for ( int k : vLeftNeighs) vCells.push_back( m_mTree.at(k)) ; std::sort( vCells.begin(), vCells.end(), Cell::minorY) ; @@ -1064,7 +1062,7 @@ Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const } } } - vector vCells ; + std::vector vCells ; for ( int k : vRightNeighs) vCells.push_back( m_mTree.at(k)) ; std::sort( vCells.begin(), vCells.end(), Cell::minorY) ; @@ -1149,7 +1147,7 @@ Tree::GetHeightLeaves( int nId, INTVECTOR& vnLeaves, int d) const -- j ; vnLeaves.push_back( m_mTree.at(i).m_nChild1) ; vnLeaves.push_back( m_mTree.at(i).m_nChild2) ; - d = max ( d, m_mTree.at(m_mTree.at(i).m_nChild1).m_nDepth) ; + d = std::max ( d, m_mTree.at(m_mTree.at(i).m_nChild1).m_nDepth) ; } } return d ; @@ -1170,347 +1168,65 @@ Tree::GetDepth( int nId, int nRef = -2) const return c ; } +struct generator +{ + int value ; + generator() { value = -1 ;} + int operator() () { return ++value ; } +} ; + //---------------------------------------------------------------------------- bool Tree::GetPolygons( std::vector& vPolygons) { - if ( ! m_bTrimmed) { - vPolygons.clear() ; - POLYLINEVECTOR vPolygonsBasic ; - GetPolygonsBasic( vPolygonsBasic) ; - for ( PolyLine pl : vPolygonsBasic) { - POLYLINEVECTOR vSinglePolygon ; - vSinglePolygon.push_back( pl) ; - vPolygons.push_back( vSinglePolygon) ; + if ( (int) m_vPolygons.size() == 0 ) { + if ( ! m_bTrimmed) { + vPolygons.clear() ; + POLYLINEVECTOR vPolygonsBasic ; + GetPolygonsBasic( vPolygonsBasic) ; + for ( PolyLine pl : vPolygonsBasic) { + POLYLINEVECTOR vSinglePolygon ; + vSinglePolygon.push_back( pl) ; + vPolygons.push_back( vSinglePolygon) ; + } + return true ; + } + // trimmata + else { + TraceLoopLabelCell() ; + POLYLINEVECTOR vPolygonsBasic ; + GetPolygonsBasic( vPolygonsBasic) ; + // scorro sui poligoni delle celle non trimmate + int nCells = (int)vPolygonsBasic.size() ; + for ( int i = 0 ; i < nCells ; ++i ) { + // vettore dei poligoni ( loop) della cella nId + POLYLINEVECTOR vCellPolygons ; + // costruisco i poligoni partendo dal vettore delle intersezioni, come spiegato a pag15 di Cripps + int nId = m_vnLeaves[i] ; + // vettore in cui salvo il chunk di appartenenza di ogni loop che attraversa la cella + INTVECTOR vnParentChunk ; + int nEdgeIn = -1 ; + // vettore in cui salvo i loop che non appartengono al poligono che sto cotruendo nel ciclo attuale e da cui ripasserò dopo + INTVECTOR vToCheck( (int) m_mTree[nId].m_vInters.size()) ; + std::generate_n( vToCheck.begin(), (int) m_mTree[nId].m_vInters.size(), generator()) ; + // numero di poligoni aggiunti + int nPoly = 0 ; + // scorro sui vettori intersezione della cella nId e sui suoi vertici + // in questo for analizzo solo i loop che tagliano la cella + while( nPoly == 0 || (int)vToCheck.size() != 0) { + int nPolyBefore = nPoly ; + CreateCellPolygons( i, vPolygons, vToCheck, nPoly, vnParentChunk) ; + if ( nPolyBefore == nPoly) + break ; + } + // ora analizzo anche i loop che sono contenuti nella cella + CreateIslandAndHoles( i, vPolygons, nPoly, vnParentChunk) ; + } + return true; } - return true ; } - // trimmata else { - TraceLoopLabelCell() ; - POLYLINEVECTOR vPolygonsBasic ; - GetPolygonsBasic( vPolygonsBasic) ; - // scorro sui poligoni delle celle non trimmate - int nCells = (int)vPolygonsBasic.size() ; - for ( int i = 0 ; i < nCells ; ++i ) { - // vettore dei poligoni ( loop) della cella nId - POLYLINEVECTOR vCellPolygons ; - // costruisco i poligoni partendo dal vettore delle intersezioni, come spiegato a pag15 di Cripps - int nId = m_vnLeaves[i] ; - PolyLine plTrimmedPoly ; - // numero di volte che la cella è stata attraversata da una curva di trim - int nPass = (int) m_mTree[nId].m_vInters.size() ; - // numero di vertici aggiunti al nuovo poligono - int c = 0 ; - // numero di poligoni aggiunti - int nPoly = 0 ; - // vettore in cui salvo il chunk di appartenenza di ogni loop che attraversa la cella - INTVECTOR vnParentChunk ; - // scorro sui vettori intersezione della cella nId e sui suoi vertici - // in questo for analizzo solo i loop che tagliano la cella - int nEdgeIn = -1 ; - for ( int j = 0 ; j < nPass ; ++ j) { - Inters inA = m_mTree[nId].m_vInters[j] ; - if ( inA.nIn != -1) { - int nEdge ; - if ( nEdgeIn == -1) - // salvo il lato di ingresso del primo lato del poligono che sto costruendo - nEdgeIn = inA.nIn ; - for ( Point3d ptInt : inA.vpt) { - plTrimmedPoly.AddUPoint( c, ptInt) ; - ++ c ; - } - nEdge = inA.nOut ; - // se la curva è CW devo verifica di non essere uscito in un vertice, con un tratto sovrapposto al lato che ripercorrerò tra poco - if ( ! inA.bCCW) { - Point3d ptLast , ptSecondToLast; - plTrimmedPoly.GetLastPoint( ptLast) ; - plTrimmedPoly.GetPrevPoint( ptSecondToLast) ; - Vector3d vLast = ptLast - ptSecondToLast ; - vLast.Normalize(); - Vector3d vEdge ; - if ( nEdge == 0) { - Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ; - if ( AreSamePointApprox ( ptLast, ptTl)) { - vEdge = m_mTree[nId].GetBottomLeft() - ptTl ; - vEdge.Normalize() ; - if ( AreOppositeVectorApprox( vLast, vEdge) ) { - plTrimmedPoly.EraseLastUPoint() ; - nEdge = 1 ; - } - } - } - else if ( nEdge == 1 && AreSamePointApprox ( ptLast, m_mTree[nId].GetBottomLeft())) { - Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; - vEdge = ptBr - m_mTree[nId].GetBottomLeft() ; - vEdge.Normalize() ; - if ( AreOppositeVectorApprox( vLast, vEdge) ) { - plTrimmedPoly.EraseLastUPoint() ; - nEdge = 2 ; - } - } - else if ( nEdge == 2) { - Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; - if ( AreSamePointApprox ( ptLast, ptBr)) { - vEdge = m_mTree[nId].GetTopRight() - ptBr ; - vEdge.Normalize() ; - if ( AreOppositeVectorApprox( vLast, vEdge) ) { - plTrimmedPoly.EraseLastUPoint() ; - nEdge = 3 ; - } - } - } - else if ( nEdge == 3 && AreSamePointApprox ( ptLast, m_mTree[nId].GetTopRight())) { - Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ; - vEdge = ptTl - m_mTree[nId].GetTopRight() ; - vEdge.Normalize() ; - if ( AreOppositeVectorApprox(vLast, vEdge) ) { - plTrimmedPoly.EraseLastUPoint() ; - nEdge = 0 ; - } - } - } - // se mi è rimasto solo un punto sulla polyline vuol dire che avevo solo un tratto parallelo ad lato - // quindi salto al prossimo loop - if ( plTrimmedPoly.GetPointNbr() == 1 ) { - plTrimmedPoly.Clear() ; - continue ; - } - if ( nEdge > 3 && nEdge != 7) { - nEdge = nEdge - 3 ; - } - else if ( nEdge == 7 ) { - nEdge = 0 ; - } - // se ho altri Pass vado avanti ad aggiungere vertici finché trovo il prossimo o finché non sono tornato sul lato di partenza - bool bNotCameBack = true ; - bool bValidNextStart = false ; - if ( j < nPass - 1 ) { - if ( m_mTree[nId].m_vInters[j].bCCW ) { - bValidNextStart = ( m_mTree[nId].m_vInters[j + 1].nIn == nEdge) && - ! CheckIfAfter( plTrimmedPoly, m_mTree[nId].m_vInters[j + 1].vpt[0], nEdge) ; - bNotCameBack = m_mTree[nId].m_vInters[j].nIn != nEdge && // sono tornato al lato di ingresso di questo loop - nEdge != nEdgeIn ; // sono tornato sul lato di ingresso di questo poligono ( solo se la curva è CCW) - } - else { - // se il loop è CW e sono tornato sul lato di partenza allora controllo se sono prima del primo punto della polyline - if ( nEdge == nEdgeIn ) { - bValidNextStart = ( m_mTree[nId].m_vInters[j + 1].nIn == nEdge) && - CheckIfAfter( plTrimmedPoly, m_mTree[nId].m_vInters[j + 1].vpt[0], nEdge) ; - bool bBefore = CheckIfBefore( plTrimmedPoly, nEdge) ; - bNotCameBack = bNotCameBack && ! bBefore ; - } - } - // devo controllare che su questo lato il prossimo punto di ingresso sia più avanti del punto di fine a cui sono arrivato!!!!////////////////////// - while ( m_mTree[nId].m_vInters[j + 1].nIn != nEdge && // loop successivo inizia su questo lato/// questa condizione devo spostarla nell'if qui sopra - // e differenziare per CCW e CW. sostituisco con bValidNextStart - bNotCameBack) { - Point3d ptVert ; - if ( nEdge == 0) { - ptVert.x = m_mTree[nId].GetBottomLeft().x ; - ptVert.y = m_mTree[nId].GetTopRight().y ; - } - else if ( nEdge == 1) - ptVert = m_mTree[nId].GetBottomLeft() ; - else if ( nEdge == 2) { - ptVert.x = m_mTree[nId].GetTopRight().x ; - ptVert.y = m_mTree[nId].GetBottomLeft().y ; - } - else if ( nEdge == 3) - ptVert = m_mTree[nId].GetTopRight() ; - plTrimmedPoly.AddUPoint( c, ptVert) ; - ++c ; - if ( nEdge != 3) - ++ nEdge ; - else - nEdge = 0 ; - // aggiorno le condizioni per il while - if ( m_mTree[nId].m_vInters[j].bCCW ) { - bNotCameBack = m_mTree[nId].m_vInters[j].nIn != nEdge && - nEdge != nEdgeIn ; - } - else { - if ( nEdge == nEdgeIn ) { - bool bBefore = CheckIfBefore( plTrimmedPoly, nEdge) ; - bNotCameBack = bNotCameBack && ! bBefore ; - } - } - } - // se ho trovato un altro loop salto all'inizio del for - if ( m_mTree[nId].m_vInters[j + 1].nIn == nEdge) { - continue ; - } - } - // non ho altri loop quindi aggiungo vertici finché torno al punto di partenza - else { - if ( m_mTree[nId].m_vInters[j].bCCW ) { - bNotCameBack = m_mTree[nId].m_vInters[j].nIn != nEdge && // sono tornato al lato di ingresso di questo loop - nEdge != nEdgeIn ; // sono tornato sul lato di ingresso di questo poligono ( solo se la curva è CCW) - } - else { - // se il loop è CW e sono tornato sul lato di partenza allora controllo se sono prima del primo punto della polyline - if ( nEdge == nEdgeIn ) { - bool bBefore = CheckIfBefore( plTrimmedPoly, nEdge) ; - bNotCameBack = bNotCameBack && ! bBefore ; - } - } - while ( bNotCameBack) { - Point3d ptVert ; - if ( nEdge == 0) { - ptVert.x = m_mTree[nId].GetBottomLeft().x ; - ptVert.y = m_mTree[nId].GetTopRight().y ; - } - else if ( nEdge == 1) - ptVert = m_mTree[nId].GetBottomLeft() ; - else if ( nEdge == 2) { - ptVert.x = m_mTree[nId].GetTopRight().x ; - ptVert.y = m_mTree[nId].GetBottomLeft().y ; - } - else if ( nEdge == 3) - ptVert = m_mTree[nId].GetTopRight() ; - plTrimmedPoly.AddUPoint( c, ptVert) ; - ++c ; - if ( nEdge != 3) - ++ nEdge ; - else - nEdge = 0 ; - // aggiorno le condizioni per il while - if ( m_mTree[nId].m_vInters[j].bCCW ) { - bNotCameBack = m_mTree[nId].m_vInters[j].nIn != nEdge && - nEdge != nEdgeIn ; - } - else { - if ( nEdge == nEdgeIn ) { - bool bBefore = CheckIfBefore( plTrimmedPoly, nEdge) ; - bNotCameBack = bNotCameBack && ! bBefore ; - } - } - } - } - plTrimmedPoly.Close() ; - vCellPolygons.push_back( plTrimmedPoly) ; - vPolygons.push_back( vCellPolygons) ; - ++ nPoly ; - vnParentChunk.push_back( inA.nChunk) ; - vCellPolygons.clear() ; - c = 0 ; - plTrimmedPoly.Clear() ; - nEdgeIn = -1 ; - } - else - continue ; - } - - // ora analizzo anche i loop che sono contenuti nella cella - // loop interni in una cella intersecata - // - // DA AGGIUNGERE //////// - // la cella è contenuta in un loop più grande della cella -> i loop esterni devono essere CW e devo aggiungere il bordo della cella ai loop///////////////////////////////// - if ( m_mTree[nId].m_nFlag == 3 || m_mTree[nId].m_nFlag == 2) { - // devo verificare se il loop è contenuto in un'altro loop ?////////////////////////////////////sì///////////////////////////////////////// - PolyLine plInLoop ; - // numero dei loop interni passati - int n = 0 ; - Inters inA = m_mTree[nId].m_vInters[n] ; - if ( m_mTree[nId].m_nFlag == 2 && inA.nOut == -3) { - // i loop esterni sono CW, quindi prima dei loop di trim aggiungo il bordo cella - Point3d ptVert = m_mTree[nId].GetTopRight() ; - plInLoop.AddUPoint( 0, ptVert) ; - ptVert.x = m_mTree[nId].GetBottomLeft().x ; - ptVert.y = m_mTree[nId].GetTopRight().y ; - plInLoop.AddUPoint( 1, ptVert) ; - ptVert = m_mTree[nId].GetBottomLeft() ; - plInLoop.AddUPoint( 2, ptVert) ; - ptVert.x = m_mTree[nId].GetTopRight().x ; - ptVert.y = m_mTree[nId].GetBottomLeft().y ; - plInLoop.AddUPoint( 3, ptVert) ; - plInLoop.Close(); - vCellPolygons.push_back( plInLoop) ; - vPolygons.push_back( vCellPolygons) ; - ++ nPoly ; - vnParentChunk.push_back( inA.nChunk) ; - vCellPolygons.clear() ; - plInLoop.Clear() ; - } - while ( inA.nIn == -1) { - // numero di vertici aggiunti al nuovo poligono - int k = 0 ; - for ( Point3d ptInt : inA.vpt) { - plInLoop.AddUPoint( c, ptInt) ; - ++ k ; - } - plInLoop.Close(); - bool bAdded = false ; - // se il loop è CW devo controllare in quale altro dei poligoni che ho già aggiunto è contenuto - if ( ! inA.bCCW) { - Point3d ptStart ; - plInLoop.GetFirstPoint( ptStart) ; - int nOtherPoly = (int)vPolygons.size() ; - for ( int r = 0 ; r < nPoly ; ++r ) { - if ( IsPointInsidePolyLine( ptStart, vPolygons[nOtherPoly - r - 1][0], -0.01) && vnParentChunk[nPoly - r - 1] == inA.nChunk ) { - vPolygons[r].push_back( plInLoop) ; - plInLoop.Clear() ; - ++ nPoly ; - vnParentChunk.push_back( inA.nChunk) ; - bAdded = true ; - break ; - } - } - } - if ( ! bAdded ) { - vCellPolygons.push_back( plInLoop) ; - vPolygons.push_back( vCellPolygons) ; - ++ nPoly ; - vnParentChunk.push_back( inA.nChunk) ; - plInLoop.Clear() ; - vCellPolygons.clear() ; - } - - plInLoop.Clear() ; - ++ n ; - inA = m_mTree[nId].m_vInters[n] ; - } - } - //// solo loop interni - //// o la cella è contenuta in un loop più grande della cella -> i loop esterni devono essere CW e devo aggiungere il bordo della cella ai loop - //// o bisogna tenere solo il contenuto dei loop -> i loop esterni sono CCW - //if ( m_mTree[nId].m_nFlag == 2) { - // PolyLine plInLoop ; - // int n = 0 ; - // Inters inA = m_mTree[nId].m_vInters[n] ; - // if ( inA.nOut == -3) { - // // i loop esterni sono CW, quindi prima dei loop di trim aggiungo il bordo cella - // Point3d ptVert = m_mTree[nId].GetTopRight() ; - // plInLoop.AddUPoint( 0, ptVert) ; - // ptVert.x = m_mTree[nId].GetBottomLeft().x ; - // ptVert.y = m_mTree[nId].GetTopRight().y ; - // plInLoop.AddUPoint( 1, ptVert) ; - // ptVert = m_mTree[nId].GetBottomLeft() ; - // plInLoop.AddUPoint( 2, ptVert) ; - // ptVert.x = m_mTree[nId].GetTopRight().x ; - // ptVert.y = m_mTree[nId].GetBottomLeft().y ; - // plInLoop.AddUPoint( 3, ptVert) ; - // vCellPolygons.push_back( plInLoop) ; - // plInLoop.Clear() ; - // } - // while ( inA.nIn == -1) { - // // numero di vertici aggiunti al nuovo poligono - // int k = 0 ; - // for ( Point3d ptInt : inA.vpt) { - // plInLoop.AddUPoint( c, ptInt) ; - // ++ k ; - // } - // ++ n ; - // inA = m_mTree[nId].m_vInters[n] ; - // vCellPolygons.push_back( plInLoop) ; - // plInLoop.Clear() ; - // } - //} - - // questo in teoria non serve più, perché aggiungo subito un vCellPolygons a vPolygons////////////////////////////////da controllare///////////////// - //if ( (int)vCellPolygons.size() != 0) - // vPolygons.push_back( vCellPolygons) ; - } - return true; + vPolygons = m_vPolygons ; + return true ; } } @@ -1597,15 +1313,20 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons) } m_vPolygons.emplace_back() ; + m_vPolygons.back().emplace_back() ; for ( int i = 0 ; i < (int) vVertices.size() ; ++i) { - m_vPolygons.back().AddUPoint( i, vVertices.at(i)) ; + m_vPolygons.back().back().AddUPoint(i, vVertices.at(i)) ; } } } // restituisco i poligoni delle celle del tree nello spazio parametrico - vPolygons = m_vPolygons ; + for ( int t = 0 ; t < (int)m_vPolygons.size() ; ++ t) { + for ( int z = 0 ; z < (int)m_vPolygons[t].size(); ++z ) { + vPolygons.push_back( m_vPolygons[t][z]) ; + } + } return true ; } @@ -1637,6 +1358,8 @@ Tree::ResetTree( void) // nCToReset = m_mTree[nCToReset].m_nChild1 ; // } //} + + // setto tutte le foglie a Processed = false for ( int nC : m_vnLeaves ) { m_mTree[nC].SetProcessed( false) ; } @@ -1695,14 +1418,12 @@ Tree::TraceLoopLabelCell( void) vPlApprox.push_back( plApprox) ; } // ora le curve di trim hanno lo stesso indice delle loro corrispondenti spezzate nel vettore vPlApprox - // come sono composte le plApprox?? - // qui potrei aver trovato solo le celle che sono nelle box3d delle curve di trim. se ho delle curve in senso antiorario come le gestisco???? - double dLinTol = - 0.01 ; // questo è riferito allo spazio parametrico!!!!!! + double dLinTol = - 0.01 ; // questo è riferito allo spazio parametrico, quando è già stato riporatato al range 0..1 !!!!!! + // il valore è negativo perché voglio considerare contenuto anche un punto che sta su un lato POLYLINEVECTOR vplPolygons ; GetPolygonsBasic( vplPolygons) ; // percorro i loop trovando le interezioni con le celle e riempiendo i vettori m_vInters delle varie celle - //for ( PolyLine plLoop : vPlApprox) { for ( int i = 0 ; i < (int) vPlApprox.size(); ++ i) { PolyLine plLoop = vPlApprox[i] ; // calcolo se il loop è CCW o Cw @@ -1731,11 +1452,9 @@ Tree::TraceLoopLabelCell( void) // salvo il chunk del loop m_mTree[nId].m_vInters.back().nChunk = m_mChunk[i] ; bool bLoopInside = true ; - // funziona la condizione del for ??///////////////////////////////////////////////////////////////////////////////////////////////////////////// Point3d ptCurr ; INTVECTOR :: iterator iter = find( m_vnLeaves.begin(), m_vnLeaves.end(), nId) ; int nIdPolygon = std::distance( m_vnLeaves.begin(), iter) ; - //for ( Point3d ptCurr ; plLoop.GetNextPoint( ptCurr) ; ) { while ( plLoop.GetNextPoint( ptCurr)) { // sto uscendo dalla cella, quindi cerco l'intersezione Point3d ptStart, ptEnd ; @@ -1743,7 +1462,7 @@ Tree::TraceLoopLabelCell( void) plLoop.GetNextPoint( ptEnd) ; CurveLine clTrim ; clTrim.Set( ptStart, ptEnd) ; - while( ! IsPointInsidePolyLine( ptCurr, m_vPolygons[nIdPolygon], dLinTol)) { /// qui devo mettere una tolleranza negativa per poter tener conto anche dei punti che sono SULLA curva + while( ! IsPointInsidePolyLine( ptCurr, vplPolygons[nIdPolygon], dLinTol)) { /// qui devo mettere una tolleranza negativa per poter tener conto anche dei punti che sono SULLA curva bLoopInside = false ; // trovo l'intersezione e passo alla cella successiva. nId viene aggiornato dalla funzione FindInters FindInters( nId, clTrim, vptInters) ; @@ -1770,22 +1489,10 @@ Tree::TraceLoopLabelCell( void) // setto i lati di ingresso e uscita a -1 per indicare che ho un loop interno alla cella m_mTree[nId].m_vInters.back().nIn = -1 ; m_mTree[nId].m_vInters.back().nOut = -1 ; - //// salvo il verso della curva di trim ///////////////////////////////////////////////////////////////////doppione////////////////// - //double dArea ; - //Plane3d plExtPlane ; - //plLoop.IsClosedAndFlat( plExtPlane, dArea, 50 * EPS_SMALL) ; - //if ( plExtPlane.GetVersN().z > 0 ) { - // m_mTree[nId].m_vInters.back().bCCW = true ; - //} - //else { - // m_mTree[nId].m_vInters.back().bCCW = false ; - //} - } // sono tornato alla cella di partenza, quindi devo fare il merge dei due vettori di intersezione che ho creato per questa cella // per lo stesso loop else { - //int nIn = m_mTree[nId].m_vInters.back().nIn ; int nOut = m_mTree[nId].m_vInters[nPass].nOut ; m_mTree[nId].m_vInters.back().vpt.insert( m_mTree[nId].m_vInters.back().vpt.end(), m_mTree[nId].m_vInters[nPass].vpt.begin(), @@ -1802,86 +1509,105 @@ Tree::TraceLoopLabelCell( void) std::sort( m_mTree[nId].m_vInters.begin( ), m_mTree[nId].m_vInters.end()) ; } - //// devo riconoscere le celle dentro i loop che sono ancora con label nFlag = -1 - //ResetTree() ; - //INTVECTOR vNeigh, vFirst ; - //GetRootNeigh( 1, vFirst) ; - //int nLastLeft = vFirst.back() ; - //int nCell = vFirst[0] ; - //GetRightNeigh( nCell, vNeigh) ; - //// proseguo finché non sono sull'elemento più alto di vFirst e tutti i suoi vicini sono processati/categorizzati - //bool bAllDone = false , bDone ; - //while ( nCell != nLastLeft && ! bAllDone) { - // // fintanto che la cella ha tra i vicini a destra una cella non elaborata mi sposto a destra - // bDone = false ; // ramo a destra tutto categorizzato - // while ( (int)vNeigh.size() > 0 || ! bDone) { - // // verso la cella a destra più in basso da cui non sono ancora passato - // bool bProceeded = false ; - // for ( int i = 0 ; i < (int)vNeigh.size(); ++ i) { - // if ( ! m_mTree[vNeigh[i]].IsProcessed() ) { - // nCell = vNeigh[i] ; - // bProceeded = true ; - // break ; - // } - // } - // if ( ! bProceeded) - // bDone = true ; - // else { //categorizzo la cella/////////////////////////////////////////////////////////// + // devo riconoscere le celle dentro i loop che sono ancora con label nFlag = -1 + ResetTree() ; + INTVECTOR vNeigh, vFirst ; + GetRootNeigh( 1, vFirst) ; + int nLastLeft = vFirst.back() ; + int nCell = vFirst[0] ; + GetRightNeigh( nCell, vNeigh) ; + // proseguo finché non sono sull'elemento più alto di vFirst e tutti i suoi vicini sono processati/categorizzati + bool bAllDone = false ; + while ( nCell != nLastLeft && ! bAllDone) { + // categorizzo la cella + m_mTree[nCell].m_nFlag2 = 1 ; - // } - // - // if ( ! bDone) { - // // guardo i vicini a destra per passare alla prossima cella - // vNeigh.clear() ; - // GetRightNeigh( nCell, vNeigh) ; - // } - // } - // vNeigh.clear() ; - // GetRightNeigh( nCell, vNeigh) ; - // // se non ho vicini a destra o se i vicini sono già tutti categorizzati - // // torno indietro a sinistra alla cella già categorizzata più bassa - // //bDone = true ; - // while ( (int) vNeigh.size() == 0 || bDone) { - // // trovo il vicino a sinistra, già categorizzato, più basso - // vNeigh.clear() ; - // GetLeftNeigh( nCell, vNeigh) ; - // for ( int p = 0; p < (int)vNeigh.size() ; ++ p) { - // if ( m_mTree[vNeigh[p]].IsProcessed() ) { - // nCell = vNeigh[p] ; - // break ; - // } - // } - // // controllo se tutti i vicini di destra sono categorizzati - // vNeigh.clear() ; - // GetRightNeigh( nCell, vNeigh) ; - // for ( int k = 0; k < (int)vNeigh.size() ; ++ k) { - // if ( ! m_mTree[vNeigh[k]].IsProcessed() ) { - // nCell = vNeigh[k] ; - // bDone = false; - // break ; - // } - // } - // } - // // categorizzo la cella + // fintanto che la cella ha tra i vicini a destra una cella non elaborata mi sposto a destra + // definisco una cella Processed se tutto il ramo a destra è categorizzato + while ( (int)vNeigh.size() > 0 || ! m_mTree[nCell].IsProcessed()) { + // verso la cella a destra più in basso da cui non sono ancora passato + bool bProceeded = false ; + for ( int i = 0 ; i < (int)vNeigh.size(); ++ i) { + if ( m_mTree[vNeigh[i]].m_nFlag2 == 0 ) { + nCell = vNeigh[i] ; + bProceeded = true ; + break ; + } + } + if ( ! bProceeded ) { + m_mTree[nCell].SetProcessed() ; + } + else { //categorizzo la cella/////////////////////////////////////////////////////////// + m_mTree[nCell].m_nFlag2 = 1 ; + } + + if ( ! m_mTree[nCell].IsProcessed()) { + // guardo i vicini a destra per passare alla prossima cella + vNeigh.clear() ; + GetRightNeigh( nCell, vNeigh) ; + } + } + vNeigh.clear() ; + GetRightNeigh( nCell, vNeigh) ; + // se non ho vicini a destra o se i vicini sono già tutti categorizzati + // torno indietro a sinistra alla cella già categorizzata più bassa + //bDone = true ; + while ( (int) vNeigh.size() == 0 || m_mTree[nCell].IsProcessed()) { + // trovo il vicino a sinistra, già categorizzato, più basso + vNeigh.clear() ; + GetLeftNeigh( nCell, vNeigh) ; + for ( int p = 0; p < (int)vNeigh.size() ; ++ p) { + if ( m_mTree[vNeigh[p]].m_nFlag2 != 0 ) { + nCell = vNeigh[p] ; + break ; + } + } + // se non ho vicini a sinistra sono tornato sul lato sinistro e quindi devo procedere alla cella più bassa non processata sul lato sinistro + if ( vNeigh.empty() ) { + for ( int p = 0 ; p < (int)vFirst.size() ; ++ p ) { + if ( m_mTree[vFirst[p]].m_nFlag2 == 0 ) { + nCell = vFirst[p] ; + break ; + } + } + if ( nCell == nLastLeft && m_mTree[nCell].IsProcessed() ) { + // categorizzo//////////////////////////////////////////////////////////////////////////// + m_mTree[nCell].m_nFlag2 = 1 ; + bAllDone = true ; + break ; + } + } + // controllo se tutti i vicini di destra sono categorizzati + vNeigh.clear() ; + GetRightNeigh( nCell, vNeigh) ; + bool bDone = true ; + for ( int k = 0; k < (int)vNeigh.size() ; ++ k) { + if ( ! m_mTree[vNeigh[k]].IsProcessed() ) { + //nCell = vNeigh[k] ; + bDone = false ; + break ; + } + } + if ( bDone) + m_mTree[nCell].SetProcessed( bDone) ; + } + vNeigh.clear() ; + GetRightNeigh( nCell, vNeigh) ; + //// se sono all'ultimo elemento di vFirst controllo se ho processato tutti i suoi vicini di destra + //if ( nCell == nLastLeft){ + // vNeigh.clear() ; + // GetRightNeigh( nCell, vNeigh) ; + // bAllDone = true ; + // for( int j = 0 ; j < (int) vNeigh.size(); ++ j) { + // if ( ! m_mTree[vNeigh[j]].IsProcessed() ) { + // bAllDone = false ; + // break ; + // } + // } + //} - - // // se sono all'ultimo elemento di vFirst controllo se ho fatto tutti i suoi vicini di destra - // if ( nCell == nLastLeft){ - // vNeigh.clear() ; - // GetRightNeigh( nCell, vNeigh) ; - // bAllDone = true ; - // for( int j = 0 ; j < (int) vNeigh.size(); ++ j) { - // if ( ! m_mTree[vNeigh[j]].IsProcessed() ) { - // bAllDone = false ; - // break ; - // } - // } - // } - - //} - - //// RIMETTI il valore di default di m_nFlag = -1 nella creazione di una cella // mi serve???////////////////////////////////////////////////////////// + } return true ; } @@ -2030,6 +1756,8 @@ Tree::FindInters( int& nId, CurveLine& clTrim, PNTVECTOR& vptInters) m_mTree[nId].m_vInters.emplace_back() ; m_mTree[nId].m_vInters.back().nIn = 1 ; } + // per nEdge > 3 sto parlando di intersezioni sui vertici, che vengono attraversati in diagonale e non paralleli ad uno dei due lati + // se attraversati adiacenti ad uno dei due lati, viene considerata l'intersezione col lato perpendicolare else if ( nEdge == 4) { GetTopNeigh( nId, vNeigh) ; int nIdTemp = vNeigh[0] ; @@ -2071,6 +1799,346 @@ Tree::FindInters( int& nId, CurveLine& clTrim, PNTVECTOR& vptInters) return true ; } +//---------------------------------------------------------------------------- +bool +Tree::CreateCellPolygons( int nLeafId, std::vector& vPolygons, INTVECTOR& vToCheck, int& nPoly, INTVECTOR& vnParentChunk) +{ + INTVECTOR vToCheckNow = vToCheck ; + vToCheck.clear() ; + // vettore dei poligoni ( loop) della cella nId + POLYLINEVECTOR vCellPolygons ; + // costruisco i poligoni partendo dal vettore delle intersezioni, come spiegato a pag15 di Cripps + int nId = m_vnLeaves[nLeafId] ; + PolyLine plTrimmedPoly ; + // numero di volte che la cella è stata attraversata da una curva di trim + int nPassToCheck = (int) vToCheckNow.size() ; + // numero di vertici aggiunti al nuovo poligono + int c = 0 ; + // scorro sui vettori intersezione della cella nId e sui suoi vertici + // in questo for analizzo solo i loop che tagliano la cella + int nEdgeIn = -1 ; + for ( int w = 0 ; w < (int)vToCheckNow.size() ; ++ w) { + int j = vToCheckNow[w] ; + Inters inA = m_mTree[nId].m_vInters[j] ; + if ( inA.nIn != -1 ) { + int nEdge ; + if ( nEdgeIn == -1 ) + // salvo il lato di ingresso del primo lato del poligono che sto costruendo + nEdgeIn = inA.nIn ; + for ( Point3d ptInt : inA.vpt ) { + plTrimmedPoly.AddUPoint(c, ptInt) ; + ++c ; + } + nEdge = inA.nOut ; + // se la curva è CW devo verifica di non essere uscito in un vertice, con un tratto sovrapposto al lato che ripercorrerò tra poco + if ( !inA.bCCW ) { + Point3d ptLast, ptSecondToLast; + plTrimmedPoly.GetLastPoint(ptLast) ; + plTrimmedPoly.GetPrevPoint(ptSecondToLast) ; + Vector3d vLast = ptLast - ptSecondToLast ; + vLast.Normalize(); + Vector3d vEdge ; + if ( nEdge == 0 ) { + Point3d ptTl(m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ; + if ( AreSamePointApprox(ptLast, ptTl) ) { + vEdge = m_mTree[nId].GetBottomLeft() - ptTl ; + vEdge.Normalize() ; + if ( AreOppositeVectorApprox(vLast, vEdge) ) { + plTrimmedPoly.EraseLastUPoint() ; + nEdge = 1 ; + } + } + } + else if ( nEdge == 1 && AreSamePointApprox(ptLast, m_mTree[nId].GetBottomLeft()) ) { + Point3d ptBr(m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; + vEdge = ptBr - m_mTree[nId].GetBottomLeft() ; + vEdge.Normalize() ; + if ( AreOppositeVectorApprox(vLast, vEdge) ) { + plTrimmedPoly.EraseLastUPoint() ; + nEdge = 2 ; + } + } + else if ( nEdge == 2 ) { + Point3d ptBr(m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; + if ( AreSamePointApprox(ptLast, ptBr) ) { + vEdge = m_mTree[nId].GetTopRight() - ptBr ; + vEdge.Normalize() ; + if ( AreOppositeVectorApprox(vLast, vEdge) ) { + plTrimmedPoly.EraseLastUPoint() ; + nEdge = 3 ; + } + } + } + else if ( nEdge == 3 && AreSamePointApprox(ptLast, m_mTree[nId].GetTopRight()) ) { + Point3d ptTl(m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ; + vEdge = ptTl - m_mTree[nId].GetTopRight() ; + vEdge.Normalize() ; + if ( AreOppositeVectorApprox(vLast, vEdge) ) { + plTrimmedPoly.EraseLastUPoint() ; + nEdge = 0 ; + } + } + } + // se mi è rimasto solo un punto sulla polyline vuol dire che avevo solo un tratto parallelo ad lato + // quindi salto al prossimo loop + if ( plTrimmedPoly.GetPointNbr() == 1 ) { + plTrimmedPoly.Clear() ; + continue ; + } + if ( nEdge > 3 && nEdge != 7 ) { + nEdge = nEdge - 3 ; + } + else if ( nEdge == 7 ) { + nEdge = 0 ; + } + // se ho altri Pass vado avanti ad aggiungere vertici finché trovo il prossimo o finché non sono tornato sul lato di partenza + bool bNotCameBack = true ; + bool bValidNextStart = false ; + if ( j < nPassToCheck - 1) { + int nSecondCheck = 0 ; + + // ciclo sui loop successivi per vedere se ne ho uno su questo lato con un valid start + for ( int t = w ; t < nPassToCheck -1 ; ++ t) { + if ( nEdge == m_mTree[nId].m_vInters[j].nIn ) { + if ( m_mTree[nId].m_vInters[j].bCCW) { + bValidNextStart = ( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn == nEdge) && // loop successivo inizia su questo lato + ! CheckIfAfter( plTrimmedPoly, m_mTree[nId].m_vInters[vToCheckNow[t + 1]].vpt[0], nEdge) ; // in posizione giusta da essere concatenato + } + else { + // se il loop è CW e sono tornato sul lato di partenza allora controllo se sono prima del primo punto della polyline + bValidNextStart = ( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn == nEdge) && + CheckIfAfter( plTrimmedPoly, m_mTree[nId].m_vInters[vToCheckNow[t + 1]].vpt[0], nEdge) ; + } + } + else + bValidNextStart = true ; + if ( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn != nEdge || bValidNextStart) + break ; + // se ho trovato un loop successivo che devo saltare, lo salvo e considero i loop più avanti. + if ( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn == nEdge && ! bValidNextStart){ + ++ nSecondCheck ; + vToCheck.push_back( t + 1) ; + } + } + if ( m_mTree[nId].m_vInters[j].bCCW) { + bNotCameBack = m_mTree[nId].m_vInters[j].nIn != nEdge && // sono tornato al lato di ingresso di questo loop + nEdge != nEdgeIn ; // sono tornato sul lato di ingresso di questo poligono ( solo se la curva è CCW) + } + else { + // il loop è CW e sono tornato sul lato di partenza allora controllo se sono prima del primo punto della polyline + if ( nEdge == nEdgeIn ) { + bool bBefore = CheckIfBefore( plTrimmedPoly, nEdge) ; + bNotCameBack = bNotCameBack && !bBefore ; + } + } + + while ( ! bValidNextStart && bNotCameBack) { + Point3d ptVert ; + if ( nEdge == 0) { + ptVert.x = m_mTree[nId].GetBottomLeft().x ; + ptVert.y = m_mTree[nId].GetTopRight().y ; + } + else if ( nEdge == 1) + ptVert = m_mTree[nId].GetBottomLeft() ; + else if ( nEdge == 2) { + ptVert.x = m_mTree[nId].GetTopRight().x ; + ptVert.y = m_mTree[nId].GetBottomLeft().y ; + } + else if ( nEdge == 3) + ptVert = m_mTree[nId].GetTopRight() ; + plTrimmedPoly.AddUPoint( c, ptVert) ; + ++c ; + if ( nEdge != 3) + ++ nEdge ; + else + nEdge = 0 ; + + // aggiorno le condizioni per il while + // ciclo sui loop successivi per vedere se ne ho uno su questo lato con un valid start + for ( int t = w ; t < nPassToCheck -1 ; ++ t) { + if ( nEdge == m_mTree[nId].m_vInters[j].nIn ) { + if ( m_mTree[nId].m_vInters[j].bCCW) { + bValidNextStart = ( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn == nEdge) && // loop successivo inizia su questo lato + ! CheckIfAfter( plTrimmedPoly, m_mTree[nId].m_vInters[vToCheckNow[t + 1]].vpt[0], nEdge) ; // in posizione giusta da essere concatenato + } + else { + // se il loop è CW e sono tornato sul lato di partenza allora controllo se sono prima del primo punto della polyline + bValidNextStart = ( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn == nEdge) && + CheckIfAfter( plTrimmedPoly, m_mTree[nId].m_vInters[vToCheckNow[t + 1]].vpt[0], nEdge) ; + } + } + else + bValidNextStart = true ; + if ( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn != nEdge || bValidNextStart) + break ; + // se ho trovato un loop successivo che devo saltare, lo salvo e considero i loop più avanti. + if ( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn == nEdge && ! bValidNextStart){ + ++ nSecondCheck ; + vToCheck.push_back( t + 1) ; + } + } + if ( m_mTree[nId].m_vInters[j].bCCW) { + bNotCameBack = m_mTree[nId].m_vInters[j].nIn != nEdge && // sono tornato al lato di ingresso di questo loop + nEdge != nEdgeIn ; // sono tornato sul lato di ingresso di questo poligono ( solo se la curva è CCW) + } + else { + // se il loop è CW e sono tornato sul lato di partenza allora controllo se sono prima del primo punto della polyline + if ( nEdge == nEdgeIn ) { + bool bBefore = CheckIfBefore( plTrimmedPoly, nEdge) ; + bNotCameBack = bNotCameBack && !bBefore ; + } + } + + } + // se ho trovato un altro loop salto all'inizio del for + if ( m_mTree[nId].m_vInters[vToCheckNow[w + 1 + nSecondCheck]].nIn == nEdge) { + w = w + nSecondCheck ; + continue ; + } + } + // non ho altri loop quindi aggiungo vertici finché torno al punto di partenza + else { + if ( m_mTree[nId].m_vInters[j].bCCW ) { + bNotCameBack = m_mTree[nId].m_vInters[j].nIn != nEdge && // sono tornato al lato di ingresso di questo loop + nEdge != nEdgeIn ; // sono tornato sul lato di ingresso di questo poligono ( solo se la curva è CCW) + } + else { + // se il loop è CW e sono tornato sul lato di partenza allora controllo se sono prima del primo punto della polyline + if ( nEdge == nEdgeIn ) { + bool bBefore = CheckIfBefore( plTrimmedPoly, nEdge) ; + bNotCameBack = bNotCameBack && ! bBefore ; + } + } + while ( bNotCameBack) { + Point3d ptVert ; + if ( nEdge == 0) { + ptVert.x = m_mTree[nId].GetBottomLeft().x ; + ptVert.y = m_mTree[nId].GetTopRight().y ; + } + else if ( nEdge == 1) + ptVert = m_mTree[nId].GetBottomLeft() ; + else if ( nEdge == 2) { + ptVert.x = m_mTree[nId].GetTopRight().x ; + ptVert.y = m_mTree[nId].GetBottomLeft().y ; + } + else if ( nEdge == 3) + ptVert = m_mTree[nId].GetTopRight() ; + plTrimmedPoly.AddUPoint( c, ptVert) ; + ++c ; + if ( nEdge != 3) + ++ nEdge ; + else + nEdge = 0 ; + // aggiorno le condizioni per il while + if ( m_mTree[nId].m_vInters[j].bCCW ) { + bNotCameBack = m_mTree[nId].m_vInters[j].nIn != nEdge && + nEdge != nEdgeIn ; + } + else { + if ( nEdge == nEdgeIn ) { + bool bBefore = CheckIfBefore( plTrimmedPoly, nEdge) ; + bNotCameBack = bNotCameBack && ! bBefore ; + } + } + } + } + plTrimmedPoly.Close() ; + vCellPolygons.push_back( plTrimmedPoly) ; + vPolygons.push_back( vCellPolygons) ; + ++ nPoly ; + vnParentChunk.push_back( inA.nChunk) ; + vCellPolygons.clear() ; + c = 0 ; + plTrimmedPoly.Clear() ; + nEdgeIn = -1 ; + } + else + continue ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +Tree::CreateIslandAndHoles( int nLeafId, std::vector& vPolygons, int& nPoly, INTVECTOR& vnParentChunk) +{ + // vettore dei poligoni ( loop) della cella nId + POLYLINEVECTOR vCellPolygons ; + // costruisco i poligoni partendo dal vettore delle intersezioni, come spiegato a pag15 di Cripps + int nId = m_vnLeaves[nLeafId] ; + PolyLine plTrimmedPoly ; + // numero di volte che la cella è stata attraversata da una curva di trim + int nPass = (int) m_mTree[nId].m_vInters.size() ; + // numero di vertici aggiunti al nuovo poligono + int c = 0 ; + + // loop interni in una cella intersecata + if ( m_mTree[nId].m_nFlag == 3 || m_mTree[nId].m_nFlag == 2) { + PolyLine plInLoop ; + // numero dei loop interni passati + int n = 0 ; + Inters inA = m_mTree[nId].m_vInters[n] ; + if ( m_mTree[nId].m_nFlag == 2 && inA.nOut == -3) { + // i loop esterni sono CW, quindi prima dei loop di trim aggiungo il bordo cella + Point3d ptVert = m_mTree[nId].GetTopRight() ; + plInLoop.AddUPoint( 0, ptVert) ; + ptVert.x = m_mTree[nId].GetBottomLeft().x ; + ptVert.y = m_mTree[nId].GetTopRight().y ; + plInLoop.AddUPoint( 1, ptVert) ; + ptVert = m_mTree[nId].GetBottomLeft() ; + plInLoop.AddUPoint( 2, ptVert) ; + ptVert.x = m_mTree[nId].GetTopRight().x ; + ptVert.y = m_mTree[nId].GetBottomLeft().y ; + plInLoop.AddUPoint( 3, ptVert) ; + plInLoop.Close(); + vCellPolygons.push_back( plInLoop) ; + vPolygons.push_back( vCellPolygons) ; + ++ nPoly ; + vnParentChunk.push_back( inA.nChunk) ; + vCellPolygons.clear() ; + plInLoop.Clear() ; + } + while ( inA.nIn == -1) { + // numero di vertici aggiunti al nuovo poligono + int k = 0 ; + for ( Point3d ptInt : inA.vpt) { + plInLoop.AddUPoint( c, ptInt) ; + ++ k ; + } + plInLoop.Close(); + bool bAdded = false ; + // se il loop è CW devo controllare in quale altro dei poligoni che ho già aggiunto è contenuto + if ( ! inA.bCCW) { + Point3d ptStart ; + plInLoop.GetFirstPoint( ptStart) ; + int nOtherPoly = (int)vPolygons.size() ; + for ( int r = 0 ; r < nPoly ; ++r ) { + if ( IsPointInsidePolyLine( ptStart, vPolygons[nOtherPoly - r - 1][0], -0.01) && vnParentChunk[nPoly - r - 1] == inA.nChunk ) { + vPolygons[nOtherPoly - r - 1].push_back( plInLoop) ; + plInLoop.Clear() ; + vnParentChunk.push_back( inA.nChunk) ; + bAdded = true ; + break ; + } + } + } + if ( ! bAdded ) { + vCellPolygons.push_back( plInLoop) ; + vPolygons.push_back( vCellPolygons) ; + ++ nPoly ; + vnParentChunk.push_back( inA.nChunk) ; + plInLoop.Clear() ; + vCellPolygons.clear() ; + } + + plInLoop.Clear() ; + ++ n ; + inA = m_mTree[nId].m_vInters[n] ; + } + } + return true ; +} + //---------------------------------------------------------------------------- bool Tree::CheckIfBefore( PolyLine& pl, int nEdge) const diff --git a/Tree.h b/Tree.h index dbb8378..b442371 100644 --- a/Tree.h +++ b/Tree.h @@ -73,8 +73,8 @@ class Cell double m_dSplit ; // parametro a cui è stata splittata la cella int m_nChild1 ; // prima cella figlio int m_nChild2 ; // seconda cella figlio - int m_nFlag ; // falg che indica la caratterizzazaione della cella rispetto ai loop di trim - // -1 non categorizzata + int m_nFlag ; // falg che indica la caratterizzazione della cella rispetto ai loop di trim + int m_nFlag2 ; // falg che indica se la cella è stata attraversata durante l'ultima fase del labelling // 0 esterna, 1 intersecata, 2 contiene un loop, 3 intersecata e contenente un loop, 4 contenuta in un loop int m_nRightEdgeIn ; // 0 right edge fuori, 1 right edge dentro, 2 metà e metà INTVECTOR m_vnLoop ; // indice dei loop contenuti nella cella @@ -119,6 +119,8 @@ private : bool TraceLoopLabelCell( void) ; // tracing dei loop e labelling delle celle bool FindInters( int& nId, CurveLine& clTrim, PNTVECTOR& vptInters) ; // trova le intersezioni tra una cella e una linea di trim // resituisce l'id della cella verso cui la curva di trim esce e il vettore delle intersezioni per la cella successiva con il primo punto + bool CreateCellPolygons ( int nLeafId, std::vector& vPolygons, INTVECTOR& vToCheck, int& nPoly, INTVECTOR& vnParentChunk) ; + bool CreateIslandAndHoles ( int nLeafId, std::vector& vPolygons, int& nPoly, INTVECTOR& vnParentChunk) ; bool CheckIfBefore( PolyLine& pl, int nEdge) const ; bool CheckIfAfter( PolyLine& pl, Point3d& ptNextStart, int nEdge) const ; @@ -135,7 +137,7 @@ private : bool m_bClosed ; // superficie chiusa int m_nDegU ; // grado della superficie nel parametro U int m_nDegV ; // grado della superficie nel parametro V - POLYLINEVECTOR m_vPolygons ; // vettore dei poligoni del tree + std::vector m_vPolygons ; // vettore dei poligoni del tree //std::map m_mPolygons ; // mappa dei poligoni std::map m_mTree ; // mappa che contiene tutti i nodi e le foglie dell'albero. -2 è puntatore Null e -1 è root std::map m_mVert ; // mappa che contiene tutti i vertici 3d delle celle del tree. L'Id è lo stesso che la cella ha in m_mTree