From 268983804e36af1605cd2aff27c45b5249e7061f Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 17 May 2023 08:46:33 +0200 Subject: [PATCH] EgtGeomKernel : - gestite le superfici bilineari singole e multipatch - gestite le superfici chiuse o su un parametro o sull'altro - migliorate le prestazioni. Da aggiungere : - split preliminare delle patches - la gestione delle sup. trimmate --- SurfBezier.cpp | 270 ++++++++---------- SurfBezier.h | 1 + Tree.cpp | 730 ++++++++++++++++++++++++++++++------------------- Tree.h | 46 ++-- 4 files changed, 583 insertions(+), 464 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index a5f7245..054b366 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -148,6 +148,13 @@ SurfBezier::SetTrimRegion( const ISurfFlatRegion& sfrTrimReg) return true ; } +//---------------------------------------------------------------------------- +bool +SurfBezier::GetTrimRegion( ISurfFlatRegion& sfrTrimReg) +{ + return true ; +} + //---------------------------------------------------------------------------- bool SurfBezier::GetInfo( int& nDegU, int& nDegV, int& nSpanU, int& nSpanV, bool& bIsRat, bool& bTrimmed) const @@ -1464,172 +1471,111 @@ SurfBezier::GetAuxSurf( void) const // se già calcolata, la restituisco if ( m_pSTM != nullptr) return m_pSTM ; - // definisco il numero degli step in U e in V - double dMaxLenU = 0 ; - for ( int j = 0 ; j <= m_nDegV * m_nSpanV ; ++ j) - dMaxLenU = max( dMaxLenU, GetCurveOnUApproxLen( double( j) / m_nDegV)) ; - int nStepU = GetSteps( m_nDegU, m_nSpanU, dMaxLenU, 2) ; - double dMaxLenV = 0 ; - for ( int i = 0 ; i <= m_nDegU * m_nSpanU ; ++ i) - dMaxLenV = max( dMaxLenV, GetCurveOnVApproxLen( double( i) / m_nDegU)) ; - int nStepV = GetSteps( m_nDegV, m_nSpanV, dMaxLenV, 2) ; - if ( m_nDegU == 1 && m_nDegV == 1) { + //// definisco il numero degli step in U e in V + // double dMaxLenU = 0 ; + // for ( int j = 0 ; j <= m_nDegV * m_nSpanV ; ++ j) + // dMaxLenU = max( dMaxLenU, GetCurveOnUApproxLen( double( j) / m_nDegV)) ; + // int nStepU = GetSteps( m_nDegU, m_nSpanU, dMaxLenU, 2) ; + // double dMaxLenV = 0 ; + // for ( int i = 0 ; i <= m_nDegU * m_nSpanU ; ++ i) + // dMaxLenV = max( dMaxLenV, GetCurveOnVApproxLen( double( i) / m_nDegU)) ; + // int nStepV = GetSteps( m_nDegV, m_nSpanV, dMaxLenV, 2) ; + // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // if ( m_nDegU == 1 && m_nDegV == 1) { + // // costruttore della superficie + // StmFromTriangleSoup stmSoup ; + // if ( ! stmSoup.Start()) + // return nullptr ; + // // prima curva isoparametrica (potrebbe essere un solo punto) + // PolyLine PL1 ; + // GetCurveOnU( 0, nStepU, PL1) ; + // bool bSingle1 = ( PL1.GetPointNbr() == 1) ; + // // ciclo sulle isoparametriche + // for ( int i = 1 ; i <= nStepV ; ++ i) { + // // seconda curva isoparametrica (con tanti punti quanti la prima, oppure uno solo) + // double dV = double( i) * m_nSpanV / nStepV ; + // PolyLine PL2 ; + // GetCurveOnU( dV, nStepU, PL2) ; + // bool bSingle2 = ( PL2.GetPointNbr() == 1) ; + // // inserisco i triangoli della striscia nel costruttore della TriMesh + // Point3d ptP1c, ptP2c ; + // Point3d ptP1n, ptP2n ; + // bool bNext = PL1.GetFirstPoint( ptP1c) && PL2.GetFirstPoint( ptP2c) ; + // if ( bNext) { + // if ( bSingle1 && bSingle2) + // bNext = false ; + // if ( bSingle1) + // ptP1n = ptP1c ; + // else + // bNext = bNext && PL1.GetNextPoint( ptP1n) ; + // if ( bSingle2) + // ptP2n = ptP2c ; + // else + // bNext = bNext && PL2.GetNextPoint( ptP2n) ; + // } + // while ( bNext) { + // // eventuale primo triangolo (con base sui correnti e vertice su P2 successivo) + // if ( ! AreSamePointApprox( ptP1c, ptP2c)) + // stmSoup.AddTriangle( ptP2c, ptP1c, ptP2n) ; + // // eventuale secondo triangolo (con vertice su P1 corrente e base sui successivi) + // if ( ! AreSamePointApprox( ptP1n, ptP2n)) + // stmSoup.AddTriangle( ptP1c, ptP1n, ptP2n) ; + // // passo alla successiva coppia + // ptP1c = ptP1n ; + // ptP2c = ptP2n ; + // bNext = ( bSingle1 || PL1.GetNextPoint( ptP1n)) && ( bSingle2 || PL2.GetNextPoint( ptP2n)) ; + // } + // // salvo isoparametrica PL2 in PL1 + // PL1.GetUPointList().swap( PL2.GetUPointList()) ; + // bSingle1 = bSingle2 ; + // } + // // la completo + // if ( ! stmSoup.End()) + // return nullptr ; + // // la salvo + // m_pSTM = GetBasicSurfTriMesh( stmSoup.GetSurf()) ; + // } + // else { + + // costruttore della superficie - StmFromTriangleSoup stmSoup ; - if ( ! stmSoup.Start()) + Tree Tree( this) ; + Tree.BuildTree() ; + POLYLINEVECTOR vPL ; + Tree.GetPolygons( vPL) ; + 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) { + PNTVECTOR vPnt ; + INTVECTOR vTria ; + Triangulate Tri ; + if ( ! Tri.Make( i, vPnt, vTria)) return nullptr ; - // prima curva isoparametrica (potrebbe essere un solo punto) - PolyLine PL1 ; - GetCurveOnU( 0, nStepU, PL1) ; - bool bSingle1 = ( PL1.GetPointNbr() == 1) ; - // ciclo sulle isoparametriche - for ( int i = 1 ; i <= nStepV ; ++ i) { - // seconda curva isoparametrica (con tanti punti quanti la prima, oppure uno solo) - double dV = double( i) * m_nSpanV / nStepV ; - PolyLine PL2 ; - GetCurveOnU( dV, nStepU, PL2) ; - bool bSingle2 = ( PL2.GetPointNbr() == 1) ; - // inserisco i triangoli della striscia nel costruttore della TriMesh - Point3d ptP1c, ptP2c ; - Point3d ptP1n, ptP2n ; - bool bNext = PL1.GetFirstPoint( ptP1c) && PL2.GetFirstPoint( ptP2c) ; - if ( bNext) { - if ( bSingle1 && bSingle2) - bNext = false ; - if ( bSingle1) - ptP1n = ptP1c ; - else - bNext = bNext && PL1.GetNextPoint( ptP1n) ; - if ( bSingle2) - ptP2n = ptP2c ; - else - bNext = bNext && PL2.GetNextPoint( ptP2n) ; - } - while ( bNext) { - // eventuale primo triangolo (con base sui correnti e vertice su P2 successivo) - if ( ! AreSamePointApprox( ptP1c, ptP2c)) - stmSoup.AddTriangle( ptP2c, ptP1c, ptP2n) ; - // eventuale secondo triangolo (con vertice su P1 corrente e base sui successivi) - if ( ! AreSamePointApprox( ptP1n, ptP2n)) - stmSoup.AddTriangle( ptP1c, ptP1n, ptP2n) ; - // passo alla successiva coppia - ptP1c = ptP1n ; - ptP2c = ptP2n ; - bNext = ( bSingle1 || PL1.GetNextPoint( ptP1n)) && ( bSingle2 || PL2.GetNextPoint( ptP2n)) ; - } - // salvo isoparametrica PL2 in PL1 - PL1.GetUPointList().swap( PL2.GetUPointList()) ; - bSingle1 = bSingle2 ; + + // porto i punti in 3d + 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)) + return nullptr ; + vPnt3d.push_back( pt3d) ; } - // la completo - if ( ! stmSoup.End()) - return nullptr ; - // la salvo - m_pSTM = GetBasicSurfTriMesh( stmSoup.GetSurf()) ; - } - else { - // costruttore della superficie - Tree Tree( this) ; - Tree.BuildTree() ; - POLYLINEVECTOR vPL ; - Tree.GetPolygons( vPL) ; - PtrOwner pSrfTm( CreateBasicSurfTriMesh()) ; - StmFromTriangleSoup stmSoup ; - if ( ! stmSoup.Start()) - return nullptr ; + int nTria = int( vTria.size()) / 3 ; + for ( int i = 0 ; i < nTria ; ++i) { + if ( ! stmSoup.AddTriangle( vPnt3d[vTria[3*i]], vPnt3d[vTria[3*i+1]], vPnt3d[vTria[3*i+2]])) + return nullptr ; + } + } - // prendo i punti di ogni polyline dell'albero, li triangolo e li porto in 3d - for ( PolyLine i : vPL) { - PNTVECTOR vPnt ; - INTVECTOR vTria ; - Triangulate Tri ; - if ( ! Tri.Make( i, vPnt, vTria)) - return false ; - - // porto i punti in 3d - 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)) - return false ; - vPnt3d.push_back( pt3d) ; - } - int nTria = int( vTria.size()) / 3 ; - for ( int i = 0 ; i < nTria ; ++i) { - if ( ! stmSoup.AddTriangle( vPnt3d[vTria[3*i]], vPnt3d[vTria[3*i+1]], vPnt3d[vTria[3*i+2]])) - return false ; - } - - - // if ( pSrfTm->GetVertexCount() == 0) { - // // inizializzo la superficie - // int nVert = int( vPnt.size()) ; - // int nTria = int( vTria.size()) / 3 ; - // if ( ! pSrfTm->Init( nVert, nTria)) - // return false ; - - // // porti i vertici dallo spazio parametrico allo spazio 3d e li inserisco nella superficie - // for ( int i = 0 ; i < int( vPnt.size()) ; ++ i) { - // Point3d pt3d; - // GetPointD1D2( vPnt[i].x, vPnt[i].y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; - // if ( pSrfTm->AddVertex( pt3d) == SVT_NULL) - // //if ( srfTmCell->AddVertex( vPnt[i]) == SVT_NULL ) - // return false ; - // } - - // // recupero i triangoli e li inserisco nella superficie - // int vV[3] ; - // for ( int i = 0 ; i < nTria ; ++i) { - // vV[0] = vTria[3*i] ; - // vV[1] = vTria[3*i+1] ; - // vV[2] = vTria[3*i+2] ; - // if ( pSrfTm->AddTriangle( vV) == SVT_NULL) - // return false ; - // } - - // // sistemo la topologia - // if ( ! pSrfTm->AdjustTopology()) - // return false ; - - // //pSrfTm.Set( Release(srfTmCell)) ; - // } - // else { - // // inizializzo la superficie - // int nVert = int( vPnt.size()) ; - // int nTria = int( vTria.size()) / 3 ; - - // // porti i vertici dallo spazio parametrico allo spazio 3d e li inserisco nella superficie - // for ( int i = 0 ; i < int( vPnt.size()) ; ++ i) { - // Point3d pt3d; - // GetPointD1D2( vPnt[i].x, vPnt[i].y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; - // if ( pSrfTm->AddVertex( pt3d) == SVT_NULL) - // return false ; - // } - - // // recupero i triangoli e li inserisco nella superficie - // int vV[3] ; - // int nVertCount = int ( pSrfTm->GetVertexCount()) - 4 ; - // for ( int i = 0 ; i < nTria ; ++i) { - // vV[0] = vTria[3*i] + nVertCount ; - // vV[1] = vTria[3*i+1] + nVertCount ; - // vV[2] = vTria[3*i+2] + nVertCount ; - // if ( pSrfTm->AddTriangle( vV) == SVT_NULL) - // return false ; - // } - // } - } - // if ( ! pSrfTm->AdjustTopology()) - // return false ; - //// la salvo - // m_pSTM = Release( pSrfTm) ; - - - - // la salvo - if ( ! stmSoup.End()) - return nullptr ; - m_pSTM = GetBasicSurfTriMesh( stmSoup.GetSurf()) ; - } + // la salvo + if ( ! stmSoup.End()) + return nullptr ; + m_pSTM = GetBasicSurfTriMesh( stmSoup.GetSurf()) ; + //} //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// return m_pSTM ; } diff --git a/SurfBezier.h b/SurfBezier.h index b5366e9..12149f8 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -83,6 +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 ; 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 5304f3f..9d672ab 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -25,8 +25,8 @@ using namespace std ; //---------------------------------------------------------------------------- Cell::Cell( void) - : m_nId( -1), m_ptPbl( ORIG), m_bProcessed ( false) , m_bSplitVert ( true) , 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_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) { Point3d ptTr ( 1, 1) ; m_ptPtr = ptTr ; @@ -35,8 +35,8 @@ Cell::Cell( void) //---------------------------------------------------------------------------- Cell::Cell( Point3d ptBL, Point3d ptTR) - : m_nId( -1), m_ptPbl( ptBL), m_ptPtr(ptTR), m_bProcessed ( false) , m_bSplitVert ( true) , 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_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) {} @@ -47,21 +47,17 @@ Cell::~Cell( void) //---------------------------------------------------------------------------- inline bool -Cell::IsSame( Cell cOtherCell) +Cell::IsSame( Cell cOtherCell) const { - if ( AreSamePointXYApprox( m_ptPbl, cOtherCell.GetBottomLeft()) && - AreSamePointXYApprox( m_ptPtr, cOtherCell.GetTopRight())) { + if ( m_nId == cOtherCell.m_nId) return true ; - } - else { + else return false ; - } } //---------------------------------------------------------------------------- bool -//Cell::IsLeaf ( void) const -Cell::IsLeaf ( void) +Cell::IsLeaf ( void) const { if( m_nChild1 == -2 && m_nChild2 == -2) return true ; @@ -71,25 +67,18 @@ Cell::IsLeaf ( void) //---------------------------------------------------------------------------- Tree::Tree( void) - : m_dLinTol(LIN_TOL_FINE), m_pSrfBz(nullptr), m_nRoot( -1), m_bTrimmed( false) + : m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosed( false) { Point3d ptBl( 0, 0), ptTr ( 1, 1) ; Cell cRoot( ptBl, ptTr) ; - m_mTree.insert( pair< int, Cell>( m_nRoot, cRoot)) ; + m_mTree.insert( pair< int, Cell>( -1, cRoot)) ; } //---------------------------------------------------------------------------- -Tree::Tree( const SurfBezier* pSrfBz) - : m_dLinTol( LIN_TOL_FINE), m_pSrfBz ( pSrfBz), m_nRoot( -1) +Tree::Tree( const SurfBezier* pSrfBz, bool bSplitPatches) + : m_bBilinear( false), m_bMulti( false), m_bClosed( false) { - // le coordinate delle celle sono nello spazio parametrico - int nDegU, nDegV, nSpanU, nSpanV ; - bool bIsRat, bTrimmed ; - m_pSrfBz->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bIsRat, bTrimmed) ; - m_bTrimmed = bTrimmed ; - Point3d ptTop( nSpanU, nSpanV) ; - Cell cRoot( ORIG, ptTop) ; - m_mTree.insert( pair< int, Cell>( m_nRoot, cRoot)) ; + SetSurf( pSrfBz, bSplitPatches) ; } //---------------------------------------------------------------------------- @@ -98,23 +87,83 @@ Tree::~Tree( void) } //---------------------------------------------------------------------------- -void Tree::SetSurf( const SurfBezier* pSrfBz) +void Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches) { m_pSrfBz = pSrfBz ; - // le coordinate delle celle sono nello spazio parametrico + // le coordinate delle celle sono nello spazio parametrico int nDegU, nDegV, nSpanU, nSpanV ; bool bIsRat, bTrimmed ; m_pSrfBz->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bIsRat, bTrimmed) ; m_bTrimmed = bTrimmed ; + if ( nDegU == 1 && nDegV == 1) + m_bBilinear = true ; + if ( nSpanU * nSpanV != 1) + m_bMulti = true ; + if ( bSplitPatches) { + int nId = -1 ; + for ( int i = 1 ; i < nSpanU ; ++i ) { + m_mTree[nId].SetSplitDirVert( true) ; + Split( nId, i) ; + } + for ( int j = 1 ; j < nSpanV ; ++j ) { + + } + + // split preliminari per dividere le patch in modo da triangolarle indipendentemente//////////////////////////////////////////////////////// + // devo sistemare le adiacenze // queste si sistemano da sole con lo split + + // così creo dei child1 da cui devo ripassare per processarle, ma nel mio algoritmo non è previto!!!!!!!!!!!!!!!!! + } + // salvo i vertici 3d della cella root Point3d ptTop( nSpanU, nSpanV) ; Cell cRoot( ORIG, ptTop) ; m_mTree.insert( pair< int, Cell>( -1, cRoot)) ; + Point3d ptP00, ptP10, ptP11, ptP01 ; + bool bOk = false ; + PNTVECTOR vVert ; + ptP00 = m_pSrfBz->GetControlPoint( 0, &bOk); + vVert.push_back( ptP00) ; + ptP10 = m_pSrfBz->GetControlPoint( nDegU * nSpanU, &bOk) ; + vVert.push_back( ptP10) ; + ptP11 = m_pSrfBz->GetControlPoint( ( nDegU * nSpanU + 1) * ( nDegV * nSpanV + 1) - 1, &bOk) ; + vVert.push_back( ptP11) ; + ptP01 = m_pSrfBz->GetControlPoint( ( nDegU * nSpanU + 1 ) * ( nDegV * nSpanV), &bOk) ; + vVert.push_back( ptP01) ; + m_mVert.insert( pair( -1, vVert)) ; + // verifico se la superficie è chiusa ed eventualmente sistemo le adiacenze + if ( ( AreSamePointApprox(ptP00, ptP01) && AreSamePointApprox(ptP10, ptP11) ) || + ( AreSamePointApprox(ptP00, ptP10) && AreSamePointApprox(ptP01, ptP11) ) ) { + m_bClosed = true ; + // devo gestire se passo da entrambi questi if/////////////////////////////////////////////////////////////////////////////////////////////////////////// + if ( AreSamePointApprox(ptP00, ptP01)) { + m_mTree[-1].m_nTop = -1 ; + m_mTree[-1].m_nBottom = -1 ; + m_mTree[-1].SetSplitDirVert( false) ; + Split(-1) ; + } + if (AreSamePointApprox(ptP00, ptP10)) { + m_mTree[-1].m_nLeft = -1 ; + m_mTree[-1].m_nRight = -1 ; + m_mTree[-1].SetSplitDirVert( true) ; + Split( -1) ; + } + } + // calcolo e salvo la distanza reale tra i vertici della cella root + double dLen0 = Dist( ptP00, ptP10) ; + double dLen1 = Dist( ptP10, ptP11) ; + double dLen2 = Dist( ptP01, ptP11) ; + double dLen3 = Dist( ptP00, ptP01) ; + m_vDim.push_back( ( dLen0 != 0 ? dLen0 : 1)) ; + m_vDim.push_back( ( dLen1 != 0 ? dLen1 : 1)) ; + m_vDim.push_back( ( dLen2 != 0 ? dLen2 : 1)) ; + m_vDim.push_back( ( dLen3 != 0 ? dLen3 : 1)) ; } //---------------------------------------------------------------------------- void -Tree::Split( int nId) +Tree::Split( int nId, double dSplitValue) { + // per lo split a parametro libero devo impedire che si facciano split troppo vicini al bordo!!!!!!!!!!!!!!!!!!! Cell cChild1, cChild2 ; cChild1.m_nDepth = m_mTree[nId].m_nDepth + 1 ; cChild2.m_nDepth = m_mTree[nId].m_nDepth + 1 ; @@ -125,6 +174,10 @@ Tree::Split( int nId) m_mTree[nId].m_nChild2 = nNodes ; m_mTree.insert( pair( nNodes - 1, cChild1)) ; m_mTree.insert( pair( nNodes, cChild2)) ; + Point3d ptVert1, ptVert2 ; + PNTVECTOR vVert ; + m_mVert.insert( pair( nNodes - 1, vVert)) ; + m_mVert.insert( pair( nNodes, vVert)) ; if ( ! m_mTree[nId].IsSplitVert()) { // la cella figlio 1 è quella sopra @@ -142,6 +195,19 @@ Tree::Split( int nId) m_mTree[m_mTree[nId].m_nChild2].m_nBottom = m_mTree[nId].m_nBottom ; m_mTree[m_mTree[nId].m_nChild2].m_nLeft = m_mTree[nId].m_nLeft ; 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 + //double dV = ( 1 - dSplitValue) * m_mTree[nId].GetBottomLeft().y + dSplitValue * m_mTree[nId].GetTopRight().y ; + 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_mVert[nNodes - 1].push_back( ptVert1) ; + m_mVert[nNodes - 1].push_back( ptVert2) ; + m_mVert[nNodes - 1].push_back( m_mVert[nId][2]) ; + m_mVert[nNodes - 1].push_back( m_mVert[nId][3]) ; + m_mVert[nNodes].push_back( m_mVert[nId][0]) ; + m_mVert[nNodes].push_back( m_mVert[nId][1]) ; + m_mVert[nNodes].push_back( ptVert2) ; + m_mVert[nNodes].push_back( ptVert1) ; } else { // la cella figlio 1 è quella di sinistra @@ -159,253 +225,359 @@ Tree::Split( int nId) m_mTree[m_mTree[nId].m_nChild2].m_nBottom = m_mTree[nId].m_nBottom ; m_mTree[m_mTree[nId].m_nChild2].m_nLeft = m_mTree[nId].m_nChild1 ; 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 + //double dU = ( m_mTree[nId].GetBottomLeft().x + m_mTree[nId].GetTopRight().x) / 2 ; + 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_mVert[nNodes - 1].push_back( m_mVert[nId][0]) ; + m_mVert[nNodes - 1].push_back( ptVert2) ; + m_mVert[nNodes - 1].push_back( ptVert1) ; + m_mVert[nNodes - 1].push_back( m_mVert[nId][3]) ; + m_mVert[nNodes].push_back( ptVert2) ; + m_mVert[nNodes].push_back( m_mVert[nId][1]) ; + m_mVert[nNodes].push_back( m_mVert[nId][2]) ; + m_mVert[nNodes].push_back( ptVert1) ; } m_mTree[m_mTree[nId].m_nChild1].SetParent( nId) ; m_mTree[m_mTree[nId].m_nChild2].SetParent( nId) ; - //m_bProcessed = true ; } -////---------------------------------------------------------------------------- -//bool Tree::BuildTree(void) -//{ -// // di default SplitVert è true ! -// int ToSplit = -1; -// m_mTree[ToSplit].SetSplitDirVert( true) ; -// Split( ToSplit) ; -// // celle 2 e 3 -// ToSplit = m_mTree[-1].m_nChild1 ; -// m_mTree[ToSplit].SetSplitDirVert( false) ; -// Split( ToSplit) ; -// // celle 4 e 5 -// ToSplit = m_mTree[ToSplit].m_nChild1 ; -// m_mTree[ToSplit].SetSplitDirVert( true) ; -// Split( ToSplit) ; -// // celle 6 e 7 -// ToSplit = m_mTree[ToSplit].m_nChild2 ; -// m_mTree[ToSplit].SetSplitDirVert( false) ; -// Split( ToSplit) ; -// // celle 8 e 9 -// ToSplit = m_mTree[ToSplit].m_nChild2 ; -// m_mTree[ToSplit].SetSplitDirVert( true) ; -// Split( ToSplit) ; -// // celle 10 e 11 -// ToSplit = m_mTree[ToSplit].m_nChild1 ; -// m_mTree[ToSplit].SetSplitDirVert( false) ; -// Split( ToSplit) ; -// // celle 12 e 13 -// ToSplit = m_mTree[ToSplit].m_nParent ; -// ToSplit = m_mTree[ToSplit].m_nChild2 ; -// m_mTree[ToSplit].SetSplitDirVert( true) ; -// Split( ToSplit) ; -// INTVECTOR vTops, vBottoms, vLefts, vRights , vLeaves1, vLeaves2, vLeaves; -// int d1, d2 , H1 ; -// GetTopNeigh( 3, vTops) ; -// GetBottomNeigh( 6, vBottoms) ; -// GetLeftNeigh( 1, vLefts) ; -// GetRightNeigh( 4, vRights ) ; -// d1 = GetHeightLeaves( 7, vLeaves1) ; -// d2 = GetHeightLeaves( 5, vLeaves2) ; -// H1 = GetHeightLeaves( -1, vLeaves) ; -// m_vnLeaves = vLeaves ; -// int i = 0 ; -// -// return true ; -//} - -////---------------------------------------------------------------------------- -//bool Tree::BuildTree( void) -//{ -// int ToSplit = -1 ; -// m_mTree[ToSplit].SetSplitDirVert( true) ; -// Split( ToSplit) ; -// // celle 2 e 3 -// ToSplit = m_mTree[-1].m_nChild1 ; -// m_mTree[ToSplit].SetSplitDirVert( false) ; -// Split( ToSplit) ; -// -// return true ; -//} +//---------------------------------------------------------------------------- +void +Tree::Split( int nId) +{ + double dValue ; + if ( m_mTree[nId].IsSplitVert()) + dValue = ( m_mTree[nId].GetBottomLeft().x + m_mTree[nId].GetTopRight().x) / 2 ; + else + dValue = ( m_mTree[nId].GetBottomLeft().y + m_mTree[nId].GetTopRight().y) / 2 ; + Split( nId, dValue) ; +} //---------------------------------------------------------------------------- -bool Tree::BuildTree( double dLinTol, double dSideMax) +bool Tree::BuildTree( double dLinTol_, double dSideMin, double dSideMax) { - // trovo dove splittare la cella e creo i puntatori ai figli - - // comincio a suddividere la superficie usando un kd-tree - // approssimo con una bilineare e se l'errore di approssimazione è troppo grande cerco una direzione - // in cui dividere la superficie - - double dErr ; // errore calcolato - double dDist; // distanza tra punti selezionati sulla isoparametrica - double dSideMinVal, dSideMaxVal ; // lunghezza del lato della eventuale cella figlio - double dSplit = 0.5 ; // effettuo sempre split a metà - double dSideMin = 0.05 ; // lunghezza minima del lato di una cella - //double dSidemin = 0.1 ; // lunghezza minima del lato di una cella - //m_dLinTol = dLinTol ; - m_dLinTol = 0.2 ; - int nSteps = 51 ; // numero di Step mentre scorro lungo un'isoparametrica - double dU, dV , dULoc, dVLoc ; - //double dIter, dIterLoc ; - bool bVert ; - Point3d ptBz, ptBl ; - // cerco lo scostamento massimo tra la sup di Bezier e la sua approssimazione bilineare + // suddivido lo spazio parametrico con divisioni a metà su uno dei due parametri INTVECTOR vBalanceCheck ; int nCToSplit = -1 ; + // se ho già fatto degli split preliminari parto dal primo child anziché dal root + if ( (int) m_mTree.size() > 1) + nCToSplit = 0 ; + double dLinTol = 0.2 ; + //double dSideMin = 1 ; + if ( ! m_bTrimmed) { + if ( ! m_bBilinear) { + while ( nCToSplit != -2 && m_mTree[nCToSplit].IsProcessed() == false) { + // calcolo in quale direzione ho più curvatura + // ptP00P10 è un punto tra P00 e P10 + 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 ; + // per lo split scelgo la direzione che è più vicina alla superficie originale nel punto di maggior distanza + // misura approssimativa della curvatura in una direzione + double dCurvV = Dist(ptV, ptPSrf) ; + double dCurvU = Dist(ptU, ptPSrf) ; + 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 ; + } + 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 + double dErr = 0 ; + 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]) ; + double dDimV = ( dLen1 >= dLen3 ? dLen1 / m_vDim[1] : dLen3 / m_vDim[3]) ; + // 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 ; ++ u) { + dU = double ( u) / double ( nStepsU - 1) ; + 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) { + dV = double ( v) / double ( nStepsV - 1) ; + 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 > dErr) + dErr = dDist ; + } + } + } - int c = 1 ; - while ( nCToSplit != -2 && m_mTree[nCToSplit].IsProcessed() == false) { - dErr = 0 ; - // calcolo l'errore di approssimazione + if ( dErr > dLinTol || dSideMaxVal > dSideMax) { + m_mTree[nCToSplit].SetSplitDirVert( bVert) ; + // effettuo lo split + Split( nCToSplit) ; - //// calcolo l'errore di approssimazione confrontando con la bilineare corrispondente - //SurfBezier pSrfBl ; - //pSrfBl.Init(1, 1, 1, 1, false) ; - //m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x, m_mTree[nCToSplit].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz) ; - //pSrfBl.SetControlPoint( 0, ptBz) ; // P00 - //m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x, m_mTree[nCToSplit].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz) ; - //pSrfBl.SetControlPoint( 1, ptBz) ; // P10 - //m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz) ; - //pSrfBl.SetControlPoint( 2, ptBz) ; // P01 - //m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz) ; - //pSrfBl.SetControlPoint( 3, ptBz) ; // P11 - //// scorro lungo le isoparametriche a questi valori di U e V per trovare dov'è il punto di maggior discostamento - //dU = ( m_mTree[nCToSplit].GetTopRight().x + m_mTree[nCToSplit].GetBottomLeft().x) / 2 ; - //dV = ( m_mTree[nCToSplit].GetTopRight().y + m_mTree[nCToSplit].GetBottomLeft().y) / 2 ; - //dULoc = ( dU - m_mTree[nCToSplit].GetBottomLeft().x) / ( m_mTree[nCToSplit].GetTopRight().x - m_mTree[nCToSplit].GetBottomLeft().x) ; - //dVLoc = ( dV - m_mTree[nCToSplit].GetBottomLeft().y) / ( m_mTree[nCToSplit].GetTopRight().y - m_mTree[nCToSplit].GetBottomLeft().y) ; - //double dErrUmax = 0, dErrVmax = 0 ; - //for ( int i = 0 ; i < nSteps ; ++ i){ - // dIter = double ( i) / double ( nSteps - 1) ; - // dIterLoc = ( 1 - dIter) * m_mTree[nCToSplit].GetBottomLeft().y + dIter * m_mTree[nCToSplit].GetTopRight().y ; - // if ( ! m_pSrfBz->GetPointD1D2( dU, dIterLoc, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz) || - // ! pSrfBl.GetPointD1D2( dULoc, dIter, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBl)) - // return false ; - // dDist = Dist( ptBz, ptBl) ; - // dErrVmax = max ( dErrVmax, dDist) ; - // if ( dDist > dErr) { - // dErr = dDist ; - // //bVert = true ; - // } - // dIterLoc = ( 1 - dIter) * m_mTree[nCToSplit].GetBottomLeft().x + dIter * m_mTree[nCToSplit].GetTopRight().x ; - // if ( ! m_pSrfBz->GetPointD1D2( dIterLoc, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz) || - // ! pSrfBl.GetPointD1D2( dIter, dVLoc, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBl)) - // return false ; - // dDist = Dist( ptBz, ptBl) ; - // dErrUmax = max ( dErrUmax, dDist) ; - // if ( dDist > dErr) { - // dErr = dDist ; - // //bVert = false ; - // } - //} - - Point3d ptP00, ptP10, ptP11, ptP01 ; - m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x, m_mTree[nCToSplit].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00) ; - m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x, m_mTree[nCToSplit].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10) ; - m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01) ; - m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11) ; - CurveLine cl0010, cl0001, cl1011, cl0111 ; - // U=0 - cl0010.Set( ptP00, ptP10) ; - //// V=0 - //cl0001.Set( ptP00, ptP01) ; - // U=1 - cl0111.Set( ptP01, ptP11) ; - //// V=1 - //cl0111.Set( ptP01, ptP11) ; - Point3d pt0010, pt0111, ptBz0, ptBz1, ptBzV ; - int nFlag ; - CurveLine clV ; - for ( int u = 0 ; u < nSteps ; ++ u){ - dU = double ( u) / double ( nSteps - 1) ; - 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 < nSteps ; ++ v){ - dV = double ( v) / double ( nSteps - 1) ; - 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) ; - dpc.GetDist( dDist) ; - if ( dDist > dErr) - dErr = dDist ; - } - } - - // calcolo in quale direzione ho più curvatura - // devo trovare i punti sui lati corrispondenti a dUmax e dVmax, unendo queste coppie trovo le due direzioni di possibile split - // punti medi del lato successivo in senso antiorario rispetto al relativo vertice della patch - dU = ( m_mTree[nCToSplit].GetTopRight().x + m_mTree[nCToSplit].GetBottomLeft().x) / 2 ; - dV = ( m_mTree[nCToSplit].GetTopRight().y + m_mTree[nCToSplit].GetBottomLeft().y) / 2 ; - dULoc = dVLoc = 0.5 ; - Point3d ptPSrf ; //ptP00, ptP10, ptP11, ptP01; - 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, ptP00) ; - m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10) ; - m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11) ; - m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01) ; - Point3d ptP00P11 = ( 1 - dULoc) * ptP00 + dULoc * ptP11 ; - Point3d ptP10P01 = ( 1 - dVLoc) * ptP10 + dVLoc * ptP01 ; - // per lo split scelgo la direzione che è più vicina alla superficie originale nel punto di maggior distanza - // effettuo lo split e configuro le celle figlie - if ( Dist(ptP00P11, ptPSrf) > Dist(ptP10P01, ptPSrf)) - // lungo la direzione U ho una curvatura maggiore - bVert = false ; - else - // lungo la direzione V ho una curvatura maggiore - bVert = true ; - - // verifico che la cella sia da splittare e che eventualmente sia abbastanza grande da poterlo fare - if ( bVert) - dSideMinVal = min( Dist( ptP00, ptP10), Dist( ptP01, ptP11)) ; - else - dSideMinVal = min( Dist( ptP00, ptP01), Dist( ptP10, ptP11)) ; - dSideMaxVal = max( Dist( ptP00, ptP11), Dist( ptP10, ptP01)) ; - if ( ( dErr > m_dLinTol && dSideMinVal >= dSideMin) || 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()) + // 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() ; - if ( nCToSplit == m_nRoot && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed() ) - break ; + // 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 ; + } + } + Balance( vBalanceCheck) ; // da implementare quando dividerò ad un parametro a scelta e non a metà + } + // bilineare + else { + while ( nCToSplit != -2 && m_mTree[nCToSplit].IsProcessed() == false) { + // 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) ; + + // calcolo se è migliore la divisione in orizzontale o in verticale + Point3d ptP00P10, ptP00P01 , ptP01P11, ptP10P11 ; + ptP00P10 = ( ptP00 + ptP10) / 2 ; + ptP10P11 = ( ptP10 + ptP11) / 2 ; + ptP01P11 = ( ptP01 + ptP11) / 2 ; + ptP00P01 = ( ptP00 + ptP01) / 2 ; + bool bVert = false ; + + + //// questo calcolo è inutile perché confronto due cose che sono sempre uguali/////////////////////////////////////////////////////// + // calcolo se è meglio spezzare in orizzontale o in verticale + //double dErrVert1 = ( ( ptP00 - ptP01) + ( ptP01P11 - ptP00P10)).Len() ; + //double dErrVert2 = ( ( ptP00P10 - ptP01P11) + ( ptP11 - ptP10)).Len() ; + //double dErrOriz1 = ( ( ptP00P01 - ptP01) + ( ptP11 - ptP10P11)).Len() ; + //double dErrOriz2 = ( ( ptP00 - ptP00P01) + ( ptP10P11 - ptP10)).Len() ; + ////if (0 ) { + //if ( abs( dErrVert1 + dErrVert2 - dErrOriz1 - dErrOriz2) < EPS_SMALL && nCToSplit != -1) { + // bVert = ! m_mTree[m_mTree[nCToSplit].m_nParent].IsSplitVert() ; + //} + //else { + // if ( dErrVert1 + dErrVert2 > dErrOriz1 + dErrOriz2) { + // bVert = false ; + // } + // else { + // bVert = true ; + // } + //} + + // con questo esce la C sulla bilineare + // calcolo in quale direzione è meglio dividere in base allo stretch + Point3d ptPSrfU, ptPSrfV ; + double dU = 0, dV = 0 ; + double dDistU = 0, dDistV = 0 ; + double dULoc, dVLoc ; + 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 ) { + /*Point3d ptU = ( 1 - i) * ptP00P01 + i * ptP10P11 ; + Point3d ptV = ( 1 - i) * ptP00P10 + i * ptP01P11 ;*/ + 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 ; + dVLoc = ( m_mTree[nCToSplit].GetBottomLeft().y + m_mTree[nCToSplit].GetTopRight().y) / 2 ; + 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) ; + //dDistU = max( Dist( ptU , ptPSrfU), dDistU) ; + //dDistV = max( Dist( ptV , ptPSrfV), dDistV) ; + 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 ; + } + } + + // diagonali + //Point3d ptP00P11, ptP10P01, ptPSrf ; + //ptP00P11 = ( ptP00 + ptP11) / 2 ; + //ptP10P01 = ( ptP10 + ptP01) / 2 ; + //double dU = ( m_mTree[nCToSplit].GetBottomLeft().x + m_mTree[nCToSplit].GetTopRight().x) / 2 ; + //double dV = ( m_mTree[nCToSplit].GetBottomLeft().y + m_mTree[nCToSplit].GetTopRight().y) / 2 ; + //m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ; + //if ( Dist( ptP00P11, ptPSrf) > Dist( ptP10P01, ptPSrf)) + // bVert = false ; + //else + // bVert = true ; + + + + + // 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 ; + plAppr.Set( ptP00, ( ptP00 - ptP01) ^ ( 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 ; + } } - nCToSplit = m_mTree[nCToSplit].m_nChild2 ; } - c ++ ; } - Balance( vBalanceCheck) ; + // se la superficie è trimmata + else { + SurfFlatRegion sfrTrimReg ; + } return true ; } //---------------------------------------------------------------------------- void Tree::Balance( INTVECTOR vCheck) { - for ( int i : vCheck ) { - // non ancora implementato - // rendolo il tree balanced : ogni foglia deve avere una profondità di +- 1 rispetto ai suoi vicini. - } + //for ( int i : vCheck ) { + // // non ancora implementato + // // rendo il tree balanced : ogni foglia deve avere una profondità di +- 1 rispetto alle foglie adiacenti. + //} } //---------------------------------------------------------------------------- @@ -478,7 +650,7 @@ void Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) } } vector vCells ; - for ( int k : vTopNeighs ) + for ( int k : vTopNeighs) vCells.push_back( m_mTree[k]) ; sort( vCells.begin(), vCells.end(), Cell::minorX ) ; vTopNeighs.clear() ; @@ -516,7 +688,7 @@ void Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) } } bool bAllLeaves = true ; - for ( int i : vBottomNeighs ) { + for ( int i : vBottomNeighs) { if ( ! m_mTree[i].IsLeaf()) bAllLeaves = false ; } @@ -542,8 +714,8 @@ void Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) } // altrimenti solo uno dei figli lo sarà else { - if ( m_mTree[m_mTree[i].m_nChild1].GetTopRight().x <= m_mTree[nId].GetBottomLeft().x || - m_mTree[m_mTree[i].m_nChild1].GetBottomLeft().x >= m_mTree[nId].GetTopRight().x ) + if ( m_mTree[m_mTree[i].m_nChild1].GetTopRight().x <= m_mTree[nId].GetBottomLeft().x || + m_mTree[m_mTree[i].m_nChild1].GetBottomLeft().x >= m_mTree[nId].GetTopRight().x) vBottomNeighs.push_back( m_mTree[i].m_nChild2) ; else vBottomNeighs.push_back( m_mTree[i].m_nChild1) ; @@ -556,7 +728,7 @@ void Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) } } vector vCells ; - for ( int k : vBottomNeighs ) + for ( int k : vBottomNeighs) vCells.push_back( m_mTree[k]) ; sort( vCells.begin(), vCells.end(), Cell::minorX) ; vBottomNeighs.clear() ; @@ -568,7 +740,7 @@ void Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) //---------------------------------------------------------------------------- void Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) { - if ( (int) vLeftNeighs.size() == 0 ) { + if ( (int) vLeftNeighs.size() == 0) { if ( m_mTree[nId].m_nLeft == -2) return ; if ( m_mTree[m_mTree[nId].m_nLeft].IsLeaf()) @@ -577,14 +749,14 @@ void Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) if ( ! m_mTree[m_mTree[nId].m_nLeft].IsSplitVert()) { // se la cella vicina è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima if ( m_mTree[m_mTree[nId].m_nLeft].GetTopRight().y - m_mTree[m_mTree[nId].m_nLeft].GetBottomLeft().y <= - m_mTree[nId].GetTopRight().y - m_mTree[nId].GetBottomLeft().y) { + m_mTree[nId].GetTopRight().y - m_mTree[nId].GetBottomLeft().y) { vLeftNeighs.push_back( m_mTree[m_mTree[nId].m_nLeft].m_nChild1) ; vLeftNeighs.push_back( m_mTree[m_mTree[nId].m_nLeft].m_nChild2) ; } // altrimenti solo uno dei figli lo sarà else{ - if ( m_mTree[m_mTree[m_mTree[nId].m_nLeft].m_nChild1].GetTopRight().y <= m_mTree[nId].GetBottomLeft().y || - m_mTree[m_mTree[m_mTree[nId].m_nLeft].m_nChild1].GetBottomLeft().y >= m_mTree[nId].GetTopRight().y ) + if ( m_mTree[m_mTree[m_mTree[nId].m_nLeft].m_nChild1].GetTopRight().y <= m_mTree[nId].GetBottomLeft().y || + m_mTree[m_mTree[m_mTree[nId].m_nLeft].m_nChild1].GetBottomLeft().y >= m_mTree[nId].GetTopRight().y) vLeftNeighs.push_back( m_mTree[m_mTree[nId].m_nLeft].m_nChild2) ; else vLeftNeighs.push_back( m_mTree[m_mTree[nId].m_nLeft].m_nChild1) ; @@ -595,7 +767,7 @@ void Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) } } bool bAllLeaves = true ; - for ( int i : vLeftNeighs ) { + for ( int i : vLeftNeighs) { if ( ! m_mTree[i].IsLeaf()) bAllLeaves = false ; } @@ -615,14 +787,14 @@ void Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) if ( ! m_mTree[i].IsSplitVert()) { // se la cella è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima if ( m_mTree[i].GetTopRight().y - m_mTree[i].GetBottomLeft().y <= - m_mTree[nId].GetTopRight().y - m_mTree[nId].GetBottomLeft().y) { + m_mTree[nId].GetTopRight().y - m_mTree[nId].GetBottomLeft().y) { vLeftNeighs.push_back( m_mTree[i].m_nChild1) ; vLeftNeighs.push_back( m_mTree[i].m_nChild2) ; } // altrimenti solo uno dei figli lo sarà else { - if ( m_mTree[m_mTree[i].m_nChild1].GetTopRight().y <= m_mTree[nId].GetBottomLeft().y || - m_mTree[m_mTree[i].m_nChild1].GetBottomLeft().y >= m_mTree[nId].GetTopRight().y ) + if ( m_mTree[m_mTree[i].m_nChild1].GetTopRight().y <= m_mTree[nId].GetBottomLeft().y || + m_mTree[m_mTree[i].m_nChild1].GetBottomLeft().y >= m_mTree[nId].GetTopRight().y) vLeftNeighs.push_back( m_mTree[i].m_nChild2) ; else vLeftNeighs.push_back( m_mTree[i].m_nChild1) ; @@ -661,8 +833,8 @@ void Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs) } // altrimenti solo uno dei figli lo sarà else{ - if ( m_mTree[m_mTree[m_mTree[nId].m_nRight].m_nChild1].GetTopRight().y <= m_mTree[nId].GetBottomLeft().y || - m_mTree[m_mTree[m_mTree[nId].m_nRight].m_nChild1].GetBottomLeft().y >= m_mTree[nId].GetTopRight().y ) + if ( m_mTree[m_mTree[m_mTree[nId].m_nRight].m_nChild1].GetTopRight().y <= m_mTree[nId].GetBottomLeft().y || + m_mTree[m_mTree[m_mTree[nId].m_nRight].m_nChild1].GetBottomLeft().y >= m_mTree[nId].GetTopRight().y) vRightNeighs.push_back( m_mTree[m_mTree[nId].m_nRight].m_nChild2) ; else vRightNeighs.push_back( m_mTree[m_mTree[nId].m_nRight].m_nChild1) ; @@ -693,14 +865,14 @@ void Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs) if ( ! m_mTree[i].IsSplitVert()) { // se la cella è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima if ( m_mTree[i].GetTopRight().y - m_mTree[i].GetBottomLeft().y <= - m_mTree[nId].GetTopRight().y - m_mTree[nId].GetBottomLeft().y) { + m_mTree[nId].GetTopRight().y - m_mTree[nId].GetBottomLeft().y) { vRightNeighs.push_back( m_mTree[i].m_nChild1) ; vRightNeighs.push_back( m_mTree[i].m_nChild2) ; } // altrimenti solo uno dei figli lo sarà else { - if ( m_mTree[m_mTree[i].m_nChild1].GetTopRight().y <= m_mTree[nId].GetBottomLeft().y || - m_mTree[m_mTree[i].m_nChild1].GetBottomLeft().y >= m_mTree[nId].GetTopRight().y ) + if ( m_mTree[m_mTree[i].m_nChild1].GetTopRight().y <= m_mTree[nId].GetBottomLeft().y || + m_mTree[m_mTree[i].m_nChild1].GetBottomLeft().y >= m_mTree[nId].GetTopRight().y) vRightNeighs.push_back( m_mTree[i].m_nChild2) ; else vRightNeighs.push_back( m_mTree[i].m_nChild1) ; @@ -759,7 +931,7 @@ int Tree::GetHeightLeaves( int nId, INTVECTOR& vnLeaves, int d) int Tree::GetDepth( int nId, int nRef = -2) { int c = 0 ; - while ( m_mTree[nId].m_nParent != nRef ) { + while ( m_mTree[nId].m_nParent != nRef) { nId = m_mTree[nId].m_nParent ; ++ c ; } @@ -826,7 +998,7 @@ bool Tree::GetPolygons( POLYLINEVECTOR& vPolygons) } vNeigh.clear() ; vVertices.push_back( m_mTree[nId].GetBottomLeft()) ; - // se hop una cella con vicino dello stesso grado controllo la curvatura nella cella e + // se ho una cella con vicino dello stesso grado ( quindi il poligono ha solo 5 punti) controllo la curvatura nella cella e // se necessario cambio l'ordine dei vertici per scegliere la diagonale di split migliore if ( vVertices.size() == 5) { Point3d ptPSrf, ptP00, ptP10, ptP11, ptP01; @@ -834,23 +1006,21 @@ bool Tree::GetPolygons( POLYLINEVECTOR& vPolygons) dU = ( m_mTree[nId].GetBottomLeft().x + m_mTree[nId].GetTopRight().x) / 2 ; dV = ( m_mTree[nId].GetBottomLeft().y + m_mTree[nId].GetTopRight().y) / 2 ; m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ; - m_pSrfBz->GetPointD1D2( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00) ; - m_pSrfBz->GetPointD1D2( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10) ; - m_pSrfBz->GetPointD1D2( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11) ; - m_pSrfBz->GetPointD1D2( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01) ; + ptP00 = m_mVert[nId][0] ; + ptP10 = m_mVert[nId][1] ; + ptP11 = m_mVert[nId][2] ; + ptP01 = m_mVert[nId][3] ; Point3d ptP00P11 = ( ptP00 + ptP11) / 2 ; Point3d ptP10P01 = ( ptP10 + ptP01) / 2 ; // ho la curvatura maggiore sulla diagonale tra P10 e P01, ruoto l'ordine dei vertici, in modo che triangulate prenda la diagonale giusta - if ( Dist(ptP00P11, ptPSrf) > Dist(ptP10P01, ptPSrf)) { + if ( Dist(ptP00P11, ptPSrf) + EPS_SMALL > Dist(ptP10P01, ptPSrf)) { rotate(vVertices.begin(), vVertices.begin() + 1,vVertices.end()) ; vVertices.back() = vVertices[0] ; } } - //double k = 0 ; m_vPolygons.emplace_back() ; - for ( int i = 0 ; i < (int) vVertices.size() ; ++i ) { - //k = double( i) / double( vVertices.size()) ; + for ( int i = 0 ; i < (int) vVertices.size() ; ++i) { m_vPolygons.back().AddUPoint( i, vVertices[i]) ; } } diff --git a/Tree.h b/Tree.h index 4df9a50..00f73bf 100644 --- a/Tree.h +++ b/Tree.h @@ -15,7 +15,6 @@ //--------------------------- Include ---------------------------------------- #include -#include "tree.h" #include "SurfBezier.h" #include "GeoConst.h" @@ -26,19 +25,18 @@ class Cell ~Cell( void) ; Cell( void) ; Cell( Point3d ptBL, Point3d ptTR) ; - inline bool IsSame( Cell cOtherCell) ; + inline bool IsSame( Cell cOtherCell) const ; void SetBottomLeft( Point3d ptBL) { m_ptPbl = ptBL ; } void SetTopRight( Point3d ptTR) { m_ptPtr = ptTR ; } void SetSplitDirVert( bool bVert) { m_bSplitVert = bVert ; } void SetParent(int nParent) { m_nParent = nParent ; } - Point3d GetBottomLeft( void) { return m_ptPbl ; } - Point3d GetTopRight( void) { return m_ptPtr ; } - bool IsSplitVert( void) { return m_bSplitVert ; } - bool IsLeaf( void) ; + Point3d GetBottomLeft( void) const { return m_ptPbl ; } + Point3d GetTopRight( void) const { return m_ptPtr ; } + double GetSplitValue( void) const { return m_dSplit ; } + bool IsSplitVert( void) const { return m_bSplitVert ; } + bool IsLeaf( void) const ; bool IsProcessed( void) const { return m_bProcessed ; } void Processed( void) { m_bProcessed = true ; } - //bool operator- ( const Cell &other) const { return m_ptPbl.x < other.m_ptPbl.x ; } - //bool operator| ( const Cell &other) const { return m_ptPbl.y < other.m_ptPbl.y ; } 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 ; } @@ -58,7 +56,7 @@ class Cell Point3d m_ptPtr ; // punto top right bool m_bProcessed ; // flag che indica se la cella è stata processata bool m_bSplitVert ; // flag che indica in quale direzione è stata divisa la cella - // double m_dSplit ; // lunghezza normalizzata a cui è stata splittata la cella + double m_dSplit ; // parametro a cui è stata splittata la cella } ; //---------------------------------------------------------------------------- @@ -67,28 +65,32 @@ class Tree public : ~Tree( void) ; Tree( void) ; - Tree ( const SurfBezier* pSrfBz) ; - void SetSurf( const SurfBezier* pSrfBz) ; - bool BuildTree( double dLinTol = LIN_TOL_STD, double dSideMax = INFINITO) ; // dSidemax è il massimo per la dimensione maggiore di un triangolo della trimesh + Tree ( const SurfBezier* pSrfBz, bool bSplitPatches = false) ; + void SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches = false) ; + 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) ; private : - void Split( int nId) ; // funzione di split di una cella dell'albero + 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 void Balance ( INTVECTOR vCheck) ; // creo rami in modo che tutte tutte le foglie abbiano come adiacenti foglie ad una profonditù di +- 1 int GetHeightLeaves ( int nId, INTVECTOR& vnLeaves, int d = 0) ; // altezza del subtree a partire dal nodo nId int GetDepth ( int nId, int nRef) ; // livello del nodo nId - void GetTopNeigh( int nId, INTVECTOR& vTopNeighs) ; - void GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) ; - void GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) ; - void GetRightNeigh( int nId, INTVECTOR& vRightNeighs) ; - + void GetTopNeigh( int nId, INTVECTOR& vTopNeighs) ; // restituisce le celle foglie che sono adiacenti al lato top + void GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) ; // restituisce le celle foglie che sono adiacenti al lato bottom + void GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) ; // restituisce le celle foglie che sono adiacenti al lato left + void GetRightNeigh( int nId, INTVECTOR& vRightNeighs) ; // restituisce le celle foglie che sono adiacenti al lato right private : - double m_dLinTol ; // errore dell'approssimazione - int m_nRoot ; // cella base - const SurfBezier* m_pSrfBz ; // root + 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 bool m_bTrimmed ; // superficie trimmata - POLYLINEVECTOR m_vPolygons ; // vettore dei poligoni del kd-tree + bool m_bBilinear ; // superficie bilineare + bool m_bMulti ; // superficie multi-patch + bool m_bClosed ; // superficie chiusa + POLYLINEVECTOR m_vPolygons ; // vettore dei poligoni del tree 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 } ; \ No newline at end of file