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
This commit is contained in:
@@ -25,8 +25,8 @@ using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Cell::Cell( void)
|
||||
: m_nId( -1), m_ptPbl( ORIG), m_bProcessed ( false) , m_bSplitVert ( true) , m_nTop ( -2), m_nBottom( -2),
|
||||
m_nLeft( -2), m_nRight ( -2), m_nParent( -2), m_nDepth( 0), m_nChild1( -2), m_nChild2( -2)
|
||||
: m_nId( -1),m_nTop ( -2), m_nBottom( -2), m_nLeft( -2), m_nRight ( -2), m_nParent( -2), m_nDepth( 0),
|
||||
m_nChild1( -2), m_nChild2( -2), m_ptPbl( ORIG), m_ptPtr(), m_bProcessed ( false) , m_bSplitVert ( true)
|
||||
{
|
||||
Point3d ptTr ( 1, 1) ;
|
||||
m_ptPtr = ptTr ;
|
||||
@@ -35,8 +35,8 @@ Cell::Cell( void)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Cell::Cell( Point3d ptBL, Point3d ptTR)
|
||||
: m_nId( -1), m_ptPbl( ptBL), m_ptPtr(ptTR), m_bProcessed ( false) , m_bSplitVert ( true) , m_nTop ( -2),
|
||||
m_nBottom( -2), m_nLeft( -2), m_nRight ( -2), m_nParent( -2), m_nDepth( 0), m_nChild1( -2), m_nChild2( -2)
|
||||
: m_nId( -1),m_nTop ( -2), m_nBottom( -2), m_nLeft( -2), m_nRight ( -2), m_nParent( -2), m_nDepth( 0),
|
||||
m_nChild1( -2), m_nChild2( -2), m_ptPbl( ptBL), m_ptPtr(ptTR), m_bProcessed ( false) , m_bSplitVert ( true)
|
||||
{}
|
||||
|
||||
|
||||
@@ -47,21 +47,17 @@ Cell::~Cell( void)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline bool
|
||||
Cell::IsSame( Cell cOtherCell)
|
||||
Cell::IsSame( Cell cOtherCell) const
|
||||
{
|
||||
if ( AreSamePointXYApprox( m_ptPbl, cOtherCell.GetBottomLeft()) &&
|
||||
AreSamePointXYApprox( m_ptPtr, cOtherCell.GetTopRight())) {
|
||||
if ( m_nId == cOtherCell.m_nId)
|
||||
return true ;
|
||||
}
|
||||
else {
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
//Cell::IsLeaf ( void) const
|
||||
Cell::IsLeaf ( void)
|
||||
Cell::IsLeaf ( void) const
|
||||
{
|
||||
if( m_nChild1 == -2 && m_nChild2 == -2)
|
||||
return true ;
|
||||
@@ -71,25 +67,18 @@ Cell::IsLeaf ( void)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Tree::Tree( void)
|
||||
: m_dLinTol(LIN_TOL_FINE), m_pSrfBz(nullptr), m_nRoot( -1), m_bTrimmed( false)
|
||||
: m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosed( false)
|
||||
{
|
||||
Point3d ptBl( 0, 0), ptTr ( 1, 1) ;
|
||||
Cell cRoot( ptBl, ptTr) ;
|
||||
m_mTree.insert( pair< int, Cell>( m_nRoot, cRoot)) ;
|
||||
m_mTree.insert( pair< int, Cell>( -1, cRoot)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Tree::Tree( const SurfBezier* pSrfBz)
|
||||
: m_dLinTol( LIN_TOL_FINE), m_pSrfBz ( pSrfBz), m_nRoot( -1)
|
||||
Tree::Tree( const SurfBezier* pSrfBz, bool bSplitPatches)
|
||||
: m_bBilinear( false), m_bMulti( false), m_bClosed( false)
|
||||
{
|
||||
// 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) ;
|
||||
m_bTrimmed = bTrimmed ;
|
||||
Point3d ptTop( nSpanU, nSpanV) ;
|
||||
Cell cRoot( ORIG, ptTop) ;
|
||||
m_mTree.insert( pair< int, Cell>( m_nRoot, cRoot)) ;
|
||||
SetSurf( pSrfBz, bSplitPatches) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -98,23 +87,83 @@ Tree::~Tree( void)
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Tree::SetSurf( const SurfBezier* pSrfBz)
|
||||
void Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches)
|
||||
{
|
||||
m_pSrfBz = pSrfBz ;
|
||||
// le coordinate delle celle sono nello spazio parametrico
|
||||
// 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) ;
|
||||
m_bTrimmed = bTrimmed ;
|
||||
if ( nDegU == 1 && nDegV == 1)
|
||||
m_bBilinear = true ;
|
||||
if ( nSpanU * nSpanV != 1)
|
||||
m_bMulti = true ;
|
||||
if ( bSplitPatches) {
|
||||
int nId = -1 ;
|
||||
for ( int i = 1 ; i < nSpanU ; ++i ) {
|
||||
m_mTree[nId].SetSplitDirVert( true) ;
|
||||
Split( nId, i) ;
|
||||
}
|
||||
for ( int j = 1 ; j < nSpanV ; ++j ) {
|
||||
|
||||
}
|
||||
|
||||
// split preliminari per dividere le patch in modo da triangolarle indipendentemente////////////////////////////////////////////////////////
|
||||
// devo sistemare le adiacenze // queste si sistemano da sole con lo split
|
||||
|
||||
// così creo dei child1 da cui devo ripassare per processarle, ma nel mio algoritmo non è previto!!!!!!!!!!!!!!!!!
|
||||
}
|
||||
// salvo i vertici 3d della cella root
|
||||
Point3d ptTop( nSpanU, nSpanV) ;
|
||||
Cell cRoot( ORIG, ptTop) ;
|
||||
m_mTree.insert( pair< int, Cell>( -1, cRoot)) ;
|
||||
Point3d ptP00, ptP10, ptP11, ptP01 ;
|
||||
bool bOk = false ;
|
||||
PNTVECTOR vVert ;
|
||||
ptP00 = m_pSrfBz->GetControlPoint( 0, &bOk);
|
||||
vVert.push_back( ptP00) ;
|
||||
ptP10 = m_pSrfBz->GetControlPoint( nDegU * nSpanU, &bOk) ;
|
||||
vVert.push_back( ptP10) ;
|
||||
ptP11 = m_pSrfBz->GetControlPoint( ( nDegU * nSpanU + 1) * ( nDegV * nSpanV + 1) - 1, &bOk) ;
|
||||
vVert.push_back( ptP11) ;
|
||||
ptP01 = m_pSrfBz->GetControlPoint( ( nDegU * nSpanU + 1 ) * ( nDegV * nSpanV), &bOk) ;
|
||||
vVert.push_back( ptP01) ;
|
||||
m_mVert.insert( pair<int, PNTVECTOR>( -1, vVert)) ;
|
||||
// verifico se la superficie è chiusa ed eventualmente sistemo le adiacenze
|
||||
if ( ( AreSamePointApprox(ptP00, ptP01) && AreSamePointApprox(ptP10, ptP11) ) ||
|
||||
( AreSamePointApprox(ptP00, ptP10) && AreSamePointApprox(ptP01, ptP11) ) ) {
|
||||
m_bClosed = true ;
|
||||
// devo gestire se passo da entrambi questi if///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
if ( AreSamePointApprox(ptP00, ptP01)) {
|
||||
m_mTree[-1].m_nTop = -1 ;
|
||||
m_mTree[-1].m_nBottom = -1 ;
|
||||
m_mTree[-1].SetSplitDirVert( false) ;
|
||||
Split(-1) ;
|
||||
}
|
||||
if (AreSamePointApprox(ptP00, ptP10)) {
|
||||
m_mTree[-1].m_nLeft = -1 ;
|
||||
m_mTree[-1].m_nRight = -1 ;
|
||||
m_mTree[-1].SetSplitDirVert( true) ;
|
||||
Split( -1) ;
|
||||
}
|
||||
}
|
||||
// calcolo e salvo la distanza reale tra i vertici della cella root
|
||||
double dLen0 = Dist( ptP00, ptP10) ;
|
||||
double dLen1 = Dist( ptP10, ptP11) ;
|
||||
double dLen2 = Dist( ptP01, ptP11) ;
|
||||
double dLen3 = Dist( ptP00, ptP01) ;
|
||||
m_vDim.push_back( ( dLen0 != 0 ? dLen0 : 1)) ;
|
||||
m_vDim.push_back( ( dLen1 != 0 ? dLen1 : 1)) ;
|
||||
m_vDim.push_back( ( dLen2 != 0 ? dLen2 : 1)) ;
|
||||
m_vDim.push_back( ( dLen3 != 0 ? dLen3 : 1)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
Tree::Split( int nId)
|
||||
Tree::Split( int nId, double dSplitValue)
|
||||
{
|
||||
// per lo split a parametro libero devo impedire che si facciano split troppo vicini al bordo!!!!!!!!!!!!!!!!!!!
|
||||
Cell cChild1, cChild2 ;
|
||||
cChild1.m_nDepth = m_mTree[nId].m_nDepth + 1 ;
|
||||
cChild2.m_nDepth = m_mTree[nId].m_nDepth + 1 ;
|
||||
@@ -125,6 +174,10 @@ Tree::Split( int nId)
|
||||
m_mTree[nId].m_nChild2 = nNodes ;
|
||||
m_mTree.insert( pair<int, Cell>( nNodes - 1, cChild1)) ;
|
||||
m_mTree.insert( pair<int, Cell>( nNodes, cChild2)) ;
|
||||
Point3d ptVert1, ptVert2 ;
|
||||
PNTVECTOR vVert ;
|
||||
m_mVert.insert( pair<int, PNTVECTOR>( nNodes - 1, vVert)) ;
|
||||
m_mVert.insert( pair<int, PNTVECTOR>( nNodes, vVert)) ;
|
||||
if ( ! m_mTree[nId].IsSplitVert())
|
||||
{
|
||||
// la cella figlio 1 è quella sopra
|
||||
@@ -142,6 +195,19 @@ Tree::Split( int nId)
|
||||
m_mTree[m_mTree[nId].m_nChild2].m_nBottom = m_mTree[nId].m_nBottom ;
|
||||
m_mTree[m_mTree[nId].m_nChild2].m_nLeft = m_mTree[nId].m_nLeft ;
|
||||
m_mTree[m_mTree[nId].m_nChild2].m_nRight = m_mTree[nId].m_nRight ;
|
||||
// metto i corrispondenti 3d dei punti dello split nella mappa m_mVert
|
||||
// per ogni cella i punti devono essere nell'ordine ptP00, ptP10, ptP11, ptP01
|
||||
//double dV = ( 1 - dSplitValue) * m_mTree[nId].GetBottomLeft().y + dSplitValue * m_mTree[nId].GetTopRight().y ;
|
||||
m_pSrfBz->GetPointD1D2( m_mTree[nId].GetBottomLeft().x, dSplitValue, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptVert1) ;
|
||||
m_pSrfBz->GetPointD1D2( m_mTree[nId].GetTopRight().x, dSplitValue, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptVert2) ;
|
||||
m_mVert[nNodes - 1].push_back( ptVert1) ;
|
||||
m_mVert[nNodes - 1].push_back( ptVert2) ;
|
||||
m_mVert[nNodes - 1].push_back( m_mVert[nId][2]) ;
|
||||
m_mVert[nNodes - 1].push_back( m_mVert[nId][3]) ;
|
||||
m_mVert[nNodes].push_back( m_mVert[nId][0]) ;
|
||||
m_mVert[nNodes].push_back( m_mVert[nId][1]) ;
|
||||
m_mVert[nNodes].push_back( ptVert2) ;
|
||||
m_mVert[nNodes].push_back( ptVert1) ;
|
||||
}
|
||||
else {
|
||||
// la cella figlio 1 è quella di sinistra
|
||||
@@ -159,253 +225,359 @@ Tree::Split( int nId)
|
||||
m_mTree[m_mTree[nId].m_nChild2].m_nBottom = m_mTree[nId].m_nBottom ;
|
||||
m_mTree[m_mTree[nId].m_nChild2].m_nLeft = m_mTree[nId].m_nChild1 ;
|
||||
m_mTree[m_mTree[nId].m_nChild2].m_nRight = m_mTree[nId].m_nRight ;
|
||||
// metto i corrispondenti 3d dei punti dello split nella mappa m_mVert
|
||||
// per ogni cella i punti devono essere nell'ordine ptP00, ptP10, ptP11, ptP01
|
||||
//double dU = ( m_mTree[nId].GetBottomLeft().x + m_mTree[nId].GetTopRight().x) / 2 ;
|
||||
m_pSrfBz->GetPointD1D2( dSplitValue, m_mTree[nId].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptVert2) ;
|
||||
m_pSrfBz->GetPointD1D2( dSplitValue, m_mTree[nId].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptVert1) ;
|
||||
m_mVert[nNodes - 1].push_back( m_mVert[nId][0]) ;
|
||||
m_mVert[nNodes - 1].push_back( ptVert2) ;
|
||||
m_mVert[nNodes - 1].push_back( ptVert1) ;
|
||||
m_mVert[nNodes - 1].push_back( m_mVert[nId][3]) ;
|
||||
m_mVert[nNodes].push_back( ptVert2) ;
|
||||
m_mVert[nNodes].push_back( m_mVert[nId][1]) ;
|
||||
m_mVert[nNodes].push_back( m_mVert[nId][2]) ;
|
||||
m_mVert[nNodes].push_back( ptVert1) ;
|
||||
}
|
||||
m_mTree[m_mTree[nId].m_nChild1].SetParent( nId) ;
|
||||
m_mTree[m_mTree[nId].m_nChild2].SetParent( nId) ;
|
||||
//m_bProcessed = true ;
|
||||
}
|
||||
|
||||
////----------------------------------------------------------------------------
|
||||
//bool Tree::BuildTree(void)
|
||||
//{
|
||||
// // di default SplitVert è true !
|
||||
// int ToSplit = -1;
|
||||
// m_mTree[ToSplit].SetSplitDirVert( true) ;
|
||||
// Split( ToSplit) ;
|
||||
// // celle 2 e 3
|
||||
// ToSplit = m_mTree[-1].m_nChild1 ;
|
||||
// m_mTree[ToSplit].SetSplitDirVert( false) ;
|
||||
// Split( ToSplit) ;
|
||||
// // celle 4 e 5
|
||||
// ToSplit = m_mTree[ToSplit].m_nChild1 ;
|
||||
// m_mTree[ToSplit].SetSplitDirVert( true) ;
|
||||
// Split( ToSplit) ;
|
||||
// // celle 6 e 7
|
||||
// ToSplit = m_mTree[ToSplit].m_nChild2 ;
|
||||
// m_mTree[ToSplit].SetSplitDirVert( false) ;
|
||||
// Split( ToSplit) ;
|
||||
// // celle 8 e 9
|
||||
// ToSplit = m_mTree[ToSplit].m_nChild2 ;
|
||||
// m_mTree[ToSplit].SetSplitDirVert( true) ;
|
||||
// Split( ToSplit) ;
|
||||
// // celle 10 e 11
|
||||
// ToSplit = m_mTree[ToSplit].m_nChild1 ;
|
||||
// m_mTree[ToSplit].SetSplitDirVert( false) ;
|
||||
// Split( ToSplit) ;
|
||||
// // celle 12 e 13
|
||||
// ToSplit = m_mTree[ToSplit].m_nParent ;
|
||||
// ToSplit = m_mTree[ToSplit].m_nChild2 ;
|
||||
// m_mTree[ToSplit].SetSplitDirVert( true) ;
|
||||
// Split( ToSplit) ;
|
||||
// INTVECTOR vTops, vBottoms, vLefts, vRights , vLeaves1, vLeaves2, vLeaves;
|
||||
// int d1, d2 , H1 ;
|
||||
// GetTopNeigh( 3, vTops) ;
|
||||
// GetBottomNeigh( 6, vBottoms) ;
|
||||
// GetLeftNeigh( 1, vLefts) ;
|
||||
// GetRightNeigh( 4, vRights ) ;
|
||||
// d1 = GetHeightLeaves( 7, vLeaves1) ;
|
||||
// d2 = GetHeightLeaves( 5, vLeaves2) ;
|
||||
// H1 = GetHeightLeaves( -1, vLeaves) ;
|
||||
// m_vnLeaves = vLeaves ;
|
||||
// int i = 0 ;
|
||||
//
|
||||
// return true ;
|
||||
//}
|
||||
|
||||
////----------------------------------------------------------------------------
|
||||
//bool Tree::BuildTree( void)
|
||||
//{
|
||||
// int ToSplit = -1 ;
|
||||
// m_mTree[ToSplit].SetSplitDirVert( true) ;
|
||||
// Split( ToSplit) ;
|
||||
// // celle 2 e 3
|
||||
// ToSplit = m_mTree[-1].m_nChild1 ;
|
||||
// m_mTree[ToSplit].SetSplitDirVert( false) ;
|
||||
// Split( ToSplit) ;
|
||||
//
|
||||
// return true ;
|
||||
//}
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
Tree::Split( int nId)
|
||||
{
|
||||
double dValue ;
|
||||
if ( m_mTree[nId].IsSplitVert())
|
||||
dValue = ( m_mTree[nId].GetBottomLeft().x + m_mTree[nId].GetTopRight().x) / 2 ;
|
||||
else
|
||||
dValue = ( m_mTree[nId].GetBottomLeft().y + m_mTree[nId].GetTopRight().y) / 2 ;
|
||||
Split( nId, dValue) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool Tree::BuildTree( double dLinTol, double dSideMax)
|
||||
bool Tree::BuildTree( double dLinTol_, double dSideMin, double dSideMax)
|
||||
{
|
||||
// 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 dErr ; // errore calcolato
|
||||
double dDist; // distanza tra punti selezionati sulla isoparametrica
|
||||
double dSideMinVal, dSideMaxVal ; // lunghezza del lato della eventuale cella figlio
|
||||
double dSplit = 0.5 ; // effettuo sempre split a metà
|
||||
double dSideMin = 0.05 ; // lunghezza minima del lato di una cella
|
||||
//double dSidemin = 0.1 ; // lunghezza minima del lato di una cella
|
||||
//m_dLinTol = dLinTol ;
|
||||
m_dLinTol = 0.2 ;
|
||||
int nSteps = 51 ; // numero di Step mentre scorro lungo un'isoparametrica
|
||||
double dU, dV , dULoc, dVLoc ;
|
||||
//double dIter, dIterLoc ;
|
||||
bool bVert ;
|
||||
Point3d ptBz, ptBl ;
|
||||
// cerco lo scostamento massimo tra la sup di Bezier e la sua approssimazione bilineare
|
||||
// suddivido lo spazio parametrico con divisioni a metà su uno dei due parametri
|
||||
INTVECTOR vBalanceCheck ;
|
||||
int nCToSplit = -1 ;
|
||||
// se ho già fatto degli split preliminari parto dal primo child anziché dal root
|
||||
if ( (int) m_mTree.size() > 1)
|
||||
nCToSplit = 0 ;
|
||||
double dLinTol = 0.2 ;
|
||||
//double dSideMin = 1 ;
|
||||
if ( ! m_bTrimmed) {
|
||||
if ( ! m_bBilinear) {
|
||||
while ( nCToSplit != -2 && m_mTree[nCToSplit].IsProcessed() == false) {
|
||||
// calcolo in quale direzione ho più curvatura
|
||||
// ptP00P10 è un punto tra P00 e P10
|
||||
double dU = ( m_mTree[nCToSplit].GetTopRight().x + m_mTree[nCToSplit].GetBottomLeft().x) / 2 ;
|
||||
double dV = ( m_mTree[nCToSplit].GetTopRight().y + m_mTree[nCToSplit].GetBottomLeft().y) / 2 ;
|
||||
double dULoc = 0.5, dVLoc = 0.5 ;
|
||||
Point3d ptPSrf, ptP00P10, ptP10P11, ptP11P01, ptP01P00 ;
|
||||
m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ;
|
||||
m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00P10) ;
|
||||
m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10P11) ;
|
||||
m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11P01) ;
|
||||
m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01P00) ;
|
||||
Point3d ptV = ( 1 - dULoc) * ptP00P10 + dULoc * ptP11P01 ;
|
||||
Point3d ptU = ( 1 - dVLoc) * ptP10P11 + dVLoc * ptP01P00 ;
|
||||
// per lo split scelgo la direzione che è più vicina alla superficie originale nel punto di maggior distanza
|
||||
// misura approssimativa della curvatura in una direzione
|
||||
double dCurvV = Dist(ptV, ptPSrf) ;
|
||||
double dCurvU = Dist(ptU, ptPSrf) ;
|
||||
bool bVert ;
|
||||
if ( dCurvV > dCurvU) {
|
||||
// lungo la direzione V ho una curvatura maggiore
|
||||
bVert = false ;
|
||||
}
|
||||
else {
|
||||
// lungo la direzione U ho una curvatura maggiore
|
||||
bVert = true ;
|
||||
}
|
||||
Point3d ptP00, ptP10, ptP11, ptP01 ;
|
||||
// distanza reale tra i vertici della cella
|
||||
ptP00 = m_mVert[nCToSplit][0] ;
|
||||
ptP10 = m_mVert[nCToSplit][1] ;
|
||||
ptP11 = m_mVert[nCToSplit][2] ;
|
||||
ptP01 = m_mVert[nCToSplit][3] ;
|
||||
double dLen0 = Dist( ptP00, ptP10) ;
|
||||
double dLen1 = Dist( ptP10, ptP11) ;
|
||||
double dLen2 = Dist( ptP01, ptP11) ;
|
||||
double dLen3 = Dist( ptP00, ptP01) ;
|
||||
// verifico che la cella sia da splittare e che eventualmente sia abbastanza grande da poterlo fare
|
||||
double dSideMinVal = 0, dSideMaxVal = 0 ;
|
||||
if ( bVert) {
|
||||
if ( dLen0 != 0 && dLen2 != 0)
|
||||
dSideMinVal = min( dLen0, dLen2) ;
|
||||
else
|
||||
dSideMinVal = max( dLen0, dLen2) ;
|
||||
}
|
||||
else {
|
||||
if ( dLen1 != 0 && dLen3 != 0)
|
||||
dSideMinVal = min( dLen1, dLen3) ;
|
||||
else
|
||||
dSideMinVal = max( dLen1, dLen3) ;
|
||||
}
|
||||
// calcolo le diagonali per controllare la dimensione massima dei triangoli in cui dividerei la cella
|
||||
dSideMaxVal = max( Dist( ptP00, ptP11), Dist( ptP10, ptP01)) ;
|
||||
|
||||
// se la cella è abbastanza grande da poter essere divisa ancora, calcolo l'errore di approssimazione
|
||||
double dErr = 0 ;
|
||||
if ( dSideMinVal / 2 >= dSideMin && dSideMaxVal < dSideMax && ( dCurvV > dLinTol || dCurvU > dLinTol)) {
|
||||
CurveLine cl0010, cl0001, cl1011, cl0111 ;
|
||||
// U=0
|
||||
cl0010.Set( ptP00, ptP10) ;
|
||||
// U=1
|
||||
cl0111.Set( ptP01, ptP11) ;
|
||||
Point3d pt0010, pt0111, ptBz0, ptBz1, ptBzV ;
|
||||
int nFlag ;
|
||||
CurveLine clV ;
|
||||
// determino quanti Step fare per ogni direzione parametrica
|
||||
double dDimU = ( dLen0 >= dLen2 ? dLen0 / m_vDim[0] : dLen2 / m_vDim[2]) ;
|
||||
double dDimV = ( dLen1 >= dLen3 ? dLen1 / m_vDim[1] : dLen3 / m_vDim[3]) ;
|
||||
// numero di Step per campionare la superficie nelle due direzioni parametriche
|
||||
int nStepsU = int( 51 * dDimU + 5 * ( 1 - dDimU)) ;
|
||||
int nStepsV = int( 51 * dDimV + 5 * ( 1 - dDimV)) ;
|
||||
for ( int u = 0 ; u < nStepsU ; ++ u) {
|
||||
dU = double ( u) / double ( nStepsU - 1) ;
|
||||
dULoc = ( 1 - dU) * m_mTree[nCToSplit].GetBottomLeft().x + dU * m_mTree[nCToSplit].GetTopRight().x ;
|
||||
if ( ! m_pSrfBz->GetPointD1D2( dULoc, m_mTree[nCToSplit].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz0) ||
|
||||
! m_pSrfBz->GetPointD1D2( dULoc, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz1))
|
||||
return false ;
|
||||
DistPointCurve dpc0010( ptBz0, cl0010) ;
|
||||
DistPointCurve dpc0111( ptBz1, cl0111) ;
|
||||
dpc0010.GetMinDistPoint( 0, pt0010, nFlag) ;
|
||||
dpc0111.GetMinDistPoint( 0, pt0111, nFlag) ;
|
||||
clV.Set( pt0010, pt0111) ;
|
||||
for ( int v = 0 ; v < nStepsV ; ++ v) {
|
||||
dV = double ( v) / double ( nStepsV - 1) ;
|
||||
dVLoc = ( 1 - dV) * m_mTree[nCToSplit].GetBottomLeft().y + dV * m_mTree[nCToSplit].GetTopRight().y ;
|
||||
if ( ! m_pSrfBz->GetPointD1D2( dULoc, dVLoc, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBzV))
|
||||
return false ;
|
||||
DistPointCurve dpc( ptBzV, clV) ;
|
||||
// distanza di approssimazione locale
|
||||
double dDist ;
|
||||
dpc.GetDist( dDist) ;
|
||||
if ( dDist > dErr)
|
||||
dErr = dDist ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int c = 1 ;
|
||||
while ( nCToSplit != -2 && m_mTree[nCToSplit].IsProcessed() == false) {
|
||||
dErr = 0 ;
|
||||
// calcolo l'errore di approssimazione
|
||||
if ( dErr > dLinTol || dSideMaxVal > dSideMax) {
|
||||
m_mTree[nCToSplit].SetSplitDirVert( bVert) ;
|
||||
// effettuo lo split
|
||||
Split( nCToSplit) ;
|
||||
|
||||
//// calcolo l'errore di approssimazione confrontando con la bilineare corrispondente
|
||||
//SurfBezier pSrfBl ;
|
||||
//pSrfBl.Init(1, 1, 1, 1, false) ;
|
||||
//m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x, m_mTree[nCToSplit].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz) ;
|
||||
//pSrfBl.SetControlPoint( 0, ptBz) ; // P00
|
||||
//m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x, m_mTree[nCToSplit].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz) ;
|
||||
//pSrfBl.SetControlPoint( 1, ptBz) ; // P10
|
||||
//m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz) ;
|
||||
//pSrfBl.SetControlPoint( 2, ptBz) ; // P01
|
||||
//m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz) ;
|
||||
//pSrfBl.SetControlPoint( 3, ptBz) ; // P11
|
||||
//// scorro lungo le isoparametriche a questi valori di U e V per trovare dov'è il punto di maggior discostamento
|
||||
//dU = ( m_mTree[nCToSplit].GetTopRight().x + m_mTree[nCToSplit].GetBottomLeft().x) / 2 ;
|
||||
//dV = ( m_mTree[nCToSplit].GetTopRight().y + m_mTree[nCToSplit].GetBottomLeft().y) / 2 ;
|
||||
//dULoc = ( dU - m_mTree[nCToSplit].GetBottomLeft().x) / ( m_mTree[nCToSplit].GetTopRight().x - m_mTree[nCToSplit].GetBottomLeft().x) ;
|
||||
//dVLoc = ( dV - m_mTree[nCToSplit].GetBottomLeft().y) / ( m_mTree[nCToSplit].GetTopRight().y - m_mTree[nCToSplit].GetBottomLeft().y) ;
|
||||
//double dErrUmax = 0, dErrVmax = 0 ;
|
||||
//for ( int i = 0 ; i < nSteps ; ++ i){
|
||||
// dIter = double ( i) / double ( nSteps - 1) ;
|
||||
// dIterLoc = ( 1 - dIter) * m_mTree[nCToSplit].GetBottomLeft().y + dIter * m_mTree[nCToSplit].GetTopRight().y ;
|
||||
// if ( ! m_pSrfBz->GetPointD1D2( dU, dIterLoc, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz) ||
|
||||
// ! pSrfBl.GetPointD1D2( dULoc, dIter, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBl))
|
||||
// return false ;
|
||||
// dDist = Dist( ptBz, ptBl) ;
|
||||
// dErrVmax = max ( dErrVmax, dDist) ;
|
||||
// if ( dDist > dErr) {
|
||||
// dErr = dDist ;
|
||||
// //bVert = true ;
|
||||
// }
|
||||
// dIterLoc = ( 1 - dIter) * m_mTree[nCToSplit].GetBottomLeft().x + dIter * m_mTree[nCToSplit].GetTopRight().x ;
|
||||
// if ( ! m_pSrfBz->GetPointD1D2( dIterLoc, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz) ||
|
||||
// ! pSrfBl.GetPointD1D2( dIter, dVLoc, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBl))
|
||||
// return false ;
|
||||
// dDist = Dist( ptBz, ptBl) ;
|
||||
// dErrUmax = max ( dErrUmax, dDist) ;
|
||||
// if ( dDist > dErr) {
|
||||
// dErr = dDist ;
|
||||
// //bVert = false ;
|
||||
// }
|
||||
//}
|
||||
|
||||
Point3d ptP00, ptP10, ptP11, ptP01 ;
|
||||
m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x, m_mTree[nCToSplit].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00) ;
|
||||
m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x, m_mTree[nCToSplit].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10) ;
|
||||
m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01) ;
|
||||
m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11) ;
|
||||
CurveLine cl0010, cl0001, cl1011, cl0111 ;
|
||||
// U=0
|
||||
cl0010.Set( ptP00, ptP10) ;
|
||||
//// V=0
|
||||
//cl0001.Set( ptP00, ptP01) ;
|
||||
// U=1
|
||||
cl0111.Set( ptP01, ptP11) ;
|
||||
//// V=1
|
||||
//cl0111.Set( ptP01, ptP11) ;
|
||||
Point3d pt0010, pt0111, ptBz0, ptBz1, ptBzV ;
|
||||
int nFlag ;
|
||||
CurveLine clV ;
|
||||
for ( int u = 0 ; u < nSteps ; ++ u){
|
||||
dU = double ( u) / double ( nSteps - 1) ;
|
||||
dULoc = ( 1 - dU) * m_mTree[nCToSplit].GetBottomLeft().x + dU * m_mTree[nCToSplit].GetTopRight().x ;
|
||||
if ( ! m_pSrfBz->GetPointD1D2( dULoc, m_mTree[nCToSplit].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz0) ||
|
||||
! m_pSrfBz->GetPointD1D2( dULoc, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz1))
|
||||
return false ;
|
||||
DistPointCurve dpc0010( ptBz0, cl0010) ;
|
||||
DistPointCurve dpc0111( ptBz1, cl0111) ;
|
||||
dpc0010.GetMinDistPoint( 0, pt0010, nFlag) ;
|
||||
dpc0111.GetMinDistPoint( 0, pt0111, nFlag) ;
|
||||
clV.Set( pt0010, pt0111) ;
|
||||
for ( int v = 0 ; v < nSteps ; ++ v){
|
||||
dV = double ( v) / double ( nSteps - 1) ;
|
||||
dVLoc = ( 1 - dV) * m_mTree[nCToSplit].GetBottomLeft().y + dV * m_mTree[nCToSplit].GetTopRight().y ;
|
||||
if ( ! m_pSrfBz->GetPointD1D2( dULoc, dVLoc, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBzV))
|
||||
return false ;
|
||||
DistPointCurve dpc( ptBzV, clV) ;
|
||||
dpc.GetDist( dDist) ;
|
||||
if ( dDist > dErr)
|
||||
dErr = dDist ;
|
||||
}
|
||||
}
|
||||
|
||||
// calcolo in quale direzione ho più curvatura
|
||||
// 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 antiorario rispetto al relativo vertice della patch
|
||||
dU = ( m_mTree[nCToSplit].GetTopRight().x + m_mTree[nCToSplit].GetBottomLeft().x) / 2 ;
|
||||
dV = ( m_mTree[nCToSplit].GetTopRight().y + m_mTree[nCToSplit].GetBottomLeft().y) / 2 ;
|
||||
dULoc = dVLoc = 0.5 ;
|
||||
Point3d ptPSrf ; //ptP00, ptP10, ptP11, ptP01;
|
||||
m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ;
|
||||
m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00) ;
|
||||
m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10) ;
|
||||
m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11) ;
|
||||
m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01) ;
|
||||
Point3d ptP00P11 = ( 1 - dULoc) * ptP00 + dULoc * ptP11 ;
|
||||
Point3d ptP10P01 = ( 1 - dVLoc) * ptP10 + dVLoc * 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))
|
||||
// lungo la direzione U ho una curvatura maggiore
|
||||
bVert = false ;
|
||||
else
|
||||
// lungo la direzione V ho una curvatura maggiore
|
||||
bVert = true ;
|
||||
|
||||
// verifico che la cella sia da splittare e che eventualmente sia abbastanza grande da poterlo fare
|
||||
if ( bVert)
|
||||
dSideMinVal = min( Dist( ptP00, ptP10), Dist( ptP01, ptP11)) ;
|
||||
else
|
||||
dSideMinVal = min( Dist( ptP00, ptP01), Dist( ptP10, ptP11)) ;
|
||||
dSideMaxVal = max( Dist( ptP00, ptP11), Dist( ptP10, ptP01)) ;
|
||||
if ( ( dErr > m_dLinTol && dSideMinVal >= dSideMin) || dSideMaxVal > dSideMax) {
|
||||
m_mTree[nCToSplit].SetSplitDirVert( bVert) ;
|
||||
// effettuo lo split
|
||||
Split( nCToSplit) ;
|
||||
|
||||
// procedo con lo split del Child1
|
||||
nCToSplit = m_mTree[nCToSplit].m_nChild1 ;
|
||||
}
|
||||
else {
|
||||
// sono arrivato ad una cella Leaf, quindi salvo la cella
|
||||
m_vnLeaves.push_back( nCToSplit) ;
|
||||
m_mTree[nCToSplit].Processed() ;
|
||||
// risalgo i parent finché non trovo il primo Child2 da processare
|
||||
nCToSplit = m_mTree[nCToSplit].m_nParent ;
|
||||
if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
|
||||
m_mTree[nCToSplit].Processed() ;
|
||||
while ( m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) {
|
||||
if ( m_mTree[nCToSplit].m_nParent != -2 )
|
||||
nCToSplit = m_mTree[nCToSplit].m_nParent ;
|
||||
if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
|
||||
// procedo con lo split del Child1
|
||||
nCToSplit = m_mTree[nCToSplit].m_nChild1 ;
|
||||
}
|
||||
else {
|
||||
// sono arrivato ad una cella Leaf, quindi salvo la cella
|
||||
m_vnLeaves.push_back( nCToSplit) ;
|
||||
m_mTree[nCToSplit].Processed() ;
|
||||
if ( nCToSplit == m_nRoot && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed() )
|
||||
break ;
|
||||
// risalgo i parent finché non trovo il primo Child2 da processare
|
||||
nCToSplit = m_mTree[nCToSplit].m_nParent ;
|
||||
if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
|
||||
m_mTree[nCToSplit].Processed() ;
|
||||
while ( m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) {
|
||||
if ( m_mTree[nCToSplit].m_nParent != -2)
|
||||
nCToSplit = m_mTree[nCToSplit].m_nParent ;
|
||||
if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
|
||||
m_mTree[nCToSplit].Processed() ;
|
||||
if ( nCToSplit == -1 && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
|
||||
break ;
|
||||
}
|
||||
nCToSplit = m_mTree[nCToSplit].m_nChild2 ;
|
||||
}
|
||||
}
|
||||
Balance( vBalanceCheck) ; // da implementare quando dividerò ad un parametro a scelta e non a metà
|
||||
}
|
||||
// bilineare
|
||||
else {
|
||||
while ( nCToSplit != -2 && m_mTree[nCToSplit].IsProcessed() == false) {
|
||||
// vertici della cella
|
||||
Point3d ptP00, ptP10, ptP11, ptP01 ;
|
||||
ptP00 = m_mVert[nCToSplit][0] ;
|
||||
ptP10 = m_mVert[nCToSplit][1] ;
|
||||
ptP11 = m_mVert[nCToSplit][2] ;
|
||||
ptP01 = m_mVert[nCToSplit][3] ;
|
||||
|
||||
// distanza reale tra i vertici della cella
|
||||
double dLen0 = Dist( ptP00, ptP10) ;
|
||||
double dLen1 = Dist( ptP10, ptP11) ;
|
||||
double dLen2 = Dist( ptP01, ptP11) ;
|
||||
double dLen3 = Dist( ptP00, ptP01) ;
|
||||
|
||||
// calcolo se è migliore la divisione in orizzontale o in verticale
|
||||
Point3d ptP00P10, ptP00P01 , ptP01P11, ptP10P11 ;
|
||||
ptP00P10 = ( ptP00 + ptP10) / 2 ;
|
||||
ptP10P11 = ( ptP10 + ptP11) / 2 ;
|
||||
ptP01P11 = ( ptP01 + ptP11) / 2 ;
|
||||
ptP00P01 = ( ptP00 + ptP01) / 2 ;
|
||||
bool bVert = false ;
|
||||
|
||||
|
||||
//// questo calcolo è inutile perché confronto due cose che sono sempre uguali///////////////////////////////////////////////////////
|
||||
// calcolo se è meglio spezzare in orizzontale o in verticale
|
||||
//double dErrVert1 = ( ( ptP00 - ptP01) + ( ptP01P11 - ptP00P10)).Len() ;
|
||||
//double dErrVert2 = ( ( ptP00P10 - ptP01P11) + ( ptP11 - ptP10)).Len() ;
|
||||
//double dErrOriz1 = ( ( ptP00P01 - ptP01) + ( ptP11 - ptP10P11)).Len() ;
|
||||
//double dErrOriz2 = ( ( ptP00 - ptP00P01) + ( ptP10P11 - ptP10)).Len() ;
|
||||
////if (0 ) {
|
||||
//if ( abs( dErrVert1 + dErrVert2 - dErrOriz1 - dErrOriz2) < EPS_SMALL && nCToSplit != -1) {
|
||||
// bVert = ! m_mTree[m_mTree[nCToSplit].m_nParent].IsSplitVert() ;
|
||||
//}
|
||||
//else {
|
||||
// if ( dErrVert1 + dErrVert2 > dErrOriz1 + dErrOriz2) {
|
||||
// bVert = false ;
|
||||
// }
|
||||
// else {
|
||||
// bVert = true ;
|
||||
// }
|
||||
//}
|
||||
|
||||
// con questo esce la C sulla bilineare
|
||||
// calcolo in quale direzione è meglio dividere in base allo stretch
|
||||
Point3d ptPSrfU, ptPSrfV ;
|
||||
double dU = 0, dV = 0 ;
|
||||
double dDistU = 0, dDistV = 0 ;
|
||||
double dULoc, dVLoc ;
|
||||
PNTVECTOR vPtU, vPtV ;
|
||||
if ( ! m_bMulti) {
|
||||
if ( max(dLen0, dLen2) > max(dLen1, dLen3)) {
|
||||
bVert = true ;
|
||||
}
|
||||
else {
|
||||
bVert = false ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for ( double i = 0.25 ; i < 1 ; i = i + 0.25 ) {
|
||||
/*Point3d ptU = ( 1 - i) * ptP00P01 + i * ptP10P11 ;
|
||||
Point3d ptV = ( 1 - i) * ptP00P10 + i * ptP01P11 ;*/
|
||||
dU = ( 1 - i) * m_mTree[nCToSplit].GetBottomLeft().x + i * m_mTree[nCToSplit].GetTopRight().x ;
|
||||
dV = ( 1 - i) * m_mTree[nCToSplit].GetBottomLeft().y + i * m_mTree[nCToSplit].GetTopRight().y ;
|
||||
dVLoc = ( m_mTree[nCToSplit].GetBottomLeft().y + m_mTree[nCToSplit].GetTopRight().y) / 2 ;
|
||||
dULoc = ( m_mTree[nCToSplit].GetBottomLeft().x + m_mTree[nCToSplit].GetTopRight().x) / 2 ;
|
||||
m_pSrfBz->GetPointD1D2( dU, dVLoc, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrfU) ;
|
||||
m_pSrfBz->GetPointD1D2( dULoc, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrfV) ;
|
||||
//dDistU = max( Dist( ptU , ptPSrfU), dDistU) ;
|
||||
//dDistV = max( Dist( ptV , ptPSrfV), dDistV) ;
|
||||
vPtU.push_back(ptPSrfU) ;
|
||||
vPtV.push_back(ptPSrfV) ;
|
||||
}
|
||||
// devo guardare se i tre punti in vPtU e vPtV sono allineati
|
||||
CurveLine clU, clV;
|
||||
clU.Set(vPtU[0], vPtU[1]) ;
|
||||
clV.Set(vPtV[0], vPtV[1]) ;
|
||||
DistPointCurve dpcU( vPtU[2], clU, false) ;
|
||||
DistPointCurve dpcV( vPtV[2], clV, false) ;
|
||||
dpcU.GetDist( dDistU) ;
|
||||
dpcV.GetDist( dDistV) ;
|
||||
if ( dDistU > dDistV ) {
|
||||
bVert = true ;
|
||||
}
|
||||
else {
|
||||
bVert = false ;
|
||||
}
|
||||
}
|
||||
|
||||
// diagonali
|
||||
//Point3d ptP00P11, ptP10P01, ptPSrf ;
|
||||
//ptP00P11 = ( ptP00 + ptP11) / 2 ;
|
||||
//ptP10P01 = ( ptP10 + ptP01) / 2 ;
|
||||
//double dU = ( m_mTree[nCToSplit].GetBottomLeft().x + m_mTree[nCToSplit].GetTopRight().x) / 2 ;
|
||||
//double dV = ( m_mTree[nCToSplit].GetBottomLeft().y + m_mTree[nCToSplit].GetTopRight().y) / 2 ;
|
||||
//m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ;
|
||||
//if ( Dist( ptP00P11, ptPSrf) > Dist( ptP10P01, ptPSrf))
|
||||
// bVert = false ;
|
||||
//else
|
||||
// bVert = true ;
|
||||
|
||||
|
||||
|
||||
|
||||
// verifico che la cella sia abbastanza grande da poter essere splittata
|
||||
double dSideMinVal = 0, dSideMaxVal = 0 ;
|
||||
if ( bVert) {
|
||||
if ( dLen0 != 0 && dLen2 != 0)
|
||||
dSideMinVal = min( dLen0, dLen2) ;
|
||||
else
|
||||
dSideMinVal = max( dLen0, dLen2) ;
|
||||
}
|
||||
else {
|
||||
if ( dLen1 != 0 && dLen3 != 0)
|
||||
dSideMinVal = min( dLen1, dLen3) ;
|
||||
else
|
||||
dSideMinVal = max( dLen1, dLen3) ;
|
||||
}
|
||||
// calcolo le diagonali per controllare la dimensione massima dei triangoli in cui dividerei la cella
|
||||
dSideMaxVal = max( Dist( ptP00, ptP11), Dist( ptP10, ptP01)) ;
|
||||
|
||||
|
||||
double dErr = 0 ;
|
||||
if ( m_bMulti ) {
|
||||
Point3d ptPSrf ;
|
||||
Plane3d plAppr ;
|
||||
plAppr.Set( ptP00, ( ptP00 - ptP01) ^ ( ptP00 - ptP10)) ;
|
||||
for ( double i = 0.25 ; i < 1 ; i = i + 0.25) {
|
||||
for ( double j = 0.25 ; j < 1 ; j = j + 0.25) {
|
||||
double dU = ( 1 - i) * m_mTree[nCToSplit].GetTopRight().x + i * m_mTree[nCToSplit].GetBottomLeft().x ;
|
||||
double dV = ( 1 - j) * m_mTree[nCToSplit].GetTopRight().y + j * m_mTree[nCToSplit].GetBottomLeft().y ;
|
||||
m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ;
|
||||
dErr = max( abs( DistPointPlane( ptPSrf, plAppr)), dErr) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
dErr = 1. / 4. * ( (ptP00 - ptP01) + (ptP11 - ptP10)).Len() ;
|
||||
}
|
||||
// se la cella è abbastanza grande da poter essere divisa ancora e devo approssimare meglio, la divido
|
||||
if ( dSideMinVal / 2 >= dSideMin && dSideMaxVal < dSideMax && dErr > dLinTol) {
|
||||
m_mTree[nCToSplit].SetSplitDirVert( bVert) ;
|
||||
// effettuo lo split
|
||||
Split( nCToSplit) ;
|
||||
|
||||
// procedo con lo split del Child1
|
||||
nCToSplit = m_mTree[nCToSplit].m_nChild1 ;
|
||||
}
|
||||
else {
|
||||
// sono arrivato ad una cella Leaf, quindi salvo la cella
|
||||
m_vnLeaves.push_back( nCToSplit) ;
|
||||
m_mTree[nCToSplit].Processed() ;
|
||||
// risalgo i parent finché non trovo il primo Child2 da processare
|
||||
nCToSplit = m_mTree[nCToSplit].m_nParent ;
|
||||
if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
|
||||
m_mTree[nCToSplit].Processed() ;
|
||||
while ( m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) {
|
||||
if ( m_mTree[nCToSplit].m_nParent != -2)
|
||||
nCToSplit = m_mTree[nCToSplit].m_nParent ;
|
||||
if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
|
||||
m_mTree[nCToSplit].Processed() ;
|
||||
if ( nCToSplit == -1 && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
|
||||
break ;
|
||||
}
|
||||
nCToSplit = m_mTree[nCToSplit].m_nChild2 ;
|
||||
}
|
||||
}
|
||||
nCToSplit = m_mTree[nCToSplit].m_nChild2 ;
|
||||
}
|
||||
c ++ ;
|
||||
}
|
||||
Balance( vBalanceCheck) ;
|
||||
// se la superficie è trimmata
|
||||
else {
|
||||
SurfFlatRegion sfrTrimReg ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Tree::Balance( INTVECTOR vCheck)
|
||||
{
|
||||
for ( int i : vCheck ) {
|
||||
// non ancora implementato
|
||||
// rendolo il tree balanced : ogni foglia deve avere una profondità di +- 1 rispetto ai suoi vicini.
|
||||
}
|
||||
//for ( int i : vCheck ) {
|
||||
// // non ancora implementato
|
||||
// // rendo il tree balanced : ogni foglia deve avere una profondità di +- 1 rispetto alle foglie adiacenti.
|
||||
//}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -478,7 +650,7 @@ void Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs)
|
||||
}
|
||||
}
|
||||
vector<Cell> vCells ;
|
||||
for ( int k : vTopNeighs )
|
||||
for ( int k : vTopNeighs)
|
||||
vCells.push_back( m_mTree[k]) ;
|
||||
sort( vCells.begin(), vCells.end(), Cell::minorX ) ;
|
||||
vTopNeighs.clear() ;
|
||||
@@ -516,7 +688,7 @@ void Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs)
|
||||
}
|
||||
}
|
||||
bool bAllLeaves = true ;
|
||||
for ( int i : vBottomNeighs ) {
|
||||
for ( int i : vBottomNeighs) {
|
||||
if ( ! m_mTree[i].IsLeaf())
|
||||
bAllLeaves = false ;
|
||||
}
|
||||
@@ -542,8 +714,8 @@ void Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs)
|
||||
}
|
||||
// altrimenti solo uno dei figli lo sarà
|
||||
else {
|
||||
if ( m_mTree[m_mTree[i].m_nChild1].GetTopRight().x <= m_mTree[nId].GetBottomLeft().x ||
|
||||
m_mTree[m_mTree[i].m_nChild1].GetBottomLeft().x >= m_mTree[nId].GetTopRight().x )
|
||||
if ( m_mTree[m_mTree[i].m_nChild1].GetTopRight().x <= m_mTree[nId].GetBottomLeft().x ||
|
||||
m_mTree[m_mTree[i].m_nChild1].GetBottomLeft().x >= m_mTree[nId].GetTopRight().x)
|
||||
vBottomNeighs.push_back( m_mTree[i].m_nChild2) ;
|
||||
else
|
||||
vBottomNeighs.push_back( m_mTree[i].m_nChild1) ;
|
||||
@@ -556,7 +728,7 @@ void Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs)
|
||||
}
|
||||
}
|
||||
vector<Cell> vCells ;
|
||||
for ( int k : vBottomNeighs )
|
||||
for ( int k : vBottomNeighs)
|
||||
vCells.push_back( m_mTree[k]) ;
|
||||
sort( vCells.begin(), vCells.end(), Cell::minorX) ;
|
||||
vBottomNeighs.clear() ;
|
||||
@@ -568,7 +740,7 @@ void Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs)
|
||||
//----------------------------------------------------------------------------
|
||||
void Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs)
|
||||
{
|
||||
if ( (int) vLeftNeighs.size() == 0 ) {
|
||||
if ( (int) vLeftNeighs.size() == 0) {
|
||||
if ( m_mTree[nId].m_nLeft == -2)
|
||||
return ;
|
||||
if ( m_mTree[m_mTree[nId].m_nLeft].IsLeaf())
|
||||
@@ -577,14 +749,14 @@ void Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs)
|
||||
if ( ! m_mTree[m_mTree[nId].m_nLeft].IsSplitVert()) {
|
||||
// se la cella vicina è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima
|
||||
if ( m_mTree[m_mTree[nId].m_nLeft].GetTopRight().y - m_mTree[m_mTree[nId].m_nLeft].GetBottomLeft().y <=
|
||||
m_mTree[nId].GetTopRight().y - m_mTree[nId].GetBottomLeft().y) {
|
||||
m_mTree[nId].GetTopRight().y - m_mTree[nId].GetBottomLeft().y) {
|
||||
vLeftNeighs.push_back( m_mTree[m_mTree[nId].m_nLeft].m_nChild1) ;
|
||||
vLeftNeighs.push_back( m_mTree[m_mTree[nId].m_nLeft].m_nChild2) ;
|
||||
}
|
||||
// altrimenti solo uno dei figli lo sarà
|
||||
else{
|
||||
if ( m_mTree[m_mTree[m_mTree[nId].m_nLeft].m_nChild1].GetTopRight().y <= m_mTree[nId].GetBottomLeft().y ||
|
||||
m_mTree[m_mTree[m_mTree[nId].m_nLeft].m_nChild1].GetBottomLeft().y >= m_mTree[nId].GetTopRight().y )
|
||||
if ( m_mTree[m_mTree[m_mTree[nId].m_nLeft].m_nChild1].GetTopRight().y <= m_mTree[nId].GetBottomLeft().y ||
|
||||
m_mTree[m_mTree[m_mTree[nId].m_nLeft].m_nChild1].GetBottomLeft().y >= m_mTree[nId].GetTopRight().y)
|
||||
vLeftNeighs.push_back( m_mTree[m_mTree[nId].m_nLeft].m_nChild2) ;
|
||||
else
|
||||
vLeftNeighs.push_back( m_mTree[m_mTree[nId].m_nLeft].m_nChild1) ;
|
||||
@@ -595,7 +767,7 @@ void Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs)
|
||||
}
|
||||
}
|
||||
bool bAllLeaves = true ;
|
||||
for ( int i : vLeftNeighs ) {
|
||||
for ( int i : vLeftNeighs) {
|
||||
if ( ! m_mTree[i].IsLeaf())
|
||||
bAllLeaves = false ;
|
||||
}
|
||||
@@ -615,14 +787,14 @@ void Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs)
|
||||
if ( ! m_mTree[i].IsSplitVert()) {
|
||||
// se la cella è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima
|
||||
if ( m_mTree[i].GetTopRight().y - m_mTree[i].GetBottomLeft().y <=
|
||||
m_mTree[nId].GetTopRight().y - m_mTree[nId].GetBottomLeft().y) {
|
||||
m_mTree[nId].GetTopRight().y - m_mTree[nId].GetBottomLeft().y) {
|
||||
vLeftNeighs.push_back( m_mTree[i].m_nChild1) ;
|
||||
vLeftNeighs.push_back( m_mTree[i].m_nChild2) ;
|
||||
}
|
||||
// altrimenti solo uno dei figli lo sarà
|
||||
else {
|
||||
if ( m_mTree[m_mTree[i].m_nChild1].GetTopRight().y <= m_mTree[nId].GetBottomLeft().y ||
|
||||
m_mTree[m_mTree[i].m_nChild1].GetBottomLeft().y >= m_mTree[nId].GetTopRight().y )
|
||||
if ( m_mTree[m_mTree[i].m_nChild1].GetTopRight().y <= m_mTree[nId].GetBottomLeft().y ||
|
||||
m_mTree[m_mTree[i].m_nChild1].GetBottomLeft().y >= m_mTree[nId].GetTopRight().y)
|
||||
vLeftNeighs.push_back( m_mTree[i].m_nChild2) ;
|
||||
else
|
||||
vLeftNeighs.push_back( m_mTree[i].m_nChild1) ;
|
||||
@@ -661,8 +833,8 @@ void Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs)
|
||||
}
|
||||
// altrimenti solo uno dei figli lo sarà
|
||||
else{
|
||||
if ( m_mTree[m_mTree[m_mTree[nId].m_nRight].m_nChild1].GetTopRight().y <= m_mTree[nId].GetBottomLeft().y ||
|
||||
m_mTree[m_mTree[m_mTree[nId].m_nRight].m_nChild1].GetBottomLeft().y >= m_mTree[nId].GetTopRight().y )
|
||||
if ( m_mTree[m_mTree[m_mTree[nId].m_nRight].m_nChild1].GetTopRight().y <= m_mTree[nId].GetBottomLeft().y ||
|
||||
m_mTree[m_mTree[m_mTree[nId].m_nRight].m_nChild1].GetBottomLeft().y >= m_mTree[nId].GetTopRight().y)
|
||||
vRightNeighs.push_back( m_mTree[m_mTree[nId].m_nRight].m_nChild2) ;
|
||||
else
|
||||
vRightNeighs.push_back( m_mTree[m_mTree[nId].m_nRight].m_nChild1) ;
|
||||
@@ -693,14 +865,14 @@ void Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs)
|
||||
if ( ! m_mTree[i].IsSplitVert()) {
|
||||
// se la cella è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima
|
||||
if ( m_mTree[i].GetTopRight().y - m_mTree[i].GetBottomLeft().y <=
|
||||
m_mTree[nId].GetTopRight().y - m_mTree[nId].GetBottomLeft().y) {
|
||||
m_mTree[nId].GetTopRight().y - m_mTree[nId].GetBottomLeft().y) {
|
||||
vRightNeighs.push_back( m_mTree[i].m_nChild1) ;
|
||||
vRightNeighs.push_back( m_mTree[i].m_nChild2) ;
|
||||
}
|
||||
// altrimenti solo uno dei figli lo sarà
|
||||
else {
|
||||
if ( m_mTree[m_mTree[i].m_nChild1].GetTopRight().y <= m_mTree[nId].GetBottomLeft().y ||
|
||||
m_mTree[m_mTree[i].m_nChild1].GetBottomLeft().y >= m_mTree[nId].GetTopRight().y )
|
||||
if ( m_mTree[m_mTree[i].m_nChild1].GetTopRight().y <= m_mTree[nId].GetBottomLeft().y ||
|
||||
m_mTree[m_mTree[i].m_nChild1].GetBottomLeft().y >= m_mTree[nId].GetTopRight().y)
|
||||
vRightNeighs.push_back( m_mTree[i].m_nChild2) ;
|
||||
else
|
||||
vRightNeighs.push_back( m_mTree[i].m_nChild1) ;
|
||||
@@ -759,7 +931,7 @@ int Tree::GetHeightLeaves( int nId, INTVECTOR& vnLeaves, int d)
|
||||
int Tree::GetDepth( int nId, int nRef = -2)
|
||||
{
|
||||
int c = 0 ;
|
||||
while ( m_mTree[nId].m_nParent != nRef ) {
|
||||
while ( m_mTree[nId].m_nParent != nRef) {
|
||||
nId = m_mTree[nId].m_nParent ;
|
||||
++ c ;
|
||||
}
|
||||
@@ -826,7 +998,7 @@ bool Tree::GetPolygons( POLYLINEVECTOR& vPolygons)
|
||||
}
|
||||
vNeigh.clear() ;
|
||||
vVertices.push_back( m_mTree[nId].GetBottomLeft()) ;
|
||||
// se hop una cella con vicino dello stesso grado controllo la curvatura nella cella e
|
||||
// se ho una cella con vicino dello stesso grado ( quindi il poligono ha solo 5 punti) controllo la curvatura nella cella e
|
||||
// se necessario cambio l'ordine dei vertici per scegliere la diagonale di split migliore
|
||||
if ( vVertices.size() == 5) {
|
||||
Point3d ptPSrf, ptP00, ptP10, ptP11, ptP01;
|
||||
@@ -834,23 +1006,21 @@ bool Tree::GetPolygons( POLYLINEVECTOR& vPolygons)
|
||||
dU = ( m_mTree[nId].GetBottomLeft().x + m_mTree[nId].GetTopRight().x) / 2 ;
|
||||
dV = ( m_mTree[nId].GetBottomLeft().y + m_mTree[nId].GetTopRight().y) / 2 ;
|
||||
m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ;
|
||||
m_pSrfBz->GetPointD1D2( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00) ;
|
||||
m_pSrfBz->GetPointD1D2( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10) ;
|
||||
m_pSrfBz->GetPointD1D2( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11) ;
|
||||
m_pSrfBz->GetPointD1D2( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01) ;
|
||||
ptP00 = m_mVert[nId][0] ;
|
||||
ptP10 = m_mVert[nId][1] ;
|
||||
ptP11 = m_mVert[nId][2] ;
|
||||
ptP01 = m_mVert[nId][3] ;
|
||||
Point3d ptP00P11 = ( ptP00 + ptP11) / 2 ;
|
||||
Point3d ptP10P01 = ( ptP10 + ptP01) / 2 ;
|
||||
// ho la curvatura maggiore sulla diagonale tra P10 e P01, ruoto l'ordine dei vertici, in modo che triangulate prenda la diagonale giusta
|
||||
if ( Dist(ptP00P11, ptPSrf) > Dist(ptP10P01, ptPSrf)) {
|
||||
if ( Dist(ptP00P11, ptPSrf) + EPS_SMALL > Dist(ptP10P01, ptPSrf)) {
|
||||
rotate(vVertices.begin(), vVertices.begin() + 1,vVertices.end()) ;
|
||||
vVertices.back() = vVertices[0] ;
|
||||
}
|
||||
}
|
||||
|
||||
//double k = 0 ;
|
||||
m_vPolygons.emplace_back() ;
|
||||
for ( int i = 0 ; i < (int) vVertices.size() ; ++i ) {
|
||||
//k = double( i) / double( vVertices.size()) ;
|
||||
for ( int i = 0 ; i < (int) vVertices.size() ; ++i) {
|
||||
m_vPolygons.back().AddUPoint( i, vVertices[i]) ;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user