8c79bbb2b6
- completata l'implementazione della tassellazione adattiva per una superficie di bezier ( si può migliorare il costo di memoria e computazionale) - manca la gestione del trim dello spazio parametrico.
862 lines
39 KiB
C++
862 lines
39 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2023
|
|
//----------------------------------------------------------------------------
|
|
// File : Tree.cpp Data : 21.04.23 Versione :
|
|
// Contenuto : Implementazione della classe Tree.
|
|
//
|
|
//
|
|
//
|
|
// Modifiche : 21.04.23 DB Creazione modulo.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include <algorithm>
|
|
#include "Tree.h"
|
|
#include "SurfBezier.h"
|
|
#include "GeoConst.h"
|
|
#include "CurveLine.h"
|
|
#include "/EgtDev/Include/EGkPolyLine.h"
|
|
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
|
|
|
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)
|
|
{
|
|
Point3d ptTr ( 1, 1) ;
|
|
m_ptPtr = ptTr ;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
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)
|
|
{}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
Cell::~Cell( void)
|
|
{
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
inline bool
|
|
Cell::IsSame( Cell cOtherCell)
|
|
{
|
|
if ( AreSamePointXYApprox( m_ptPbl, cOtherCell.GetBottomLeft()) &&
|
|
AreSamePointXYApprox( m_ptPtr, cOtherCell.GetTopRight())) {
|
|
return true ;
|
|
}
|
|
else {
|
|
return false ;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
//Cell::IsLeaf ( void) const
|
|
Cell::IsLeaf ( void)
|
|
{
|
|
if( m_nChild1 == -2 && m_nChild2 == -2)
|
|
return true ;
|
|
else
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
Tree::Tree( void)
|
|
: m_dLinTol(LIN_TOL_FINE), m_pSrfBz(nullptr), m_nRoot( -1), m_bTrimmed( false)
|
|
{
|
|
Point3d ptBl( 0, 0), ptTr ( 1, 1) ;
|
|
Cell cRoot( ptBl, ptTr) ;
|
|
m_mTree.insert( pair< int, Cell>( m_nRoot, cRoot)) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
Tree::Tree( const SurfBezier* pSrfBz)
|
|
: m_dLinTol( LIN_TOL_FINE), m_pSrfBz ( pSrfBz), m_nRoot( -1)
|
|
{
|
|
// 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)) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
Tree::~Tree( void)
|
|
{
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void Tree::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) ;
|
|
m_bTrimmed = bTrimmed ;
|
|
Point3d ptTop( nSpanU, nSpanV) ;
|
|
Cell cRoot( ORIG, ptTop) ;
|
|
m_mTree.insert( pair< int, Cell>( -1, cRoot)) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
Tree::Split( int nId)
|
|
{
|
|
Cell cChild1, cChild2 ;
|
|
cChild1.m_nDepth = m_mTree[nId].m_nDepth + 1 ;
|
|
cChild2.m_nDepth = m_mTree[nId].m_nDepth + 1 ;
|
|
int nNodes = (int) m_mTree.size() ;
|
|
cChild1.m_nId = nNodes - 1 ;
|
|
m_mTree[nId].m_nChild1 = nNodes - 1 ;
|
|
cChild2.m_nId = nNodes ;
|
|
m_mTree[nId].m_nChild2 = nNodes ;
|
|
m_mTree.insert( pair<int, Cell>( nNodes - 1, cChild1)) ;
|
|
m_mTree.insert( pair<int, Cell>( nNodes, cChild2)) ;
|
|
if ( ! m_mTree[nId].IsSplitVert())
|
|
{
|
|
// la cella figlio 1 è quella sopra
|
|
Point3d ptBL( m_mTree[nId].GetBottomLeft().x, ( m_mTree[nId].GetBottomLeft().y + m_mTree[nId].GetTopRight().y) / 2) ;
|
|
m_mTree[m_mTree[nId].m_nChild1].SetBottomLeft( ptBL) ;
|
|
m_mTree[m_mTree[nId].m_nChild1].SetTopRight( m_mTree[nId].GetTopRight()) ;
|
|
m_mTree[m_mTree[nId].m_nChild1].m_nTop = m_mTree[nId].m_nTop ;
|
|
m_mTree[m_mTree[nId].m_nChild1].m_nBottom = m_mTree[nId].m_nChild2 ;
|
|
m_mTree[m_mTree[nId].m_nChild1].m_nLeft = m_mTree[nId].m_nLeft ;
|
|
m_mTree[m_mTree[nId].m_nChild1].m_nRight = m_mTree[nId].m_nRight ;
|
|
Point3d ptTR( m_mTree[nId].GetTopRight().x, ( m_mTree[nId].GetTopRight().y + m_mTree[nId].GetBottomLeft().y) / 2) ;
|
|
m_mTree[m_mTree[nId].m_nChild2].SetBottomLeft( m_mTree[nId].GetBottomLeft()) ;
|
|
m_mTree[m_mTree[nId].m_nChild2].SetTopRight( ptTR) ;
|
|
m_mTree[m_mTree[nId].m_nChild2].m_nTop = m_mTree[nId].m_nChild1 ;
|
|
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 ;
|
|
}
|
|
else {
|
|
// la cella figlio 1 è quella di sinistra
|
|
Point3d ptTR( ( m_mTree[nId].GetBottomLeft().x + m_mTree[nId].GetTopRight().x) / 2, m_mTree[nId].GetTopRight().y) ;
|
|
m_mTree[m_mTree[nId].m_nChild1].SetBottomLeft( m_mTree[nId].GetBottomLeft()) ;
|
|
m_mTree[m_mTree[nId].m_nChild1].SetTopRight( ptTR) ;
|
|
m_mTree[m_mTree[nId].m_nChild1].m_nTop = m_mTree[nId].m_nTop ;
|
|
m_mTree[m_mTree[nId].m_nChild1].m_nBottom = m_mTree[nId].m_nBottom ;
|
|
m_mTree[m_mTree[nId].m_nChild1].m_nLeft = m_mTree[nId].m_nLeft ;
|
|
m_mTree[m_mTree[nId].m_nChild1].m_nRight = m_mTree[nId].m_nChild2 ;
|
|
Point3d ptBL(( m_mTree[nId].GetBottomLeft().x + m_mTree[nId].GetTopRight().x) / 2, m_mTree[nId].GetBottomLeft().y) ;
|
|
m_mTree[m_mTree[nId].m_nChild2].SetBottomLeft( ptBL) ;
|
|
m_mTree[m_mTree[nId].m_nChild2].SetTopRight( m_mTree[nId].GetTopRight()) ;
|
|
m_mTree[m_mTree[nId].m_nChild2].m_nTop = m_mTree[nId].m_nTop ;
|
|
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 ;
|
|
}
|
|
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 ;
|
|
//}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool Tree::BuildTree( double dLinTol, 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
|
|
INTVECTOR vBalanceCheck ;
|
|
int nCToSplit = -1 ;
|
|
|
|
int c = 1 ;
|
|
while ( nCToSplit != -2 && m_mTree[nCToSplit].IsProcessed() == false) {
|
|
dErr = 0 ;
|
|
// calcolo l'errore di approssimazione
|
|
|
|
//// 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())
|
|
m_mTree[nCToSplit].Processed() ;
|
|
if ( nCToSplit == m_nRoot && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed() )
|
|
break ;
|
|
}
|
|
nCToSplit = m_mTree[nCToSplit].m_nChild2 ;
|
|
}
|
|
c ++ ;
|
|
}
|
|
Balance( vBalanceCheck) ;
|
|
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.
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs)
|
|
{
|
|
if ( (int) vTopNeighs.size() == 0) {
|
|
if ( m_mTree[nId].m_nTop == -2)
|
|
return ;
|
|
if ( m_mTree[m_mTree[nId].m_nTop].IsLeaf())
|
|
vTopNeighs.push_back( m_mTree[nId].m_nTop) ;
|
|
else {
|
|
if ( m_mTree[m_mTree[nId].m_nTop].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_nTop].GetTopRight().x - m_mTree[m_mTree[nId].m_nTop].GetBottomLeft().x <=
|
|
m_mTree[nId].GetTopRight().x - m_mTree[nId].GetBottomLeft().x) {
|
|
vTopNeighs.push_back( m_mTree[m_mTree[nId].m_nTop].m_nChild1) ;
|
|
vTopNeighs.push_back( m_mTree[m_mTree[nId].m_nTop].m_nChild2) ;
|
|
}
|
|
// altrimenti solo uno dei figli lo sarà
|
|
else{
|
|
if ( m_mTree[m_mTree[m_mTree[nId].m_nTop].m_nChild1].GetTopRight().x <= m_mTree[nId].GetBottomLeft().x ||
|
|
m_mTree[m_mTree[m_mTree[nId].m_nTop].m_nChild1].GetBottomLeft().x >= m_mTree[nId].GetTopRight().x )
|
|
vTopNeighs.push_back( m_mTree[m_mTree[nId].m_nTop].m_nChild2) ;
|
|
else
|
|
vTopNeighs.push_back( m_mTree[m_mTree[nId].m_nTop].m_nChild1) ;
|
|
}
|
|
}
|
|
else {
|
|
vTopNeighs.push_back( m_mTree[m_mTree[nId].m_nTop].m_nChild2) ;
|
|
}
|
|
}
|
|
bool bAllLeaves = true ;
|
|
for ( int i : vTopNeighs ) {
|
|
if ( ! m_mTree[i].IsLeaf())
|
|
bAllLeaves = false ;
|
|
}
|
|
if ( ! bAllLeaves )
|
|
// almeno una cella tra i vicini trovati non è leaf quindi devo richiamare ricorsivamente questa funzione per trovare i suoi child
|
|
GetTopNeigh( nId, vTopNeighs) ;
|
|
}
|
|
else {
|
|
for ( int j = 0 ; j != (int) vTopNeighs.size() ; ++ j) {
|
|
int i = vTopNeighs[j] ;
|
|
if ( m_mTree[i].IsLeaf())
|
|
continue;
|
|
else {
|
|
// se la cella non è leaf la tolgo dal vettore delle foglie e aggiungo invece i suoi child
|
|
vTopNeighs.erase( remove( vTopNeighs.begin(),vTopNeighs.end(),i)) ;
|
|
-- j ;
|
|
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().x - m_mTree[i].GetBottomLeft().x <=
|
|
m_mTree[nId].GetTopRight().x - m_mTree[nId].GetBottomLeft().x) {
|
|
vTopNeighs.push_back( m_mTree[i].m_nChild1) ;
|
|
vTopNeighs.push_back( m_mTree[i].m_nChild2) ;
|
|
}
|
|
// 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 )
|
|
vTopNeighs.push_back( m_mTree[i].m_nChild2) ;
|
|
else
|
|
vTopNeighs.push_back( m_mTree[i].m_nChild1) ;
|
|
}
|
|
}
|
|
else {
|
|
vTopNeighs.push_back( m_mTree[i].m_nChild2) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
vector<Cell> vCells ;
|
|
for ( int k : vTopNeighs )
|
|
vCells.push_back( m_mTree[k]) ;
|
|
sort( vCells.begin(), vCells.end(), Cell::minorX ) ;
|
|
vTopNeighs.clear() ;
|
|
for ( Cell c : vCells)
|
|
vTopNeighs.push_back( c.m_nId) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs)
|
|
{
|
|
if ( (int) vBottomNeighs.size() == 0) {
|
|
if ( m_mTree[nId].m_nBottom == -2)
|
|
return ;
|
|
if ( m_mTree[m_mTree[nId].m_nBottom].IsLeaf())
|
|
vBottomNeighs.push_back( m_mTree[nId].m_nBottom) ;
|
|
else {
|
|
if ( m_mTree[m_mTree[nId].m_nBottom].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_nBottom].GetTopRight().x - m_mTree[m_mTree[nId].m_nBottom].GetBottomLeft().x <=
|
|
m_mTree[nId].GetTopRight().x - m_mTree[nId].GetBottomLeft().x) {
|
|
vBottomNeighs.push_back( m_mTree[m_mTree[nId].m_nBottom].m_nChild1) ;
|
|
vBottomNeighs.push_back( m_mTree[m_mTree[nId].m_nBottom].m_nChild2) ;
|
|
}
|
|
// altrimenti solo uno dei figli lo sarà
|
|
else{
|
|
if ( m_mTree[m_mTree[m_mTree[nId].m_nBottom].m_nChild1].GetTopRight().x <= m_mTree[nId].GetBottomLeft().x ||
|
|
m_mTree[m_mTree[m_mTree[nId].m_nBottom].m_nChild1].GetBottomLeft().x >= m_mTree[nId].GetTopRight().x )
|
|
vBottomNeighs.push_back( m_mTree[m_mTree[nId].m_nBottom].m_nChild2) ;
|
|
else
|
|
vBottomNeighs.push_back( m_mTree[m_mTree[nId].m_nBottom].m_nChild1) ;
|
|
}
|
|
}
|
|
else {
|
|
vBottomNeighs.push_back( m_mTree[m_mTree[nId].m_nBottom].m_nChild1) ;
|
|
}
|
|
}
|
|
bool bAllLeaves = true ;
|
|
for ( int i : vBottomNeighs ) {
|
|
if ( ! m_mTree[i].IsLeaf())
|
|
bAllLeaves = false ;
|
|
}
|
|
if ( ! bAllLeaves )
|
|
// almeno una cella tra i vicini trovati non è leaf quindi devo richiamare ricorsivamente questa funzione per trovare i suoi child
|
|
GetBottomNeigh( nId, vBottomNeighs) ;
|
|
}
|
|
else {
|
|
for ( int j = 0 ; j != (int) vBottomNeighs.size() ; ++ j) {
|
|
int i = vBottomNeighs[j] ;
|
|
if ( m_mTree[i].IsLeaf())
|
|
continue;
|
|
else {
|
|
// se la cella non è leaf la tolgo dal vettore delle foglie e aggiungo invece i suoi child
|
|
vBottomNeighs.erase( remove( vBottomNeighs.begin(),vBottomNeighs.end(),i)) ;
|
|
-- j ;
|
|
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().x - m_mTree[i].GetBottomLeft().x <=
|
|
m_mTree[nId].GetTopRight().x - m_mTree[nId].GetBottomLeft().x) {
|
|
vBottomNeighs.push_back( m_mTree[i].m_nChild1) ;
|
|
vBottomNeighs.push_back( m_mTree[i].m_nChild2) ;
|
|
}
|
|
// 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 )
|
|
vBottomNeighs.push_back( m_mTree[i].m_nChild2) ;
|
|
else
|
|
vBottomNeighs.push_back( m_mTree[i].m_nChild1) ;
|
|
}
|
|
}
|
|
else {
|
|
vBottomNeighs.push_back( m_mTree[i].m_nChild1) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
vector<Cell> vCells ;
|
|
for ( int k : vBottomNeighs )
|
|
vCells.push_back( m_mTree[k]) ;
|
|
sort( vCells.begin(), vCells.end(), Cell::minorX) ;
|
|
vBottomNeighs.clear() ;
|
|
for ( Cell c : vCells)
|
|
vBottomNeighs.push_back( c.m_nId) ;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
void Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs)
|
|
{
|
|
if ( (int) vLeftNeighs.size() == 0 ) {
|
|
if ( m_mTree[nId].m_nLeft == -2)
|
|
return ;
|
|
if ( m_mTree[m_mTree[nId].m_nLeft].IsLeaf())
|
|
vLeftNeighs.push_back( m_mTree[nId].m_nLeft) ;
|
|
else {
|
|
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) {
|
|
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 )
|
|
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) ;
|
|
}
|
|
}
|
|
else {
|
|
vLeftNeighs.push_back( m_mTree[m_mTree[nId].m_nLeft].m_nChild2) ;
|
|
}
|
|
}
|
|
bool bAllLeaves = true ;
|
|
for ( int i : vLeftNeighs ) {
|
|
if ( ! m_mTree[i].IsLeaf())
|
|
bAllLeaves = false ;
|
|
}
|
|
if ( ! bAllLeaves )
|
|
// almeno una cella tra i vicini trovati non è leaf quindi devo richiamare ricorsivamente questa funzione per trovare i suoi child
|
|
GetLeftNeigh( nId, vLeftNeighs) ;
|
|
}
|
|
else {
|
|
for ( int j = 0 ; j != (int) vLeftNeighs.size() ; ++ j) {
|
|
int i = vLeftNeighs[j] ;
|
|
if ( m_mTree[i].IsLeaf())
|
|
continue;
|
|
else {
|
|
// se la cella non è leaf la tolgo dal vettore delle foglie e aggiungo invece i suoi child
|
|
vLeftNeighs.erase( remove( vLeftNeighs.begin(),vLeftNeighs.end(),i)) ;
|
|
-- j ;
|
|
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) {
|
|
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 )
|
|
vLeftNeighs.push_back( m_mTree[i].m_nChild2) ;
|
|
else
|
|
vLeftNeighs.push_back( m_mTree[i].m_nChild1) ;
|
|
}
|
|
}
|
|
else {
|
|
vLeftNeighs.push_back( m_mTree[i].m_nChild2) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
vector<Cell> vCells ;
|
|
for ( int k : vLeftNeighs)
|
|
vCells.push_back( m_mTree[k]) ;
|
|
sort( vCells.begin(), vCells.end(), Cell::minorY) ;
|
|
vLeftNeighs.clear() ;
|
|
for ( Cell c : vCells)
|
|
vLeftNeighs.push_back( c.m_nId) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs)
|
|
{
|
|
if ( (int) vRightNeighs.size() == 0) {
|
|
if ( m_mTree[nId].m_nRight == -2)
|
|
return ;
|
|
if ( m_mTree[m_mTree[nId].m_nRight].IsLeaf())
|
|
vRightNeighs.push_back( m_mTree[nId].m_nRight) ;
|
|
else {
|
|
if ( ! m_mTree[m_mTree[nId].m_nRight].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_nRight].GetTopRight().y - m_mTree[m_mTree[nId].m_nRight].GetBottomLeft().y <=
|
|
m_mTree[nId].GetTopRight().y - m_mTree[nId].GetBottomLeft().y) {
|
|
vRightNeighs.push_back( m_mTree[m_mTree[nId].m_nRight].m_nChild1) ;
|
|
vRightNeighs.push_back( m_mTree[m_mTree[nId].m_nRight].m_nChild2) ;
|
|
}
|
|
// 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 )
|
|
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) ;
|
|
}
|
|
}
|
|
else {
|
|
vRightNeighs.push_back( m_mTree[m_mTree[nId].m_nRight].m_nChild1) ;
|
|
}
|
|
}
|
|
bool bAllLeaves = true ;
|
|
for ( int i : vRightNeighs) {
|
|
if ( ! m_mTree[i].IsLeaf())
|
|
bAllLeaves = false ;
|
|
}
|
|
if ( ! bAllLeaves )
|
|
// almeno una cella tra i vicini trovati non è leaf quindi devo richiamare ricorsivamente questa funzione per trovare i suoi child
|
|
GetRightNeigh( nId, vRightNeighs) ;
|
|
}
|
|
else {
|
|
for ( int j = 0 ; j != (int) vRightNeighs.size() ; ++ j) {
|
|
int i = vRightNeighs[j] ;
|
|
if ( m_mTree[i].IsLeaf())
|
|
continue;
|
|
else {
|
|
// se la cella non è leaf la tolgo dal vettore delle foglie e aggiungo invece i suoi child
|
|
vRightNeighs.erase( remove( vRightNeighs.begin(),vRightNeighs.end(), i)) ;
|
|
-- j ;
|
|
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) {
|
|
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 )
|
|
vRightNeighs.push_back( m_mTree[i].m_nChild2) ;
|
|
else
|
|
vRightNeighs.push_back( m_mTree[i].m_nChild1) ;
|
|
}
|
|
}
|
|
else {
|
|
vRightNeighs.push_back( m_mTree[i].m_nChild1) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
vector<Cell> vCells ;
|
|
for ( int k : vRightNeighs)
|
|
vCells.push_back( m_mTree[k]) ;
|
|
sort( vCells.begin(), vCells.end(), Cell::minorY) ;
|
|
vRightNeighs.clear() ;
|
|
for ( Cell c : vCells)
|
|
vRightNeighs.push_back( c.m_nId) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int Tree::GetHeightLeaves( int nId, INTVECTOR& vnLeaves, int d)
|
|
{
|
|
if ( (int) vnLeaves.size() == 0) {
|
|
if ( m_mTree[nId].IsLeaf())
|
|
return d ;
|
|
else {
|
|
vnLeaves.push_back( m_mTree[nId].m_nChild1) ;
|
|
vnLeaves.push_back( m_mTree[nId].m_nChild2) ;
|
|
if ( ! m_mTree[m_mTree[nId].m_nChild1].IsLeaf() || ! m_mTree[m_mTree[nId].m_nChild2].IsLeaf())
|
|
// almeno un child non è leaf quindi devo richiamare ricorsivamente questa funzione sui child in questione
|
|
d = GetHeightLeaves( nId, vnLeaves, m_mTree[m_mTree[nId].m_nChild1].m_nDepth) ;
|
|
}
|
|
}
|
|
else {
|
|
for ( int j = 0 ; j != (int) vnLeaves.size() ; ++ j) {
|
|
int i = vnLeaves[j] ;
|
|
if ( m_mTree[i].IsLeaf() ) {
|
|
continue ;
|
|
}
|
|
else {
|
|
// se la cella non è leaf la tolgo dal vettore delle foglie e aggiungo invece i suoi child
|
|
vnLeaves.erase( remove( vnLeaves.begin(),vnLeaves.end(),i)) ;
|
|
-- j ;
|
|
vnLeaves.push_back( m_mTree[i].m_nChild1) ;
|
|
vnLeaves.push_back( m_mTree[i].m_nChild2) ;
|
|
d = max ( d, m_mTree[m_mTree[i].m_nChild1].m_nDepth) ;
|
|
}
|
|
}
|
|
return d ;
|
|
}
|
|
return d - m_mTree[nId].m_nDepth ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int Tree::GetDepth( int nId, int nRef = -2)
|
|
{
|
|
int c = 0 ;
|
|
while ( m_mTree[nId].m_nParent != nRef ) {
|
|
nId = m_mTree[nId].m_nParent ;
|
|
++ c ;
|
|
}
|
|
return c ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool Tree::GetPolygons( POLYLINEVECTOR& vPolygons)
|
|
{
|
|
if ( m_vPolygons.empty()) {
|
|
PNTVECTOR vVertices ;
|
|
INTVECTOR vNeigh ;
|
|
bool bBottomRight , bTopLeft ;
|
|
// scorro lungo tutte le celle leaves ( dell'albero bilanciato) e oltre agli angoli della cella aggiungo alla polyline anche i vertici sui lati
|
|
for ( int nId : m_vnLeaves) {
|
|
vVertices.clear() ;
|
|
vNeigh.clear() ;
|
|
vVertices.push_back( m_mTree[nId].GetBottomLeft()) ;
|
|
GetBottomNeigh( nId, vNeigh) ;
|
|
// aggiungo i vertici che sono sul lato bottom, solo se ho più di un vicino bottom
|
|
if ( (int) vNeigh.size() != 0 && (int) vNeigh.size() != 1){
|
|
for ( int j : vNeigh )
|
|
vVertices.push_back( m_mTree[j].GetTopRight()) ;
|
|
bBottomRight = true ;
|
|
}
|
|
else
|
|
bBottomRight = false ;
|
|
vNeigh.clear() ;
|
|
GetRightNeigh ( nId, vNeigh) ;
|
|
// aggiungo i vertici che sono sul lato right, solo se ho più di un vicino right
|
|
if ( (int) vNeigh.size() != 0 && (int) vNeigh.size() != 1){
|
|
for ( int j : vNeigh )
|
|
vVertices.push_back( m_mTree[j].GetBottomLeft()) ;
|
|
}
|
|
// se non l'ho già aggiunto tramite i vicini bottom aggiungo il punto bottom right
|
|
else if ( ! bBottomRight ) {
|
|
Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ;
|
|
vVertices.push_back( ptBr) ;
|
|
}
|
|
vNeigh.clear() ;
|
|
vVertices.push_back( m_mTree[nId].GetTopRight()) ;
|
|
GetTopNeigh ( nId, vNeigh) ;
|
|
reverse( vNeigh.begin(), vNeigh.end()) ;
|
|
// aggiungo i vertici che sono sul lato top, solo se ho più di un vicino top
|
|
if ( (int) vNeigh.size() != 0 && (int) vNeigh.size() != 1) {
|
|
for ( int j : vNeigh)
|
|
vVertices.push_back( m_mTree[j].GetBottomLeft()) ;
|
|
bTopLeft = true ;
|
|
}
|
|
else
|
|
bTopLeft = false ;
|
|
vNeigh.clear() ;
|
|
GetLeftNeigh ( nId, vNeigh) ;
|
|
reverse( vNeigh.begin(), vNeigh.end()) ;
|
|
// aggiungo i vertici che sono sul lato left, solo se ho più di un vicino left
|
|
if ( (int) vNeigh.size() != 0 && (int) vNeigh.size() != 1) {
|
|
for ( int j : vNeigh)
|
|
vVertices.push_back( m_mTree[j].GetTopRight()) ;
|
|
}
|
|
// se non l'ho già aggiunto tramite i vicini top aggiungo il punto top left
|
|
else if ( ! bTopLeft) {
|
|
Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ;
|
|
vVertices.push_back( ptTl) ;
|
|
}
|
|
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 necessario cambio l'ordine dei vertici per scegliere la diagonale di split migliore
|
|
if ( vVertices.size() == 5) {
|
|
Point3d ptPSrf, ptP00, ptP10, ptP11, ptP01;
|
|
double dU, dV ;
|
|
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) ;
|
|
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)) {
|
|
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()) ;
|
|
m_vPolygons.back().AddUPoint( i, vVertices[i]) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// restituisco i poligoni delle celle del tree nello spazio parametrico
|
|
vPolygons = m_vPolygons ;
|
|
return true ;
|
|
} |