diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj
index f1ddf40..0e496f4 100644
--- a/EgtGeomKernel.vcxproj
+++ b/EgtGeomKernel.vcxproj
@@ -339,6 +339,7 @@ copy $(TargetPath) \EgtProg\Dll64
+
@@ -603,6 +604,7 @@ copy $(TargetPath) \EgtProg\Dll64
+
diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters
index f6a5e4c..4503501 100644
--- a/EgtGeomKernel.vcxproj.filters
+++ b/EgtGeomKernel.vcxproj.filters
@@ -471,6 +471,9 @@
File di origine\GeoOffset
+
+ File di origine\Base
+
@@ -1103,6 +1106,9 @@
File di intestazione
+
+ File di intestazione
+
diff --git a/KdTree.cpp b/KdTree.cpp
new file mode 100644
index 0000000..fc945ef
--- /dev/null
+++ b/KdTree.cpp
@@ -0,0 +1,286 @@
+//----------------------------------------------------------------------------
+// EgalTech 2023
+//----------------------------------------------------------------------------
+// File : Kd-tree.cpp Data : 21.04.23 Versione :
+// Contenuto : Implementazione della classe kd-tree.
+//
+//
+//
+// Modifiche : 21.04.23 DB Creazione modulo.
+//
+//
+//----------------------------------------------------------------------------
+
+//--------------------------- Include ----------------------------------------
+#include "stdafx.h"
+#include "KdTree.h"
+#include "SurfBezier.h"
+#include "GeoConst.h"
+
+using namespace std ;
+
+//----------------------------------------------------------------------------
+Cell::Cell( void)
+ : m_ptPbl( ORIG), m_ptPtr( ORIG), m_bProcessed ( false) , m_bSplitVert ( true) , m_dSplit( 0) , m_cTop ( nullptr), m_cBottom( nullptr),
+ m_cLeft( nullptr), m_cRight ( nullptr), m_cParent( nullptr), m_cChild1( nullptr), m_cChild2( nullptr)
+{}
+
+//----------------------------------------------------------------------------
+Cell::~Cell( void)
+{
+}
+
+//----------------------------------------------------------------------------
+inline bool
+Cell::IsSame( std::shared_ptr cOtherCell)
+{
+ if ( AreSamePointXYApprox( m_ptPbl, cOtherCell->GetBottomLeft()) &&
+ AreSamePointXYApprox( m_ptPtr, cOtherCell->GetTopRight())) {
+ return true ;
+ }
+ else {
+ return false ;
+ }
+}
+
+//----------------------------------------------------------------------------
+void
+Cell::Split( double dSplitValue)
+{
+ m_dSplit = dSplitValue ;
+ //Cell cChild1, cChild2, cParent, cTop, cBottom, cLeft, cRight ;
+ m_cChild1 = make_shared() ;
+ //m_cChild2 = &cChild2 ;
+ //m_cParent = &cParent ;
+ //m_cTop = &cTop ;
+ //m_cBottom = &cBottom ;
+ //m_cLeft = &cLeft ;
+ //m_cRight = &cRight ;
+
+ m_cChild2 = make_shared() ;
+ //m_cParent = make_shared() ;
+ //m_cTop = make_shared() ;
+ //m_cBottom = make_shared() ;
+ //m_cLeft = make_shared() ;
+ //m_cRight = make_shared() ;
+ if ( ! m_bSplitVert )
+ {
+ // la cella figlio 1 è quella sopra
+ Point3d ptBL( m_ptPbl.x, m_dSplit) ;
+ m_cChild1->SetBottomLeft( ptBL) ;
+ m_cChild1->SetTopRight( m_ptPtr) ;
+ m_cChild1->m_cTop = m_cTop ;
+ m_cChild1->m_cBottom = m_cChild2 ;
+ m_cChild1->m_cLeft = m_cLeft ;
+ m_cChild1->m_cRight = m_cRight ;
+ //m_cChild1->m_cParent = make_shared(*this) ;
+ Point3d ptTR( m_ptPtr.x, m_dSplit) ;
+ m_cChild2->SetBottomLeft( m_ptPbl) ;
+ m_cChild2->SetTopRight( ptTR) ;
+ m_cChild2->m_cTop = m_cChild1 ;
+ m_cChild2->m_cBottom = m_cBottom ;
+ m_cChild2->m_cLeft = m_cLeft ;
+ m_cChild2->m_cRight = m_cRight ;
+ //m_cChild2->m_cParent = make_shared(*this) ;
+ }
+ else {
+ // la cella figlio 1 è quella di sinistra
+ Point3d ptTR( m_dSplit, m_ptPtr.y) ;
+ m_cChild1->SetBottomLeft( m_ptPbl) ;
+ m_cChild1->SetTopRight( ptTR) ;
+ m_cChild1->m_cTop = m_cTop ;
+ m_cChild1->m_cBottom = m_cBottom ;
+ m_cChild1->m_cLeft = m_cLeft ;
+ m_cChild1->m_cRight = m_cChild2 ;
+ //m_cChild1->m_cParent = make_shared(*this) ;
+ Point3d ptBL( m_dSplit, m_ptPbl.y) ;
+ m_cChild2->SetBottomLeft( ptBL) ;
+ m_cChild2->SetTopRight( m_ptPtr) ;
+ m_cChild2->m_cTop = m_cTop ;
+ m_cChild2->m_cBottom = m_cBottom ;
+ m_cChild2->m_cLeft = m_cChild1 ;
+ m_cChild2->m_cRight = m_cRight ;
+ //m_cChild2->m_cParent = make_shared(*this) ;
+ }
+ //m_bProcessed = true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+//Cell::IsLeaf ( void) const
+Cell::IsLeaf ( void)
+{
+ if( m_cChild1 == nullptr && m_cChild2 == nullptr)
+ return true ;
+ else
+ return false ;
+}
+
+//----------------------------------------------------------------------------
+KdTree::KdTree( void)
+ : m_dLinTol(LIN_TOL_FINE), m_pSrfBz(nullptr), m_cRoot( make_shared())
+{}
+
+//----------------------------------------------------------------------------
+KdTree::KdTree( const SurfBezier* pSrfBz)
+ : m_dLinTol( LIN_TOL_FINE), m_pSrfBz ( pSrfBz)
+{
+ // le coordinate delle celle sono nello spazio parametrico
+ int nDegU, nDegV, nSpanU, nSpanV ;
+ bool bIsRat, bTrimmed ;
+ m_pSrfBz->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bIsRat, bTrimmed) ;
+ Point3d ptTop( nSpanU, nSpanV) ;
+ m_cRoot = make_shared() ;
+ m_cRoot->SetBottomLeft( ORIG) ;
+ m_cRoot->SetTopRight( ptTop) ;
+}
+
+//----------------------------------------------------------------------------
+KdTree::~KdTree( void)
+{
+}
+
+//----------------------------------------------------------------------------
+void KdTree::SetSurf( const SurfBezier* pSrfBz)
+{
+ m_pSrfBz = pSrfBz ;
+ // le coordinate delle celle sono nello spazio parametrico
+ int nDegU, nDegV, nSpanU, nSpanV ;
+ bool bIsRat, bTrimmed ;
+ m_pSrfBz->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bIsRat, bTrimmed) ;
+ Point3d ptTop( nSpanU, nSpanV) ;
+ m_cRoot = make_shared() ;
+ m_cRoot->SetBottomLeft( ORIG) ;
+ m_cRoot->SetTopRight( ptTop) ;
+}
+
+//----------------------------------------------------------------------------
+bool KdTree::BuildTree( int nStepU, int nStepV)
+{
+ // trovo dove splittare la cella e creo i puntatori ai figli
+
+ // comincio a suddividere la superficie usando un kd-tree
+ // approssimo con una bilineare e se l'errore di approssimazione è troppo grande cerco una direzione
+ // in cui dividere la superficie
+
+ double err ; // errore calcolato
+ double dist ; // distanza tra punti selezionati
+ double dU, dV , dUmax, dVmax;
+ Point3d ptBz, ptBl ;
+ // cerco lo scostamento massimo tra la sup di Bezier e la sua approssimazione bilineare
+
+ // shared_ptr cToSplit = make_shared(&m_cRoot) ;
+ shared_ptr cToSplit = m_cRoot ;
+
+
+ //while ( cToSplit != nullptr &&
+ // ( cToSplit->IsSame( &m_cRoot) || // per entrare nel ciclo
+ // cToSplit->IsProcessed() == false || // per processare le child1
+ // ( ! cToSplit->IsSame( &m_cRoot) && cToSplit->m_cChild2->IsProcessed() == false))) { // per processare le child2 finché torno alla root
+ int c = 1 ;
+ while ( cToSplit != nullptr && cToSplit->IsProcessed() == false) {
+ err = 0 ;
+ // calcolo la bilineare per gli estremi della cella
+ SurfBezier pSrfBl ;
+ pSrfBl.Init(1, 1, 1, 1, false) ;
+ m_pSrfBz->GetPointD1D2( cToSplit->GetBottomLeft().x, cToSplit->GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz) ;
+ pSrfBl.SetControlPoint( 0, ptBz) ; // P00
+ m_pSrfBz->GetPointD1D2( cToSplit->GetTopRight().x, cToSplit->GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz) ;
+ pSrfBl.SetControlPoint( 1, ptBz) ; // P01
+ m_pSrfBz->GetPointD1D2( cToSplit->GetBottomLeft().x, cToSplit->GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz) ;
+ pSrfBl.SetControlPoint( 2, ptBz) ; // P10
+ m_pSrfBz->GetPointD1D2( cToSplit->GetTopRight().x, cToSplit->GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz) ;
+ pSrfBl.SetControlPoint( 3, ptBz) ; // P11
+ for ( int i = 1 ; i <= nStepU ; ++ i) {
+ for ( int j = 1 ; j <= nStepV ; ++ j) {
+ dU = double ( i) / nStepU * ( cToSplit->GetTopRight().y - cToSplit->GetBottomLeft().y) ;
+ dV = double ( j) / nStepV * ( cToSplit->GetTopRight().x - cToSplit->GetBottomLeft().x) ;
+ if ( ! m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz) ||
+ ! pSrfBl.GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBl))
+ return false ;
+ dist = Dist( ptBz, ptBl) ;
+ if ( dist > err) { // ### nelle condizioni dell'if probabilmente devo già controllare che la dimensione della cella non sia troppo piccola
+ err = dist ;
+ dUmax = dU ;
+ dVmax = dV ;
+ }
+ }
+ }
+ // devo spostare la condizione sulla dimensione minima di una cella/////////////////////////////////////////////////////////////////////
+ // probabilmente qui ###
+ if ( err > m_dLinTol && ( dUmax - cToSplit->GetBottomLeft().y) >= 0.01 && ( dVmax - cToSplit->GetBottomLeft().x) >= 0.01) {
+ // devo trovare i punti sui lati corrispondenti a dUmax e dVmax, unendo queste coppie trovo le due direzioni di possibile split
+ // punti medi del lato successivo in senso orario rispetto al relativo vertice della patch
+ Point3d ptPSrf, ptP00, ptP10, ptP11, ptP01;
+ m_pSrfBz->GetPointD1D2( dUmax, dVmax, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ;
+ m_pSrfBz->GetPointD1D2( dUmax, 0, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00) ;
+ m_pSrfBz->GetPointD1D2( 1, dVmax, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10) ;
+ m_pSrfBz->GetPointD1D2( dUmax, 1, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11) ;
+ m_pSrfBz->GetPointD1D2( 0, dVmax, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01) ;
+ Point3d ptP00P11 = ( 1 - dVmax) * ptP00 + dVmax * ptP11 ;
+ Point3d ptP10P01 = ( 1 - dUmax) * ptP10 + dUmax * ptP01 ;
+ // per lo split scelgo la direzione che è più vicina alla superficie originale nel punto di maggior distanza
+ // effettuo lo split e configuro le celle figlie
+ if ( Dist(ptP00P11, ptPSrf) > Dist(ptP10P01, ptPSrf)) {
+ cToSplit->SetSplitDirVert( false) ;
+ cToSplit->Split( dUmax) ;
+ }
+ else {
+ cToSplit->SetSplitDirVert( true) ;
+ cToSplit->Split( dVmax) ;
+ }
+ cToSplit->m_cChild1->SetParent( cToSplit) ;
+ cToSplit->m_cChild2->SetParent( cToSplit) ;
+ // procedo con lo split del Child1
+ cToSplit = cToSplit->m_cChild1 ;
+ }
+ else {
+ // sono arrivato ad una cella Leaf, quindi salvo il poligono
+ cToSplit->Processed() ;
+ Point3d ptPbr( cToSplit->GetTopRight().x, cToSplit->GetBottomLeft().y) ;
+ Point3d ptPtl( cToSplit->GetBottomLeft().x, cToSplit->GetTopRight().y) ;
+ m_vPolygons.emplace_back() ;
+ m_vPolygons.back().AddUPoint(0, cToSplit->GetBottomLeft()) ;
+ m_vPolygons.back().AddUPoint(0.25, ptPbr) ;
+ m_vPolygons.back().AddUPoint(0.5, cToSplit->GetTopRight()) ;
+ m_vPolygons.back().AddUPoint(0.75, ptPtl) ;
+ m_vPolygons.back().AddUPoint(1, cToSplit->GetBottomLeft()) ;
+ // risalgo i parent finché non trovo il primo Child2 da processare
+ cToSplit = cToSplit->m_cParent ;
+ if ( cToSplit->m_cChild1->IsProcessed() && cToSplit->m_cChild2->IsProcessed())
+ cToSplit->Processed() ;
+ // questa condizione mi manda in un loop perché non processo mai il child2 di root
+ // a'altro canto devo evitare di fare i passaggi successivi se sono già parent processato
+
+ //if ( cToSplit->IsSame( &m_cRoot))
+ // continue ;
+
+ while ( cToSplit->m_cChild2->IsProcessed()) {
+ if ( cToSplit->m_cParent != nullptr )
+ cToSplit = cToSplit->m_cParent ;
+ if ( cToSplit->m_cChild1->IsProcessed() && cToSplit->m_cChild2->IsProcessed())
+ cToSplit->Processed() ;
+ if ( cToSplit->IsSame( m_cRoot) && cToSplit->m_cChild2->IsProcessed())
+ break ;
+ }
+ //if ( cToSplit->IsSame( &m_cRoot))
+ // continue ;
+ //else
+ // cToSplit = cToSplit->m_cChild2 ;
+
+ cToSplit = cToSplit->m_cChild2 ;
+ }
+ c ++ ;
+ }
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool KdTree::GetPolygons( POLYLINEVECTOR& vPolygons)
+{
+ // restituisco i poligoni delle celle del kd-tree nello spazio parametrico
+ if ( m_vPolygons.empty())
+ return false ;
+ vPolygons = m_vPolygons ;
+ return true ;
+}
\ No newline at end of file
diff --git a/KdTree.h b/KdTree.h
new file mode 100644
index 0000000..c782103
--- /dev/null
+++ b/KdTree.h
@@ -0,0 +1,73 @@
+//----------------------------------------------------------------------------
+// EgalTech 2023
+//----------------------------------------------------------------------------
+// File : Kd-tree.h Data : 21.04.23 Versione :
+// Contenuto : Implementazione della classe Cell di un kd-tree.
+//
+//
+//
+// Modifiche : 21.04.23 DB Creazione modulo.
+//
+//
+//----------------------------------------------------------------------------
+
+#pragma once
+
+//--------------------------- Include ----------------------------------------
+#include "SurfBezier.h"
+
+//----------------------------------------------------------------------------
+class Cell
+{
+ public :
+ ~Cell( void) ;
+ Cell( void) ;
+ Cell( Point3d ptBL, Point3d ptTR) : m_ptPbl( ptBL), m_ptPtr(ptTR) {}
+ inline bool IsSame ( std::shared_ptr cOtherCell) ;
+ void SetBottomLeft( Point3d ptBL) { m_ptPbl = ptBL ; }
+ void SetTopRight( Point3d ptTR) { m_ptPtr = ptTR ; }
+ void SetSplitDirVert( bool bVert) { m_bSplitVert = bVert ; }
+ void SetSplitValue ( double dSplitValue) { m_dSplit = dSplitValue ; }
+ void SetParent (std::shared_ptr pCParent) { m_cParent = pCParent ; }
+ void Split( double dSpiltValue) ;
+ Point3d GetBottomLeft( void) { return m_ptPbl ; }
+ Point3d GetTopRight( void) { return m_ptPtr ; }
+ //bool IsLeaf( void) const ;
+ bool IsLeaf( void) ;
+ bool IsProcessed ( void) const { return m_bProcessed ; }
+ void Processed ( void) { m_bProcessed = true ; }
+
+ public :
+ std::shared_ptr m_cTop ; // cella adiacente al lato top
+ std::shared_ptr m_cBottom ; // cella adiacente al lato bottom
+ std::shared_ptr m_cLeft ; // cella adiacente al lato left
+ std::shared_ptr m_cRight ; // cella adiacente al lato right
+ std::shared_ptr m_cParent ; // cella genitore
+ std::shared_ptr m_cChild1 ; // prima cella figlio
+ std::shared_ptr m_cChild2 ; // seconda cella figlio
+
+ private :
+ Point3d m_ptPbl ; // punto bottom left
+ Point3d m_ptPtr ; // punto top right
+ bool m_bProcessed ; // flag che indica se la cella è stata processata
+ bool m_bSplitVert ; // flag che indica in quale direzione è stata divisa la cella
+ double m_dSplit ; // lunghezza normalizzata a cui è stata splittata la cella
+} ;
+
+//----------------------------------------------------------------------------
+class KdTree
+{
+public :
+ ~KdTree( void) ;
+ KdTree( void) ;
+ KdTree ( const SurfBezier* pSrfBz) ;
+ void SetSurf( const SurfBezier* pSrfBz) ;
+ bool BuildTree( int nStepU, int nStepV) ;
+ bool GetPolygons( POLYLINEVECTOR& vPolygons) ;
+
+private :
+ double m_dLinTol ; // errore dell'approssimazione
+ std::shared_ptr| m_cRoot ; // cella base
+ const SurfBezier* m_pSrfBz ; // root
+ POLYLINEVECTOR m_vPolygons ; // vettore dei poligoni del kd-tree
+} ;
\ No newline at end of file
diff --git a/SurfBezier.cpp b/SurfBezier.cpp
index ef96e0d..1ec67b5 100644
--- a/SurfBezier.cpp
+++ b/SurfBezier.cpp
@@ -20,6 +20,9 @@
#include "Bernstein.h"
#include "CurveBezier.h"
#include "CurveComposite.h"
+#include "KdTree.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 ;
+
}
//----------------------------------------------------------------------------
@@ -1372,6 +1376,82 @@ SurfBezier::GetCurveOnVApproxLen( double dU) const
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*
SurfBezier::GetAuxSurf( void) const
@@ -1384,10 +1464,6 @@ SurfBezier::GetAuxSurf( void) const
// 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)
@@ -1397,54 +1473,121 @@ SurfBezier::GetAuxSurf( void) const
for ( int i = 0 ; i <= m_nDegU * m_nSpanU ; ++ i)
dMaxLenV = max( dMaxLenV, GetCurveOnVApproxLen( double( i) / m_nDegU)) ;
int nStepV = GetSteps( m_nDegV, m_nSpanV, dMaxLenV, 2) ;
- // 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) ;
+ if ( m_nDegU == 1 && m_nDegV == 1) {
+ // costruttore della superficie
+ StmFromTriangleSoup stmSoup ;
+ if ( ! stmSoup.Start())
+ return nullptr ;
+ // prima curva isoparametrica (potrebbe essere un solo punto)
+ PolyLine PL1 ;
+ GetCurveOnU( 0, nStepU, PL1) ;
+ bool bSingle1 = ( PL1.GetPointNbr() == 1) ;
+ // ciclo sulle isoparametriche
+ for ( int i = 1 ; i <= nStepV ; ++ i) {
+ // seconda curva isoparametrica (con tanti punti quanti la prima, oppure uno solo)
+ double dV = double( i) * m_nSpanV / nStepV ;
+ PolyLine PL2 ;
+ GetCurveOnU( dV, nStepU, PL2) ;
+ bool bSingle2 = ( PL2.GetPointNbr() == 1) ;
+ // inserisco i triangoli della striscia nel costruttore della TriMesh
+ Point3d ptP1c, ptP2c ;
+ Point3d ptP1n, ptP2n ;
+ bool bNext = PL1.GetFirstPoint( ptP1c) && PL2.GetFirstPoint( ptP2c) ;
+ if ( bNext) {
+ if ( bSingle1 && bSingle2)
+ bNext = false ;
+ if ( bSingle1)
+ ptP1n = ptP1c ;
+ else
+ bNext = bNext && PL1.GetNextPoint( ptP1n) ;
+ if ( bSingle2)
+ ptP2n = ptP2c ;
+ else
+ bNext = bNext && PL2.GetNextPoint( ptP2n) ;
+ }
+ while ( bNext) {
+ // eventuale primo triangolo (con base sui correnti e vertice su P2 successivo)
+ if ( ! AreSamePointApprox( ptP1c, ptP2c))
+ stmSoup.AddTriangle( ptP2c, ptP1c, ptP2n) ;
+ // eventuale secondo triangolo (con vertice su P1 corrente e base sui successivi)
+ if ( ! AreSamePointApprox( ptP1n, ptP2n))
+ stmSoup.AddTriangle( ptP1c, ptP1n, ptP2n) ;
+ // passo alla successiva coppia
+ ptP1c = ptP1n ;
+ ptP2c = ptP2n ;
+ bNext = ( bSingle1 || PL1.GetNextPoint( ptP1n)) && ( bSingle2 || PL2.GetNextPoint( ptP2n)) ;
+ }
+ // salvo isoparametrica PL2 in PL1
+ PL1.GetUPointList().swap( PL2.GetUPointList()) ;
+ bSingle1 = bSingle2 ;
}
- 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)) ;
+ // la completo
+ if ( ! stmSoup.End())
+ return nullptr ;
+ // la salvo
+ m_pSTM = GetBasicSurfTriMesh( stmSoup.GetSurf()) ;
+ }
+ else {
+ // costruttore della superficie
+ KdTree kdTree( this) ;
+ kdTree.BuildTree( nStepU, nStepV) ;
+ POLYLINEVECTOR vPL ;
+ kdTree.GetPolygons( vPL) ;
+ PtrOwner pSrfTm( CreateBasicSurfTriMesh()) ;
+
+ //srfTm.CreateByRegion( vPL) ;
+ // prendo i punti di ogni polyline dell'albero, li triangolo e li porto in 3d
+ for ( PolyLine i : vPL ) {
+ SurfTriMesh srfTmCell ;
+ PNTVECTOR vPnt ;
+ INTVECTOR vTria ;
+ Triangulate Tri ;
+ if ( ! Tri.Make( i, vPnt, vTria))
+ return false ;
+
+ // inizializzo la superficie
+ int nVert = int( vPnt.size()) ;
+ int nTria = int( vTria.size()) / 3 ;
+ if ( ! srfTmCell.Init( nVert, nTria))
+ return false ;
+
+ // porti i vertici dallo spazio parametrico allo spazio 3d e li inserisco nella superficie
+ for ( int i = 0 ; i < int( vPnt.size()) ; ++ i) {
+ Point3d pt3d;
+ GetPointD1D2( vPnt[i].y, vPnt[i].x, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ;
+ if ( srfTmCell.AddVertex( pt3d) == SVT_NULL)
+ return false ;
+ }
+
+ // recupero i triangoli e li inserisco nella superficie
+ int vV[3] ;
+ for ( int i = 0 ; i < nTria ; ++i) {
+ vV[0] = vTria[3*i] ;
+ vV[1] = vTria[3*i+1] ;
+ vV[2] = vTria[3*i+2] ;
+ if ( srfTmCell.AddTriangle( vV) == SVT_NULL)
+ return false ;
+ }
+
+ // sistemo la topologia
+ if ( ! srfTmCell.AdjustTopology())
+ return false ;
+ //if ( ! pSrfTm->Add( srfTmCell))
+ // return false ;
+
+ if ( ! pSrfTm->IsValid() ) {
+ *pSrfTm= srfTmCell ;
+ }
+ else {
+ if ( ! pSrfTm->Add( srfTmCell))
+ return false ;
+ }
+
}
- // 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()) ;
+
+ // la salvo
+ m_pSTM = Release(pSrfTm) ;
+ }
return m_pSTM ;
}
diff --git a/SurfBezier.h b/SurfBezier.h
index f64e5a1..b5366e9 100644
--- a/SurfBezier.h
+++ b/SurfBezier.h
@@ -166,7 +166,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
} ;
//-----------------------------------------------------------------------------
| | | | | | | | | | | | | | | | | | | | | | | | | | | |