EgtGeomKernel :
- aggiunto lo split preliminare delle patches e impostato come default - gestito il caso di superfici chiuse come il toro - corretto un errore sul miglioramento delle prestazioni Da aggiungere : - gestione delle sup. trimmate.
This commit is contained in:
@@ -99,21 +99,7 @@ void Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches)
|
||||
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) ;
|
||||
@@ -130,24 +116,96 @@ void Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches)
|
||||
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) ;
|
||||
// se richiesto divido preliminarmente le patches
|
||||
if ( bSplitPatches && ( nSpanU > 1 || nSpanV > 1)) {
|
||||
int nId = -1 ;
|
||||
for ( int i = 1 ; i < nSpanU ; ++i) {
|
||||
m_mTree[nId].SetSplitDirVert( true) ;
|
||||
Split( nId, i) ;
|
||||
++ nId ;
|
||||
++ nId ;
|
||||
}
|
||||
if (AreSamePointApprox(ptP00, ptP10)) {
|
||||
m_mTree[-1].m_nLeft = -1 ;
|
||||
m_mTree[-1].m_nRight = -1 ;
|
||||
m_mTree[-1].SetSplitDirVert( true) ;
|
||||
Split( -1) ;
|
||||
INTVECTOR vLeaves ;
|
||||
GetHeightLeaves( -1, vLeaves) ;
|
||||
for ( int nId : vLeaves) {
|
||||
for ( int j = nSpanV - 1 ; j > 0 ; --j ) {
|
||||
m_mTree[nId].SetSplitDirVert( false) ;
|
||||
Split( nId, j) ;
|
||||
nId = m_mTree[nId].m_nChild2 ;
|
||||
}
|
||||
}
|
||||
// split preliminari per dividere le patch in modo da triangolarle indipendentemente////////////////////////////////////////////////////////
|
||||
}
|
||||
// se non ho già splittato le patches, controllo se la superficie è chiusa. In tal caso la splitto sul parametro su cui è chiusa
|
||||
else {
|
||||
// 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 ;
|
||||
if ( AreSamePointApprox(ptP00, ptP01)) {
|
||||
m_mTree[-1].m_nTop = -1 ;
|
||||
m_mTree[-1].m_nBottom = -1 ;
|
||||
m_mTree[-1].SetSplitDirVert( false) ;
|
||||
Split(-1) ;
|
||||
// qui devo fare il controllo capped
|
||||
// devo controllare se i punti ai parametri U=0 e U=1 sono tutti coincidenti
|
||||
// in caso devo fare uno split nell'altra direzione
|
||||
bool bOk = false ;
|
||||
bool bCapped0 = true, bCapped1 = true ;
|
||||
Point3d ptV0, ptV1 ;
|
||||
// controllo se tutti i punti sull'isoparametrica sono uguali
|
||||
for ( int i = 1 ; i < nDegV * nSpanV + 1 ; ++ i) {
|
||||
ptV0 = m_pSrfBz->GetControlPoint( i * ( nDegU * nSpanU + 1), &bOk) ;
|
||||
bCapped0 = bCapped0 && AreSamePointApprox( ptP00, ptV0) ;
|
||||
ptV1 = m_pSrfBz->GetControlPoint( ( i + 1) * ( nDegU * nSpanU + 1) - 1, &bOk) ;
|
||||
bCapped1 = bCapped1 && AreSamePointApprox( ptP10, ptV1) ;
|
||||
}
|
||||
if ( bCapped0 && bCapped1) {
|
||||
m_mTree[0].SetSplitDirVert( true) ;
|
||||
Split( 0) ;
|
||||
m_mTree[1].SetSplitDirVert( true) ;
|
||||
Split( 1) ;
|
||||
}
|
||||
}
|
||||
if ( AreSamePointApprox(ptP00, ptP10)) {
|
||||
if( (int) m_mTree.size() == 1) {
|
||||
m_mTree[-1].m_nLeft = -1 ;
|
||||
m_mTree[-1].m_nRight = -1 ;
|
||||
m_mTree[-1].SetSplitDirVert( true) ;
|
||||
Split( -1) ;
|
||||
// devo controllare se i punti ai parametri V=0 e V=1 sono tutti coincidenti
|
||||
// in caso devo fare uno split nell'altra direzione
|
||||
bool bOk = false ;
|
||||
bool bCapped0 = true, bCapped1 = true ;
|
||||
Point3d ptU0, ptU1 ;
|
||||
// controllo se tutti i punti sull'isoparametrica sono uguali
|
||||
for ( int i = 1 ; i < nDegU * nSpanU + 1 ; ++ i) {
|
||||
ptU0 = m_pSrfBz->GetControlPoint( i, &bOk) ;
|
||||
bCapped0 = bCapped0 && AreSamePointApprox( ptP00, ptU0) ;
|
||||
ptU1 = m_pSrfBz->GetControlPoint( i + ( nDegU * nSpanU + 1 ) * ( nDegV * nSpanV), &bOk) ;
|
||||
bCapped1 = bCapped1 && AreSamePointApprox( ptP01, ptU1) ;
|
||||
}
|
||||
if ( bCapped0 && bCapped1) {
|
||||
m_mTree[0].SetSplitDirVert( false) ;
|
||||
Split( 0) ;
|
||||
m_mTree[1].SetSplitDirVert( false) ;
|
||||
Split( 1) ;
|
||||
}
|
||||
}
|
||||
else if ( (int) m_mTree.size() > 1 && (int) m_mTree.size() < 4) {
|
||||
m_mTree[0].m_nLeft = -1 ;
|
||||
m_mTree[0].m_nRight = -1 ;
|
||||
m_mTree[1].m_nLeft = -1 ;
|
||||
m_mTree[1].m_nRight = -1 ;
|
||||
m_mTree[0].SetSplitDirVert( true) ;
|
||||
Split( 0) ;
|
||||
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) ;
|
||||
@@ -163,84 +221,87 @@ void Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches)
|
||||
void
|
||||
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 ;
|
||||
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)) ;
|
||||
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
|
||||
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 ;
|
||||
// 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) ;
|
||||
// controllo che lo split non venga fatto sul lato della cella
|
||||
if ( ( m_mTree[nId].IsSplitVert() && dSplitValue > m_mTree[nId].GetBottomLeft().x + EPS_SMALL && dSplitValue < m_mTree[nId].GetTopRight().x - EPS_SMALL) ||
|
||||
( ! m_mTree[nId].IsSplitVert() && dSplitValue > m_mTree[nId].GetBottomLeft().y + EPS_SMALL && dSplitValue < m_mTree[nId].GetTopRight().y - EPS_SMALL)) {
|
||||
// per lo split a parametro libero devo impedire che si facciano split troppo vicini al bordo!!!!!!!!!!!!!!!!!!!
|
||||
m_mTree[nId].m_dSplit = dSplitValue ;
|
||||
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)) ;
|
||||
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
|
||||
Point3d ptBL( m_mTree[nId].GetBottomLeft().x, dSplitValue) ;
|
||||
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, dSplitValue) ;
|
||||
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 ;
|
||||
// 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
|
||||
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
|
||||
Point3d ptTR( dSplitValue, 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( dSplitValue, 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 ;
|
||||
// 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
|
||||
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) ;
|
||||
}
|
||||
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 ;
|
||||
// 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) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -259,307 +320,288 @@ Tree::Split( int nId)
|
||||
bool Tree::BuildTree( double dLinTol_, double dSideMin, double dSideMax)
|
||||
{
|
||||
// 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)) ;
|
||||
// controllo che la cella non sia già stata preliminarmente splittata
|
||||
if ( m_mTree[nCToSplit].IsLeaf()) {
|
||||
// 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 ;
|
||||
}
|
||||
m_mTree[nCToSplit].SetSplitDirVert( bVert) ;
|
||||
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))
|
||||
// se la cella è abbastanza grande da poter essere divisa ancora, calcolo l'errore di approssimazione
|
||||
double dErr = 0 ;
|
||||
bool bSplit = false ;
|
||||
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]) ;
|
||||
dDimU = ( dDimU > 1 ? 1 : dDimU) ;
|
||||
double dDimV = ( dLen1 >= dLen3 ? dLen1 / m_vDim[1] : dLen3 / m_vDim[3]) ;
|
||||
dDimV = ( dDimV > 1 ? 1 : dDimV) ;
|
||||
// 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 && ! bSplit ; ++ 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 dpc( ptBzV, clV) ;
|
||||
// distanza di approssimazione locale
|
||||
double dDist ;
|
||||
dpc.GetDist( dDist) ;
|
||||
if ( dDist > dErr)
|
||||
dErr = dDist ;
|
||||
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 ;
|
||||
if ( dDist > dLinTol) {
|
||||
bSplit = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( dErr > dLinTol || dSideMaxVal > dSideMax) {
|
||||
m_mTree[nCToSplit].SetSplitDirVert( bVert) ;
|
||||
// effettuo lo split
|
||||
Split( nCToSplit) ;
|
||||
//if ( dErr > dLinTol || dSideMaxVal > dSideMax) {
|
||||
if ( bSplit || 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())
|
||||
// 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() ;
|
||||
while ( m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) {
|
||||
if ( m_mTree[nCToSplit].m_nParent != -2)
|
||||
nCToSplit = m_mTree[nCToSplit].m_nParent ;
|
||||
// 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() ;
|
||||
if ( nCToSplit == -1 && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
|
||||
break ;
|
||||
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 ;
|
||||
}
|
||||
else {
|
||||
nCToSplit = m_mTree[nCToSplit].m_nChild1 ;
|
||||
}
|
||||
}
|
||||
Balance( vBalanceCheck) ; // da implementare quando dividerò ad un parametro a scelta e non a metà
|
||||
Balance() ; // 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) ;
|
||||
if ( m_mTree[nCToSplit].IsLeaf()) {
|
||||
// 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 ;
|
||||
// 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 {
|
||||
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) ;
|
||||
else {
|
||||
for ( double i = 0.25 ; i < 1 ; i = i + 0.25 ) {
|
||||
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) ;
|
||||
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 ;
|
||||
}
|
||||
}
|
||||
|
||||
// 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)) ;
|
||||
|
||||
// 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())
|
||||
|
||||
double dErr = 0 ;
|
||||
if ( m_bMulti) {
|
||||
Point3d ptPSrf ;
|
||||
Plane3d plAppr ;
|
||||
if ( ! AreSamePointApprox( ptP00, ptP10) && ! AreSamePointApprox( ptP00, ptP01))
|
||||
plAppr.Set( ptP00, ( ptP00 - ptP01) ^ ( ptP00 - ptP10)) ;
|
||||
else if ( AreSamePointApprox( ptP00, ptP10)) {
|
||||
plAppr.Set( ptP01, ( ptP00 - ptP01) ^ ( ptP01 - ptP11)) ;
|
||||
}
|
||||
else if ( AreSamePointApprox( ptP00, ptP01)) {
|
||||
plAppr.Set( ptP10, ( ptP10 - ptP11) ^ ( 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() ;
|
||||
while ( m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) {
|
||||
if ( m_mTree[nCToSplit].m_nParent != -2)
|
||||
nCToSplit = m_mTree[nCToSplit].m_nParent ;
|
||||
// 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() ;
|
||||
if ( nCToSplit == -1 && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
|
||||
break ;
|
||||
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 ;
|
||||
}
|
||||
else {
|
||||
nCToSplit = m_mTree[nCToSplit].m_nChild1 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -572,7 +614,7 @@ bool Tree::BuildTree( double dLinTol_, double dSideMin, double dSideMax)
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Tree::Balance( INTVECTOR vCheck)
|
||||
void Tree::Balance()
|
||||
{
|
||||
//for ( int i : vCheck ) {
|
||||
// // non ancora implementato
|
||||
@@ -652,12 +694,13 @@ void Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs)
|
||||
vector<Cell> vCells ;
|
||||
for ( int k : vTopNeighs)
|
||||
vCells.push_back( m_mTree[k]) ;
|
||||
sort( vCells.begin(), vCells.end(), Cell::minorX ) ;
|
||||
std::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)
|
||||
{
|
||||
@@ -730,7 +773,7 @@ void Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs)
|
||||
vector<Cell> vCells ;
|
||||
for ( int k : vBottomNeighs)
|
||||
vCells.push_back( m_mTree[k]) ;
|
||||
sort( vCells.begin(), vCells.end(), Cell::minorX) ;
|
||||
std::sort( vCells.begin(), vCells.end(), Cell::minorX) ;
|
||||
vBottomNeighs.clear() ;
|
||||
for ( Cell c : vCells)
|
||||
vBottomNeighs.push_back( c.m_nId) ;
|
||||
@@ -809,7 +852,7 @@ void Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs)
|
||||
vector<Cell> vCells ;
|
||||
for ( int k : vLeftNeighs)
|
||||
vCells.push_back( m_mTree[k]) ;
|
||||
sort( vCells.begin(), vCells.end(), Cell::minorY) ;
|
||||
std::sort( vCells.begin(), vCells.end(), Cell::minorY) ;
|
||||
vLeftNeighs.clear() ;
|
||||
for ( Cell c : vCells)
|
||||
vLeftNeighs.push_back( c.m_nId) ;
|
||||
@@ -887,7 +930,7 @@ void Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs)
|
||||
vector<Cell> vCells ;
|
||||
for ( int k : vRightNeighs)
|
||||
vCells.push_back( m_mTree[k]) ;
|
||||
sort( vCells.begin(), vCells.end(), Cell::minorY) ;
|
||||
std::sort( vCells.begin(), vCells.end(), Cell::minorY) ;
|
||||
vRightNeighs.clear() ;
|
||||
for ( Cell c : vCells)
|
||||
vRightNeighs.push_back( c.m_nId) ;
|
||||
@@ -896,35 +939,41 @@ void Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs)
|
||||
//----------------------------------------------------------------------------
|
||||
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) ;
|
||||
}
|
||||
if ( nId == -1 && m_mTree[-1].IsLeaf()) {
|
||||
vnLeaves.push_back( -1) ;
|
||||
return 0 ;
|
||||
}
|
||||
else {
|
||||
for ( int j = 0 ; j != (int) vnLeaves.size() ; ++ j) {
|
||||
int i = vnLeaves[j] ;
|
||||
if ( m_mTree[i].IsLeaf() ) {
|
||||
continue ;
|
||||
}
|
||||
if ( (int) vnLeaves.size() == 0) {
|
||||
if ( m_mTree[nId].IsLeaf())
|
||||
return d ;
|
||||
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) ;
|
||||
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) ;
|
||||
}
|
||||
}
|
||||
return d ;
|
||||
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 ;
|
||||
}
|
||||
return d - m_mTree[nId].m_nDepth ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -974,7 +1023,7 @@ bool Tree::GetPolygons( POLYLINEVECTOR& vPolygons)
|
||||
vNeigh.clear() ;
|
||||
vVertices.push_back( m_mTree[nId].GetTopRight()) ;
|
||||
GetTopNeigh ( nId, vNeigh) ;
|
||||
reverse( vNeigh.begin(), vNeigh.end()) ;
|
||||
std::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)
|
||||
@@ -985,7 +1034,7 @@ bool Tree::GetPolygons( POLYLINEVECTOR& vPolygons)
|
||||
bTopLeft = false ;
|
||||
vNeigh.clear() ;
|
||||
GetLeftNeigh ( nId, vNeigh) ;
|
||||
reverse( vNeigh.begin(), vNeigh.end()) ;
|
||||
std::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)
|
||||
|
||||
Reference in New Issue
Block a user