From 579bc5492c8f057417153e5c929a7932f46abbd3 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Tue, 6 Jun 2023 10:40:03 +0200 Subject: [PATCH] EgtGeomKernel : - sistemati vari bug nella creazione della superficie trimesh trimmata si una superficie di bezier Problemi noti : - sui casi con un tree reale genero dei poligoni sbagliati per le celle --- SurfBezier.cpp | 1 + Tree.cpp | 1065 +++++++++++++++++++++++++----------------------- Tree.h | 4 +- 3 files changed, 553 insertions(+), 517 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index b0fb6c6..cca23c6 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1500,6 +1500,7 @@ SurfBezier::GetAuxSurf( void) const // costruttore della superficie Tree Tree( this, true) ; + //Tree.BuildTree_test() ; Tree.BuildTree() ; vector vvPL ; Tree.GetPolygons( vvPL) ; diff --git a/Tree.cpp b/Tree.cpp index eaf7ffd..131e469 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -373,7 +373,7 @@ Tree::Split( int nId) //---------------------------------------------------------------------------- bool -Tree::BuildTree( double dLinTol_, double dSideMin, double dSideMax) +Tree::BuildTree_test( double dLinTol_, double dSideMin, double dSideMax) { //int nCToSplit = -1 ; //celle 0,1 @@ -409,336 +409,337 @@ Tree::BuildTree( double dLinTol_, double dSideMin, double dSideMax) return true ; } -////---------------------------------------------------------------------------- -//bool -//Tree::BuildTree( double dLinTol_, double dSideMin, double dSideMax) -//{ -// // 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) { -// 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 ; -// double dLenParV = m_mTree[nCToSplit].GetTopRight().y - m_mTree[nCToSplit].GetBottomLeft().y ; -// if ( dLenParU <= 1. / m_nDegV || dLenParV <= 1. / m_nDegU) { -// 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 ; -// 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 ; -// double dV = ( m_mTree[nCToSplit].GetTopRight().y + m_mTree[nCToSplit].GetBottomLeft().y) / 2 ; -// 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, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00P10) ; -// m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetTopRight().y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11P01) ; -// CurveLine clV ; -// clV.Set( ptP00P10, ptP11P01) ; -// DistPointCurve dpc( ptPSrf, clV) ; -// double dDist ; -// dpc.GetDist( dDist) ; -// dCurvV = 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 ; -// double dV = k * m_mTree[nCToSplit].GetTopRight().y + ( 1 - k) * m_mTree[nCToSplit].GetBottomLeft().y ; -// 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, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10P11) ; -// m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01P00) ; -// CurveLine clU ; -// clU.Set( ptP01P00, ptP10P11) ; -// DistPointCurve dpc( ptPSrf, clU) ; -// double dDist ; -// dpc.GetDist( dDist) ; -// dCurvU = 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 ; -// } -// 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 -// 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 ; -// 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) { -// double dV = double ( v) / double ( nStepsV - 1) ; -// double 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 > 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 ( 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 ( max(dLen0, dLen2) > 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 ; -// dV = ( 1 - i) * m_mTree[nCToSplit].GetBottomLeft().y + i * m_mTree[nCToSplit].GetTopRight().y ; -// double dVLoc = ( m_mTree[nCToSplit].GetBottomLeft().y + m_mTree[nCToSplit].GetTopRight().y) / 2 ; -// double 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)) ; -// -// -// 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].SetProcessed() ; -// // 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].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 ; -// } -// } -// } -// } -// // se la superficie è trimmata -// else { -// SurfFlatRegion sfrTrimReg ; -// } -// return true ; -//} +//---------------------------------------------------------------------------- +bool +Tree::BuildTree( double dLinTol_, double dSideMin, double dSideMax) +{ + // 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 ; + double dLenParV = m_mTree[nCToSplit].GetTopRight().y - m_mTree[nCToSplit].GetBottomLeft().y ; + if ( dLenParU <= 1. / m_nDegV || dLenParV <= 1. / m_nDegU) { + 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 ; + 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 ; + double dV = ( m_mTree[nCToSplit].GetTopRight().y + m_mTree[nCToSplit].GetBottomLeft().y) / 2 ; + 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, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00P10) ; + m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetTopRight().y, 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 ; + double dV = k * m_mTree[nCToSplit].GetTopRight().y + ( 1 - k) * m_mTree[nCToSplit].GetBottomLeft().y ; + 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, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10P11) ; + m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x, 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 ; + } + 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 ; + 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) { + double dV = double ( v) / double ( nStepsV - 1) ; + double 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 > 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 ( 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 ; + } + 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 ; + dV = ( 1 - i) * m_mTree[nCToSplit].GetBottomLeft().y + i * m_mTree[nCToSplit].GetTopRight().y ; + double dVLoc = ( m_mTree[nCToSplit].GetBottomLeft().y + m_mTree[nCToSplit].GetTopRight().y) / 2 ; + double 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 = 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 ; + 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 = std::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].SetProcessed() ; + // 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].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 ; +} //---------------------------------------------------------------------------- void @@ -1522,7 +1523,7 @@ Tree::TraceLoopLabelCell( void) } // ora le curve di trim hanno lo stesso indice delle loro corrispondenti spezzate nel vettore vPlApprox - double dLinTol = - 0.01 ; // questo è riferito allo spazio parametrico, quando è già stato riporatato al range 0..1 !!!!!! + 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) ; @@ -1879,7 +1880,10 @@ Tree::FindInters( int& nId, CurveLine& clTrim, PNTVECTOR& vptInters, bool& bVert m_mTree[nId].m_vInters.back().nOut = nEdge ; vptInters.push_back( ptInters) ; // salvo il vettore intersezione per la cella e capisco in quale altra cella passare - m_mTree[nId].m_vInters.back().vpt = vptInters ; // al posto di .vpt = vptInters metto un push_back //////////////////////////////////////////////// + if ( (int)vptInters.size() == 1) + m_mTree[nId].m_vInters.back().vpt.push_back( vptInters[0]) ; // al posto di .vpt = vptInters metto un push_back //////////////////////////////////////////////// + else + m_mTree[nId].m_vInters.back().vpt = vptInters ; vptInters.clear() ; // setto la categoria della cella if ( m_mTree[nId].m_nFlag == -1) @@ -1899,12 +1903,14 @@ Tree::FindInters( int& nId, CurveLine& clTrim, PNTVECTOR& vptInters, bool& bVert } m_mTree[nId].m_vInters.emplace_back() ; Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; - if ( ptInters.x > m_mTree[nId].GetBottomLeft().x && ptInters.x < m_mTree[nId].GetTopRight().x ) + if ( ptInters.x > m_mTree[nId].GetBottomLeft().x + EPS_SMALL && ptInters.x < m_mTree[nId].GetTopRight().x - EPS_SMALL) m_mTree[nId].m_vInters.back().nIn = 2 ; else if ( AreSamePointApprox( ptInters, m_mTree[nId].GetBottomLeft())) m_mTree[nId].m_vInters.back().nIn = 5 ; else if ( AreSamePointApprox( ptInters, ptBr)) m_mTree[nId].m_vInters.back().nIn = 6 ; + else + m_mTree[nId].m_vInters.back().nIn = 2 ; } else if ( nEdge == 1) { GetLeftNeigh( nId, vNeigh) ; @@ -1917,12 +1923,14 @@ Tree::FindInters( int& nId, CurveLine& clTrim, PNTVECTOR& vptInters, bool& bVert } m_mTree[nId].m_vInters.emplace_back() ; Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; - if ( ptInters.y > m_mTree[nId].GetBottomLeft().y && ptInters.y < m_mTree[nId].GetTopRight().y ) + if ( ptInters.y > m_mTree[nId].GetBottomLeft().y + EPS_SMALL && ptInters.y < m_mTree[nId].GetTopRight().y - EPS_SMALL) m_mTree[nId].m_vInters.back().nIn = 3 ; else if ( AreSamePointApprox( ptInters, ptBr)) m_mTree[nId].m_vInters.back().nIn = 6 ; else if ( AreSamePointApprox( ptInters, m_mTree[nId].GetTopRight())) m_mTree[nId].m_vInters.back().nIn = 7 ; + else + m_mTree[nId].m_vInters.back().nIn = 3 ; } else if ( nEdge == 2) { GetBottomNeigh( nId, vNeigh) ; @@ -1934,12 +1942,14 @@ Tree::FindInters( int& nId, CurveLine& clTrim, PNTVECTOR& vptInters, bool& bVert } m_mTree[nId].m_vInters.emplace_back() ; Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ; - if ( ptInters.x > m_mTree[nId].GetBottomLeft().x && ptInters.x < m_mTree[nId].GetTopRight().x ) + if ( ptInters.x > m_mTree[nId].GetBottomLeft().x + EPS_SMALL && ptInters.x < m_mTree[nId].GetTopRight().x - EPS_SMALL) m_mTree[nId].m_vInters.back().nIn = 0 ; else if ( AreSamePointApprox( ptInters, ptTl)) m_mTree[nId].m_vInters.back().nIn = 4 ; else if ( AreSamePointApprox( ptInters, m_mTree[nId].GetTopRight())) m_mTree[nId].m_vInters.back().nIn = 7 ; + else + m_mTree[nId].m_vInters.back().nIn = 0 ; } else if ( nEdge == 3) { GetRightNeigh( nId, vNeigh) ; @@ -1951,12 +1961,14 @@ Tree::FindInters( int& nId, CurveLine& clTrim, PNTVECTOR& vptInters, bool& bVert } m_mTree[nId].m_vInters.emplace_back() ; Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ; - if ( ptInters.y > m_mTree[nId].GetBottomLeft().y && ptInters.y < m_mTree[nId].GetTopRight().y ) + if ( ptInters.y > m_mTree[nId].GetBottomLeft().y + EPS_SMALL && ptInters.y < m_mTree[nId].GetTopRight().y - EPS_SMALL) m_mTree[nId].m_vInters.back().nIn = 1 ; else if ( AreSamePointApprox( ptInters, m_mTree[nId].GetBottomLeft())) m_mTree[nId].m_vInters.back().nIn = 5 ; else if ( AreSamePointApprox( ptInters, ptTl)) m_mTree[nId].m_vInters.back().nIn = 4 ; + else + m_mTree[nId].m_vInters.back().nIn = 1 ; } // esco da uno dei vertici else if ( nEdge == 4) { @@ -2153,6 +2165,7 @@ Tree::CreateCellPolygons( int nLeafId, std::vector& vPolygons, I int nEdgeIn = -1 ; int nFirstLoopInPoly = -1 ; for ( int w = 0 ; w < (int)vToCheckNow.size() ; ++ w) { + // primo loop di questo poligono int j = vToCheckNow[w] ; Inters inA = m_mTree[nId].m_vInters[j] ; if ( inA.nIn != -1 ) { @@ -2167,50 +2180,50 @@ Tree::CreateCellPolygons( int nLeafId, std::vector& vPolygons, I } nEdge = inA.nOut ; // se la curva è CW devo verifica di non essere uscito in un vertice, con un tratto sovrapposto al lato che ripercorrerò tra poco - if ( !inA.bCCW ) { - Point3d ptLast, ptSecondToLast; - plTrimmedPoly.GetLastPoint(ptLast) ; - plTrimmedPoly.GetPrevPoint(ptSecondToLast) ; - Vector3d vLast = ptLast - ptSecondToLast ; - vLast.Normalize(); - Vector3d vEdge ; - if ( AreSameEdge( nEdge, 0)) { - if ( AreSamePointApprox(ptLast, ptTl) ) { - vEdge = m_mTree[nId].GetBottomLeft() - ptTl ; - vEdge.Normalize() ; - if ( AreOppositeVectorApprox(vLast, vEdge) ) { - plTrimmedPoly.EraseLastUPoint() ; - nEdge = 1 ; - } - } - } - else if ( AreSameEdge( nEdge, 1) && AreSamePointApprox(ptLast, m_mTree[nId].GetBottomLeft()) ) { - vEdge = ptBr - m_mTree[nId].GetBottomLeft() ; + // qui ho tolto l'if e esteso anche ai casi CCW perché anche lì devo controllare!!!!!//////////////////////////////////////////////////////////// + Point3d ptLast, ptSecondToLast; + plTrimmedPoly.GetLastPoint(ptLast) ; + plTrimmedPoly.GetPrevPoint(ptSecondToLast) ; + Vector3d vLast = ptLast - ptSecondToLast ; + vLast.Normalize(); + Vector3d vEdge ; + if ( AreSameEdge( nEdge, 0)) { + if ( AreSamePointApprox(ptLast, ptTl) ) { + vEdge = m_mTree[nId].GetBottomLeft() - ptTl ; vEdge.Normalize() ; if ( AreOppositeVectorApprox(vLast, vEdge) ) { plTrimmedPoly.EraseLastUPoint() ; - nEdge = 2 ; - } - } - else if ( AreSameEdge( nEdge, 2) ) { - if ( AreSamePointApprox(ptLast, ptBr) ) { - vEdge = m_mTree[nId].GetTopRight() - ptBr ; - vEdge.Normalize() ; - if ( AreOppositeVectorApprox(vLast, vEdge) ) { - plTrimmedPoly.EraseLastUPoint() ; - nEdge = 3 ; - } - } - } - else if ( AreSameEdge( nEdge, 3) && AreSamePointApprox(ptLast, m_mTree[nId].GetTopRight()) ) { - vEdge = ptTl - m_mTree[nId].GetTopRight() ; - vEdge.Normalize() ; - if ( AreOppositeVectorApprox(vLast, vEdge) ) { - plTrimmedPoly.EraseLastUPoint() ; - nEdge = 0 ; + nEdge = 1 ; } } } + else if ( AreSameEdge( nEdge, 1) && AreSamePointApprox(ptLast, m_mTree[nId].GetBottomLeft()) ) { + vEdge = ptBr - m_mTree[nId].GetBottomLeft() ; + vEdge.Normalize() ; + if ( AreOppositeVectorApprox(vLast, vEdge) ) { + plTrimmedPoly.EraseLastUPoint() ; + nEdge = 2 ; + } + } + else if ( AreSameEdge( nEdge, 2) ) { + if ( AreSamePointApprox(ptLast, ptBr) ) { + vEdge = m_mTree[nId].GetTopRight() - ptBr ; + vEdge.Normalize() ; + if ( AreOppositeVectorApprox(vLast, vEdge) ) { + plTrimmedPoly.EraseLastUPoint() ; + nEdge = 3 ; + } + } + } + else if ( AreSameEdge( nEdge, 3) && AreSamePointApprox(ptLast, m_mTree[nId].GetTopRight()) ) { + vEdge = ptTl - m_mTree[nId].GetTopRight() ; + vEdge.Normalize() ; + if ( AreOppositeVectorApprox(vLast, vEdge) ) { + plTrimmedPoly.EraseLastUPoint() ; + nEdge = 0 ; + } + } + // se mi è rimasto solo un punto sulla polyline vuol dire che avevo solo un tratto parallelo ad lato // quindi salto al prossimo loop if ( plTrimmedPoly.GetPointNbr() == 1 ) { @@ -2226,63 +2239,63 @@ Tree::CreateCellPolygons( int nLeafId, std::vector& vPolygons, I // se ho altri Pass vado avanti ad aggiungere vertici finché trovo il prossimo o finché non sono tornato sul lato di partenza bool bNotCameBack = true ; bool bValidNextStart = false ; + bool bAtNextStart = false ; if ( j < nPassToCheck - 1) { int nSecondCheck = 0 ; - - // ciclo sui loop successivi per vedere se ne ho uno su questo lato con un valid start - for ( int t = w ; t < nPassToCheck -1 ; ++ t) { - if ( AreSameEdge( nEdge, m_mTree[nId].m_vInters[j].nIn) ) { - if ( m_mTree[nId].m_vInters[j].bCCW) { - bValidNextStart = ( AreSameEdge( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn, nEdge)) && // loop successivo inizia su questo lato - ! CheckIfAfter( plTrimmedPoly, m_mTree[nId].m_vInters[vToCheckNow[t + 1]].vpt[0], nEdge) ; // in posizione giusta da essere concatenato - } - else { - // se il loop è CW e sono tornato sul lato di partenza allora controllo se sono prima del primo punto della polyline - bValidNextStart = ( AreSameEdge( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn, nEdge)) && - CheckIfAfter( plTrimmedPoly, m_mTree[nId].m_vInters[vToCheckNow[t + 1]].vpt[0], nEdge) ; - } - } - else - bValidNextStart = CheckIfAfter( plTrimmedPoly, m_mTree[nId].m_vInters[vToCheckNow[t + 1]].vpt[0], nEdge) ; - if ( ! AreSameEdge( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn, nEdge) || bValidNextStart) + int nNext ; + // ciclo sui loop successivi per vedere se ne ho uno con un valid start + for ( int t = w + 1 ; t < nPassToCheck ; ++ t) { + bValidNextStart = CheckIfBetween( m_mTree[nId].m_vInters[j], m_mTree[nId].m_vInters[vToCheckNow[t]]) ; + if ( bValidNextStart) { + nNext = t ; + bAtNextStart = AreSameEdge( m_mTree[nId].m_vInters[j].nOut, m_mTree[nId].m_vInters[vToCheckNow[t]].nIn) ; break ; - // se ho trovato un loop successivo che devo saltare, lo salvo e considero i loop più avanti. - if ( AreSameEdge( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn, nEdge) && ! bValidNextStart){ - ++ nSecondCheck ; - vToCheck.push_back( t + 1) ; } - } - if ( m_mTree[nId].m_vInters[j].bCCW) { - //bNotCameBack = ! AreSameEdge( m_mTree[nId].m_vInters[j].nIn, nEdge) && // sono tornato al lato di ingresso di questo loop - // ! AreSameEdge( nEdge, nEdgeIn) ; // sono tornato sul lato di ingresso di questo poligono ( solo se la curva è CCW) - bNotCameBack = ! ( AreSameEdge( nEdge, nEdgeIn) && CheckIfBefore( plTrimmedPoly, nEdge)) ; - } - else { - // il loop è CW e sono tornato sul lato di partenza allora controllo se sono prima del primo punto della polyline - if ( AreSameEdge( nEdge, nEdgeIn)) { - bool bBefore = CheckIfBefore( plTrimmedPoly, nEdge) ; - bNotCameBack = bNotCameBack && !bBefore ; + else { + ++ nSecondCheck ; + vToCheck.push_back( t) ; } } - while ( ! bValidNextStart && bNotCameBack) { + //// ciclo sui loop successivi per vedere se ne ho uno su questo lato con un valid start + //for ( int t = w ; t < nPassToCheck -1 ; ++ t) { + // if ( AreSameEdge( nEdge, m_mTree[nId].m_vInters[j].nIn) ) { + // if ( m_mTree[nId].m_vInters[j].bCCW) { + // bValidNextStart = ( AreSameEdge( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn, nEdge)) && // loop successivo inizia su questo lato + // ! CheckIfAfter( plTrimmedPoly, m_mTree[nId].m_vInters[vToCheckNow[t + 1]].vpt[0], nEdge) ; // in posizione giusta da essere concatenato + // } + // else { + // // se il loop è CW e sono tornato sul lato di partenza allora controllo se sono prima del primo punto della polyline + // bValidNextStart = ( AreSameEdge( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn, nEdge)) && + // CheckIfAfter( plTrimmedPoly, m_mTree[nId].m_vInters[vToCheckNow[t + 1]].vpt[0], nEdge) ; + // } + // } + // else + // bValidNextStart = CheckIfAfter( plTrimmedPoly, m_mTree[nId].m_vInters[vToCheckNow[t + 1]].vpt[0], nEdge) ; + // if ( ! AreSameEdge( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn, nEdge) || bValidNextStart) + // //if ( bValidNextStart) + // break ; + // // se ho trovato un loop successivo che devo saltare, lo salvo e considero i loop più avanti. + // if ( AreSameEdge( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn, nEdge) && ! bValidNextStart){ + // //else { + // ++ nSecondCheck ; + // vToCheck.push_back( t + 1) ; + // } + //} + + bNotCameBack = ! ( AreSameEdge( nEdge, nEdgeIn) && CheckIfBefore( plTrimmedPoly, nEdge)) ; + + //while ( ! bValidNextStart && bNotCameBack) { + while ( ! ( bValidNextStart && bAtNextStart) && bNotCameBack) { Point3d ptVert ; - if ( nEdge == 0) { - //ptVert.x = m_mTree[nId].GetBottomLeft().x ; - //ptVert.y = m_mTree[nId].GetTopRight().y ; + if ( nEdge == 0) ptVert = ptTl ; - } - else if ( nEdge == 1) { + else if ( nEdge == 1) ptVert = m_mTree[nId].GetBottomLeft() ; - } - else if ( nEdge == 2) { - //ptVert.x = m_mTree[nId].GetTopRight().x ; - //ptVert.y = m_mTree[nId].GetBottomLeft().y ; + else if ( nEdge == 2) ptVert = ptBr ; - } - else if ( nEdge == 3) { + else if ( nEdge == 3) ptVert = m_mTree[nId].GetTopRight() ; - } AddVertex( nId, vEdgeVertex, plTrimmedPoly, c, ptVert) ; //plTrimmedPoly.AddUPoint( c, ptVert) ; //++c ; @@ -2294,42 +2307,48 @@ Tree::CreateCellPolygons( int nLeafId, std::vector& vPolygons, I nEdge = 0 ; // aggiorno le condizioni per il while - // ciclo sui loop successivi per vedere se ne ho uno su questo lato con un valid start - for ( int t = w ; t < nPassToCheck -1 ; ++ t) { - if ( AreSameEdge( nEdge, m_mTree[nId].m_vInters[j].nIn) ) { - if ( m_mTree[nId].m_vInters[j].bCCW) { - bValidNextStart = ( AreSameEdge( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn, nEdge)) && // loop successivo inizia su questo lato - ! CheckIfAfter( plTrimmedPoly, m_mTree[nId].m_vInters[vToCheckNow[t + 1]].vpt[0], nEdge) ; // in posizione giusta da essere concatenato - } - else { - // se il loop è CW e sono tornato sul lato di partenza allora controllo se sono prima del primo punto della polyline - bValidNextStart = ( AreSameEdge( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn, nEdge)) && - CheckIfAfter( plTrimmedPoly, m_mTree[nId].m_vInters[vToCheckNow[t + 1]].vpt[0], nEdge) ; - } - } - else - bValidNextStart = CheckIfAfter( plTrimmedPoly, m_mTree[nId].m_vInters[vToCheckNow[t + 1]].vpt[0], nEdge) ; - if ( ! AreSameEdge( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn, nEdge) || bValidNextStart) - break ; - // se ho trovato un loop successivo che devo saltare, lo salvo e considero i loop più avanti. - if ( AreSameEdge( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn, nEdge) && ! bValidNextStart){ - ++ nSecondCheck ; - vToCheck.push_back( t + 1) ; - } - } - if ( m_mTree[nId].m_vInters[j].bCCW) { - //bNotCameBack = ! AreSameEdge( m_mTree[nId].m_vInters[j].nIn, nEdge) && // sono tornato al lato di ingresso di questo loop - // ! AreSameEdge( nEdge, nEdgeIn) ; // sono tornato sul lato di ingresso di questo poligono ( solo se la curva è CCW) - bNotCameBack = ! ( AreSameEdge( nEdge, nEdgeIn) && CheckIfBefore( plTrimmedPoly, nEdge)) ; - } - else { - // il loop è CW e sono tornato sul lato di partenza allora controllo se sono prima del primo punto della polyline - if ( AreSameEdge( nEdge, nEdgeIn)) { - bool bBefore = CheckIfBefore( plTrimmedPoly, nEdge) ; - bNotCameBack = bNotCameBack && !bBefore ; - } - } + if ( bValidNextStart) + bAtNextStart = AreSameEdge( nEdge, m_mTree[nId].m_vInters[vToCheckNow[nNext]].nIn) ; + bNotCameBack = ! ( AreSameEdge( nEdge, nEdgeIn) && CheckIfBefore( plTrimmedPoly, nEdge)) ; + + /*for ( int t = w + 1 ; t < nPassToCheck -1 ; ++ t) { + bValidNextStart = CheckIfBetween( m_mTree[nId].m_vInters[j], m_mTree[nId].m_vInters[vToCheckNow[t]]) ; + if ( bValidNextStart) { + bAtNextStart = AreSameEdge( m_mTree[nId].m_vInters[j].nOut, m_mTree[nId].m_vInters[vToCheckNow[t]].nIn) ; + break ; + } + else { + ++ nSecondCheck ; + vToCheck.push_back( t) ; + } + }*/ + + // ciclo sui loop successivi per vedere se ne ho uno su questo lato con un valid start + //for ( int t = w ; t < nPassToCheck -1 ; ++ t) { + // if ( AreSameEdge( nEdge, m_mTree[nId].m_vInters[j].nIn) ) { + // if ( m_mTree[nId].m_vInters[j].bCCW) { + // bValidNextStart = ( AreSameEdge( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn, nEdge)) && // loop successivo inizia su questo lato + // ! CheckIfAfter( plTrimmedPoly, m_mTree[nId].m_vInters[vToCheckNow[t + 1]].vpt[0], nEdge) ; // in posizione giusta da essere concatenato + // } + // else { + // // se il loop è CW e sono tornato sul lato di partenza allora controllo se sono prima del primo punto della polyline + // bValidNextStart = ( AreSameEdge( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn, nEdge)) && + // CheckIfAfter( plTrimmedPoly, m_mTree[nId].m_vInters[vToCheckNow[t + 1]].vpt[0], nEdge) ; + // } + // } + // else + // bValidNextStart = CheckIfAfter( plTrimmedPoly, m_mTree[nId].m_vInters[vToCheckNow[t + 1]].vpt[0], nEdge) ; + // if ( ! AreSameEdge( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn, nEdge) || bValidNextStart) + // //if ( bValidNextStart) + // break ; + // // se ho trovato un loop successivo che devo saltare, lo salvo e considero i loop più avanti. + // if ( AreSameEdge( m_mTree[nId].m_vInters[vToCheckNow[t + 1]].nIn, nEdge) && ! bValidNextStart){ + // //else { + // ++ nSecondCheck ; + // vToCheck.push_back( t + 1) ; + // } + //} } // se ho trovato un altro loop salto all'inizio del for // @@ -2341,31 +2360,16 @@ Tree::CreateCellPolygons( int nLeafId, std::vector& vPolygons, I } // non ho altri loop quindi aggiungo vertici finché torno al punto di partenza else { - if ( m_mTree[nId].m_vInters[j].bCCW ) { - bNotCameBack = ! AreSameEdge( m_mTree[nId].m_vInters[j].nIn, nEdge) && // sono tornato al lato di ingresso di questo loop - ! AreSameEdge( nEdge, nEdgeIn) ; // sono tornato sul lato di ingresso di questo poligono ( solo se la curva è CCW) - } - else { - // se il loop è CW e sono tornato sul lato di partenza allora controllo se sono prima del primo punto della polyline - if ( AreSameEdge( nEdge, nEdgeIn) ) { - bool bBefore = CheckIfBefore( plTrimmedPoly, nEdge) ; - bNotCameBack = bNotCameBack && ! bBefore ; - } - } + bNotCameBack = ! ( AreSameEdge( nEdge, nEdgeIn) && CheckIfBefore( plTrimmedPoly, nEdge)) ; + while ( bNotCameBack) { Point3d ptVert ; - if ( nEdge == 0) { - //ptVert.x = m_mTree[nId].GetBottomLeft().x ; - //ptVert.y = m_mTree[nId].GetTopRight().y ; + if ( nEdge == 0) ptVert = ptTl ; - } else if ( nEdge == 1) ptVert = m_mTree[nId].GetBottomLeft() ; - else if ( nEdge == 2) { - //ptVert.x = m_mTree[nId].GetTopRight().x ; - //ptVert.y = m_mTree[nId].GetBottomLeft().y ; + else if ( nEdge == 2) ptVert = ptBr ; - } else if ( nEdge == 3) ptVert = m_mTree[nId].GetTopRight() ; AddVertex( nId, vEdgeVertex, plTrimmedPoly, c, ptVert) ; @@ -2378,16 +2382,7 @@ Tree::CreateCellPolygons( int nLeafId, std::vector& vPolygons, I else nEdge = 0 ; // aggiorno le condizioni per il while - if ( m_mTree[nId].m_vInters[j].bCCW ) { - bNotCameBack = ! AreSameEdge( m_mTree[nId].m_vInters[j].nIn, nEdge) && - ! AreSameEdge( nEdge, nEdgeIn) ; - } - else { - if ( AreSameEdge( nEdge, nEdgeIn)) { - bool bBefore = CheckIfBefore( plTrimmedPoly, nEdge) ; - bNotCameBack = bNotCameBack && ! bBefore ; - } - } + bNotCameBack = ! ( AreSameEdge( nEdge, nEdgeIn) && CheckIfBefore( plTrimmedPoly, nEdge)) ; } } plTrimmedPoly.Close() ; @@ -2528,8 +2523,8 @@ Tree::CheckIfBefore( Inters& inA) const // pl.AddUPoint( c, ptToAdd) ; // ++ c ; //} - pl.AddUPoint( 0, inA.vpt[0]) ; - pl.AddUPoint( 1, inA.vpt.back()) ; + pl.AddUPoint( 0, inA.vpt.back()) ; + pl.AddUPoint( 1, inA.vpt[0]) ; INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6} ; // controllo se nEdge1 viene prima di nEdge2. la partenza è da ptTR e l'arrivo è ptBr @@ -2579,36 +2574,53 @@ Tree::CheckIfBefore( int& nEdge1, Point3d& ptP1, int& nEdge2, Point3d& ptP2) con //---------------------------------------------------------------------------- bool -Tree::CheckIfAfter( PolyLine& pl, Point3d& ptNextStart, int nEdge) const +Tree::CheckIfAfter( PolyLine& pl, Point3d& ptNextStart, int nEdge, bool bSameEdge) const { // controllo se ptNextStart è più avanti rispetto a ptEnd in senso antiorario + // ATTENZIONE i due punti devono essere sullo stesso lato! - // se i punti non sono sullo stesso lato ritorno false + // se i punti non sono sullo stesso lato ritorno false ( con bSameEdge == true) Point3d ptEnd ; pl.GetLastPoint( ptEnd) ; if ( nEdge == 0 ) { - if ( ptNextStart.y > ptEnd.y - EPS_SMALL && ptNextStart.y < ptEnd.y + EPS_SMALL) - return ptEnd.x > ptNextStart.x ; + if ( bSameEdge) { + if ( ptNextStart.y > ptEnd.y - EPS_SMALL && ptNextStart.y < ptEnd.y + EPS_SMALL) + return ptEnd.x > ptNextStart.x ; + else + return false ; + } else - return false ; + return ptEnd.x > ptNextStart.x ; } else if ( nEdge == 1 ) { - if ( ptNextStart.x > ptEnd.x - EPS_SMALL && ptNextStart.x < ptEnd.x + EPS_SMALL) + if ( bSameEdge) { + if ( ptNextStart.x > ptEnd.x - EPS_SMALL && ptNextStart.x < ptEnd.x + EPS_SMALL) + return ptEnd.y > ptNextStart.y ; + else + return false ; + } + else return ptEnd.y > ptNextStart.y ; - else - return false ; } else if ( nEdge == 2 ) { - if ( ptNextStart.y > ptEnd.y - EPS_SMALL && ptNextStart.y < ptEnd.y + EPS_SMALL) - return ptEnd.x < ptNextStart.x ; + if ( bSameEdge) { + if ( ptNextStart.y > ptEnd.y - EPS_SMALL && ptNextStart.y < ptEnd.y + EPS_SMALL) + return ptEnd.x < ptNextStart.x ; + else + return false ; + } else - return false ; + return ptEnd.x < ptNextStart.x ; } else if ( nEdge == 3 ) { - if ( ptNextStart.x > ptEnd.x - EPS_SMALL && ptNextStart.x < ptEnd.x + EPS_SMALL) - return ptEnd.y < ptNextStart.y ; + if ( bSameEdge) { + if ( ptNextStart.x > ptEnd.x - EPS_SMALL && ptNextStart.x < ptEnd.x + EPS_SMALL) + return ptEnd.y < ptNextStart.y ; + else + return false ; + } else - return false ; + return ptEnd.y < ptNextStart.y ; } return false ; } @@ -2688,7 +2700,7 @@ Tree::AddVertex( int nId, std::vector& vEdgeVertex, PolyLine& plTrimm if ( ptToAdd.x >= ptBL.x && ptToAdd.x <= ptTR.x && ptToAdd.y == ptTR.y && abs(vDir.x) > 1 - EPS_SMALL) { for ( int t = 0 ; t < (int)vEdgeVertex[0].size() ; ++ t) { Point3d ptIntermed = vEdgeVertex[0][t] ; - if ( ptIntermed.x > ptToAdd.x ) { + if ( ptIntermed.x > ptToAdd.x && ptIntermed.x < ptLast.x) { plTrimmedPoly.AddUPoint( c, ptIntermed) ; ++ c ; } @@ -2702,7 +2714,7 @@ Tree::AddVertex( int nId, std::vector& vEdgeVertex, PolyLine& plTrimm else if ( ptToAdd.y >= ptBL.y && ptToAdd.y <= ptTR.y && ptToAdd.x == ptBL.x && abs(vDir.y) > 1 - EPS_SMALL) { for ( int t = 0 ; t < (int)vEdgeVertex[1].size() ; ++ t) { Point3d ptIntermed = vEdgeVertex[1][t] ; - if ( ptIntermed.y > ptToAdd.y ) { + if ( ptIntermed.y > ptToAdd.y && ptIntermed.y < ptLast.y) { plTrimmedPoly.AddUPoint( c, ptIntermed) ; ++ c ; } @@ -2716,7 +2728,7 @@ Tree::AddVertex( int nId, std::vector& vEdgeVertex, PolyLine& plTrimm else if ( ptToAdd.x >= ptBL.x && ptToAdd.x <= ptTR.x && ptToAdd.y == ptBL.y && abs(vDir.x) > 1 - EPS_SMALL) { for ( int t = 0 ; t < (int)vEdgeVertex[2].size() ; ++ t) { Point3d ptIntermed = vEdgeVertex[2][t] ; - if ( ptIntermed.x < ptToAdd.x ) { + if ( ptIntermed.x < ptToAdd.x && ptIntermed.x > ptLast.x) { plTrimmedPoly.AddUPoint( c, ptIntermed) ; ++ c ; } @@ -2730,7 +2742,7 @@ Tree::AddVertex( int nId, std::vector& vEdgeVertex, PolyLine& plTrimm else if ( ptToAdd.y >= ptBL.y && ptToAdd.y <= ptTR.y && ptToAdd.x == ptTR.x && abs(vDir.y) > 1 - EPS_SMALL) { for ( int t = 0 ; t < (int)vEdgeVertex[3].size() ; ++ t) { Point3d ptIntermed = vEdgeVertex[3][t] ; - if ( ptIntermed.y < ptToAdd.y ) { + if ( ptIntermed.y < ptToAdd.y && ptIntermed.y > ptLast.y) { plTrimmedPoly.AddUPoint( c, ptIntermed) ; ++ c ; } @@ -2900,18 +2912,6 @@ Tree::CategorizeCell( int& nId) // se solo parte del right edge del vicino è compreso, allora devo verificare se la cella è contenuta o no // guardando nFlag del vicino bottom, che è già categorizzato! else if ( m_mTree[vNeigh[0]].m_nRightEdgeIn == 2 ) { - // guardo le intersezioni a mano - // - //int nPass = (int) m_mTree[vNeigh[0]].m_vInters.size() ; - //for ( int p = 0 ; p < nPass ; ++p ) { - // // se ho almeno un ingresso o un'uscita - // if ( ) { - - // } - // else { - // m_mTree[nId].m_nFlag == 0 ; - // } - //} GetBottomNeigh( nId, vNeigh1) ; int nNeigh = vNeigh1[0] ; if ( m_mTree[nNeigh].m_nFlag == 0 || m_mTree[nNeigh].m_nFlag == 2) { @@ -2989,3 +2989,36 @@ Tree::CategorizeCell( int& nId) return true ; } + +//---------------------------------------------------------------------------- +bool +Tree::CheckIfBetween( Inters& intA, Inters& intB) const +{ + // controllo se intB è compreso tra l'end e lo start di intA + // ( dall'end di A percorro i bordi della cella fino a tornare allo start e devo incontrare In e Out di B) + INTVECTOR vEdges ; + int nEdge = intA.nOut ; + vEdges.push_back( nEdge) ; + if ( nEdge == 3) + nEdge = 0 ; + else + ++ nEdge ; + while ( nEdge != intA.nIn ) { + vEdges.push_back( nEdge) ; + if ( nEdge == 3) + nEdge = 0 ; + else + ++ nEdge ; + } + bool bFound = false ; + for ( int i : vEdges) { + if ( intB.nIn == i) { + PolyLine pl ; + pl.AddUPoint( 0, intA.vpt[0]) ; + pl.AddUPoint( 1, intA.vpt.back()) ; + if ( CheckIfAfter( pl, intB.vpt[0], i, false)) + bFound = true ; + } + } + return bFound ; +} diff --git a/Tree.h b/Tree.h index 369acba..fb3663e 100644 --- a/Tree.h +++ b/Tree.h @@ -99,6 +99,7 @@ public : void SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches = true) ; bool BuildTree( double dLinTol = LIN_TOL_STD, double dSideMin = 5, 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( double dLinTol = LIN_TOL_STD, double dSideMin = 5, double dSideMax = INFINITO) ; bool GetPolygons( std::vector& vPolygons) ; bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero // ad ogni poligono sono stati aggiunti tutti i vertici dei vicini posizionati sui suoi lati @@ -126,12 +127,13 @@ private : bool CheckIfBefore( PolyLine& pl, int nEdge) const ; bool CheckIfBefore( Inters& inA) const ; bool CheckIfBefore( int& nEdge1, Point3d& ptP1, int& nEdge2, Point3d& ptP2) const ; - bool CheckIfAfter( PolyLine& pl, Point3d& ptNextStart, int nEdge) const ; + bool CheckIfAfter( PolyLine& pl, Point3d& ptNextStart, int nEdge, bool bSameEdge = true) const ; bool AreSameEdge( int nEdge1, int nEdge2) const ; bool AddVertex( int nId, std::vector& vEdgeVertex, PolyLine& plTrimmedPoly, int& c, Point3d& ptToAdd) const ; //bool SetRightEdgeIn( int nId, std::vector& vEdgeVertex, PolyLine& plTrimmedPoly) ; bool SetRightEdgeIn( int nId) ; bool CategorizeCell( int& nId) ; + bool CheckIfBetween( Inters& intA, Inters& intB) const ; private : const SurfBezier* m_pSrfBz ; // superficie di bezier