diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 23460a2..513306f 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1507,13 +1507,21 @@ SurfBezier::GetAuxSurf( void) const Tree Tree( this, true) ; BIPNTVECTOR vTrees ; Tree.GetIndependentTrees( vTrees) ; + bool bTest = false ; // per debug for ( int i = 0 ; i < (int) vTrees.size() ; ++ i) { Point3d ptMin = std::get<0>( vTrees[i]) ; Point3d ptMax = std::get<1>( vTrees[i]) ; Tree.SetSurf( this, true, ptMin, ptMax) ; - Tree.BuildTree( 5 * LIN_TOL_FINE, 0.1) ; + if ( bTest) { + Tree.BuildTree_test() ; // per debug + //Tree.BuildTree( 5 * LIN_TOL_FINE, 1) ; // per debug + Tree.SetTestMode() ; + } + else { + Tree.BuildTree( 5 * LIN_TOL_FINE, 0.1) ; + } Tree.GetPolygons( vvPL) ; - // + //Tree.GetPolygonsBasic( vPL) ; // per usare i polygon basic } //// per usare i polygon basic////////////////////// @@ -1572,7 +1580,14 @@ SurfBezier::GetLeaves( vector>& vLeaves) const Point3d ptMin = get<0>( vTrees[i]) ; Point3d ptMax = get<1>( vTrees[i]) ; Tree.SetSurf( this, true, ptMin, ptMax) ; - Tree.BuildTree( 5 * LIN_TOL_FINE, 0.1) ; + bool bTest = false ; // per debug + if ( bTest) { + Tree.BuildTree_test() ; // per debug + //Tree.BuildTree( 5 * LIN_TOL_FINE, 1) ; // per debug + } + else { + Tree.BuildTree( 5 * LIN_TOL_FINE, 0.1) ; + } vector vCells ; Tree.GetLeaves( vCells) ; for ( int k = 0 ; k < int( vCells.size()) ; ++ k) { diff --git a/Tree.cpp b/Tree.cpp index 9536a8d..387568c 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -35,7 +35,7 @@ using namespace std ; //---------------------------------------------------------------------------- Tree::Tree( void) - : m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_bSplitPatches( true) + : m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_bSplitPatches( true), m_bTestMode( false) { Point3d ptBl( 0, 0), ptTr ( 1 * SBZ_TREG_COEFF, 1 * SBZ_TREG_COEFF) ; Cell cRoot( ptBl, ptTr) ; @@ -44,7 +44,7 @@ Tree::Tree( void) //---------------------------------------------------------------------------- Tree::Tree( const SurfBezier* pSrfBz, const bool bSplitPatches, const Point3d& ptMin, const Point3d& ptMax) - : m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_bSplitPatches( true) + : m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_bSplitPatches( true), m_bTestMode( false) { SetSurf( pSrfBz, bSplitPatches, ptMin, ptMax) ; } @@ -554,6 +554,8 @@ Tree::BuildTree_test( double dLinTol, double dSideMin, double dSideMax) Split( 10) ; m_vnLeaves.push_back( 20) ; m_vnLeaves.push_back( 21) ; + // riempio anche la lista dei parent delle celle + m_vnParents = m_vnLeaves ; return true ; } @@ -1496,9 +1498,9 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons) reverse( vNeigh.begin(), vNeigh.end()) ; // aggiungo i vertici che sono sul lato top, solo se ho più di un vicino top if ( ! vNeigh.empty() && vNeigh.size() != 1) { - // se la superficie è chiusa lungo il parametro U e la cella è sul lato top + // se la superficie è chiusa lungo il parametro V e la cella è sul lato top // devo aggiungere i vertici tenendo conto della periodicità dello spazio parametrico. - if ( m_bClosedU && m_mTree.at( nId).m_bOnTopEdge) { + if ( m_bClosedV && m_mTree.at( nId).m_bOnTopEdge) { for ( int j : vNeigh) { Point3d pt( m_mTree.at( j).GetBottomLeft().x, m_mTree.at( nId).GetTopRight().y) ; vVertices.push_back( pt) ; @@ -1596,6 +1598,7 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& clTrim, bool bRecurs int nId = -1 ; // se fallisce ritorna un vettore vuoto // verifico che il punto sia all'interno dello spazio parametrico + // allargo i bordi in modo da tenere anche i punti sul bordo dello spazio parametrico if ( ptToAssign.x < m_mTree.at( -1).GetBottomLeft().x - EPS_SMALL || ptToAssign.x > m_mTree.at( -1).GetTopRight().x + EPS_SMALL|| ptToAssign.y < m_mTree.at( -1).GetBottomLeft().y - EPS_SMALL || ptToAssign.y > m_mTree.at( -1).GetTopRight().y + EPS_SMALL) { //nCells.push_back( - 2) ; @@ -1604,15 +1607,19 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& clTrim, bool bRecurs // se ho diviso preliminarmente le patches e in uno dei due parametri ho un numero dispari di patches devo individuare a mano la cella parent // in cui individuare la foglia giusta - if ( m_bSplitPatches && ( m_nSpanU > 1 || m_nSpanV > 1)) { + if ( (m_bSplitPatches && ( m_nSpanU > 1 || m_nSpanV > 1)) || m_bTestMode) { INTVECTOR nParents = FindCell( ptToAssign, clTrim, m_vnParents) ; nId = nParents.back() ; + if ( m_bTestMode ) { + nCells.push_back(nId) ; + return nCells ; + } } // individuo la foglia in cui ho lo start del loop while ( ! m_mTree.at( nId).IsLeaf()) { if ( m_mTree.at( nId).IsSplitVert()) { double dMid = ( m_mTree.at( nId).GetBottomLeft().x + m_mTree.at( nId).GetTopRight().x) / 2 ; - if ( ptToAssign.x < dMid + EPS_SMALL) { + if ( ptToAssign.x < dMid) { nId = m_mTree.at( nId).m_nChild1 ; } else { @@ -1621,7 +1628,7 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& clTrim, bool bRecurs } else { double dMid = ( m_mTree.at( nId).GetBottomLeft().y + m_mTree.at( nId).GetTopRight().y) / 2 ; - if ( ptToAssign.y < dMid + EPS_SMALL) { + if ( ptToAssign.y < dMid) { nId = m_mTree.at( nId).m_nChild2 ; } else { @@ -1638,23 +1645,29 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& clTrim, bool bRecurs if ( abs( ptToAssign.x - ptTl.x) < EPS_SMALL || abs( ptToAssign.x - ptBr.x) < EPS_SMALL || abs( ptToAssign.y - ptTl.y) < EPS_SMALL || abs( ptToAssign.y - ptBr.y) < EPS_SMALL) { - Point3d ptToAssignPlus ; - double dParam ; Vector3d vtDir ; - clTrim.GetParamAtPoint( ptToAssign, dParam, EPS_SMALL) ; - clTrim.GetPointTang( dParam + EPS_SMALL, ICurve::FROM_MINUS, ptToAssignPlus, vtDir) ; + clTrim.GetStartDir( vtDir) ; + // proseguo lungo la curva di trim di EPS_SMALL + Point3d ptToAssignPlus = ptToAssign + vtDir * EPS_SMALL ; + // se la curva di trim è praticamente parallela ad un lato allora giro a destra, perché voglio considerare intersecate le celle esterne ( sul bordo) al loop if ( abs( vtDir.x) > 1 - EPS_SMALL || abs( vtDir.y) > 1 - EPS_SMALL) { - vtDir.Rotate( Z_AX, -90) ; - ptToAssignPlus = ptToAssignPlus + vtDir * 2 * EPS_SMALL ; + Vector3d vtDirDX = vtDir ; vtDirDX.Rotate( Z_AX, 90) ; + ptToAssignPlus = ptToAssignPlus + vtDir * EPS_SMALL ; + // controllo di non essere uscito dallo spazio parametrico ed eventualmente giro a sinistra + if ( ptToAssignPlus.x < m_mTree.at( -1).GetBottomLeft().x - EPS_SMALL || ptToAssignPlus.x > m_mTree.at( -1).GetTopRight().x + EPS_SMALL|| + ptToAssignPlus.y < m_mTree.at( -1).GetBottomLeft().y - EPS_SMALL || ptToAssignPlus.y > m_mTree.at( -1).GetTopRight().y + EPS_SMALL) { + // rispetto al punto di partenza avanzo lungo la curva di trim + ptToAssignPlus = ptToAssign + vtDir * EPS_SMALL ; + Vector3d vtDirSX = vtDir ; vtDirSX.Rotate( Z_AX, -90) ; + // e poi giro a sinistra + ptToAssignPlus = ptToAssign + vtDir * EPS_SMALL ; + } } + INTVECTOR nCellsSave = nCells ; nCells = FindCell( ptToAssignPlus, clTrim, true) ; if ( nCells.empty()) { - ptToAssignPlus = ptToAssignPlus - 2 * vtDir * EPS_SMALL ; - vtDir.Rotate( Z_AX, 90) ; - ptToAssignPlus = ptToAssignPlus + 10 * vtDir * EPS_SMALL ; - nCells = FindCell( ptToAssignPlus, clTrim, true) ; - if ( nCells.empty()) - nCells.push_back( nId) ; + // se nonostante tutto non trovo nulla allora tengo il risultato ottenuto scorrendo l'albero + nCells = nCellsSave ; } } } @@ -1693,15 +1706,13 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells else if ( (int)nCells.size() >= 1 ) { // la CurveLine è il segmento di trim su cui giace ptToAssign Point3d ptIntersPlus ; - double dParam ; - Vector3d vDir ; - cl.GetParamAtPoint( ptToAssign, dParam, EPS_SMALL) ; - cl.GetStartDir( vDir) ; + Vector3d vtDir ; + cl.GetStartDir( vtDir) ; // mi sposto appena più avanti di ptToAssign // se la curva è orientata come l'asse x o y mi sto muovendo su un lato e sarò ancora sul lato, quindi dovrei ruotare il vettore prima di spostarmi - if ( abs( vDir.x) >= 1 - EPS_SMALL || abs( vDir.y) >= 1 - EPS_SMALL) - vDir.Rotate( Z_AX, -45) ; - ptIntersPlus = ptToAssign + vDir * EPS_SMALL ; + if ( abs( vtDir.x) >= 1 - EPS_SMALL || abs( vtDir.y) >= 1 - EPS_SMALL) + vtDir.Rotate( Z_AX, -45) ; + ptIntersPlus = ptToAssign + vtDir * EPS_SMALL ; nCells = FindCell( ptIntersPlus, cl, vCells) ; } // se vuoto allora il punto non è in nessuna delle celle passate in input @@ -2012,7 +2023,6 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool int nEdge ; // flag che indica il lato su cui ho l'intersezione a partire dal lato top in senso antiorario // oltre il 3 sono le celle adiacenti in diagonale al vertice-> 4 corrisponde al ptTl e da lì in senso antiorario // -1 se la curva è sempre dentro la cella - bool bIntersFound = false ; Point3d ptInters ; int nEdge2 ; if ( ptEnd.y >= ptTR.y && ptEnd.x <= ptTR.x) { @@ -2024,16 +2034,6 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool nEdge2 = 1 ; clEdge2.Set( ptTl, ptBL) ; } - //else if ( AreSamePointExact( ptEnd, ptTl) && bFirstInters) { - // nEdge = 4 ; - // ptInters = ptTl ; - // bIntersFound = true ; - //} - //else if ( AreSamePointExact( ptEnd, ptTR) && bFirstInters) { - // nEdge = 7 ; - // ptInters = ptTR ; - // bIntersFound = true ; - //} } else if ( ptEnd.x <= ptBL.x && ptEnd.y <= ptTR.y) { nEdge = 1 ; @@ -2044,16 +2044,6 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool nEdge2 = 2 ; clEdge2.Set( ptBL, ptBr) ; } - //else if ( AreSamePointExact( ptEnd, ptBL) && bFirstInters) { - // nEdge = 5 ; - // ptInters = ptBL ; - // bIntersFound = true ; - //} - //else if ( AreSamePointExact( ptEnd, ptTl) && bFirstInters) { - // nEdge = 4 ; - // ptInters = ptTl ; - // bIntersFound = true ; - //} } else if ( ptEnd.y <= ptBL.y && ptEnd.x >= ptBL.x) { nEdge = 2 ; @@ -2064,16 +2054,6 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool nEdge2 = 3 ; clEdge2.Set( ptBr, ptTR) ; } - //else if ( AreSamePointExact( ptEnd, ptBr) && bFirstInters) { - // nEdge = 6 ; - // ptInters = ptBr ; - // bIntersFound = true ; - //} - //else if ( AreSamePointExact( ptEnd, ptBL) && bFirstInters) { - // nEdge = 5 ; - // ptInters = ptBL ; - // bIntersFound = true ; - //} } else if ( ptEnd.x >= ptTR.x && ptEnd.y >= ptBL.y) { nEdge = 3 ; @@ -2084,71 +2064,44 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool nEdge2 = 0 ; clEdge2.Set( ptTR, ptTl) ; } - //else if ( AreSamePointExact( ptEnd, ptTR) && bFirstInters) { - // nEdge = 7 ; - // ptInters = ptTR ; - // bIntersFound = true ; - //} - //else if ( AreSamePointExact( ptEnd, ptBr) && bFirstInters) { - // nEdge = 6 ; - // ptInters = ptBr ; - // bIntersFound = true ; - //} } else return false ; - bool bIntersOn2Found = false ; - if ( ! bIntersFound) { - // intersezione e controlli - IntersLineLine illExit( clTrim, clEdge, true) ; - IntCrvCrvInfo aInfo, aInfo2 ; - bool bIntersOn1Found = true ; - if ( ! illExit.GetIntCrvCrvInfo( aInfo)) { - bIntersOn1Found = false ; - if ( ! clEdge2.IsValid()) - return false ; - } - //else if ( aInfo.bOverlap && ! bFirstInters) { - // ptInters = aInfo.IciA[1].ptI ; - // bIntersFound = true ; - //} + bool bIntersFound = false ; + // intersezione e controlli + IntersLineLine illExit( clTrim, clEdge, true) ; + IntCrvCrvInfo aInfo, aInfo2 ; + if ( ! illExit.GetIntCrvCrvInfo( aInfo)) { + bIntersFound = false ; + if ( ! clEdge2.IsValid()) + return false ; + } + else { + bIntersFound = true ; + if ( aInfo.bOverlap) + ptInters = aInfo.IciA[1].ptI ; else - bIntersOn1Found = true ; - if ( clEdge2.IsValid() && ! bIntersOn1Found){ - IntersLineLine illExit2( clTrim, clEdge2, true) ; - // verifico su quale dei due lati ho l'intersezione - if ( ! illExit2.GetIntCrvCrvInfo( aInfo2)){ - if ( bIntersOn1Found) { - // se ho intersezione su Edge1 con sovrapposizione, seleziono o il primo punto o il secondo. - if ( aInfo.bOverlap && ! bFirstInters) - ptInters = aInfo.IciA[1].ptI ; - else - ptInters = aInfo.IciA[0].ptI ; - } - else - return false ; - } - else { - //// solo intersezione sul lato 2 - bIntersOn2Found = true ; - if ( aInfo2.bOverlap && ! bFirstInters) - ptInters = aInfo2.IciA[1].ptI ; - else - ptInters = aInfo2.IciA[0].ptI ; - } - } + ptInters = aInfo.IciA[0].ptI ; + } + if ( clEdge2.IsValid() && ! bIntersFound){ + IntersLineLine illExit2( clTrim, clEdge2, true) ; + // verifico su quale dei due lati ho l'intersezione + if ( ! illExit2.GetIntCrvCrvInfo( aInfo2)) + bIntersFound = false ; else { - if ( aInfo.bOverlap && ! bFirstInters) - ptInters = aInfo.IciA[1].ptI ; + bIntersFound = true ; + //// solo intersezione sul lato 2 + if ( aInfo2.bOverlap) + ptInters = aInfo2.IciA[1].ptI ; else - ptInters = aInfo.IciA[0].ptI ; + ptInters = aInfo2.IciA[0].ptI ; } } - if ( ! bIntersOn2Found) - OnWhichEdge( nId, ptInters, nEdge) ; - else - nEdge = nEdge2 ; + if ( ! bIntersFound) + return false ; + // determino il lato/vertice di uscita + OnWhichEdge( nId, ptInters, nEdge) ; m_mTree[nId].m_vInters.back().nOut = nEdge ; if ( (int)vptInters.size() == 0 || ! AreSamePointExact( ptInters , vptInters.back())) vptInters.push_back( ptInters) ; @@ -2290,11 +2243,13 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool m_mTree[nId].m_vInters.emplace_back() ; m_mTree[nId].m_vInters.back().nIn = 6 ; } - else { + else if (! vNeigh1.empty()) { nId = vNeigh1.back() ; m_mTree[nId].m_vInters.emplace_back() ; m_mTree[nId].m_vInters.back().nIn = 7 ; } + else + return false ; } } else if ( nEdge == 5) { @@ -2339,11 +2294,13 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool m_mTree[nId].m_vInters.emplace_back() ; m_mTree[nId].m_vInters.back().nIn = 7 ; } - else { + else if (! vNeigh1.empty()) { nId = vNeigh1[0] ; m_mTree[nId].m_vInters.emplace_back() ; m_mTree[nId].m_vInters.back().nIn = 4 ; } + else + return false ; } } else if ( nEdge == 6) { @@ -2388,11 +2345,13 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool m_mTree[nId].m_vInters.emplace_back() ; m_mTree[nId].m_vInters.back().nIn = 4 ; } - else { + else if (! vNeigh1.empty()) { nId = vNeigh1[0] ; m_mTree[nId].m_vInters.emplace_back() ; m_mTree[nId].m_vInters.back().nIn = 5 ; } + else + return false ; } } else if ( nEdge == 7) { @@ -2437,11 +2396,13 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool m_mTree[nId].m_vInters.emplace_back() ; m_mTree[nId].m_vInters.back().nIn = 5 ; } - else { + else if (! vNeigh1.empty()) { nId = vNeigh1.back() ; m_mTree[nId].m_vInters.emplace_back() ; m_mTree[nId].m_vInters.back().nIn = 6 ; } + else + return false ; } } // aggiungo l'intersezione al vettore delle intersezioni della prossima cella @@ -3427,14 +3388,6 @@ Tree::OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const Point3d ptTl ( ptBL.x, ptTR.y) ; Point3d ptBr ( ptTR.x, ptBL.y) ; - if ( ptToAssign.x > ptBL.x && ptToAssign.x < ptTR.x && abs( ptToAssign.y - ptTR.y) < EPS_SMALL) - nEdge = 0 ; - else if ( ptToAssign.y > ptBL.y && ptToAssign.y < ptTR.y && abs( ptToAssign.x - ptBL.x) < EPS_SMALL) - nEdge = 1 ; - else if ( ptToAssign.x > ptBL.x && ptToAssign.x < ptTR.x && abs( ptToAssign.y - ptBL.y) < EPS_SMALL) - nEdge = 2 ; - else if ( ptToAssign.y > ptBL.y && ptToAssign.y < ptTR.y && abs( ptToAssign.x - ptTR.x) < EPS_SMALL) - nEdge = 3 ; if ( AreSamePointApprox( ptToAssign, ptTR)) nEdge = 7 ; else if ( AreSamePointApprox( ptToAssign, ptTl)) @@ -3443,6 +3396,14 @@ Tree::OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const nEdge = 5 ; else if ( AreSamePointApprox( ptToAssign, ptBr)) nEdge = 6 ; + else if ( ptToAssign.x > ptBL.x && ptToAssign.x < ptTR.x && abs( ptToAssign.y - ptTR.y) < EPS_SMALL) + nEdge = 0 ; + else if ( ptToAssign.y > ptBL.y && ptToAssign.y < ptTR.y && abs( ptToAssign.x - ptBL.x) < EPS_SMALL) + nEdge = 1 ; + else if ( ptToAssign.x > ptBL.x && ptToAssign.x < ptTR.x && abs( ptToAssign.y - ptBL.y) < EPS_SMALL) + nEdge = 2 ; + else if ( ptToAssign.y > ptBL.y && ptToAssign.y < ptTR.y && abs( ptToAssign.x - ptTR.x) < EPS_SMALL) + nEdge = 3 ; else return false ; return true ; diff --git a/Tree.h b/Tree.h index 83f279e..d9ff804 100644 --- a/Tree.h +++ b/Tree.h @@ -174,6 +174,7 @@ class Tree bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero // ad ogni poligono sono stati aggiunti tutti i vertici dei vicini posizionati sui suoi lati bool GetLeaves ( std::vector& vLeaves) const ; + void SetTestMode( void) { m_bTestMode = true ;} ; private : bool Split( int nId, double dSplitValue) ; // funzione di split di una cella al parametro indicato nella direzione data da bVert @@ -227,4 +228,5 @@ class Tree 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 INTVECTOR m_vnLeaves ; // vettore delle foglie INTVECTOR m_vnParents ; // vettore delle celle ottenute dalla divisione preliminare in singole patch + bool m_bTestMode ; // bool che indica se la test mode è attiva } ; \ No newline at end of file