diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters
index 13b53ad..ce7eb9f 100644
--- a/EgtGeomKernel.vcxproj.filters
+++ b/EgtGeomKernel.vcxproj.filters
@@ -473,6 +473,7 @@
File di origine\Base
+
File di origine\GeoInters
@@ -1112,6 +1113,8 @@
File di intestazione
+ File di intestazione
+
File di intestazione
diff --git a/SurfBezier.cpp b/SurfBezier.cpp
index c1c5b3d..b0fb6c6 100644
--- a/SurfBezier.cpp
+++ b/SurfBezier.cpp
@@ -149,10 +149,12 @@ SurfBezier::SetTrimRegion( const ISurfFlatRegion& sfrTrimReg)
}
//----------------------------------------------------------------------------
-bool
-SurfBezier::GetTrimRegion( ISurfFlatRegion& sfrTrimReg)
+SurfFlatRegion*
+SurfBezier::GetTrimRegion( void) const
{
- return true ;
+ if ( ! m_bTrimmed || m_pTrimReg == nullptr )
+ return nullptr ;
+ return m_pTrimReg ;
}
//----------------------------------------------------------------------------
@@ -1228,39 +1230,62 @@ SurfBezier::GetCurveOnV( double dU) const
CurveComposite*
SurfBezier::GetLoop( int nLoop) const
{
- // Se superficie completa, basta concatenare le 4 isoparametriche di bordo
- if ( ! m_bTrimmed) {
- // Esiste solo il loop esterno
- if ( nLoop != 0)
+ // Il primo loop sono le 4 isoparametriche di bordo concatenate
+ if ( ! m_bTrimmed ) {
+ if ( nLoop != 0 )
return nullptr ;
- // Loop
+ // Loop
PtrOwner pLoop( CreateBasicCurveComposite()) ;
- // prima curva isoparametrica in U con V=0
+ // prima curva isoparametrica in U con V=0
PtrOwner pCrvCoU0( GetCurveOnU( 0)) ;
if ( ! IsNull( pCrvCoU0) && ! pCrvCoU0->IsAPoint())
pLoop->AddCurve( Release( pCrvCoU0)) ;
- // seconda curva isoparametrica in V con U=m_nSpanU
+ // seconda curva isoparametrica in V con U=m_nSpanU
PtrOwner pCrvCoV1( GetCurveOnV( m_nSpanU)) ;
if ( ! IsNull( pCrvCoV1) && ! pCrvCoV1->IsAPoint())
pLoop->AddCurve( Release( pCrvCoV1)) ;
- // terza curva isoparametrica in U con V=m_nSpanV invertita
+ // terza curva isoparametrica in U con V=m_nSpanV invertita
PtrOwner pCrvCoU1( GetCurveOnU( m_nSpanV)) ;
if ( ! IsNull( pCrvCoU1) && ! pCrvCoU1->IsAPoint()) {
pCrvCoU1->Invert() ;
pLoop->AddCurve( Release( pCrvCoU1)) ;
}
- // quarta curva isoparametrica in V con U=0 invertita
+ // quarta curva isoparametrica in V con U=0 invertita
PtrOwner pCrvCoV0( GetCurveOnV( 0)) ;
if ( ! IsNull( pCrvCoV0) && ! pCrvCoV0->IsAPoint()) {
pCrvCoV0->Invert() ;
pLoop->AddCurve( Release( pCrvCoV0)) ;
}
- // se loop chiuso lo restituisco, altrimenti errore
+ // se loop chiuso lo restituisco, altrimenti errore
return ( pLoop->IsClosed() ? Release( pLoop) : nullptr) ;
}
- // altrimenti trimmata, per ora non gestita
- else
- return nullptr ;
+ // la superficie è trimmata, quindi devo cercare nei vari chunck il loop corrispondente
+ else {
+ if ( nLoop > m_pTrimReg->GetChunkCount())
+ return nullptr ;
+ else {
+ int nLoopCount = 0 ;
+ int nChunck = 0, nLoopLoc = 0;
+ INTVECTOR nLoopCountPerChunck ;
+ for ( int i = 0 ; i < m_pTrimReg->GetChunkCount() && nLoopCount != nLoop ; ++ i) {
+ int nLoopCountLoc = 0 ;
+ for ( int j = 0 ; j < m_pTrimReg->GetLoopCount( i) ; ++ j) {
+ ++ nLoopCountLoc ;
+ ++ nLoopCount ;
+ if ( nLoopCount != nLoop ) {
+ nChunck = i ;
+ nLoopLoc = j ;
+ break ;
+ }
+ }
+ nLoopCountPerChunck.push_back( nLoopCountLoc) ;
+ }
+ if ( nLoopCount < nLoop )
+ return nullptr ;
+ PtrOwner pLoop( GetBasicCurveComposite( m_pTrimReg->GetLoop( nChunck, nLoopLoc))) ;
+ return Release( pLoop) ;
+ }
+ }
}
//----------------------------------------------------------------------------
@@ -1473,21 +1498,22 @@ SurfBezier::GetAuxSurf( void) const
return m_pSTM ;
// costruttore della superficie
+
Tree Tree( this, true) ;
Tree.BuildTree() ;
- POLYLINEVECTOR vPL ;
- Tree.GetPolygons( vPL) ;
+ vector vvPL ;
+ Tree.GetPolygons( vvPL) ;
PtrOwner pSrfTm( CreateBasicSurfTriMesh()) ;
StmFromTriangleSoup stmSoup ;
if ( ! stmSoup.Start())
return nullptr ;
// prendo i punti di ogni polyline dell'albero, li triangolo e li porto in 3d
- for ( PolyLine i : vPL) {
+ for ( POLYLINEVECTOR vPL : vvPL) {
PNTVECTOR vPnt ;
INTVECTOR vTria ;
Triangulate Tri ;
- if ( ! Tri.Make( i, vPnt, vTria))
+ if ( ! Tri.Make( vPL, vPnt, vTria))
return nullptr ;
// porto i punti in 3d
diff --git a/SurfBezier.h b/SurfBezier.h
index 12149f8..6cfc9e2 100644
--- a/SurfBezier.h
+++ b/SurfBezier.h
@@ -83,7 +83,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
{ return SetControlPoint( GetInd( nIndU, nIndV), ptCtrl, dW) ; }
bool SetControlPoint( int nInd, const Point3d& ptCtrl, double dW) override ;
bool SetTrimRegion( const ISurfFlatRegion& sfrTrimReg) override ;
- bool GetTrimRegion( ISurfFlatRegion& sfrTrimReg) override ;
+ SurfFlatRegion* GetTrimRegion( void) const override ;
bool GetInfo( int& nDegU, int& nDegV, int& nSpanU, int& nSpanV, bool& bIsRat, bool& bTrimmed) const override ;
const Point3d& GetControlPoint( int nIndU, int nIndV, bool* pbOk) const override
{ return GetControlPoint( GetInd( nIndU, nIndV), pbOk) ; }
diff --git a/Tree.cpp b/Tree.cpp
index 3ef45ea..21a8aa1 100644
--- a/Tree.cpp
+++ b/Tree.cpp
@@ -18,15 +18,19 @@
#include "SurfBezier.h"
#include "GeoConst.h"
#include "CurveLine.h"
+#include "CurveComposite.h"
+#include "SurfFlatRegion.h"
+#include "IntersLineLine.h"
#include "/EgtDev/Include/EGkPolyLine.h"
#include "/EgtDev/Include/EGkDistPointCurve.h"
+#include "/EgtDev/Include/EGkCurve.h"
using namespace std ;
//----------------------------------------------------------------------------
Cell::Cell( void)
: m_nId( -1),m_nTop ( -2), m_nBottom( -2), m_nLeft( -2), m_nRight ( -2), m_nParent( -2), m_nDepth( 0),
- m_nChild1( -2), m_nChild2( -2), m_ptPbl( ORIG), m_ptPtr(), m_bProcessed ( false) , m_bSplitVert ( true)
+ m_nChild1( -2), m_nChild2( -2), m_nFlag( 0), m_nRightEdgeIn( 0), m_ptPbl(ORIG), m_ptPtr(), m_bProcessed(false), m_bSplitVert(true)
{
Point3d ptTr ( 1, 1) ;
m_ptPtr = ptTr ;
@@ -36,7 +40,7 @@ Cell::Cell( void)
//----------------------------------------------------------------------------
Cell::Cell( Point3d& ptBL, Point3d& ptTR)
: m_nId( -1),m_nTop ( -2), m_nBottom( -2), m_nLeft( -2), m_nRight ( -2), m_nParent( -2), m_nDepth( 0),
- m_nChild1( -2), m_nChild2( -2), m_ptPbl( ptBL), m_ptPtr( ptTR), m_bProcessed ( false) , m_bSplitVert ( true)
+ m_nChild1( -2), m_nChild2( -2), m_nFlag( 0), m_nRightEdgeIn( 0), m_ptPbl(ptBL), m_ptPtr(ptTR), m_bProcessed(false), m_bSplitVert(true)
{}
@@ -87,7 +91,8 @@ Tree::~Tree( void)
}
//----------------------------------------------------------------------------
-void Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches)
+void
+Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches)
{
m_pSrfBz = pSrfBz ;
// le coordinate delle celle sono nello spazio parametrico
@@ -101,7 +106,56 @@ void Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches)
m_bBilinear = true ;
if ( nSpanU * nSpanV != 1)
m_bMulti = true ;
-
+ // recupero i loop di trim e li divido per chunk
+ if ( m_bTrimmed) {
+ int nLoop = 0 ;
+ INTVECTOR vChunk ;
+ // dalla superficie recupero un vettore con i loop di trim
+ //
+ //PtrOwner pLoop( GetBasicCurveComposite( m_pSrfBz->GetLoop( nLoop))) ;
+ //while ( ! IsNull( pLoop) && pLoop->IsValid()) {
+ // if ( nLoop == 0) {
+ // m_vLoop.push_back( Release( pLoop)) ;
+ // vChunck.push_back( nLoop) ;
+ // ++ nLoop ;
+ // }
+ // else {
+ // // se il loop corrente è contenuto nel precedente e sono girati in verso opposto, allora lo aggiungo allo stesso chunk
+ // if ( ) {
+
+ // }
+ // // salvo il precedente chunk e creo un nuovo chunk
+ // else {
+ // m_vChunk.push_back( vChunk) ;
+ // vChunk.clear() ;
+ // vChunk.push_back( nLoop) ;
+ // }
+ // ++ nLoop ;
+ // PtrOwner pLoop( GetBasicCurveComposite( m_pSrfBz->GetLoop( nLoop))) ;
+ // }
+ //}
+
+ // recupero la superficie di trim per avere accesso diretto ai loop e mantenendo le informazioni sui chunk
+
+ Frame3d frSurf ;
+ //const SurfFlatRegion* pTrimReg_( m_pSrfBz->GetTrimRegion()) ;
+ //PtrOwner pTrimReg( pTrimReg_->Clone()) ;
+ PtrOwner pTrimReg( m_pSrfBz->GetTrimRegion()->Clone()) ;
+ for ( int i = 0 ; i < pTrimReg->GetChunkCount() ; ++ i) {
+ PtrOwner pChunk( pTrimReg->CloneChunk( i)) ;
+ pChunk->Scale( frSurf, 1./ SBZ_TREG_COEFF, 1./ SBZ_TREG_COEFF, 1) ;
+ for ( int j = 0 ; j < pChunk->GetLoopCount( 0) ; ++ j) {
+ vChunk.push_back( nLoop) ;
+ // i chunk della superficie orignale non possono avere dei sub chunk
+ PtrOwner pLoop (pChunk->GetLoop(0, j)) ;
+ m_vLoop.emplace_back( Release( pLoop )) ;
+ m_mChunk[nLoop] = i ;
+ ++ nLoop ;
+ }
+ m_vChunk.push_back( vChunk) ;
+ vChunk.clear() ;
+ }
+ }
// salvo i vertici 3d della cella root
Point3d ptBottom ( 0, 0) ;
Point3d ptTop( nSpanU, nSpanV) ;
@@ -320,346 +374,390 @@ Tree::Split( int nId)
}
//----------------------------------------------------------------------------
-bool Tree::BuildTree( double dLinTol_, double dSideMin, double dSideMax)
+bool
+Tree::BuildTree( double dLinTol_, double dSideMin, double dSideMax)
{
- // suddivido lo spazio parametrico con divisioni a metà su uno dei due parametri
- int nCToSplit = -1 ;
- double dLinTol = 0.2 ;
- //double dSideMin = 1 ;
- if ( ! m_bTrimmed) {
- if ( ! m_bBilinear) {
- while ( nCToSplit != -2 && m_mTree[nCToSplit].IsProcessed() == false) {
- // controllo che la cella non sia già stata preliminarmente splittata
- if ( m_mTree[nCToSplit].IsLeaf()) {
- // calcolo in quale direzione ho più curvatura
- // ptP00P10 è un punto tra P00 e P10
- double dCurvU = 0, dCurvV = 0 ;
- double dLenParU = m_mTree[nCToSplit].GetTopRight().x - m_mTree[nCToSplit].GetBottomLeft().x ;
- double dLenParV = m_mTree[nCToSplit].GetTopRight().y - m_mTree[nCToSplit].GetBottomLeft().y ;
- if ( dLenParU <= 1. / m_nDegV || dLenParV <= 1. / m_nDegU) {
- double dU = ( m_mTree[nCToSplit].GetTopRight().x + m_mTree[nCToSplit].GetBottomLeft().x) / 2 ;
- double dV = ( m_mTree[nCToSplit].GetTopRight().y + m_mTree[nCToSplit].GetBottomLeft().y) / 2 ;
- double dULoc = 0.5, dVLoc = 0.5 ;
- Point3d ptPSrf, ptP00P10, ptP10P11, ptP11P01, ptP01P00 ;
- m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ;
- m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00P10) ;
- m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10P11) ;
- m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11P01) ;
- m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01P00) ;
- Point3d ptV = ( 1 - dULoc) * ptP00P10 + dULoc * ptP11P01 ;
- Point3d ptU = ( 1 - dVLoc) * ptP10P11 + dVLoc * ptP01P00 ;
- dCurvV = Dist( ptV, ptPSrf) ;
- dCurvU = Dist( ptU, ptPSrf) ;
- }
- // faccio un'analisi più fine della curvatura se almeno il grado di una curva di uno dei due parametri è alto e
- // se sto ancora guardando una cella abbastanza grande
- else{
- Point3d ptPSrf, ptP00P10, ptP10P11, ptP11P01, ptP01P00, ptPSrfMid;
- double dStep = 1. / m_nDegU ;
- for ( double k = dStep ; k < 1 ; k = k + dStep) {
- double dU = k * m_mTree[nCToSplit].GetTopRight().x + ( 1 - k) * m_mTree[nCToSplit].GetBottomLeft().x ;
- double dV = ( m_mTree[nCToSplit].GetTopRight().y + m_mTree[nCToSplit].GetBottomLeft().y) / 2 ;
- m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ;
- if ( k == 0.5)
- ptPSrfMid = ptPSrf ;
- m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00P10) ;
- m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11P01) ;
- CurveLine clV ;
- clV.Set( ptP00P10, ptP11P01) ;
- DistPointCurve dpc( ptPSrf, clV) ;
- double dDist ;
- dpc.GetDist( dDist) ;
- dCurvV = max( dCurvV, dDist) ;
- }
- dStep = 1. / m_nDegV ;
- for ( double k = dStep ; k < 1 ; k = k + dStep) {
- double dU = ( m_mTree[nCToSplit].GetTopRight().x + m_mTree[nCToSplit].GetBottomLeft().x) / 2 ;
- double dV = k * m_mTree[nCToSplit].GetTopRight().y + ( 1 - k) * m_mTree[nCToSplit].GetBottomLeft().y ;
- if ( k == 0.5)
- ptPSrf = ptPSrfMid ;
- else
- m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ;
- m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10P11) ;
- m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01P00) ;
- CurveLine clU ;
- clU.Set( ptP01P00, ptP10P11) ;
- DistPointCurve dpc( ptPSrf, clU) ;
- double dDist ;
- dpc.GetDist( dDist) ;
- dCurvU = max( dCurvU, dDist) ;
- }
- }
+ //int nCToSplit = -1 ;
+ //celle 0,1
+ m_mTree[-1].SetSplitDirVert( true) ;
+ Split( -1) ;
+ //celle 2,3
+ m_mTree[0].SetSplitDirVert( false) ;
+ Split( 0) ;
+ //celle 4,5
+ m_mTree[2].SetSplitDirVert( false) ;
+ Split( 2) ;
+ //celle 6,7
+ m_mTree[3].SetSplitDirVert( true) ;
+ Split( 3) ;
+ //celle 8,9
+ m_mTree[1].SetSplitDirVert( false) ;
+ Split( 1) ;
+ //celle 10,11
+ m_mTree[8].SetSplitDirVert( true) ;
+ Split( 8) ;
+ //celle 12,13
+ m_mTree[9].SetSplitDirVert( false) ;
+ Split( 9) ;
+ m_vnLeaves.push_back( 4) ;
+ m_vnLeaves.push_back( 5) ;
+ m_vnLeaves.push_back( 6) ;
+ m_vnLeaves.push_back( 7) ;
+ m_vnLeaves.push_back( 10) ;
+ m_vnLeaves.push_back( 11) ;
+ m_vnLeaves.push_back( 12) ;
+ m_vnLeaves.push_back( 13) ;
- // per lo split scelgo la direzione che è più vicina alla superficie originale nel punto di maggior distanza
- // misura approssimativa della curvatura in una direzione
- bool bVert ;
- if ( dCurvV > dCurvU) {
- // lungo la direzione V ho una curvatura maggiore
- bVert = false ;
- }
- else {
- // lungo la direzione U ho una curvatura maggiore
- bVert = true ;
- }
- m_mTree[nCToSplit].SetSplitDirVert( bVert) ;
- Point3d ptP00, ptP10, ptP11, ptP01 ;
- // distanza reale tra i vertici della cella
- ptP00 = m_mVert[nCToSplit][0] ;
- ptP10 = m_mVert[nCToSplit][1] ;
- ptP11 = m_mVert[nCToSplit][2] ;
- ptP01 = m_mVert[nCToSplit][3] ;
- double dLen0 = Dist( ptP00, ptP10) ;
- double dLen1 = Dist( ptP10, ptP11) ;
- double dLen2 = Dist( ptP01, ptP11) ;
- double dLen3 = Dist( ptP00, ptP01) ;
- // verifico che la cella sia da splittare e che eventualmente sia abbastanza grande da poterlo fare
- double dSideMinVal = 0, dSideMaxVal = 0 ;
- if ( bVert) {
- if ( dLen0 != 0 && dLen2 != 0)
- dSideMinVal = min( dLen0, dLen2) ;
- else
- dSideMinVal = max( dLen0, dLen2) ;
- }
- else {
- if ( dLen1 != 0 && dLen3 != 0)
- dSideMinVal = min( dLen1, dLen3) ;
- else
- dSideMinVal = max( dLen1, dLen3) ;
- }
- // calcolo le diagonali per controllare la dimensione massima dei triangoli in cui dividerei la cella
- dSideMaxVal = max( Dist( ptP00, ptP11), Dist( ptP10, ptP01)) ;
-
- // se la cella è abbastanza grande da poter essere divisa ancora, calcolo l'errore di approssimazione
- bool bSplit = false ;
- if ( dSideMinVal / 2 >= dSideMin && dSideMaxVal < dSideMax && ( dCurvV > dLinTol || dCurvU > dLinTol)) {
- CurveLine cl0010, cl0001, cl1011, cl0111 ;
- // U=0
- cl0010.Set( ptP00, ptP10) ;
- // U=1
- cl0111.Set( ptP01, ptP11) ;
- Point3d pt0010, pt0111, ptBz0, ptBz1, ptBzV ;
- int nFlag ;
- CurveLine clV ;
- // determino quanti Step fare per ogni direzione parametrica
- double dDimU = ( dLen0 >= dLen2 ? dLen0 / m_vDim[0] : dLen2 / m_vDim[2]) ;
- dDimU = ( dDimU > 1 ? 1 : dDimU) ;
- double dDimV = ( dLen1 >= dLen3 ? dLen1 / m_vDim[1] : dLen3 / m_vDim[3]) ;
- dDimV = ( dDimV > 1 ? 1 : dDimV) ;
- // numero di Step per campionare la superficie nelle due direzioni parametriche
- int nStepsU = int( 51 * dDimU + 5 * ( 1 - dDimU)) ;
- int nStepsV = int( 51 * dDimV + 5 * ( 1 - dDimV)) ;
- for ( int u = 0 ; u < nStepsU && ! bSplit ; ++ u) {
- double dU = double ( u) / double ( nStepsU - 1) ;
- double dULoc = ( 1 - dU) * m_mTree[nCToSplit].GetBottomLeft().x + dU * m_mTree[nCToSplit].GetTopRight().x ;
- if ( ! m_pSrfBz->GetPointD1D2( dULoc, m_mTree[nCToSplit].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz0) ||
- ! m_pSrfBz->GetPointD1D2( dULoc, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz1))
- return false ;
- DistPointCurve dpc0010( ptBz0, cl0010) ;
- DistPointCurve dpc0111( ptBz1, cl0111) ;
- dpc0010.GetMinDistPoint( 0, pt0010, nFlag) ;
- dpc0111.GetMinDistPoint( 0, pt0111, nFlag) ;
- clV.Set( pt0010, pt0111) ;
- for ( int v = 0 ; v < nStepsV ; ++ v) {
- double dV = double ( v) / double ( nStepsV - 1) ;
- double dVLoc = ( 1 - dV) * m_mTree[nCToSplit].GetBottomLeft().y + dV * m_mTree[nCToSplit].GetTopRight().y ;
- if ( ! m_pSrfBz->GetPointD1D2( dULoc, dVLoc, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBzV))
- return false ;
- DistPointCurve dpc( ptBzV, clV) ;
- // distanza di approssimazione locale
- double dDist ;
- dpc.GetDist( dDist) ;
- if ( dDist > dLinTol) {
- bSplit = true ;
- break ;
- }
- }
- }
- }
-
- if ( bSplit || dSideMaxVal > dSideMax) {
- m_mTree[nCToSplit].SetSplitDirVert( bVert) ;
- // effettuo lo split
- Split( nCToSplit) ;
-
- // procedo con lo split del Child1
- nCToSplit = m_mTree[nCToSplit].m_nChild1 ;
- }
- else {
- // sono arrivato ad una cella Leaf, quindi salvo la cella
- m_vnLeaves.push_back( nCToSplit) ;
- m_mTree[nCToSplit].Processed() ;
- // risalgo i parent finché non trovo il primo Child2 da processare
- nCToSplit = m_mTree[nCToSplit].m_nParent ;
- if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
- m_mTree[nCToSplit].Processed() ;
- while ( m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) {
- if ( m_mTree[nCToSplit].m_nParent != -2)
- nCToSplit = m_mTree[nCToSplit].m_nParent ;
- if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
- m_mTree[nCToSplit].Processed() ;
- if ( nCToSplit == -1 && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
- break ;
- }
- nCToSplit = m_mTree[nCToSplit].m_nChild2 ;
- }
- }
- else {
- nCToSplit = m_mTree[nCToSplit].m_nChild1 ;
- }
- }
- Balance() ; // da implementare quando dividerò ad un parametro a scelta e non a metÃ
- }
- // bilineare
- else {
- while ( nCToSplit != -2 && m_mTree[nCToSplit].IsProcessed() == false) {
- if ( m_mTree[nCToSplit].IsLeaf()) {
- // vertici della cella
- Point3d ptP00, ptP10, ptP11, ptP01 ;
- ptP00 = m_mVert[nCToSplit][0] ;
- ptP10 = m_mVert[nCToSplit][1] ;
- ptP11 = m_mVert[nCToSplit][2] ;
- ptP01 = m_mVert[nCToSplit][3] ;
- // distanza reale tra i vertici della cella
- double dLen0 = Dist( ptP00, ptP10) ;
- double dLen1 = Dist( ptP10, ptP11) ;
- double dLen2 = Dist( ptP01, ptP11) ;
- double dLen3 = Dist( ptP00, ptP01) ;
-
- bool bVert = false ;
- // calcolo in quale direzione è meglio dividere in base allo stretch
- Point3d ptPSrfU, ptPSrfV ;
- double dU = 0, dV = 0 ;
- double dDistU = 0, dDistV = 0 ;
- PNTVECTOR vPtU, vPtV ;
- if ( ! m_bMulti) {
- if ( max(dLen0, dLen2) > max(dLen1, dLen3)) {
- bVert = true ;
- }
- else {
- bVert = false ;
- }
- }
- else {
- for ( double i = 0.25 ; i < 1 ; i = i + 0.25 ) {
- dU = ( 1 - i) * m_mTree[nCToSplit].GetBottomLeft().x + i * m_mTree[nCToSplit].GetTopRight().x ;
- dV = ( 1 - i) * m_mTree[nCToSplit].GetBottomLeft().y + i * m_mTree[nCToSplit].GetTopRight().y ;
- double dVLoc = ( m_mTree[nCToSplit].GetBottomLeft().y + m_mTree[nCToSplit].GetTopRight().y) / 2 ;
- double dULoc = ( m_mTree[nCToSplit].GetBottomLeft().x + m_mTree[nCToSplit].GetTopRight().x) / 2 ;
- m_pSrfBz->GetPointD1D2( dU, dVLoc, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrfU) ;
- m_pSrfBz->GetPointD1D2( dULoc, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrfV) ;
- vPtU.push_back( ptPSrfU) ;
- vPtV.push_back( ptPSrfV) ;
- }
- // devo guardare se i tre punti in vPtU e vPtV sono allineati
- CurveLine clU, clV;
- clU.Set(vPtU[0], vPtU[1]) ;
- clV.Set(vPtV[0], vPtV[1]) ;
- DistPointCurve dpcU( vPtU[2], clU, false) ;
- DistPointCurve dpcV( vPtV[2], clV, false) ;
- dpcU.GetDist( dDistU) ;
- dpcV.GetDist( dDistV) ;
- if ( dDistU > dDistV) {
- bVert = true ;
- }
- else {
- bVert = false ;
- }
- }
-
- // verifico che la cella sia abbastanza grande da poter essere splittata
- double dSideMinVal = 0, dSideMaxVal = 0 ;
- if ( bVert) {
- if ( dLen0 != 0 && dLen2 != 0)
- dSideMinVal = min( dLen0, dLen2) ;
- else
- dSideMinVal = max( dLen0, dLen2) ;
- }
- else {
- if ( dLen1 != 0 && dLen3 != 0)
- dSideMinVal = min( dLen1, dLen3) ;
- else
- dSideMinVal = max( dLen1, dLen3) ;
- }
- // calcolo le diagonali per controllare la dimensione massima dei triangoli in cui dividerei la cella
- dSideMaxVal = max( Dist( ptP00, ptP11), Dist( ptP10, ptP01)) ;
-
-
- double dErr = 0 ;
- if ( m_bMulti) {
- Point3d ptPSrf ;
- Plane3d plAppr ;
- if ( ! AreSamePointApprox( ptP00, ptP10) && ! AreSamePointApprox( ptP00, ptP01))
- plAppr.Set( ptP00, ( ptP00 - ptP01) ^ ( ptP00 - ptP10)) ;
- else if ( AreSamePointApprox( ptP00, ptP10)) {
- plAppr.Set( ptP01, ( ptP00 - ptP01) ^ ( ptP01 - ptP11)) ;
- }
- else if ( AreSamePointApprox( ptP00, ptP01)) {
- plAppr.Set( ptP10, ( ptP10 - ptP11) ^ ( ptP00 - ptP10)) ;
- }
- for ( double i = 0.25 ; i < 1 ; i = i + 0.25) {
- for ( double j = 0.25 ; j < 1 ; j = j + 0.25) {
- double dU = ( 1 - i) * m_mTree[nCToSplit].GetTopRight().x + i * m_mTree[nCToSplit].GetBottomLeft().x ;
- double dV = ( 1 - j) * m_mTree[nCToSplit].GetTopRight().y + j * m_mTree[nCToSplit].GetBottomLeft().y ;
- m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ;
- dErr = max( abs( DistPointPlane( ptPSrf, plAppr)), dErr) ;
- }
- }
- }
- else {
- dErr = 1. / 4. * ( (ptP00 - ptP01) + (ptP11 - ptP10)).Len() ;
- }
- // se la cella è abbastanza grande da poter essere divisa ancora e devo approssimare meglio, la divido
- if ( dSideMinVal / 2 >= dSideMin && dSideMaxVal < dSideMax && dErr > dLinTol) {
- m_mTree[nCToSplit].SetSplitDirVert( bVert) ;
- // effettuo lo split
- Split( nCToSplit) ;
-
- // procedo con lo split del Child1
- nCToSplit = m_mTree[nCToSplit].m_nChild1 ;
- }
- else {
- // sono arrivato ad una cella Leaf, quindi salvo la cella
- m_vnLeaves.push_back( nCToSplit) ;
- m_mTree[nCToSplit].Processed() ;
- // risalgo i parent finché non trovo il primo Child2 da processare
- nCToSplit = m_mTree[nCToSplit].m_nParent ;
- if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
- m_mTree[nCToSplit].Processed() ;
- while ( m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) {
- if ( m_mTree[nCToSplit].m_nParent != -2)
- nCToSplit = m_mTree[nCToSplit].m_nParent ;
- if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
- m_mTree[nCToSplit].Processed() ;
- if ( nCToSplit == -1 && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
- break ;
- }
- nCToSplit = m_mTree[nCToSplit].m_nChild2 ;
- }
- }
- else {
- nCToSplit = m_mTree[nCToSplit].m_nChild1 ;
- }
- }
- }
- }
- // se la superficie è trimmata
- else {
- SurfFlatRegion sfrTrimReg ;
- }
return true ;
}
+////----------------------------------------------------------------------------
+//bool
+//Tree::BuildTree( double dLinTol_, double dSideMin, double dSideMax)
+//{
+// // suddivido lo spazio parametrico con divisioni a metà su uno dei due parametri
+// int nCToSplit = -1 ;
+// double dLinTol = 0.2 ;
+// //double dSideMin = 1 ;
+// if ( ! m_bTrimmed) {
+// if ( ! m_bBilinear) {
+// while ( nCToSplit != -2 && m_mTree[nCToSplit].IsProcessed() == false) {
+// // controllo che la cella non sia già stata preliminarmente splittata
+// if ( m_mTree[nCToSplit].IsLeaf()) {
+// // calcolo in quale direzione ho più curvatura
+// // ptP00P10 è un punto tra P00 e P10
+// double dCurvU = 0, dCurvV = 0 ;
+// double dLenParU = m_mTree[nCToSplit].GetTopRight().x - m_mTree[nCToSplit].GetBottomLeft().x ;
+// double dLenParV = m_mTree[nCToSplit].GetTopRight().y - m_mTree[nCToSplit].GetBottomLeft().y ;
+// if ( dLenParU <= 1. / m_nDegV || dLenParV <= 1. / m_nDegU) {
+// double dU = ( m_mTree[nCToSplit].GetTopRight().x + m_mTree[nCToSplit].GetBottomLeft().x) / 2 ;
+// double dV = ( m_mTree[nCToSplit].GetTopRight().y + m_mTree[nCToSplit].GetBottomLeft().y) / 2 ;
+// double dULoc = 0.5, dVLoc = 0.5 ;
+// Point3d ptPSrf, ptP00P10, ptP10P11, ptP11P01, ptP01P00 ;
+// m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ;
+// m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00P10) ;
+// m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10P11) ;
+// m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11P01) ;
+// m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01P00) ;
+// Point3d ptV = ( 1 - dULoc) * ptP00P10 + dULoc * ptP11P01 ;
+// Point3d ptU = ( 1 - dVLoc) * ptP10P11 + dVLoc * ptP01P00 ;
+// dCurvV = Dist( ptV, ptPSrf) ;
+// dCurvU = Dist( ptU, ptPSrf) ;
+// }
+// // faccio un'analisi più fine della curvatura se almeno il grado di una curva di uno dei due parametri è alto e
+// // se sto ancora guardando una cella abbastanza grande
+// else{
+// Point3d ptPSrf, ptP00P10, ptP10P11, ptP11P01, ptP01P00, ptPSrfMid;
+// double dStep = 1. / m_nDegU ;
+// for ( double k = dStep ; k < 1 ; k = k + dStep) {
+// double dU = k * m_mTree[nCToSplit].GetTopRight().x + ( 1 - k) * m_mTree[nCToSplit].GetBottomLeft().x ;
+// double dV = ( m_mTree[nCToSplit].GetTopRight().y + m_mTree[nCToSplit].GetBottomLeft().y) / 2 ;
+// m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ;
+// if ( k == 0.5)
+// ptPSrfMid = ptPSrf ;
+// m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00P10) ;
+// m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11P01) ;
+// CurveLine clV ;
+// clV.Set( ptP00P10, ptP11P01) ;
+// DistPointCurve dpc( ptPSrf, clV) ;
+// double dDist ;
+// dpc.GetDist( dDist) ;
+// dCurvV = max( dCurvV, dDist) ;
+// }
+// dStep = 1. / m_nDegV ;
+// for ( double k = dStep ; k < 1 ; k = k + dStep) {
+// double dU = ( m_mTree[nCToSplit].GetTopRight().x + m_mTree[nCToSplit].GetBottomLeft().x) / 2 ;
+// double dV = k * m_mTree[nCToSplit].GetTopRight().y + ( 1 - k) * m_mTree[nCToSplit].GetBottomLeft().y ;
+// if ( k == 0.5)
+// ptPSrf = ptPSrfMid ;
+// else
+// m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ;
+// m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10P11) ;
+// m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01P00) ;
+// CurveLine clU ;
+// clU.Set( ptP01P00, ptP10P11) ;
+// DistPointCurve dpc( ptPSrf, clU) ;
+// double dDist ;
+// dpc.GetDist( dDist) ;
+// dCurvU = max( dCurvU, dDist) ;
+// }
+// }
+//
+// // per lo split scelgo la direzione che è più vicina alla superficie originale nel punto di maggior distanza
+// // misura approssimativa della curvatura in una direzione
+// bool bVert ;
+// if ( dCurvV > dCurvU) {
+// // lungo la direzione V ho una curvatura maggiore
+// bVert = false ;
+// }
+// else {
+// // lungo la direzione U ho una curvatura maggiore
+// bVert = true ;
+// }
+// m_mTree[nCToSplit].SetSplitDirVert( bVert) ;
+// Point3d ptP00, ptP10, ptP11, ptP01 ;
+// // distanza reale tra i vertici della cella
+// ptP00 = m_mVert[nCToSplit][0] ;
+// ptP10 = m_mVert[nCToSplit][1] ;
+// ptP11 = m_mVert[nCToSplit][2] ;
+// ptP01 = m_mVert[nCToSplit][3] ;
+// double dLen0 = Dist( ptP00, ptP10) ;
+// double dLen1 = Dist( ptP10, ptP11) ;
+// double dLen2 = Dist( ptP01, ptP11) ;
+// double dLen3 = Dist( ptP00, ptP01) ;
+// // verifico che la cella sia da splittare e che eventualmente sia abbastanza grande da poterlo fare
+// double dSideMinVal = 0, dSideMaxVal = 0 ;
+// if ( bVert) {
+// if ( dLen0 != 0 && dLen2 != 0)
+// dSideMinVal = min( dLen0, dLen2) ;
+// else
+// dSideMinVal = max( dLen0, dLen2) ;
+// }
+// else {
+// if ( dLen1 != 0 && dLen3 != 0)
+// dSideMinVal = min( dLen1, dLen3) ;
+// else
+// dSideMinVal = max( dLen1, dLen3) ;
+// }
+// // calcolo le diagonali per controllare la dimensione massima dei triangoli in cui dividerei la cella
+// dSideMaxVal = max( Dist( ptP00, ptP11), Dist( ptP10, ptP01)) ;
+//
+// // se la cella è abbastanza grande da poter essere divisa ancora, calcolo l'errore di approssimazione
+// bool bSplit = false ;
+// if ( dSideMinVal / 2 >= dSideMin && dSideMaxVal < dSideMax && ( dCurvV > dLinTol || dCurvU > dLinTol)) {
+// CurveLine cl0010, cl0001, cl1011, cl0111 ;
+// // U=0
+// cl0010.Set( ptP00, ptP10) ;
+// // U=1
+// cl0111.Set( ptP01, ptP11) ;
+// Point3d pt0010, pt0111, ptBz0, ptBz1, ptBzV ;
+// int nFlag ;
+// CurveLine clV ;
+// // determino quanti Step fare per ogni direzione parametrica
+// double dDimU = ( dLen0 >= dLen2 ? dLen0 / m_vDim[0] : dLen2 / m_vDim[2]) ;
+// dDimU = ( dDimU > 1 ? 1 : dDimU) ;
+// double dDimV = ( dLen1 >= dLen3 ? dLen1 / m_vDim[1] : dLen3 / m_vDim[3]) ;
+// dDimV = ( dDimV > 1 ? 1 : dDimV) ;
+// // numero di Step per campionare la superficie nelle due direzioni parametriche
+// int nStepsU = int( 51 * dDimU + 5 * ( 1 - dDimU)) ;
+// int nStepsV = int( 51 * dDimV + 5 * ( 1 - dDimV)) ;
+// for ( int u = 0 ; u < nStepsU && ! bSplit ; ++ u) {
+// double dU = double ( u) / double ( nStepsU - 1) ;
+// double dULoc = ( 1 - dU) * m_mTree[nCToSplit].GetBottomLeft().x + dU * m_mTree[nCToSplit].GetTopRight().x ;
+// if ( ! m_pSrfBz->GetPointD1D2( dULoc, m_mTree[nCToSplit].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz0) ||
+// ! m_pSrfBz->GetPointD1D2( dULoc, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz1))
+// return false ;
+// DistPointCurve dpc0010( ptBz0, cl0010) ;
+// DistPointCurve dpc0111( ptBz1, cl0111) ;
+// dpc0010.GetMinDistPoint( 0, pt0010, nFlag) ;
+// dpc0111.GetMinDistPoint( 0, pt0111, nFlag) ;
+// clV.Set( pt0010, pt0111) ;
+// for ( int v = 0 ; v < nStepsV ; ++ v) {
+// double dV = double ( v) / double ( nStepsV - 1) ;
+// double dVLoc = ( 1 - dV) * m_mTree[nCToSplit].GetBottomLeft().y + dV * m_mTree[nCToSplit].GetTopRight().y ;
+// if ( ! m_pSrfBz->GetPointD1D2( dULoc, dVLoc, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBzV))
+// return false ;
+// DistPointCurve dpc( ptBzV, clV) ;
+// // distanza di approssimazione locale
+// double dDist ;
+// dpc.GetDist( dDist) ;
+// if ( dDist > dLinTol) {
+// bSplit = true ;
+// break ;
+// }
+// }
+// }
+// }
+//
+// if ( bSplit || dSideMaxVal > dSideMax) {
+// m_mTree[nCToSplit].SetSplitDirVert( bVert) ;
+// // effettuo lo split
+// Split( nCToSplit) ;
+//
+// // procedo con lo split del Child1
+// nCToSplit = m_mTree[nCToSplit].m_nChild1 ;
+// }
+// else {
+// // sono arrivato ad una cella Leaf, quindi salvo la cella
+// m_vnLeaves.push_back( nCToSplit) ;
+// m_mTree[nCToSplit].SetProcessed() ;
+// // risalgo i parent finché non trovo il primo Child2 da processare
+// nCToSplit = m_mTree[nCToSplit].m_nParent ;
+// if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
+// m_mTree[nCToSplit].SetProcessed() ;
+// while ( m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) {
+// if ( m_mTree[nCToSplit].m_nParent != -2)
+// nCToSplit = m_mTree[nCToSplit].m_nParent ;
+// if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
+// m_mTree[nCToSplit].SetProcessed() ;
+// if ( nCToSplit == -1 && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
+// break ;
+// }
+// nCToSplit = m_mTree[nCToSplit].m_nChild2 ;
+// }
+// }
+// else {
+// nCToSplit = m_mTree[nCToSplit].m_nChild1 ;
+// }
+// }
+// Balance() ; // da implementare quando dividerò ad un parametro a scelta e non a metÃ
+// }
+// // bilineare
+// else {
+// while ( nCToSplit != -2 && m_mTree[nCToSplit].IsProcessed() == false) {
+// if ( m_mTree[nCToSplit].IsLeaf()) {
+// // vertici della cella
+// Point3d ptP00, ptP10, ptP11, ptP01 ;
+// ptP00 = m_mVert[nCToSplit][0] ;
+// ptP10 = m_mVert[nCToSplit][1] ;
+// ptP11 = m_mVert[nCToSplit][2] ;
+// ptP01 = m_mVert[nCToSplit][3] ;
+// // distanza reale tra i vertici della cella
+// double dLen0 = Dist( ptP00, ptP10) ;
+// double dLen1 = Dist( ptP10, ptP11) ;
+// double dLen2 = Dist( ptP01, ptP11) ;
+// double dLen3 = Dist( ptP00, ptP01) ;
+//
+// bool bVert = false ;
+// // calcolo in quale direzione è meglio dividere in base allo stretch
+// Point3d ptPSrfU, ptPSrfV ;
+// double dU = 0, dV = 0 ;
+// double dDistU = 0, dDistV = 0 ;
+// PNTVECTOR vPtU, vPtV ;
+// if ( ! m_bMulti) {
+// if ( max(dLen0, dLen2) > max(dLen1, dLen3)) {
+// bVert = true ;
+// }
+// else {
+// bVert = false ;
+// }
+// }
+// else {
+// for ( double i = 0.25 ; i < 1 ; i = i + 0.25 ) {
+// dU = ( 1 - i) * m_mTree[nCToSplit].GetBottomLeft().x + i * m_mTree[nCToSplit].GetTopRight().x ;
+// dV = ( 1 - i) * m_mTree[nCToSplit].GetBottomLeft().y + i * m_mTree[nCToSplit].GetTopRight().y ;
+// double dVLoc = ( m_mTree[nCToSplit].GetBottomLeft().y + m_mTree[nCToSplit].GetTopRight().y) / 2 ;
+// double dULoc = ( m_mTree[nCToSplit].GetBottomLeft().x + m_mTree[nCToSplit].GetTopRight().x) / 2 ;
+// m_pSrfBz->GetPointD1D2( dU, dVLoc, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrfU) ;
+// m_pSrfBz->GetPointD1D2( dULoc, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrfV) ;
+// vPtU.push_back( ptPSrfU) ;
+// vPtV.push_back( ptPSrfV) ;
+// }
+// // devo guardare se i tre punti in vPtU e vPtV sono allineati
+// CurveLine clU, clV;
+// clU.Set(vPtU[0], vPtU[1]) ;
+// clV.Set(vPtV[0], vPtV[1]) ;
+// DistPointCurve dpcU( vPtU[2], clU, false) ;
+// DistPointCurve dpcV( vPtV[2], clV, false) ;
+// dpcU.GetDist( dDistU) ;
+// dpcV.GetDist( dDistV) ;
+// if ( dDistU > dDistV) {
+// bVert = true ;
+// }
+// else {
+// bVert = false ;
+// }
+// }
+//
+// // verifico che la cella sia abbastanza grande da poter essere splittata
+// double dSideMinVal = 0, dSideMaxVal = 0 ;
+// if ( bVert) {
+// if ( dLen0 != 0 && dLen2 != 0)
+// dSideMinVal = min( dLen0, dLen2) ;
+// else
+// dSideMinVal = max( dLen0, dLen2) ;
+// }
+// else {
+// if ( dLen1 != 0 && dLen3 != 0)
+// dSideMinVal = min( dLen1, dLen3) ;
+// else
+// dSideMinVal = max( dLen1, dLen3) ;
+// }
+// // calcolo le diagonali per controllare la dimensione massima dei triangoli in cui dividerei la cella
+// dSideMaxVal = max( Dist( ptP00, ptP11), Dist( ptP10, ptP01)) ;
+//
+//
+// double dErr = 0 ;
+// if ( m_bMulti) {
+// Point3d ptPSrf ;
+// Plane3d plAppr ;
+// if ( ! AreSamePointApprox( ptP00, ptP10) && ! AreSamePointApprox( ptP00, ptP01))
+// plAppr.Set( ptP00, ( ptP00 - ptP01) ^ ( ptP00 - ptP10)) ;
+// else if ( AreSamePointApprox( ptP00, ptP10)) {
+// plAppr.Set( ptP01, ( ptP00 - ptP01) ^ ( ptP01 - ptP11)) ;
+// }
+// else if ( AreSamePointApprox( ptP00, ptP01)) {
+// plAppr.Set( ptP10, ( ptP10 - ptP11) ^ ( ptP00 - ptP10)) ;
+// }
+// for ( double i = 0.25 ; i < 1 ; i = i + 0.25) {
+// for ( double j = 0.25 ; j < 1 ; j = j + 0.25) {
+// double dU = ( 1 - i) * m_mTree[nCToSplit].GetTopRight().x + i * m_mTree[nCToSplit].GetBottomLeft().x ;
+// double dV = ( 1 - j) * m_mTree[nCToSplit].GetTopRight().y + j * m_mTree[nCToSplit].GetBottomLeft().y ;
+// m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ;
+// dErr = max( abs( DistPointPlane( ptPSrf, plAppr)), dErr) ;
+// }
+// }
+// }
+// else {
+// dErr = 1. / 4. * ( (ptP00 - ptP01) + (ptP11 - ptP10)).Len() ;
+// }
+// // se la cella è abbastanza grande da poter essere divisa ancora e devo approssimare meglio, la divido
+// if ( dSideMinVal / 2 >= dSideMin && dSideMaxVal < dSideMax && dErr > dLinTol) {
+// m_mTree[nCToSplit].SetSplitDirVert( bVert) ;
+// // effettuo lo split
+// Split( nCToSplit) ;
+//
+// // procedo con lo split del Child1
+// nCToSplit = m_mTree[nCToSplit].m_nChild1 ;
+// }
+// else {
+// // sono arrivato ad una cella Leaf, quindi salvo la cella
+// m_vnLeaves.push_back( nCToSplit) ;
+// m_mTree[nCToSplit].SetProcessed() ;
+// // risalgo i parent finché non trovo il primo Child2 da processare
+// nCToSplit = m_mTree[nCToSplit].m_nParent ;
+// if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
+// m_mTree[nCToSplit].SetProcessed() ;
+// while ( m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) {
+// if ( m_mTree[nCToSplit].m_nParent != -2)
+// nCToSplit = m_mTree[nCToSplit].m_nParent ;
+// if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
+// m_mTree[nCToSplit].SetProcessed() ;
+// if ( nCToSplit == -1 && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
+// break ;
+// }
+// nCToSplit = m_mTree[nCToSplit].m_nChild2 ;
+// }
+// }
+// else {
+// nCToSplit = m_mTree[nCToSplit].m_nChild1 ;
+// }
+// }
+// }
+// }
+// // se la superficie è trimmata
+// else {
+// SurfFlatRegion sfrTrimReg ;
+// }
+// return true ;
+//}
+
//----------------------------------------------------------------------------
-void Tree::Balance()
+void
+Tree::Balance()
{
//for ( int i : vCheck ) {
// // non ancora implementato
// // rendo il tree balanced : ogni foglia deve avere una profondità di +- 1 rispetto alle foglie adiacenti.
//}
+
+ // al momento il problema viene bypassato in fase di generazione dei poligoni, considerando per ogni cella, oltre ai propri vertici
+ // i vertici dei vicini che giacciono sui suoi lati
}
//----------------------------------------------------------------------------
-void Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const
+void
+Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const
{
if ( (int) vTopNeighs.size() == 0) {
if ( m_mTree.at(nId).m_nTop == -2)
@@ -738,7 +836,8 @@ void Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const
//----------------------------------------------------------------------------
-void Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const
+void
+Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const
{
if ( (int) vBottomNeighs.size() == 0) {
if ( m_mTree.at(nId).m_nBottom == -2)
@@ -817,7 +916,8 @@ void Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const
//----------------------------------------------------------------------------
-void Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const
+void
+Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const
{
if ( (int) vLeftNeighs.size() == 0) {
if ( m_mTree.at(nId).m_nLeft == -2)
@@ -895,7 +995,8 @@ void Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const
}
//----------------------------------------------------------------------------
-void Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const
+void
+Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const
{
if ( (int) vRightNeighs.size() == 0) {
if ( m_mTree.at(nId).m_nRight == -2)
@@ -973,7 +1074,52 @@ void Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const
}
//----------------------------------------------------------------------------
-int Tree::GetHeightLeaves( int nId, INTVECTOR& vnLeaves, int d) const
+void
+Tree::GetRootNeigh( int nEdge, INTVECTOR& vNeigh)
+{
+ int nId = -1 ;
+ bool bMod = false ;
+ if ( nEdge == 0 ) {
+ if ( m_mTree[nId].m_nBottom == -2 ) {
+ m_mTree[nId].m_nBottom = -1 ;
+ bMod = true;
+ }
+ GetBottomNeigh( nId, vNeigh) ;
+ if ( bMod)
+ m_mTree[nId].m_nBottom = -2 ;
+ }
+ else if ( nEdge == 1 ) {
+ if ( m_mTree[nId].m_nRight == -2 ) {
+ m_mTree[nId].m_nRight = -1 ;
+ bMod = true;
+ }
+ GetRightNeigh( nId, vNeigh) ;
+ if ( bMod)
+ m_mTree[nId].m_nRight = -2 ;
+ }
+ else if ( nEdge == 2 ) {
+ if ( m_mTree[nId].m_nTop == -2 ) {
+ m_mTree[nId].m_nTop = -1 ;
+ bMod = true;
+ }
+ GetTopNeigh( nId, vNeigh) ;
+ if ( bMod)
+ m_mTree[nId].m_nTop = -2 ;
+ }
+ else if ( nEdge == 3 ) {
+ if ( m_mTree[nId].m_nLeft == -2 ) {
+ m_mTree[nId].m_nLeft = -1 ;
+ bMod = true;
+ }
+ GetLeftNeigh( nId, vNeigh) ;
+ if ( bMod)
+ m_mTree[nId].m_nLeft = -2 ;
+ }
+}
+
+//----------------------------------------------------------------------------
+int
+Tree::GetHeightLeaves( int nId, INTVECTOR& vnLeaves, int d) const
{
if ( nId == -1 && m_mTree.at(-1).IsLeaf()) {
vnLeaves.push_back( -1) ;
@@ -1013,7 +1159,8 @@ int Tree::GetHeightLeaves( int nId, INTVECTOR& vnLeaves, int d) const
}
//----------------------------------------------------------------------------
-int Tree::GetDepth( int nId, int nRef = -2) const
+int
+Tree::GetDepth( int nId, int nRef = -2) const
{
int c = 0 ;
while ( m_mTree.at(nId).m_nParent != nRef) {
@@ -1024,7 +1171,352 @@ int Tree::GetDepth( int nId, int nRef = -2) const
}
//----------------------------------------------------------------------------
-bool Tree::GetPolygons( POLYLINEVECTOR& vPolygons)
+bool
+Tree::GetPolygons( std::vector& vPolygons) {
+ if ( ! m_bTrimmed) {
+ vPolygons.clear() ;
+ POLYLINEVECTOR vPolygonsBasic ;
+ GetPolygonsBasic( vPolygonsBasic) ;
+ for ( PolyLine pl : vPolygonsBasic) {
+ POLYLINEVECTOR vSinglePolygon ;
+ vSinglePolygon.push_back( pl) ;
+ vPolygons.push_back( vSinglePolygon) ;
+ }
+ return true ;
+ }
+ // trimmata
+ else {
+ TraceLoopLabelCell() ;
+ POLYLINEVECTOR vPolygonsBasic ;
+ GetPolygonsBasic( vPolygonsBasic) ;
+ // scorro sui poligoni delle celle non trimmate
+ int nCells = (int)vPolygonsBasic.size() ;
+ for ( int i = 0 ; i < nCells ; ++i ) {
+ // vettore dei poligoni ( loop) della cella nId
+ POLYLINEVECTOR vCellPolygons ;
+ // costruisco i poligoni partendo dal vettore delle intersezioni, come spiegato a pag15 di Cripps
+ int nId = m_vnLeaves[i] ;
+ PolyLine plTrimmedPoly ;
+ // numero di volte che la cella è stata attraversata da una curva di trim
+ int nPass = (int) m_mTree[nId].m_vInters.size() ;
+ // numero di vertici aggiunti al nuovo poligono
+ int c = 0 ;
+ // numero di poligoni aggiunti
+ int nPoly = 0 ;
+ // vettore in cui salvo il chunk di appartenenza di ogni loop che attraversa la cella
+ INTVECTOR vnParentChunk ;
+ // scorro sui vettori intersezione della cella nId e sui suoi vertici
+ // in questo for analizzo solo i loop che tagliano la cella
+ int nEdgeIn = -1 ;
+ for ( int j = 0 ; j < nPass ; ++ j) {
+ Inters inA = m_mTree[nId].m_vInters[j] ;
+ if ( inA.nIn != -1) {
+ int nEdge ;
+ if ( nEdgeIn == -1)
+ // salvo il lato di ingresso del primo lato del poligono che sto costruendo
+ nEdgeIn = inA.nIn ;
+ for ( Point3d ptInt : inA.vpt) {
+ plTrimmedPoly.AddUPoint( c, ptInt) ;
+ ++ c ;
+ }
+ nEdge = inA.nOut ;
+ // se la curva è CW devo verifica di non essere uscito in un vertice, con un tratto sovrapposto al lato che ripercorrerò tra poco
+ if ( ! inA.bCCW) {
+ Point3d ptLast , ptSecondToLast;
+ plTrimmedPoly.GetLastPoint( ptLast) ;
+ plTrimmedPoly.GetPrevPoint( ptSecondToLast) ;
+ Vector3d vLast = ptLast - ptSecondToLast ;
+ vLast.Normalize();
+ Vector3d vEdge ;
+ if ( nEdge == 0) {
+ Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ;
+ if ( AreSamePointApprox ( ptLast, ptTl)) {
+ vEdge = m_mTree[nId].GetBottomLeft() - ptTl ;
+ vEdge.Normalize() ;
+ if ( AreOppositeVectorApprox( vLast, vEdge) ) {
+ plTrimmedPoly.EraseLastUPoint() ;
+ nEdge = 1 ;
+ }
+ }
+ }
+ else if ( nEdge == 1 && AreSamePointApprox ( ptLast, m_mTree[nId].GetBottomLeft())) {
+ Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ;
+ vEdge = ptBr - m_mTree[nId].GetBottomLeft() ;
+ vEdge.Normalize() ;
+ if ( AreOppositeVectorApprox( vLast, vEdge) ) {
+ plTrimmedPoly.EraseLastUPoint() ;
+ nEdge = 2 ;
+ }
+ }
+ else if ( nEdge == 2) {
+ Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ;
+ if ( AreSamePointApprox ( ptLast, ptBr)) {
+ vEdge = m_mTree[nId].GetTopRight() - ptBr ;
+ vEdge.Normalize() ;
+ if ( AreOppositeVectorApprox( vLast, vEdge) ) {
+ plTrimmedPoly.EraseLastUPoint() ;
+ nEdge = 3 ;
+ }
+ }
+ }
+ else if ( nEdge == 3 && AreSamePointApprox ( ptLast, m_mTree[nId].GetTopRight())) {
+ Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ;
+ vEdge = ptTl - m_mTree[nId].GetTopRight() ;
+ vEdge.Normalize() ;
+ if ( AreOppositeVectorApprox(vLast, vEdge) ) {
+ plTrimmedPoly.EraseLastUPoint() ;
+ nEdge = 0 ;
+ }
+ }
+ }
+ // se mi è rimasto solo un punto sulla polyline vuol dire che avevo solo un tratto parallelo ad lato
+ // quindi salto al prossimo loop
+ if ( plTrimmedPoly.GetPointNbr() == 1 ) {
+ plTrimmedPoly.Clear() ;
+ continue ;
+ }
+ if ( nEdge > 3 && nEdge != 7) {
+ nEdge = nEdge - 3 ;
+ }
+ else if ( nEdge == 7 ) {
+ nEdge = 0 ;
+ }
+ // se ho altri Pass vado avanti ad aggiungere vertici finché trovo il prossimo o finché non sono tornato sul lato di partenza
+ bool bNotCameBack = true ;
+ bool bValidNextStart = false ;
+ if ( j < nPass - 1 ) {
+ if ( m_mTree[nId].m_vInters[j].bCCW ) {
+ bValidNextStart = ( m_mTree[nId].m_vInters[j + 1].nIn == nEdge) &&
+ ! CheckIfAfter( plTrimmedPoly, m_mTree[nId].m_vInters[j + 1].vpt[0], nEdge) ;
+ bNotCameBack = m_mTree[nId].m_vInters[j].nIn != nEdge && // sono tornato al lato di ingresso di questo loop
+ nEdge != nEdgeIn ; // sono tornato sul lato di ingresso di questo poligono ( solo se la curva è CCW)
+ }
+ else {
+ // se il loop è CW e sono tornato sul lato di partenza allora controllo se sono prima del primo punto della polyline
+ if ( nEdge == nEdgeIn ) {
+ bValidNextStart = ( m_mTree[nId].m_vInters[j + 1].nIn == nEdge) &&
+ CheckIfAfter( plTrimmedPoly, m_mTree[nId].m_vInters[j + 1].vpt[0], nEdge) ;
+ bool bBefore = CheckIfBefore( plTrimmedPoly, nEdge) ;
+ bNotCameBack = bNotCameBack && ! bBefore ;
+ }
+ }
+ // devo controllare che su questo lato il prossimo punto di ingresso sia più avanti del punto di fine a cui sono arrivato!!!!//////////////////////
+ while ( m_mTree[nId].m_vInters[j + 1].nIn != nEdge && // loop successivo inizia su questo lato/// questa condizione devo spostarla nell'if qui sopra
+ // e differenziare per CCW e CW. sostituisco con bValidNextStart
+ bNotCameBack) {
+ Point3d ptVert ;
+ if ( nEdge == 0) {
+ ptVert.x = m_mTree[nId].GetBottomLeft().x ;
+ ptVert.y = m_mTree[nId].GetTopRight().y ;
+ }
+ else if ( nEdge == 1)
+ ptVert = m_mTree[nId].GetBottomLeft() ;
+ else if ( nEdge == 2) {
+ ptVert.x = m_mTree[nId].GetTopRight().x ;
+ ptVert.y = m_mTree[nId].GetBottomLeft().y ;
+ }
+ else if ( nEdge == 3)
+ ptVert = m_mTree[nId].GetTopRight() ;
+ plTrimmedPoly.AddUPoint( c, ptVert) ;
+ ++c ;
+ if ( nEdge != 3)
+ ++ nEdge ;
+ else
+ nEdge = 0 ;
+ // aggiorno le condizioni per il while
+ if ( m_mTree[nId].m_vInters[j].bCCW ) {
+ bNotCameBack = m_mTree[nId].m_vInters[j].nIn != nEdge &&
+ nEdge != nEdgeIn ;
+ }
+ else {
+ if ( nEdge == nEdgeIn ) {
+ bool bBefore = CheckIfBefore( plTrimmedPoly, nEdge) ;
+ bNotCameBack = bNotCameBack && ! bBefore ;
+ }
+ }
+ }
+ // se ho trovato un altro loop salto all'inizio del for
+ if ( m_mTree[nId].m_vInters[j + 1].nIn == nEdge) {
+ continue ;
+ }
+ }
+ // non ho altri loop quindi aggiungo vertici finché torno al punto di partenza
+ else {
+ if ( m_mTree[nId].m_vInters[j].bCCW ) {
+ bNotCameBack = m_mTree[nId].m_vInters[j].nIn != nEdge && // sono tornato al lato di ingresso di questo loop
+ nEdge != nEdgeIn ; // sono tornato sul lato di ingresso di questo poligono ( solo se la curva è CCW)
+ }
+ else {
+ // se il loop è CW e sono tornato sul lato di partenza allora controllo se sono prima del primo punto della polyline
+ if ( nEdge == nEdgeIn ) {
+ bool bBefore = CheckIfBefore( plTrimmedPoly, nEdge) ;
+ bNotCameBack = bNotCameBack && ! bBefore ;
+ }
+ }
+ while ( bNotCameBack) {
+ Point3d ptVert ;
+ if ( nEdge == 0) {
+ ptVert.x = m_mTree[nId].GetBottomLeft().x ;
+ ptVert.y = m_mTree[nId].GetTopRight().y ;
+ }
+ else if ( nEdge == 1)
+ ptVert = m_mTree[nId].GetBottomLeft() ;
+ else if ( nEdge == 2) {
+ ptVert.x = m_mTree[nId].GetTopRight().x ;
+ ptVert.y = m_mTree[nId].GetBottomLeft().y ;
+ }
+ else if ( nEdge == 3)
+ ptVert = m_mTree[nId].GetTopRight() ;
+ plTrimmedPoly.AddUPoint( c, ptVert) ;
+ ++c ;
+ if ( nEdge != 3)
+ ++ nEdge ;
+ else
+ nEdge = 0 ;
+ // aggiorno le condizioni per il while
+ if ( m_mTree[nId].m_vInters[j].bCCW ) {
+ bNotCameBack = m_mTree[nId].m_vInters[j].nIn != nEdge &&
+ nEdge != nEdgeIn ;
+ }
+ else {
+ if ( nEdge == nEdgeIn ) {
+ bool bBefore = CheckIfBefore( plTrimmedPoly, nEdge) ;
+ bNotCameBack = bNotCameBack && ! bBefore ;
+ }
+ }
+ }
+ }
+ plTrimmedPoly.Close() ;
+ vCellPolygons.push_back( plTrimmedPoly) ;
+ vPolygons.push_back( vCellPolygons) ;
+ ++ nPoly ;
+ vnParentChunk.push_back( inA.nChunk) ;
+ vCellPolygons.clear() ;
+ c = 0 ;
+ plTrimmedPoly.Clear() ;
+ nEdgeIn = -1 ;
+ }
+ else
+ continue ;
+ }
+
+ // ora analizzo anche i loop che sono contenuti nella cella
+ // loop interni in una cella intersecata
+ //
+ // DA AGGIUNGERE ////////
+ // la cella è contenuta in un loop più grande della cella -> i loop esterni devono essere CW e devo aggiungere il bordo della cella ai loop/////////////////////////////////
+ if ( m_mTree[nId].m_nFlag == 3 || m_mTree[nId].m_nFlag == 2) {
+ // devo verificare se il loop è contenuto in un'altro loop ?////////////////////////////////////sì/////////////////////////////////////////
+ PolyLine plInLoop ;
+ // numero dei loop interni passati
+ int n = 0 ;
+ Inters inA = m_mTree[nId].m_vInters[n] ;
+ if ( m_mTree[nId].m_nFlag == 2 && inA.nOut == -3) {
+ // i loop esterni sono CW, quindi prima dei loop di trim aggiungo il bordo cella
+ Point3d ptVert = m_mTree[nId].GetTopRight() ;
+ plInLoop.AddUPoint( 0, ptVert) ;
+ ptVert.x = m_mTree[nId].GetBottomLeft().x ;
+ ptVert.y = m_mTree[nId].GetTopRight().y ;
+ plInLoop.AddUPoint( 1, ptVert) ;
+ ptVert = m_mTree[nId].GetBottomLeft() ;
+ plInLoop.AddUPoint( 2, ptVert) ;
+ ptVert.x = m_mTree[nId].GetTopRight().x ;
+ ptVert.y = m_mTree[nId].GetBottomLeft().y ;
+ plInLoop.AddUPoint( 3, ptVert) ;
+ plInLoop.Close();
+ vCellPolygons.push_back( plInLoop) ;
+ vPolygons.push_back( vCellPolygons) ;
+ ++ nPoly ;
+ vnParentChunk.push_back( inA.nChunk) ;
+ vCellPolygons.clear() ;
+ plInLoop.Clear() ;
+ }
+ while ( inA.nIn == -1) {
+ // numero di vertici aggiunti al nuovo poligono
+ int k = 0 ;
+ for ( Point3d ptInt : inA.vpt) {
+ plInLoop.AddUPoint( c, ptInt) ;
+ ++ k ;
+ }
+ plInLoop.Close();
+ bool bAdded = false ;
+ // se il loop è CW devo controllare in quale altro dei poligoni che ho già aggiunto è contenuto
+ if ( ! inA.bCCW) {
+ Point3d ptStart ;
+ plInLoop.GetFirstPoint( ptStart) ;
+ int nOtherPoly = (int)vPolygons.size() ;
+ for ( int r = 0 ; r < nPoly ; ++r ) {
+ if ( IsPointInsidePolyLine( ptStart, vPolygons[nOtherPoly - r - 1][0], -0.01) && vnParentChunk[nPoly - r - 1] == inA.nChunk ) {
+ vPolygons[r].push_back( plInLoop) ;
+ plInLoop.Clear() ;
+ ++ nPoly ;
+ vnParentChunk.push_back( inA.nChunk) ;
+ bAdded = true ;
+ break ;
+ }
+ }
+ }
+ if ( ! bAdded ) {
+ vCellPolygons.push_back( plInLoop) ;
+ vPolygons.push_back( vCellPolygons) ;
+ ++ nPoly ;
+ vnParentChunk.push_back( inA.nChunk) ;
+ plInLoop.Clear() ;
+ vCellPolygons.clear() ;
+ }
+
+ plInLoop.Clear() ;
+ ++ n ;
+ inA = m_mTree[nId].m_vInters[n] ;
+ }
+ }
+ //// solo loop interni
+ //// o la cella è contenuta in un loop più grande della cella -> i loop esterni devono essere CW e devo aggiungere il bordo della cella ai loop
+ //// o bisogna tenere solo il contenuto dei loop -> i loop esterni sono CCW
+ //if ( m_mTree[nId].m_nFlag == 2) {
+ // PolyLine plInLoop ;
+ // int n = 0 ;
+ // Inters inA = m_mTree[nId].m_vInters[n] ;
+ // if ( inA.nOut == -3) {
+ // // i loop esterni sono CW, quindi prima dei loop di trim aggiungo il bordo cella
+ // Point3d ptVert = m_mTree[nId].GetTopRight() ;
+ // plInLoop.AddUPoint( 0, ptVert) ;
+ // ptVert.x = m_mTree[nId].GetBottomLeft().x ;
+ // ptVert.y = m_mTree[nId].GetTopRight().y ;
+ // plInLoop.AddUPoint( 1, ptVert) ;
+ // ptVert = m_mTree[nId].GetBottomLeft() ;
+ // plInLoop.AddUPoint( 2, ptVert) ;
+ // ptVert.x = m_mTree[nId].GetTopRight().x ;
+ // ptVert.y = m_mTree[nId].GetBottomLeft().y ;
+ // plInLoop.AddUPoint( 3, ptVert) ;
+ // vCellPolygons.push_back( plInLoop) ;
+ // plInLoop.Clear() ;
+ // }
+ // while ( inA.nIn == -1) {
+ // // numero di vertici aggiunti al nuovo poligono
+ // int k = 0 ;
+ // for ( Point3d ptInt : inA.vpt) {
+ // plInLoop.AddUPoint( c, ptInt) ;
+ // ++ k ;
+ // }
+ // ++ n ;
+ // inA = m_mTree[nId].m_vInters[n] ;
+ // vCellPolygons.push_back( plInLoop) ;
+ // plInLoop.Clear() ;
+ // }
+ //}
+
+ // questo in teoria non serve più, perché aggiungo subito un vCellPolygons a vPolygons////////////////////////////////da controllare/////////////////
+ //if ( (int)vCellPolygons.size() != 0)
+ // vPolygons.push_back( vCellPolygons) ;
+ }
+ return true;
+ }
+}
+
+//----------------------------------------------------------------------------
+bool
+Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons)
{
if ( m_vPolygons.empty()) {
PNTVECTOR vVertices ;
@@ -1108,10 +1600,517 @@ bool Tree::GetPolygons( POLYLINEVECTOR& vPolygons)
for ( int i = 0 ; i < (int) vVertices.size() ; ++i) {
m_vPolygons.back().AddUPoint( i, vVertices.at(i)) ;
}
+
}
}
// restituisco i poligoni delle celle del tree nello spazio parametrico
vPolygons = m_vPolygons ;
return true ;
-}
\ No newline at end of file
+}
+
+//----------------------------------------------------------------------------
+void
+Tree::ResetTree( void)
+{
+ //int nCToReset = -1 ;
+ //while ( nCToReset != -2 && m_mTree[nCToReset].IsProcessed() == true) {
+ // if ( m_mTree[nCToReset].IsLeaf()) {
+ // m_mTree[nCToReset].SetProcessed( false) ;
+ //
+ // // risalgo i parent finché non trovo il primo Child2 da deprocessare
+ // nCToReset = m_mTree[nCToReset].m_nParent ;
+ // if ( ! m_mTree[m_mTree[nCToReset].m_nChild1].IsProcessed() && ! m_mTree[m_mTree[nCToReset].m_nChild2].IsProcessed())
+ // m_mTree[nCToReset].SetProcessed( false) ;
+ // while ( ! m_mTree[m_mTree[nCToReset].m_nChild2].IsProcessed()) {
+ // if ( m_mTree[nCToReset].m_nParent != -2)
+ // nCToReset = m_mTree[nCToReset].m_nParent ;
+ // if ( ! m_mTree[m_mTree[nCToReset].m_nChild1].IsProcessed() && ! m_mTree[m_mTree[nCToReset].m_nChild2].IsProcessed())
+ // m_mTree[nCToReset].SetProcessed( false) ;
+ // if ( nCToReset == -1 && ! m_mTree[m_mTree[nCToReset].m_nChild2].IsProcessed())
+ // break ;
+ // }
+ // nCToReset = m_mTree[nCToReset].m_nChild2 ;
+
+ // }
+ // else {
+ // nCToReset = m_mTree[nCToReset].m_nChild1 ;
+ // }
+ //}
+ for ( int nC : m_vnLeaves ) {
+ m_mTree[nC].SetProcessed( false) ;
+ }
+}
+
+//----------------------------------------------------------------------------
+int
+Tree::FindCell( const Point3d& ptToAssign) const
+{
+ // se fallisce ritorna -2
+ // verifico che il punto sia all'interno dello spazio parametrico
+ if ( ptToAssign.x < m_mTree.at(-1).GetBottomLeft().x || ptToAssign.x > m_mTree.at( -1).GetTopRight().x ||
+ ptToAssign.y < m_mTree.at(-1).GetBottomLeft().y || ptToAssign.y > m_mTree.at( -1).GetTopRight().y )
+ return -2 ;
+
+ int nId = -1 ;
+ while ( ! m_mTree.at(nId).IsLeaf()) {
+ if ( m_mTree.at(nId).IsSplitVert()) {
+ double dMid = ( m_mTree.at(nId).GetBottomLeft().x + m_mTree.at(nId).GetTopRight().x) / 2 ;
+ if ( ptToAssign.x < dMid) {
+ nId = m_mTree.at(nId).m_nChild1 ;
+ }
+ else {
+ nId = m_mTree.at(nId).m_nChild2 ;
+ }
+ }
+ else {
+ double dMid = ( m_mTree.at(nId).GetBottomLeft().y + m_mTree.at(nId).GetTopRight().y) / 2 ;
+ if ( ptToAssign.y < dMid ) {
+ nId = m_mTree.at(nId).m_nChild2 ;
+ }
+ else {
+ nId = m_mTree.at(nId).m_nChild1 ;
+ }
+ }
+ }
+ if ( nId == -1)
+ nId = -2 ;
+ return nId ;
+}
+
+//----------------------------------------------------------------------------
+bool
+Tree::TraceLoopLabelCell( void)
+{
+ // approssimo i loop di trim con delle spezzate
+ POLYLINEVECTOR vPlApprox ;
+ //for ( PtrOwner pCrv : m_vLoop){
+ for ( int p = 0 ; p < (int) m_vLoop.size(); ++ p){
+ PtrOwner pCrv( m_vLoop[p]->Clone()) ;
+ double dLinTol = 0.01 ; // questo è riferito allo spazio parametrico perché le curve di loop sono già state riscalate!!!!!!
+ double dAngTolDeg = 5 ;
+ PolyLine plApprox ;
+ int nType = 0 ;
+ pCrv->ApproxWithLines( dLinTol,dAngTolDeg, nType, plApprox) ;
+ vPlApprox.push_back( plApprox) ;
+ }
+ // ora le curve di trim hanno lo stesso indice delle loro corrispondenti spezzate nel vettore vPlApprox
+ // come sono composte le plApprox??
+
+ // qui potrei aver trovato solo le celle che sono nelle box3d delle curve di trim. se ho delle curve in senso antiorario come le gestisco????
+ double dLinTol = - 0.01 ; // questo è riferito allo spazio parametrico!!!!!!
+ POLYLINEVECTOR vplPolygons ;
+ GetPolygonsBasic( vplPolygons) ;
+ // percorro i loop trovando le interezioni con le celle e riempiendo i vettori m_vInters delle varie celle
+ //for ( PolyLine plLoop : vPlApprox) {
+ for ( int i = 0 ; i < (int) vPlApprox.size(); ++ i) {
+ PolyLine plLoop = vPlApprox[i] ;
+ // calcolo se il loop è CCW o Cw
+ double dArea ;
+ Plane3d plExtPlane ;
+ bool bCCW ;
+ plLoop.IsClosedAndFlat( plExtPlane, dArea, 50 * EPS_SMALL) ;
+ if ( plExtPlane.GetVersN().z > 0 )
+ bCCW = true ;
+ else
+ bCCW = false ;
+ // trovo in quale cella è il ptStart
+ Point3d ptStart ;
+ plLoop.GetFirstPoint( ptStart) ;
+ int nId = FindCell( ptStart) ;
+ // trovo quali punti della polyline sono nella cella e l'intersezione
+ PNTVECTOR vptInters ;
+ vptInters.push_back( ptStart) ;
+ // qui mi devo salvare quanti elementi ho già nel vettore m_vInters della cella
+ // per poter fare il merge con l'ultimo vptInters della curva di trim, che sarà ancora in questa cella
+ // e terminerà nel punto di start
+ int nPass = (int) m_mTree[nId].m_vInters.size() ;
+ m_mTree[nId].m_vInters.emplace_back() ;
+ // salvo il verso del loop
+ m_mTree[nId].m_vInters.back().bCCW = bCCW ;
+ // salvo il chunk del loop
+ m_mTree[nId].m_vInters.back().nChunk = m_mChunk[i] ;
+ bool bLoopInside = true ;
+ // funziona la condizione del for ??/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ Point3d ptCurr ;
+ INTVECTOR :: iterator iter = find( m_vnLeaves.begin(), m_vnLeaves.end(), nId) ;
+ int nIdPolygon = std::distance( m_vnLeaves.begin(), iter) ;
+ //for ( Point3d ptCurr ; plLoop.GetNextPoint( ptCurr) ; ) {
+ while ( plLoop.GetNextPoint( ptCurr)) {
+ // sto uscendo dalla cella, quindi cerco l'intersezione
+ Point3d ptStart, ptEnd ;
+ plLoop.GetPrevPoint( ptStart) ;
+ plLoop.GetNextPoint( ptEnd) ;
+ CurveLine clTrim ;
+ clTrim.Set( ptStart, ptEnd) ;
+ while( ! IsPointInsidePolyLine( ptCurr, m_vPolygons[nIdPolygon], dLinTol)) { /// qui devo mettere una tolleranza negativa per poter tener conto anche dei punti che sono SULLA curva
+ bLoopInside = false ;
+ // trovo l'intersezione e passo alla cella successiva. nId viene aggiornato dalla funzione FindInters
+ FindInters( nId, clTrim, vptInters) ;
+ // ricalcolo la posizione di nId nel vettore delle foglie
+ iter = find( m_vnLeaves.begin(), m_vnLeaves.end(), nId) ;
+ nIdPolygon = std::distance( m_vnLeaves.begin(), iter) ;
+ // salvo il verso del loop
+ m_mTree[nId].m_vInters.back().bCCW = bCCW ;
+ // salvo il chunk del loop
+ m_mTree[nId].m_vInters.back().nChunk = m_mChunk[i] ;
+ }
+ // aggiungo la fine del segmento nel vettore delle intersezioni
+ vptInters.push_back( ptCurr) ;
+ }
+ vptInters.pop_back() ;
+ m_mTree[nId].m_vInters.back().vpt = vptInters ;
+ if ( bLoopInside) {
+ m_mTree[nId].m_vnLoop.push_back( i) ;
+ // setto la categoria della cella
+ if ( m_mTree[nId].m_nFlag == 0)
+ m_mTree[nId].m_nFlag = 2 ;
+ else if ( m_mTree[nId].m_nFlag == 1)
+ m_mTree[nId].m_nFlag = 3 ;
+ // setto i lati di ingresso e uscita a -1 per indicare che ho un loop interno alla cella
+ m_mTree[nId].m_vInters.back().nIn = -1 ;
+ m_mTree[nId].m_vInters.back().nOut = -1 ;
+ //// salvo il verso della curva di trim ///////////////////////////////////////////////////////////////////doppione//////////////////
+ //double dArea ;
+ //Plane3d plExtPlane ;
+ //plLoop.IsClosedAndFlat( plExtPlane, dArea, 50 * EPS_SMALL) ;
+ //if ( plExtPlane.GetVersN().z > 0 ) {
+ // m_mTree[nId].m_vInters.back().bCCW = true ;
+ //}
+ //else {
+ // m_mTree[nId].m_vInters.back().bCCW = false ;
+ //}
+
+ }
+ // sono tornato alla cella di partenza, quindi devo fare il merge dei due vettori di intersezione che ho creato per questa cella
+ // per lo stesso loop
+ else {
+ //int nIn = m_mTree[nId].m_vInters.back().nIn ;
+ int nOut = m_mTree[nId].m_vInters[nPass].nOut ;
+ m_mTree[nId].m_vInters.back().vpt.insert( m_mTree[nId].m_vInters.back().vpt.end(),
+ m_mTree[nId].m_vInters[nPass].vpt.begin(),
+ m_mTree[nId].m_vInters[nPass].vpt.end()) ;
+ m_mTree[nId].m_vInters[nPass] = m_mTree[nId].m_vInters.back() ;
+ m_mTree[nId].m_vInters.pop_back() ;
+ // sistemo il lato d'uscita
+ m_mTree[nId].m_vInters[nPass].nOut = nOut ;
+ }
+ }
+
+ // riordino i vettori di intersezione per ogni cella
+ for ( int nId : m_vnLeaves) {
+ std::sort( m_mTree[nId].m_vInters.begin( ), m_mTree[nId].m_vInters.end()) ;
+ }
+
+ //// devo riconoscere le celle dentro i loop che sono ancora con label nFlag = -1
+ //ResetTree() ;
+ //INTVECTOR vNeigh, vFirst ;
+ //GetRootNeigh( 1, vFirst) ;
+ //int nLastLeft = vFirst.back() ;
+ //int nCell = vFirst[0] ;
+ //GetRightNeigh( nCell, vNeigh) ;
+ //// proseguo finché non sono sull'elemento più alto di vFirst e tutti i suoi vicini sono processati/categorizzati
+ //bool bAllDone = false , bDone ;
+ //while ( nCell != nLastLeft && ! bAllDone) {
+ // // fintanto che la cella ha tra i vicini a destra una cella non elaborata mi sposto a destra
+ // bDone = false ; // ramo a destra tutto categorizzato
+ // while ( (int)vNeigh.size() > 0 || ! bDone) {
+ // // verso la cella a destra più in basso da cui non sono ancora passato
+ // bool bProceeded = false ;
+ // for ( int i = 0 ; i < (int)vNeigh.size(); ++ i) {
+ // if ( ! m_mTree[vNeigh[i]].IsProcessed() ) {
+ // nCell = vNeigh[i] ;
+ // bProceeded = true ;
+ // break ;
+ // }
+ // }
+ // if ( ! bProceeded)
+ // bDone = true ;
+ // else { //categorizzo la cella///////////////////////////////////////////////////////////
+
+ // }
+ //
+ // if ( ! bDone) {
+ // // guardo i vicini a destra per passare alla prossima cella
+ // vNeigh.clear() ;
+ // GetRightNeigh( nCell, vNeigh) ;
+ // }
+ // }
+ // vNeigh.clear() ;
+ // GetRightNeigh( nCell, vNeigh) ;
+ // // se non ho vicini a destra o se i vicini sono già tutti categorizzati
+ // // torno indietro a sinistra alla cella già categorizzata più bassa
+ // //bDone = true ;
+ // while ( (int) vNeigh.size() == 0 || bDone) {
+ // // trovo il vicino a sinistra, già categorizzato, più basso
+ // vNeigh.clear() ;
+ // GetLeftNeigh( nCell, vNeigh) ;
+ // for ( int p = 0; p < (int)vNeigh.size() ; ++ p) {
+ // if ( m_mTree[vNeigh[p]].IsProcessed() ) {
+ // nCell = vNeigh[p] ;
+ // break ;
+ // }
+ // }
+ // // controllo se tutti i vicini di destra sono categorizzati
+ // vNeigh.clear() ;
+ // GetRightNeigh( nCell, vNeigh) ;
+ // for ( int k = 0; k < (int)vNeigh.size() ; ++ k) {
+ // if ( ! m_mTree[vNeigh[k]].IsProcessed() ) {
+ // nCell = vNeigh[k] ;
+ // bDone = false;
+ // break ;
+ // }
+ // }
+ // }
+ // // categorizzo la cella
+
+
+
+ // // se sono all'ultimo elemento di vFirst controllo se ho fatto tutti i suoi vicini di destra
+ // if ( nCell == nLastLeft){
+ // vNeigh.clear() ;
+ // GetRightNeigh( nCell, vNeigh) ;
+ // bAllDone = true ;
+ // for( int j = 0 ; j < (int) vNeigh.size(); ++ j) {
+ // if ( ! m_mTree[vNeigh[j]].IsProcessed() ) {
+ // bAllDone = false ;
+ // break ;
+ // }
+ // }
+ // }
+
+ //}
+
+ //// RIMETTI il valore di default di m_nFlag = -1 nella creazione di una cella // mi serve???//////////////////////////////////////////////////////////
+
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+Tree::FindInters( int& nId, CurveLine& clTrim, PNTVECTOR& vptInters)
+{
+ CurveLine clEdge , clEdge2 ;
+ Point3d ptStart , ptEnd ;
+ clTrim.GetStartPoint( ptStart) ;
+ clTrim.GetEndPoint( ptEnd) ;
+ // trovo da quale lato sto uscendo
+ Point3d ptTR = m_mTree[nId].GetTopRight() ;
+ Point3d ptBL = m_mTree[nId].GetBottomLeft() ;
+ Point3d ptTl( ptBL.x , ptTR.y) ;
+ Point3d ptBr( ptTR.x , ptBL.y) ;
+ int nEdge ; // flag che indica il lato su cui ho l'intersezione a partire dal lato top in senso antiorario
+ // oltre il 3 sono le celle adiacenti in diagonale al vertice-> 4 corrisponde al ptTl e da lì in senso antiorario
+ // -1 se la curva è sempre dentro la cella
+ if ( ptEnd.y > ptTR.y && ptEnd.x <= ptTR.x) {
+ nEdge = 0 ;
+ // lato sopra
+ if ( ptEnd.x >= ptBL.x)
+ clEdge.Set( ptTR, ptTl) ;
+ // lato sinistro
+ else //if ( ptEnd.x < ptBL.x)
+ clEdge2.Set( ptTl, ptBL) ;
+ }
+ else if ( ptEnd.x < ptBL.x && ptEnd.y <= ptTR.y) {
+ nEdge = 1 ;
+ // lato sinistro
+ if ( ptEnd.y >= ptBL.y)
+ clEdge.Set( ptTl, ptBL) ;
+ // lato sotto
+ else //if ( ptEnd.y < ptBL.y)
+ clEdge2.Set( ptBL, ptBr) ;
+ }
+ else if ( ptEnd.y < ptBL.y && ptEnd.x >= ptBL.x) {
+ nEdge = 2 ;
+ // lato sotto
+ if ( ptEnd.x <= ptTR.x)
+ clEdge.Set( ptBL, ptBr) ;
+ // lato destro
+ else if ( ptEnd.x > ptTR.x)
+ clEdge2.Set( ptBr, ptTR) ;
+ }
+ else if ( ptEnd.x > ptTR.x && ptEnd.y >= ptBL.y) {
+ nEdge = 3 ;
+ // lato desto
+ if ( ptEnd.y <= ptTR.y)
+ clEdge.Set( ptBr, ptTR) ;
+ // lato sopra
+ if ( ptEnd.y > ptTR.y)
+ clEdge2.Set( ptTR, ptTl) ;
+ }
+ else
+ return false ;
+
+ // intersezione e controlli
+ IntersLineLine illExit( clTrim, clEdge, true) ;
+ IntCrvCrvInfo aInfo, aInfo2 ;
+ Point3d ptInters ;
+ if ( ! illExit.GetIntCrvCrvInfo( aInfo) )
+ return false ;
+ if ( clEdge2.IsValid()){
+ IntersLineLine illExit2( clTrim, clEdge2, true) ;
+ if ( ! illExit2.GetIntCrvCrvInfo( aInfo2) )
+ return false ;
+ // verifico su quale dei due lati ho l'intersezione
+ if ( illExit2.GetNumInters() == 0)
+ ptInters = aInfo.IciA[0].ptI ;
+ else {
+ // solo intersezione sul lato 2
+ if ( illExit.GetNumInters() == 0) {
+ ptInters = aInfo2.IciA[0].ptI ;
+ if ( nEdge == 3)
+ nEdge = 0 ;
+ else
+ ++ nEdge ;
+ }
+ // intersezione sul vertice della cella
+ else {
+ // la cella adiacente in diagonale a quel vertice
+ nEdge = nEdge + 4 ;
+ }
+ }
+ }
+ else
+ ptInters = aInfo.IciA[0].ptI ;
+ m_mTree[nId].m_vInters.back().nOut = nEdge ;
+ vptInters.push_back( ptInters) ;
+ // salvo il vettore intersezione per la cella e capisco in quale altra cella passare
+ m_mTree[nId].m_vInters.back().vpt = vptInters ;
+ vptInters.clear() ;
+ // setto la categoria della cella
+ if ( m_mTree[nId].m_nFlag == 0)
+ m_mTree[nId].m_nFlag = 1 ;
+ else if ( m_mTree[nId].m_nFlag == 2)
+ m_mTree[nId].m_nFlag = 3 ;
+ // seleziono la cella successiva da analizzare
+ INTVECTOR vNeigh ;
+ if ( nEdge == 0) {
+ GetTopNeigh( nId, vNeigh) ;
+ std::reverse( vNeigh.begin(), vNeigh.end()) ;
+ for ( int j : vNeigh ) {
+ if ( ptInters.x >= m_mTree[j].GetBottomLeft().x) {
+ nId = j ;
+ break ;
+ }
+ }
+ m_mTree[nId].m_vInters.emplace_back() ;
+ m_mTree[nId].m_vInters.back().nIn = 2 ;
+ }
+ else if ( nEdge == 1) {
+ GetLeftNeigh( nId, vNeigh) ;
+ std::reverse( vNeigh.begin(), vNeigh.end()) ;
+ for ( int j : vNeigh ) {
+ if ( ptInters.y >= m_mTree[j].GetBottomLeft().y) {
+ nId = j ;
+ break ;
+ }
+ }
+ m_mTree[nId].m_vInters.emplace_back() ;
+ m_mTree[nId].m_vInters.back().nIn = 3 ;
+ }
+ else if ( nEdge == 2) {
+ GetBottomNeigh( nId, vNeigh) ;
+ for ( int j : vNeigh ) {
+ if ( ptInters.x <= m_mTree[j].GetTopRight().x) {
+ nId = j ;
+ break ;
+ }
+ }
+ m_mTree[nId].m_vInters.emplace_back() ;
+ m_mTree[nId].m_vInters.back().nIn = 0 ;
+ }
+ else if ( nEdge == 3) {
+ GetRightNeigh( nId, vNeigh) ;
+ for ( int j : vNeigh ) {
+ if ( ptInters.y <= m_mTree[j].GetTopRight().y) {
+ nId = j ;
+ break ;
+ }
+ }
+ m_mTree[nId].m_vInters.emplace_back() ;
+ m_mTree[nId].m_vInters.back().nIn = 1 ;
+ }
+ else if ( nEdge == 4) {
+ GetTopNeigh( nId, vNeigh) ;
+ int nIdTemp = vNeigh[0] ;
+ vNeigh.clear() ;
+ GetLeftNeigh( nIdTemp, vNeigh) ;
+ nId = vNeigh[0] ;
+ m_mTree[nId].m_vInters.emplace_back() ;
+ m_mTree[nId].m_vInters.back().nIn = 6 ;
+ }
+ else if ( nEdge == 5) {
+ GetLeftNeigh( nId, vNeigh) ;
+ int nIdTemp = vNeigh[0] ;
+ vNeigh.clear() ;
+ GetBottomNeigh( nIdTemp, vNeigh) ;
+ nId = vNeigh.back() ;
+ m_mTree[nId].m_vInters.emplace_back() ;
+ m_mTree[nId].m_vInters.back().nIn = 7 ;
+ }
+ else if ( nEdge == 6) {
+ GetBottomNeigh( nId, vNeigh) ;
+ int nIdTemp = vNeigh.back() ;
+ vNeigh.clear() ;
+ GetRightNeigh( nIdTemp, vNeigh) ;
+ nId = vNeigh[0] ;
+ m_mTree[nId].m_vInters.emplace_back() ;
+ m_mTree[nId].m_vInters.back().nIn = 4 ;
+ }
+ else if ( nEdge == 7) {
+ GetRightNeigh( nId, vNeigh) ;
+ int nIdTemp = vNeigh.back() ;
+ vNeigh.clear() ;
+ GetTopNeigh( nIdTemp, vNeigh) ;
+ nId = vNeigh[0] ;
+ m_mTree[nId].m_vInters.emplace_back() ;
+ m_mTree[nId].m_vInters.back().nIn = 5 ;
+ }
+ // aggiungo l'intersezione al vettore delle intersezioni della prossima cella
+ vptInters.push_back( ptInters) ;
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+Tree::CheckIfBefore( PolyLine& pl, int nEdge) const
+{
+ Point3d ptStart, ptEnd ;
+ pl.GetFirstPoint( ptStart) ;
+ pl.GetLastPoint( ptEnd) ;
+ if ( nEdge == 0 ) {
+ return ptEnd.x > ptStart.x ;
+ }
+ else if ( nEdge == 1 ) {
+ return ptEnd.y > ptStart.y ;
+ }
+ else if ( nEdge == 2 ) {
+ return ptEnd.x < ptStart.x ;
+ }
+ else if ( nEdge == 3 ) {
+ return ptEnd.y < ptStart.y ;
+ }
+ return false ;
+}
+
+//----------------------------------------------------------------------------
+bool
+Tree::CheckIfAfter( PolyLine& pl, Point3d& ptNextStart, int nEdge) const
+{
+ Point3d ptEnd ;
+ pl.GetLastPoint( ptEnd) ;
+ if ( nEdge == 0 ) {
+ return ptEnd.x > ptNextStart.x ;
+ }
+ else if ( nEdge == 1 ) {
+ return ptEnd.y > ptNextStart.y ;
+ }
+ else if ( nEdge == 2 ) {
+ return ptEnd.x < ptNextStart.x ;
+ }
+ else if ( nEdge == 3 ) {
+ return ptEnd.y < ptNextStart.y ;
+ }
+ return false ;
+}
+
diff --git a/Tree.h b/Tree.h
index 751c21f..dbb8378 100644
--- a/Tree.h
+++ b/Tree.h
@@ -17,6 +17,28 @@
#include