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
12 changed files with 4052 additions and 536 deletions
-2
View File
@@ -362,8 +362,6 @@ Attribs::GetAllInfo( STRVECTOR& vsInfo) const
{
// riservo spazio opportuno per il vettore delle stringhe
vsInfo.clear() ;
if ( (int) m_slInfo.size() == 0)
return true ;
vsInfo.reserve( m_slInfo.size()) ;
// recupero tutte le info tranne il nome (se presente sempre al primo posto)
auto iIter = m_slInfo.cbegin() ;
+10 -196
View File
@@ -510,7 +510,14 @@ CurveToArcsPerpExtrCurve( const ICurve* pCrv, double dLinTol, double dAngTolDeg)
bool
NurbsCurveCanonicalize( CNurbsData& cnData)
{
// se con nodi extra
// se periodica
if ( cnData.bPeriodic) {
// va trasformata in non-periodica (clamped)
// vedere The NurbsBook di Les Piegl e Tiller
// mancano esempi per testare
return false ;
}
// se con nodi extra
if ( cnData.bExtraKnotes) {
int nKnotesNbr = int( cnData.vU.size()) ;
if ( nKnotesNbr < 4)
@@ -519,176 +526,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
for ( int i = 0 ; i < nKnotesNbr - 2 ; ++ i)
cnData.vU[i] = cnData.vU[i+1] ;
cnData.vU.resize( nKnotesNbr - 2) ;
}
// se periodica
if ( cnData.bPeriodic) {
// va trasformata in non-periodica (clamped)
// bisogna aumentare la molteplicità dei nodi u_p-1 e u_(m-p+1) fino ad arrivare al grado della nurbs
// e poi scartare nodi e punti fuori dalla regione clamped ( al di fuori della regione u_p-1 -> u_(m-p+1))
// l'agoritmo per l'inserimento dei nodi l' A5.1 del libro delle Nurbs ( Piegl e Tiller), con qualche modifica
// agli indici perché uso u_p-1 e u_(m-p+1), anziché u_p e u_m-p
// comincio ad aumentare la molteplictià del nodo u_m-p+1
int nCP = int( cnData.vCP.size()) ;
int nU = nCP + cnData.nDeg - 1 ;
int nDeg = cnData.nDeg ;
PNTVECTOR vBC ;
vBC.resize( nDeg + 1) ;
DBLVECTOR vBW ;
vBW.resize( nDeg + 1) ;
// trovo il nodo di cui aumentare la molteplicità e ne calcolo la molteplicità
int b = nU - nDeg - 1 +1;
int i = b ;
while ( abs( cnData.vU[b] - cnData.vU[b - 1]) < EPS_ZERO)
-- b ;
int mult = min( i - b + 1, nDeg) ; // mi aspetto che sia 1, ma comunque sarà < nDeg
// recupero i punti da modificare
if ( ! cnData.bRat) {
for ( int i = 0 ; i <= nDeg - mult ; ++ i)
vBC[i] = cnData.vCP[b - nDeg + 1 + i] ;
}
else {
for ( int i = 0 ; i <= nDeg - mult ; ++ i) {
vBC[i] = cnData.vCP[b - nDeg + 1 + i] * cnData.vW[b - nDeg + 1 + i] ;
vBW[i] = cnData.vW[b - nDeg + 1 + i] ;
}
}
// salvo i punti inalterati
int r = nDeg - mult ; // numero di volte che dovrò inserire il nodo
cnData.vCP.resize( nCP + r) ;
for ( int p = nCP - 1 ; p > b - mult ; --p) {
cnData.vCP[r + p] = cnData.vCP[p] ;
}
if ( cnData.bRat ) {
cnData.vW.resize( nCP + r) ;
for ( int p = nCP - 1 ; p > b - mult ; --p) {
cnData.vW[r + p] = cnData.vW[p] ;
}
}
// procedo all'inserimento
int L = 0 ;
double alpha ;
double num, den ;
if ( mult < nDeg) {
// inserisco il nodo r volte
for ( int j = 1 ; j <= r ; ++ j) {
L = b - nDeg + j ;
for ( int i = 0; i <= r - j ; ++i) {
num = (cnData.vU[b] - cnData.vU[L + i]) ;
den = ( cnData.vU[i + b + 1] - cnData.vU[L + i]) ;
alpha = (cnData.vU[b] - cnData.vU[L + i])/ ( cnData.vU[i + b + 1] - cnData.vU[L + i]) ;
vBC[i] = alpha * vBC[i +1 ] + ( 1 - alpha) * vBC[i] ;
if ( cnData.bRat) {
vBW[i] = alpha * vBW[i + 1] + ( 1 - alpha) * vBW[i] ;
}
}
cnData.vCP[L + 1] = vBC[0] ;
cnData.vCP[b + nDeg - j - mult] = vBC[r - j] ;
if ( cnData.bRat ) {
cnData.vW[L + 1] = vBW[0] ;
cnData.vW[b + nDeg - j - mult] = vBW[r-j] ;
}
}
}
// allungo il vettore dei nodi e sposto gli ultimi nodi
cnData.vU.resize(nU + r) ;
for ( int p = nU - 1 ; p > b ; --p)
cnData.vU[p + r] = cnData.vU[p] ;
// aggiungo i nodi nuovi
for ( int p = 0 ; p < r ; ++p)
cnData.vU[b + 1 + p] = cnData.vU[b] ;
nU = nU + r ;
nCP = nCP + r ;
// aumento la molteplicità del punto u_p-1
b = nDeg -1;
i = b ;
while ( abs( cnData.vU[b] - cnData.vU[b - 1]) < EPS_ZERO)
-- b ;
mult = min( i - b + 1, nDeg) ; // mi aspetto che sia 1, ma comunque sarà < cnData.nDeg
// recupero i punti da modificare
if ( ! cnData.bRat) {
for ( int i = 0 ; i <= nDeg - mult ; ++ i)
vBC[i] = cnData.vCP[i] ;
}
else {
for ( int i = 0 ; i <= nDeg - mult ; ++ i) {
vBC[i] = cnData.vCP[i] * cnData.vW[i] ;
vBW[i] = cnData.vW[i] ;
}
}
r = nDeg - mult ;
// salvo i punti inalterati
cnData.vCP.resize( nCP + r) ;
for ( int p = nCP - 1 ; p > b - mult ; --p) {
cnData.vCP[r + p] = cnData.vCP[p] ;
}
if ( cnData.bRat ) {
cnData.vW.resize( nCP + r) ;
for ( int p = nCP - 1 ; p > b - mult ; --p) {
cnData.vW[r + p] = cnData.vW[p] ;
}
}
// procedo all'inserimento
L = 0 ;
if ( mult < nDeg) {
// inserisco il nodo r volte
for ( int j = 1 ; j <= r ; ++ j) {
L = b - nDeg + j ;
for ( int i = 0; i <= r - j ; ++i) {
alpha = (cnData.vU[b] - cnData.vU[L + i])/ ( cnData.vU[i + b + 1] - cnData.vU[L + i]) ;
vBC[i] = alpha * vBC[i + 1] + ( 1 - alpha) * vBC[i] ;
if ( cnData.bRat) {
vBW[i] = alpha * vBW[i + 1] + ( 1 - alpha) * vBW[i] ;
}
}
cnData.vCP[L + 1] = vBC[0] ;
cnData.vCP[b + nDeg - j - mult] = vBC[r - j] ;
if ( cnData.bRat ) {
cnData.vW[L + 1] = vBW[0] ;
cnData.vW[b + nDeg - j - mult] = vBW[r - j] ;
}
}
}
// allungo il vettore dei nodi e sposto gli ultimi nodi
cnData.vU.resize(nU + r) ;
for ( int p = nU - 1 ; p > b ; --p)
cnData.vU[p+r] = cnData.vU[p] ;
// aggiungo i nodi nuovi
for ( int p = 0 ; p < r ; ++p)
cnData.vU[b + 1 + p] = cnData.vU[b] ;
nU = nU + r ;
nCP = nCP + r ;
// rendo la curva chiusa e non periodica eliminando i primi e gli ultimi nDeg punti e nodi
cnData.bPeriodic = false ;
nCP = nCP - 2 * ( nDeg - 1);
nU = nU - 2 * ( nDeg - 1);
PNTVECTOR vCP_clamped ;
vCP_clamped.resize( nCP) ;
DBLVECTOR vU_clamped ;
vU_clamped.resize( nU) ;
for ( int i = 0 ; i < nCP ; ++i) {
if ( ! cnData.bRat)
vCP_clamped[i] = cnData.vCP[i + nDeg - 1] ;
else
vCP_clamped[i] = cnData.vCP[i + nDeg - 1] / cnData.vW[i + nDeg - 1] ;
}
cnData.vCP = vCP_clamped ;
for ( int i = 0 ; i < nU ; ++i) {
vU_clamped[i] = cnData.vU[i + nDeg - 1] ;
}
cnData.vU = vU_clamped ;
return true ;
}
return true ;
@@ -720,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
@@ -872,30 +710,6 @@ NurbsToBezierCurve( const CNurbsData& cnData)
}
}
// se la curva ha grado 1, manca da aggiungere l'ultimo tratto
if ( cnData.nDeg == 1 ) {
// costruisco la curva di Bezier e la inserisco nella curva composita
PtrOwner<ICurveBezier> pCrvBez( CreateCurveBezier()) ;
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 ;
}
}
if ( ! pCrvBez->IsAPoint()) {
if ( ! pCrvCompo->AddCurve( Release( pCrvBez)))
return nullptr ;
}
}
// restituisco la curva composita
return Release( pCrvCompo) ;
}
+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 -7
View File
@@ -77,12 +77,12 @@ StmFromTriangleSoup::AddTriangle( const Triangle3d& Tria)
//----------------------------------------------------------------------------
bool
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)
const double dU0, const double dV0,const double dU1, const double dV1,const double dU2, const double dV2)
{
// verifico inizializzazione
// verifico inizializzazione
if ( m_pSTM == nullptr)
return false ;
// ciclo sui tre vertici
// ciclo sui tre vertici
int nIdV[3] ;
if ( ( nIdV[0] = AddVertex( ptP0, dU0, dV0)) == SVT_NULL)
return false ;
@@ -90,10 +90,10 @@ StmFromTriangleSoup::AddTriangle( const Point3d& ptP0, const Point3d& ptP1, cons
return false ;
if ( ( nIdV[2] = AddVertex( ptP2, dU2, dV2)) == SVT_NULL)
return false ;
// se i vertici sono tutti diversi tra loro, inserisco il triangolo
// se i vertici sono tutti diversi tra loro, inserisco il triangolo
if ( nIdV[0] != nIdV[1] && nIdV[0] != nIdV[2] && nIdV[1] != nIdV[2]) {
if ( m_pSTM->AddTriangle( nIdV) == SVT_NULL)
return false ;
return false ;
}
return true ;
}
@@ -102,11 +102,11 @@ StmFromTriangleSoup::AddTriangle( const Point3d& ptP0, const Point3d& ptP1, cons
int
StmFromTriangleSoup::AddVertex( const Point3d& ptP, const double dU, const double dV)
{
// verifico se già presente
// verifico se già presente
int nId ;
if ( m_VertGrid.Find( ptP, 2 * EPS_SMALL, nId))
return nId ;
// aggiungo il vertice
// aggiungo il vertice
if ( ( nId = m_pSTM->AddVertex( ptP, dU, dV)) == SVT_NULL)
return SVT_NULL ;
m_VertGrid.InsertPoint( ptP, nId) ;
+158 -243
View File
@@ -2,7 +2,7 @@
// EgalTech 2023-2023
//----------------------------------------------------------------------------
// File : SurfAux.cpp Data : 09.08.23 Versione :
// Contenuto : Implementazione di alcune funzioni di utilit? per le Superfici.
// Contenuto : Implementazione di alcune funzioni di utilità per le Superfici.
//
//
//
@@ -26,92 +26,9 @@
using namespace std ;
bool
NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
{
// per rendere una superficie non periodica devo recuperare i punti di controllo, suddivisi in isoparametriche lungo una direzione
// e applicare la trasformazione ad ogni isoparametrica, sostituendola poi a quella originale. ( si mantiene il numero di punti)
if ( snData.bPeriodicU ) {
bool bIsRational = snData.bRat ;
// vettore dei nodi
DBLVECTOR vU ;
int nKnot = (int) snData.vU.size() ;
for ( int k = 0 ; k < nKnot ; ++k ) {
double dKnot = snData.vU[k] ;
vU.push_back( dKnot) ;
}
for( int j = 0 ; j < snData.nCPV ; ++j) {
CNurbsData nuCurve ;
nuCurve.bPeriodic = true ;
nuCurve.nDeg = snData.nDegU ;
nuCurve.vU = vU ;
// vettore dei punti di controllo
PNTVECTOR vPtCtrl ;
// vettore dei pesi
DBLVECTOR vWeCtrl ;
for ( int i = 0 ; i < snData.nCPU ; ++i ) {
if ( bIsRational) {
vPtCtrl.push_back( snData.mCP[i][j] / snData.mW[i][j]) ;
vWeCtrl.push_back( snData.mW[i][j]) ;
}
else
vPtCtrl.push_back( snData.mCP[i][j]) ;
}
nuCurve.vCP = vPtCtrl ;
nuCurve.vW = vWeCtrl ;
// i punti dell' oggetto nuCurve devono essere in forma non omogenea
NurbsCurveCanonicalize( nuCurve) ;
for ( int i = 0 ; i < snData.nCPU ; ++i) {
snData.mCP[i][j] = nuCurve.vCP[i] ;
}
snData.vU = nuCurve.vU ;
}
snData.bPeriodicU = false ;
}
if ( snData.bPeriodicV ) {
bool bIsRational = snData.bRat ;
// vettore dei nodi
DBLVECTOR vV ;
int nKnot = (int) snData.vV.size() ;
for ( int k = 0 ; k < nKnot ; ++k ) {
double dKnot = snData.vV[k] ;
vV.push_back( dKnot) ;
}
for( int i = 0 ; i < snData.nCPU ; ++i) {
CNurbsData nuCurve ;
nuCurve.bPeriodic = true ;
nuCurve.nDeg = snData.nDegV ;
nuCurve.vU = vV ;
// vettore dei punti di controllo
PNTVECTOR vPtCtrl ;
// vettore dei pesi
DBLVECTOR vWeCtrl ;
for ( int j = 0 ; j < snData.nCPV ; ++j ) {
if ( bIsRational) {
vPtCtrl.push_back( snData.mCP[i][j] / snData.mW[i][j]) ;
vWeCtrl.push_back( snData.mW[i][j]) ;
}
else
vPtCtrl.push_back( snData.mCP[i][j]) ;
}
nuCurve.vCP = vPtCtrl ;
nuCurve.vW = vWeCtrl ;
// i punti dell' oggetto nuCurve devono essere in forma non omogenea
NurbsCurveCanonicalize( nuCurve) ;
for ( int j = 0 ; j < snData.nCPV ; ++j ) {
snData.mCP[i][j] = nuCurve.vCP[j] ;
}
snData.vV = nuCurve.vU ;
}
snData.bPeriodicV = false ;
}
return true;
}
//----------------------------------------------------------------------------
ISurf*
NurbsToBezierSurface(const SNurbsSurfData& snData)
NurbsToBezierSurface(const CNurbsSurfData& cnData)
{
//INTVECTOR vInt_sub( 10) ;
//INTMATRIX vInt( 10, vInt_sub) ;
@@ -128,64 +45,64 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
// la superficie Nurbs deve essere in forma canonica
if ( snData.bPeriodicU || snData.bPeriodicV || snData.bExtraKnotes )
if ( cnData.bPeriodicU || cnData.bPeriodicV || cnData.bExtraKnotes )
return nullptr ;
// controllo sul numero dei nodi
int nU = snData.nCPU + snData.nDegU - 1 ;
int nV = snData.nCPV + snData.nDegV - 1 ;
int nU = cnData.nCPU + cnData.nDegU - 1 ;
int nV = cnData.nCPV + cnData.nDegV - 1 ;
// controllo nodi e punti di controllo
//if ( nU != int( snData.vU.size()) || nV != int( snData.vV.size()) || snData.nCPU * snData.nCPV != int( snData.vCP.size()))
if ( nU != int(snData.vU.size()) || nV != int(snData.vV.size())) {
//if ( nU != int( cnData.vU.size()) || nV != int( cnData.vV.size()) || cnData.nCPU * cnData.nCPV != int( cnData.vCP.size()))
if ( nU != int(cnData.vU.size()) || nV != int(cnData.vV.size())) {
return nullptr ;
}
//// numero degli intervalli
//int nInt = nU - 2 * snData.nDeg + 1 ;
//int nInt = nU - 2 * cnData.nDeg + 1 ;
// verifico le condizioni agli estremi sui nodi (i primi nDeg nodi e gli ultimi nDeg nodi devono essere uguali tra loro)
bool bOk = true ;
// direzione U
for ( int i = 1 ; i < snData.nDegU ; ++ i) {
if ( abs( snData.vU[i] - snData.vU[0]) >= EPS_ZERO)
for ( int i = 1 ; i < cnData.nDegU ; ++ i) {
if ( abs( cnData.vU[i] - cnData.vU[0]) >= EPS_ZERO)
bOk = false ;
}
for ( int i = 1 ; i < snData.nDegU ; ++ i) {
if ( abs( snData.vU[nU - 1 - i] - snData.vU[nU - 1]) >= EPS_ZERO)
for ( int i = 1 ; i < cnData.nDegU ; ++ i) {
if ( abs( cnData.vU[nU - 1 - i] - cnData.vU[nU - 1]) >= EPS_ZERO)
bOk = false ;
}
// direzione V
for ( int i = 1 ; i < snData.nDegV ; ++ i) {
if ( abs( snData.vV[i] - snData.vV[0]) >= EPS_ZERO)
for ( int i = 1 ; i < cnData.nDegV ; ++ i) {
if ( abs( cnData.vV[i] - cnData.vV[0]) >= EPS_ZERO)
bOk = false ;
}
for ( int i = 1 ; i < snData.nDegV ; ++ i) {
if ( abs( snData.vV[nV - 1 - i] - snData.vV[nV - 1]) >= EPS_ZERO)
for ( int i = 1 ; i < cnData.nDegV ; ++ i) {
if ( abs( cnData.vV[nV - 1 - i] - cnData.vV[nV - 1]) >= EPS_ZERO)
bOk = false ;
}
if ( ! bOk)
return nullptr ;
//// se 1 solo intervallo, la Nurbs ? gi? una curva di Bezier
//// se 1 solo intervallo, la Nurbs è già una curva di Bezier
//if ( nInt == 1) {
// // creo la curva di Bezier
// PtrOwner<ICurveBezier> pCrvBez( CreateCurveBezier()) ;
// if ( IsNull( pCrvBez))
// return nullptr ;
// // la inizializzo
// if ( ! pCrvBez->Init( snData.nDeg, snData.bRat))
// if ( ! pCrvBez->Init( cnData.nDeg, cnData.bRat))
// return nullptr ;
// for ( int i = 0 ; i <= snData.nDeg ; ++ i) {
// if ( ! snData.bRat) {
// if ( ! pCrvBez->SetControlPoint( i, snData.vCP[i]))
// for ( int i = 0 ; i <= cnData.nDeg ; ++ i) {
// if ( ! cnData.bRat) {
// if ( ! pCrvBez->SetControlPoint( i, cnData.vCP[i]))
// return nullptr ;
// }
// else {
// if ( ! pCrvBez->SetControlPoint( i, snData.vCP[i], snData.vW[i]))
// if ( ! pCrvBez->SetControlPoint( i, cnData.vCP[i], cnData.vW[i]))
// return nullptr ;
// }
// }
// // se non ? una curva ma un punto, la invalido
// // se non è una curva ma un punto, la invalido
// if ( pCrvBez->IsAPoint())
// pCrvBez->Init( snData.nDeg, snData.bRat) ;
// pCrvBez->Init( cnData.nDeg, cnData.bRat) ;
// // restituisco la curva
// return Release( pCrvBez) ;
//}
@@ -193,77 +110,77 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
// algoritmo 5.7 del libro "The NURBS book"//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// creazione delle strips nella direzione U ( trasformo le curve iso con U costante in bezier)
int a = snData.nDegU - 1 ;
int b = snData.nDegU ;
int a = cnData.nDegU - 1 ;
int b = cnData.nDegU ;
int nb = 0 ; // numero di strisce in U ( lunghezza con U costante)
//PNTVECTOR vBC ;
//vBC.resize( snData.nCPV * snData.nDegU) ;
//for (int row = 0 ; row < snData.nCPV ; ++row ) {
// for ( int i = 0 ; i <= snData.nDegU ; ++i ) {
// vBC[nDegU*row + i] = ( snData.vCP[nCPU*row + i]) ;
//vBC.resize( cnData.nCPV * cnData.nDegU) ;
//for (int row = 0 ; row < cnData.nCPV ; ++row ) {
// for ( int i = 0 ; i <= cnData.nDegU ; ++i ) {
// vBC[nDegU*row + i] = ( cnData.vCP[nCPU*row + i]) ;
// }
//}
vector<Point3d> vCPV( snData.nCPV) ;
vector< vector<Point3d>> mBC (snData.nDegU + 1,vCPV ) ;
vector< vector<Point3d>> mBC_next (snData.nDegU - 1, vCPV) ;
vector< vector<Point3d>> mPC_strip(snData.nDegU + 1, vCPV) ; // matrice che verr? ingrandita e conterr? la superficie met? bezier e met? NURBS
DBLVECTOR vV_W( snData.nCPV) ;
vector<DBLVECTOR> mW( snData.nDegU + 1, vV_W) ;
vector<DBLVECTOR> mW_next( snData.nDegU - 1, vV_W) ;
vector<DBLVECTOR> mW_strip( snData.nDegU + 1, vV_W) ;
vector<Point3d> vCPV( cnData.nCPV) ;
vector< vector<Point3d>> mBC (cnData.nDegU + 1,vCPV ) ;
vector< vector<Point3d>> mBC_next (cnData.nDegU - 1, vCPV) ;
vector< vector<Point3d>> mPC_strip(cnData.nDegU + 1, vCPV) ; // matrice che verrà ingrandita e conterrà la superficie metà bezier e metà NURBS
DBLVECTOR vV_W( cnData.nCPV) ;
vector<DBLVECTOR> mW( cnData.nDegU + 1, vV_W) ;
vector<DBLVECTOR> mW_next( cnData.nDegU - 1, vV_W) ;
vector<DBLVECTOR> mW_strip( cnData.nDegU + 1, vV_W) ;
DBLVECTOR vAlpha ;
vAlpha.resize( snData.nDegU - 1) ;
if ( ! snData.bRat ) {
for ( int i = 0 ; i <= snData.nDegU ; ++i ) {
for ( int row = 0 ; row < snData.nCPV ; ++row ) {
mBC[i][row] = snData.mCP[i][row] ;
vAlpha.resize( cnData.nDegU - 1) ;
if ( ! cnData.bRat ) {
for ( int i = 0 ; i <= cnData.nDegU ; ++i ) {
for ( int row = 0 ; row < cnData.nCPV ; ++row ) {
mBC[i][row] = cnData.mCP[i][row] ;
}
}
}
else {
for ( int i = 0 ; i <= snData.nDegU ; ++i ) {
for (int row = 0 ; row < snData.nCPV ; ++ row) {
mW[i][row] = snData.mW[i][row] ;
mBC[i][row] = snData.mCP[i][row] * snData.mW[i][row] ;
for ( int i = 0 ; i <= cnData.nDegU ; ++i ) {
for (int row = 0 ; row < cnData.nCPV ; ++ row) {
mW[i][row] = cnData.mW[i][row] ;
mBC[i][row] = cnData.mCP[i][row] * cnData.mW[i][row] ;
}
}
}
bool bRef = false ;
// se la superficie ? lineare nel parametro U allora ? gi? in forma di Bezier in questo parametro
// 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
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( snData.vU[b+1] - snData.vU[b]) < EPS_ZERO)
while ( b < nU - 1 && abs( cnData.vU[b+1] - cnData.vU[b]) < EPS_ZERO)
++ b ;
int mult = b - i + 1 ;
if ( mult < snData.nDegU ) {
if ( mult < cnData.nDegU ) {
bRef = true ;
// calcolo numeratore e alpha
double numer = snData.vU[b] - snData.vU[a] ;
for ( int j = snData.nDegU ; j > mult ; -- j)
vAlpha[j-mult-1] = numer / ( snData.vU[a+j] - snData.vU[a]) ;
int r = snData.nDegU - mult ;
for ( int j = 1 ; j <= snData.nDegU - mult ; ++j ) {
double numer = cnData.vU[b] - cnData.vU[a] ;
for ( int j = cnData.nDegU ; j > mult ; -- j)
vAlpha[j-mult-1] = numer / ( cnData.vU[a+j] - cnData.vU[a]) ;
int r = cnData.nDegU - mult ;
for ( int j = 1 ; j <= cnData.nDegU - mult ; ++j ) {
int save = r - j ;
int s = mult + j ;
//for ( int row = 0 ; row < snData.nCPV ; ++row) {
// for ( int k = snData.nDegU ; k >= s ; --k ) {
//for ( int row = 0 ; row < cnData.nCPV ; ++row) {
// for ( int k = cnData.nDegU ; k >= s ; --k ) {
// vBC[nCPU*row + k] = vAlpha[k-s]*vBC[nCPU*row + k] + ( 1 - vAlfa[k-s]) * vBC[nCPU*row + k - 1]
// }
//}
if ( ! snData.bRat ) {
for ( int k = snData.nDegU ; k >= s ; --k ) {
for ( int row = 0 ; row < snData.nCPV ; ++row) {
if ( ! cnData.bRat ) {
for ( int k = cnData.nDegU ; k >= s ; --k ) {
for ( int row = 0 ; row < cnData.nCPV ; ++row) {
mBC[k][row] = vAlpha[k-s] * mBC[k][row] + ( 1 - vAlpha[k-s]) * mBC[k-1][row] ;
}
}
}
else {
for ( int k = snData.nDegU ; k >= s ; --k ) {
for ( int row = 0 ; row < snData.nCPV ; ++row) {
for ( int k = cnData.nDegU ; k >= s ; --k ) {
for ( int row = 0 ; row < cnData.nCPV ; ++row) {
mBC[k][row] = vAlpha[k-s] * mBC[k][row] + ( 1 - vAlpha[k-s]) * mBC[k-1][row] ;
mW[k][row] = vAlpha[k-s] * mW[k][row] + ( 1 - vAlpha[k-s]) * mW[k-1][row] ;
}
@@ -271,46 +188,46 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
}
if ( b < nU - 1 ) {
for ( int row = 0 ; row < snData.nCPV ; ++row) {
mBC_next[save][row] = mBC[snData.nDegU][row] ;
for ( int row = 0 ; row < cnData.nCPV ; ++row) {
mBC_next[save][row] = mBC[cnData.nDegU][row] ;
}
if ( snData.bRat )
for ( int row = 0 ; row < snData.nCPV ; ++row) {
mW_next[save][row] = mW[snData.nDegU][row] ;
if ( cnData.bRat )
for ( int row = 0 ; row < cnData.nCPV ; ++row) {
mW_next[save][row] = mW[cnData.nDegU][row] ;
}
}
}
}
mPC_strip.resize( snData.nDegU * ( nb + 1) + 1 , vCPV) ;
mW_strip.resize( snData.nDegU * ( nb + 1) + 1, vV_W) ;
if ( ! snData.bRat)
for ( int i = 0 ; i <= snData.nDegU ; ++i) {
for ( int row = 0 ; row < snData.nCPV ; ++row ) {
mPC_strip[i+ nb * snData.nDegU][row] = mBC[i][row] ;
mPC_strip.resize( cnData.nDegU * ( nb + 1) + 1 , vCPV) ;
mW_strip.resize( cnData.nDegU * ( nb + 1) + 1, vV_W) ;
if ( ! cnData.bRat)
for ( int i = 0 ; i <= cnData.nDegU ; ++i) {
for ( int row = 0 ; row < cnData.nCPV ; ++row ) {
mPC_strip[i+ nb * cnData.nDegU][row] = mBC[i][row] ;
}
}
}
else {
for ( int i = 0 ; i <= snData.nDegU ; ++i) {
for ( int row = 0 ; row < snData.nCPV ; ++row ) {
mPC_strip[i+ nb * snData.nDegU][row] = mBC[i][row]/mW[i][row] ;
mW_strip[i+ nb * snData.nDegU][row] = mW[i][row] ;
else {
for ( int i = 0 ; i <= cnData.nDegU ; ++i) {
for ( int row = 0 ; row < cnData.nCPV ; ++row ) {
mPC_strip[i+ nb * cnData.nDegU][row] = mBC[i][row]/mW[i][row] ;
mW_strip[i+ nb * cnData.nDegU][row] = mW[i][row] ;
}
}
}
}
++ nb ;
// ho finito di definire la patch di Bezier attuale e passo alla successiva
// aggiorno mBC con i valori della prossima pezza di Bezier // corrisponde a nb = nb + 1
if ( ! snData.bRat){
for (int i = 0 ; i < snData.nDegU - 1 ; ++ i) {
for ( int row = 0 ; row < snData.nCPV ; ++row) {
if ( ! cnData.bRat){
for (int i = 0 ; i < cnData.nDegU - 1 ; ++ i) {
for ( int row = 0 ; row < cnData.nCPV ; ++row) {
mBC[i][row] = mBC_next[i][row] ;
}
}
}
else {
for (int i = 0 ; i < snData.nDegU - 1 ; ++ i) {
for ( int row = 0 ; row < snData.nCPV ; ++row) {
for (int i = 0 ; i < cnData.nDegU - 1 ; ++ i) {
for ( int row = 0 ; row < cnData.nCPV ; ++row) {
mBC[i][row] = mBC_next[i][row] ;
mW[i][row] = mW_next[i][row] ;
}
@@ -318,15 +235,15 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
}
if ( b < nU - 1 ) {
for ( int i = snData.nDegU - mult ; i <= snData.nDegU ; ++ i) {
for (int row = 0 ; row < snData.nCPV ; ++ row ) {
mBC[i][row] = snData.mCP[b - snData.nDegU + i + 1][row] ;
for ( int i = cnData.nDegU - mult ; i <= cnData.nDegU ; ++ i) {
for (int row = 0 ; row < cnData.nCPV ; ++ row ) {
mBC[i][row] = cnData.mCP[b - cnData.nDegU + i + 1][row] ;
}
}
if ( snData.bRat ) {
for ( int i = snData.nDegU - mult ; i <= snData.nDegU ; ++ i) {
for (int row = 0 ; row < snData.nCPV ; ++ row ) {
mW[i][row] = snData.mW[b - snData.nDegU + i + 1][row] ;
if ( cnData.bRat ) {
for ( int i = cnData.nDegU - mult ; i <= cnData.nDegU ; ++ i) {
for (int row = 0 ; row < cnData.nCPV ; ++ row ) {
mW[i][row] = cnData.mW[b - cnData.nDegU + i + 1][row] ;
}
}
}
@@ -335,59 +252,59 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
}
}
// se non ho raffinato allora tutti i nodi avevano gi? molteplicit? massima. Converto direttamente in Bezier la dir U
// se non ho raffinato allora tutti i nodi avevano già molteplicità massima. Converto direttamente in Bezier la dir U
int nCPU_ref ; // numero dei punti di controllo in U dopo il raffinamento
if ( ! bRef ) {
nCPU_ref = snData.nCPU ;
mPC_strip.resize( snData.nCPU, vCPV) ;
mW_strip.resize( snData.nCPU, vV_W) ;
if ( ! snData.bRat) {
nCPU_ref = cnData.nCPU ;
mPC_strip.resize( cnData.nCPU, vCPV) ;
mW_strip.resize( cnData.nCPU, vV_W) ;
if ( ! cnData.bRat) {
for ( int i = 0 ; i < nCPU_ref ; ++i) {
for ( int row = 0 ; row < snData.nCPV ; ++ row) {
mPC_strip[i][row] = snData.mCP[i][row] ;
for ( int row = 0 ; row < cnData.nCPV ; ++ row) {
mPC_strip[i][row] = cnData.mCP[i][row] ;
}
}
}
else {
for ( int i = 0 ; i < nCPU_ref ; ++i) {
for ( int row = 0 ; row < snData.nCPV ; ++ row) {
mPC_strip[i][row] = snData.mCP[i][row] ;
mW_strip[i][row] = snData.mW[i][row] ;
for ( int row = 0 ; row < cnData.nCPV ; ++ row) {
mPC_strip[i][row] = cnData.mCP[i][row] ;
mW_strip[i][row] = cnData.mW[i][row] ;
}
}
}
// devo vedere quante patch ci stanno prendendo i punti che ci sono
//nb = (snData.nCPU - 1) / snData.nDegU ;
//nb = (cnData.nCPU - 1) / cnData.nDegU ;
}
else
nCPU_ref = snData.nDegU * nb + 1 ; // numero dei punti di controllo in U dopo il raffinamento
nCPU_ref = cnData.nDegU * nb + 1 ; // numero dei punti di controllo in U dopo il raffinamento
// ora ho ottenuto le strisce nDegU x nCPV
// devo ripetere la procedura, sulla dir V, per ottenere le patch nDegU x nDegV
a = snData.nDegV - 1 ;
b = snData.nDegV ;
a = cnData.nDegV - 1 ;
b = cnData.nDegV ;
int nc = 0 ; // numero di strisce in V ( lunghezza con V costante)
vector<Point3d> vDegV(snData.nDegV + 1) ;
vector<Point3d> vDegV_1(snData.nDegV - 1) ;
vector<Point3d> vDegV(cnData.nDegV + 1) ;
vector<Point3d> vDegV_1(cnData.nDegV - 1) ;
vector< vector<Point3d>> m_BC1( nCPU_ref, vDegV) ;
vector< vector<Point3d>> m_BC1_next( nCPU_ref, vDegV_1) ;
DBLVECTOR vV1_W(snData.nDegV + 1) ;
DBLVECTOR vV2_W(snData.nDegV - 1) ;
DBLVECTOR vV1_W(cnData.nDegV + 1) ;
DBLVECTOR vV2_W(cnData.nDegV - 1) ;
vector<DBLVECTOR> mW1( nCPU_ref, vV1_W) ;
vector<DBLVECTOR> mW1_next( nCPU_ref, vV2_W) ;
DBLVECTOR vAlpha1( snData.nDegV - 1) ;
DBLVECTOR vAlpha1( cnData.nDegV - 1) ;
vector<vector<Point3d>> mPC_tot( nCPU_ref, vDegV) ;
vector<DBLVECTOR> mW_tot( nCPU_ref, vV1_W) ;
if ( ! snData.bRat ) {
if ( ! cnData.bRat ) {
for ( int i = 0 ; i < nCPU_ref ; ++i ) {
for ( int row = 0 ; row <= snData.nDegV ; ++row ) {
for ( int row = 0 ; row <= cnData.nDegV ; ++row ) {
m_BC1[i][row] = mPC_strip[i][row] ;
}
}
}
else {
for ( int i = 0 ; i < nCPU_ref ; ++i ) {
for (int row = 0 ; row <= snData.nDegV ; ++ row) {
for (int row = 0 ; row <= cnData.nDegV ; ++ row) {
mW1[i][row] = mW_strip[i][row] ;
m_BC1[i][row] = mPC_strip[i][row] * mW_strip[i][row] ;
}
@@ -395,40 +312,40 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
}
bRef = false ;
// se la superficie ? lineare nel parametro V allora ? gi? in forma di Bezier in questo parametro
// 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( snData.vV[b+1] - snData.vV[b]) < EPS_ZERO)
while ( b < nV - 1 && abs( cnData.vV[b+1] - cnData.vV[b]) < EPS_ZERO)
++ b ;
int mult = b - i + 1 ;
if ( mult < snData.nDegV ) {
if ( mult < cnData.nDegV ) {
bRef = true ;
// calcolo numeratore e alpha
double numer = snData.vV[b] - snData.vV[a] ;
for ( int j = snData.nDegV ; j > mult ; -- j)
vAlpha1[j-mult-1] = numer / ( snData.vV[a+j] - snData.vV[a]) ;
int r = snData.nDegV - mult ;
for ( int j = 1 ; j <= snData.nDegV - mult ; ++j ) {
double numer = cnData.vV[b] - cnData.vV[a] ;
for ( int j = cnData.nDegV ; j > mult ; -- j)
vAlpha1[j-mult-1] = numer / ( cnData.vV[a+j] - cnData.vV[a]) ;
int r = cnData.nDegV - mult ;
for ( int j = 1 ; j <= cnData.nDegV - mult ; ++j ) {
int save = r - j ;
int s = mult + j ;
//for ( int row = 0 ; row < snData.nCPV ; ++row) {
// for ( int k = snData.nDegU ; k >= s ; --k ) {
//for ( int row = 0 ; row < cnData.nCPV ; ++row) {
// for ( int k = cnData.nDegU ; k >= s ; --k ) {
// vBC[nCPU*row + k] = vAlpha1[k-s]*vBC[nCPU*row + k] + ( 1 - vAlpha1[k-s]) * vBC[nCPU*row + k - 1]
// }
//}
if ( ! snData.bRat) {
if ( ! cnData.bRat) {
for ( int k = 0 ; k < nCPU_ref ; ++k) {
for ( int row = snData.nDegV ; row >= s ; --row ) {
for ( int row = cnData.nDegV ; row >= s ; --row ) {
m_BC1[k][row] = vAlpha1[row-s] * m_BC1[k][row] + ( 1 - vAlpha1[row-s]) * m_BC1[k][row-1] ;
}
}
}
else {
for ( int k = 0 ; k < nCPU_ref ; ++k) {
for ( int row = snData.nDegV ; row >= s ; --row ) {
for ( int row = cnData.nDegV ; row >= s ; --row ) {
m_BC1[k][row] = vAlpha1[row-s] * m_BC1[k][row] + ( 1 - vAlpha1[row-s]) * m_BC1[k][row-1] ;
mW1[k][row] = vAlpha1[row-s] * mW1[k][row] + ( 1 - vAlpha1[row-s]) * mW1[k][row-1] ;
}
@@ -436,36 +353,36 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
}
if ( b < nV - 1 ) {
if ( !snData.bRat ){
if ( !cnData.bRat ){
for ( int i = 0 ; i < nCPU_ref ; ++i) {
m_BC1_next[i][save] = m_BC1[i][snData.nDegV] ;
m_BC1_next[i][save] = m_BC1[i][cnData.nDegV] ;
}
}
else {
for ( int i = 0 ; i < nCPU_ref ; ++i) {
m_BC1_next[i][save] = m_BC1[i][snData.nDegV] ;
mW1_next[save] = mW1[snData.nDegV] ;
m_BC1_next[i][save] = m_BC1[i][cnData.nDegV] ;
mW1_next[save] = mW1[cnData.nDegV] ;
}
}
}
}
}
int nRef = snData.nDegV * ( nc + 1) + 1 ;
int nRef = cnData.nDegV * ( nc + 1) + 1 ;
for ( int k = 0 ; k < nCPU_ref; ++k){
mPC_tot[k].resize( nRef) ;
mW_tot[k].resize( nRef) ;
}
if ( ! snData.bRat)
if ( ! cnData.bRat)
for ( int i = 0 ; i < nCPU_ref ; ++i) {
for ( int row = 0 ; row <= snData.nDegV ; ++row ) {
mPC_tot[i][row + nc * snData.nDegV] = m_BC1[i][row] ;
for ( int row = 0 ; row <= cnData.nDegV ; ++row ) {
mPC_tot[i][row + nc * cnData.nDegV] = m_BC1[i][row] ;
}
}
else {
for ( int i = 0 ; i < nCPU_ref ; ++i) {
for ( int row = 0 ; row <= snData.nDegV ; ++row ) {
mPC_tot[i][row + nc * snData.nDegV] = m_BC1[i][row]/mW1[i][row] ;
mW_tot[i][row + nc * snData.nDegV] = mW1[i][row] ;
for ( int row = 0 ; row <= cnData.nDegV ; ++row ) {
mPC_tot[i][row + nc * cnData.nDegV] = m_BC1[i][row]/mW1[i][row] ;
mW_tot[i][row + nc * cnData.nDegV] = mW1[i][row] ;
}
}
}
@@ -473,16 +390,16 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
// ho finito di definire la patch di Bezier attuale e passo alla successiva
// aggiorno mBC con i valori della prossima pezza di Bezier // corrisponde a nc = nc + 1
if ( ! snData.bRat){
if ( ! cnData.bRat){
for (int i = 0 ; i < nCPU_ref ; ++ i) {
for ( int row = 0 ; row < snData.nDegV - 1 ; ++row) {
for ( int row = 0 ; row < cnData.nDegV - 1 ; ++row) {
m_BC1[i][row] = m_BC1_next[i][row] ;
}
}
}
else {
for (int i = 0 ; i < nCPU_ref ; ++ i) {
for ( int row = 0 ; row < snData.nDegV - 1 ; ++row) {
for ( int row = 0 ; row < cnData.nDegV - 1 ; ++row) {
m_BC1[i][row] = m_BC1_next[i][row] ;
mW1[i][row] = mW1_next[i][row] ;
}
@@ -491,16 +408,14 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
if ( b < nV - 1) {
for (int i = 0 ; i < nCPU_ref ; ++ i ) {
for ( int row = snData.nDegV - mult ; row <= snData.nDegV ; ++ row) {
//m_BC1[i][row] = snData.mCP[i][b - snData.nDegV + row + 1] ;
m_BC1[i][row] = mPC_strip[i][b - snData.nDegV + row + 1] ;
for ( int row = cnData.nDegV - mult ; row <= cnData.nDegV ; ++ row) {
m_BC1[i][row] = cnData.mCP[i][b - cnData.nDegV + row + 1] ;
}
}
if ( snData.bRat ) {
if ( cnData.bRat ) {
for (int i = 0 ; i < nCPU_ref ; ++ i ) {
for ( int row = snData.nDegV - mult ; row <= snData.nDegV ; ++ row) {
//mW1[i][row] = snData.mW[i][b - snData.nDegV + row + 1] ;
mW1[i][row] = mW_strip[i][b - snData.nDegV + row + 1] ;
for ( int row = cnData.nDegV - mult ; row <= cnData.nDegV ; ++ row) {
mW1[i][row] = cnData.mW[i][b - cnData.nDegV + row + 1] ;
}
}
}
@@ -512,12 +427,12 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
// se non ho raffinato allora aggiungo direttamente alle matrici della superficie totale
int nCPV_ref ; // numero dei punti di controllo in V dopo il raffinamento
if ( ! bRef) {
nCPV_ref = snData.nCPV ;
nCPV_ref = cnData.nCPV ;
for ( int k = 0 ; k < nCPU_ref ; ++k){
mPC_tot[k].resize( snData.nCPV) ;
mW_tot[k].resize( snData.nCPV) ;
mPC_tot[k].resize( cnData.nCPV) ;
mW_tot[k].resize( cnData.nCPV) ;
}
if ( ! snData.bRat) {
if ( ! cnData.bRat) {
for ( int i = 0 ; i < nCPU_ref ; ++i) {
for ( int row = 0 ; row < nCPV_ref ; ++ row) {
mPC_tot[i][row] = mPC_strip[i][row] ;
@@ -533,17 +448,17 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
}
}
// devo vedere quante patch ci stanno prendendo i punti che ci sono
//nc = (snData.nCPV - 1) / snData.nDegV ;
//nc = (cnData.nCPV - 1) / cnData.nDegV ;
}
else
nCPV_ref = snData.nDegV * nc + 1 ;
nCPV_ref = cnData.nDegV * nc + 1 ;
// finalmente setto la superficie di bezier totale divisa in nb patch in U e nc patch in V
PtrOwner<ISurfBezier> pSrfBz( CreateSurfBezier()) ;
if ( IsNull( pSrfBz))
return nullptr ;
pSrfBz->Init(snData.nDegU, snData.nDegV, nb, nc, snData.bRat) ;
if ( !snData.bRat ) {
pSrfBz->Init(cnData.nDegU, cnData.nDegV, nb, nc, cnData.bRat) ;
if ( !cnData.bRat ) {
for ( int i = 0 ; i < nCPU_ref; ++ i) {
for (int j = 0 ; j < nCPV_ref; ++j) {
pSrfBz->SetControlPoint( i + nCPU_ref * j, mPC_tot[i][j]) ;
+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
} ;
//-----------------------------------------------------------------------------
+6 -7
View File
@@ -109,17 +109,17 @@ SurfTriMesh::Clear( void)
int
SurfTriMesh::AddVertex( const Point3d& ptVert, const double dU, const double dV)
{
// imposto ricalcolo
// imposto ricalcolo
m_nStatus = TO_VERIFY ;
m_nParts = - 1 ;
m_OGrMgr.Reset() ;
ResetHashGrids3d() ;
// inserisco il vertice
// inserisco il vertice
try { m_vVert.emplace_back( ptVert) ;}
catch(...) { return SVT_NULL ;}
// ne determino l'indice
// ne determino l'indice
int nId = int( m_vVert.size() - 1) ;
// aggiugo le coordinate corrispondenti allo spazio parametrico
// aggiugo le coordinate corrispondenti allo spazio parametrico
m_vVert[nId].dU = dU ;
m_vVert[nId].dV = dV ;
return nId ;
@@ -483,16 +483,15 @@ SurfTriMesh::GetVertex( int nId, Point3d& ptP) const
bool
SurfTriMesh::GetVertexParam( int nId, double& dU, double& dV) const
{
// verifico esistenza del vertice
// verifico esistenza del vertice
if ( nId < 0 || nId >= GetVertexSize() || m_vVert[nId].nIdTria == SVT_DEL)
return false ;
// recupero i dati
// recupero i dati
dU = m_vVert[nId].dU ;
dV = m_vVert[nId].dV ;
return true ;
}
//----------------------------------------------------------------------------
int
SurfTriMesh::GetFirstVertex( Point3d& ptP) const
+13 -13
View File
@@ -27,19 +27,19 @@ class SurfFlatRegion ;
// Classe Vertice
class StmVert
{
public :
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 ;
public :
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 ;
} ;
//----------------------------------------------------------------------------
+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
} ;