From f3346fd1f19e7269b8ba456328722121bb7dca57 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Tue, 6 Jun 2023 16:36:09 +0200 Subject: [PATCH] EgtGeomKernel : - sistemati vari bug nella creazione della superficie trimesh trimmata si una superficie di bezier Problemi noti : - sui casi con un tree reale entro in un loop infinito o seleziono oppure seleziono un elemento inesistente di un vettore --- Tree.cpp | 240 ++++++++++++++++++++++++++----------------------------- Tree.h | 5 +- 2 files changed, 118 insertions(+), 127 deletions(-) diff --git a/Tree.cpp b/Tree.cpp index 131e469..ec0d431 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -1393,6 +1393,12 @@ Tree::FindCell( const Point3d& ptToAssign, CurveLine& clTrim) const //nCells.push_back( - 2) ; return nCells ; } + + // se lo spazio parametrico non è stato suddiviso ( ho un piano), restituisco la cella root + if ( m_mTree.at(nId).IsLeaf() ) { + nCells.push_back( nId) ; + return nCells ; + } while ( ! m_mTree.at(nId).IsLeaf()) { if ( m_mTree.at(nId).IsSplitVert()) { @@ -2164,23 +2170,24 @@ Tree::CreateCellPolygons( int nLeafId, std::vector& vPolygons, I // in questo for analizzo solo i loop che tagliano la cella int nEdgeIn = -1 ; int nFirstLoopInPoly = -1 ; + INTVECTOR vAddedLoops ; for ( int w = 0 ; w < (int)vToCheckNow.size() ; ++ w) { - // primo loop di questo poligono + // indice del loop in m_vInters int j = vToCheckNow[w] ; Inters inA = m_mTree[nId].m_vInters[j] ; if ( inA.nIn != -1 ) { int nEdge ; - if ( nEdgeIn == -1 ) + if ( nEdgeIn == -1 ) { // salvo il lato di ingresso del primo lato del poligono che sto costruendo nEdgeIn = inA.nIn ; + nFirstLoopInPoly = j ; + } for ( Point3d ptInt : inA.vpt ) { AddVertex( nId, vEdgeVertex, plTrimmedPoly, c, ptInt) ; - //plTrimmedPoly.AddUPoint(c, ptInt) ; - //++c ; } + vAddedLoops.push_back( j) ; 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 - // qui ho tolto l'if e esteso anche ai casi CCW perché anche lì devo controllare!!!!!//////////////////////////////////////////////////////////// + // devo verificare di non essere uscito in un vertice, con un tratto sovrapposto al lato che ripercorrerò tra poco Point3d ptLast, ptSecondToLast; plTrimmedPoly.GetLastPoint(ptLast) ; plTrimmedPoly.GetPrevPoint(ptSecondToLast) ; @@ -2240,7 +2247,7 @@ Tree::CreateCellPolygons( int nLeafId, std::vector& vPolygons, I bool bNotCameBack = true ; bool bValidNextStart = false ; bool bAtNextStart = false ; - if ( j < nPassToCheck - 1) { + if ( w < nPassToCheck - 1) { // ho messo w al posto di j //////////////////////////////////////////////////////////////////////////////////////// int nSecondCheck = 0 ; int nNext ; // ciclo sui loop successivi per vedere se ne ho uno con un valid start @@ -2253,39 +2260,12 @@ Tree::CreateCellPolygons( int nLeafId, std::vector& vPolygons, I } else { ++ nSecondCheck ; - vToCheck.push_back( t) ; + vToCheck.push_back( vToCheckNow[t]) ; } } - //// 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 ( AreSameEdge( nEdge, m_mTree[nId].m_vInters[j].nIn) ) { - // if ( m_mTree[nId].m_vInters[j].bCCW) { - // bValidNextStart = ( AreSameEdge( 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 = ( AreSameEdge( 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 = CheckIfAfter( plTrimmedPoly, m_mTree[nId].m_vInters[vToCheckNow[t + 1]].vpt[0], nEdge) ; - // if ( ! AreSameEdge( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn, nEdge) || bValidNextStart) - // //if ( bValidNextStart) - // break ; - // // se ho trovato un loop successivo che devo saltare, lo salvo e considero i loop più avanti. - // if ( AreSameEdge( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn, nEdge) && ! bValidNextStart){ - // //else { - // ++ nSecondCheck ; - // vToCheck.push_back( t + 1) ; - // } - //} - bNotCameBack = ! ( AreSameEdge( nEdge, nEdgeIn) && CheckIfBefore( plTrimmedPoly, nEdge)) ; - //while ( ! bValidNextStart && bNotCameBack) { while ( ! ( bValidNextStart && bAtNextStart) && bNotCameBack) { Point3d ptVert ; if ( nEdge == 0) @@ -2297,8 +2277,6 @@ Tree::CreateCellPolygons( int nLeafId, std::vector& vPolygons, I else if ( nEdge == 3) ptVert = m_mTree[nId].GetTopRight() ; AddVertex( nId, vEdgeVertex, plTrimmedPoly, c, ptVert) ; - //plTrimmedPoly.AddUPoint( c, ptVert) ; - //++c ; if ( nEdge > 3 && nEdge != 7) nEdge = nEdge - 4 ; else if ( nEdge < 3 ) @@ -2311,50 +2289,10 @@ Tree::CreateCellPolygons( int nLeafId, std::vector& vPolygons, I bAtNextStart = AreSameEdge( nEdge, m_mTree[nId].m_vInters[vToCheckNow[nNext]].nIn) ; bNotCameBack = ! ( AreSameEdge( nEdge, nEdgeIn) && CheckIfBefore( plTrimmedPoly, nEdge)) ; - - /*for ( int t = w + 1 ; t < nPassToCheck -1 ; ++ t) { - bValidNextStart = CheckIfBetween( m_mTree[nId].m_vInters[j], m_mTree[nId].m_vInters[vToCheckNow[t]]) ; - if ( bValidNextStart) { - bAtNextStart = AreSameEdge( m_mTree[nId].m_vInters[j].nOut, m_mTree[nId].m_vInters[vToCheckNow[t]].nIn) ; - break ; - } - else { - ++ nSecondCheck ; - vToCheck.push_back( t) ; - } - }*/ - - // 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 ( AreSameEdge( nEdge, m_mTree[nId].m_vInters[j].nIn) ) { - // if ( m_mTree[nId].m_vInters[j].bCCW) { - // bValidNextStart = ( AreSameEdge( 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 = ( AreSameEdge( 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 = CheckIfAfter( plTrimmedPoly, m_mTree[nId].m_vInters[vToCheckNow[t + 1]].vpt[0], nEdge) ; - // if ( ! AreSameEdge( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn, nEdge) || bValidNextStart) - // //if ( bValidNextStart) - // break ; - // // se ho trovato un loop successivo che devo saltare, lo salvo e considero i loop più avanti. - // if ( AreSameEdge( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn, nEdge) && ! bValidNextStart){ - // //else { - // ++ nSecondCheck ; - // vToCheck.push_back( t + 1) ; - // } - //} } // se ho trovato un altro loop salto all'inizio del for - // - //if ( AreSameEdge( m_mTree[nId].m_vInters[vToCheckNow[w + 1 + nSecondCheck]].nIn, nEdge) && bValidNextStart) { // qui ho aggiunto bValidNextStart///////////////////////// - if ( bValidNextStart) { /////////////////////////////// - w = w + nSecondCheck ; + if ( bValidNextStart) { + w = w + nSecondCheck ; continue ; } } @@ -2398,6 +2336,14 @@ Tree::CreateCellPolygons( int nLeafId, std::vector& vPolygons, I c = 0 ; plTrimmedPoly.Clear() ; nEdgeIn = -1 ; + // devo verificare se tra i loop che sono finiti in vToCheck in realtà qualcuno l'ho usato per fare un poligono///////////////////////////////////// + for ( int k = 0 ; k < (int)vToCheck.size() ; ++ k) { + for ( int i = 0 ; i < (int)vAddedLoops.size() ; ++ i) { + if ( vToCheck[k] == vAddedLoops[i] ) { + vToCheck.erase(vToCheck.begin() + k) ; + } + } + } } else continue ; @@ -2551,7 +2497,7 @@ bool Tree::CheckIfBefore( int& nEdge1, Point3d& ptP1, int& nEdge2, Point3d& ptP2) const { INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6} ; - // controllo se nEdge1 viene prima di nEdge2. la partenza è da ptTR e l'arrivo è ptBr + // controllo se ptP1, che è su nEdge1, viene prima di ptP2, che è su nEdge2. la partenza è da ptTR e l'arrivo è ptBr INTVECTOR :: iterator iter1 = find( vEdges.begin(), vEdges.end(), nEdge1) ; int nPos1 = std::distance( vEdges.begin(), iter1) ; INTVECTOR :: iterator iter2 = find( vEdges.begin(), vEdges.end(), nEdge2) ; @@ -2574,53 +2520,58 @@ Tree::CheckIfBefore( int& nEdge1, Point3d& ptP1, int& nEdge2, Point3d& ptP2) con //---------------------------------------------------------------------------- bool -Tree::CheckIfAfter( PolyLine& pl, Point3d& ptNextStart, int nEdge, bool bSameEdge) const +Tree::CheckIfBefore( int& nEdge, Point3d& ptP1, Point3d& ptP2) const +{ + // sul lato nEdge controllo se ptP1 viene prima di ptP2. + // i lati vengono percorsi in senso antiorario + if ( nEdge == 0 ) { + return ptP1.x > ptP2.x ; + } + else if ( nEdge == 1 ) { + return ptP1.y > ptP2.y ; + } + else if ( nEdge == 2 ) { + return ptP1.x < ptP2.x ; + } + else if ( nEdge == 3 ) { + return ptP1.y < ptP2.y ; + } + return false ; +} + +//---------------------------------------------------------------------------- +bool +Tree::CheckIfAfter( PolyLine& pl, Point3d& ptNextStart, int nEdge) const { // controllo se ptNextStart è più avanti rispetto a ptEnd in senso antiorario // ATTENZIONE i due punti devono essere sullo stesso lato! - // se i punti non sono sullo stesso lato ritorno false ( con bSameEdge == true) + // se i punti non sono sullo stesso lato ritorno false Point3d ptEnd ; pl.GetLastPoint( ptEnd) ; if ( nEdge == 0 ) { - if ( bSameEdge) { - if ( ptNextStart.y > ptEnd.y - EPS_SMALL && ptNextStart.y < ptEnd.y + EPS_SMALL) - return ptEnd.x > ptNextStart.x ; - else - return false ; - } - else + if ( ptNextStart.y > ptEnd.y - EPS_SMALL && ptNextStart.y < ptEnd.y + EPS_SMALL) return ptEnd.x > ptNextStart.x ; + else + return false ; } else if ( nEdge == 1 ) { - if ( bSameEdge) { - if ( ptNextStart.x > ptEnd.x - EPS_SMALL && ptNextStart.x < ptEnd.x + EPS_SMALL) - return ptEnd.y > ptNextStart.y ; - else - return false ; - } - else + if ( ptNextStart.x > ptEnd.x - EPS_SMALL && ptNextStart.x < ptEnd.x + EPS_SMALL) return ptEnd.y > ptNextStart.y ; + else + return false ; } else if ( nEdge == 2 ) { - if ( bSameEdge) { - if ( ptNextStart.y > ptEnd.y - EPS_SMALL && ptNextStart.y < ptEnd.y + EPS_SMALL) - return ptEnd.x < ptNextStart.x ; - else - return false ; - } - else + if ( ptNextStart.y > ptEnd.y - EPS_SMALL && ptNextStart.y < ptEnd.y + EPS_SMALL) return ptEnd.x < ptNextStart.x ; + else + return false ; } else if ( nEdge == 3 ) { - if ( bSameEdge) { - if ( ptNextStart.x > ptEnd.x - EPS_SMALL && ptNextStart.x < ptEnd.x + EPS_SMALL) - return ptEnd.y < ptNextStart.y ; - else - return false ; - } - else + if ( ptNextStart.x > ptEnd.x - EPS_SMALL && ptNextStart.x < ptEnd.x + EPS_SMALL) return ptEnd.y < ptNextStart.y ; + else + return false ; } return false ; } @@ -2992,33 +2943,72 @@ Tree::CategorizeCell( int& nId) //---------------------------------------------------------------------------- bool -Tree::CheckIfBetween( Inters& intA, Inters& intB) const +Tree::CheckIfBetween( Inters& inA, Inters& inB) const { - // controllo se intB è compreso tra l'end e lo start di intA + // controllo se inB è compreso tra l'end e lo start di inA // ( dall'end di A percorro i bordi della cella fino a tornare allo start e devo incontrare In e Out di B) INTVECTOR vEdges ; - int nEdge = intA.nOut ; - vEdges.push_back( nEdge) ; - if ( nEdge == 3) - nEdge = 0 ; - else - ++ nEdge ; - while ( nEdge != intA.nIn ) { + int nEdge = inA.nOut ; + //vEdges.push_back( nEdge) ; + //if ( nEdge == 3) + // nEdge = 0 ; + //else + // ++ nEdge ; + while ( nEdge != inA.nIn || (int) vEdges.size() == 0) { vEdges.push_back( nEdge) ; if ( nEdge == 3) nEdge = 0 ; else ++ nEdge ; } + if ( inA.nIn != inA.nOut) + vEdges.push_back( nEdge) ; bool bFound = false ; for ( int i : vEdges) { - if ( intB.nIn == i) { - PolyLine pl ; - pl.AddUPoint( 0, intA.vpt[0]) ; - pl.AddUPoint( 1, intA.vpt.back()) ; - if ( CheckIfAfter( pl, intB.vpt[0], i, false)) - bFound = true ; + if ( inB.nIn == i) { + if ( inB.nIn == inA.nIn && inA.nIn == inA.nOut ) { + nEdge = inA.nIn ; + //se l'inizio di A è prima della fine, allora devo controllare che B sia compreso tra Out e In (esterno) + if ( CheckIfBefore( nEdge, inA.vpt[0], inA.vpt.back()) ) { + if ( CheckIfBefore( nEdge, inA.vpt.back(), inB.vpt[0]) || CheckIfBefore( nEdge, inB.vpt[0], inA.vpt[0])) + bFound = true ; + } + // se l'inizio di A è dopo la fine, allora devo controllare che B sia compreso tra In e Out ( interno) + else { + if ( CheckIfBefore( nEdge, inA.vpt.back(), inB.vpt[0]) && CheckIfBefore( nEdge, inB.vpt[0], inA.vpt[0])) + bFound = true ; + } + + // alternativa + // percorrendo il lato in modo ciclico ( con condizioni al contorno che dalla fine mi riportano all'inizio) + // partendo da OutA devo incontrare InB e poi InA + //if ( CheckIfBefore( nEdge, inA.vpt.back(), nEdge, inB.vpt[0]) && CheckIfBefore( nEdge, inA.vpt.back(), nEdge, inB.vpt[0])) { + // bFound = true ; + //} + // mancano gli altri due casi da aggiungere alla ( condizione) || ( ) || ( ) + } + else if ( inB.nIn == inA.nOut) { + PolyLine pl ; + pl.AddUPoint( 0, inA.vpt[0]) ; + pl.AddUPoint( 1, inA.vpt.back()) ; + if ( CheckIfAfter( pl, inB.vpt[0], i)) + bFound = true ; + } + else if ( inB.nIn == inA.nIn ) { + //devo controllare il loop b sia prima dell'inizio di A + if ( CheckIfBefore(inA.nIn, inB.vpt[0], inA.nIn, inA.vpt[0])) + bFound = true ; + } + else + // devo controllare che inB sia prima di OutB + if ( inB.nOut == inB.nIn && CheckIfBefore( inB.nOut, inB.vpt[0], inB.vpt.back())) { + bFound = true ; + } + else if ( inB.nOut != inB.nIn) + bFound = true ; } + if ( inB.nOut == i && ! bFound) + break ; } return bFound ; } diff --git a/Tree.h b/Tree.h index fb3663e..55b76f0 100644 --- a/Tree.h +++ b/Tree.h @@ -127,13 +127,14 @@ private : bool CheckIfBefore( PolyLine& pl, int nEdge) const ; bool CheckIfBefore( Inters& inA) const ; bool CheckIfBefore( int& nEdge1, Point3d& ptP1, int& nEdge2, Point3d& ptP2) const ; - bool CheckIfAfter( PolyLine& pl, Point3d& ptNextStart, int nEdge, bool bSameEdge = true) const ; + bool CheckIfBefore( int& nEdge, Point3d& ptP1, Point3d& ptP2) const ; + bool CheckIfAfter( PolyLine& pl, Point3d& ptNextStart, int nEdge) const ; bool AreSameEdge( int nEdge1, int nEdge2) const ; bool AddVertex( int nId, std::vector& vEdgeVertex, PolyLine& plTrimmedPoly, int& c, Point3d& ptToAdd) const ; //bool SetRightEdgeIn( int nId, std::vector& vEdgeVertex, PolyLine& plTrimmedPoly) ; bool SetRightEdgeIn( int nId) ; bool CategorizeCell( int& nId) ; - bool CheckIfBetween( Inters& intA, Inters& intB) const ; + bool CheckIfBetween( Inters& inA, Inters& inB) const ; private : const SurfBezier* m_pSrfBz ; // superficie di bezier