From 535011072d0c704a728e4edaca2a01abeedc037d Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 21 Mar 2024 12:57:59 +0100 Subject: [PATCH] EgtGeomKernel : - corretta e ultimata la funzione edges3D per Bezier. #11 --- SurfBezier.cpp | 224 +++++++++++++++++-------------------------------- Tree.cpp | 5 +- 2 files changed, 81 insertions(+), 148 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 709aec5..17433aa 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1447,7 +1447,7 @@ SurfBezier::GetCurveOnVApproxLen( double dU) const bool SurfBezier::UpdateEdgesFromTree( Tree& tr) const { - POLYLINEMATRIX mPlEdges(4) ; + POLYLINEMATRIX mPlEdges ; tr.GetEdges3D( mPlEdges) ; for ( int i= 0 ; i < int( mPlEdges.size()); ++i) { for ( int j = 0 ; j < int ( mPlEdges[i].size()) ; ++j) { @@ -1464,7 +1464,9 @@ SurfBezier::UpdateEdgesFromTree( Tree& tr) const ++ nCount ; } if ( ! m_mCCEdge[i].back()->FromPolyLine(pl3D)) { - Point3d ptStart ; pl3D.GetFirstPoint( ptStart) ; + Point3d ptStart ; + if ( ! pl3D.GetFirstPoint( ptStart)) + continue ; m_mCCEdge[i].back()->FromPoint( ptStart) ; } } @@ -1474,28 +1476,11 @@ SurfBezier::UpdateEdgesFromTree( Tree& tr) const POLYLINEVECTOR vPl ; tr.GetSplitLoops( vPl) ; - //// per split nel parametrico + // recupero i loop nel parametrico for( int i = 0 ; i < int( vPl.size()); ++i) { m_vCCLoop.emplace_back(CreateBasicCurveComposite()) ; m_vCCLoop.back()->FromPolyLine(vPl[i]) ; } - - //// Loop 3D - //for( int i = 0 ; i < int( vPl.size()); ++i) { - // m_vCCLoop.emplace_back(CreateBasicCurveComposite()) ; - // PolyLine pl3D ; - // Point3d pt ; vPl[i].GetFirstPoint( pt) ; - // Point3d pt3D ; GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; - // int nCount = 0 ; - // pl3D.AddUPoint( nCount, pt3D) ; - // ++ nCount ; - // while( vPl[i].GetNextPoint( pt)){ - // GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; - // pl3D.AddUPoint( nCount, pt3D) ; - // ++ nCount ; - // } - // m_vCCLoop.back()->FromPolyLine(pl3D) ; - //} } return true ; @@ -2795,7 +2780,6 @@ SurfBezier::GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdg } // se la superficie è trimmata devo recuperare i loop dello spazio parametrico else { - //// con split nel parametrico//////////////////////////////////////////////////////// // devo ricostruire i bordi aperti in caso di superficie chiusa // costruisco gli edge ICurveLine* pCLU0( CreateCurveLine()) ; @@ -2865,11 +2849,11 @@ SurfBezier::GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdg // devo cancellare la parte comune Point3d ptStart2 = inters2.IciA[0].ptI ; Point3d ptEnd2 = inters2.IciA[1].ptI ; - // come ptStart2 prendo quello con la x minore - if ( ptStart2.x > ptEnd2.x) + // come ptStart2 prendo quello con la x maggiore + if ( ptStart2.x < ptEnd2.x) swap( ptStart2, ptEnd2) ; - if ( (( ptStart0.x - EPS_SMALL< ptStart2.x && ptStart2.x < ptEnd0.x + EPS_SMALL) && ( ptStart0.x - EPS_SMALL < ptEnd2.x && ptEnd2.x < ptEnd0.x + EPS_SMALL)) || - (( ptStart2.x - EPS_SMALL < ptStart0.x && ptStart0.x < ptEnd2.x + EPS_SMALL) && ( ptStart2.x - EPS_SMALL < ptEnd0.x && ptEnd0.x < ptEnd2.x + EPS_SMALL))) { + if ( (( ptEnd0.x - EPS_SMALL< ptStart2.x && ptStart2.x < ptStart0.x + EPS_SMALL) && ( ptEnd0.x - EPS_SMALL < ptEnd2.x && ptEnd2.x < ptStart0.x + EPS_SMALL)) || + (( ptEnd2.x - EPS_SMALL < ptStart0.x && ptStart0.x < ptStart2.x + EPS_SMALL) && ( ptEnd2.x - EPS_SMALL < ptEnd0.x && ptEnd0.x < ptStart2.x + EPS_SMALL))) { PtrOwner pCL( CreateBasicCurveLine()) ; pCL->Set( ptStart0, ptEnd0) ; // devo scorrere su tutte le curve che sono state ottenute dallo split del loop originale @@ -2877,6 +2861,11 @@ SurfBezier::GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdg int nIndex2 = mSplitLoop[vInters2.first][w] ; IntersCurveCurve icc( *m_vCCLoop[nIndex2], *pCL) ; IntCrvCrvInfo iccInfo ; icc.GetIntCrvCrvInfo( 0, iccInfo) ; + for ( int k = 0 ; k < icc.GetIntersCount() ; ++k) { + icc.GetIntCrvCrvInfo( k, iccInfo) ; + if ( iccInfo.bOverlap) + break ; + } if ( ! iccInfo.bOverlap) continue ; // se parto da una curva chiusa semplicemente tolgo un pezzo @@ -2887,12 +2876,18 @@ SurfBezier::GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdg else { // se la curva era già aperta allora otterrò due curve separate ICurveComposite* pCC2a( GetCurveComposite( m_vCCLoop[nIndex2]->Clone())) ; - pCC2a->TrimEndAtParam( iccInfo.IciA[1].dU) ; + bool bDoneA = pCC2a->TrimEndAtParam( iccInfo.IciA[0].dU) ; ICurveComposite* pCC2b( GetCurveComposite( m_vCCLoop[nIndex2]->Clone())) ; - pCC2b->TrimStartAtParam( iccInfo.IciA[0].dU) ; - m_vCCLoop[nIndex2].Set( pCC2a) ; - m_vCCLoop.emplace_back( pCC2b) ; - mSplitLoop[vInters2.first].push_back( m_vCCLoop.size() - 1) ; + bool bDoneB = pCC2b->TrimStartAtParam( iccInfo.IciA[1].dU) ; + if ( bDoneA) { + m_vCCLoop[nIndex2].Set( pCC2a) ; + if ( bDoneB) { + m_vCCLoop.emplace_back( pCC2b) ; + mSplitLoop[vInters2.first].push_back( m_vCCLoop.size() - 1) ; + } + } + else if ( bDoneB) + m_vCCLoop[nIndex2].Set( pCC2b) ; } // per togliere la parte comune al loop corrente devo riportare i punti di intersezione sull'edge di partenza @@ -2902,30 +2897,35 @@ SurfBezier::GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdg ptOverlapE.y = m_nSpanV * SBZ_TREG_COEFF ; double dStart0, dEnd0 ; // scorro tutte le curve in cui è stato splittato il loop iniziale - for ( int j = 0 ; int( mSplitLoop[vInters0.first].size()) ; ++j ) { + for ( int j = 0 ; j < int( mSplitLoop[vInters0.first].size()) ; ++j ) { int nIndex0 = mSplitLoop[vInters0.first][j] ; - if ( ! m_vCCLoop[nIndex0]->GetParamAtPoint( ptOverlapS, dStart0) || m_vCCLoop[nIndex0]->GetParamAtPoint( ptOverlapE, dEnd0)) + if ( ! m_vCCLoop[nIndex0]->GetParamAtPoint( ptOverlapS, dStart0) || ! m_vCCLoop[nIndex0]->GetParamAtPoint( ptOverlapE, dEnd0)) continue ; // se parto da una curva chiusa semplicemente tolgo un pezzo if ( m_vCCLoop[nIndex0]->IsClosed()) { - ICurveComposite* pCC0( GetCurveComposite( m_vCCLoop[nIndex0]->CopyParamRange( dEnd0, dStart0))) ; + ICurveComposite* pCC0( GetCurveComposite( m_vCCLoop[nIndex0]->CopyParamRange( dStart0, dEnd0))) ; m_vCCLoop[nIndex0].Set( pCC0) ; } else { // se la curva era già aperta allora otterrò due curve separate ICurveComposite* pCC0a( GetCurveComposite( m_vCCLoop[nIndex0]->Clone())) ; - pCC0a->TrimEndAtParam( dStart0) ; + bool bDoneA = pCC0a->TrimEndAtParam( dEnd0) ; ICurveComposite* pCC0b( GetCurveComposite( m_vCCLoop[nIndex0]->Clone())) ; - pCC0b->TrimStartAtParam( dEnd0) ; - m_vCCLoop[nIndex0].Set( pCC0a) ; - m_vCCLoop.emplace_back( pCC0b) ; - mSplitLoop[vInters0.first].push_back( m_vCCLoop.size() - 1) ; + bool bDoneB = pCC0b->TrimStartAtParam( dStart0) ; + if ( bDoneA) { + m_vCCLoop[nIndex0].Set( pCC0a) ; + if ( bDoneB) { + m_vCCLoop.emplace_back( pCC0b) ; + mSplitLoop[vInters0.first].push_back( m_vCCLoop.size() - 1) ; + } + } + else if ( bDoneB) + m_vCCLoop[nIndex0].Set( pCC0b) ; } break ; } break ; } - break ; } } } @@ -2963,7 +2963,12 @@ SurfBezier::GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdg for ( int w = 0 ; w < int( mSplitLoop[vInters3.first].size()) ; ++w) { int nIndex3 = mSplitLoop[vInters3.first][w] ; IntersCurveCurve icc( *m_vCCLoop[nIndex3], *pCL) ; - IntCrvCrvInfo iccInfo ; icc.GetIntCrvCrvInfo( 0, iccInfo) ; + IntCrvCrvInfo iccInfo ; + for ( int k = 0 ; k < icc.GetIntersCount() ; ++k) { + icc.GetIntCrvCrvInfo( k, iccInfo) ; + if ( iccInfo.bOverlap) + break ; + } if ( ! iccInfo.bOverlap) continue ; // se parto da una curva chiusa semplicemente tolgo un pezzo @@ -2974,12 +2979,18 @@ SurfBezier::GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdg else { // se la curva era già aperta allora otterrò due curve separate ICurveComposite* pCC3a( GetCurveComposite( m_vCCLoop[nIndex3]->Clone())) ; - pCC3a->TrimEndAtParam( iccInfo.IciA[0].dU) ; + bool bDoneA = pCC3a->TrimEndAtParam( iccInfo.IciA[0].dU) ; ICurveComposite* pCC3b( GetCurveComposite( m_vCCLoop[nIndex3]->Clone())) ; - pCC3b->TrimStartAtParam( iccInfo.IciA[1].dU) ; - m_vCCLoop[nIndex3].Set( pCC3a) ; - m_vCCLoop.emplace_back( pCC3b) ; - mSplitLoop[vInters3.first].push_back( m_vCCLoop.size() - 1) ; + bool bDoneB = pCC3b->TrimStartAtParam( iccInfo.IciA[1].dU) ; + if ( bDoneA) { + m_vCCLoop[nIndex3].Set( pCC3a) ; + if ( bDoneB) { + m_vCCLoop.emplace_back( pCC3b) ; + mSplitLoop[vInters3.first].push_back( m_vCCLoop.size() - 1) ; + } + } + else if ( bDoneB ) + m_vCCLoop[nIndex3].Set( pCC3b) ; } // per togliere la parte comune al loop corrente devo riportare i punti di intersezione sull'edge di partenza @@ -3001,18 +3012,23 @@ SurfBezier::GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdg else { // se la curva era già aperta allora otterrò due curve separate ICurveComposite* pCC1a( GetCurveComposite( m_vCCLoop[nIndex1]->Clone())) ; - pCC1a->TrimEndAtParam( dEnd1) ; + bool bDoneA = pCC1a->TrimEndAtParam( dEnd1) ; ICurveComposite* pCC1b( GetCurveComposite( m_vCCLoop[nIndex1]->Clone())) ; - pCC1b->TrimStartAtParam( dStart1) ; + bool bDoneB = pCC1b->TrimStartAtParam( dStart1) ; + if ( bDoneA) { m_vCCLoop[nIndex1].Set( pCC1a) ; - m_vCCLoop.emplace_back( pCC1b) ; - mSplitLoop[vInters1.first].push_back( m_vCCLoop.size() - 1) ; + if ( bDoneB) { + m_vCCLoop.emplace_back( pCC1b) ; + mSplitLoop[vInters1.first].push_back( m_vCCLoop.size() - 1) ; + } + } + else if ( bDoneB) + m_vCCLoop[nIndex1].Set( pCC1b) ; } break ; } break ; } - break ; } } } @@ -3050,107 +3066,21 @@ SurfBezier::GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdg continue ; PtrOwner pCC( vpCCOpen[k]->Clone()) ; vbAdded[k] = true ; - for ( int t = k ; t < int(vpCCOpen.size()); ++t ) { - if ( pCC->AddCurve( vpCCOpen[t]->Clone())) - vbAdded[t] = true ; + bool bAddedOne = true ; + while( bAddedOne) { + bAddedOne = false ; + for ( int t = k ; t < int(vpCCOpen.size()); ++t ) { + if ( vbAdded[t]) + continue ; + if ( pCC->AddCurve( vpCCOpen[t]->Clone())) { + vbAdded[t] = true ; + bAddedOne = true ; + } + } } // aggiungo la curva agli edge 3d da restituire vCC.emplace_back( Release( pCC)) ; } - - //// con split nel parametrico//////////////////////////////////////////////////////// - - //// se volessi restiturie tutto passo i loop del parametrico portati in 3D - //for ( int i = 0 ; i < int(m_vCCLoop2D.size()) ; ++i) - // vCC.emplace_back( m_vCCLoop2D[i]->Clone()) ; - - - //// con le inters in 3D/////////////////////////////////////////////////// - //for ( int i = 0 ; i < int( m_vCCLoop.size()) ; ++i) { - // //// debug - // ////disegno le curve nel nuovo riferimento - // //vCC.emplace_back( Release(m_vCCLoop[i])) ; - // // continue ; - // ////debug - - // // calcolo le autointersezioni a mano - // // le premesse sono che le compo è formata da curveLine e che i tratti eventualmente sovrapposti sono linee interamente coincidenti ( start-end e viceversa) - // double dStart, dEnd ; m_vCCLoop[i]->GetDomain( dStart, dEnd) ; - // Intervals inDomain ; inDomain.Set( dStart, dEnd) ; - // //DBLVECTOR vdU ; - // BOOLVECTOR vbErased( m_vCCLoop[i]->GetCurveCount()) ; - // fill( vbErased.begin(), vbErased.end(), false) ; - // // scorro tutte le curve singole della compo - // for ( int k = 0 ; k < int( m_vCCLoop[i]->GetCurveCount()); ++k) { - // const ICurve* pCrvA = m_vCCLoop[i]->GetCurve( k) ; - // if ( vbErased[k]) - // continue ; - // Point3d ptStartA ; pCrvA->GetStartPoint( ptStartA) ; - // Point3d ptEndA ; pCrvA->GetEndPoint( ptEndA) ; - // // devo confrontarla con tutte le successive - // for ( int w = k + 1 ; w < int(m_vCCLoop[i]->GetCurveCount()); ++w ) { - // const ICurve* pCrvB = m_vCCLoop[i]->GetCurve( w) ; - // Point3d ptStartB ; pCrvB->GetStartPoint( ptStartB) ; - // Point3d ptEndB ; pCrvB->GetEndPoint( ptEndB) ; - // IntCrvCrvInfo iccInfo ; - // Vector3d vtDirSA ; pCrvA->GetStartDir( vtDirSA) ; - // Vector3d vtDirSB ; pCrvB->GetStartDir( vtDirSB) ; - // if ( AreSameOrOppositeVectorApprox( vtDirSA, Z_AX) || AreSameOrOppositeVectorApprox( vtDirSB, Z_AX)) { - // Frame3d frOptimal ; - // if ( (vtDirSA ^ vtDirSB).Len() > EPS_SMALL) - // frOptimal.Set( ORIG, vtDirSA ^ vtDirSB, vtDirSA) ; - // else - // frOptimal.Set( ORIG, X_AX, vtDirSA) ; - // PtrOwner pCrvNewA( pCrvA->Clone()) ; - // pCrvNewA->ToLoc( frOptimal) ; - // PtrOwner pCrvNewB( pCrvB->Clone()) ; - // pCrvNewB->ToLoc( frOptimal) ; - // IntersCurveCurve icc( *pCrvNewA, *pCrvNewB) ; - // icc.GetIntCrvCrvInfo( 0, iccInfo) ; - // } - // else { - // IntersCurveCurve icc( *pCrvA, *pCrvB) ; - // icc.GetIntCrvCrvInfo( 0, iccInfo) ; - // } - // // se sono sovrapposte allora devo eliminare la parte comune - // if ( iccInfo.bOverlap && ( AreSamePointApprox( ptStartA, ptEndB) || AreSamePointApprox( ptEndA, ptStartB) || - // AreSamePointApprox( ptStartA, ptStartB) || AreSamePointApprox( ptEndA, ptEndB))) { - // inDomain.Subtract( k + iccInfo.IciA[0].dU, k + iccInfo.IciA[1].dU) ; - // vbErased[k] = true ; - // inDomain.Subtract( w + iccInfo.IciB[0].dU, w + iccInfo.IciB[1].dU) ; - // vbErased[w] = true ; - // break ; - // } - // } - // // quando raggiungo la prima intersezione potrei anche uscire dal for.. però devo salvarmi da qualche parte tra quali sottocurve - // // ci sono intersezioni sennò non posso accorgermene - // } - - // ICRVCOMPOPOVECTOR vpCCOpen ; - - // // con Intervals - // double dStart0, dEnd0 ; inDomain.GetFirst( dStart0, dEnd0) ; - // vpCCOpen.emplace_back( GetCurveComposite( m_vCCLoop[i]->CopyParamRange( dStart0, dEnd0))) ; - // while ( inDomain.GetNext( dStart0, dEnd0)) - // vpCCOpen.emplace_back( GetCurveComposite( m_vCCLoop[i]->CopyParamRange( dStart0, dEnd0))) ; - // - // // creo la chain a mano con le compo - // BOOLVECTOR vbAdded( vpCCOpen.size()) ; - // fill( vbAdded.begin(), vbAdded.end(), false) ; - // for ( int k = 0 ; k < int( vpCCOpen.size()); ++k ) { - // if ( vbAdded[k]) - // continue ; - // PtrOwner pCC( vpCCOpen[k]->Clone()) ; - // vbAdded[k] = true ; - // for ( int t = k ; t < int(vpCCOpen.size()); ++t ) { - // if ( pCC->AddCurve( vpCCOpen[t]->Clone())) - // vbAdded[t] = true ; - // } - // // aggiungo la curva agli edge 3d da restituire - // vCC.emplace_back( Release( pCC)) ; - // } - //} - //// con le inters in 3D/////////////////////////////////////////////////// } return true ; } diff --git a/Tree.cpp b/Tree.cpp index 38b6b62..f390ec2 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -73,6 +73,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi m_vPlApprox.clear() ; m_vChunk.clear() ; m_vPolygons.clear() ; + m_vPlLoop2D.clear() ; m_pSrfBz = pSrfBz ; m_bSplitPatches = bSplitPatches ; @@ -3639,10 +3640,11 @@ Tree::GetEdges3D( POLYLINEMATRIX& mPLEdges) // scorro sui gruppi di polyline che rappresentano i poligoni delle celle lungo un lato for ( int i = 0 ; i < int( mPL.size()) ; ++i) { - mPLEdges.back().emplace_back() ; + mPLEdges.emplace_back() ; int nPtCount = 0 ; // scorro sui poligoni delle celle di un lato for ( int c = 0 ; c < int( mPL[i].size()) ; ++c) { + mPLEdges.back().emplace_back() ; Point3d pt ; mPL[i][c].GetFirstPoint( pt) ; Point3d pt3d ; // a seconda del lato controllo di stare scorrendo il poligono prendendo solo i punti su quel lato @@ -3713,6 +3715,7 @@ Tree::GetEdges3D( POLYLINEMATRIX& mPLEdges) else { // per ogni edge creo le compo che compongono l'edge dopo i trim ( possono essere più compo separate tra loro) for ( int i = 0 ; i < 4 ; ++i) { + mPLEdges.emplace_back() ; INTVECTOR vId ; Point3d ptNear = m_mTree.at(-1).GetBottomLeft() ; while( m_vCEdge2D[i].second.GetChainFromNear(ptNear, false, vId) ) {