EgtGeomKernel :
- correzione di bug nel trim di sup di Bezier chiuse - correzione di bug nella conversione di NURBS in sup di Bezier
This commit is contained in:
+1
-1
@@ -558,7 +558,7 @@ NurbsToBezierCurve( const CNurbsData& cnData)
|
||||
}
|
||||
if ( ! bOk)
|
||||
return nullptr ;
|
||||
|
||||
|
||||
// se 1 solo intervallo, la Nurbs è già una curva di Bezier
|
||||
if ( nInt == 1) {
|
||||
// creo la curva di Bezier
|
||||
|
||||
+12
-129
@@ -147,6 +147,10 @@ NurbsToBezierSurface(const CNurbsSurfData& cnData)
|
||||
}
|
||||
|
||||
bool bRef = false ;
|
||||
// se la superficie è lineare nel parametro U allora è già in forma di Bezier in questo parametro
|
||||
if ( b == nU - 1 ) {
|
||||
nb = 1 ;
|
||||
}
|
||||
while ( b < nU - 1) { // qui correggo un probabile errore, mettendo nU anziché nCPV, come indicato nell'algoritmo
|
||||
int i = b ;
|
||||
while ( b < nU - 1 && abs( cnData.vU[b+1] - cnData.vU[b]) < EPS_ZERO)
|
||||
@@ -270,7 +274,7 @@ NurbsToBezierSurface(const CNurbsSurfData& cnData)
|
||||
}
|
||||
}
|
||||
// devo vedere quante patch ci stanno prendendo i punti che ci sono
|
||||
nb = (cnData.nCPU - 1) / cnData.nDegU ;
|
||||
//nb = (cnData.nCPU - 1) / cnData.nDegU ;
|
||||
}
|
||||
else
|
||||
nCPU_ref = cnData.nDegU * nb + 1 ; // numero dei punti di controllo in U dopo il raffinamento
|
||||
@@ -308,7 +312,11 @@ NurbsToBezierSurface(const CNurbsSurfData& cnData)
|
||||
}
|
||||
|
||||
bRef = false ;
|
||||
while ( b < nV - 1) { // qui correggo un probabile errore, mettendo nU anziché nCPV, come indicato nell'algoritmo
|
||||
// se la superficie è lineare nel parametro V allora è già in forma di Bezier in questo parametro
|
||||
if ( b == nV - 1 ) {
|
||||
nc = 1 ;
|
||||
}
|
||||
while ( b < nV - 1) {
|
||||
int i = b ;
|
||||
while ( b < nV - 1 && abs( cnData.vV[b+1] - cnData.vV[b]) < EPS_ZERO)
|
||||
++ b ;
|
||||
@@ -440,7 +448,7 @@ NurbsToBezierSurface(const CNurbsSurfData& cnData)
|
||||
}
|
||||
}
|
||||
// devo vedere quante patch ci stanno prendendo i punti che ci sono
|
||||
nc = (cnData.nCPV - 1) / cnData.nDegV ;
|
||||
//nc = (cnData.nCPV - 1) / cnData.nDegV ;
|
||||
}
|
||||
else
|
||||
nCPV_ref = cnData.nDegV * nc + 1 ;
|
||||
@@ -465,129 +473,4 @@ NurbsToBezierSurface(const CNurbsSurfData& cnData)
|
||||
}
|
||||
}
|
||||
return Release( pSrfBz) ;
|
||||
}
|
||||
|
||||
//// algoritmo per le curve, da usare come reference///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
// // vettore dei punti di controllo della curva di Bezier
|
||||
// PNTVECTOR vBC ;
|
||||
// vBC.resize( cnData.nDeg + 1) ;
|
||||
// DBLVECTOR vBW ;
|
||||
// vBW.resize( cnData.nDeg + 1) ;
|
||||
// if ( ! cnData.bRat) {
|
||||
// for ( int i = 0 ; i <= cnData.nDeg ; ++ i)
|
||||
// vBC[i] = cnData.vCP[i] ;
|
||||
// }
|
||||
// else {
|
||||
// for ( int i = 0 ; i <= cnData.nDeg ; ++ i) {
|
||||
// vBC[i] = cnData.vCP[i] * cnData.vW[i] ;
|
||||
// vBW[i] = cnData.vW[i] ;
|
||||
// }
|
||||
// }
|
||||
// // primi coefficienti della successiva
|
||||
// PNTVECTOR vNextBC ;
|
||||
// vNextBC.resize( cnData.nDeg - 1) ;
|
||||
// DBLVECTOR vNextBW ;
|
||||
// vNextBW.resize( cnData.nDeg - 1) ;
|
||||
// // ...
|
||||
// DBLVECTOR vAlfa ;
|
||||
// vAlfa.resize( cnData.nDeg - 1) ;
|
||||
// int a = cnData.nDeg - 1 ;
|
||||
// int b = cnData.nDeg ;
|
||||
// bool bPrevRejected = false ;
|
||||
// // ciclo
|
||||
// while ( b < nU - 1) {
|
||||
// int i = b ;
|
||||
// while ( b < nU - 1 && abs( cnData.vU[b+1] - cnData.vU[b]) < EPS_ZERO)
|
||||
// ++ b ;
|
||||
// int mult = min( b - i + 1, cnData.nDeg) ;
|
||||
// if ( mult < cnData.nDeg) {
|
||||
// // numeratore di alfa
|
||||
// double numer = cnData.vU[b] - cnData.vU[a] ;
|
||||
// // calcola e salva gli alfa
|
||||
// for ( int j = cnData.nDeg ; j > mult ; -- j)
|
||||
// vAlfa[j-mult-1] = numer / ( cnData.vU[a+j] - cnData.vU[a]) ;
|
||||
// // inserisco il nodo r volte
|
||||
// int r = cnData.nDeg - mult ;
|
||||
// for ( int j = 1 ; j <= r ; ++ j) {
|
||||
// int save = r - j ;
|
||||
// int s = mult + j ;
|
||||
// for ( int k = cnData.nDeg ; k >= s ; -- k)
|
||||
// vBC[k] = vAlfa[k-s] * vBC[k] + ( 1 - vAlfa[k-s]) * vBC[k-1] ;
|
||||
// if ( cnData.bRat) {
|
||||
// for ( int k = cnData.nDeg ; k >= s ; -- k)
|
||||
// vBW[k] = vAlfa[k-s] * vBW[k] + ( 1 - vAlfa[k-s]) * vBW[k-1] ;
|
||||
// }
|
||||
// if ( b < nU - 1) {
|
||||
// vNextBC[save] = vBC[cnData.nDeg] ;
|
||||
// if ( cnData.bRat)
|
||||
// vNextBW[save] = vBW[cnData.nDeg] ;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // costruisco la curva di Bezier e la inserisco nella curva composita
|
||||
// PtrOwner<ICurveBezier> pCrvBez( CreateCurveBezier()) ;
|
||||
// if ( IsNull( pCrvBez))
|
||||
// return nullptr ;
|
||||
// // se precedente saltata
|
||||
// if ( bPrevRejected) {
|
||||
// // prendo l'ultimo punto della curva composita per garantire la continuità
|
||||
// Point3d ptEnd ;
|
||||
// if ( pCrvCompo->GetEndPoint( ptEnd))
|
||||
// vBC[0] = ptEnd ;
|
||||
// }
|
||||
// // la inizializzo
|
||||
// if ( ! pCrvBez->Init( cnData.nDeg, cnData.bRat))
|
||||
// return nullptr ;
|
||||
// if ( ! cnData.bRat) {
|
||||
// for ( int i = 0 ; i <= cnData.nDeg ; ++ i) {
|
||||
// if ( ! pCrvBez->SetControlPoint( i, vBC[i]))
|
||||
// return nullptr ;
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// for ( int i = 0 ; i <= cnData.nDeg ; ++ i) {
|
||||
// if ( ! pCrvBez->SetControlPoint( i, vBC[i] / vBW[i], vBW[i]))
|
||||
// return nullptr ;
|
||||
// }
|
||||
// }
|
||||
// // se è una vera curva, la aggiungo alla curva composita
|
||||
// if ( ! pCrvBez->IsAPoint()) {
|
||||
// if ( ! pCrvCompo->AddCurve( Release( pCrvBez)))
|
||||
// return nullptr ;
|
||||
// bPrevRejected = false ;
|
||||
// }
|
||||
// // altrimenti è un punto, la cancello
|
||||
// else {
|
||||
// pCrvBez.Reset() ;
|
||||
// bPrevRejected = true ;
|
||||
// }
|
||||
//
|
||||
// // inizializzazioni per la prossima curva di Bezier
|
||||
// if ( b < nU - 1) {
|
||||
// if ( ! cnData.bRat) {
|
||||
// for ( int i = 0 ; i < cnData.nDeg - 1 ; ++ i)
|
||||
// vBC[i] = vNextBC[i] ;
|
||||
// for ( int i = cnData.nDeg - mult ; i <= cnData.nDeg ; ++ i)
|
||||
// vBC[i] = cnData.vCP[b-cnData.nDeg+i+1] ;
|
||||
// }
|
||||
// else {
|
||||
// for ( int i = 0 ; i < cnData.nDeg - 1 ; ++ i) {
|
||||
// vBC[i] = vNextBC[i] ;
|
||||
// vBW[i] = vNextBW[i] ;
|
||||
// }
|
||||
// for ( int i = cnData.nDeg - mult ; i <= cnData.nDeg ; ++ i) {
|
||||
// vBC[i] = cnData.vCP[b-cnData.nDeg+i+1] * cnData.vW[b-cnData.nDeg+i+1] ;
|
||||
// vBW[i] = cnData.vW[b-cnData.nDeg+i+1] ;
|
||||
// }
|
||||
// }
|
||||
// a = b ;
|
||||
// ++ b ;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // restituisco la curva composita
|
||||
// return Release( pCrvCompo) ;
|
||||
//}
|
||||
}
|
||||
@@ -1507,6 +1507,7 @@ SurfBezier::GetAuxSurf( void) const
|
||||
Point3d ptMin = std::get<0>( vTrees[i]) ;
|
||||
Point3d ptMax = std::get<1>( vTrees[i]) ;
|
||||
Tree.SetSurf( this, true, ptMin, ptMax) ;
|
||||
//Tree.BuildTree_test() ;
|
||||
Tree.BuildTree( 5 * LIN_TOL_FINE, 1) ;
|
||||
Tree.GetPolygons( vvPL) ;
|
||||
}
|
||||
@@ -1559,6 +1560,7 @@ SurfBezier::GetLeaves( std::vector<std::tuple<int, Point3d, Point3d>>& vLeaves)
|
||||
Point3d ptMin = std::get<0>( vTrees[i]) ;
|
||||
Point3d ptMax = std::get<1>( vTrees[i]) ;
|
||||
Tree.SetSurf( this, true, ptMin, ptMax) ;
|
||||
//Tree.BuildTree_test() ;
|
||||
Tree.BuildTree( 5 * LIN_TOL_FINE, 1) ;
|
||||
Tree.GetLeaves( vCells) ;
|
||||
for (int k = 0 ; k < (int)vCells.size(); ++ k ) {
|
||||
|
||||
@@ -29,7 +29,8 @@
|
||||
//----------------------------------------------------------------------------
|
||||
Cell::Cell( void)
|
||||
: 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_nFlag( -1), m_nFlag2( 0), m_nRightEdgeIn( -1), m_ptPbl( ORIG), m_ptPtr(), m_bProcessed( false), m_bSplitVert( true)
|
||||
m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_nFlag2( 0), m_nRightEdgeIn( -1), m_bOnLeftEdge( false),
|
||||
m_ptPbl( ORIG), m_ptPtr(), m_bProcessed( false), m_bSplitVert( true)
|
||||
{
|
||||
Point3d ptTr ( 1 * SBZ_TREG_COEFF, 1 * SBZ_TREG_COEFF) ;
|
||||
m_ptPtr = ptTr ;
|
||||
@@ -39,7 +40,8 @@ Cell::Cell( void)
|
||||
//----------------------------------------------------------------------------
|
||||
Cell::Cell( const Point3d& ptBL, const Point3d& ptTR)
|
||||
: 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_nFlag( -1), m_nFlag2( 0), m_nRightEdgeIn( -1), m_ptPbl( ptBL), m_ptPtr( ptTR), m_bProcessed( false), m_bSplitVert( true)
|
||||
m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_nFlag2( 0), m_nRightEdgeIn( -1), m_bOnLeftEdge( false),
|
||||
m_ptPbl( ptBL), m_ptPtr( ptTR), m_bProcessed( false), m_bSplitVert( true)
|
||||
{}
|
||||
|
||||
|
||||
@@ -200,8 +202,18 @@ Tree::SetSurf( const SurfBezier* pSrfBz, const bool bSplitPatches, const Point3d
|
||||
m_mVert.insert( std::pair<int, PNTVECTOR>( -1, vVert)) ;
|
||||
// se richiesto divido preliminarmente le patches
|
||||
m_vnParents.clear() ;
|
||||
if ( bSplitPatches && ( nSpanU > 1 || nSpanV > 1)) {
|
||||
if ( m_bSplitPatches && ( nSpanU > 1 || nSpanV > 1)) {
|
||||
int nId = -1 ;
|
||||
// se la superficie è chiusa lungo il parametro U, sistemo le adiacenze al bordo
|
||||
if ( AreSamePointApprox(ptP00, ptP10) && AreSamePointApprox(ptP01, ptP11) ) {
|
||||
m_mTree[-1].m_nLeft = -1 ;
|
||||
m_mTree[-1].m_nRight = -1 ;
|
||||
}
|
||||
// se la superficie è chiusa lungo il parametro V, sistemo le adiacenze al bordo
|
||||
if ( ( AreSamePointApprox(ptP00, ptP01) && AreSamePointApprox(ptP10, ptP11) ) ) {
|
||||
m_mTree[-1].m_nTop = -1 ;
|
||||
m_mTree[-1].m_nBottom = -1 ;
|
||||
}
|
||||
for ( int i = 1 ; i < nSpanU ; ++i) {
|
||||
if ( i * SBZ_TREG_COEFF > ptMin.x && i * SBZ_TREG_COEFF < ptTop.x){
|
||||
m_mTree[nId].SetSplitDirVert( true) ;
|
||||
@@ -225,17 +237,20 @@ Tree::SetSurf( const SurfBezier* pSrfBz, const bool bSplitPatches, const Point3d
|
||||
GetHeightLeaves( -1, vLeaves) ;
|
||||
m_vnParents = vLeaves ;
|
||||
}
|
||||
// controllo se la superficie è chiusa. In tal caso la splitto sul parametro su cui è chiusa
|
||||
// verifico se la superficie è chiusa ed eventualmente sistemo le adiacenze
|
||||
// controllo se la superficie è chiusa.
|
||||
// se è chiusa e non ho già fatto split preliminare, splitto sul parametro su cui è chiusa
|
||||
// e 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 ;
|
||||
if ( ( AreSamePointApprox( ptP00, ptP01) || AreSamePointApprox( ptP10, ptP11)) && (int) m_mTree.size() == 1) {
|
||||
if ( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11)) {
|
||||
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
|
||||
// qui devo fare il controllo capped ( chiusura a semisfera)
|
||||
// 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 ;
|
||||
@@ -255,10 +270,13 @@ Tree::SetSurf( const SurfBezier* pSrfBz, const bool bSplitPatches, const Point3d
|
||||
Split( 1) ;
|
||||
}
|
||||
}
|
||||
if ( AreSamePointApprox( ptP00, ptP10)) {
|
||||
// nella condizione di questo if non controllo eventuali divisioni preliminari, perché ne tengo conto dopo
|
||||
if ( AreSamePointApprox( ptP00, ptP10) || AreSamePointApprox( ptP01, ptP11)) {
|
||||
if( (int) m_mTree.size() == 1) {
|
||||
m_mTree[-1].m_nLeft = -1 ;
|
||||
m_mTree[-1].m_nRight = -1 ;
|
||||
if ( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11)) {
|
||||
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
|
||||
@@ -280,7 +298,8 @@ Tree::SetSurf( const SurfBezier* pSrfBz, const bool bSplitPatches, const Point3d
|
||||
Split( 1) ;
|
||||
}
|
||||
}
|
||||
else if ( (int) m_mTree.size() > 1 && (int) m_mTree.size() < 4) {
|
||||
// se ho fatto solo 1 split e ho due celle foglie nId = 0 e nId = 1
|
||||
else if ( (int) m_mTree.size() > 1 && (int) m_mTree.size() < 4) { // si può mettere anche < 5
|
||||
m_mTree[0].m_nLeft = -1 ;
|
||||
m_mTree[0].m_nRight = -1 ;
|
||||
m_mTree[1].m_nLeft = -1 ;
|
||||
@@ -295,13 +314,29 @@ Tree::SetSurf( const SurfBezier* pSrfBz, const bool bSplitPatches, const Point3d
|
||||
|
||||
// calcolo e salvo la lunghezza reale delle curve di bezier di bordo
|
||||
PtrOwner<CurveComposite> pCrvV0( m_pSrfBz->GetCurveOnU( 0)) ;
|
||||
PtrOwner<CurveComposite> pCrvV1( m_pSrfBz->GetCurveOnU( 1)) ;
|
||||
PtrOwner<CurveComposite> pCrvV1( m_pSrfBz->GetCurveOnU( double(nSpanV))) ;
|
||||
PtrOwner<CurveComposite> pCrvU0( m_pSrfBz->GetCurveOnV( 0)) ;
|
||||
PtrOwner<CurveComposite> pCrvU1( m_pSrfBz->GetCurveOnV( 1)) ;
|
||||
PtrOwner<CurveComposite> pCrvU1( m_pSrfBz->GetCurveOnV( double(nSpanU))) ;
|
||||
double dLen0 ; pCrvV0->GetApproxLength( dLen0) ;
|
||||
double dLen1 ; pCrvU1->GetApproxLength( dLen1) ;
|
||||
double dLen2 ; pCrvV1->GetApproxLength( dLen2) ;
|
||||
double dLen3 ; pCrvU0->GetApproxLength( dLen3) ;
|
||||
if ( dLen0 < EPS_ZERO && dLen2 < EPS_ZERO ) {
|
||||
PtrOwner<CurveComposite> pCrvV( m_pSrfBz->GetCurveOnU( double(nSpanV) / 2)) ;
|
||||
pCrvV->GetApproxLength( dLen0) ;
|
||||
if ( dLen0 < EPS_ZERO ) {
|
||||
pCrvV.Set( m_pSrfBz->GetCurveOnU( double(nSpanV) / 4)) ;
|
||||
pCrvV->GetApproxLength( dLen0) ;
|
||||
}
|
||||
}
|
||||
if ( dLen1 < EPS_ZERO && dLen3 < EPS_ZERO ) {
|
||||
PtrOwner<CurveComposite> pCrvU( m_pSrfBz->GetCurveOnV( double(nSpanU) / 2)) ;
|
||||
pCrvU->GetApproxLength( dLen1) ;
|
||||
if ( dLen1 < EPS_ZERO ) {
|
||||
pCrvU.Set( m_pSrfBz->GetCurveOnV( double(nSpanU) / 4)) ;
|
||||
pCrvU->GetApproxLength( dLen1) ;
|
||||
}
|
||||
}
|
||||
m_vDim.clear() ;
|
||||
m_vDim.push_back( ( dLen0 > EPS_ZERO ? dLen0 : 1)) ;
|
||||
m_vDim.push_back( ( dLen1 > EPS_ZERO ? dLen1 : 1)) ;
|
||||
@@ -491,6 +526,11 @@ Tree::Split( const int& nId)
|
||||
bool
|
||||
Tree::BuildTree_test( const double& dLinTol, const double& dSideMin, const double& dSideMax)
|
||||
{
|
||||
// per poter usare questa funzione, anziché quella normale, bisogna:
|
||||
// - commentare la parte di funzione di SetSurf dove si fanno gli split preliminare
|
||||
// - se si usa anche la funzione GetLeaves, bisogna anche lì usare BuildTree_test al posto di BuildTree
|
||||
|
||||
|
||||
//int nCToSplit = -1 ;
|
||||
//celle 0,1
|
||||
m_mTree[-1].SetSplitDirVert( true) ;
|
||||
@@ -638,17 +678,33 @@ Tree::BuildTree( const double& dLinTol, const double& dSideMin, const double& dS
|
||||
double dLen1 = Dist( ptP10, ptP11) ;
|
||||
double dLen2 = Dist( ptP01, ptP11) ;
|
||||
double dLen3 = Dist( ptP00, ptP01) ;
|
||||
if ( dLen0 < EPS_ZERO && dLen2 < EPS_ZERO ) {
|
||||
double dV = ( m_mTree[nCToSplit].GetBottomLeft().y + m_mTree[nCToSplit].GetTopRight().y) / 2 / SBZ_TREG_COEFF ;
|
||||
PtrOwner<CurveComposite> pCrvV( m_pSrfBz->GetCurveOnU( dV)) ;
|
||||
double dLenU0, dLenU1 ;
|
||||
pCrvV->GetLengthAtParam( m_mTree[nCToSplit].GetBottomLeft().x / SBZ_TREG_COEFF, dLenU0) ;
|
||||
pCrvV->GetLengthAtParam( m_mTree[nCToSplit].GetTopRight().x / SBZ_TREG_COEFF, dLenU1) ;
|
||||
dLen0 = abs( dLenU1 - dLenU0) ;
|
||||
}
|
||||
if ( dLen1 < EPS_ZERO && dLen3 < EPS_ZERO ) {
|
||||
double dU = ( m_mTree[nCToSplit].GetBottomLeft().x + m_mTree[nCToSplit].GetTopRight().x) / 2 / SBZ_TREG_COEFF ;
|
||||
PtrOwner<CurveComposite> pCrvU( m_pSrfBz->GetCurveOnV( dU)) ;
|
||||
double dLenV0, dLenV1 ;
|
||||
pCrvU->GetLengthAtParam( m_mTree[nCToSplit].GetBottomLeft().y / SBZ_TREG_COEFF, dLenV0) ;
|
||||
pCrvU->GetLengthAtParam( m_mTree[nCToSplit].GetTopRight().y / SBZ_TREG_COEFF, dLenV1) ;
|
||||
dLen1 = abs( dLenV1 - dLenV0) ;
|
||||
}
|
||||
// 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 = std::max( dLen0, dLen2) ;
|
||||
if ( dLen0 > EPS_ZERO && dLen2 > EPS_ZERO)
|
||||
dSideMinVal = std::min( dLen0, dLen2) ;
|
||||
else
|
||||
dSideMinVal = std::max( dLen0, dLen2) ;
|
||||
}
|
||||
else {
|
||||
if ( dLen1 != 0 && dLen3 != 0)
|
||||
dSideMinVal = std::max( dLen1, dLen3) ;
|
||||
if ( dLen1 > EPS_ZERO && dLen3 > EPS_ZERO)
|
||||
dSideMinVal = std::min( dLen1, dLen3) ;
|
||||
else
|
||||
dSideMinVal = std::max( dLen1, dLen3) ;
|
||||
}
|
||||
@@ -657,11 +713,13 @@ Tree::BuildTree( const double& dLinTol, const double& dSideMin, const double& dS
|
||||
|
||||
// se la cella è abbastanza grande da poter essere divisa ancora, calcolo l'errore di approssimazione
|
||||
bool bSplit = false ;
|
||||
if ( dSideMinVal / 2 >= dSideMin && dSideMaxVal < dSideMax && ( dCurvV > dLinTol || dCurvU > dLinTol)) {
|
||||
// dSideMinVal potrebbe essere zero se entrambi i lati che dovrei splittare sono collassati in un punto, ma questo non vuol
|
||||
// dire che non dovrei eseguire lo split
|
||||
if ( (dSideMinVal / 2 >= dSideMin || dSideMinVal < EPS_SMALL) && dSideMaxVal < dSideMax && ( dCurvV > dLinTol || dCurvU > dLinTol)) {
|
||||
CurveLine cl0010, cl0001, cl1011, cl0111 ;
|
||||
// U=0
|
||||
// V=0
|
||||
cl0010.Set( ptP00, ptP10) ;
|
||||
// U=1
|
||||
// V=1
|
||||
cl0111.Set( ptP01, ptP11) ;
|
||||
Point3d pt0010, pt0111, ptBz0, ptBz1, ptBzV ;
|
||||
int nFlag ;
|
||||
@@ -680,10 +738,22 @@ Tree::BuildTree( const double& dLinTol, const double& dSideMin, const double& dS
|
||||
if ( ! m_pSrfBz->GetPointD1D2( dULoc, m_mTree[nCToSplit].GetBottomLeft().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz0) ||
|
||||
! m_pSrfBz->GetPointD1D2( dULoc, m_mTree[nCToSplit].GetTopRight().y / SBZ_TREG_COEFF, 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) ;
|
||||
// verifico che la cella non sia uno spicchio in verticale, cioè con ptP00 == ptP01 && ptP10 == ptP11
|
||||
// ( vedi disegno sotto per uno spicchio verticale)
|
||||
// sennò i punti che cerco sono semplicemente i vertici
|
||||
if ( cl0010.IsValid()) {
|
||||
DistPointCurve dpc0010( ptBz0, cl0010) ;
|
||||
dpc0010.GetMinDistPoint( 0, pt0010, nFlag) ;
|
||||
}
|
||||
else
|
||||
pt0010 = ptP00 ;
|
||||
if ( cl0111.IsValid()) {
|
||||
DistPointCurve dpc0111( ptBz1, cl0111) ;
|
||||
dpc0111.GetMinDistPoint( 0, pt0111, nFlag) ;
|
||||
}
|
||||
else
|
||||
pt0111 = ptP01 ;
|
||||
// curva a parametro U fisso, con V che scorre
|
||||
clV.Set( pt0010, pt0111) ;
|
||||
for ( int v = 0 ; v < nStepsV ; ++ v) {
|
||||
double dV = double ( v) / double ( nStepsV - 1) ;
|
||||
@@ -694,6 +764,20 @@ Tree::BuildTree( const double& dLinTol, const double& dSideMin, const double& dS
|
||||
// distanza di approssimazione locale
|
||||
double dDist ;
|
||||
dpc.GetDist( dDist) ;
|
||||
// se la cella è uno spicchio, quindi con due lati collassati, devo calcolare in modo diverso dist
|
||||
// ptP00 == ptP01
|
||||
// / \
|
||||
// / \
|
||||
// / \
|
||||
// ( )
|
||||
// \ /
|
||||
// \ /
|
||||
// \ /
|
||||
// ptP10 == ptP11
|
||||
if ( ! clV.IsValid() && AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11)) {
|
||||
DistPointCurve dpcSlice( ptBzV, cl0010) ;
|
||||
dpcSlice.GetDist( dDist) ;
|
||||
}
|
||||
if ( dDist > dLinTol) {
|
||||
bSplit = true ;
|
||||
break ;
|
||||
@@ -1726,11 +1810,16 @@ Tree::TraceLoopLabelCell( void)
|
||||
ResetTree() ;
|
||||
INTVECTOR vNeigh, vFirst ;
|
||||
GetRootNeigh( 1, vFirst) ;
|
||||
for ( int k : vFirst) {
|
||||
m_mTree[k].m_bOnLeftEdge = true ;
|
||||
}
|
||||
int nLastLeft = vFirst.back() ;
|
||||
int nCell = vFirst[0] ;
|
||||
GetRightNeigh( nCell, vNeigh) ;
|
||||
// proseguo finché non sono sull'elemento più alto di vFirst e tutti i suoi vicini sono processati/categorizzati
|
||||
bool bAllDone = false ;
|
||||
// mentre scorro a destra mi basta trovare un vicino da cui non sono passato
|
||||
// mentre torno indietro a sinistra, mi fermo quando trovo una cella non processata ( con vicini a destra da cui non sono passato)
|
||||
while ( ! bAllDone) {
|
||||
// categorizzo la cella
|
||||
m_mTree[nCell].m_nFlag2 = 1 ;
|
||||
@@ -1738,7 +1827,7 @@ Tree::TraceLoopLabelCell( void)
|
||||
bool bDone = false ;
|
||||
// fintanto che la cella ha tra i vicini a destra una cella non elaborata mi sposto a destra
|
||||
// definisco una cella Processed se tutto il ramo a destra è categorizzato
|
||||
while ( ( (int)vNeigh.size() > 0 && ! bDone) || ! m_mTree[nCell].IsProcessed()) {
|
||||
while ( ! m_mTree[nCell].IsProcessed()) {
|
||||
// verso la cella a destra più in basso da cui non sono ancora passato
|
||||
bool bProceeded = false ;
|
||||
for ( int i = 0 ; i < (int)vNeigh.size() ; ++ i) {
|
||||
@@ -1762,20 +1851,31 @@ Tree::TraceLoopLabelCell( void)
|
||||
vNeigh.clear() ;
|
||||
GetRightNeigh( nCell, vNeigh) ;
|
||||
bDone = true ;
|
||||
// controllo che tra i vicini di destra ce ne sia almeno uno non processato
|
||||
//controllo che tra i vicini di destra ce ne sia almeno uno da cui non sono passato
|
||||
// ( e controllo che non sia una cella sul lato sinistro ( adiacenza in caso di superficie chiusa))
|
||||
for ( int t: vNeigh) {
|
||||
if ( ! m_mTree[t].IsProcessed()) {
|
||||
bDone = false ;
|
||||
break ;
|
||||
if ( m_mTree[t].m_nFlag2 == 0 ) {
|
||||
if ( ! m_bClosed) {
|
||||
bDone = false ;
|
||||
break ;
|
||||
}
|
||||
else {
|
||||
// controllo che non sia sul lato sinistro
|
||||
if ( ! m_mTree[t].m_bOnLeftEdge) {
|
||||
bDone = false ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_mTree[nCell].SetProcessed( bDone) ;
|
||||
}
|
||||
}
|
||||
vNeigh.clear() ;
|
||||
GetRightNeigh( nCell, vNeigh) ;
|
||||
// se non ho vicini a destra o se i vicini sono già tutti categorizzati
|
||||
// torno indietro a sinistra alla cella già categorizzata più bassa
|
||||
while ( (int) vNeigh.size() == 0 || m_mTree[nCell].IsProcessed()) {
|
||||
while ( m_mTree[nCell].IsProcessed()) {
|
||||
// trovo il vicino a sinistra, già categorizzato, più basso
|
||||
vNeigh.clear() ;
|
||||
GetLeftNeigh( nCell, vNeigh) ;
|
||||
@@ -1785,21 +1885,36 @@ Tree::TraceLoopLabelCell( void)
|
||||
break ;
|
||||
}
|
||||
}
|
||||
// se non ho vicini a sinistra sono tornato sul lato sinistro e quindi devo procedere alla cella più bassa non processata sul lato sinistro
|
||||
if ( vNeigh.empty()) {
|
||||
for ( int p = 0 ; p < (int)vFirst.size() ; ++ p) {
|
||||
if ( m_mTree[vFirst[p]].m_nFlag2 == 0) {
|
||||
nCell = vFirst[p] ;
|
||||
if ( ! m_bClosed) {
|
||||
// se non ho vicini a sinistra sono tornato sul lato sinistro e quindi devo procedere alla cella più bassa non processata sul lato sinistro
|
||||
if ( vNeigh.empty()) {
|
||||
for ( int p = 0 ; p < (int)vFirst.size() ; ++ p) {
|
||||
if ( m_mTree[vFirst[p]].m_nFlag2 == 0) {
|
||||
nCell = vFirst[p] ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if ( nCell == nLastLeft && m_mTree[nCell].IsProcessed()) {
|
||||
bAllDone = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if ( nCell == nLastLeft && m_mTree[nCell].IsProcessed()) {
|
||||
// categorizzo
|
||||
m_mTree[nCell].m_nFlag2 = 1 ;
|
||||
CategorizeCell( nCell) ;
|
||||
bAllDone = true ;
|
||||
break ;
|
||||
}
|
||||
else {
|
||||
// verifico se sono tornato sul lato sinistro, in questo caso procedo con la prima cella di vFirst non processata
|
||||
if ( m_mTree[nCell].m_bOnLeftEdge) {
|
||||
for ( int p = 0 ; p < (int) vFirst.size(); ++ p) {
|
||||
if ( nCell == vFirst[p] && nCell != nLastLeft) {
|
||||
nCell = vFirst[p + 1] ;
|
||||
break ;
|
||||
}
|
||||
else if ( nCell == nLastLeft && m_mTree[nCell].IsProcessed()){
|
||||
bAllDone = true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( bAllDone)
|
||||
break ;
|
||||
}
|
||||
// controllo se tutti i vicini di destra sono categorizzati
|
||||
vNeigh.clear() ;
|
||||
@@ -2887,7 +3002,7 @@ Tree::AddVertex( const int& nId, const std::vector<PNTVECTOR>& vEdgeVertex, Poly
|
||||
return true ;
|
||||
}
|
||||
|
||||
//usando i poligoni
|
||||
//usando i poligoni // deprecato e non funzionante
|
||||
////----------------------------------------------------------------------------
|
||||
//bool
|
||||
//Tree::SetRightEdgeIn( int nId, std::vector<PNTVECTOR>& vEdgeVertex, PolyLine& plTrimmedPoly)
|
||||
@@ -2959,6 +3074,10 @@ Tree::SetRightEdgeIn( const int& nId)
|
||||
// categorizzo la cella in base a quanta parte del lato destro è conenuta all'interno delle curve di trim
|
||||
// RightEdgeIn -> 0 non contenuto ; 1 contenuto ; 2 in parte contenuto
|
||||
int nPass = (int) m_mTree[nId].m_vInters.size() ;
|
||||
if ( nPass == 0 ) {
|
||||
m_mTree[nId].m_nRightEdgeIn = 0 ;
|
||||
return true ;
|
||||
}
|
||||
bool bDone = false ;
|
||||
// se ho solo loop interni devo controllare se il più esterno è CCW ( lato destro esterno) o CW ( lato destro interno)
|
||||
if ( m_mTree[nId].m_nFlag == 2) {
|
||||
|
||||
@@ -76,6 +76,15 @@ struct Inters {
|
||||
//----------------------------------------------------------------------------
|
||||
class Cell
|
||||
{
|
||||
// Edge 0 ( Top)
|
||||
// Edge 4 ( NW) __________________ Edge 7 ( NE)
|
||||
// | |
|
||||
// | |
|
||||
// Edge 1 ( Left) | | Edge 3 ( Right)
|
||||
// | |
|
||||
// | |
|
||||
// |_________________|
|
||||
// Edge 5 ( SW) Edge 2 (Bottom) Edge 6 ( SE)
|
||||
public :
|
||||
~Cell( void) ;
|
||||
Cell( void) ;
|
||||
@@ -110,7 +119,8 @@ class Cell
|
||||
// 0 esterna, 1 intersecata, 2 contiene un loop, 3 intersecata e contenente un loop, 4 contenuta in un loop
|
||||
int m_nFlag2 ; // falg che indica se la cella è stata attraversata durante l'ultima fase del labelling
|
||||
int m_nRightEdgeIn ; // 0 right edge fuori, 1 right edge dentro, 2 metà e metà
|
||||
std::vector<Inters> m_vInters ; // vettore delle intersezioni della cella con i loop di trim
|
||||
bool m_bOnLeftEdge ; // flag che indica se la cella è sul lato sinistro ( per superfici chiuse)
|
||||
std::vector<Inters> m_vInters ; // vettore delle intersezioni della cella con i loop di trim
|
||||
// ogni elemento del vettore è l'insieme dei punti che caratterizza un atrtaversamento della cella
|
||||
|
||||
private :
|
||||
@@ -128,7 +138,7 @@ public :
|
||||
Tree( void) ;
|
||||
Tree ( const SurfBezier* pSrfBz, const bool bSplitPatches = true, const Point3d ptMin = ORIG, const Point3d ptMax = ORIG) ;
|
||||
void SetSurf( const SurfBezier* pSrfBz, const bool bSplitPatches = true, const Point3d ptMin = ORIG, const Point3d ptMax = ORIG) ;
|
||||
bool GetIndependentTrees( std::vector<std::tuple<Point3d,Point3d>>& vTrees) ;
|
||||
bool GetIndependentTrees( std::vector<std::tuple<Point3d,Point3d>>& vTrees) ; // calcolo la suddivisione della superficie solo sulle singole bbox dei loop di trim ( unendo quelli vicini)
|
||||
bool BuildTree( const double& dLinTol = LIN_TOL_STD, const double& dSideMin = 1, const double& dSideMax = INFINITO) ; // dSideMax è il massimo per la dimensione maggiore di un triangolo della trimesh
|
||||
// dSideMin è lunghezza minima del lato di una cella nello spazio reale
|
||||
bool BuildTree_test( const double& dLinTol = LIN_TOL_STD, const double& dSideMin = 1, const double& dSideMax = INFINITO) ;
|
||||
|
||||
Reference in New Issue
Block a user