diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj
index 0e496f4..ef86681 100644
--- a/EgtGeomKernel.vcxproj
+++ b/EgtGeomKernel.vcxproj
@@ -339,7 +339,7 @@ copy $(TargetPath) \EgtProg\Dll64
-
+
@@ -604,7 +604,7 @@ copy $(TargetPath) \EgtProg\Dll64
-
+
diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters
index 4503501..ce84aa1 100644
--- a/EgtGeomKernel.vcxproj.filters
+++ b/EgtGeomKernel.vcxproj.filters
@@ -471,7 +471,7 @@
File di origine\GeoOffset
-
+
File di origine\Base
@@ -1106,7 +1106,7 @@
File di intestazione
-
+
File di intestazione
diff --git a/KdTree.cpp b/KdTree.cpp
deleted file mode 100644
index fc945ef..0000000
--- a/KdTree.cpp
+++ /dev/null
@@ -1,286 +0,0 @@
-//----------------------------------------------------------------------------
-// EgalTech 2023
-//----------------------------------------------------------------------------
-// File : Kd-tree.cpp Data : 21.04.23 Versione :
-// Contenuto : Implementazione della classe kd-tree.
-//
-//
-//
-// Modifiche : 21.04.23 DB Creazione modulo.
-//
-//
-//----------------------------------------------------------------------------
-
-//--------------------------- Include ----------------------------------------
-#include "stdafx.h"
-#include "KdTree.h"
-#include "SurfBezier.h"
-#include "GeoConst.h"
-
-using namespace std ;
-
-//----------------------------------------------------------------------------
-Cell::Cell( void)
- : m_ptPbl( ORIG), m_ptPtr( ORIG), m_bProcessed ( false) , m_bSplitVert ( true) , m_dSplit( 0) , m_cTop ( nullptr), m_cBottom( nullptr),
- m_cLeft( nullptr), m_cRight ( nullptr), m_cParent( nullptr), m_cChild1( nullptr), m_cChild2( nullptr)
-{}
-
-//----------------------------------------------------------------------------
-Cell::~Cell( void)
-{
-}
-
-//----------------------------------------------------------------------------
-inline bool
-Cell::IsSame( std::shared_ptr cOtherCell)
-{
- if ( AreSamePointXYApprox( m_ptPbl, cOtherCell->GetBottomLeft()) &&
- AreSamePointXYApprox( m_ptPtr, cOtherCell->GetTopRight())) {
- return true ;
- }
- else {
- return false ;
- }
-}
-
-//----------------------------------------------------------------------------
-void
-Cell::Split( double dSplitValue)
-{
- m_dSplit = dSplitValue ;
- //Cell cChild1, cChild2, cParent, cTop, cBottom, cLeft, cRight ;
- m_cChild1 = make_shared() ;
- //m_cChild2 = &cChild2 ;
- //m_cParent = &cParent ;
- //m_cTop = &cTop ;
- //m_cBottom = &cBottom ;
- //m_cLeft = &cLeft ;
- //m_cRight = &cRight ;
-
- m_cChild2 = make_shared() ;
- //m_cParent = make_shared() ;
- //m_cTop = make_shared() ;
- //m_cBottom = make_shared() ;
- //m_cLeft = make_shared() ;
- //m_cRight = make_shared() ;
- if ( ! m_bSplitVert )
- {
- // la cella figlio 1 è quella sopra
- Point3d ptBL( m_ptPbl.x, m_dSplit) ;
- m_cChild1->SetBottomLeft( ptBL) ;
- m_cChild1->SetTopRight( m_ptPtr) ;
- m_cChild1->m_cTop = m_cTop ;
- m_cChild1->m_cBottom = m_cChild2 ;
- m_cChild1->m_cLeft = m_cLeft ;
- m_cChild1->m_cRight = m_cRight ;
- //m_cChild1->m_cParent = make_shared(*this) ;
- Point3d ptTR( m_ptPtr.x, m_dSplit) ;
- m_cChild2->SetBottomLeft( m_ptPbl) ;
- m_cChild2->SetTopRight( ptTR) ;
- m_cChild2->m_cTop = m_cChild1 ;
- m_cChild2->m_cBottom = m_cBottom ;
- m_cChild2->m_cLeft = m_cLeft ;
- m_cChild2->m_cRight = m_cRight ;
- //m_cChild2->m_cParent = make_shared(*this) ;
- }
- else {
- // la cella figlio 1 è quella di sinistra
- Point3d ptTR( m_dSplit, m_ptPtr.y) ;
- m_cChild1->SetBottomLeft( m_ptPbl) ;
- m_cChild1->SetTopRight( ptTR) ;
- m_cChild1->m_cTop = m_cTop ;
- m_cChild1->m_cBottom = m_cBottom ;
- m_cChild1->m_cLeft = m_cLeft ;
- m_cChild1->m_cRight = m_cChild2 ;
- //m_cChild1->m_cParent = make_shared(*this) ;
- Point3d ptBL( m_dSplit, m_ptPbl.y) ;
- m_cChild2->SetBottomLeft( ptBL) ;
- m_cChild2->SetTopRight( m_ptPtr) ;
- m_cChild2->m_cTop = m_cTop ;
- m_cChild2->m_cBottom = m_cBottom ;
- m_cChild2->m_cLeft = m_cChild1 ;
- m_cChild2->m_cRight = m_cRight ;
- //m_cChild2->m_cParent = make_shared(*this) ;
- }
- //m_bProcessed = true ;
-}
-
-//----------------------------------------------------------------------------
-bool
-//Cell::IsLeaf ( void) const
-Cell::IsLeaf ( void)
-{
- if( m_cChild1 == nullptr && m_cChild2 == nullptr)
- return true ;
- else
- return false ;
-}
-
-//----------------------------------------------------------------------------
-KdTree::KdTree( void)
- : m_dLinTol(LIN_TOL_FINE), m_pSrfBz(nullptr), m_cRoot( make_shared())
-{}
-
-//----------------------------------------------------------------------------
-KdTree::KdTree( const SurfBezier* pSrfBz)
- : m_dLinTol( LIN_TOL_FINE), m_pSrfBz ( pSrfBz)
-{
- // 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) ;
- Point3d ptTop( nSpanU, nSpanV) ;
- m_cRoot = make_shared() ;
- m_cRoot->SetBottomLeft( ORIG) ;
- m_cRoot->SetTopRight( ptTop) ;
-}
-
-//----------------------------------------------------------------------------
-KdTree::~KdTree( void)
-{
-}
-
-//----------------------------------------------------------------------------
-void KdTree::SetSurf( const SurfBezier* pSrfBz)
-{
- m_pSrfBz = pSrfBz ;
- // 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) ;
- Point3d ptTop( nSpanU, nSpanV) ;
- m_cRoot = make_shared() ;
- m_cRoot->SetBottomLeft( ORIG) ;
- m_cRoot->SetTopRight( ptTop) ;
-}
-
-//----------------------------------------------------------------------------
-bool KdTree::BuildTree( int nStepU, int nStepV)
-{
- // 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 err ; // errore calcolato
- double dist ; // distanza tra punti selezionati
- double dU, dV , dUmax, dVmax;
- Point3d ptBz, ptBl ;
- // cerco lo scostamento massimo tra la sup di Bezier e la sua approssimazione bilineare
-
- // shared_ptr cToSplit = make_shared(&m_cRoot) ;
- shared_ptr cToSplit = m_cRoot ;
-
-
- //while ( cToSplit != nullptr &&
- // ( cToSplit->IsSame( &m_cRoot) || // per entrare nel ciclo
- // cToSplit->IsProcessed() == false || // per processare le child1
- // ( ! cToSplit->IsSame( &m_cRoot) && cToSplit->m_cChild2->IsProcessed() == false))) { // per processare le child2 finché torno alla root
- int c = 1 ;
- while ( cToSplit != nullptr && cToSplit->IsProcessed() == false) {
- err = 0 ;
- // calcolo la bilineare per gli estremi della cella
- SurfBezier pSrfBl ;
- pSrfBl.Init(1, 1, 1, 1, false) ;
- m_pSrfBz->GetPointD1D2( cToSplit->GetBottomLeft().x, cToSplit->GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz) ;
- pSrfBl.SetControlPoint( 0, ptBz) ; // P00
- m_pSrfBz->GetPointD1D2( cToSplit->GetTopRight().x, cToSplit->GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz) ;
- pSrfBl.SetControlPoint( 1, ptBz) ; // P01
- m_pSrfBz->GetPointD1D2( cToSplit->GetBottomLeft().x, cToSplit->GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz) ;
- pSrfBl.SetControlPoint( 2, ptBz) ; // P10
- m_pSrfBz->GetPointD1D2( cToSplit->GetTopRight().x, cToSplit->GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz) ;
- pSrfBl.SetControlPoint( 3, ptBz) ; // P11
- for ( int i = 1 ; i <= nStepU ; ++ i) {
- for ( int j = 1 ; j <= nStepV ; ++ j) {
- dU = double ( i) / nStepU * ( cToSplit->GetTopRight().y - cToSplit->GetBottomLeft().y) ;
- dV = double ( j) / nStepV * ( cToSplit->GetTopRight().x - cToSplit->GetBottomLeft().x) ;
- if ( ! m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz) ||
- ! pSrfBl.GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBl))
- return false ;
- dist = Dist( ptBz, ptBl) ;
- if ( dist > err) { // ### nelle condizioni dell'if probabilmente devo già controllare che la dimensione della cella non sia troppo piccola
- err = dist ;
- dUmax = dU ;
- dVmax = dV ;
- }
- }
- }
- // devo spostare la condizione sulla dimensione minima di una cella/////////////////////////////////////////////////////////////////////
- // probabilmente qui ###
- if ( err > m_dLinTol && ( dUmax - cToSplit->GetBottomLeft().y) >= 0.01 && ( dVmax - cToSplit->GetBottomLeft().x) >= 0.01) {
- // 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 orario rispetto al relativo vertice della patch
- Point3d ptPSrf, ptP00, ptP10, ptP11, ptP01;
- m_pSrfBz->GetPointD1D2( dUmax, dVmax, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ;
- m_pSrfBz->GetPointD1D2( dUmax, 0, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00) ;
- m_pSrfBz->GetPointD1D2( 1, dVmax, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10) ;
- m_pSrfBz->GetPointD1D2( dUmax, 1, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11) ;
- m_pSrfBz->GetPointD1D2( 0, dVmax, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01) ;
- Point3d ptP00P11 = ( 1 - dVmax) * ptP00 + dVmax * ptP11 ;
- Point3d ptP10P01 = ( 1 - dUmax) * ptP10 + dUmax * 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)) {
- cToSplit->SetSplitDirVert( false) ;
- cToSplit->Split( dUmax) ;
- }
- else {
- cToSplit->SetSplitDirVert( true) ;
- cToSplit->Split( dVmax) ;
- }
- cToSplit->m_cChild1->SetParent( cToSplit) ;
- cToSplit->m_cChild2->SetParent( cToSplit) ;
- // procedo con lo split del Child1
- cToSplit = cToSplit->m_cChild1 ;
- }
- else {
- // sono arrivato ad una cella Leaf, quindi salvo il poligono
- cToSplit->Processed() ;
- Point3d ptPbr( cToSplit->GetTopRight().x, cToSplit->GetBottomLeft().y) ;
- Point3d ptPtl( cToSplit->GetBottomLeft().x, cToSplit->GetTopRight().y) ;
- m_vPolygons.emplace_back() ;
- m_vPolygons.back().AddUPoint(0, cToSplit->GetBottomLeft()) ;
- m_vPolygons.back().AddUPoint(0.25, ptPbr) ;
- m_vPolygons.back().AddUPoint(0.5, cToSplit->GetTopRight()) ;
- m_vPolygons.back().AddUPoint(0.75, ptPtl) ;
- m_vPolygons.back().AddUPoint(1, cToSplit->GetBottomLeft()) ;
- // risalgo i parent finché non trovo il primo Child2 da processare
- cToSplit = cToSplit->m_cParent ;
- if ( cToSplit->m_cChild1->IsProcessed() && cToSplit->m_cChild2->IsProcessed())
- cToSplit->Processed() ;
- // questa condizione mi manda in un loop perché non processo mai il child2 di root
- // a'altro canto devo evitare di fare i passaggi successivi se sono già parent processato
-
- //if ( cToSplit->IsSame( &m_cRoot))
- // continue ;
-
- while ( cToSplit->m_cChild2->IsProcessed()) {
- if ( cToSplit->m_cParent != nullptr )
- cToSplit = cToSplit->m_cParent ;
- if ( cToSplit->m_cChild1->IsProcessed() && cToSplit->m_cChild2->IsProcessed())
- cToSplit->Processed() ;
- if ( cToSplit->IsSame( m_cRoot) && cToSplit->m_cChild2->IsProcessed())
- break ;
- }
- //if ( cToSplit->IsSame( &m_cRoot))
- // continue ;
- //else
- // cToSplit = cToSplit->m_cChild2 ;
-
- cToSplit = cToSplit->m_cChild2 ;
- }
- c ++ ;
- }
- return true ;
-}
-
-//----------------------------------------------------------------------------
-bool KdTree::GetPolygons( POLYLINEVECTOR& vPolygons)
-{
- // restituisco i poligoni delle celle del kd-tree nello spazio parametrico
- if ( m_vPolygons.empty())
- return false ;
- vPolygons = m_vPolygons ;
- return true ;
-}
\ No newline at end of file
diff --git a/KdTree.h b/KdTree.h
deleted file mode 100644
index c782103..0000000
--- a/KdTree.h
+++ /dev/null
@@ -1,73 +0,0 @@
-//----------------------------------------------------------------------------
-// EgalTech 2023
-//----------------------------------------------------------------------------
-// File : Kd-tree.h Data : 21.04.23 Versione :
-// Contenuto : Implementazione della classe Cell di un kd-tree.
-//
-//
-//
-// Modifiche : 21.04.23 DB Creazione modulo.
-//
-//
-//----------------------------------------------------------------------------
-
-#pragma once
-
-//--------------------------- Include ----------------------------------------
-#include "SurfBezier.h"
-
-//----------------------------------------------------------------------------
-class Cell
-{
- public :
- ~Cell( void) ;
- Cell( void) ;
- Cell( Point3d ptBL, Point3d ptTR) : m_ptPbl( ptBL), m_ptPtr(ptTR) {}
- inline bool IsSame ( std::shared_ptr cOtherCell) ;
- void SetBottomLeft( Point3d ptBL) { m_ptPbl = ptBL ; }
- void SetTopRight( Point3d ptTR) { m_ptPtr = ptTR ; }
- void SetSplitDirVert( bool bVert) { m_bSplitVert = bVert ; }
- void SetSplitValue ( double dSplitValue) { m_dSplit = dSplitValue ; }
- void SetParent (std::shared_ptr pCParent) { m_cParent = pCParent ; }
- void Split( double dSpiltValue) ;
- Point3d GetBottomLeft( void) { return m_ptPbl ; }
- Point3d GetTopRight( void) { return m_ptPtr ; }
- //bool IsLeaf( void) const ;
- bool IsLeaf( void) ;
- bool IsProcessed ( void) const { return m_bProcessed ; }
- void Processed ( void) { m_bProcessed = true ; }
-
- public :
- std::shared_ptr m_cTop ; // cella adiacente al lato top
- std::shared_ptr m_cBottom ; // cella adiacente al lato bottom
- std::shared_ptr m_cLeft ; // cella adiacente al lato left
- std::shared_ptr m_cRight ; // cella adiacente al lato right
- std::shared_ptr m_cParent ; // cella genitore
- std::shared_ptr m_cChild1 ; // prima cella figlio
- std::shared_ptr m_cChild2 ; // seconda cella figlio
-
- private :
- Point3d m_ptPbl ; // punto bottom left
- 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
-} ;
-
-//----------------------------------------------------------------------------
-class KdTree
-{
-public :
- ~KdTree( void) ;
- KdTree( void) ;
- KdTree ( const SurfBezier* pSrfBz) ;
- void SetSurf( const SurfBezier* pSrfBz) ;
- bool BuildTree( int nStepU, int nStepV) ;
- bool GetPolygons( POLYLINEVECTOR& vPolygons) ;
-
-private :
- double m_dLinTol ; // errore dell'approssimazione
- std::shared_ptr m_cRoot ; // cella base
- const SurfBezier* m_pSrfBz ; // root
- POLYLINEVECTOR m_vPolygons ; // vettore dei poligoni del kd-tree
-} ;
\ No newline at end of file
diff --git a/SurfBezier.cpp b/SurfBezier.cpp
index 1ec67b5..7106029 100644
--- a/SurfBezier.cpp
+++ b/SurfBezier.cpp
@@ -20,7 +20,7 @@
#include "Bernstein.h"
#include "CurveBezier.h"
#include "CurveComposite.h"
-#include "KdTree.h"
+#include "Tree.h"
#include "Triangulate.h"
#include "SurfTriMesh.h"
#include "/EgtDev/Include/EGkSfrCreate.h"
@@ -1473,7 +1473,7 @@ SurfBezier::GetAuxSurf( void) const
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) {
+ if ( m_nDegU == 1 && m_nDegV == 1) {
// costruttore della superficie
StmFromTriangleSoup stmSoup ;
if ( ! stmSoup.Start())
@@ -1529,16 +1529,16 @@ SurfBezier::GetAuxSurf( void) const
}
else {
// costruttore della superficie
- KdTree kdTree( this) ;
- kdTree.BuildTree( nStepU, nStepV) ;
+ Tree Tree( this) ;
+ Tree.BuildTree() ;
POLYLINEVECTOR vPL ;
- kdTree.GetPolygons( vPL) ;
+ Tree.GetPolygons( vPL) ;
PtrOwner pSrfTm( CreateBasicSurfTriMesh()) ;
//srfTm.CreateByRegion( vPL) ;
// prendo i punti di ogni polyline dell'albero, li triangolo e li porto in 3d
- for ( PolyLine i : vPL ) {
- SurfTriMesh srfTmCell ;
+ for ( PolyLine i : vPL) {
+ PtrOwner srfTmCell( CreateBasicSurfTriMesh()) ;
PNTVECTOR vPnt ;
INTVECTOR vTria ;
Triangulate Tri ;
@@ -1548,14 +1548,15 @@ SurfBezier::GetAuxSurf( void) const
// inizializzo la superficie
int nVert = int( vPnt.size()) ;
int nTria = int( vTria.size()) / 3 ;
- if ( ! srfTmCell.Init( nVert, nTria))
+ if ( ! srfTmCell->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].y, vPnt[i].x, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ;
- if ( srfTmCell.AddVertex( pt3d) == SVT_NULL)
+ GetPointD1D2( vPnt[i].x, vPnt[i].y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ;
+ if ( srfTmCell->AddVertex( pt3d) == SVT_NULL)
+ //if ( srfTmCell->AddVertex( vPnt[i]) == SVT_NULL )
return false ;
}
@@ -1565,21 +1566,23 @@ SurfBezier::GetAuxSurf( void) const
vV[0] = vTria[3*i] ;
vV[1] = vTria[3*i+1] ;
vV[2] = vTria[3*i+2] ;
- if ( srfTmCell.AddTriangle( vV) == SVT_NULL)
+ if ( srfTmCell->AddTriangle( vV) == SVT_NULL)
return false ;
}
// sistemo la topologia
- if ( ! srfTmCell.AdjustTopology())
+ if ( ! srfTmCell->AdjustTopology())
return false ;
//if ( ! pSrfTm->Add( srfTmCell))
// return false ;
if ( ! pSrfTm->IsValid() ) {
- *pSrfTm= srfTmCell ;
+ //pSrfTm.Set( CloneBasicSurfTriMesh(srfTmCell)) ;
+ pSrfTm.Set( Release(srfTmCell)) ;
}
else {
- if ( ! pSrfTm->Add( srfTmCell))
+ //if ( ! pSrfTm->Add( *srfTmCell))
+ if ( ! pSrfTm->DoSewing( *srfTmCell))
return false ;
}
diff --git a/Tree.cpp b/Tree.cpp
new file mode 100644
index 0000000..3d6f8e3
--- /dev/null
+++ b/Tree.cpp
@@ -0,0 +1,756 @@
+//----------------------------------------------------------------------------
+// EgalTech 2023
+//----------------------------------------------------------------------------
+// File : Tree.cpp Data : 21.04.23 Versione :
+// Contenuto : Implementazione della classe Tree.
+//
+//
+//
+// Modifiche : 21.04.23 DB Creazione modulo.
+//
+//
+//----------------------------------------------------------------------------
+
+//--------------------------- Include ----------------------------------------
+#include "stdafx.h"
+#include
+#include "Tree.h"
+#include "SurfBezier.h"
+#include "GeoConst.h"
+
+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)
+{
+ Point3d ptTr ( 1, 1) ;
+ m_ptPtr = ptTr ;
+}
+
+
+//----------------------------------------------------------------------------
+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)
+{}
+
+
+//----------------------------------------------------------------------------
+Cell::~Cell( void)
+{
+}
+
+//----------------------------------------------------------------------------
+inline bool
+Cell::IsSame( Cell cOtherCell)
+{
+ if ( AreSamePointXYApprox( m_ptPbl, cOtherCell.GetBottomLeft()) &&
+ AreSamePointXYApprox( m_ptPtr, cOtherCell.GetTopRight())) {
+ return true ;
+ }
+ else {
+ return false ;
+ }
+}
+
+//----------------------------------------------------------------------------
+bool
+//Cell::IsLeaf ( void) const
+Cell::IsLeaf ( void)
+{
+ if( m_nChild1 == -2 && m_nChild2 == -2)
+ return true ;
+ else
+ return false ;
+}
+
+//----------------------------------------------------------------------------
+Tree::Tree( void)
+ : m_dLinTol(LIN_TOL_FINE), m_pSrfBz(nullptr), m_nRoot( -1)
+{
+ Point3d ptBl( 0, 0), ptTr ( 1, 1) ;
+ Cell cRoot( ptBl, ptTr) ;
+ m_mTree.insert( pair< int, Cell>( m_nRoot, cRoot)) ;
+}
+
+//----------------------------------------------------------------------------
+Tree::Tree( const SurfBezier* pSrfBz)
+ : m_dLinTol( LIN_TOL_FINE), m_pSrfBz ( pSrfBz), m_nRoot( -1)
+{
+ // 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) ;
+ Point3d ptTop( nSpanU, nSpanV) ;
+ Cell cRoot( ORIG, ptTop) ;
+ m_mTree.insert( pair< int, Cell>( m_nRoot, cRoot)) ;
+}
+
+//----------------------------------------------------------------------------
+Tree::~Tree( void)
+{
+}
+
+//----------------------------------------------------------------------------
+void Tree::SetSurf( const SurfBezier* pSrfBz)
+{
+ m_pSrfBz = pSrfBz ;
+ // 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) ;
+ Point3d ptTop( nSpanU, nSpanV) ;
+ Cell cRoot( ORIG, ptTop) ;
+ m_mTree.insert( pair< int, Cell>( -1, cRoot)) ;
+}
+
+//----------------------------------------------------------------------------
+void
+Tree::Split( int nId)
+{
+ Cell cChild1, cChild2 ;
+ cChild1.m_nDepth = m_mTree[nId].m_nDepth + 1 ;
+ cChild2.m_nDepth = m_mTree[nId].m_nDepth + 1 ;
+ int nNodes = (int) m_mTree.size() ;
+ cChild1.m_nId = nNodes - 1 ;
+ m_mTree[nId].m_nChild1 = nNodes - 1 ;
+ cChild2.m_nId = nNodes ;
+ m_mTree[nId].m_nChild2 = nNodes ;
+ m_mTree.insert( pair( nNodes - 1, cChild1)) ;
+ m_mTree.insert( pair( nNodes, cChild2)) ;
+ if ( ! m_mTree[nId].IsSplitVert())
+ {
+ // la cella figlio 1 è quella sopra
+ Point3d ptBL( m_mTree[nId].GetBottomLeft().x, ( m_mTree[nId].GetBottomLeft().y + m_mTree[nId].GetTopRight().y) / 2) ;
+ m_mTree[m_mTree[nId].m_nChild1].SetBottomLeft( ptBL) ;
+ m_mTree[m_mTree[nId].m_nChild1].SetTopRight( m_mTree[nId].GetTopRight()) ;
+ m_mTree[m_mTree[nId].m_nChild1].m_nTop = m_mTree[nId].m_nTop ;
+ m_mTree[m_mTree[nId].m_nChild1].m_nBottom = m_mTree[nId].m_nChild2 ;
+ m_mTree[m_mTree[nId].m_nChild1].m_nLeft = m_mTree[nId].m_nLeft ;
+ m_mTree[m_mTree[nId].m_nChild1].m_nRight = m_mTree[nId].m_nRight ;
+ Point3d ptTR( m_mTree[nId].GetTopRight().x, ( m_mTree[nId].GetTopRight().y + m_mTree[nId].GetBottomLeft().y) / 2) ;
+ m_mTree[m_mTree[nId].m_nChild2].SetBottomLeft( m_mTree[nId].GetBottomLeft()) ;
+ m_mTree[m_mTree[nId].m_nChild2].SetTopRight( ptTR) ;
+ m_mTree[m_mTree[nId].m_nChild2].m_nTop = m_mTree[nId].m_nChild1 ;
+ 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 ;
+ }
+ else {
+ // la cella figlio 1 è quella di sinistra
+ Point3d ptTR( ( m_mTree[nId].GetBottomLeft().x + m_mTree[nId].GetTopRight().x) / 2, m_mTree[nId].GetTopRight().y) ;
+ m_mTree[m_mTree[nId].m_nChild1].SetBottomLeft( m_mTree[nId].GetBottomLeft()) ;
+ m_mTree[m_mTree[nId].m_nChild1].SetTopRight( ptTR) ;
+ m_mTree[m_mTree[nId].m_nChild1].m_nTop = m_mTree[nId].m_nTop ;
+ m_mTree[m_mTree[nId].m_nChild1].m_nBottom = m_mTree[nId].m_nBottom ;
+ m_mTree[m_mTree[nId].m_nChild1].m_nLeft = m_mTree[nId].m_nLeft ;
+ m_mTree[m_mTree[nId].m_nChild1].m_nRight = m_mTree[nId].m_nChild2 ;
+ Point3d ptBL(( m_mTree[nId].GetBottomLeft().x + m_mTree[nId].GetTopRight().x) / 2, m_mTree[nId].GetBottomLeft().y) ;
+ m_mTree[m_mTree[nId].m_nChild2].SetBottomLeft( ptBL) ;
+ m_mTree[m_mTree[nId].m_nChild2].SetTopRight( m_mTree[nId].GetTopRight()) ;
+ m_mTree[m_mTree[nId].m_nChild2].m_nTop = m_mTree[nId].m_nTop ;
+ 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 ;
+ }
+ 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)
+{
+ // 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 dSide ; // 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
+ int nSteps = 51 ; // numero di Step mentre scorro lungo un'isoparametrica
+ double dU, dV , dIter, dIterLoc, dULoc, dVLoc ;
+ bool bVert ;
+ Point3d ptBz, ptBl ;
+ // cerco lo scostamento massimo tra la sup di Bezier e la sua approssimazione bilineare
+ INTVECTOR vBalanceCheck ;
+ int nCToSplit = -1 ;
+
+ int c = 1 ;
+ while ( nCToSplit != -2 && m_mTree[nCToSplit].IsProcessed() == false) {
+ dErr = 0 ;
+ // verifico se l'approsimazione bilineare è ancora troppo distante dalla superficie reale
+ // calcolo la bilineare per gli estremi della cella
+ 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) ; // P01
+ m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz) ;
+ pSrfBl.SetControlPoint( 2, ptBz) ; // P10
+ 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, dErrVmax ;
+ 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( dU, dIter, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBl)) /// dU è riferito alla Bz totale, quant'è sulla Bl??
+ return false ;
+ dDist = Dist( ptBz, ptBl) ;
+ if ( dDist > dErr) {
+ dErr = dDist ;
+ bVert = true ;
+ dErrVmax = dErr ;
+ }
+ 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, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBl)) /// dV è riferito alla Bz totale, quant'è sulla Bl??
+ return false ;
+ dDist = Dist( ptBz, ptBl) ;
+ if ( dDist > dErr) {
+ dErr = dDist ;
+ bVert = false ;
+ dErrUmax = dErr ;
+ }
+ }
+ // verifico che la cella sia da splittare e che eventualmente sia abbastanza grande da poterlo fare
+ if ( bVert)
+ dSide = m_mTree[nCToSplit].GetTopRight().x - m_mTree[nCToSplit].GetBottomLeft().x ;
+ else
+ dSide = m_mTree[nCToSplit].GetTopRight().y - m_mTree[nCToSplit].GetBottomLeft().y ;
+ if ( dErr > m_dLinTol && dSide >= dSidemin) {
+ m_mTree[nCToSplit].SetSplitDirVert( bVert) ;
+ // effettuo lo split
+ Split( nCToSplit) ;
+
+ // qui faccio i check per capire quali celle devo inserire in vBalanceCheck ///////////////////////////////////////////////////////
+
+ // 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 == m_nRoot && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed() )
+ break ;
+ }
+ nCToSplit = m_mTree[nCToSplit].m_nChild2 ;
+ }
+ c ++ ;
+ }
+ Balance( vBalanceCheck) ;
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+void Tree::Balance( INTVECTOR vCheck)
+{
+ for ( int i : vCheck ) {
+
+ }
+}
+
+//----------------------------------------------------------------------------
+void Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs)
+{
+ if ( (int) vTopNeighs.size() == 0) {
+ if ( m_mTree[nId].m_nTop == -2)
+ return ;
+ if ( m_mTree[m_mTree[nId].m_nTop].IsLeaf())
+ vTopNeighs.push_back( m_mTree[nId].m_nTop) ;
+ else {
+ if ( m_mTree[m_mTree[nId].m_nTop].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_nTop].GetTopRight().x - m_mTree[m_mTree[nId].m_nTop].GetBottomLeft().x <=
+ m_mTree[nId].GetTopRight().x - m_mTree[nId].GetBottomLeft().x) {
+ vTopNeighs.push_back( m_mTree[m_mTree[nId].m_nTop].m_nChild1) ;
+ vTopNeighs.push_back( m_mTree[m_mTree[nId].m_nTop].m_nChild2) ;
+ }
+ // altrimenti solo uno dei figli lo sarà
+ else{
+ if ( m_mTree[m_mTree[m_mTree[nId].m_nTop].m_nChild1].GetTopRight().x <= m_mTree[nId].GetBottomLeft().x ||
+ m_mTree[m_mTree[m_mTree[nId].m_nTop].m_nChild1].GetBottomLeft().x >= m_mTree[nId].GetTopRight().x )
+ vTopNeighs.push_back( m_mTree[m_mTree[nId].m_nTop].m_nChild2) ;
+ else
+ vTopNeighs.push_back( m_mTree[m_mTree[nId].m_nTop].m_nChild1) ;
+ }
+ }
+ else {
+ vTopNeighs.push_back( m_mTree[m_mTree[nId].m_nTop].m_nChild2) ;
+ }
+ }
+ bool bAllLeaves = true ;
+ for ( int i : vTopNeighs ) {
+ if ( ! m_mTree[i].IsLeaf())
+ bAllLeaves = false ;
+ }
+ if ( ! bAllLeaves )
+ // almeno una cella tra i vicini trovati non è leaf quindi devo richiamare ricorsivamente questa funzione per trovare i suoi child
+ GetTopNeigh( nId, vTopNeighs) ;
+ }
+ else {
+ for ( int j = 0 ; j != (int) vTopNeighs.size() ; ++ j) {
+ int i = vTopNeighs[j] ;
+ if ( m_mTree[i].IsLeaf())
+ continue;
+ else {
+ // se la cella non è leaf la tolgo dal vettore delle foglie e aggiungo invece i suoi child
+ vTopNeighs.erase( remove( vTopNeighs.begin(),vTopNeighs.end(),i)) ;
+ -- j ;
+ 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().x - m_mTree[i].GetBottomLeft().x <=
+ m_mTree[nId].GetTopRight().x - m_mTree[nId].GetBottomLeft().x) {
+ vTopNeighs.push_back( m_mTree[i].m_nChild1) ;
+ vTopNeighs.push_back( m_mTree[i].m_nChild2) ;
+ }
+ // 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 )
+ vTopNeighs.push_back( m_mTree[i].m_nChild2) ;
+ else
+ vTopNeighs.push_back( m_mTree[i].m_nChild1) ;
+ }
+ }
+ else {
+ vTopNeighs.push_back( m_mTree[i].m_nChild2) ;
+ }
+ }
+ }
+ }
+ vector vCells ;
+ for ( int k : vTopNeighs )
+ vCells.push_back( m_mTree[k]) ;
+ sort( vCells.begin(), vCells.end(), Cell::minorX ) ;
+ vTopNeighs.clear() ;
+ for ( Cell c : vCells)
+ vTopNeighs.push_back( c.m_nId) ;
+}
+
+//----------------------------------------------------------------------------
+void Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs)
+{
+ if ( (int) vBottomNeighs.size() == 0) {
+ if ( m_mTree[nId].m_nBottom == -2)
+ return ;
+ if ( m_mTree[m_mTree[nId].m_nBottom].IsLeaf())
+ vBottomNeighs.push_back( m_mTree[nId].m_nBottom) ;
+ else {
+ if ( m_mTree[m_mTree[nId].m_nBottom].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_nBottom].GetTopRight().x - m_mTree[m_mTree[nId].m_nBottom].GetBottomLeft().x <=
+ m_mTree[nId].GetTopRight().x - m_mTree[nId].GetBottomLeft().x) {
+ vBottomNeighs.push_back( m_mTree[m_mTree[nId].m_nBottom].m_nChild1) ;
+ vBottomNeighs.push_back( m_mTree[m_mTree[nId].m_nBottom].m_nChild2) ;
+ }
+ // altrimenti solo uno dei figli lo sarà
+ else{
+ if ( m_mTree[m_mTree[m_mTree[nId].m_nBottom].m_nChild1].GetTopRight().x <= m_mTree[nId].GetBottomLeft().x ||
+ m_mTree[m_mTree[m_mTree[nId].m_nBottom].m_nChild1].GetBottomLeft().x >= m_mTree[nId].GetTopRight().x )
+ vBottomNeighs.push_back( m_mTree[m_mTree[nId].m_nBottom].m_nChild2) ;
+ else
+ vBottomNeighs.push_back( m_mTree[m_mTree[nId].m_nBottom].m_nChild1) ;
+ }
+ }
+ else {
+ vBottomNeighs.push_back( m_mTree[m_mTree[nId].m_nBottom].m_nChild1) ;
+ }
+ }
+ bool bAllLeaves = true ;
+ for ( int i : vBottomNeighs ) {
+ if ( ! m_mTree[i].IsLeaf())
+ bAllLeaves = false ;
+ }
+ if ( ! bAllLeaves )
+ // almeno una cella tra i vicini trovati non è leaf quindi devo richiamare ricorsivamente questa funzione per trovare i suoi child
+ GetBottomNeigh( nId, vBottomNeighs) ;
+ }
+ else {
+ for ( int j = 0 ; j != (int) vBottomNeighs.size() ; ++ j) {
+ int i = vBottomNeighs[j] ;
+ if ( m_mTree[i].IsLeaf())
+ continue;
+ else {
+ // se la cella non è leaf la tolgo dal vettore delle foglie e aggiungo invece i suoi child
+ vBottomNeighs.erase( remove( vBottomNeighs.begin(),vBottomNeighs.end(),i)) ;
+ -- j ;
+ 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().x - m_mTree[i].GetBottomLeft().x <=
+ m_mTree[nId].GetTopRight().x - m_mTree[nId].GetBottomLeft().x) {
+ vBottomNeighs.push_back( m_mTree[i].m_nChild1) ;
+ vBottomNeighs.push_back( m_mTree[i].m_nChild2) ;
+ }
+ // 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 )
+ vBottomNeighs.push_back( m_mTree[i].m_nChild2) ;
+ else
+ vBottomNeighs.push_back( m_mTree[i].m_nChild1) ;
+ }
+ }
+ else {
+ vBottomNeighs.push_back( m_mTree[i].m_nChild1) ;
+ }
+ }
+ }
+ }
+ vector vCells ;
+ for ( int k : vBottomNeighs )
+ vCells.push_back( m_mTree[k]) ;
+ sort( vCells.begin(), vCells.end(), Cell::minorX) ;
+ vBottomNeighs.clear() ;
+ for ( Cell c : vCells)
+ vBottomNeighs.push_back( c.m_nId) ;
+}
+
+
+//----------------------------------------------------------------------------
+void Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs)
+{
+ if ( (int) vLeftNeighs.size() == 0 ) {
+ if ( m_mTree[nId].m_nLeft == -2)
+ return ;
+ if ( m_mTree[m_mTree[nId].m_nLeft].IsLeaf())
+ vLeftNeighs.push_back( m_mTree[nId].m_nLeft) ;
+ else {
+ 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) {
+ 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 )
+ 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) ;
+ }
+ }
+ else {
+ vLeftNeighs.push_back( m_mTree[m_mTree[nId].m_nLeft].m_nChild2) ;
+ }
+ }
+ bool bAllLeaves = true ;
+ for ( int i : vLeftNeighs ) {
+ if ( ! m_mTree[i].IsLeaf())
+ bAllLeaves = false ;
+ }
+ if ( ! bAllLeaves )
+ // almeno una cella tra i vicini trovati non è leaf quindi devo richiamare ricorsivamente questa funzione per trovare i suoi child
+ GetLeftNeigh( nId, vLeftNeighs) ;
+ }
+ else {
+ for ( int j = 0 ; j != (int) vLeftNeighs.size() ; ++ j) {
+ int i = vLeftNeighs[j] ;
+ if ( m_mTree[i].IsLeaf())
+ continue;
+ else {
+ // se la cella non è leaf la tolgo dal vettore delle foglie e aggiungo invece i suoi child
+ vLeftNeighs.erase( remove( vLeftNeighs.begin(),vLeftNeighs.end(),i)) ;
+ -- j ;
+ 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) {
+ 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 )
+ vLeftNeighs.push_back( m_mTree[i].m_nChild2) ;
+ else
+ vLeftNeighs.push_back( m_mTree[i].m_nChild1) ;
+ }
+ }
+ else {
+ vLeftNeighs.push_back( m_mTree[i].m_nChild2) ;
+ }
+ }
+ }
+ }
+ vector vCells ;
+ for ( int k : vLeftNeighs)
+ vCells.push_back( m_mTree[k]) ;
+ sort( vCells.begin(), vCells.end(), Cell::minorY) ;
+ vLeftNeighs.clear() ;
+ for ( Cell c : vCells)
+ vLeftNeighs.push_back( c.m_nId) ;
+}
+
+//----------------------------------------------------------------------------
+void Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs)
+{
+ if ( (int) vRightNeighs.size() == 0) {
+ if ( m_mTree[nId].m_nRight == -2)
+ return ;
+ if ( m_mTree[m_mTree[nId].m_nRight].IsLeaf())
+ vRightNeighs.push_back( m_mTree[nId].m_nRight) ;
+ else {
+ if ( ! m_mTree[m_mTree[nId].m_nRight].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_nRight].GetTopRight().y - m_mTree[m_mTree[nId].m_nRight].GetBottomLeft().y <=
+ m_mTree[nId].GetTopRight().y - m_mTree[nId].GetBottomLeft().y) {
+ vRightNeighs.push_back( m_mTree[m_mTree[nId].m_nRight].m_nChild1) ;
+ vRightNeighs.push_back( m_mTree[m_mTree[nId].m_nRight].m_nChild2) ;
+ }
+ // 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 )
+ 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) ;
+ }
+ }
+ else {
+ vRightNeighs.push_back( m_mTree[m_mTree[nId].m_nRight].m_nChild1) ;
+ }
+ }
+ bool bAllLeaves = true ;
+ for ( int i : vRightNeighs) {
+ if ( ! m_mTree[i].IsLeaf())
+ bAllLeaves = false ;
+ }
+ if ( ! bAllLeaves )
+ // almeno una cella tra i vicini trovati non è leaf quindi devo richiamare ricorsivamente questa funzione per trovare i suoi child
+ GetRightNeigh( nId, vRightNeighs) ;
+ }
+ else {
+ for ( int j = 0 ; j != (int) vRightNeighs.size() ; ++ j) {
+ int i = vRightNeighs[j] ;
+ if ( m_mTree[i].IsLeaf())
+ continue;
+ else {
+ // se la cella non è leaf la tolgo dal vettore delle foglie e aggiungo invece i suoi child
+ vRightNeighs.erase( remove( vRightNeighs.begin(),vRightNeighs.end(), i)) ;
+ -- j ;
+ 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) {
+ 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 )
+ vRightNeighs.push_back( m_mTree[i].m_nChild2) ;
+ else
+ vRightNeighs.push_back( m_mTree[i].m_nChild1) ;
+ }
+ }
+ else {
+ vRightNeighs.push_back( m_mTree[i].m_nChild1) ;
+ }
+ }
+ }
+ }
+ vector| vCells ;
+ for ( int k : vRightNeighs)
+ vCells.push_back( m_mTree[k]) ;
+ sort( vCells.begin(), vCells.end(), Cell::minorY) ;
+ vRightNeighs.clear() ;
+ for ( Cell c : vCells)
+ vRightNeighs.push_back( c.m_nId) ;
+}
+
+//----------------------------------------------------------------------------
+int Tree::GetHeightLeaves( int nId, INTVECTOR& vnLeaves, int d)
+{
+ if ( (int) vnLeaves.size() == 0) {
+ if ( m_mTree[nId].IsLeaf())
+ return d ;
+ else {
+ vnLeaves.push_back( m_mTree[nId].m_nChild1) ;
+ vnLeaves.push_back( m_mTree[nId].m_nChild2) ;
+ if ( ! m_mTree[m_mTree[nId].m_nChild1].IsLeaf() || ! m_mTree[m_mTree[nId].m_nChild2].IsLeaf())
+ // almeno un child non è leaf quindi devo richiamare ricorsivamente questa funzione sui child in questione
+ d = GetHeightLeaves( nId, vnLeaves, m_mTree[m_mTree[nId].m_nChild1].m_nDepth) ;
+ }
+ }
+ else {
+ for ( int j = 0 ; j != (int) vnLeaves.size() ; ++ j) {
+ int i = vnLeaves[j] ;
+ if ( m_mTree[i].IsLeaf() ) {
+ continue ;
+ }
+ else {
+ // se la cella non è leaf la tolgo dal vettore delle foglie e aggiungo invece i suoi child
+ vnLeaves.erase( remove( vnLeaves.begin(),vnLeaves.end(),i)) ;
+ -- j ;
+ vnLeaves.push_back( m_mTree[i].m_nChild1) ;
+ vnLeaves.push_back( m_mTree[i].m_nChild2) ;
+ d = max ( d, m_mTree[m_mTree[i].m_nChild1].m_nDepth) ;
+ }
+ }
+ return d ;
+ }
+ return d - m_mTree[nId].m_nDepth ;
+}
+
+//----------------------------------------------------------------------------
+int Tree::GetDepth( int nId, int nRef = -2)
+{
+ int c = 0 ;
+ while ( m_mTree[nId].m_nParent != nRef ) {
+ nId = m_mTree[nId].m_nParent ;
+ ++ c ;
+ }
+ return c ;
+}
+
+//----------------------------------------------------------------------------
+bool Tree::GetPolygons( POLYLINEVECTOR& vPolygons)
+{
+ if ( m_vPolygons.empty()) {
+ PNTVECTOR vVertices ;
+ INTVECTOR vNeigh ;
+ bool bBottomRight , bTopLeft ;
+ // scorro lungo tutte le celle leaves ( dell'albero bilanciato) e oltre agli angoli della cella aggiungo alla polyline anche i vertici sui lati
+ for ( int nId : m_vnLeaves) {
+ //Point3d ptPbr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ;
+ //Point3d ptPtl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ;
+ vVertices.clear() ;
+ vNeigh.clear() ;
+ vVertices.push_back( m_mTree[nId].GetBottomLeft()) ;
+ GetBottomNeigh( nId, vNeigh) ;
+ // aggiungo i vertici che sono sul lato bottom, solo se ho più di un vicino bottom
+ if ( (int) vNeigh.size() != 0 && (int) vNeigh.size() != 1){
+ for ( int j : vNeigh )
+ vVertices.push_back( m_mTree[j].GetTopRight()) ;
+ bBottomRight = true ;
+ }
+ else
+ bBottomRight = false ;
+ vNeigh.clear() ;
+ GetRightNeigh ( nId, vNeigh) ;
+ // aggiungo i vertici che sono sul lato right, solo se ho più di un vicino right
+ if ( (int) vNeigh.size() != 0 && (int) vNeigh.size() != 1){
+ for ( int j : vNeigh )
+ vVertices.push_back( m_mTree[j].GetBottomLeft()) ;
+ }
+ // se non l'ho già aggiunto tramite i vicini bottom aggiungo il punto bottom right
+ else if ( ! bBottomRight ) {
+ Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ;
+ vVertices.push_back( ptBr) ;
+ }
+ vNeigh.clear() ;
+ vVertices.push_back( m_mTree[nId].GetTopRight()) ;
+ GetTopNeigh ( nId, vNeigh) ;
+ reverse( vNeigh.begin(), vNeigh.end()) ;
+ // aggiungo i vertici che sono sul lato top, solo se ho più di un vicino top
+ if ( (int) vNeigh.size() != 0 && (int) vNeigh.size() != 1) {
+ for ( int j : vNeigh)
+ vVertices.push_back( m_mTree[j].GetBottomLeft()) ;
+ bTopLeft = true ;
+ }
+ else
+ bTopLeft = false ;
+ vNeigh.clear() ;
+ GetLeftNeigh ( nId, vNeigh) ;
+ reverse( vNeigh.begin(), vNeigh.end()) ;
+ // aggiungo i vertici che sono sul lato left, solo se ho più di un vicino left
+ if ( (int) vNeigh.size() != 0 && (int) vNeigh.size() != 1) {
+ for ( int j : vNeigh)
+ vVertices.push_back( m_mTree[j].GetTopRight()) ;
+ }
+ // se non l'ho già aggiunto tramite i vicini top aggiungo il punto top left
+ else if ( ! bTopLeft) {
+ Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ;
+ vVertices.push_back( ptTl) ;
+ }
+ vNeigh.clear() ;
+ vVertices.push_back( m_mTree[nId].GetBottomLeft()) ;
+ double k = 0 ;
+ m_vPolygons.emplace_back() ;
+ for ( int i = 0 ; i < (int) vVertices.size() ; ++i ) {
+ k = double( i) / double( vVertices.size()) ;
+ m_vPolygons.back().AddUPoint( i, vVertices[i]) ;
+ }
+ }
+ }
+ // restituisco i poligoni delle celle del tree nello spazio parametrico
+ vPolygons = m_vPolygons ;
+ return true ;
+}
\ No newline at end of file
diff --git a/Tree.h b/Tree.h
new file mode 100644
index 0000000..aab0ac1
--- /dev/null
+++ b/Tree.h
@@ -0,0 +1,92 @@
+//----------------------------------------------------------------------------
+// EgalTech 2023
+//----------------------------------------------------------------------------
+// File : Tree.h Data : 21.04.23 Versione :
+// Contenuto : Implementazione della classe Cell di un albero binario Tree.
+//
+//
+//
+// Modifiche : 21.04.23 DB Creazione modulo.
+//
+//
+//----------------------------------------------------------------------------
+
+#pragma once
+
+//--------------------------- Include ----------------------------------------
+#include | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |