EgtGeomKernel :
- implementazione delle classi KdTree e Cell - problemi : bilanciamento albero e uso puntatori
This commit is contained in:
@@ -339,6 +339,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="IntersPlaneTria.cpp" />
|
||||
<ClCompile Include="IntersSurfTmSurfTm.cpp" />
|
||||
<ClCompile Include="IntersTriaTria.cpp" />
|
||||
<ClCompile Include="KdTree.cpp" />
|
||||
<ClCompile Include="MedialAxis.cpp" />
|
||||
<ClCompile Include="OffsetCurve.cpp" />
|
||||
<ClCompile Include="DistPointArc.cpp" />
|
||||
@@ -603,6 +604,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClInclude Include="IntersLineSurfStd.h" />
|
||||
<ClInclude Include="IntersLineTria.h" />
|
||||
<ClInclude Include="IterManager.h" />
|
||||
<ClInclude Include="KdTree.h" />
|
||||
<ClInclude Include="Material.h" />
|
||||
<ClInclude Include="FontNfe.h" />
|
||||
<ClInclude Include="MC_Tables.h" />
|
||||
|
||||
@@ -471,6 +471,9 @@
|
||||
<ClCompile Include="MedialAxis.cpp">
|
||||
<Filter>File di origine\GeoOffset</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="KdTree.cpp">
|
||||
<Filter>File di origine\Base</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
@@ -1103,6 +1106,9 @@
|
||||
<ClInclude Include="CDeCapsTria.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="KdTree.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="EgtGeomKernel.rc">
|
||||
|
||||
+286
@@ -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<Cell> 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<Cell>() ;
|
||||
//m_cChild2 = &cChild2 ;
|
||||
//m_cParent = &cParent ;
|
||||
//m_cTop = &cTop ;
|
||||
//m_cBottom = &cBottom ;
|
||||
//m_cLeft = &cLeft ;
|
||||
//m_cRight = &cRight ;
|
||||
|
||||
m_cChild2 = make_shared<Cell>() ;
|
||||
//m_cParent = make_shared<Cell>() ;
|
||||
//m_cTop = make_shared<Cell>() ;
|
||||
//m_cBottom = make_shared<Cell>() ;
|
||||
//m_cLeft = make_shared<Cell>() ;
|
||||
//m_cRight = make_shared<Cell>() ;
|
||||
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<Cell>(*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<Cell>(*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<Cell>(*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<Cell>(*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<Cell>())
|
||||
{}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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<Cell>() ;
|
||||
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<Cell>() ;
|
||||
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<Cell> cToSplit = make_shared<Cell>(&m_cRoot) ;
|
||||
shared_ptr<Cell> 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 ;
|
||||
}
|
||||
@@ -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<Cell> 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<Cell> 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<Cell> m_cTop ; // cella adiacente al lato top
|
||||
std::shared_ptr<Cell> m_cBottom ; // cella adiacente al lato bottom
|
||||
std::shared_ptr<Cell> m_cLeft ; // cella adiacente al lato left
|
||||
std::shared_ptr<Cell> m_cRight ; // cella adiacente al lato right
|
||||
std::shared_ptr<Cell> m_cParent ; // cella genitore
|
||||
std::shared_ptr<Cell> m_cChild1 ; // prima cella figlio
|
||||
std::shared_ptr<Cell> 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<Cell> m_cRoot ; // cella base
|
||||
const SurfBezier* m_pSrfBz ; // root
|
||||
POLYLINEVECTOR m_vPolygons ; // vettore dei poligoni del kd-tree
|
||||
} ;
|
||||
+194
-51
@@ -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<SurfTriMesh> 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 ;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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
|
||||
} ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user