diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index 13b53ad..ce7eb9f 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -473,6 +473,7 @@ File di origine\Base + File di origine\GeoInters @@ -1112,6 +1113,8 @@ File di intestazione + File di intestazione + File di intestazione diff --git a/SurfBezier.cpp b/SurfBezier.cpp index c1c5b3d..b0fb6c6 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -149,10 +149,12 @@ SurfBezier::SetTrimRegion( const ISurfFlatRegion& sfrTrimReg) } //---------------------------------------------------------------------------- -bool -SurfBezier::GetTrimRegion( ISurfFlatRegion& sfrTrimReg) +SurfFlatRegion* +SurfBezier::GetTrimRegion( void) const { - return true ; + if ( ! m_bTrimmed || m_pTrimReg == nullptr ) + return nullptr ; + return m_pTrimReg ; } //---------------------------------------------------------------------------- @@ -1228,39 +1230,62 @@ SurfBezier::GetCurveOnV( double dU) const CurveComposite* SurfBezier::GetLoop( int nLoop) const { - // Se superficie completa, basta concatenare le 4 isoparametriche di bordo - if ( ! m_bTrimmed) { - // Esiste solo il loop esterno - if ( nLoop != 0) + // Il primo loop sono le 4 isoparametriche di bordo concatenate + if ( ! m_bTrimmed ) { + if ( nLoop != 0 ) return nullptr ; - // Loop + // Loop PtrOwner pLoop( CreateBasicCurveComposite()) ; - // prima curva isoparametrica in U con V=0 + // prima curva isoparametrica in U con V=0 PtrOwner pCrvCoU0( GetCurveOnU( 0)) ; if ( ! IsNull( pCrvCoU0) && ! pCrvCoU0->IsAPoint()) pLoop->AddCurve( Release( pCrvCoU0)) ; - // seconda curva isoparametrica in V con U=m_nSpanU + // seconda curva isoparametrica in V con U=m_nSpanU PtrOwner pCrvCoV1( GetCurveOnV( m_nSpanU)) ; if ( ! IsNull( pCrvCoV1) && ! pCrvCoV1->IsAPoint()) pLoop->AddCurve( Release( pCrvCoV1)) ; - // terza curva isoparametrica in U con V=m_nSpanV invertita + // terza curva isoparametrica in U con V=m_nSpanV invertita PtrOwner pCrvCoU1( GetCurveOnU( m_nSpanV)) ; if ( ! IsNull( pCrvCoU1) && ! pCrvCoU1->IsAPoint()) { pCrvCoU1->Invert() ; pLoop->AddCurve( Release( pCrvCoU1)) ; } - // quarta curva isoparametrica in V con U=0 invertita + // quarta curva isoparametrica in V con U=0 invertita PtrOwner pCrvCoV0( GetCurveOnV( 0)) ; if ( ! IsNull( pCrvCoV0) && ! pCrvCoV0->IsAPoint()) { pCrvCoV0->Invert() ; pLoop->AddCurve( Release( pCrvCoV0)) ; } - // se loop chiuso lo restituisco, altrimenti errore + // se loop chiuso lo restituisco, altrimenti errore return ( pLoop->IsClosed() ? Release( pLoop) : nullptr) ; } - // altrimenti trimmata, per ora non gestita - else - return nullptr ; + // la superficie è trimmata, quindi devo cercare nei vari chunck il loop corrispondente + else { + if ( nLoop > m_pTrimReg->GetChunkCount()) + return nullptr ; + else { + int nLoopCount = 0 ; + int nChunck = 0, nLoopLoc = 0; + INTVECTOR nLoopCountPerChunck ; + for ( int i = 0 ; i < m_pTrimReg->GetChunkCount() && nLoopCount != nLoop ; ++ i) { + int nLoopCountLoc = 0 ; + for ( int j = 0 ; j < m_pTrimReg->GetLoopCount( i) ; ++ j) { + ++ nLoopCountLoc ; + ++ nLoopCount ; + if ( nLoopCount != nLoop ) { + nChunck = i ; + nLoopLoc = j ; + break ; + } + } + nLoopCountPerChunck.push_back( nLoopCountLoc) ; + } + if ( nLoopCount < nLoop ) + return nullptr ; + PtrOwner pLoop( GetBasicCurveComposite( m_pTrimReg->GetLoop( nChunck, nLoopLoc))) ; + return Release( pLoop) ; + } + } } //---------------------------------------------------------------------------- @@ -1473,21 +1498,22 @@ SurfBezier::GetAuxSurf( void) const return m_pSTM ; // costruttore della superficie + Tree Tree( this, true) ; Tree.BuildTree() ; - POLYLINEVECTOR vPL ; - Tree.GetPolygons( vPL) ; + vector vvPL ; + Tree.GetPolygons( vvPL) ; PtrOwner pSrfTm( CreateBasicSurfTriMesh()) ; StmFromTriangleSoup stmSoup ; if ( ! stmSoup.Start()) return nullptr ; // prendo i punti di ogni polyline dell'albero, li triangolo e li porto in 3d - for ( PolyLine i : vPL) { + for ( POLYLINEVECTOR vPL : vvPL) { PNTVECTOR vPnt ; INTVECTOR vTria ; Triangulate Tri ; - if ( ! Tri.Make( i, vPnt, vTria)) + if ( ! Tri.Make( vPL, vPnt, vTria)) return nullptr ; // porto i punti in 3d diff --git a/SurfBezier.h b/SurfBezier.h index 12149f8..6cfc9e2 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -83,7 +83,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW { return SetControlPoint( GetInd( nIndU, nIndV), ptCtrl, dW) ; } bool SetControlPoint( int nInd, const Point3d& ptCtrl, double dW) override ; bool SetTrimRegion( const ISurfFlatRegion& sfrTrimReg) override ; - bool GetTrimRegion( ISurfFlatRegion& sfrTrimReg) override ; + SurfFlatRegion* GetTrimRegion( void) const override ; bool GetInfo( int& nDegU, int& nDegV, int& nSpanU, int& nSpanV, bool& bIsRat, bool& bTrimmed) const override ; const Point3d& GetControlPoint( int nIndU, int nIndV, bool* pbOk) const override { return GetControlPoint( GetInd( nIndU, nIndV), pbOk) ; } diff --git a/Tree.cpp b/Tree.cpp index 3ef45ea..21a8aa1 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -18,15 +18,19 @@ #include "SurfBezier.h" #include "GeoConst.h" #include "CurveLine.h" +#include "CurveComposite.h" +#include "SurfFlatRegion.h" +#include "IntersLineLine.h" #include "/EgtDev/Include/EGkPolyLine.h" #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_ptPbl( ORIG), m_ptPtr(), m_bProcessed ( false) , m_bSplitVert ( true) + m_nChild1( -2), m_nChild2( -2), m_nFlag( 0), m_nRightEdgeIn( 0), m_ptPbl(ORIG), m_ptPtr(), m_bProcessed(false), m_bSplitVert(true) { Point3d ptTr ( 1, 1) ; m_ptPtr = ptTr ; @@ -36,7 +40,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_ptPbl( ptBL), m_ptPtr( ptTR), m_bProcessed ( false) , m_bSplitVert ( true) + m_nChild1( -2), m_nChild2( -2), m_nFlag( 0), m_nRightEdgeIn( 0), m_ptPbl(ptBL), m_ptPtr(ptTR), m_bProcessed(false), m_bSplitVert(true) {} @@ -87,7 +91,8 @@ Tree::~Tree( void) } //---------------------------------------------------------------------------- -void Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches) +void +Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches) { m_pSrfBz = pSrfBz ; // le coordinate delle celle sono nello spazio parametrico @@ -101,7 +106,56 @@ void Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches) m_bBilinear = true ; if ( nSpanU * nSpanV != 1) m_bMulti = true ; - + // recupero i loop di trim e li divido per chunk + if ( m_bTrimmed) { + int nLoop = 0 ; + INTVECTOR vChunk ; + // dalla superficie recupero un vettore con i loop di trim + // + //PtrOwner pLoop( GetBasicCurveComposite( m_pSrfBz->GetLoop( nLoop))) ; + //while ( ! IsNull( pLoop) && pLoop->IsValid()) { + // if ( nLoop == 0) { + // m_vLoop.push_back( Release( pLoop)) ; + // vChunck.push_back( nLoop) ; + // ++ nLoop ; + // } + // else { + // // se il loop corrente è contenuto nel precedente e sono girati in verso opposto, allora lo aggiungo allo stesso chunk + // if ( ) { + + // } + // // salvo il precedente chunk e creo un nuovo chunk + // else { + // m_vChunk.push_back( vChunk) ; + // vChunk.clear() ; + // vChunk.push_back( nLoop) ; + // } + // ++ nLoop ; + // PtrOwner pLoop( GetBasicCurveComposite( m_pSrfBz->GetLoop( nLoop))) ; + // } + //} + + // recupero la superficie di trim per avere accesso diretto ai loop e mantenendo le informazioni sui chunk + + Frame3d frSurf ; + //const SurfFlatRegion* pTrimReg_( m_pSrfBz->GetTrimRegion()) ; + //PtrOwner pTrimReg( pTrimReg_->Clone()) ; + PtrOwner pTrimReg( m_pSrfBz->GetTrimRegion()->Clone()) ; + for ( int i = 0 ; i < pTrimReg->GetChunkCount() ; ++ i) { + PtrOwner pChunk( pTrimReg->CloneChunk( i)) ; + pChunk->Scale( frSurf, 1./ SBZ_TREG_COEFF, 1./ SBZ_TREG_COEFF, 1) ; + for ( int j = 0 ; j < pChunk->GetLoopCount( 0) ; ++ j) { + vChunk.push_back( nLoop) ; + // i chunk della superficie orignale non possono avere dei sub chunk + PtrOwner pLoop (pChunk->GetLoop(0, j)) ; + m_vLoop.emplace_back( Release( pLoop )) ; + m_mChunk[nLoop] = i ; + ++ nLoop ; + } + m_vChunk.push_back( vChunk) ; + vChunk.clear() ; + } + } // salvo i vertici 3d della cella root Point3d ptBottom ( 0, 0) ; Point3d ptTop( nSpanU, nSpanV) ; @@ -320,346 +374,390 @@ Tree::Split( int nId) } //---------------------------------------------------------------------------- -bool Tree::BuildTree( double dLinTol_, double dSideMin, double dSideMax) +bool +Tree::BuildTree( double dLinTol_, double dSideMin, double dSideMax) { - // suddivido lo spazio parametrico con divisioni a metà su uno dei due parametri - int nCToSplit = -1 ; - double dLinTol = 0.2 ; - //double dSideMin = 1 ; - if ( ! m_bTrimmed) { - if ( ! m_bBilinear) { - while ( nCToSplit != -2 && m_mTree[nCToSplit].IsProcessed() == false) { - // controllo che la cella non sia già stata preliminarmente splittata - if ( m_mTree[nCToSplit].IsLeaf()) { - // calcolo in quale direzione ho più curvatura - // ptP00P10 è un punto tra P00 e P10 - double dCurvU = 0, dCurvV = 0 ; - double dLenParU = m_mTree[nCToSplit].GetTopRight().x - m_mTree[nCToSplit].GetBottomLeft().x ; - double dLenParV = m_mTree[nCToSplit].GetTopRight().y - m_mTree[nCToSplit].GetBottomLeft().y ; - if ( dLenParU <= 1. / m_nDegV || dLenParV <= 1. / m_nDegU) { - double dU = ( m_mTree[nCToSplit].GetTopRight().x + m_mTree[nCToSplit].GetBottomLeft().x) / 2 ; - double dV = ( m_mTree[nCToSplit].GetTopRight().y + m_mTree[nCToSplit].GetBottomLeft().y) / 2 ; - double dULoc = 0.5, dVLoc = 0.5 ; - Point3d ptPSrf, ptP00P10, ptP10P11, ptP11P01, ptP01P00 ; - m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ; - m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00P10) ; - m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10P11) ; - m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11P01) ; - m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01P00) ; - Point3d ptV = ( 1 - dULoc) * ptP00P10 + dULoc * ptP11P01 ; - Point3d ptU = ( 1 - dVLoc) * ptP10P11 + dVLoc * ptP01P00 ; - dCurvV = Dist( ptV, ptPSrf) ; - dCurvU = Dist( ptU, ptPSrf) ; - } - // faccio un'analisi più fine della curvatura se almeno il grado di una curva di uno dei due parametri è alto e - // se sto ancora guardando una cella abbastanza grande - else{ - Point3d ptPSrf, ptP00P10, ptP10P11, ptP11P01, ptP01P00, ptPSrfMid; - double dStep = 1. / m_nDegU ; - for ( double k = dStep ; k < 1 ; k = k + dStep) { - double dU = k * m_mTree[nCToSplit].GetTopRight().x + ( 1 - k) * m_mTree[nCToSplit].GetBottomLeft().x ; - double dV = ( m_mTree[nCToSplit].GetTopRight().y + m_mTree[nCToSplit].GetBottomLeft().y) / 2 ; - m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ; - if ( k == 0.5) - ptPSrfMid = ptPSrf ; - m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00P10) ; - m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11P01) ; - CurveLine clV ; - clV.Set( ptP00P10, ptP11P01) ; - DistPointCurve dpc( ptPSrf, clV) ; - double dDist ; - dpc.GetDist( dDist) ; - dCurvV = max( dCurvV, dDist) ; - } - dStep = 1. / m_nDegV ; - for ( double k = dStep ; k < 1 ; k = k + dStep) { - double dU = ( m_mTree[nCToSplit].GetTopRight().x + m_mTree[nCToSplit].GetBottomLeft().x) / 2 ; - double dV = k * m_mTree[nCToSplit].GetTopRight().y + ( 1 - k) * m_mTree[nCToSplit].GetBottomLeft().y ; - if ( k == 0.5) - ptPSrf = ptPSrfMid ; - else - m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ; - m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10P11) ; - m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01P00) ; - CurveLine clU ; - clU.Set( ptP01P00, ptP10P11) ; - DistPointCurve dpc( ptPSrf, clU) ; - double dDist ; - dpc.GetDist( dDist) ; - dCurvU = max( dCurvU, dDist) ; - } - } + //int nCToSplit = -1 ; + //celle 0,1 + m_mTree[-1].SetSplitDirVert( true) ; + Split( -1) ; + //celle 2,3 + m_mTree[0].SetSplitDirVert( false) ; + Split( 0) ; + //celle 4,5 + m_mTree[2].SetSplitDirVert( false) ; + Split( 2) ; + //celle 6,7 + m_mTree[3].SetSplitDirVert( true) ; + Split( 3) ; + //celle 8,9 + m_mTree[1].SetSplitDirVert( false) ; + Split( 1) ; + //celle 10,11 + m_mTree[8].SetSplitDirVert( true) ; + Split( 8) ; + //celle 12,13 + m_mTree[9].SetSplitDirVert( false) ; + Split( 9) ; + m_vnLeaves.push_back( 4) ; + m_vnLeaves.push_back( 5) ; + m_vnLeaves.push_back( 6) ; + m_vnLeaves.push_back( 7) ; + m_vnLeaves.push_back( 10) ; + m_vnLeaves.push_back( 11) ; + m_vnLeaves.push_back( 12) ; + m_vnLeaves.push_back( 13) ; - // per lo split scelgo la direzione che è più vicina alla superficie originale nel punto di maggior distanza - // misura approssimativa della curvatura in una direzione - bool bVert ; - if ( dCurvV > dCurvU) { - // lungo la direzione V ho una curvatura maggiore - bVert = false ; - } - else { - // lungo la direzione U ho una curvatura maggiore - bVert = true ; - } - m_mTree[nCToSplit].SetSplitDirVert( bVert) ; - Point3d ptP00, ptP10, ptP11, ptP01 ; - // distanza reale tra i vertici della cella - ptP00 = m_mVert[nCToSplit][0] ; - ptP10 = m_mVert[nCToSplit][1] ; - ptP11 = m_mVert[nCToSplit][2] ; - ptP01 = m_mVert[nCToSplit][3] ; - double dLen0 = Dist( ptP00, ptP10) ; - double dLen1 = Dist( ptP10, ptP11) ; - double dLen2 = Dist( ptP01, ptP11) ; - double dLen3 = Dist( ptP00, ptP01) ; - // verifico che la cella sia da splittare e che eventualmente sia abbastanza grande da poterlo fare - double dSideMinVal = 0, dSideMaxVal = 0 ; - if ( bVert) { - if ( dLen0 != 0 && dLen2 != 0) - dSideMinVal = min( dLen0, dLen2) ; - else - dSideMinVal = max( dLen0, dLen2) ; - } - else { - if ( dLen1 != 0 && dLen3 != 0) - dSideMinVal = min( dLen1, dLen3) ; - else - dSideMinVal = max( dLen1, dLen3) ; - } - // calcolo le diagonali per controllare la dimensione massima dei triangoli in cui dividerei la cella - dSideMaxVal = max( Dist( ptP00, ptP11), Dist( ptP10, ptP01)) ; - - // se la cella è abbastanza grande da poter essere divisa ancora, calcolo l'errore di approssimazione - bool bSplit = false ; - if ( dSideMinVal / 2 >= dSideMin && dSideMaxVal < dSideMax && ( dCurvV > dLinTol || dCurvU > dLinTol)) { - CurveLine cl0010, cl0001, cl1011, cl0111 ; - // U=0 - cl0010.Set( ptP00, ptP10) ; - // U=1 - cl0111.Set( ptP01, ptP11) ; - Point3d pt0010, pt0111, ptBz0, ptBz1, ptBzV ; - int nFlag ; - CurveLine clV ; - // determino quanti Step fare per ogni direzione parametrica - double dDimU = ( dLen0 >= dLen2 ? dLen0 / m_vDim[0] : dLen2 / m_vDim[2]) ; - dDimU = ( dDimU > 1 ? 1 : dDimU) ; - double dDimV = ( dLen1 >= dLen3 ? dLen1 / m_vDim[1] : dLen3 / m_vDim[3]) ; - dDimV = ( dDimV > 1 ? 1 : dDimV) ; - // numero di Step per campionare la superficie nelle due direzioni parametriche - int nStepsU = int( 51 * dDimU + 5 * ( 1 - dDimU)) ; - int nStepsV = int( 51 * dDimV + 5 * ( 1 - dDimV)) ; - for ( int u = 0 ; u < nStepsU && ! bSplit ; ++ u) { - double dU = double ( u) / double ( nStepsU - 1) ; - double dULoc = ( 1 - dU) * m_mTree[nCToSplit].GetBottomLeft().x + dU * m_mTree[nCToSplit].GetTopRight().x ; - if ( ! m_pSrfBz->GetPointD1D2( dULoc, m_mTree[nCToSplit].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz0) || - ! m_pSrfBz->GetPointD1D2( dULoc, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz1)) - return false ; - DistPointCurve dpc0010( ptBz0, cl0010) ; - DistPointCurve dpc0111( ptBz1, cl0111) ; - dpc0010.GetMinDistPoint( 0, pt0010, nFlag) ; - dpc0111.GetMinDistPoint( 0, pt0111, nFlag) ; - clV.Set( pt0010, pt0111) ; - for ( int v = 0 ; v < nStepsV ; ++ v) { - double dV = double ( v) / double ( nStepsV - 1) ; - double dVLoc = ( 1 - dV) * m_mTree[nCToSplit].GetBottomLeft().y + dV * m_mTree[nCToSplit].GetTopRight().y ; - if ( ! m_pSrfBz->GetPointD1D2( dULoc, dVLoc, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBzV)) - return false ; - DistPointCurve dpc( ptBzV, clV) ; - // distanza di approssimazione locale - double dDist ; - dpc.GetDist( dDist) ; - if ( dDist > dLinTol) { - bSplit = true ; - break ; - } - } - } - } - - if ( bSplit || dSideMaxVal > dSideMax) { - m_mTree[nCToSplit].SetSplitDirVert( bVert) ; - // effettuo lo split - Split( nCToSplit) ; - - // procedo con lo split del Child1 - nCToSplit = m_mTree[nCToSplit].m_nChild1 ; - } - else { - // sono arrivato ad una cella Leaf, quindi salvo la cella - m_vnLeaves.push_back( nCToSplit) ; - m_mTree[nCToSplit].Processed() ; - // risalgo i parent finché non trovo il primo Child2 da processare - nCToSplit = m_mTree[nCToSplit].m_nParent ; - if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) - m_mTree[nCToSplit].Processed() ; - while ( m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) { - if ( m_mTree[nCToSplit].m_nParent != -2) - nCToSplit = m_mTree[nCToSplit].m_nParent ; - if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) - m_mTree[nCToSplit].Processed() ; - if ( nCToSplit == -1 && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) - break ; - } - nCToSplit = m_mTree[nCToSplit].m_nChild2 ; - } - } - else { - nCToSplit = m_mTree[nCToSplit].m_nChild1 ; - } - } - Balance() ; // da implementare quando dividerò ad un parametro a scelta e non a metà - } - // bilineare - else { - while ( nCToSplit != -2 && m_mTree[nCToSplit].IsProcessed() == false) { - if ( m_mTree[nCToSplit].IsLeaf()) { - // vertici della cella - Point3d ptP00, ptP10, ptP11, ptP01 ; - ptP00 = m_mVert[nCToSplit][0] ; - ptP10 = m_mVert[nCToSplit][1] ; - ptP11 = m_mVert[nCToSplit][2] ; - ptP01 = m_mVert[nCToSplit][3] ; - // distanza reale tra i vertici della cella - double dLen0 = Dist( ptP00, ptP10) ; - double dLen1 = Dist( ptP10, ptP11) ; - double dLen2 = Dist( ptP01, ptP11) ; - double dLen3 = Dist( ptP00, ptP01) ; - - bool bVert = false ; - // calcolo in quale direzione è meglio dividere in base allo stretch - Point3d ptPSrfU, ptPSrfV ; - double dU = 0, dV = 0 ; - double dDistU = 0, dDistV = 0 ; - PNTVECTOR vPtU, vPtV ; - if ( ! m_bMulti) { - if ( max(dLen0, dLen2) > max(dLen1, dLen3)) { - bVert = true ; - } - else { - bVert = false ; - } - } - else { - for ( double i = 0.25 ; i < 1 ; i = i + 0.25 ) { - dU = ( 1 - i) * m_mTree[nCToSplit].GetBottomLeft().x + i * m_mTree[nCToSplit].GetTopRight().x ; - dV = ( 1 - i) * m_mTree[nCToSplit].GetBottomLeft().y + i * m_mTree[nCToSplit].GetTopRight().y ; - double dVLoc = ( m_mTree[nCToSplit].GetBottomLeft().y + m_mTree[nCToSplit].GetTopRight().y) / 2 ; - double dULoc = ( m_mTree[nCToSplit].GetBottomLeft().x + m_mTree[nCToSplit].GetTopRight().x) / 2 ; - m_pSrfBz->GetPointD1D2( dU, dVLoc, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrfU) ; - m_pSrfBz->GetPointD1D2( dULoc, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrfV) ; - vPtU.push_back( ptPSrfU) ; - vPtV.push_back( ptPSrfV) ; - } - // devo guardare se i tre punti in vPtU e vPtV sono allineati - CurveLine clU, clV; - clU.Set(vPtU[0], vPtU[1]) ; - clV.Set(vPtV[0], vPtV[1]) ; - DistPointCurve dpcU( vPtU[2], clU, false) ; - DistPointCurve dpcV( vPtV[2], clV, false) ; - dpcU.GetDist( dDistU) ; - dpcV.GetDist( dDistV) ; - if ( dDistU > dDistV) { - bVert = true ; - } - else { - bVert = false ; - } - } - - // verifico che la cella sia abbastanza grande da poter essere splittata - double dSideMinVal = 0, dSideMaxVal = 0 ; - if ( bVert) { - if ( dLen0 != 0 && dLen2 != 0) - dSideMinVal = min( dLen0, dLen2) ; - else - dSideMinVal = max( dLen0, dLen2) ; - } - else { - if ( dLen1 != 0 && dLen3 != 0) - dSideMinVal = min( dLen1, dLen3) ; - else - dSideMinVal = max( dLen1, dLen3) ; - } - // calcolo le diagonali per controllare la dimensione massima dei triangoli in cui dividerei la cella - dSideMaxVal = max( Dist( ptP00, ptP11), Dist( ptP10, ptP01)) ; - - - double dErr = 0 ; - if ( m_bMulti) { - Point3d ptPSrf ; - Plane3d plAppr ; - if ( ! AreSamePointApprox( ptP00, ptP10) && ! AreSamePointApprox( ptP00, ptP01)) - plAppr.Set( ptP00, ( ptP00 - ptP01) ^ ( ptP00 - ptP10)) ; - else if ( AreSamePointApprox( ptP00, ptP10)) { - plAppr.Set( ptP01, ( ptP00 - ptP01) ^ ( ptP01 - ptP11)) ; - } - else if ( AreSamePointApprox( ptP00, ptP01)) { - plAppr.Set( ptP10, ( ptP10 - ptP11) ^ ( ptP00 - ptP10)) ; - } - for ( double i = 0.25 ; i < 1 ; i = i + 0.25) { - for ( double j = 0.25 ; j < 1 ; j = j + 0.25) { - double dU = ( 1 - i) * m_mTree[nCToSplit].GetTopRight().x + i * m_mTree[nCToSplit].GetBottomLeft().x ; - double dV = ( 1 - j) * m_mTree[nCToSplit].GetTopRight().y + j * m_mTree[nCToSplit].GetBottomLeft().y ; - m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ; - dErr = max( abs( DistPointPlane( ptPSrf, plAppr)), dErr) ; - } - } - } - else { - dErr = 1. / 4. * ( (ptP00 - ptP01) + (ptP11 - ptP10)).Len() ; - } - // se la cella è abbastanza grande da poter essere divisa ancora e devo approssimare meglio, la divido - if ( dSideMinVal / 2 >= dSideMin && dSideMaxVal < dSideMax && dErr > dLinTol) { - m_mTree[nCToSplit].SetSplitDirVert( bVert) ; - // effettuo lo split - Split( nCToSplit) ; - - // procedo con lo split del Child1 - nCToSplit = m_mTree[nCToSplit].m_nChild1 ; - } - else { - // sono arrivato ad una cella Leaf, quindi salvo la cella - m_vnLeaves.push_back( nCToSplit) ; - m_mTree[nCToSplit].Processed() ; - // risalgo i parent finché non trovo il primo Child2 da processare - nCToSplit = m_mTree[nCToSplit].m_nParent ; - if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) - m_mTree[nCToSplit].Processed() ; - while ( m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) { - if ( m_mTree[nCToSplit].m_nParent != -2) - nCToSplit = m_mTree[nCToSplit].m_nParent ; - if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) - m_mTree[nCToSplit].Processed() ; - if ( nCToSplit == -1 && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) - break ; - } - nCToSplit = m_mTree[nCToSplit].m_nChild2 ; - } - } - else { - nCToSplit = m_mTree[nCToSplit].m_nChild1 ; - } - } - } - } - // se la superficie è trimmata - else { - SurfFlatRegion sfrTrimReg ; - } return true ; } +////---------------------------------------------------------------------------- +//bool +//Tree::BuildTree( double dLinTol_, double dSideMin, double dSideMax) +//{ +// // suddivido lo spazio parametrico con divisioni a metà su uno dei due parametri +// int nCToSplit = -1 ; +// double dLinTol = 0.2 ; +// //double dSideMin = 1 ; +// if ( ! m_bTrimmed) { +// if ( ! m_bBilinear) { +// while ( nCToSplit != -2 && m_mTree[nCToSplit].IsProcessed() == false) { +// // controllo che la cella non sia già stata preliminarmente splittata +// if ( m_mTree[nCToSplit].IsLeaf()) { +// // calcolo in quale direzione ho più curvatura +// // ptP00P10 è un punto tra P00 e P10 +// double dCurvU = 0, dCurvV = 0 ; +// double dLenParU = m_mTree[nCToSplit].GetTopRight().x - m_mTree[nCToSplit].GetBottomLeft().x ; +// double dLenParV = m_mTree[nCToSplit].GetTopRight().y - m_mTree[nCToSplit].GetBottomLeft().y ; +// if ( dLenParU <= 1. / m_nDegV || dLenParV <= 1. / m_nDegU) { +// double dU = ( m_mTree[nCToSplit].GetTopRight().x + m_mTree[nCToSplit].GetBottomLeft().x) / 2 ; +// double dV = ( m_mTree[nCToSplit].GetTopRight().y + m_mTree[nCToSplit].GetBottomLeft().y) / 2 ; +// double dULoc = 0.5, dVLoc = 0.5 ; +// Point3d ptPSrf, ptP00P10, ptP10P11, ptP11P01, ptP01P00 ; +// m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ; +// m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00P10) ; +// m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10P11) ; +// m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11P01) ; +// m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01P00) ; +// Point3d ptV = ( 1 - dULoc) * ptP00P10 + dULoc * ptP11P01 ; +// Point3d ptU = ( 1 - dVLoc) * ptP10P11 + dVLoc * ptP01P00 ; +// dCurvV = Dist( ptV, ptPSrf) ; +// dCurvU = Dist( ptU, ptPSrf) ; +// } +// // faccio un'analisi più fine della curvatura se almeno il grado di una curva di uno dei due parametri è alto e +// // se sto ancora guardando una cella abbastanza grande +// else{ +// Point3d ptPSrf, ptP00P10, ptP10P11, ptP11P01, ptP01P00, ptPSrfMid; +// double dStep = 1. / m_nDegU ; +// for ( double k = dStep ; k < 1 ; k = k + dStep) { +// double dU = k * m_mTree[nCToSplit].GetTopRight().x + ( 1 - k) * m_mTree[nCToSplit].GetBottomLeft().x ; +// double dV = ( m_mTree[nCToSplit].GetTopRight().y + m_mTree[nCToSplit].GetBottomLeft().y) / 2 ; +// m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ; +// if ( k == 0.5) +// ptPSrfMid = ptPSrf ; +// m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00P10) ; +// m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11P01) ; +// CurveLine clV ; +// clV.Set( ptP00P10, ptP11P01) ; +// DistPointCurve dpc( ptPSrf, clV) ; +// double dDist ; +// dpc.GetDist( dDist) ; +// dCurvV = max( dCurvV, dDist) ; +// } +// dStep = 1. / m_nDegV ; +// for ( double k = dStep ; k < 1 ; k = k + dStep) { +// double dU = ( m_mTree[nCToSplit].GetTopRight().x + m_mTree[nCToSplit].GetBottomLeft().x) / 2 ; +// double dV = k * m_mTree[nCToSplit].GetTopRight().y + ( 1 - k) * m_mTree[nCToSplit].GetBottomLeft().y ; +// if ( k == 0.5) +// ptPSrf = ptPSrfMid ; +// else +// m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ; +// m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10P11) ; +// m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01P00) ; +// CurveLine clU ; +// clU.Set( ptP01P00, ptP10P11) ; +// DistPointCurve dpc( ptPSrf, clU) ; +// double dDist ; +// dpc.GetDist( dDist) ; +// dCurvU = max( dCurvU, dDist) ; +// } +// } +// +// // per lo split scelgo la direzione che è più vicina alla superficie originale nel punto di maggior distanza +// // misura approssimativa della curvatura in una direzione +// bool bVert ; +// if ( dCurvV > dCurvU) { +// // lungo la direzione V ho una curvatura maggiore +// bVert = false ; +// } +// else { +// // lungo la direzione U ho una curvatura maggiore +// bVert = true ; +// } +// m_mTree[nCToSplit].SetSplitDirVert( bVert) ; +// Point3d ptP00, ptP10, ptP11, ptP01 ; +// // distanza reale tra i vertici della cella +// ptP00 = m_mVert[nCToSplit][0] ; +// ptP10 = m_mVert[nCToSplit][1] ; +// ptP11 = m_mVert[nCToSplit][2] ; +// ptP01 = m_mVert[nCToSplit][3] ; +// double dLen0 = Dist( ptP00, ptP10) ; +// double dLen1 = Dist( ptP10, ptP11) ; +// double dLen2 = Dist( ptP01, ptP11) ; +// double dLen3 = Dist( ptP00, ptP01) ; +// // verifico che la cella sia da splittare e che eventualmente sia abbastanza grande da poterlo fare +// double dSideMinVal = 0, dSideMaxVal = 0 ; +// if ( bVert) { +// if ( dLen0 != 0 && dLen2 != 0) +// dSideMinVal = min( dLen0, dLen2) ; +// else +// dSideMinVal = max( dLen0, dLen2) ; +// } +// else { +// if ( dLen1 != 0 && dLen3 != 0) +// dSideMinVal = min( dLen1, dLen3) ; +// else +// dSideMinVal = max( dLen1, dLen3) ; +// } +// // calcolo le diagonali per controllare la dimensione massima dei triangoli in cui dividerei la cella +// dSideMaxVal = max( Dist( ptP00, ptP11), Dist( ptP10, ptP01)) ; +// +// // se la cella è abbastanza grande da poter essere divisa ancora, calcolo l'errore di approssimazione +// bool bSplit = false ; +// if ( dSideMinVal / 2 >= dSideMin && dSideMaxVal < dSideMax && ( dCurvV > dLinTol || dCurvU > dLinTol)) { +// CurveLine cl0010, cl0001, cl1011, cl0111 ; +// // U=0 +// cl0010.Set( ptP00, ptP10) ; +// // U=1 +// cl0111.Set( ptP01, ptP11) ; +// Point3d pt0010, pt0111, ptBz0, ptBz1, ptBzV ; +// int nFlag ; +// CurveLine clV ; +// // determino quanti Step fare per ogni direzione parametrica +// double dDimU = ( dLen0 >= dLen2 ? dLen0 / m_vDim[0] : dLen2 / m_vDim[2]) ; +// dDimU = ( dDimU > 1 ? 1 : dDimU) ; +// double dDimV = ( dLen1 >= dLen3 ? dLen1 / m_vDim[1] : dLen3 / m_vDim[3]) ; +// dDimV = ( dDimV > 1 ? 1 : dDimV) ; +// // numero di Step per campionare la superficie nelle due direzioni parametriche +// int nStepsU = int( 51 * dDimU + 5 * ( 1 - dDimU)) ; +// int nStepsV = int( 51 * dDimV + 5 * ( 1 - dDimV)) ; +// for ( int u = 0 ; u < nStepsU && ! bSplit ; ++ u) { +// double dU = double ( u) / double ( nStepsU - 1) ; +// double dULoc = ( 1 - dU) * m_mTree[nCToSplit].GetBottomLeft().x + dU * m_mTree[nCToSplit].GetTopRight().x ; +// if ( ! m_pSrfBz->GetPointD1D2( dULoc, m_mTree[nCToSplit].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz0) || +// ! m_pSrfBz->GetPointD1D2( dULoc, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz1)) +// return false ; +// DistPointCurve dpc0010( ptBz0, cl0010) ; +// DistPointCurve dpc0111( ptBz1, cl0111) ; +// dpc0010.GetMinDistPoint( 0, pt0010, nFlag) ; +// dpc0111.GetMinDistPoint( 0, pt0111, nFlag) ; +// clV.Set( pt0010, pt0111) ; +// for ( int v = 0 ; v < nStepsV ; ++ v) { +// double dV = double ( v) / double ( nStepsV - 1) ; +// double dVLoc = ( 1 - dV) * m_mTree[nCToSplit].GetBottomLeft().y + dV * m_mTree[nCToSplit].GetTopRight().y ; +// if ( ! m_pSrfBz->GetPointD1D2( dULoc, dVLoc, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBzV)) +// return false ; +// DistPointCurve dpc( ptBzV, clV) ; +// // distanza di approssimazione locale +// double dDist ; +// dpc.GetDist( dDist) ; +// if ( dDist > dLinTol) { +// bSplit = true ; +// break ; +// } +// } +// } +// } +// +// if ( bSplit || dSideMaxVal > dSideMax) { +// m_mTree[nCToSplit].SetSplitDirVert( bVert) ; +// // effettuo lo split +// Split( nCToSplit) ; +// +// // procedo con lo split del Child1 +// nCToSplit = m_mTree[nCToSplit].m_nChild1 ; +// } +// else { +// // sono arrivato ad una cella Leaf, quindi salvo la cella +// m_vnLeaves.push_back( nCToSplit) ; +// m_mTree[nCToSplit].SetProcessed() ; +// // risalgo i parent finché non trovo il primo Child2 da processare +// nCToSplit = m_mTree[nCToSplit].m_nParent ; +// if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) +// m_mTree[nCToSplit].SetProcessed() ; +// while ( m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) { +// if ( m_mTree[nCToSplit].m_nParent != -2) +// nCToSplit = m_mTree[nCToSplit].m_nParent ; +// if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) +// m_mTree[nCToSplit].SetProcessed() ; +// if ( nCToSplit == -1 && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) +// break ; +// } +// nCToSplit = m_mTree[nCToSplit].m_nChild2 ; +// } +// } +// else { +// nCToSplit = m_mTree[nCToSplit].m_nChild1 ; +// } +// } +// Balance() ; // da implementare quando dividerò ad un parametro a scelta e non a metà +// } +// // bilineare +// else { +// while ( nCToSplit != -2 && m_mTree[nCToSplit].IsProcessed() == false) { +// if ( m_mTree[nCToSplit].IsLeaf()) { +// // vertici della cella +// Point3d ptP00, ptP10, ptP11, ptP01 ; +// ptP00 = m_mVert[nCToSplit][0] ; +// ptP10 = m_mVert[nCToSplit][1] ; +// ptP11 = m_mVert[nCToSplit][2] ; +// ptP01 = m_mVert[nCToSplit][3] ; +// // distanza reale tra i vertici della cella +// double dLen0 = Dist( ptP00, ptP10) ; +// double dLen1 = Dist( ptP10, ptP11) ; +// double dLen2 = Dist( ptP01, ptP11) ; +// double dLen3 = Dist( ptP00, ptP01) ; +// +// bool bVert = false ; +// // calcolo in quale direzione è meglio dividere in base allo stretch +// Point3d ptPSrfU, ptPSrfV ; +// double dU = 0, dV = 0 ; +// double dDistU = 0, dDistV = 0 ; +// PNTVECTOR vPtU, vPtV ; +// if ( ! m_bMulti) { +// if ( max(dLen0, dLen2) > max(dLen1, dLen3)) { +// bVert = true ; +// } +// else { +// bVert = false ; +// } +// } +// else { +// for ( double i = 0.25 ; i < 1 ; i = i + 0.25 ) { +// dU = ( 1 - i) * m_mTree[nCToSplit].GetBottomLeft().x + i * m_mTree[nCToSplit].GetTopRight().x ; +// dV = ( 1 - i) * m_mTree[nCToSplit].GetBottomLeft().y + i * m_mTree[nCToSplit].GetTopRight().y ; +// double dVLoc = ( m_mTree[nCToSplit].GetBottomLeft().y + m_mTree[nCToSplit].GetTopRight().y) / 2 ; +// double dULoc = ( m_mTree[nCToSplit].GetBottomLeft().x + m_mTree[nCToSplit].GetTopRight().x) / 2 ; +// m_pSrfBz->GetPointD1D2( dU, dVLoc, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrfU) ; +// m_pSrfBz->GetPointD1D2( dULoc, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrfV) ; +// vPtU.push_back( ptPSrfU) ; +// vPtV.push_back( ptPSrfV) ; +// } +// // devo guardare se i tre punti in vPtU e vPtV sono allineati +// CurveLine clU, clV; +// clU.Set(vPtU[0], vPtU[1]) ; +// clV.Set(vPtV[0], vPtV[1]) ; +// DistPointCurve dpcU( vPtU[2], clU, false) ; +// DistPointCurve dpcV( vPtV[2], clV, false) ; +// dpcU.GetDist( dDistU) ; +// dpcV.GetDist( dDistV) ; +// if ( dDistU > dDistV) { +// bVert = true ; +// } +// else { +// bVert = false ; +// } +// } +// +// // verifico che la cella sia abbastanza grande da poter essere splittata +// double dSideMinVal = 0, dSideMaxVal = 0 ; +// if ( bVert) { +// if ( dLen0 != 0 && dLen2 != 0) +// dSideMinVal = min( dLen0, dLen2) ; +// else +// dSideMinVal = max( dLen0, dLen2) ; +// } +// else { +// if ( dLen1 != 0 && dLen3 != 0) +// dSideMinVal = min( dLen1, dLen3) ; +// else +// dSideMinVal = max( dLen1, dLen3) ; +// } +// // calcolo le diagonali per controllare la dimensione massima dei triangoli in cui dividerei la cella +// dSideMaxVal = max( Dist( ptP00, ptP11), Dist( ptP10, ptP01)) ; +// +// +// double dErr = 0 ; +// if ( m_bMulti) { +// Point3d ptPSrf ; +// Plane3d plAppr ; +// if ( ! AreSamePointApprox( ptP00, ptP10) && ! AreSamePointApprox( ptP00, ptP01)) +// plAppr.Set( ptP00, ( ptP00 - ptP01) ^ ( ptP00 - ptP10)) ; +// else if ( AreSamePointApprox( ptP00, ptP10)) { +// plAppr.Set( ptP01, ( ptP00 - ptP01) ^ ( ptP01 - ptP11)) ; +// } +// else if ( AreSamePointApprox( ptP00, ptP01)) { +// plAppr.Set( ptP10, ( ptP10 - ptP11) ^ ( ptP00 - ptP10)) ; +// } +// for ( double i = 0.25 ; i < 1 ; i = i + 0.25) { +// for ( double j = 0.25 ; j < 1 ; j = j + 0.25) { +// double dU = ( 1 - i) * m_mTree[nCToSplit].GetTopRight().x + i * m_mTree[nCToSplit].GetBottomLeft().x ; +// double dV = ( 1 - j) * m_mTree[nCToSplit].GetTopRight().y + j * m_mTree[nCToSplit].GetBottomLeft().y ; +// m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ; +// dErr = max( abs( DistPointPlane( ptPSrf, plAppr)), dErr) ; +// } +// } +// } +// else { +// dErr = 1. / 4. * ( (ptP00 - ptP01) + (ptP11 - ptP10)).Len() ; +// } +// // se la cella è abbastanza grande da poter essere divisa ancora e devo approssimare meglio, la divido +// if ( dSideMinVal / 2 >= dSideMin && dSideMaxVal < dSideMax && dErr > dLinTol) { +// m_mTree[nCToSplit].SetSplitDirVert( bVert) ; +// // effettuo lo split +// Split( nCToSplit) ; +// +// // procedo con lo split del Child1 +// nCToSplit = m_mTree[nCToSplit].m_nChild1 ; +// } +// else { +// // sono arrivato ad una cella Leaf, quindi salvo la cella +// m_vnLeaves.push_back( nCToSplit) ; +// m_mTree[nCToSplit].SetProcessed() ; +// // risalgo i parent finché non trovo il primo Child2 da processare +// nCToSplit = m_mTree[nCToSplit].m_nParent ; +// if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) +// m_mTree[nCToSplit].SetProcessed() ; +// while ( m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) { +// if ( m_mTree[nCToSplit].m_nParent != -2) +// nCToSplit = m_mTree[nCToSplit].m_nParent ; +// if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) +// m_mTree[nCToSplit].SetProcessed() ; +// if ( nCToSplit == -1 && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) +// break ; +// } +// nCToSplit = m_mTree[nCToSplit].m_nChild2 ; +// } +// } +// else { +// nCToSplit = m_mTree[nCToSplit].m_nChild1 ; +// } +// } +// } +// } +// // se la superficie è trimmata +// else { +// SurfFlatRegion sfrTrimReg ; +// } +// return true ; +//} + //---------------------------------------------------------------------------- -void Tree::Balance() +void +Tree::Balance() { //for ( int i : vCheck ) { // // non ancora implementato // // rendo il tree balanced : ogni foglia deve avere una profondità di +- 1 rispetto alle foglie adiacenti. //} + + // al momento il problema viene bypassato in fase di generazione dei poligoni, considerando per ogni cella, oltre ai propri vertici + // i vertici dei vicini che giacciono sui suoi lati } //---------------------------------------------------------------------------- -void Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const +void +Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const { if ( (int) vTopNeighs.size() == 0) { if ( m_mTree.at(nId).m_nTop == -2) @@ -738,7 +836,8 @@ void Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const //---------------------------------------------------------------------------- -void Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const +void +Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const { if ( (int) vBottomNeighs.size() == 0) { if ( m_mTree.at(nId).m_nBottom == -2) @@ -817,7 +916,8 @@ void Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const //---------------------------------------------------------------------------- -void Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const +void +Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const { if ( (int) vLeftNeighs.size() == 0) { if ( m_mTree.at(nId).m_nLeft == -2) @@ -895,7 +995,8 @@ void Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const } //---------------------------------------------------------------------------- -void Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const +void +Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const { if ( (int) vRightNeighs.size() == 0) { if ( m_mTree.at(nId).m_nRight == -2) @@ -973,7 +1074,52 @@ void Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const } //---------------------------------------------------------------------------- -int Tree::GetHeightLeaves( int nId, INTVECTOR& vnLeaves, int d) const +void +Tree::GetRootNeigh( int nEdge, INTVECTOR& vNeigh) +{ + int nId = -1 ; + bool bMod = false ; + if ( nEdge == 0 ) { + if ( m_mTree[nId].m_nBottom == -2 ) { + m_mTree[nId].m_nBottom = -1 ; + bMod = true; + } + GetBottomNeigh( nId, vNeigh) ; + if ( bMod) + m_mTree[nId].m_nBottom = -2 ; + } + else if ( nEdge == 1 ) { + if ( m_mTree[nId].m_nRight == -2 ) { + m_mTree[nId].m_nRight = -1 ; + bMod = true; + } + GetRightNeigh( nId, vNeigh) ; + if ( bMod) + m_mTree[nId].m_nRight = -2 ; + } + else if ( nEdge == 2 ) { + if ( m_mTree[nId].m_nTop == -2 ) { + m_mTree[nId].m_nTop = -1 ; + bMod = true; + } + GetTopNeigh( nId, vNeigh) ; + if ( bMod) + m_mTree[nId].m_nTop = -2 ; + } + else if ( nEdge == 3 ) { + if ( m_mTree[nId].m_nLeft == -2 ) { + m_mTree[nId].m_nLeft = -1 ; + bMod = true; + } + GetLeftNeigh( nId, vNeigh) ; + if ( bMod) + m_mTree[nId].m_nLeft = -2 ; + } +} + +//---------------------------------------------------------------------------- +int +Tree::GetHeightLeaves( int nId, INTVECTOR& vnLeaves, int d) const { if ( nId == -1 && m_mTree.at(-1).IsLeaf()) { vnLeaves.push_back( -1) ; @@ -1013,7 +1159,8 @@ int Tree::GetHeightLeaves( int nId, INTVECTOR& vnLeaves, int d) const } //---------------------------------------------------------------------------- -int Tree::GetDepth( int nId, int nRef = -2) const +int +Tree::GetDepth( int nId, int nRef = -2) const { int c = 0 ; while ( m_mTree.at(nId).m_nParent != nRef) { @@ -1024,7 +1171,352 @@ int Tree::GetDepth( int nId, int nRef = -2) const } //---------------------------------------------------------------------------- -bool Tree::GetPolygons( POLYLINEVECTOR& vPolygons) +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) ; + } + 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; + } +} + +//---------------------------------------------------------------------------- +bool +Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons) { if ( m_vPolygons.empty()) { PNTVECTOR vVertices ; @@ -1108,10 +1600,517 @@ bool Tree::GetPolygons( POLYLINEVECTOR& vPolygons) for ( int i = 0 ; i < (int) vVertices.size() ; ++i) { m_vPolygons.back().AddUPoint( i, vVertices.at(i)) ; } + } } // restituisco i poligoni delle celle del tree nello spazio parametrico vPolygons = m_vPolygons ; return true ; -} \ No newline at end of file +} + +//---------------------------------------------------------------------------- +void +Tree::ResetTree( void) +{ + //int nCToReset = -1 ; + //while ( nCToReset != -2 && m_mTree[nCToReset].IsProcessed() == true) { + // if ( m_mTree[nCToReset].IsLeaf()) { + // m_mTree[nCToReset].SetProcessed( false) ; + // + // // risalgo i parent finché non trovo il primo Child2 da deprocessare + // nCToReset = m_mTree[nCToReset].m_nParent ; + // if ( ! m_mTree[m_mTree[nCToReset].m_nChild1].IsProcessed() && ! m_mTree[m_mTree[nCToReset].m_nChild2].IsProcessed()) + // m_mTree[nCToReset].SetProcessed( false) ; + // while ( ! m_mTree[m_mTree[nCToReset].m_nChild2].IsProcessed()) { + // if ( m_mTree[nCToReset].m_nParent != -2) + // nCToReset = m_mTree[nCToReset].m_nParent ; + // if ( ! m_mTree[m_mTree[nCToReset].m_nChild1].IsProcessed() && ! m_mTree[m_mTree[nCToReset].m_nChild2].IsProcessed()) + // m_mTree[nCToReset].SetProcessed( false) ; + // if ( nCToReset == -1 && ! m_mTree[m_mTree[nCToReset].m_nChild2].IsProcessed()) + // break ; + // } + // nCToReset = m_mTree[nCToReset].m_nChild2 ; + + // } + // else { + // nCToReset = m_mTree[nCToReset].m_nChild1 ; + // } + //} + for ( int nC : m_vnLeaves ) { + m_mTree[nC].SetProcessed( false) ; + } +} + +//---------------------------------------------------------------------------- +int +Tree::FindCell( const Point3d& ptToAssign) const +{ + // se fallisce ritorna -2 + // verifico che il punto sia all'interno dello spazio parametrico + if ( ptToAssign.x < m_mTree.at(-1).GetBottomLeft().x || ptToAssign.x > m_mTree.at( -1).GetTopRight().x || + ptToAssign.y < m_mTree.at(-1).GetBottomLeft().y || ptToAssign.y > m_mTree.at( -1).GetTopRight().y ) + return -2 ; + + int nId = -1 ; + 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) { + nId = m_mTree.at(nId).m_nChild1 ; + } + else { + nId = m_mTree.at(nId).m_nChild2 ; + } + } + else { + double dMid = ( m_mTree.at(nId).GetBottomLeft().y + m_mTree.at(nId).GetTopRight().y) / 2 ; + if ( ptToAssign.y < dMid ) { + nId = m_mTree.at(nId).m_nChild2 ; + } + else { + nId = m_mTree.at(nId).m_nChild1 ; + } + } + } + if ( nId == -1) + nId = -2 ; + return nId ; +} + +//---------------------------------------------------------------------------- +bool +Tree::TraceLoopLabelCell( void) +{ + // approssimo i loop di trim con delle spezzate + POLYLINEVECTOR vPlApprox ; + //for ( PtrOwner pCrv : m_vLoop){ + for ( int p = 0 ; p < (int) m_vLoop.size(); ++ p){ + PtrOwner pCrv( m_vLoop[p]->Clone()) ; + double dLinTol = 0.01 ; // questo è riferito allo spazio parametrico perché le curve di loop sono già state riscalate!!!!!! + double dAngTolDeg = 5 ; + PolyLine plApprox ; + int nType = 0 ; + pCrv->ApproxWithLines( dLinTol,dAngTolDeg, nType, plApprox) ; + 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!!!!!! + 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 + double dArea ; + Plane3d plExtPlane ; + bool bCCW ; + plLoop.IsClosedAndFlat( plExtPlane, dArea, 50 * EPS_SMALL) ; + if ( plExtPlane.GetVersN().z > 0 ) + bCCW = true ; + else + bCCW = false ; + // trovo in quale cella è il ptStart + Point3d ptStart ; + plLoop.GetFirstPoint( ptStart) ; + int nId = FindCell( ptStart) ; + // trovo quali punti della polyline sono nella cella e l'intersezione + PNTVECTOR vptInters ; + vptInters.push_back( ptStart) ; + // qui mi devo salvare quanti elementi ho già nel vettore m_vInters della cella + // per poter fare il merge con l'ultimo vptInters della curva di trim, che sarà ancora in questa cella + // e terminerà nel punto di start + int nPass = (int) m_mTree[nId].m_vInters.size() ; + m_mTree[nId].m_vInters.emplace_back() ; + // salvo il verso del loop + m_mTree[nId].m_vInters.back().bCCW = bCCW ; + // 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 ; + plLoop.GetPrevPoint( ptStart) ; + 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 + bLoopInside = false ; + // trovo l'intersezione e passo alla cella successiva. nId viene aggiornato dalla funzione FindInters + FindInters( nId, clTrim, vptInters) ; + // ricalcolo la posizione di nId nel vettore delle foglie + iter = find( m_vnLeaves.begin(), m_vnLeaves.end(), nId) ; + nIdPolygon = std::distance( m_vnLeaves.begin(), iter) ; + // salvo il verso del loop + m_mTree[nId].m_vInters.back().bCCW = bCCW ; + // salvo il chunk del loop + m_mTree[nId].m_vInters.back().nChunk = m_mChunk[i] ; + } + // aggiungo la fine del segmento nel vettore delle intersezioni + vptInters.push_back( ptCurr) ; + } + vptInters.pop_back() ; + m_mTree[nId].m_vInters.back().vpt = vptInters ; + if ( bLoopInside) { + m_mTree[nId].m_vnLoop.push_back( i) ; + // setto la categoria della cella + if ( m_mTree[nId].m_nFlag == 0) + m_mTree[nId].m_nFlag = 2 ; + else if ( m_mTree[nId].m_nFlag == 1) + m_mTree[nId].m_nFlag = 3 ; + // 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(), + m_mTree[nId].m_vInters[nPass].vpt.end()) ; + m_mTree[nId].m_vInters[nPass] = m_mTree[nId].m_vInters.back() ; + m_mTree[nId].m_vInters.pop_back() ; + // sistemo il lato d'uscita + m_mTree[nId].m_vInters[nPass].nOut = nOut ; + } + } + + // riordino i vettori di intersezione per ogni cella + for ( int nId : m_vnLeaves) { + 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/////////////////////////////////////////////////////////// + + // } + // + // 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 + + + + // // 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 ; +} + +//---------------------------------------------------------------------------- +bool +Tree::FindInters( int& nId, CurveLine& clTrim, PNTVECTOR& vptInters) +{ + CurveLine clEdge , clEdge2 ; + Point3d ptStart , ptEnd ; + clTrim.GetStartPoint( ptStart) ; + clTrim.GetEndPoint( ptEnd) ; + // trovo da quale lato sto uscendo + Point3d ptTR = m_mTree[nId].GetTopRight() ; + Point3d ptBL = m_mTree[nId].GetBottomLeft() ; + Point3d ptTl( ptBL.x , ptTR.y) ; + Point3d ptBr( ptTR.x , ptBL.y) ; + 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 + if ( ptEnd.y > ptTR.y && ptEnd.x <= ptTR.x) { + nEdge = 0 ; + // lato sopra + if ( ptEnd.x >= ptBL.x) + clEdge.Set( ptTR, ptTl) ; + // lato sinistro + else //if ( ptEnd.x < ptBL.x) + clEdge2.Set( ptTl, ptBL) ; + } + else if ( ptEnd.x < ptBL.x && ptEnd.y <= ptTR.y) { + nEdge = 1 ; + // lato sinistro + if ( ptEnd.y >= ptBL.y) + clEdge.Set( ptTl, ptBL) ; + // lato sotto + else //if ( ptEnd.y < ptBL.y) + clEdge2.Set( ptBL, ptBr) ; + } + else if ( ptEnd.y < ptBL.y && ptEnd.x >= ptBL.x) { + nEdge = 2 ; + // lato sotto + if ( ptEnd.x <= ptTR.x) + clEdge.Set( ptBL, ptBr) ; + // lato destro + else if ( ptEnd.x > ptTR.x) + clEdge2.Set( ptBr, ptTR) ; + } + else if ( ptEnd.x > ptTR.x && ptEnd.y >= ptBL.y) { + nEdge = 3 ; + // lato desto + if ( ptEnd.y <= ptTR.y) + clEdge.Set( ptBr, ptTR) ; + // lato sopra + if ( ptEnd.y > ptTR.y) + clEdge2.Set( ptTR, ptTl) ; + } + else + return false ; + + // intersezione e controlli + IntersLineLine illExit( clTrim, clEdge, true) ; + IntCrvCrvInfo aInfo, aInfo2 ; + Point3d ptInters ; + if ( ! illExit.GetIntCrvCrvInfo( aInfo) ) + return false ; + if ( clEdge2.IsValid()){ + IntersLineLine illExit2( clTrim, clEdge2, true) ; + if ( ! illExit2.GetIntCrvCrvInfo( aInfo2) ) + return false ; + // verifico su quale dei due lati ho l'intersezione + if ( illExit2.GetNumInters() == 0) + ptInters = aInfo.IciA[0].ptI ; + else { + // solo intersezione sul lato 2 + if ( illExit.GetNumInters() == 0) { + ptInters = aInfo2.IciA[0].ptI ; + if ( nEdge == 3) + nEdge = 0 ; + else + ++ nEdge ; + } + // intersezione sul vertice della cella + else { + // la cella adiacente in diagonale a quel vertice + nEdge = nEdge + 4 ; + } + } + } + else + ptInters = aInfo.IciA[0].ptI ; + m_mTree[nId].m_vInters.back().nOut = nEdge ; + vptInters.push_back( ptInters) ; + // salvo il vettore intersezione per la cella e capisco in quale altra cella passare + m_mTree[nId].m_vInters.back().vpt = vptInters ; + vptInters.clear() ; + // setto la categoria della cella + if ( m_mTree[nId].m_nFlag == 0) + m_mTree[nId].m_nFlag = 1 ; + else if ( m_mTree[nId].m_nFlag == 2) + m_mTree[nId].m_nFlag = 3 ; + // seleziono la cella successiva da analizzare + INTVECTOR vNeigh ; + if ( nEdge == 0) { + GetTopNeigh( nId, vNeigh) ; + std::reverse( vNeigh.begin(), vNeigh.end()) ; + for ( int j : vNeigh ) { + if ( ptInters.x >= m_mTree[j].GetBottomLeft().x) { + nId = j ; + break ; + } + } + m_mTree[nId].m_vInters.emplace_back() ; + m_mTree[nId].m_vInters.back().nIn = 2 ; + } + else if ( nEdge == 1) { + GetLeftNeigh( nId, vNeigh) ; + std::reverse( vNeigh.begin(), vNeigh.end()) ; + for ( int j : vNeigh ) { + if ( ptInters.y >= m_mTree[j].GetBottomLeft().y) { + nId = j ; + break ; + } + } + m_mTree[nId].m_vInters.emplace_back() ; + m_mTree[nId].m_vInters.back().nIn = 3 ; + } + else if ( nEdge == 2) { + GetBottomNeigh( nId, vNeigh) ; + for ( int j : vNeigh ) { + if ( ptInters.x <= m_mTree[j].GetTopRight().x) { + nId = j ; + break ; + } + } + m_mTree[nId].m_vInters.emplace_back() ; + m_mTree[nId].m_vInters.back().nIn = 0 ; + } + else if ( nEdge == 3) { + GetRightNeigh( nId, vNeigh) ; + for ( int j : vNeigh ) { + if ( ptInters.y <= m_mTree[j].GetTopRight().y) { + nId = j ; + break ; + } + } + m_mTree[nId].m_vInters.emplace_back() ; + m_mTree[nId].m_vInters.back().nIn = 1 ; + } + else if ( nEdge == 4) { + GetTopNeigh( nId, vNeigh) ; + int nIdTemp = vNeigh[0] ; + vNeigh.clear() ; + GetLeftNeigh( nIdTemp, vNeigh) ; + nId = vNeigh[0] ; + m_mTree[nId].m_vInters.emplace_back() ; + m_mTree[nId].m_vInters.back().nIn = 6 ; + } + else if ( nEdge == 5) { + GetLeftNeigh( nId, vNeigh) ; + int nIdTemp = vNeigh[0] ; + vNeigh.clear() ; + GetBottomNeigh( nIdTemp, vNeigh) ; + nId = vNeigh.back() ; + m_mTree[nId].m_vInters.emplace_back() ; + m_mTree[nId].m_vInters.back().nIn = 7 ; + } + else if ( nEdge == 6) { + GetBottomNeigh( nId, vNeigh) ; + int nIdTemp = vNeigh.back() ; + vNeigh.clear() ; + GetRightNeigh( nIdTemp, vNeigh) ; + nId = vNeigh[0] ; + m_mTree[nId].m_vInters.emplace_back() ; + m_mTree[nId].m_vInters.back().nIn = 4 ; + } + else if ( nEdge == 7) { + GetRightNeigh( nId, vNeigh) ; + int nIdTemp = vNeigh.back() ; + vNeigh.clear() ; + GetTopNeigh( nIdTemp, vNeigh) ; + nId = vNeigh[0] ; + m_mTree[nId].m_vInters.emplace_back() ; + m_mTree[nId].m_vInters.back().nIn = 5 ; + } + // aggiungo l'intersezione al vettore delle intersezioni della prossima cella + vptInters.push_back( ptInters) ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +Tree::CheckIfBefore( PolyLine& pl, int nEdge) const +{ + Point3d ptStart, ptEnd ; + pl.GetFirstPoint( ptStart) ; + pl.GetLastPoint( ptEnd) ; + if ( nEdge == 0 ) { + return ptEnd.x > ptStart.x ; + } + else if ( nEdge == 1 ) { + return ptEnd.y > ptStart.y ; + } + else if ( nEdge == 2 ) { + return ptEnd.x < ptStart.x ; + } + else if ( nEdge == 3 ) { + return ptEnd.y < ptStart.y ; + } + return false ; +} + +//---------------------------------------------------------------------------- +bool +Tree::CheckIfAfter( PolyLine& pl, Point3d& ptNextStart, int nEdge) const +{ + Point3d ptEnd ; + pl.GetLastPoint( ptEnd) ; + if ( nEdge == 0 ) { + return ptEnd.x > ptNextStart.x ; + } + else if ( nEdge == 1 ) { + return ptEnd.y > ptNextStart.y ; + } + else if ( nEdge == 2 ) { + return ptEnd.x < ptNextStart.x ; + } + else if ( nEdge == 3 ) { + return ptEnd.y < ptNextStart.y ; + } + return false ; +} + diff --git a/Tree.h b/Tree.h index 751c21f..dbb8378 100644 --- a/Tree.h +++ b/Tree.h @@ -17,6 +17,28 @@ #include #include "SurfBezier.h" #include "GeoConst.h" +#include "CurveLine.h" + +struct Inters { + int nIn ; + PNTVECTOR vpt ; + int nOut ; + bool bCCW ; + int nChunk ; + // riordino le intersezioni per lato in senso antiorario dal top + // se ho più intersezioni che entrano in un lato le riordino considerando che percorro i lati in senso antiorario a partire da ptTR + bool operator < ( Inters& b) { + bool bEqIn = ( nIn == b.nIn) ; + return nIn < b.nIn || + ( bEqIn && nIn == 0 && vpt[0].x > b.vpt[0].x) || + ( bEqIn && nIn == 1 && vpt[0].y > b.vpt[0].y) || + ( bEqIn && nIn == 2 && vpt[0].x < b.vpt[0].x) || + ( bEqIn && nIn == 3 && vpt[0].y < b.vpt[0].y) + ; } +} ; +// nIn e nOut sono flag che indicano da quale lato ho l'ingresso e l'uscita 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 //---------------------------------------------------------------------------- class Cell @@ -36,21 +58,28 @@ class Cell bool IsSplitVert( void) const { return m_bSplitVert ; } // se true la cella verrebbe splittata verticalmente, sennò orizzontalmente bool IsLeaf( void) const ; // flag che indica se la cella ha figli o se è una foglia bool IsProcessed( void) const { return m_bProcessed ; } // flag che indica se tutti i figli della cella, se ce ne sono, sono stati processati - void Processed( void) { m_bProcessed = true ; } + void SetProcessed( bool bProcessed = true) { m_bProcessed = bProcessed ; } static bool minorX ( const Cell& c1, const Cell& c2) { return c1.m_ptPbl.x < c2.m_ptPbl.x ; } static bool minorY ( const Cell& c1, const Cell& c2) { return c1.m_ptPbl.y < c2.m_ptPbl.y ; } - + public : - int m_nId ; // Id della cella - int m_nTop ; // cella adiacente al lato top - int m_nBottom ; // cella adiacente al lato bottom - int m_nLeft ; // cella adiacente al lato left - int m_nRight ; // cella adiacente al lato right - int m_nParent ; // cella genitore - int m_nDepth ; // profondità della cella rispetto a root - double m_dSplit ; // parametro a cui è stata splittata la cella - int m_nChild1 ; // prima cella figlio - int m_nChild2 ; // seconda cella figlio + int m_nId ; // Id della cella + int m_nTop ; // cella adiacente al lato top + int m_nBottom ; // cella adiacente al lato bottom + int m_nLeft ; // cella adiacente al lato left + int m_nRight ; // cella adiacente al lato right + int m_nParent ; // cella genitore + int m_nDepth ; // profondità della cella rispetto a root + 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 + // 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 + std::vector m_vInters ; // vettore delle intersezioni della cella con i loop di trim + // ogni elemento del vettore è l'insieme dei punti che caratterizza un atrtaversamento della cella private : Point3d m_ptPbl ; // punto bottom left @@ -69,9 +98,11 @@ public : void SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches = true) ; bool BuildTree( double dLinTol = LIN_TOL_STD, double dSideMin = 5, double dSideMax = INFINITO) ; // dSideMax è il massimo per la dimensione maggiore di un triangolo della trimesh // dSideMin è lunghezza minima del lato di una cella nello spazio reale - bool GetPolygons( POLYLINEVECTOR& vPolygons) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero + bool GetPolygons( std::vector& vPolygons) ; + 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 + private : void Split( int nId, double dSplitValue) ; // funzione di split di una cella al parametro indicato nella direzione data da bVert void Split( int nId) ; // funzione di split di una cella dell'albero a metà nella direzione data da bVert @@ -82,17 +113,30 @@ private : void GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato bottom void GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato left void GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato right + void GetRootNeigh( int nEdge, INTVECTOR& vNeigh) ; // restituisce le foglie dell'albero che sono adiacenti al lato nEdge, numerato a partire dal top ( 0) in senso antiorario + void ResetTree ( void) ; // resetto m_bProcessed a false per tutti i nodi dell'albero + int FindCell ( const Point3d& ptToAssign) const ; // dato un punto, trova la cella foglia a cui appartiene + 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 CheckIfBefore( PolyLine& pl, int nEdge) const ; + bool CheckIfAfter( PolyLine& pl, Point3d& ptNextStart, int nEdge) const ; private : const SurfBezier* m_pSrfBz ; // superficie di bezier - DBLVECTOR m_vDim ; // distanze tra i vertici della superficie di bezier in ordine antiorario a partire da ptP00 + DBLVECTOR m_vDim ; // distanze tra i vertici della superficie di bezier in 3d in ordine antiorario a partire da ptP00 bool m_bTrimmed ; // superficie trimmata + std::vector m_vChunk ; // elenco dei loop divisi per chunk + std::map m_mChunk ; + //std::vector m_vLoop ; + ICURVEPOVECTOR m_vLoop ; // curve di loop. la 0 è il bordo dello spazio parametrico, le altre sono i loop interni bool m_bBilinear ; // superficie bilineare bool m_bMulti ; // superficie multi-patch 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::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 INTVECTOR m_vnLeaves ; // vettore delle foglie