Compare commits

...

28 Commits

Author SHA1 Message Date
Daniele Bariletti d96ea77db7 EgtGeomKernel :
- correzione su coordinate U e V dei vertici delle TriMesh.
2023-09-26 12:22:32 +02:00
Daniele Bariletti b2bd8f7afe EgtGeomKernel :
- correzione su coordinate U e V ai vertici delle TriMesh.
2023-09-18 10:33:50 +02:00
Daniele Bariletti cb0452a248 EgtGeomKernel :
- aggiunta delle coordinate U e V ai vertici delle TriMesh.
Manca da modificare :
- funzione MoveVertex.
2023-09-18 10:21:49 +02:00
Daniele Bariletti 419d325409 EgtGeomKernel :
- correzione di bug nel trim di sup di Bezier chiuse
- correzione di bug nella conversione di NURBS in sup di Bezier
2023-09-12 14:49:43 +02:00
Daniele Bariletti 69166fe585 Merge branch '3dm_import' into Bezier_trim&mesh 2023-08-28 16:07:47 +02:00
Daniele Bariletti 8279e66cae EgtGeomKernel :
- correzione minore alle superfici di bezier
2023-06-23 16:56:48 +02:00
Daniele Bariletti 1c34e40289 Merge remote-tracking branch 'origin/HEAD' into Bezier_trim&mesh 2023-06-21 09:31:36 +02:00
Daniele Bariletti e9c22b895b EgtGeomKernel :
- risolti vari bug
- ridotto il calcolo del tree alle bbox delle curve di trim
2023-06-21 09:30:07 +02:00
Daniele Bariletti ebda605497 EgftGeomKernel :
- sistemati i bug noti
- pulito il codice
Da aggiungere :
- calcolo del tree solo nelle bbox delle curve di trim
2023-06-19 08:50:47 +02:00
Daniele Bariletti 06a69fa66b EgtGeomKernel :
- pulizia del codice
Problemi :
- bug dovuto a problemi numerici sulle intersezione tra trim e celle
2023-06-15 15:28:04 +02:00
Daniele Bariletti 4daa62db97 EgtGeomKernel :
- risolti i bug noti
- fatti con successo test con superfici e curve complesse
manca
- pulizia del codice.
2023-06-15 10:47:53 +02:00
Daniele Bariletti cb1edcf20a EgtGeomKernel :
- sistemati vari bug
Manca
- da testare superfici e trim complessi
2023-06-13 16:40:45 +02:00
Daniele Bariletti d3d7f94c3a EgtGeomKernel :
- risolti i bug noti
- gestiti problemi numerici al bordo delle celle
Manca
- test in casi più complicati
2023-06-13 11:55:33 +02:00
Daniele Bariletti 1aeb2809fa EgtGeomKernel :
- risolti i bug noti
Da migliorare:
- in caso di curve di trim sul bordo di celle, considero intersecate
quelle esterne
- possibili problemi numerici al bordo delle celle in FindInters
2023-06-09 17:51:47 +02:00
Daniele Bariletti 7cf933ec48 EgtGeomKernel :
- risolti i problemi di trim su superfici di bezier
Problemi noti:
- mancano ancora delle celle
- si formano delle crack
2023-06-07 17:43:23 +02:00
Daniele Bariletti f3346fd1f1 EgtGeomKernel :
- sistemati vari bug nella creazione della superficie trimesh trimmata
si una superficie di bezier
Problemi noti :
- sui casi con un tree reale entro in un loop infinito o seleziono oppure
seleziono un elemento inesistente di un vettore
2023-06-06 16:36:09 +02:00
Daniele Bariletti 579bc5492c EgtGeomKernel :
- sistemati vari bug nella creazione della superficie trimesh trimmata
si una superficie di bezier
Problemi noti :
- sui casi con un tree reale genero dei poligoni sbagliati per le celle
2023-06-06 10:40:03 +02:00
Daniele Bariletti 71ac2fde82 EgtGeomKernel :
- aggiunte tutte le funzionalità per la gestione delle superfici di bezier
con spazio parametrico trimmato
Manca :
- debug.
2023-06-05 12:12:47 +02:00
Daniele Bariletti 56d80f5bdd EgtGeomKernel :
- aggiustati dei bug
- implementati gli strumenti per la gestione delle celle non intersecate
Da aggiungere :
- categorizzazione celle rispetto ai loop.
2023-06-01 15:32:05 +02:00
Daniele Bariletti 4704554728 EgtGeomKernel :
- aggiunta la gestione delle aree di trim nested
Da aggiungere :
- gestione delle celle non intersecate dai loop
2023-05-30 09:05:26 +02:00
Daniele Bariletti e4243a2df3 EgtGeomKernel :
- implementato il trim dello spazio parametrico.
Da aggiungere :
- gestione delle celle non intersecate, interne ai loop
Problematiche :
- gestione di aree di trim nested in una cella
2023-05-29 09:02:51 +02:00
Daniele Bariletti 967f5aa795 Merge remote-tracking branch 'origin/master' into Bezier_trim&mesh 2023-05-19 12:17:38 +02:00
Daniele Bariletti f0429aefa4 EgtGeomKernel :
- migliorata la robustezza per il calcolo della curvatura
- pulizia del codice
Da aggiungere :
- gestione trim.
2023-05-18 15:07:27 +02:00
Daniele Bariletti c3b8677910 EgtGeomKernel :
- aggiunto lo split preliminare delle patches e impostato come default
- gestito il caso di superfici chiuse come il toro
- corretto un errore sul miglioramento delle prestazioni
Da aggiungere :
- gestione delle sup. trimmate.
2023-05-18 09:48:02 +02:00
Daniele Bariletti 268983804e EgtGeomKernel :
- gestite le superfici bilineari singole e multipatch
- gestite le superfici chiuse o su un parametro o sull'altro
- migliorate le prestazioni.
Da aggiungere :
- split preliminare delle patches
- la gestione delle sup. trimmate
2023-05-17 08:46:33 +02:00
Daniele Bariletti 8c79bbb2b6 EgtGeomKernel :
- completata l'implementazione della tassellazione adattiva per una
superficie di bezier
( si può migliorare il costo di memoria e computazionale)
- manca la gestione del trim dello spazio parametrico.
2023-05-10 15:35:42 +02:00
Daniele Bariletti 2d83c860f2 EgtGeomKernel :
- utilizzo di un binary tree al posto del kd-tree
- implementate le funzioni sul binary tree ( a parte il bilanciamento)
- errori noti : calcolo curvatura per decidere la direzione di split.
2023-05-08 17:02:02 +02:00
Daniele Bariletti 6a3fc0fd97 EgtGeomKernel :
- implementazione delle classi KdTree e Cell
- problemi : bilanciamento albero e uso puntatori
2023-05-03 12:09:58 +02:00
11 changed files with 3933 additions and 210 deletions
+1 -1
View File
@@ -558,7 +558,7 @@ NurbsToBezierCurve( const CNurbsData& cnData)
}
if ( ! bOk)
return nullptr ;
// se 1 solo intervallo, la Nurbs è già una curva di Bezier
if ( nInt == 1) {
// creo la curva di Bezier
+2
View File
@@ -342,6 +342,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="IntersPlaneTria.cpp" />
<ClCompile Include="IntersSurfTmSurfTm.cpp" />
<ClCompile Include="IntersTriaTria.cpp" />
<ClCompile Include="Tree.cpp" />
<ClCompile Include="MedialAxis.cpp" />
<ClCompile Include="OffsetCurve.cpp" />
<ClCompile Include="DistPointArc.cpp" />
@@ -610,6 +611,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClInclude Include="IntersLineSurfStd.h" />
<ClInclude Include="IntersLineTria.h" />
<ClInclude Include="IterManager.h" />
<ClInclude Include="Tree.h" />
<ClInclude Include="Material.h" />
<ClInclude Include="FontNfe.h" />
<ClInclude Include="MC_Tables.h" />
+6
View File
@@ -471,6 +471,9 @@
<ClCompile Include="MedialAxis.cpp">
<Filter>File di origine\GeoOffset</Filter>
</ClCompile>
<ClCompile Include="Tree.cpp">
<Filter>File di origine\Base</Filter>
</ClCompile>
<ClCompile Include="IntersLineCyl.cpp">
<Filter>File di origine\GeoInters</Filter>
</ClCompile>
@@ -1115,6 +1118,9 @@
<ClInclude Include="CDeCapsTria.h">
<Filter>File di intestazione</Filter>
</ClInclude>
<ClInclude Include="Tree.h">
<Filter>File di intestazione</Filter>
</ClInclude>
<ClInclude Include="IntersLineCyl.h">
<Filter>File di intestazione</Filter>
</ClInclude>
+7 -6
View File
@@ -76,18 +76,19 @@ StmFromTriangleSoup::AddTriangle( const Triangle3d& Tria)
//----------------------------------------------------------------------------
bool
StmFromTriangleSoup::AddTriangle( const Point3d& ptP0, const Point3d& ptP1, const Point3d& ptP2)
StmFromTriangleSoup::AddTriangle( const Point3d& ptP0, const Point3d& ptP1, const Point3d& ptP2,
const double dU0, const double dV0,const double dU1, const double dV1,const double dU2, const double dV2)
{
// verifico inizializzazione
if ( m_pSTM == nullptr)
return false ;
// ciclo sui tre vertici
int nIdV[3] ;
if ( ( nIdV[0] = AddVertex( ptP0)) == SVT_NULL)
if ( ( nIdV[0] = AddVertex( ptP0, dU0, dV0)) == SVT_NULL)
return false ;
if ( ( nIdV[1] = AddVertex( ptP1)) == SVT_NULL)
if ( ( nIdV[1] = AddVertex( ptP1, dU1, dV1)) == SVT_NULL)
return false ;
if ( ( nIdV[2] = AddVertex( ptP2)) == SVT_NULL)
if ( ( nIdV[2] = AddVertex( ptP2, dU2, dV2)) == SVT_NULL)
return false ;
// se i vertici sono tutti diversi tra loro, inserisco il triangolo
if ( nIdV[0] != nIdV[1] && nIdV[0] != nIdV[2] && nIdV[1] != nIdV[2]) {
@@ -99,14 +100,14 @@ StmFromTriangleSoup::AddTriangle( const Point3d& ptP0, const Point3d& ptP1, cons
//----------------------------------------------------------------------------
int
StmFromTriangleSoup::AddVertex( const Point3d& ptP)
StmFromTriangleSoup::AddVertex( const Point3d& ptP, const double dU, const double dV)
{
// verifico se già presente
int nId ;
if ( m_VertGrid.Find( ptP, 2 * EPS_SMALL, nId))
return nId ;
// aggiungo il vertice
if ( ( nId = m_pSTM->AddVertex( ptP)) == SVT_NULL)
if ( ( nId = m_pSTM->AddVertex( ptP, dU, dV)) == SVT_NULL)
return SVT_NULL ;
m_VertGrid.InsertPoint( ptP, nId) ;
return nId ;
+12 -129
View File
@@ -147,6 +147,10 @@ NurbsToBezierSurface(const CNurbsSurfData& cnData)
}
bool bRef = false ;
// se la superficie è lineare nel parametro U allora è già in forma di Bezier in questo parametro
if ( b == nU - 1 ) {
nb = 1 ;
}
while ( b < nU - 1) { // qui correggo un probabile errore, mettendo nU anziché nCPV, come indicato nell'algoritmo
int i = b ;
while ( b < nU - 1 && abs( cnData.vU[b+1] - cnData.vU[b]) < EPS_ZERO)
@@ -270,7 +274,7 @@ NurbsToBezierSurface(const CNurbsSurfData& cnData)
}
}
// devo vedere quante patch ci stanno prendendo i punti che ci sono
nb = (cnData.nCPU - 1) / cnData.nDegU ;
//nb = (cnData.nCPU - 1) / cnData.nDegU ;
}
else
nCPU_ref = cnData.nDegU * nb + 1 ; // numero dei punti di controllo in U dopo il raffinamento
@@ -308,7 +312,11 @@ NurbsToBezierSurface(const CNurbsSurfData& cnData)
}
bRef = false ;
while ( b < nV - 1) { // qui correggo un probabile errore, mettendo nU anziché nCPV, come indicato nell'algoritmo
// se la superficie è lineare nel parametro V allora è già in forma di Bezier in questo parametro
if ( b == nV - 1 ) {
nc = 1 ;
}
while ( b < nV - 1) {
int i = b ;
while ( b < nV - 1 && abs( cnData.vV[b+1] - cnData.vV[b]) < EPS_ZERO)
++ b ;
@@ -440,7 +448,7 @@ NurbsToBezierSurface(const CNurbsSurfData& cnData)
}
}
// devo vedere quante patch ci stanno prendendo i punti che ci sono
nc = (cnData.nCPV - 1) / cnData.nDegV ;
//nc = (cnData.nCPV - 1) / cnData.nDegV ;
}
else
nCPV_ref = cnData.nDegV * nc + 1 ;
@@ -465,129 +473,4 @@ NurbsToBezierSurface(const CNurbsSurfData& cnData)
}
}
return Release( pSrfBz) ;
}
//// algoritmo per le curve, da usare come reference///////////////////////////////////////////////////////////////////////////////
//
//
// // vettore dei punti di controllo della curva di Bezier
// PNTVECTOR vBC ;
// vBC.resize( cnData.nDeg + 1) ;
// DBLVECTOR vBW ;
// vBW.resize( cnData.nDeg + 1) ;
// if ( ! cnData.bRat) {
// for ( int i = 0 ; i <= cnData.nDeg ; ++ i)
// vBC[i] = cnData.vCP[i] ;
// }
// else {
// for ( int i = 0 ; i <= cnData.nDeg ; ++ i) {
// vBC[i] = cnData.vCP[i] * cnData.vW[i] ;
// vBW[i] = cnData.vW[i] ;
// }
// }
// // primi coefficienti della successiva
// PNTVECTOR vNextBC ;
// vNextBC.resize( cnData.nDeg - 1) ;
// DBLVECTOR vNextBW ;
// vNextBW.resize( cnData.nDeg - 1) ;
// // ...
// DBLVECTOR vAlfa ;
// vAlfa.resize( cnData.nDeg - 1) ;
// int a = cnData.nDeg - 1 ;
// int b = cnData.nDeg ;
// bool bPrevRejected = false ;
// // ciclo
// while ( b < nU - 1) {
// int i = b ;
// while ( b < nU - 1 && abs( cnData.vU[b+1] - cnData.vU[b]) < EPS_ZERO)
// ++ b ;
// int mult = min( b - i + 1, cnData.nDeg) ;
// if ( mult < cnData.nDeg) {
// // numeratore di alfa
// double numer = cnData.vU[b] - cnData.vU[a] ;
// // calcola e salva gli alfa
// for ( int j = cnData.nDeg ; j > mult ; -- j)
// vAlfa[j-mult-1] = numer / ( cnData.vU[a+j] - cnData.vU[a]) ;
// // inserisco il nodo r volte
// int r = cnData.nDeg - mult ;
// for ( int j = 1 ; j <= r ; ++ j) {
// int save = r - j ;
// int s = mult + j ;
// for ( int k = cnData.nDeg ; k >= s ; -- k)
// vBC[k] = vAlfa[k-s] * vBC[k] + ( 1 - vAlfa[k-s]) * vBC[k-1] ;
// if ( cnData.bRat) {
// for ( int k = cnData.nDeg ; k >= s ; -- k)
// vBW[k] = vAlfa[k-s] * vBW[k] + ( 1 - vAlfa[k-s]) * vBW[k-1] ;
// }
// if ( b < nU - 1) {
// vNextBC[save] = vBC[cnData.nDeg] ;
// if ( cnData.bRat)
// vNextBW[save] = vBW[cnData.nDeg] ;
// }
// }
// }
//
// // costruisco la curva di Bezier e la inserisco nella curva composita
// PtrOwner<ICurveBezier> pCrvBez( CreateCurveBezier()) ;
// if ( IsNull( pCrvBez))
// return nullptr ;
// // se precedente saltata
// if ( bPrevRejected) {
// // prendo l'ultimo punto della curva composita per garantire la continuità
// Point3d ptEnd ;
// if ( pCrvCompo->GetEndPoint( ptEnd))
// vBC[0] = ptEnd ;
// }
// // la inizializzo
// if ( ! pCrvBez->Init( cnData.nDeg, cnData.bRat))
// return nullptr ;
// if ( ! cnData.bRat) {
// for ( int i = 0 ; i <= cnData.nDeg ; ++ i) {
// if ( ! pCrvBez->SetControlPoint( i, vBC[i]))
// return nullptr ;
// }
// }
// else {
// for ( int i = 0 ; i <= cnData.nDeg ; ++ i) {
// if ( ! pCrvBez->SetControlPoint( i, vBC[i] / vBW[i], vBW[i]))
// return nullptr ;
// }
// }
// // se è una vera curva, la aggiungo alla curva composita
// if ( ! pCrvBez->IsAPoint()) {
// if ( ! pCrvCompo->AddCurve( Release( pCrvBez)))
// return nullptr ;
// bPrevRejected = false ;
// }
// // altrimenti è un punto, la cancello
// else {
// pCrvBez.Reset() ;
// bPrevRejected = true ;
// }
//
// // inizializzazioni per la prossima curva di Bezier
// if ( b < nU - 1) {
// if ( ! cnData.bRat) {
// for ( int i = 0 ; i < cnData.nDeg - 1 ; ++ i)
// vBC[i] = vNextBC[i] ;
// for ( int i = cnData.nDeg - mult ; i <= cnData.nDeg ; ++ i)
// vBC[i] = cnData.vCP[b-cnData.nDeg+i+1] ;
// }
// else {
// for ( int i = 0 ; i < cnData.nDeg - 1 ; ++ i) {
// vBC[i] = vNextBC[i] ;
// vBW[i] = vNextBW[i] ;
// }
// for ( int i = cnData.nDeg - mult ; i <= cnData.nDeg ; ++ i) {
// vBC[i] = cnData.vCP[b-cnData.nDeg+i+1] * cnData.vW[b-cnData.nDeg+i+1] ;
// vBW[i] = cnData.vW[b-cnData.nDeg+i+1] ;
// }
// }
// a = b ;
// ++ b ;
// }
// }
//
// // restituisco la curva composita
// return Release( pCrvCompo) ;
//}
}
+193 -67
View File
@@ -20,6 +20,9 @@
#include "Bernstein.h"
#include "CurveBezier.h"
#include "CurveComposite.h"
#include "Tree.h"
#include "Triangulate.h"
#include "SurfTriMesh.h"
#include "/EgtDev/Include/EGkSfrCreate.h"
#include "/EgtDev/Include/EGkStmFromTriangleSoup.h"
#include "/EgtDev/Include/EGkStringUtils3d.h"
@@ -33,12 +36,13 @@ using namespace std ;
GEOOBJ_REGISTER( SRF_BEZIER, NGE_S_BEZ, SurfBezier) ;
//----------------------------------------------------------------------------
SurfBezier::SurfBezier(void)
SurfBezier::SurfBezier( void)
: m_pSTM( nullptr), m_nStatus( TO_VERIFY), m_nDegU(), m_nDegV(), m_nSpanU(), m_nSpanV(), m_bRat( false),
m_bTrimmed( false), m_pTrimReg( nullptr)
{
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
}
//----------------------------------------------------------------------------
@@ -144,6 +148,15 @@ SurfBezier::SetTrimRegion( const ISurfFlatRegion& sfrTrimReg)
return true ;
}
//----------------------------------------------------------------------------
SurfFlatRegion*
SurfBezier::GetTrimRegion( void) const
{
if ( ! m_bTrimmed || m_pTrimReg == nullptr )
return nullptr ;
return m_pTrimReg ;
}
//----------------------------------------------------------------------------
bool
SurfBezier::GetInfo( int& nDegU, int& nDegV, int& nSpanU, int& nSpanV, bool& bIsRat, bool& bTrimmed) const
@@ -1218,39 +1231,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<CurveComposite> pLoop( CreateBasicCurveComposite()) ;
// prima curva isoparametrica in U con V=0
// prima curva isoparametrica in U con V=0
PtrOwner<CurveComposite> 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<CurveComposite> 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<CurveComposite> 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<CurveComposite> 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<CurveComposite> pLoop( GetBasicCurveComposite( m_pTrimReg->GetLoop( nChunck, nLoopLoc))) ;
return Release( pLoop) ;
}
}
}
//----------------------------------------------------------------------------
@@ -1372,6 +1408,82 @@ SurfBezier::GetCurveOnVApproxLen( double dU) const
return 0 ;
return dLen ;
}
//
////----------------------------------------------------------------------------
//const SurfTriMesh*
//SurfBezier::GetAuxSurf( void) const
//{
// // la superficie deve essere validata
// if ( m_nStatus != OK) {
// ResetAuxSurf() ;
// return nullptr ;
// }
// // se già calcolata, la restituisco
// if ( m_pSTM != nullptr)
// return m_pSTM ;
// // costruttore della superficie
// StmFromTriangleSoup stmSoup ;
// if ( ! stmSoup.Start())
// return nullptr ;
// // definisco il numero degli step in U e in V
// double dMaxLenU = 0 ;
// for ( int j = 0 ; j <= m_nDegV * m_nSpanV ; ++ j)
// dMaxLenU = max( dMaxLenU, GetCurveOnUApproxLen( double( j) / m_nDegV)) ;
// int nStepU = GetSteps( m_nDegU, m_nSpanU, dMaxLenU, 2) ;
// double dMaxLenV = 0 ;
// for ( int i = 0 ; i <= m_nDegU * m_nSpanU ; ++ i)
// dMaxLenV = max( dMaxLenV, GetCurveOnVApproxLen( double( i) / m_nDegU)) ;
// int nStepV = GetSteps( m_nDegV, m_nSpanV, dMaxLenV, 2) ;
// // prima curva isoparametrica (potrebbe essere un solo punto)
// PolyLine PL1 ;
// GetCurveOnU( 0, nStepU, PL1) ;
// bool bSingle1 = ( PL1.GetPointNbr() == 1) ;
// // ciclo sulle isoparametriche
// for ( int i = 1 ; i <= nStepV ; ++ i) {
// // seconda curva isoparametrica (con tanti punti quanti la prima, oppure uno solo)
// double dV = double( i) * m_nSpanV / nStepV ;
// PolyLine PL2 ;
// GetCurveOnU( dV, nStepU, PL2) ;
// bool bSingle2 = ( PL2.GetPointNbr() == 1) ;
// // inserisco i triangoli della striscia nel costruttore della TriMesh
// Point3d ptP1c, ptP2c ;
// Point3d ptP1n, ptP2n ;
// bool bNext = PL1.GetFirstPoint( ptP1c) && PL2.GetFirstPoint( ptP2c) ;
// if ( bNext) {
// if ( bSingle1 && bSingle2)
// bNext = false ;
// if ( bSingle1)
// ptP1n = ptP1c ;
// else
// bNext = bNext && PL1.GetNextPoint( ptP1n) ;
// if ( bSingle2)
// ptP2n = ptP2c ;
// else
// bNext = bNext && PL2.GetNextPoint( ptP2n) ;
// }
// while ( bNext) {
// // eventuale primo triangolo (con base sui correnti e vertice su P2 successivo)
// if ( ! AreSamePointApprox( ptP1c, ptP2c))
// stmSoup.AddTriangle( ptP2c, ptP1c, ptP2n) ;
// // eventuale secondo triangolo (con vertice su P1 corrente e base sui successivi)
// if ( ! AreSamePointApprox( ptP1n, ptP2n))
// stmSoup.AddTriangle( ptP1c, ptP1n, ptP2n) ;
// // passo alla successiva coppia
// ptP1c = ptP1n ;
// ptP2c = ptP2n ;
// bNext = ( bSingle1 || PL1.GetNextPoint( ptP1n)) && ( bSingle2 || PL2.GetNextPoint( ptP2n)) ;
// }
// // salvo isoparametrica PL2 in PL1
// PL1.GetUPointList().swap( PL2.GetUPointList()) ;
// bSingle1 = bSingle2 ;
// }
// // la completo
// if ( ! stmSoup.End())
// return nullptr ;
// // la salvo
// m_pSTM = GetBasicSurfTriMesh( stmSoup.GetSurf()) ;
// return m_pSTM ;
//}
//----------------------------------------------------------------------------
const SurfTriMesh*
@@ -1385,70 +1497,84 @@ SurfBezier::GetAuxSurf( void) const
// se già calcolata, la restituisco
if ( m_pSTM != nullptr)
return m_pSTM ;
// costruttore della superficie
// costruttore della superficie
vector<POLYLINEVECTOR> vvPL ;
Tree Tree( this, true) ;
std::vector<std::tuple<Point3d,Point3d>> vTrees ;
Tree.GetIndependentTrees( vTrees) ;
for ( int i = 0 ; i < (int) vTrees.size() ; ++ i) {
Point3d ptMin = std::get<0>( vTrees[i]) ;
Point3d ptMax = std::get<1>( vTrees[i]) ;
Tree.SetSurf( this, true, ptMin, ptMax) ;
//Tree.BuildTree_test() ;
Tree.BuildTree( 5 * LIN_TOL_FINE, 1) ;
Tree.GetPolygons( vvPL) ;
}
PtrOwner<SurfTriMesh> pSrfTm( CreateBasicSurfTriMesh()) ;
StmFromTriangleSoup stmSoup ;
if ( ! stmSoup.Start())
return nullptr ;
// definisco il numero degli step in U e in V
double dMaxLenU = 0 ;
for ( int j = 0 ; j <= m_nDegV * m_nSpanV ; ++ j)
dMaxLenU = max( dMaxLenU, GetCurveOnUApproxLen( double( j) / m_nDegV)) ;
int nStepU = GetSteps( m_nDegU, m_nSpanU, dMaxLenU, 2) ;
double dMaxLenV = 0 ;
for ( int i = 0 ; i <= m_nDegU * m_nSpanU ; ++ i)
dMaxLenV = max( dMaxLenV, GetCurveOnVApproxLen( double( i) / m_nDegU)) ;
int nStepV = GetSteps( m_nDegV, m_nSpanV, dMaxLenV, 2) ;
// prima curva isoparametrica (potrebbe essere un solo punto)
PolyLine PL1 ;
GetCurveOnU( 0, nStepU, PL1) ;
bool bSingle1 = ( PL1.GetPointNbr() == 1) ;
// ciclo sulle isoparametriche
for ( int i = 1 ; i <= nStepV ; ++ i) {
// seconda curva isoparametrica (con tanti punti quanti la prima, oppure uno solo)
double dV = double( i) * m_nSpanV / nStepV ;
PolyLine PL2 ;
GetCurveOnU( dV, nStepU, PL2) ;
bool bSingle2 = ( PL2.GetPointNbr() == 1) ;
// inserisco i triangoli della striscia nel costruttore della TriMesh
Point3d ptP1c, ptP2c ;
Point3d ptP1n, ptP2n ;
bool bNext = PL1.GetFirstPoint( ptP1c) && PL2.GetFirstPoint( ptP2c) ;
if ( bNext) {
if ( bSingle1 && bSingle2)
bNext = false ;
if ( bSingle1)
ptP1n = ptP1c ;
else
bNext = bNext && PL1.GetNextPoint( ptP1n) ;
if ( bSingle2)
ptP2n = ptP2c ;
else
bNext = bNext && PL2.GetNextPoint( ptP2n) ;
// prendo i punti di ogni polyline dell'albero, li triangolo e li porto in 3d
for ( POLYLINEVECTOR vPL : vvPL) {
PNTVECTOR vPnt ;
INTVECTOR vTria ;
Triangulate Tri ;
if ( ! Tri.Make( vPL, vPnt, vTria))
return nullptr ;
// porto i punti in 3d
PNTVECTOR vPnt3d ;
for ( int i = 0 ; i < int( vPnt.size()) ; ++ i) {
Point3d pt3d ;
if ( ! GetPointD1D2( vPnt[i].x / SBZ_TREG_COEFF, vPnt[i].y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d))
return nullptr ;
vPnt3d.push_back( pt3d) ;
}
while ( bNext) {
// eventuale primo triangolo (con base sui correnti e vertice su P2 successivo)
if ( ! AreSamePointApprox( ptP1c, ptP2c))
stmSoup.AddTriangle( ptP2c, ptP1c, ptP2n) ;
// eventuale secondo triangolo (con vertice su P1 corrente e base sui successivi)
if ( ! AreSamePointApprox( ptP1n, ptP2n))
stmSoup.AddTriangle( ptP1c, ptP1n, ptP2n) ;
// passo alla successiva coppia
ptP1c = ptP1n ;
ptP2c = ptP2n ;
bNext = ( bSingle1 || PL1.GetNextPoint( ptP1n)) && ( bSingle2 || PL2.GetNextPoint( ptP2n)) ;
int nTria = int( vTria.size()) / 3 ;
for ( int i = 0 ; i < nTria ; ++i) {
if ( ! stmSoup.AddTriangle( vPnt3d[vTria[3*i]], vPnt3d[vTria[3*i+1]], vPnt3d[vTria[3*i+2]],
vPnt[vTria[3*i]].x, vPnt[vTria[3*i]].y,
vPnt[vTria[3*i+1]].x, vPnt[vTria[3*i+1]].y,
vPnt[vTria[3*i+2]].x, vPnt[vTria[3*i+2]].y))
return nullptr ;
}
// salvo isoparametrica PL2 in PL1
PL1.GetUPointList().swap( PL2.GetUPointList()) ;
bSingle1 = bSingle2 ;
}
// la completo
}
// la salvo
if ( ! stmSoup.End())
return nullptr ;
// la salvo
m_pSTM = GetBasicSurfTriMesh( stmSoup.GetSurf()) ;
return m_pSTM ;
}
//----------------------------------------------------------------------------
bool
SurfBezier::GetLeaves( std::vector<std::tuple<int, Point3d, Point3d>>& vLeaves) const
{
std::vector<Cell> vCells ;
Tree Tree( this, true) ;
std::vector<std::tuple<Point3d,Point3d>> vTrees ;
Tree.GetIndependentTrees( vTrees) ;
for ( int i = 0 ; i < (int) vTrees.size() ; ++ i) {
Point3d ptMin = std::get<0>( vTrees[i]) ;
Point3d ptMax = std::get<1>( vTrees[i]) ;
Tree.SetSurf( this, true, ptMin, ptMax) ;
//Tree.BuildTree_test() ;
Tree.BuildTree( 5 * LIN_TOL_FINE, 1) ;
Tree.GetLeaves( vCells) ;
for (int k = 0 ; k < (int)vCells.size(); ++ k ) {
std::tuple<int, Point3d, Point3d> tCell ;
tCell = make_tuple( vCells[k].m_nId, vCells[k].GetBottomLeft(), vCells[k].GetTopRight()) ;
vLeaves.push_back( tCell) ;
}
}
return true ;
}
//----------------------------------------------------------------------------
void
SurfBezier::ResetAuxSurf( void) const
+3 -1
View File
@@ -83,6 +83,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
{ return SetControlPoint( GetInd( nIndU, nIndV), ptCtrl, dW) ; }
bool SetControlPoint( int nInd, const Point3d& ptCtrl, double dW) override ;
bool SetTrimRegion( const ISurfFlatRegion& sfrTrimReg) override ;
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) ; }
@@ -105,6 +106,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
bool GetControlCurveOnU( int nIndV, PolyLine& plCtrlU) const override ;
bool GetControlCurveOnV( int nIndU, PolyLine& plCtrlV) const override ;
const SurfTriMesh* GetAuxSurf( void) const override ;
bool GetLeaves( std::vector<std::tuple<int, Point3d, Point3d>>& vLeaves) const override ;
public : // IGeoObjRW
int GetNgeId( void) const override ;
@@ -166,7 +168,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
PNTVECTOR m_vPtCtrl ; // vettore dei punti di controllo
DBLVECTOR m_vWeCtrl ; // vettore dei pesi di controllo
SurfFlatRegion* m_pTrimReg ; // eventuale regione di trim
int m_nTempProp[2] ; // vettore proprietà temporanee
int m_nTempProp[2] ; // vettore proprietà temporanee
} ;
//-----------------------------------------------------------------------------
+44 -2
View File
@@ -107,7 +107,7 @@ SurfTriMesh::Clear( void)
//----------------------------------------------------------------------------
int
SurfTriMesh::AddVertex( const Point3d& ptVert)
SurfTriMesh::AddVertex( const Point3d& ptVert, const double dU, const double dV)
{
// imposto ricalcolo
m_nStatus = TO_VERIFY ;
@@ -118,7 +118,11 @@ SurfTriMesh::AddVertex( const Point3d& ptVert)
try { m_vVert.emplace_back( ptVert) ;}
catch(...) { return SVT_NULL ;}
// ne determino l'indice
return int( m_vVert.size() - 1) ;
int nId = int( m_vVert.size() - 1) ;
// aggiugo le coordinate corrispondenti allo spazio parametrico
m_vVert[nId].dU = dU ;
m_vVert[nId].dV = dV ;
return nId ;
}
//----------------------------------------------------------------------------
@@ -475,6 +479,19 @@ SurfTriMesh::GetVertex( int nId, Point3d& ptP) const
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::GetVertexParam( int nId, double& dU, double& dV) const
{
// verifico esistenza del vertice
if ( nId < 0 || nId >= GetVertexSize() || m_vVert[nId].nIdTria == SVT_DEL)
return false ;
// recupero i dati
dU = m_vVert[nId].dU ;
dV = m_vVert[nId].dV ;
return true ;
}
//----------------------------------------------------------------------------
int
SurfTriMesh::GetFirstVertex( Point3d& ptP) const
@@ -482,6 +499,13 @@ SurfTriMesh::GetFirstVertex( Point3d& ptP) const
return GetNextVertex( SVT_NULL, ptP) ;
}
//----------------------------------------------------------------------------
int
SurfTriMesh::GetFirstVertexParam( int nId, double& dU, double& dV) const
{
return GetNextVertexParam( SVT_NULL, dU, dV) ;
}
//----------------------------------------------------------------------------
int
SurfTriMesh::GetNextVertex( int nId, Point3d& ptP) const
@@ -499,6 +523,24 @@ SurfTriMesh::GetNextVertex( int nId, Point3d& ptP) const
return nId ;
}
//----------------------------------------------------------------------------
int
SurfTriMesh::GetNextVertexParam( int nId, double& dU, double& dV) const
{
// cerco il primo successivo valido
do {
nId ++ ;
} while ( nId < GetVertexSize() && m_vVert[nId].nIdTria == SVT_DEL) ;
// se oltrepassata fine
if ( nId >= GetVertexSize())
return SVT_NULL ;
// recupero i dati
dU = m_vVert[nId].dU ;
dV = m_vVert[nId].dV ;
// ritorno indice triangolo corrente
return nId ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::GetTriangle( int nId, int nIdVert[3]) const
+11 -4
View File
@@ -28,11 +28,15 @@ class SurfFlatRegion ;
class StmVert
{
public :
StmVert( void) : ptP(), nIdTria( SVT_NULL), nFlag( 0), nTemp( 0) {}
StmVert( const Point3d& ptQ) : ptP( ptQ), nIdTria( SVT_NULL), nFlag( 0), nTemp( 0) {}
StmVert( const Point3d& ptQ, int nIdT, int nF) : ptP( ptQ), nIdTria( nIdT), nFlag( nF), nTemp( 0) {}
StmVert( void) : ptP(), dU( -1), dV( -1), nIdTria( SVT_NULL), nFlag( 0), nTemp( 0) {}
StmVert( const Point3d& ptQ) : ptP( ptQ), dU( -1), dV( -1), nIdTria( SVT_NULL), nFlag( 0), nTemp( 0) {}
StmVert( const Point3d& ptQ, int nIdT, int nF) : ptP( ptQ), dU( -1), dV( -1), nIdTria( nIdT), nFlag( nF), nTemp( 0) {}
public :
Point3d ptP ;
double dU ; // parametro riferito alle coordinate del punto nello spazio parametrico ( nSpanU x 1000) ( nSpanV x 1000)
// della sup di Bezier // -1 se non definito
double dV ; // parametro riferito alle coordinate del punto nello spazio parametrico ( nSpanU x 1000) ( nSpanV x 1000)
// della sup di Bezier // -1 se non definito
int nIdTria ;
int nFlag ;
mutable int nTemp ;
@@ -215,7 +219,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
{ m_dSmoothAng = std::max( dSmoothAngDeg, EPS_ANG_SMALL) ;
m_dCosSmAng = cos( m_dSmoothAng * DEGTORAD) ;
m_OGrMgr.Reset() ; }
int AddVertex( const Point3d& ptVert) override ;
int AddVertex( const Point3d& ptVert, const double dU = -1 , const double dV = -1) override ;
bool MoveVertex( int nInd, const Point3d& ptNewVert) override ;
int AddTriangle( const int nIdVert[3], int nTFlag = 0) override ;
bool RemoveTriangle( int nId) override ;
@@ -244,8 +248,11 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
double GetSmoothAngle( void) const override
{ return m_dSmoothAng ; }
bool GetVertex( int nId, Point3d& ptP) const override ;
bool GetVertexParam( int nId, double& dU, double& dV) const override ;
int GetFirstVertex( Point3d& ptP) const override ;
int GetFirstVertexParam( int nId, double& dU, double& dV) const override ;
int GetNextVertex( int nId, Point3d& ptP) const override ;
int GetNextVertexParam( int nId, double& dU, double& dV) const override ;
bool GetTriangle( int nId, int nIdVert[3]) const override ;
int GetFirstTriangle( int nIdVert[3]) const override ;
int GetNextTriangle( int nId, int nIdVert[3]) const override ;
+3452
View File
File diff suppressed because it is too large Load Diff
+202
View File
@@ -0,0 +1,202 @@
//----------------------------------------------------------------------------
// 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 <map>
#include "SurfBezier.h"
#include "GeoConst.h"
#include "CurveLine.h"
#include "/EgtDev/Include/EGkPolyLine.h"
struct Inters {
int nIn ;
PNTVECTOR vpt ;
int nOut ;
bool bCCW ;
bool bVertex ;
int nChunk ;
// riordino le intersezioni per lato in senso antiorario dal top
// se ho più intersezioni che entrano in un lato le riordino considerando che percorro i lati in senso antiorario a partire da ptTR
bool operator < ( Inters& b) {
// trovo in che ordine stanno i due strat, tenendo conto anche della possibilità che siano vertici
INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6, 3} ;
INTVECTOR::iterator iter1 = find( vEdges.begin(), vEdges.end(), nIn) ;
int nPos1 = std::distance( vEdges.begin(), iter1) ;
INTVECTOR::iterator iter2 = find( vEdges.begin(), vEdges.end(), b.nIn) ;
int nPos2 = std::distance( vEdges.begin(), iter2) ;
// se sono loop interni li ordino in modo decrescente rispetto all'area
bool bEqIn = ( nIn == b.nIn) ;
double dAreaA = 0 , dAreaB = 0 ;
if ( bEqIn && nIn == -1) {
PolyLine pl ;
for ( int k = 0 ; k < (int)vpt.size(); ++ k)
pl.AddUPoint( k, vpt[k]) ;
pl.Close() ;
pl.GetAreaXY( dAreaA) ;
pl.Clear() ;
for ( int k = 0 ; k < (int)b.vpt.size(); ++ k)
pl.AddUPoint( k, b.vpt[k]) ;
pl.Close() ;
pl.GetAreaXY( dAreaB) ;
}
// se nIn è un vertice sistemo il valore
int nEdgeIn = nIn ;
if ( nIn > 3)
nEdgeIn = nIn - 4 ;
return nPos1 < nPos2 ||
( bEqIn && nEdgeIn == -1 && abs(dAreaA) > abs(dAreaB)) ||
( bEqIn && nEdgeIn == 0 && vpt[0].x > b.vpt[0].x) ||
( bEqIn && nEdgeIn == 1 && vpt[0].y > b.vpt[0].y) ||
( bEqIn && nEdgeIn == 2 && vpt[0].x < b.vpt[0].x) ||
( bEqIn && nEdgeIn == 3 && vpt[0].y < b.vpt[0].y)
; }
bool operator == ( Inters& b) {
return AreSamePointExact( vpt[0], b.vpt[0]) ;
}
bool operator != ( Inters& b){
return ! AreSamePointExact( vpt[0], b.vpt[0]) ;
}
} ;
// nIn e nOut sono flag che indicano da quale lato ho l'ingresso e l'uscita a partire dal lato top in senso antiorario
// oltre il 3 sono le celle adiacenti in diagonale al vertice-> 4 corrisponde al ptTl e da lì in senso antiorario
// -1 se la curva è sempre dentro la cella
//----------------------------------------------------------------------------
class Cell
{
// Edge 0 ( Top)
// Edge 4 ( NW) __________________ Edge 7 ( NE)
// | |
// | |
// Edge 1 ( Left) | | Edge 3 ( Right)
// | |
// | |
// |_________________|
// Edge 5 ( SW) Edge 2 (Bottom) Edge 6 ( SE)
public :
~Cell( void) ;
Cell( void) ;
Cell( const Point3d& ptBL, const Point3d& ptTR) ;
inline bool IsSame( const Cell& cOtherCell) const ;
void SetBottomLeft( const Point3d ptBL) { m_ptPbl = ptBL ; }
void SetTopRight( const Point3d ptTR) { m_ptPtr = ptTR ; }
void SetSplitDirVert( const bool bVert) { m_bSplitVert = bVert ; }
void SetParent( const int& nParent) { m_nParent = nParent ; }
Point3d GetBottomLeft( void) const { return m_ptPbl ; }
Point3d GetTopRight( void) const { return m_ptPtr ; }
double GetSplitValue( void) const { return m_dSplit ; }
bool IsSplitVert( void) const { return m_bSplitVert ; } // se true la cella verrebbe splittata verticalmente, sennò orizzontalmente
bool IsLeaf( void) const ; // flag che indica se la cella ha figli o se è una foglia
bool IsProcessed( void) const { return m_bProcessed ; } // flag che indica se tutti i figli della cella, se ce ne sono, sono stati processati
void SetProcessed( const bool bProcessed = true) { m_bProcessed = bProcessed ; }
static bool minorX ( const Cell& c1, const Cell& c2) { return c1.m_ptPbl.x < c2.m_ptPbl.x ; }
static bool minorY ( const Cell& c1, const Cell& c2) { return c1.m_ptPbl.y < c2.m_ptPbl.y ; }
public :
int m_nId ; // Id della cella
int m_nTop ; // cella adiacente al lato top
int m_nBottom ; // cella adiacente al lato bottom
int m_nLeft ; // cella adiacente al lato left
int m_nRight ; // cella adiacente al lato right
int m_nParent ; // cella genitore
int m_nDepth ; // profondità della cella rispetto a root
double m_dSplit ; // parametro a cui è stata splittata la cella
int m_nChild1 ; // prima cella figlio
int m_nChild2 ; // seconda cella figlio
int m_nFlag ; // falg che indica la caratterizzazione della cella rispetto ai loop di trim
// 0 esterna, 1 intersecata, 2 contiene un loop, 3 intersecata e contenente un loop, 4 contenuta in un loop
int m_nFlag2 ; // falg che indica se la cella è stata attraversata durante l'ultima fase del labelling
int m_nRightEdgeIn ; // 0 right edge fuori, 1 right edge dentro, 2 metà e metà
bool m_bOnLeftEdge ; // flag che indica se la cella è sul lato sinistro ( per superfici chiuse)
std::vector<Inters> m_vInters ; // vettore delle intersezioni della cella con i loop di trim
// ogni elemento del vettore è l'insieme dei punti che caratterizza un atrtaversamento della cella
private :
Point3d m_ptPbl ; // punto bottom left
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
} ;
//----------------------------------------------------------------------------
class Tree
{
public :
~Tree( void) ;
Tree( void) ;
Tree ( const SurfBezier* pSrfBz, const bool bSplitPatches = true, const Point3d ptMin = ORIG, const Point3d ptMax = ORIG) ;
void SetSurf( const SurfBezier* pSrfBz, const bool bSplitPatches = true, const Point3d ptMin = ORIG, const Point3d ptMax = ORIG) ;
bool GetIndependentTrees( std::vector<std::tuple<Point3d,Point3d>>& vTrees) ; // calcolo la suddivisione della superficie solo sulle singole bbox dei loop di trim ( unendo quelli vicini)
bool BuildTree( const double& dLinTol = LIN_TOL_STD, const double& dSideMin = 1, const double& dSideMax = INFINITO) ; // dSideMax è il massimo per la dimensione maggiore di un triangolo della trimesh
// dSideMin è lunghezza minima del lato di una cella nello spazio reale
bool BuildTree_test( const double& dLinTol = LIN_TOL_STD, const double& dSideMin = 1, const double& dSideMax = INFINITO) ;
bool GetPolygons( std::vector<POLYLINEVECTOR>& vPolygons) ;
bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero
// ad ogni poligono sono stati aggiunti tutti i vertici dei vicini posizionati sui suoi lati
bool GetLeaves ( std::vector<Cell>& vLeaves) const ;
private :
void Split( const int& nId, const double& dSplitValue) ; // funzione di split di una cella al parametro indicato nella direzione data da bVert
void Split( const int& nId) ; // funzione di split di una cella dell'albero a metà nella direzione data da bVert
void Balance () ; // creo rami in modo che tutte tutte le foglie abbiano come adiacenti foglie ad una profonditù di +- 1
int GetHeightLeaves ( const int& nId, INTVECTOR& vnLeaves, int d = 0) const ; // altezza del subtree a partire dal nodo nId
int GetDepth ( const int& nId, const int& nRef) const ; // livello del nodo nId
void GetTopNeigh( const int& nId, INTVECTOR& vTopNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato top
void GetBottomNeigh( const int& nId, INTVECTOR& vBottomNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato bottom
void GetLeftNeigh( const int& nId, INTVECTOR& vLeftNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato left
void GetRightNeigh( const int& nId, INTVECTOR& vRightNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato right
void GetRootNeigh( const int& nEdge, INTVECTOR& vNeigh) ; // restituisce le foglie dell'albero che sono adiacenti al lato nEdge, numerato a partire dal top ( 0) in senso antiorario
void ResetTree ( void) ; // resetto m_bProcessed a false per tutti i nodi dell'albero
INTVECTOR FindCell ( const Point3d& ptToAssign, const CurveLine& cl) const ; // dato un punto, trova la cella foglia a cui appartiene
INTVECTOR FindCell ( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells) const ; // dato un punto, trova la cella foglia a cui appartiene
bool TraceLoopLabelCell( void) ; // tracing dei loop e labelling delle celle
bool FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool bFirstInters = true) ; // trova le intersezioni tra una cella e una linea di trim
// resituisce l'id della cella verso cui la curva di trim esce e il vettore delle intersezioni per la cella successiva con il primo punto
bool CreateCellPolygons ( const int& nLeafId, std::vector<POLYLINEVECTOR>& vPolygons, INTVECTOR& vToCheck, int& nPoly, INTVECTOR& vnParentChunk, const PolyLine& plCell) ;
bool CreateIslandAndHoles ( const int& nLeafId, std::vector<POLYLINEVECTOR>& vPolygons, int& nPoly, INTVECTOR& vnParentChunk) ;
bool CheckIfBefore( const PolyLine& pl, const int& nEdge) const ;
bool CheckIfBefore( const Inters& inA) const ;
bool CheckIfBefore( const int& nEdge1, const Point3d& ptP1, const int& nEdge2, const Point3d& ptP2) const ; // punto 1 su edge 1 e punto 2 su edge 2, rispetto al lato 3
bool CheckIfBefore( const int& nEdge, const Point3d& ptP1, const Point3d& ptP2, const int& nEdge2 = -1) const ; // entrambi i punti sullo stesso lato, nEdge. nEdge2 serve come backup, in caso nEdge sia un vertice.
bool AreSameEdge( const int& nEdge1, const int nEdge2) const ;
bool AddVertex( const int& nId, const std::vector<PNTVECTOR>& vEdgeVertex, PolyLine& plTrimmedPoly, int& c, const Point3d& ptToAdd) const ;
//bool SetRightEdgeIn( int nId, std::vector<PNTVECTOR>& vEdgeVertex, PolyLine& plTrimmedPoly) ;
bool SetRightEdgeIn( const int& nId) ;
bool CategorizeCell( const int& nId) ;
bool CheckIfBetween( const Inters& inA, const Inters& inB) const ;
bool OnWhichEdge( const int& nId, const Point3d& ptToAssign, int& nEdge) const ;
private :
const SurfBezier* m_pSrfBz ; // superficie di bezier
DBLVECTOR m_vDim ; // distanze tra i vertici della superficie di bezier in 3d in ordine antiorario a partire da ptP00
bool m_bTrimmed ; // superficie trimmata
std::vector<INTVECTOR> m_vChunk ; // elenco dei loop divisi per chunk
std::map<int,int> m_mChunk ;
ICURVEPOVECTOR m_vLoop ; // curve di loop
std::vector<std::tuple<PolyLine,bool>> m_vPlApprox ;
bool m_bBilinear ; // superficie bilineare
bool m_bMulti ; // superficie multi-patch
bool m_bClosed ; // superficie chiusa
bool m_bSplitPatches ; // flag che indica se le patches sono state divise prima della creazione dell'albero
int m_nDegU ; // grado della superficie nel parametro U
int m_nDegV ; // grado della superficie nel parametro V
int m_nSpanU ;
int m_nSpanV ;
std::vector<POLYLINEVECTOR> m_vPolygons ; // vettore dei poligoni del tree
std::map<int,Cell> m_mTree ; // mappa che contiene tutti i nodi e le foglie dell'albero. -2 è puntatore Null e -1 è root
std::map<int,PNTVECTOR> m_mVert ; // mappa che contiene tutti i vertici 3d delle celle del tree. L'Id è lo stesso che la cella ha in m_mTree
INTVECTOR m_vnLeaves ; // vettore delle foglie
INTVECTOR m_vnParents ; // vettore delle celle ottenute dalla divisione preliminare in singole patch
} ;