diff --git a/SurfBezier.cpp b/SurfBezier.cpp index fe54cf4..36bacaa 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1500,8 +1500,9 @@ SurfBezier::GetAuxSurf( void) const // costruttore della superficie Tree Tree( this, true) ; - //Tree.BuildTree_test() ; - Tree.BuildTree( 0.2, 25) ; + Tree.BuildTree_test() ; + //Tree.BuildTree( 0.2, 5) ; + //Tree.BuildTree( 1, 25) ; vector vvPL ; Tree.GetPolygons( vvPL) ; PtrOwner pSrfTm( CreateBasicSurfTriMesh()) ; @@ -1521,7 +1522,7 @@ SurfBezier::GetAuxSurf( void) const PNTVECTOR vPnt3d ; for ( int i = 0 ; i < int( vPnt.size()) ; ++ i) { Point3d pt3d ; - if ( ! GetPointD1D2( vPnt[i].x, vPnt[i].y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d)) + if ( ! GetPointD1D2( vPnt[i].x / SBZ_TREG_COEFF, vPnt[i].y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d)) return nullptr ; vPnt3d.push_back( pt3d) ; } @@ -1540,6 +1541,24 @@ SurfBezier::GetAuxSurf( void) const return m_pSTM ; } +//---------------------------------------------------------------------------- +bool +SurfBezier::GetLeaves( std::vector>& vLeaves) const +{ + Tree Tree( this, true) ; + Tree.BuildTree_test() ; + //Tree.BuildTree( 0.2, 5) ; + //Tree.BuildTree( 1, 25) ; + std::vector vCells ; + Tree.GetLeaves( vCells) ; + for (int k = 0 ; k < (int)vCells.size(); ++ k ) { + std::tuple tCell ; + tCell = make_tuple( vCells[k].m_nId, vCells[k].GetBottomLeft(), vCells[k].GetTopRight()) ; + vLeaves.push_back( tCell) ; + } + return true ; +} + //---------------------------------------------------------------------------- void SurfBezier::ResetAuxSurf( void) const diff --git a/SurfBezier.h b/SurfBezier.h index 6cfc9e2..cec073c 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -106,6 +106,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool GetControlCurveOnU( int nIndV, PolyLine& plCtrlU) const override ; bool GetControlCurveOnV( int nIndU, PolyLine& plCtrlV) const override ; const SurfTriMesh* GetAuxSurf( void) const override ; + bool GetLeaves( std::vector>& vLeaves) const override ; public : // IGeoObjRW int GetNgeId( void) const override ; diff --git a/Tree.cpp b/Tree.cpp index bbbe40c..d5f3f04 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -30,7 +30,7 @@ Cell::Cell( void) : m_nId( -1),m_nTop ( -2), m_nBottom( -2), m_nLeft( -2), m_nRight ( -2), m_nParent( -2), m_nDepth( 0), m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_nFlag2( 0), m_nRightEdgeIn( -1), m_ptPbl(ORIG), m_ptPtr(), m_bProcessed(false), m_bSplitVert(true) { - Point3d ptTr ( 1, 1) ; + Point3d ptTr ( 1 * SBZ_TREG_COEFF, 1 * SBZ_TREG_COEFF) ; m_ptPtr = ptTr ; } @@ -71,7 +71,7 @@ Cell::IsLeaf ( void) const Tree::Tree( void) : m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosed( false) { - Point3d ptBl( 0, 0), ptTr ( 1, 1) ; + Point3d ptBl( 0, 0), ptTr ( 1 * SBZ_TREG_COEFF, 1 * SBZ_TREG_COEFF) ; Cell cRoot( ptBl, ptTr) ; m_mTree.insert( std::pair< int, Cell>( -1, cRoot)) ; } @@ -141,7 +141,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches) 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) ; + //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 @@ -156,7 +156,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches) } // salvo i vertici 3d della cella root Point3d ptBottom ( 0, 0) ; - Point3d ptTop( nSpanU, nSpanV) ; + Point3d ptTop( nSpanU * SBZ_TREG_COEFF, nSpanV * SBZ_TREG_COEFF) ; Cell cRoot( ptBottom, ptTop) ; m_mTree.insert( std::pair< int, Cell>( -1, cRoot)) ; Point3d ptP00, ptP10, ptP11, ptP01 ; @@ -314,8 +314,8 @@ Tree::Split( int nId, double dSplitValue) m_mTree[m_mTree[nId].m_nChild2].m_nRight = m_mTree[nId].m_nRight ; // metto i corrispondenti 3d dei punti dello split nella mappa m_mVert // per ogni cella i punti devono essere nell'ordine ptP00, ptP10, ptP11, ptP01 - m_pSrfBz->GetPointD1D2( m_mTree[nId].GetBottomLeft().x, dSplitValue, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptVert1) ; - m_pSrfBz->GetPointD1D2( m_mTree[nId].GetTopRight().x, dSplitValue, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptVert2) ; + m_pSrfBz->GetPointD1D2( m_mTree[nId].GetBottomLeft().x / SBZ_TREG_COEFF, dSplitValue / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptVert1) ; + m_pSrfBz->GetPointD1D2( m_mTree[nId].GetTopRight().x / SBZ_TREG_COEFF, dSplitValue / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptVert2) ; m_mVert[nNodes - 1].push_back( ptVert1) ; m_mVert[nNodes - 1].push_back( ptVert2) ; m_mVert[nNodes - 1].push_back( m_mVert[nId][2]) ; @@ -343,8 +343,8 @@ Tree::Split( int nId, double dSplitValue) m_mTree[m_mTree[nId].m_nChild2].m_nRight = m_mTree[nId].m_nRight ; // metto i corrispondenti 3d dei punti dello split nella mappa m_mVert // per ogni cella i punti devono essere nell'ordine ptP00, ptP10, ptP11, ptP01 - m_pSrfBz->GetPointD1D2( dSplitValue, m_mTree[nId].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptVert2) ; - m_pSrfBz->GetPointD1D2( dSplitValue, m_mTree[nId].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptVert1) ; + m_pSrfBz->GetPointD1D2( dSplitValue / SBZ_TREG_COEFF, m_mTree[nId].GetBottomLeft().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptVert2) ; + m_pSrfBz->GetPointD1D2( dSplitValue / SBZ_TREG_COEFF, m_mTree[nId].GetTopRight().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptVert1) ; m_mVert[nNodes - 1].push_back( m_mVert[nId][0]) ; m_mVert[nNodes - 1].push_back( ptVert2) ; m_mVert[nNodes - 1].push_back( ptVert1) ; @@ -398,24 +398,46 @@ Tree::BuildTree_test( double dLinTol_, double dSideMin, double dSideMax) m_mTree[9].SetSplitDirVert( false) ; Split( 9) ; m_vnLeaves.push_back( 4) ; - m_vnLeaves.push_back( 5) ; + //m_vnLeaves.push_back( 5) ; m_vnLeaves.push_back( 6) ; - m_vnLeaves.push_back( 7) ; - m_vnLeaves.push_back( 10) ; + //m_vnLeaves.push_back( 7) ; + //m_vnLeaves.push_back( 10) ; m_vnLeaves.push_back( 11) ; - m_vnLeaves.push_back( 12) ; + //m_vnLeaves.push_back( 12) ; m_vnLeaves.push_back( 13) ; + // aggiunta di split + //celle 14,15 + m_mTree[5].SetSplitDirVert( true) ; + Split( 5) ; + m_vnLeaves.push_back( 14) ; + m_vnLeaves.push_back( 15) ; + //celle 16,17 + m_mTree[7].SetSplitDirVert( false) ; + Split( 7) ; + m_vnLeaves.push_back( 16) ; + m_vnLeaves.push_back( 17) ; + //celle 18,19 + m_mTree[12].SetSplitDirVert( true) ; + Split( 12) ; + m_vnLeaves.push_back( 18) ; + m_vnLeaves.push_back( 19) ; + //celle 20,21 + m_mTree[10].SetSplitDirVert( false) ; + Split( 10) ; + m_vnLeaves.push_back( 20) ; + m_vnLeaves.push_back( 21) ; + return true ; } //---------------------------------------------------------------------------- bool -Tree::BuildTree( double dLinTol_, double dSideMin, double dSideMax) +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 dLinTol = 0.2 ; //double dSideMin = 1 ; if ( ! m_bTrimmed || m_bTrimmed) { if ( ! m_bBilinear) { @@ -425,18 +447,18 @@ Tree::BuildTree( double dLinTol_, double dSideMin, double dSideMax) // 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 ; + double dLenParU = ( m_mTree[nCToSplit].GetTopRight().x - m_mTree[nCToSplit].GetBottomLeft().x) / SBZ_TREG_COEFF ; + double dLenParV = ( m_mTree[nCToSplit].GetTopRight().y - m_mTree[nCToSplit].GetBottomLeft().y) / SBZ_TREG_COEFF; 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 dU = ( m_mTree[nCToSplit].GetTopRight().x + m_mTree[nCToSplit].GetBottomLeft().x) / 2 / SBZ_TREG_COEFF ; + double dV = ( m_mTree[nCToSplit].GetTopRight().y + m_mTree[nCToSplit].GetBottomLeft().y) / 2 / SBZ_TREG_COEFF ; 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) ; + m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetBottomLeft().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00P10) ; + m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10P11) ; + m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetTopRight().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11P01) ; + m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x / SBZ_TREG_COEFF, 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) ; @@ -448,13 +470,13 @@ Tree::BuildTree( double dLinTol_, double dSideMin, double dSideMax) 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 ; + double dU = ( k * m_mTree[nCToSplit].GetTopRight().x + ( 1 - k) * m_mTree[nCToSplit].GetBottomLeft().x) / SBZ_TREG_COEFF ; + double dV = ( m_mTree[nCToSplit].GetTopRight().y + m_mTree[nCToSplit].GetBottomLeft().y) / 2 / SBZ_TREG_COEFF; 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) ; + m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetBottomLeft().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00P10) ; + m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetTopRight().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11P01) ; CurveLine clV ; clV.Set( ptP00P10, ptP11P01) ; DistPointCurve dpc( ptPSrf, clV) ; @@ -464,14 +486,14 @@ Tree::BuildTree( double dLinTol_, double dSideMin, double dSideMax) } 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 ; + double dU = ( m_mTree[nCToSplit].GetTopRight().x + m_mTree[nCToSplit].GetBottomLeft().x) / 2 / SBZ_TREG_COEFF ; + double dV = ( k * m_mTree[nCToSplit].GetTopRight().y + ( 1 - k) * m_mTree[nCToSplit].GetBottomLeft().y) / SBZ_TREG_COEFF ; 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) ; + m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10P11) ; + m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01P00) ; CurveLine clU ; clU.Set( ptP01P00, ptP10P11) ; DistPointCurve dpc( ptPSrf, clU) ; @@ -541,9 +563,9 @@ Tree::BuildTree( double dLinTol_, double dSideMin, double dSideMax) 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)) + double dULoc = (( 1 - dU) * m_mTree[nCToSplit].GetBottomLeft().x + dU * m_mTree[nCToSplit].GetTopRight().x) / SBZ_TREG_COEFF ; + if ( ! m_pSrfBz->GetPointD1D2( dULoc, m_mTree[nCToSplit].GetBottomLeft().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz0) || + ! m_pSrfBz->GetPointD1D2( dULoc, m_mTree[nCToSplit].GetTopRight().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz1)) return false ; DistPointCurve dpc0010( ptBz0, cl0010) ; DistPointCurve dpc0111( ptBz1, cl0111) ; @@ -552,7 +574,7 @@ Tree::BuildTree( double dLinTol_, double dSideMin, double dSideMax) 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 ; + double dVLoc = ( ( 1 - dV) * m_mTree[nCToSplit].GetBottomLeft().y + dV * m_mTree[nCToSplit].GetTopRight().y) / SBZ_TREG_COEFF ; if ( ! m_pSrfBz->GetPointD1D2( dULoc, dVLoc, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBzV)) return false ; DistPointCurve dpc( ptBzV, clV) ; @@ -632,10 +654,10 @@ Tree::BuildTree( double dLinTol_, double dSideMin, double dSideMax) } 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 ; + dU = (( 1 - i) * m_mTree[nCToSplit].GetBottomLeft().x + i * m_mTree[nCToSplit].GetTopRight().x) / SBZ_TREG_COEFF ; + dV = (( 1 - i) * m_mTree[nCToSplit].GetBottomLeft().y + i * m_mTree[nCToSplit].GetTopRight().y) / SBZ_TREG_COEFF ; + double dVLoc = ( m_mTree[nCToSplit].GetBottomLeft().y + m_mTree[nCToSplit].GetTopRight().y) / 2 / SBZ_TREG_COEFF ; + double dULoc = ( m_mTree[nCToSplit].GetBottomLeft().x + m_mTree[nCToSplit].GetTopRight().x) / 2 / SBZ_TREG_COEFF ; 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) ; @@ -689,8 +711,8 @@ Tree::BuildTree( double dLinTol_, double dSideMin, double dSideMax) } 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 ; + double dU = ( ( 1 - i) * m_mTree[nCToSplit].GetTopRight().x + i * m_mTree[nCToSplit].GetBottomLeft().x) / SBZ_TREG_COEFF ; + double dV = ( ( 1 - j) * m_mTree[nCToSplit].GetTopRight().y + j * m_mTree[nCToSplit].GetBottomLeft().y) / SBZ_TREG_COEFF ; m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ; dErr = std::max( abs( DistPointPlane( ptPSrf, plAppr)), dErr) ; } @@ -1307,8 +1329,8 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons) if ( vVertices.size() == 5) { Point3d ptPSrf, ptP00, ptP10, ptP11, ptP01; double dU, dV ; - dU = ( m_mTree.at(nId).GetBottomLeft().x + m_mTree.at(nId).GetTopRight().x) / 2 ; - dV = ( m_mTree.at(nId).GetBottomLeft().y + m_mTree.at(nId).GetTopRight().y) / 2 ; + dU = ( m_mTree.at(nId).GetBottomLeft().x + m_mTree.at(nId).GetTopRight().x) / 2 / SBZ_TREG_COEFF; + dV = ( m_mTree.at(nId).GetBottomLeft().y + m_mTree.at(nId).GetTopRight().y) / 2 / SBZ_TREG_COEFF; m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ; ptP00 = m_mVert.at(nId).at(0) ; ptP10 = m_mVert.at(nId).at(1) ; @@ -1555,13 +1577,14 @@ Tree::TraceLoopLabelCell( void) CurveLine clFirst ; clFirst.Set( ptFirst->first, ptSecond->first) ; INTVECTOR nCells = FindCell( ptStart, clFirst) ; - int nId ; + int nId, nFirstCell ; if ( (int)nCells.size() == 1) { nId = nCells[0] ; } else { nId = nCells.back() ; } + nFirstCell = nId ; // trovo quali punti della polyline sono nella cella e l'intersezione PNTVECTOR vptInters ; vptInters.push_back( ptStart) ; @@ -1581,11 +1604,11 @@ Tree::TraceLoopLabelCell( void) bool bVertex = false ; while ( plLoop.GetNextPoint( ptCurr)) { // sto uscendo dalla cella, quindi cerco l'intersezione - Point3d ptStart, ptEnd ; - plLoop.GetPrevPoint( ptStart) ; - plLoop.GetNextPoint( ptEnd) ; + Point3d ptTStart, ptTEnd ; + plLoop.GetPrevPoint( ptTStart) ; + plLoop.GetNextPoint( ptTEnd) ; CurveLine clTrim ; - clTrim.Set( ptStart, ptEnd) ; + clTrim.Set( ptTStart, ptTEnd) ; while( ! IsPointInsidePolyLine( ptCurr, vplPolygons[nIdPolygon], dLinTol)) { /// qui devo mettere una tolleranza negativa per poter tener conto anche dei punti che sono SULLA curva bLoopInside = false ; // trovo l'intersezione e passo alla cella successiva. nId viene aggiornato dalla funzione FindInters @@ -1602,10 +1625,11 @@ Tree::TraceLoopLabelCell( void) // aggiungo la fine del segmento nel vettore delle intersezioni vptInters.push_back( ptCurr) ; } - vptInters.pop_back() ; + if ( AreSamePointExact( ptCurr, ptStart)) + vptInters.pop_back() ; m_mTree[nId].m_vInters.back().vpt = vptInters ; if ( bLoopInside) { - m_mTree[nId].m_vnLoop.push_back( i) ; + //m_mTree[nId].m_vnLoop.push_back( i) ; // setto la categoria della cella if ( m_mTree[nId].m_nFlag == -1) m_mTree[nId].m_nFlag = 2 ; @@ -1618,24 +1642,27 @@ Tree::TraceLoopLabelCell( void) // 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 { + // verifico se sono effettivamente nella cella di partenza o nella penultima cella // devo verificare se il loop finisce in un vertice! in questo caso sono nella penultima cella! e devo fare un FindInters di nuovo per sistemare Point3d ptLast = m_mTree[nId].m_vInters.back().vpt.back() ; - Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ; - Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; - int nLastId ; - if ( AreSamePointApprox( m_mTree[nId].GetTopRight(), ptLast) || - AreSamePointApprox( ptTl, ptLast) || - AreSamePointApprox( m_mTree[nId].GetBottomLeft(), ptLast) || - AreSamePointApprox( ptBr, ptLast)) { - Point3d ptStart, ptEnd ; - plLoop.GetPrevPoint( ptEnd) ; - plLoop.GetPrevPoint( ptStart) ; - CurveLine clTrim ; - clTrim.Set( ptStart, ptEnd) ; - vptInters.clear() ; - nLastId = nId ; - FindInters( nId, clTrim, vptInters, bVertex) ; - m_mTree[nLastId].m_vInters.back().vpt.push_back( vptInters[0]) ; + if ( nId != nFirstCell) { + Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ; + Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; + int nLastId ; + if ( AreSamePointApprox( m_mTree[nId].GetTopRight(), ptLast) || + AreSamePointApprox( ptTl, ptLast) || + AreSamePointApprox( m_mTree[nId].GetBottomLeft(), ptLast) || + AreSamePointApprox( ptBr, ptLast)) { + Point3d ptTStart, ptTEnd ; + plLoop.GetPrevPoint( ptTEnd) ; + plLoop.GetPrevPoint( ptTStart) ; + CurveLine clTrim ; + clTrim.Set( ptTStart, ptTEnd) ; + vptInters.clear() ; + nLastId = nId ; + FindInters( nId, clTrim, vptInters, bVertex) ; + m_mTree[nLastId].m_vInters.back().vpt.push_back( vptInters[0]) ; + } } 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(), @@ -2256,6 +2283,7 @@ Tree::CreateCellPolygons( int nLeafId, std::vector& vPolygons, I while ( plCell.GetNextPoint( ptToAdd) && ! AreSamePointExact( ptToAdd, vEdgeVertex[next][0])) { vEdgeVertex[j].push_back( ptToAdd) ; } + //vEdgeVertex[next].push_back( ptToAdd) ; } // comincio a costruire il poligono @@ -2298,7 +2326,7 @@ Tree::CreateCellPolygons( int nLeafId, std::vector& vPolygons, I vLast.Normalize(); Vector3d vEdge ; if ( AreSameEdge( nEdge, 0)) { - if ( AreSamePointApprox(ptLast, ptTl) ) { + if ( AreSamePointExact(ptLast, ptTl) ) { vEdge = m_mTree[nId].GetBottomLeft() - ptTl ; vEdge.Normalize() ; if ( AreOppositeVectorApprox(vLast, vEdge) ) { @@ -2307,7 +2335,7 @@ Tree::CreateCellPolygons( int nLeafId, std::vector& vPolygons, I } } } - else if ( AreSameEdge( nEdge, 1) && AreSamePointApprox(ptLast, m_mTree[nId].GetBottomLeft()) ) { + else if ( AreSameEdge( nEdge, 1) && AreSamePointExact(ptLast, m_mTree[nId].GetBottomLeft()) ) { vEdge = ptBr - m_mTree[nId].GetBottomLeft() ; vEdge.Normalize() ; if ( AreOppositeVectorApprox(vLast, vEdge) ) { @@ -2316,7 +2344,7 @@ Tree::CreateCellPolygons( int nLeafId, std::vector& vPolygons, I } } else if ( AreSameEdge( nEdge, 2) ) { - if ( AreSamePointApprox(ptLast, ptBr) ) { + if ( AreSamePointExact(ptLast, ptBr) ) { vEdge = m_mTree[nId].GetTopRight() - ptBr ; vEdge.Normalize() ; if ( AreOppositeVectorApprox(vLast, vEdge) ) { @@ -2325,7 +2353,7 @@ Tree::CreateCellPolygons( int nLeafId, std::vector& vPolygons, I } } } - else if ( AreSameEdge( nEdge, 3) && AreSamePointApprox(ptLast, m_mTree[nId].GetTopRight()) ) { + else if ( AreSameEdge( nEdge, 3) && AreSamePointExact(ptLast, m_mTree[nId].GetTopRight()) ) { vEdge = ptTl - m_mTree[nId].GetTopRight() ; vEdge.Normalize() ; if ( AreOppositeVectorApprox(vLast, vEdge) ) { @@ -2393,16 +2421,36 @@ Tree::CreateCellPolygons( int nLeafId, std::vector& vPolygons, I bNotCameBack = ! ( AreSameEdge( nEdge, nEdgeIn) && CheckIfBefore( plTrimmedPoly, nEdge)) ; } - // se ho trovato un altro loop salto all'inizio del for + + // se ho trovato un altro loop salto all'inizio del for, dopo aver aggiunto eventuali punti intermedi if ( bValidNextStart) { + for ( int p = 1 ; p < (int) vEdgeVertex[nEdge].size() ; ++ p) { + if ( CheckIfBefore( nEdge, vEdgeVertex[nEdge][p], m_mTree[nId].m_vInters[vToCheckNow[nNext]].vpt[0]) ) { + plTrimmedPoly.AddUPoint( c, vEdgeVertex[nEdge][p]) ; + ++ c ; + } + } w = w + nSecondCheck ; continue ; } + // sono tornato indietro + else if ( ! bNotCameBack){ + Point3d ptStart ; + plTrimmedPoly.GetFirstPoint( ptStart) ; + for ( int p = 1 ; p < (int) vEdgeVertex[nEdge].size() ; ++ p) { + if ( CheckIfBefore( nEdge, vEdgeVertex[nEdge][p], ptStart) ) { + plTrimmedPoly.AddUPoint( c, vEdgeVertex[nEdge][p]) ; + ++ c ; + } + } + } } // non ho altri loop quindi aggiungo vertici finché torno al punto di partenza else { bNotCameBack = ! ( AreSameEdge( nEdge, nEdgeIn) && CheckIfBefore( plTrimmedPoly, nEdge)) ; + Point3d ptStart ; + plTrimmedPoly.GetFirstPoint( ptStart) ; while ( bNotCameBack) { Point3d ptVert ; if ( nEdge == 0) @@ -2421,19 +2469,29 @@ Tree::CreateCellPolygons( int nLeafId, std::vector& vPolygons, I else nEdge = 0 ; // aggiorno le condizioni per il while - bNotCameBack = ! ( AreSameEdge( nEdge, nEdgeIn) && CheckIfBefore( plTrimmedPoly, nEdge)) ; + bNotCameBack = ! ( AreSameEdge( nEdge, nEdgeIn) && CheckIfBefore( plTrimmedPoly, nEdge)) ; } + for ( int p = 1 ; p < (int) vEdgeVertex[nEdge].size() ; ++ p) { + if ( CheckIfBefore( nEdge, vEdgeVertex[nEdge][p], ptStart)) { + plTrimmedPoly.AddUPoint( c, vEdgeVertex[nEdge][p]) ; + ++ c ; + } + } + } plTrimmedPoly.Close() ; + // controllo sull'area del poligono, se è 0 ( quindi un segmento), non lo aggiungo double dArea ; plTrimmedPoly.GetAreaXY( dArea) ; - if ( dArea > SQ_EPS_SMALL) { + //if ( dArea > SQ_EPS_SMALL) { + if ( dArea > 0) { vCellPolygons.push_back( plTrimmedPoly) ; vPolygons.push_back( vCellPolygons) ; ++ nPoly ; vnParentChunk.push_back( inA.nChunk) ; vCellPolygons.clear() ; } + c = 0 ; plTrimmedPoly.Clear() ; nEdgeIn = -1 ; @@ -2470,20 +2528,38 @@ Tree::CreateIslandAndHoles( int nLeafId, std::vector& vPolygons, if ( m_mTree[nId].m_nFlag == 3 || m_mTree[nId].m_nFlag == 2) { PolyLine plInLoop ; // numero dei loop interni passati - int n = 0 ; - Inters inA = m_mTree[nId].m_vInters[n] ; - // se ho almeno un loop CW che non è contenuto in un altro poligono o in un loop interno CCW - bool bAllCW = true ; - for ( Inters inB : m_mTree[nId].m_vInters) { - if ( inB.nIn == -1){ - if ( inB.bCCW) { - bAllCW = false ; - break ; + Inters inA ; + // se ho almeno un loop CW che non è contenuto in un altro poligono o in un loop interno CCW devo aggiungere il bordo + bool bEdgeToAdd = true ; + bool bAllContained = true ; + bool bContained = false ; + int nInters = (int) m_mTree[nId].m_vInters.size() ; + for ( int n = 0 ; n < nInters ; ++ n) { + inA = m_mTree[nId].m_vInters[n] ; + if ( inA.nIn == -1) { + // per ogni loop CW verifico che ci sia un loop CCW dello stesso chunk ( che quindi lo contiene) + if ( ! inA.bCCW) { + bContained = false ; + Inters inB = m_mTree[nId].m_vInters[0] ; + for( int c = 0 ; c < nInters ; ++ c){ + inB = m_mTree[nId].m_vInters[c] ; + if ( inB.nIn == -1) { + if ( inB != inA && inB.nChunk == inA.nChunk) { + bContained = true ; + break ; + } + } + else + break ; + } + bAllContained = bAllContained && bContained ; } } + else + break ; } - // la seconda condizione è da cambiareeeeeeeeeeeeeeeeeeeee//////////////////////////////////////////////////////////////////////////////////////////// - if ( m_mTree[nId].m_nFlag == 2 && ! inA.bCCW) { + + if ( m_mTree[nId].m_nFlag == 2 && ( bEdgeToAdd || ! bAllContained)) { // 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) ; @@ -2503,42 +2579,44 @@ Tree::CreateIslandAndHoles( int nLeafId, std::vector& vPolygons, 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( k, ptInt) ; - ++ k ; - } - plInLoop.Close(); - bool bAdded = false ; - // se il loop è CW devo controllare in quale altro dei poligoni che ho già aggiunto è contenuto - if ( ! inA.bCCW) { - Point3d ptStart ; - plInLoop.GetFirstPoint( ptStart) ; - int nOtherPoly = (int)vPolygons.size() ; - for ( int r = 0 ; r < nPoly ; ++r ) { - if ( IsPointInsidePolyLine( ptStart, vPolygons[nOtherPoly - r - 1][0], -0.01) && vnParentChunk[nPoly - r - 1] == inA.nChunk ) { - vPolygons[nOtherPoly - r - 1].push_back( plInLoop) ; - plInLoop.Clear() ; - vnParentChunk.push_back( inA.nChunk) ; - bAdded = true ; - break ; + for ( int i = 0 ; i < nInters ; ++ i) { + inA = m_mTree[nId].m_vInters[i] ; + if ( inA.nIn == -1) { + // numero di vertici aggiunti al nuovo poligono + int k = 0 ; + for ( Point3d ptInt : inA.vpt) { + plInLoop.AddUPoint( k, ptInt) ; + ++ k ; + } + plInLoop.Close(); + bool bAdded = false ; + // se il loop è CW devo controllare in quale altro dei poligoni che ho già aggiunto è contenuto + if ( ! inA.bCCW) { + Point3d ptStart ; + plInLoop.GetFirstPoint( ptStart) ; + int nOtherPoly = (int)vPolygons.size() ; + for ( int r = 0 ; r < nPoly ; ++r ) { + if ( IsPointInsidePolyLine( ptStart, vPolygons[nOtherPoly - r - 1][0], -0.01) && vnParentChunk[nPoly - r - 1] == inA.nChunk ) { + vPolygons[nOtherPoly - r - 1].push_back( plInLoop) ; + plInLoop.Clear() ; + vnParentChunk.push_back( inA.nChunk) ; + bAdded = true ; + break ; + } } } - } - if ( ! bAdded ) { - vCellPolygons.push_back( plInLoop) ; - vPolygons.push_back( vCellPolygons) ; - ++ nPoly ; - vnParentChunk.push_back( inA.nChunk) ; + if ( ! bAdded) { + vCellPolygons.push_back( plInLoop) ; + vPolygons.push_back( vCellPolygons) ; + ++ nPoly ; + vnParentChunk.push_back( inA.nChunk) ; + plInLoop.Clear() ; + vCellPolygons.clear() ; + } plInLoop.Clear() ; - vCellPolygons.clear() ; } - - plInLoop.Clear() ; - ++ n ; - inA = m_mTree[nId].m_vInters[n] ; + else + break ; } } return true ; @@ -2552,16 +2630,16 @@ Tree::CheckIfBefore( PolyLine& pl, int nEdge) const Point3d ptStart, ptEnd ; pl.GetFirstPoint( ptStart) ; pl.GetLastPoint( ptEnd) ; - if ( nEdge == 0 ) { + if ( AreSameEdge( nEdge, 0)) { return ptEnd.x > ptStart.x ; } - else if ( nEdge == 1 ) { + else if ( AreSameEdge( nEdge, 1) ) { return ptEnd.y > ptStart.y ; } - else if ( nEdge == 2 ) { + else if ( AreSameEdge( nEdge, 2) ) { return ptEnd.x < ptStart.x ; } - else if ( nEdge == 3 ) { + else if ( AreSameEdge( nEdge, 3) ) { return ptEnd.y < ptStart.y ; } return false ; @@ -2571,9 +2649,12 @@ Tree::CheckIfBefore( PolyLine& pl, int nEdge) const bool Tree::CheckIfBefore( Inters& inA) const { + // questa funzione è pensata in riferimento al lato 3, quindi nessuno dei due punti può stare su Edge = 3 // controllo se l'ingresso è prima dell'uscita int nEdge1 = inA.nIn ; int nEdge2 = inA.nOut ; + if ( nEdge1 == -1) + return false ; PolyLine pl ; pl.AddUPoint( 0, inA.vpt.back()) ; pl.AddUPoint( 1, inA.vpt[0]) ; @@ -2602,6 +2683,9 @@ Tree::CheckIfBefore( Inters& inA) const bool Tree::CheckIfBefore( int& nEdge1, Point3d& ptP1, int& nEdge2, Point3d& ptP2) const { + if ( nEdge1 == -1 || nEdge2 == -1) + return false ; + // questa funzione è pensata in riferimento al lato 3, quindi nessuno dei due punti può stare su Edge = 3 INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6} ; // controllo se ptP1, che è su nEdge1, viene prima di ptP2, che è su nEdge2. la partenza è da ptTR e l'arrivo è ptBr INTVECTOR :: iterator iter1 = find( vEdges.begin(), vEdges.end(), nEdge1) ; @@ -2630,16 +2714,16 @@ Tree::CheckIfBefore( int& nEdge, Point3d& ptP1, Point3d& ptP2) const { // sul lato nEdge controllo se ptP1 viene prima di ptP2. // i lati vengono percorsi in senso antiorario - if ( nEdge == 0 ) { + if ( AreSameEdge(nEdge, 0) ) { return ptP1.x > ptP2.x ; } - else if ( nEdge == 1 ) { + else if ( AreSameEdge(nEdge, 1) ) { return ptP1.y > ptP2.y ; } - else if ( nEdge == 2 ) { + else if ( AreSameEdge(nEdge, 2) ) { return ptP1.x < ptP2.x ; } - else if ( nEdge == 3 ) { + else if ( AreSameEdge(nEdge, 3) ) { return ptP1.y < ptP2.y ; } return false ; @@ -2655,25 +2739,25 @@ Tree::CheckIfAfter( PolyLine& pl, Point3d& ptNextStart, int nEdge) const // se i punti non sono sullo stesso lato ritorno false Point3d ptEnd ; pl.GetLastPoint( ptEnd) ; - if ( nEdge == 0 ) { + if ( AreSameEdge(nEdge, 0) ) { if ( ptNextStart.y > ptEnd.y - EPS_SMALL && ptNextStart.y < ptEnd.y + EPS_SMALL) return ptEnd.x > ptNextStart.x ; else return false ; } - else if ( nEdge == 1 ) { + else if ( AreSameEdge(nEdge, 1) ) { if ( ptNextStart.x > ptEnd.x - EPS_SMALL && ptNextStart.x < ptEnd.x + EPS_SMALL) return ptEnd.y > ptNextStart.y ; else return false ; } - else if ( nEdge == 2 ) { + else if ( AreSameEdge(nEdge, 2) ) { if ( ptNextStart.y > ptEnd.y - EPS_SMALL && ptNextStart.y < ptEnd.y + EPS_SMALL) return ptEnd.x < ptNextStart.x ; else return false ; } - else if ( nEdge == 3 ) { + else if ( AreSameEdge(nEdge, 3) ) { if ( ptNextStart.x > ptEnd.x - EPS_SMALL && ptNextStart.x < ptEnd.x + EPS_SMALL) return ptEnd.y < ptNextStart.y ; else @@ -2742,15 +2826,32 @@ Tree::AreSameEdge( int nEdge1, int nEdge2) const bool Tree::AddVertex( int nId, std::vector& vEdgeVertex, PolyLine& plTrimmedPoly, int& c, Point3d& ptToAdd) const { - Point3d ptBr( m_mTree.at(nId).GetTopRight().x , m_mTree.at(nId).GetBottomLeft().y) ; - Point3d ptTl( m_mTree.at(nId).GetBottomLeft().x , m_mTree.at(nId).GetTopRight().y) ; - Point3d ptBL = m_mTree.at(nId).GetBottomLeft() ; - Point3d ptTR = m_mTree.at(nId).GetTopRight() ; + //Point3d ptBr( m_mTree.at(nId).GetTopRight().x , m_mTree.at(nId).GetBottomLeft().y) ; + //Point3d ptTl( m_mTree.at(nId).GetBottomLeft().x , m_mTree.at(nId).GetTopRight().y) ; + //Point3d ptBL = m_mTree.at(nId).GetBottomLeft() ; + //Point3d ptTR = m_mTree.at(nId).GetTopRight() ; + Point3d ptBr = vEdgeVertex[3][0] ; + Point3d ptTR = vEdgeVertex[0][0] ; + Point3d ptTl = vEdgeVertex[1][0] ; + Point3d ptBL = vEdgeVertex[2][0] ; Point3d ptLast ; plTrimmedPoly.GetLastPoint( ptLast) ; // verifico di essere allineato con un lato, sennò aggiungo e basta Vector3d vDir = ptToAdd - ptLast ; - vDir.Normalize() ; + // se non riesco a normalizzare perché sono troppo vicino ad un vertice allora aggiungo direttamente il vertice + if ( ! vDir.Normalize()) { + plTrimmedPoly.EraseLastUPoint() ; + if ( AreSamePointApprox( ptToAdd, ptBr)) + plTrimmedPoly.AddUPoint( c, ptBr) ; + else if ( AreSamePointApprox( ptToAdd, ptTR)) + plTrimmedPoly.AddUPoint( c, ptTR) ; + else if ( AreSamePointApprox( ptToAdd, ptTl)) + plTrimmedPoly.AddUPoint( c, ptTl) ; + else if ( AreSamePointApprox( ptToAdd, ptBL)) + plTrimmedPoly.AddUPoint( c, ptBL) ; + ++ c ; + return true ; + } if ( abs( vDir.x) > 1 - EPS_SMALL || abs( vDir.y) > 1 - EPS_SMALL) { // se su un edge devo fare dei controlli // edge 0 @@ -2761,8 +2862,6 @@ Tree::AddVertex( int nId, std::vector& vEdgeVertex, PolyLine& plTrimm plTrimmedPoly.AddUPoint( c, ptIntermed) ; ++ c ; } - else - break ; } plTrimmedPoly.AddUPoint( c, ptToAdd) ; ++ c ; @@ -2775,8 +2874,6 @@ Tree::AddVertex( int nId, std::vector& vEdgeVertex, PolyLine& plTrimm plTrimmedPoly.AddUPoint( c, ptIntermed) ; ++ c ; } - else - break ; } plTrimmedPoly.AddUPoint( c, ptToAdd) ; ++ c ; @@ -2789,8 +2886,6 @@ Tree::AddVertex( int nId, std::vector& vEdgeVertex, PolyLine& plTrimm plTrimmedPoly.AddUPoint( c, ptIntermed) ; ++ c ; } - else - break ; } plTrimmedPoly.AddUPoint( c, ptToAdd) ; ++ c ; @@ -2803,8 +2898,6 @@ Tree::AddVertex( int nId, std::vector& vEdgeVertex, PolyLine& plTrimm plTrimmedPoly.AddUPoint( c, ptIntermed) ; ++ c ; } - else - break ; } plTrimmedPoly.AddUPoint( c, ptToAdd) ; ++ c ; @@ -2891,11 +2984,50 @@ Tree::AddVertex( int nId, std::vector& vEdgeVertex, PolyLine& plTrimm bool Tree::SetRightEdgeIn( int nId) { + // categorizzo la cella in base a quanta parte del lato destro è conenuta all'interno delle curve di trim + // RightEdgeIn -> 0 non contenuto ; 1 contenuto ; 2 in parte contenuto Point3d ptBr( m_mTree.at(nId).GetTopRight().x , m_mTree.at(nId).GetBottomLeft().y) ; Point3d ptTR = m_mTree.at(nId).GetTopRight() ; - // se ho inters sul lato destro allora in parte è dentro int nPass = (int) m_mTree[nId].m_vInters.size() ; bool bDone = false ; + // se ho solo loop interni devo controllare se il più esterno è CCW ( lato destro esterno) o CW ( lato destro interno) + if ( m_mTree[nId].m_nFlag == 2 ) { + bool bAllContained = true ; + bool bContained = false ; + Inters inA ; + int nInters = (int) m_mTree[nId].m_vInters.size() ; + for ( int n = 0 ; n < nInters ; ++ n) { + inA = m_mTree[nId].m_vInters[n] ; + if ( inA.nIn == -1) { + if ( ! inA.bCCW) { + bContained = false ; + Inters inB = m_mTree[nId].m_vInters[0] ; + for( int c = 0 ; c < nInters ; ++ c){ + inB = m_mTree[nId].m_vInters[c] ; + if ( inB.nIn == -1) { + if ( inB != inA && inB.nChunk == inA.nChunk) { + bContained = true ; + break ; + } + } + else + break ; + } + bAllContained = bAllContained && bContained ; + } + } + else + break ; + } + // se i loop CW interni sono tutti contenuti in un loop CW allora il right edge è esterno + bool bRightEdgeIn = ! bAllContained ; + if ( bRightEdgeIn) + m_mTree[nId].m_nRightEdgeIn = 1 ; + else + m_mTree[nId].m_nRightEdgeIn = 0 ; + return true ; + } + // se ho inters sul lato destro allora in parte è dentro for ( int k = 0 ; k < nPass ; ++ k) { if ( m_mTree[nId].m_vInters[k].nIn == 3 || m_mTree[nId].m_vInters[k].nOut == 3) { m_mTree[nId].m_nRightEdgeIn = 2 ; @@ -2925,20 +3057,34 @@ Tree::SetRightEdgeIn( int nId) // ciclo sulle inters e cerco quella più a destra, se ha un'uscita più bassa di un'entrata allora il right edge è compreso! bool bFound = false ; bool bRightMost = false ; - int nEdgeIn = 6, nEdgeOut = 7, nLoop ; - Point3d ptIn, ptOut ; - ptIn = ptOut = m_mTree[nId].GetBottomLeft() ; + int nEdgeUp = 6, nEdgeDown = 7, nLoop ; + Point3d ptDown( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; + Point3d ptUp = m_mTree[nId].GetTopRight() ; for ( int k = 0 ; k < nPass ; ++ k) { - // trovo il loop che ha l'ingresso o l'uscita più a destra - if ( CheckIfBefore( m_mTree[nId].m_vInters[k].nIn, m_mTree[nId].m_vInters[k].vpt[0], nEdgeIn, ptIn) || - CheckIfBefore( nEdgeOut, ptOut, m_mTree[nId].m_vInters[k].nOut, m_mTree[nId].m_vInters[k].vpt.back())) { - nLoop = k ; - nEdgeIn = m_mTree[nId].m_vInters[k].nIn ; - ptIn = m_mTree[nId].m_vInters[k].vpt[0] ; - nEdgeOut = m_mTree[nId].m_vInters[k].nOut ; - ptOut = m_mTree[nId].m_vInters[k].vpt.back() ; - bFound = true ; + if ( m_mTree[nId].m_vInters[k].nIn != -1) { + // trovo il loop che ha l'ingresso o l'uscita più a destra + if ( CheckIfBefore( m_mTree[nId].m_vInters[k].nIn, m_mTree[nId].m_vInters[k].vpt[0], nEdgeUp, ptUp) || + CheckIfBefore( m_mTree[nId].m_vInters[k].nOut, m_mTree[nId].m_vInters[k].vpt.back(), nEdgeUp, ptUp) || + CheckIfBefore( nEdgeDown, ptDown, m_mTree[nId].m_vInters[k].nIn, m_mTree[nId].m_vInters[k].vpt[0]) || + CheckIfBefore( nEdgeDown, ptDown, m_mTree[nId].m_vInters[k].nOut, m_mTree[nId].m_vInters[k].vpt.back())) { + nLoop = k ; + if ( CheckIfBefore( m_mTree[nId].m_vInters[k])) { + ptUp = m_mTree[nId].m_vInters[k].vpt[0] ; + nEdgeUp = m_mTree[nId].m_vInters[k].nIn ; + ptDown = m_mTree[nId].m_vInters[k].vpt.back() ; + nEdgeDown = m_mTree[nId].m_vInters[k].nOut ; + } + else { + ptUp = m_mTree[nId].m_vInters[k].vpt.back() ; + nEdgeUp = m_mTree[nId].m_vInters[k].nOut ; + ptDown = m_mTree[nId].m_vInters[k].vpt[0] ; + nEdgeDown = m_mTree[nId].m_vInters[k].nIn ; + } + bFound = true ; + } } + else + continue ; } if ( bFound && CheckIfBefore( m_mTree[nId].m_vInters[nLoop])) { bRightMost = true ; @@ -2948,7 +3094,6 @@ Tree::SetRightEdgeIn( int nId) m_mTree[nId].m_nRightEdgeIn = 1 ; else m_mTree[nId].m_nRightEdgeIn = 0 ; - } if ( m_mTree[nId].m_nRightEdgeIn != -1) @@ -2991,77 +3136,106 @@ Tree::CategorizeCell( int& nId) // guardando nFlag del vicino bottom, che è già categorizzato! else if ( m_mTree[vNeigh[0]].m_nRightEdgeIn == 2 ) { GetBottomNeigh( nId, vNeigh1) ; - int nNeigh = vNeigh1[0] ; - if ( m_mTree[nNeigh].m_nFlag == 0 || m_mTree[nNeigh].m_nFlag == 2) { - m_mTree[nId].m_nFlag = 0 ; - } - else if ( m_mTree[nNeigh].m_nFlag == 4) { - m_mTree[nId].m_nFlag = 4 ; - } - else if ( m_mTree[nNeigh].m_nFlag == 1 || m_mTree[nNeigh].m_nFlag == 3) { - if ( m_mTree[nNeigh].m_nRightEdgeIn == 0) + if ( (int) vNeigh1.size() > 0) { + int nNeigh = vNeigh1[0] ; + if ( m_mTree[nNeigh].m_nFlag == 0 || m_mTree[nNeigh].m_nFlag == 2) { m_mTree[nId].m_nFlag = 0 ; - else if ( m_mTree[nNeigh].m_nRightEdgeIn == 1) + } + else if ( m_mTree[nNeigh].m_nFlag == 4) { m_mTree[nId].m_nFlag = 4 ; - else if ( m_mTree[nNeigh].m_nRightEdgeIn == 2 ) { - // in questo caso devo verificare le intersezioni sul lato destro del vicino bottom - // scorro e cerco l'intersezione più alta, se è out la cella è dentro, se è in devo verificare l'out se è più a sinistra o a destra. - int nPass = (int) m_mTree[nNeigh].m_vInters.size() ; - bool bTopMost = false ; - bool bFound = false; - Point3d ptInters, ptBr( m_mTree[nNeigh].GetTopRight().x, m_mTree[nNeigh].GetBottomLeft().y) ; - ptInters = ptBr ; // inizializzato a vertice bottom right - int nEdgeIn = 3, nEdgeOut = 3, nLoop ; - for ( int r = 0 ; r < nPass; ++ r ) { - // trovo il loop che ha l'ingresso o l'uscita più in alto sul lato destro - // verifico che o l'ingresso o l'uscita siano sul lato destro e che sia l'intersezione più alta su quel lato - if ( m_mTree[nNeigh].m_vInters[r].nIn == 3 && ! CheckIfBefore( m_mTree[nNeigh].m_vInters[r].nIn, m_mTree[nNeigh].m_vInters[r].vpt[0], ptInters)) { - nLoop = r ; - ptInters = m_mTree[nNeigh].m_vInters[r].vpt[0] ; - bFound = true ; + } + else if ( m_mTree[nNeigh].m_nFlag == 1 || m_mTree[nNeigh].m_nFlag == 3) { + if ( m_mTree[nNeigh].m_nRightEdgeIn == 0) + m_mTree[nId].m_nFlag = 0 ; + else if ( m_mTree[nNeigh].m_nRightEdgeIn == 1) + m_mTree[nId].m_nFlag = 4 ; + else if ( m_mTree[nNeigh].m_nRightEdgeIn == 2 ) { + // in questo caso devo verificare le intersezioni sul lato destro del vicino bottom + // scorro e cerco l'intersezione più alta, se è out la cella è dentro, se è in devo verificare l'out se è più a sinistra o a destra. + int nPass = (int) m_mTree[nNeigh].m_vInters.size() ; + bool bTopMost = false ; + bool bFound = false; + Point3d ptInters, ptBr( m_mTree[nNeigh].GetTopRight().x, m_mTree[nNeigh].GetBottomLeft().y) ; + ptInters = ptBr ; // inizializzato a vertice bottom right + int nEdgeIn = 3, nEdgeOut = 3, nLoop ; + for ( int r = 0 ; r < nPass; ++ r ) { + // trovo il loop che ha l'ingresso o l'uscita più in alto sul lato destro + // verifico che o l'ingresso o l'uscita siano sul lato destro e che sia l'intersezione più alta su quel lato + if ( m_mTree[nNeigh].m_vInters[r].nIn == 3 && ! CheckIfBefore( m_mTree[nNeigh].m_vInters[r].nIn, m_mTree[nNeigh].m_vInters[r].vpt[0], ptInters)) { + nLoop = r ; + ptInters = m_mTree[nNeigh].m_vInters[r].vpt[0] ; + bFound = true ; + } + if ( m_mTree[nNeigh].m_vInters[r].nOut == 3 && ! CheckIfBefore( m_mTree[nNeigh].m_vInters[r].nOut, m_mTree[nNeigh].m_vInters[r].vpt.back(), ptInters)) { + nLoop = r ; + ptInters = m_mTree[nNeigh].m_vInters[r].vpt.back() ; + bFound = true ; + } + // controllo nei vertici + if ( m_mTree[nNeigh].m_vInters[r].nOut == 7 || m_mTree[nNeigh].m_vInters[r].nIn == 7) { + nLoop = r ; + ptInters = m_mTree[nNeigh].GetTopRight() ; + bFound = true ; + break ; + } + if ( m_mTree[nNeigh].m_vInters[r].nOut == 6 || m_mTree[nNeigh].m_vInters[r].nIn == 6 ) { + nLoop = r ; + ptInters = ptBr ; + bFound = true ; + } } - if ( m_mTree[nNeigh].m_vInters[r].nOut == 3 && ! CheckIfBefore( m_mTree[nNeigh].m_vInters[r].nOut, m_mTree[nNeigh].m_vInters[r].vpt.back(), ptInters)) { - nLoop = r ; - ptInters = m_mTree[nNeigh].m_vInters[r].vpt.back() ; - bFound = true ; + if ( bFound && CheckIfBefore( m_mTree[nNeigh].m_vInters[nLoop])) { + bTopMost = true ; } - // controllo nei vertici - if ( m_mTree[nNeigh].m_vInters[r].nOut == 7 || m_mTree[nNeigh].m_vInters[r].nIn == 7) { - nLoop = r ; - ptInters = m_mTree[nNeigh].GetTopRight() ; - bFound = true ; - break ; - } - if ( m_mTree[nNeigh].m_vInters[r].nOut == 6 || m_mTree[nNeigh].m_vInters[r].nIn == 6 ) { - nLoop = r ; - ptInters = ptBr ; - bFound = true ; - } - } - if ( bFound && CheckIfBefore( m_mTree[nNeigh].m_vInters[nLoop])) { - bTopMost = true ; - } - if ( bFound && bTopMost) { - if ( AreSameEdge(m_mTree[nNeigh].m_vInters[nLoop].nIn, 3) && AreSameEdge(m_mTree[nNeigh].m_vInters[nLoop].nOut, 3) ) { - if ( CheckIfBefore( m_mTree[nNeigh].m_vInters[nLoop])) + if ( bFound && bTopMost) { + if ( AreSameEdge(m_mTree[nNeigh].m_vInters[nLoop].nIn, 3) && AreSameEdge(m_mTree[nNeigh].m_vInters[nLoop].nOut, 3) ) { + if ( CheckIfBefore( m_mTree[nNeigh].m_vInters[nLoop])) + m_mTree[nId].m_nFlag = 4 ; + else + m_mTree[nId].m_nFlag = 0 ; + } + else if ( AreSameEdge(m_mTree[nNeigh].m_vInters[nLoop].nOut, 3)) m_mTree[nId].m_nFlag = 4 ; - else - m_mTree[nId].m_nFlag = 0 ; - } - else if ( AreSameEdge(m_mTree[nNeigh].m_vInters[nLoop].nOut, 3)) - m_mTree[nId].m_nFlag = 4 ; - else if ( AreSameEdge(m_mTree[nNeigh].m_vInters[nLoop].nIn, 3) ) { - // devo verificare se il l'uscita è più a sinistra o più a destra della cella - Point3d ptOut = m_mTree[nNeigh].m_vInters[nLoop].vpt.back() ; - Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; - if ( ptOut.x >= ptBr.x) - m_mTree[nId].m_nFlag = 4 ; - else - m_mTree[nId].m_nFlag = 0 ; + else if ( AreSameEdge(m_mTree[nNeigh].m_vInters[nLoop].nIn, 3) ) { + // devo verificare se l'uscita è più a sinistra o più a destra della cella + Point3d ptOut = m_mTree[nNeigh].m_vInters[nLoop].vpt.back() ; + Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; + if ( ptOut.x >= ptBr.x) + m_mTree[nId].m_nFlag = 4 ; + else + m_mTree[nId].m_nFlag = 0 ; + } } } } } + // se non ho vicini bottom devo per forza guardare il vicino a sinistra + else { + Point3d ptInters = m_mTree[vNeigh[0]].GetTopRight() ; + int nLoop ; + int nEdge = 3 ; + bool bIntersIn ; + for ( int k = 0 ; k < (int) m_mTree[vNeigh[0]].m_vInters.size() ; ++ k ) { + if ( AreSameEdge(m_mTree[vNeigh[0]].m_vInters[k].nIn, 3) ) { + if ( CheckIfBefore( nEdge, m_mTree[vNeigh[0]].m_vInters[k].vpt[0], ptInters)) { + ptInters = m_mTree[vNeigh[0]].m_vInters[k].vpt[0] ; + nLoop = k ; + bIntersIn = true ; + } + } + if ( AreSameEdge(m_mTree[vNeigh[0]].m_vInters[k].nOut, 3)) { + if ( CheckIfBefore( nEdge, m_mTree[vNeigh[0]].m_vInters[k].vpt.back(), ptInters) ) { + ptInters = m_mTree[vNeigh[0]].m_vInters[k].vpt.back() ; + nLoop = k ; + bIntersIn = false ; + } + } + } + if ( bIntersIn) + m_mTree[nId].m_nFlag = 4 ; + else + m_mTree[nId].m_nFlag = 0 ; + } } } else { @@ -3071,8 +3245,14 @@ Tree::CategorizeCell( int& nId) break ; } else if ( m_mTree[vNeigh[r]].m_nRightEdgeIn == 0) { - m_mTree[nId].m_nFlag = 0 ; - break ; + if ( m_mTree[vNeigh[r]].m_nFlag == 4) { + m_mTree[nId].m_nFlag = 4 ; + break ; + } + else if ( m_mTree[vNeigh[r]].m_nFlag == 0) { + m_mTree[nId].m_nFlag = 0 ; + break ; + } } } } @@ -3088,14 +3268,19 @@ Tree::CheckIfBetween( Inters& inA, Inters& inB) const // ( dall'end di A percorro i bordi della cella fino a tornare allo start e devo incontrare In e Out di B) INTVECTOR vEdges ; int nEdge = inA.nOut ; - while ( nEdge != inA.nIn || (int) vEdges.size() == 0) { + if ( nEdge > 3 && nEdge != 7) { + nEdge = nEdge - 4 ; + } + else if ( nEdge == 7) + nEdge = 0 ; + while ( ! AreSameEdge( nEdge, inA.nIn) || (int) vEdges.size() == 0) { vEdges.push_back( nEdge) ; if ( nEdge == 3) nEdge = 0 ; else ++ nEdge ; } - if ( inA.nIn != inA.nOut) + if ( ! AreSameEdge( inA.nIn, inA.nOut)) vEdges.push_back( nEdge) ; bool bFound = false ; for ( int i : vEdges) { @@ -3138,3 +3323,16 @@ Tree::CheckIfBetween( Inters& inA, Inters& inB) const } return bFound ; } + +//---------------------------------------------------------------------------- +bool +Tree::GetLeaves( std::vector& vLeaves) const +{ + vLeaves.clear() ; + for ( int k : m_vnLeaves) { + Cell cToAdd = m_mTree.at( k) ; + vLeaves.push_back( cToAdd) ; + } + + return true ; +} diff --git a/Tree.h b/Tree.h index 55b76f0..c1e71ba 100644 --- a/Tree.h +++ b/Tree.h @@ -36,6 +36,12 @@ struct Inters { ( bEqIn && nIn == 2 && vpt[0].x < b.vpt[0].x) || ( bEqIn && nIn == 3 && vpt[0].y < b.vpt[0].y) ; } + bool operator == ( Inters& b) { + return AreSamePointExact( vpt[0], b.vpt[0]) ; + } + bool operator != ( Inters& b){ + return ! AreSamePointExact( vpt[0], b.vpt[0]) ; + } } ; // 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 @@ -78,7 +84,7 @@ class Cell // 0 esterna, 1 intersecata, 2 contiene un loop, 3 intersecata e contenente un loop, 4 contenuta in un loop int m_nFlag2 ; // falg che indica se la cella è stata attraversata durante l'ultima fase del labelling int m_nRightEdgeIn ; // 0 right edge fuori, 1 right edge dentro, 2 metà e metà - INTVECTOR m_vnLoop ; // indice dei loop contenuti nella cella + //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 @@ -95,7 +101,7 @@ class Tree public : ~Tree( void) ; Tree( void) ; - Tree ( const SurfBezier* pSrfBz, bool bSplitPatches = false) ; + Tree ( const SurfBezier* pSrfBz, bool bSplitPatches = true) ; 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 @@ -103,7 +109,7 @@ public : 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 - + bool GetLeaves ( std::vector& vLeaves) const ; private : void Split( int nId, double dSplitValue) ; // funzione di split di una cella al parametro indicato nella direzione data da bVert