EgftGeomKernel :
- sistemati i bug noti - pulito il codice Da aggiungere : - calcolo del tree solo nelle bbox delle curve di trim
This commit is contained in:
@@ -115,19 +115,46 @@ Tree::SetSurf( const SurfBezier* pSrfBz, const bool bSplitPatches)
|
||||
// recupero la superficie di trim per avere accesso diretto ai loop e mantenendo le informazioni sui chunk
|
||||
Frame3d frSurf ;
|
||||
PtrOwner<SurfFlatRegion> pTrimReg( m_pSrfBz->GetTrimRegion()->Clone()) ;
|
||||
double dLinTol = 0.01 ; // questo è riferito allo spazio parametrico perché le curve di loop sono già state riscalate!!!!!!
|
||||
double dAngTolDeg = 5 ;
|
||||
for ( int i = 0 ; i < pTrimReg->GetChunkCount() ; ++ i) {
|
||||
PtrOwner<SurfFlatRegion> pChunk( pTrimReg->CloneChunk( i)) ;
|
||||
for ( int j = 0 ; j < pChunk->GetLoopCount( 0) ; ++ j) {
|
||||
vChunk.push_back( nLoop) ;
|
||||
// i chunk della superficie orignale non possono avere dei sub chunk
|
||||
// i chunk della falt region sono ancora flat region composte da 1 chunk
|
||||
PtrOwner<ICurve> pLoop ( pChunk->GetLoop( 0, j)) ;
|
||||
PtrOwner<ICurve> pCrv( pLoop->Clone()) ;
|
||||
m_vLoop.emplace_back( Release( pLoop)) ;
|
||||
m_mChunk[nLoop] = i ;
|
||||
++ nLoop ;
|
||||
// approssimo i loop di trim con delle spezzate
|
||||
PolyLine plApprox ;
|
||||
int nType = 0 ;
|
||||
pCrv->ApproxWithLines( dLinTol,dAngTolDeg, nType, plApprox) ;
|
||||
// calcolo se il loop è CCW o CW
|
||||
double dArea ;
|
||||
Plane3d plExtPlane ;
|
||||
bool bCCW ;
|
||||
plApprox.IsClosedAndFlat( plExtPlane, dArea, 50 * EPS_SMALL) ;
|
||||
if ( plExtPlane.GetVersN().z > 0)
|
||||
bCCW = true ;
|
||||
else
|
||||
bCCW = false ;
|
||||
m_vPlApprox.push_back( std::tuple<PolyLine,bool>(plApprox,bCCW)) ;
|
||||
}
|
||||
// li riordino dal più grande al più piccolo
|
||||
std::sort(vChunk.begin(), vChunk.end(), [this]( const int& a, const int& b) { double dArea1, dArea2 ;
|
||||
m_vLoop[a]->GetAreaXY( dArea1) ;
|
||||
m_vLoop[b]->GetAreaXY( dArea2) ;
|
||||
return dArea1 > dArea2 ;}) ;
|
||||
m_vChunk.push_back( vChunk) ;
|
||||
vChunk.clear() ;
|
||||
}
|
||||
// li riordino dal più grande al più piccolo
|
||||
std::sort(m_vChunk.begin(), m_vChunk.end(), [this]( const INTVECTOR& a, const INTVECTOR& b) { double dArea1, dArea2 ;
|
||||
m_vLoop[a[0]]->GetAreaXY( dArea1) ;
|
||||
m_vLoop[b[0]]->GetAreaXY( dArea2) ;
|
||||
return dArea1 > dArea2 ;}) ;
|
||||
}
|
||||
// salvo i vertici 3d della cella root
|
||||
Point3d ptBottom ( 0, 0) ;
|
||||
@@ -350,7 +377,7 @@ Tree::Split( const int& nId)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Tree::BuildTree_test( double dLinTol_, double dSideMin, double dSideMax)
|
||||
Tree::BuildTree_test( const double& dLinTol, const double& dSideMin, const double& dSideMax)
|
||||
{
|
||||
//int nCToSplit = -1 ;
|
||||
//celle 0,1
|
||||
@@ -410,337 +437,328 @@ Tree::BuildTree_test( double dLinTol_, double dSideMin, double dSideMax)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
|
||||
Tree::BuildTree( const double& dLinTol, const double& dSideMin, const double& dSideMax)
|
||||
{
|
||||
// suddivido lo spazio parametrico con divisioni a metà su uno dei due parametri
|
||||
// suddivido lo spazio parametrico con divisioni a metà su uno dei due parametri
|
||||
int nCToSplit = -1 ;
|
||||
//double dLinTol = 0.2 ;
|
||||
//double dSideMin = 1 ;
|
||||
if ( ! m_bTrimmed || m_bTrimmed) {
|
||||
if ( ! m_bBilinear) {
|
||||
while ( nCToSplit != -2 && m_mTree[nCToSplit].IsProcessed() == false) {
|
||||
// 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 dCurvU = 0, dCurvV = 0 ;
|
||||
double dLenParU = ( m_mTree[nCToSplit].GetTopRight().x - m_mTree[nCToSplit].GetBottomLeft().x) / SBZ_TREG_COEFF ;
|
||||
double dLenParV = ( m_mTree[nCToSplit].GetTopRight().y - m_mTree[nCToSplit].GetBottomLeft().y) / SBZ_TREG_COEFF ;
|
||||
if ( dLenParU <= 1. / m_nDegV || dLenParV <= 1. / m_nDegU) {
|
||||
double dU = ( m_mTree[nCToSplit].GetTopRight().x + m_mTree[nCToSplit].GetBottomLeft().x) / 2 / SBZ_TREG_COEFF ;
|
||||
if ( ! m_bBilinear) {
|
||||
while ( nCToSplit != -2 && m_mTree[nCToSplit].IsProcessed() == false) {
|
||||
// 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 dCurvU = 0, dCurvV = 0 ;
|
||||
double dLenParU = ( m_mTree[nCToSplit].GetTopRight().x - m_mTree[nCToSplit].GetBottomLeft().x) / SBZ_TREG_COEFF ;
|
||||
double dLenParV = ( m_mTree[nCToSplit].GetTopRight().y - m_mTree[nCToSplit].GetBottomLeft().y) / SBZ_TREG_COEFF ;
|
||||
if ( dLenParU <= 1. / m_nDegV || dLenParV <= 1. / m_nDegU) {
|
||||
double dU = ( m_mTree[nCToSplit].GetTopRight().x + m_mTree[nCToSplit].GetBottomLeft().x) / 2 / SBZ_TREG_COEFF ;
|
||||
double dV = ( m_mTree[nCToSplit].GetTopRight().y + m_mTree[nCToSplit].GetBottomLeft().y) / 2 / SBZ_TREG_COEFF ;
|
||||
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 / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00P10) ;
|
||||
m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10P11) ;
|
||||
m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetTopRight().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11P01) ;
|
||||
m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01P00) ;
|
||||
Point3d ptV = ( 1 - dULoc) * ptP00P10 + dULoc * ptP11P01 ;
|
||||
Point3d ptU = ( 1 - dVLoc) * ptP10P11 + dVLoc * ptP01P00 ;
|
||||
dCurvV = Dist( ptV, ptPSrf) ;
|
||||
dCurvU = Dist( ptU, ptPSrf) ;
|
||||
}
|
||||
// faccio un'analisi più fine della curvatura se almeno il grado di una curva di uno dei due parametri è alto e
|
||||
// se sto ancora guardando una cella abbastanza grande
|
||||
else{
|
||||
Point3d ptPSrf, ptP00P10, ptP10P11, ptP11P01, ptP01P00, ptPSrfMid ;
|
||||
double dStep = 1. / m_nDegU ;
|
||||
for ( double k = dStep ; k < 1 ; k = k + dStep) {
|
||||
double dU = ( k * m_mTree[nCToSplit].GetTopRight().x + ( 1 - k) * m_mTree[nCToSplit].GetBottomLeft().x) / SBZ_TREG_COEFF ;
|
||||
double dV = ( m_mTree[nCToSplit].GetTopRight().y + m_mTree[nCToSplit].GetBottomLeft().y) / 2 / SBZ_TREG_COEFF ;
|
||||
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) ;
|
||||
if ( k == 0.5)
|
||||
ptPSrfMid = ptPSrf ;
|
||||
m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetBottomLeft().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00P10) ;
|
||||
m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10P11) ;
|
||||
m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetTopRight().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11P01) ;
|
||||
m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01P00) ;
|
||||
Point3d ptV = ( 1 - dULoc) * ptP00P10 + dULoc * ptP11P01 ;
|
||||
Point3d ptU = ( 1 - dVLoc) * ptP10P11 + dVLoc * ptP01P00 ;
|
||||
dCurvV = Dist( ptV, ptPSrf) ;
|
||||
dCurvU = Dist( ptU, ptPSrf) ;
|
||||
CurveLine clV ;
|
||||
clV.Set( ptP00P10, ptP11P01) ;
|
||||
DistPointCurve dpc( ptPSrf, clV) ;
|
||||
double dDist ;
|
||||
dpc.GetDist( dDist) ;
|
||||
dCurvV = std::max( dCurvV, dDist) ;
|
||||
}
|
||||
// faccio un'analisi più fine della curvatura se almeno il grado di una curva di uno dei due parametri è alto e
|
||||
// se sto ancora guardando una cella abbastanza grande
|
||||
else{
|
||||
Point3d ptPSrf, ptP00P10, ptP10P11, ptP11P01, ptP01P00, ptPSrfMid ;
|
||||
double dStep = 1. / m_nDegU ;
|
||||
for ( double k = dStep ; k < 1 ; k = k + dStep) {
|
||||
double dU = ( k * m_mTree[nCToSplit].GetTopRight().x + ( 1 - k) * m_mTree[nCToSplit].GetBottomLeft().x) / SBZ_TREG_COEFF ;
|
||||
double dV = ( m_mTree[nCToSplit].GetTopRight().y + m_mTree[nCToSplit].GetBottomLeft().y) / 2 / SBZ_TREG_COEFF ;
|
||||
dStep = 1. / m_nDegV ;
|
||||
for ( double k = dStep ; k < 1 ; k = k + dStep) {
|
||||
double dU = ( m_mTree[nCToSplit].GetTopRight().x + m_mTree[nCToSplit].GetBottomLeft().x) / 2 / SBZ_TREG_COEFF ;
|
||||
double dV = ( k * m_mTree[nCToSplit].GetTopRight().y + ( 1 - k) * m_mTree[nCToSplit].GetBottomLeft().y) / SBZ_TREG_COEFF ;
|
||||
if ( k == 0.5)
|
||||
ptPSrf = ptPSrfMid ;
|
||||
else
|
||||
m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ;
|
||||
if ( k == 0.5)
|
||||
ptPSrfMid = ptPSrf ;
|
||||
m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetBottomLeft().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00P10) ;
|
||||
m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetTopRight().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11P01) ;
|
||||
CurveLine clV ;
|
||||
clV.Set( ptP00P10, ptP11P01) ;
|
||||
DistPointCurve dpc( ptPSrf, clV) ;
|
||||
double dDist ;
|
||||
dpc.GetDist( dDist) ;
|
||||
dCurvV = std::max( dCurvV, dDist) ;
|
||||
}
|
||||
dStep = 1. / m_nDegV ;
|
||||
for ( double k = dStep ; k < 1 ; k = k + dStep) {
|
||||
double dU = ( m_mTree[nCToSplit].GetTopRight().x + m_mTree[nCToSplit].GetBottomLeft().x) / 2 / SBZ_TREG_COEFF ;
|
||||
double dV = ( k * m_mTree[nCToSplit].GetTopRight().y + ( 1 - k) * m_mTree[nCToSplit].GetBottomLeft().y) / SBZ_TREG_COEFF ;
|
||||
if ( k == 0.5)
|
||||
ptPSrf = ptPSrfMid ;
|
||||
else
|
||||
m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ;
|
||||
m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10P11) ;
|
||||
m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01P00) ;
|
||||
CurveLine clU ;
|
||||
clU.Set( ptP01P00, ptP10P11) ;
|
||||
DistPointCurve dpc( ptPSrf, clU) ;
|
||||
double dDist ;
|
||||
dpc.GetDist( dDist) ;
|
||||
dCurvU = std::max( dCurvU, dDist) ;
|
||||
}
|
||||
m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10P11) ;
|
||||
m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01P00) ;
|
||||
CurveLine clU ;
|
||||
clU.Set( ptP01P00, ptP10P11) ;
|
||||
DistPointCurve dpc( ptPSrf, clU) ;
|
||||
double dDist ;
|
||||
dpc.GetDist( dDist) ;
|
||||
dCurvU = std::max( dCurvU, dDist) ;
|
||||
}
|
||||
}
|
||||
|
||||
// per lo split scelgo la direzione che è più vicina alla superficie originale nel punto di maggior distanza
|
||||
// misura approssimativa della curvatura in una direzione
|
||||
bool bVert ;
|
||||
if ( dCurvV > dCurvU) {
|
||||
// lungo la direzione V ho una curvatura maggiore
|
||||
bVert = false ;
|
||||
// per lo split scelgo la direzione che è più vicina alla superficie originale nel punto di maggior distanza
|
||||
// misura approssimativa della curvatura in una direzione
|
||||
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 = std::max( dLen0, dLen2) ;
|
||||
else
|
||||
dSideMinVal = std::max( dLen0, dLen2) ;
|
||||
}
|
||||
else {
|
||||
if ( dLen1 != 0 && dLen3 != 0)
|
||||
dSideMinVal = std::max( dLen1, dLen3) ;
|
||||
else
|
||||
dSideMinVal = std::max( dLen1, dLen3) ;
|
||||
}
|
||||
// calcolo le diagonali per controllare la dimensione massima dei triangoli in cui dividerei la cella
|
||||
dSideMaxVal = std::max( Dist( ptP00, ptP11), Dist( ptP10, ptP01)) ;
|
||||
|
||||
// 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)) {
|
||||
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) {
|
||||
double dU = double ( u) / double ( nStepsU - 1) ;
|
||||
double dULoc = ( ( 1 - dU) * m_mTree[nCToSplit].GetBottomLeft().x + dU * m_mTree[nCToSplit].GetTopRight().x) / SBZ_TREG_COEFF ;
|
||||
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) ;
|
||||
clV.Set( pt0010, pt0111) ;
|
||||
for ( int v = 0 ; v < nStepsV ; ++ v) {
|
||||
double dV = double ( v) / double ( nStepsV - 1) ;
|
||||
double dVLoc = ( ( 1 - dV) * m_mTree[nCToSplit].GetBottomLeft().y + dV * m_mTree[nCToSplit].GetTopRight().y) / SBZ_TREG_COEFF ;
|
||||
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 > dLinTol) {
|
||||
bSplit = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// lungo la direzione U ho una curvatura maggiore
|
||||
}
|
||||
|
||||
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].SetProcessed() ;
|
||||
// risalgo i parent finché non trovo il primo Child2 da processare
|
||||
nCToSplit = m_mTree[nCToSplit].m_nParent ;
|
||||
if ( nCToSplit == -2)
|
||||
return true ;
|
||||
if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
|
||||
m_mTree[nCToSplit].SetProcessed() ;
|
||||
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].SetProcessed() ;
|
||||
if ( nCToSplit == -1 && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
|
||||
break ;
|
||||
}
|
||||
nCToSplit = m_mTree[nCToSplit].m_nChild2 ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
nCToSplit = m_mTree[nCToSplit].m_nChild1 ;
|
||||
}
|
||||
}
|
||||
Balance() ; // da implementare quando dividerò ad un parametro a scelta e non a metà
|
||||
}
|
||||
// bilineare
|
||||
else {
|
||||
while ( nCToSplit != -2 && m_mTree[nCToSplit].IsProcessed() == false) {
|
||||
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) ;
|
||||
|
||||
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 ;
|
||||
PNTVECTOR vPtU, vPtV ;
|
||||
if ( ! m_bMulti) {
|
||||
if ( std::max( dLen0, dLen2) > std::max( dLen1, dLen3)) {
|
||||
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 = std::max( dLen0, dLen2) ;
|
||||
else
|
||||
dSideMinVal = std::max( dLen0, dLen2) ;
|
||||
}
|
||||
else {
|
||||
if ( dLen1 != 0 && dLen3 != 0)
|
||||
dSideMinVal = std::max( dLen1, dLen3) ;
|
||||
else
|
||||
dSideMinVal = std::max( dLen1, dLen3) ;
|
||||
}
|
||||
// calcolo le diagonali per controllare la dimensione massima dei triangoli in cui dividerei la cella
|
||||
dSideMaxVal = std::max( Dist( ptP00, ptP11), Dist( ptP10, ptP01)) ;
|
||||
|
||||
// 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)) {
|
||||
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) {
|
||||
double dU = double ( u) / double ( nStepsU - 1) ;
|
||||
double dULoc = ( ( 1 - dU) * m_mTree[nCToSplit].GetBottomLeft().x + dU * m_mTree[nCToSplit].GetTopRight().x) / SBZ_TREG_COEFF ;
|
||||
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) ;
|
||||
clV.Set( pt0010, pt0111) ;
|
||||
for ( int v = 0 ; v < nStepsV ; ++ v) {
|
||||
double dV = double ( v) / double ( nStepsV - 1) ;
|
||||
double dVLoc = ( ( 1 - dV) * m_mTree[nCToSplit].GetBottomLeft().y + dV * m_mTree[nCToSplit].GetTopRight().y) / SBZ_TREG_COEFF ;
|
||||
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 > dLinTol) {
|
||||
bSplit = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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].SetProcessed() ;
|
||||
// risalgo i parent finché non trovo il primo Child2 da processare
|
||||
nCToSplit = m_mTree[nCToSplit].m_nParent ;
|
||||
if ( nCToSplit == -2)
|
||||
return true ;
|
||||
if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
|
||||
m_mTree[nCToSplit].SetProcessed() ;
|
||||
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].SetProcessed() ;
|
||||
if ( nCToSplit == -1 && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
|
||||
break ;
|
||||
}
|
||||
nCToSplit = m_mTree[nCToSplit].m_nChild2 ;
|
||||
bVert = false ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
nCToSplit = m_mTree[nCToSplit].m_nChild1 ;
|
||||
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) / SBZ_TREG_COEFF ;
|
||||
dV = ( ( 1 - i) * m_mTree[nCToSplit].GetBottomLeft().y + i * m_mTree[nCToSplit].GetTopRight().y) / SBZ_TREG_COEFF ;
|
||||
double dVLoc = ( m_mTree[nCToSplit].GetBottomLeft().y + m_mTree[nCToSplit].GetTopRight().y) / 2 / SBZ_TREG_COEFF ;
|
||||
double dULoc = ( m_mTree[nCToSplit].GetBottomLeft().x + m_mTree[nCToSplit].GetTopRight().x) / 2 / SBZ_TREG_COEFF ;
|
||||
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 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
Balance() ; // da implementare quando dividerò ad un parametro a scelta e non a metà
|
||||
}
|
||||
// bilineare
|
||||
else {
|
||||
while ( nCToSplit != -2 && m_mTree[nCToSplit].IsProcessed() == false) {
|
||||
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) ;
|
||||
|
||||
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 ;
|
||||
PNTVECTOR vPtU, vPtV ;
|
||||
if ( ! m_bMulti) {
|
||||
if ( std::max( dLen0, dLen2) > std::max( dLen1, dLen3)) {
|
||||
bVert = true ;
|
||||
}
|
||||
else {
|
||||
bVert = false ;
|
||||
}
|
||||
}
|
||||
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) / SBZ_TREG_COEFF ;
|
||||
dV = ( ( 1 - i) * m_mTree[nCToSplit].GetBottomLeft().y + i * m_mTree[nCToSplit].GetTopRight().y) / SBZ_TREG_COEFF ;
|
||||
double dVLoc = ( m_mTree[nCToSplit].GetBottomLeft().y + m_mTree[nCToSplit].GetTopRight().y) / 2 / SBZ_TREG_COEFF ;
|
||||
double dULoc = ( m_mTree[nCToSplit].GetBottomLeft().x + m_mTree[nCToSplit].GetTopRight().x) / 2 / SBZ_TREG_COEFF ;
|
||||
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 = std::max( dLen0, dLen2) ;
|
||||
else
|
||||
dSideMinVal = std::max( dLen0, dLen2) ;
|
||||
}
|
||||
else {
|
||||
if ( dLen1 != 0 && dLen3 != 0)
|
||||
dSideMinVal = std::max( dLen1, dLen3) ;
|
||||
else
|
||||
dSideMinVal = std::max( dLen1, dLen3) ;
|
||||
}
|
||||
// calcolo le diagonali per controllare la dimensione massima dei triangoli in cui dividerei la cella
|
||||
dSideMaxVal = std::max( Dist( ptP00, ptP11), Dist( ptP10, ptP01)) ;
|
||||
// verifico che la cella sia abbastanza grande da poter essere splittata
|
||||
double dSideMinVal = 0, dSideMaxVal = 0 ;
|
||||
if ( bVert) {
|
||||
if ( dLen0 != 0 && dLen2 != 0)
|
||||
dSideMinVal = std::max( dLen0, dLen2) ;
|
||||
else
|
||||
dSideMinVal = std::max( dLen0, dLen2) ;
|
||||
}
|
||||
else {
|
||||
if ( dLen1 != 0 && dLen3 != 0)
|
||||
dSideMinVal = std::max( dLen1, dLen3) ;
|
||||
else
|
||||
dSideMinVal = std::max( dLen1, dLen3) ;
|
||||
}
|
||||
// calcolo le diagonali per controllare la dimensione massima dei triangoli in cui dividerei la cella
|
||||
dSideMaxVal = std::max( Dist( ptP00, ptP11), Dist( ptP10, ptP01)) ;
|
||||
|
||||
|
||||
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) / SBZ_TREG_COEFF ;
|
||||
double dV = ( ( 1 - j) * m_mTree[nCToSplit].GetTopRight().y + j * m_mTree[nCToSplit].GetBottomLeft().y) / SBZ_TREG_COEFF ;
|
||||
m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ;
|
||||
dErr = std::max( abs( DistPointPlane( ptPSrf, plAppr)), dErr) ;
|
||||
}
|
||||
}
|
||||
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 {
|
||||
dErr = 1. / 4. * ( ( ptP00 - ptP01) + ( ptP11 - ptP10)).Len() ;
|
||||
else if ( AreSamePointApprox( ptP00, ptP01)) {
|
||||
plAppr.Set( ptP10, ( ptP10 - ptP11) ^ ( ptP00 - ptP10)) ;
|
||||
}
|
||||
// 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].SetProcessed() ;
|
||||
// risalgo i parent finché non trovo il primo Child2 da processare
|
||||
nCToSplit = m_mTree[nCToSplit].m_nParent ;
|
||||
if ( nCToSplit == -2)
|
||||
return true ;
|
||||
if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
|
||||
m_mTree[nCToSplit].SetProcessed() ;
|
||||
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].SetProcessed() ;
|
||||
if ( nCToSplit == -1 && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
|
||||
break ;
|
||||
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) / SBZ_TREG_COEFF ;
|
||||
double dV = ( ( 1 - j) * m_mTree[nCToSplit].GetTopRight().y + j * m_mTree[nCToSplit].GetBottomLeft().y) / SBZ_TREG_COEFF ;
|
||||
m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ;
|
||||
dErr = std::max( abs( DistPointPlane( ptPSrf, plAppr)), dErr) ;
|
||||
}
|
||||
nCToSplit = m_mTree[nCToSplit].m_nChild2 ;
|
||||
}
|
||||
}
|
||||
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].SetProcessed() ;
|
||||
// risalgo i parent finché non trovo il primo Child2 da processare
|
||||
nCToSplit = m_mTree[nCToSplit].m_nParent ;
|
||||
if ( nCToSplit == -2)
|
||||
return true ;
|
||||
if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
|
||||
m_mTree[nCToSplit].SetProcessed() ;
|
||||
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].SetProcessed() ;
|
||||
if ( nCToSplit == -1 && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed())
|
||||
break ;
|
||||
}
|
||||
nCToSplit = m_mTree[nCToSplit].m_nChild2 ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
nCToSplit = m_mTree[nCToSplit].m_nChild1 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// NON IMPLEMENTATO
|
||||
// se la superficie è trimmata creo l'albero solo all'interno dei bbox delle curve di trim ( se ho solo trim CW allora tengo il bordo)
|
||||
else {
|
||||
SurfFlatRegion sfrTrimReg ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -1225,7 +1243,7 @@ Tree::GetPolygons( std::vector<POLYLINEVECTOR>& vPolygons) {
|
||||
int nPoly = 0 ;
|
||||
// scorro sui vettori intersezione della cella nId e sui suoi vertici
|
||||
// in questo for analizzo solo i loop che tagliano la cella
|
||||
while( nPoly == 0 || (int)vToCheck.size() != 0) {
|
||||
while( (int)vToCheck.size() != 0) {
|
||||
int nPolyBefore = nPoly ;
|
||||
CreateCellPolygons( i, vPolygons, vToCheck, nPoly, vnParentChunk, vPolygonsBasic[i]) ;
|
||||
if ( nPolyBefore == nPoly)
|
||||
@@ -1455,35 +1473,15 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells
|
||||
bool
|
||||
Tree::TraceLoopLabelCell( void)
|
||||
{
|
||||
// approssimo i loop di trim con delle spezzate
|
||||
POLYLINEVECTOR vPlApprox ;
|
||||
for ( int p = 0 ; p < (int) m_vLoop.size() ; ++ p){
|
||||
PtrOwner<ICurve> pCrv( m_vLoop[p]->Clone()) ;
|
||||
double dLinTol = 0.01 ; // questo è riferito allo spazio parametrico perché le curve di loop sono già state riscalate!!!!!!
|
||||
double dAngTolDeg = 5 ;
|
||||
PolyLine plApprox ;
|
||||
int nType = 0 ;
|
||||
pCrv->ApproxWithLines( dLinTol,dAngTolDeg, nType, plApprox) ;
|
||||
vPlApprox.push_back( plApprox) ;
|
||||
}
|
||||
// ora le curve di trim hanno lo stesso indice delle loro corrispondenti spezzate nel vettore vPlApprox
|
||||
|
||||
double dLinTol = - EPS_SMALL ; // questo è riferito allo spazio parametrico, quando è già stato riporatato al range 0..1 !!!!!!
|
||||
// il valore è negativo perché voglio considerare contenuto anche un punto che sta su un lato
|
||||
POLYLINEVECTOR vplPolygons ;
|
||||
GetPolygonsBasic( vplPolygons) ;
|
||||
// percorro i loop trovando le interezioni con le celle e riempiendo i vettori m_vInters delle varie celle
|
||||
for ( int i = 0 ; i < (int) vPlApprox.size() ; ++ i) {
|
||||
PolyLine plLoop = vPlApprox[i] ;
|
||||
// calcolo se il loop è CCW o Cw
|
||||
double dArea ;
|
||||
Plane3d plExtPlane ;
|
||||
bool bCCW ;
|
||||
plLoop.IsClosedAndFlat( plExtPlane, dArea, 50 * EPS_SMALL) ;
|
||||
if ( plExtPlane.GetVersN().z > 0)
|
||||
bCCW = true ;
|
||||
else
|
||||
bCCW = false ;
|
||||
for ( int i = 0 ; i < (int) m_vPlApprox.size() ; ++ i) {
|
||||
PolyLine plLoop = std::get<0>(m_vPlApprox[i]) ;
|
||||
// calcolo se il loop è CCW o CW
|
||||
bool bCCW = std::get<1>(m_vPlApprox[i]) ;
|
||||
// trovo in quale cella è il ptStart
|
||||
Point3d ptStart ;
|
||||
plLoop.GetFirstPoint( ptStart) ;
|
||||
@@ -1514,11 +1512,11 @@ Tree::TraceLoopLabelCell( void)
|
||||
INTVECTOR :: iterator iter = find( m_vnLeaves.begin(), m_vnLeaves.end(), nId) ;
|
||||
int nIdPolygon = std::distance( m_vnLeaves.begin(), iter) ;
|
||||
bool bEraseNextPoint = false ;
|
||||
// per debug
|
||||
int c = 0 ;
|
||||
//// per debug
|
||||
//int c = 0 ;
|
||||
Cell cUnderWork ;
|
||||
while ( plLoop.GetNextPoint( ptCurr)) {
|
||||
++ c ;
|
||||
//++ c ;
|
||||
// sto uscendo dalla cella, quindi cerco l'intersezione
|
||||
Point3d ptTStart, ptTEnd ;
|
||||
plLoop.GetPrevPoint( ptTStart) ;
|
||||
@@ -1536,7 +1534,6 @@ Tree::TraceLoopLabelCell( void)
|
||||
// al precedente FindInters avrei dovuto passare di cella
|
||||
if ( ! FindInters( nId, clTrim, vptInters, true)) {
|
||||
// scarterò il punto molto vicino al lato e tengo solo l'intersezione del trim col lato
|
||||
//m_mTree[nId].m_vInters.back().vpt.pop_back() ;
|
||||
vptInters.pop_back() ;
|
||||
plLoop.GetPrevPoint( ptTEnd) ;
|
||||
plLoop.GetPrevPoint( ptTStart) ;
|
||||
@@ -1544,8 +1541,7 @@ Tree::TraceLoopLabelCell( void)
|
||||
clTrim.Set( ptTStart, ptTEnd) ;
|
||||
clTrim.ExtendEndByLen( EPS_SMALL * 2) ;
|
||||
clTrim.ExtendStartByLen( EPS_SMALL * 2) ;
|
||||
//vptInters.clear() ;
|
||||
if ( FindInters( nId, clTrim, vptInters, true))
|
||||
if ( ! FindInters( nId, clTrim, vptInters, true))
|
||||
return false ;
|
||||
bEraseNextPoint = true ;
|
||||
}
|
||||
@@ -2401,7 +2397,6 @@ Tree::CreateIslandAndHoles( const int& nLeafId, std::vector<POLYLINEVECTOR>& vPo
|
||||
// loop interni in una cella intersecata
|
||||
if ( m_mTree[nId].m_nFlag == 3 || m_mTree[nId].m_nFlag == 2) {
|
||||
PolyLine plInLoop ;
|
||||
// numero dei loop interni passati
|
||||
Inters inA ;
|
||||
// se ho almeno un loop CW che non è contenuto in un altro poligono o in un loop interno CCW devo aggiungere il bordo
|
||||
bool bAllContained = true ;
|
||||
@@ -2469,10 +2464,9 @@ Tree::CreateIslandAndHoles( const int& nLeafId, std::vector<POLYLINEVECTOR>& vPo
|
||||
plInLoop.GetFirstPoint( ptStart) ;
|
||||
int nOtherPoly = (int)vPolygons.size() ;
|
||||
for ( int r = 0 ; r < nPoly ; ++r) {
|
||||
if ( IsPointInsidePolyLine( ptStart, vPolygons[nOtherPoly - r - 1][0], -0.01) && vnParentChunk[nLoop - r - 1] == inA.nChunk) {
|
||||
if ( IsPointInsidePolyLine( ptStart, vPolygons[nOtherPoly - r - 1][0], -0.01) && vnParentChunk[nPoly - r - 1] == inA.nChunk) {
|
||||
vPolygons[nOtherPoly - r - 1].push_back( plInLoop) ;
|
||||
plInLoop.Clear() ;
|
||||
vnParentChunk.push_back( inA.nChunk) ;
|
||||
bAdded = true ;
|
||||
break ;
|
||||
}
|
||||
@@ -2676,7 +2670,7 @@ Tree::AddVertex( const int& nId, const std::vector<PNTVECTOR>& vEdgeVertex, Poly
|
||||
plTrimmedPoly.GetLastPoint( ptLast) ;
|
||||
// verifico di essere allineato con un lato, sennò aggiungo e basta
|
||||
Vector3d vDir ;
|
||||
if ( ! AreSamePointExact( ptToAdd, ptLast))
|
||||
if ( ! AreSamePointApprox( ptToAdd, ptLast))
|
||||
vDir = ptToAdd - ptLast ;
|
||||
else
|
||||
return true ;
|
||||
@@ -2691,6 +2685,8 @@ Tree::AddVertex( const int& nId, const std::vector<PNTVECTOR>& vEdgeVertex, Poly
|
||||
plTrimmedPoly.AddUPoint( c, ptTl) ;
|
||||
else if ( AreSamePointApprox( ptToAdd, ptBL))
|
||||
plTrimmedPoly.AddUPoint( c, ptBL) ;
|
||||
else
|
||||
plTrimmedPoly.AddUPoint( c, ptToAdd) ;
|
||||
++ c ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user