From 67c03daa422e5b7d3b3c49ea285bb5fc2fa65488 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 13 Mar 2024 15:59:55 +0100 Subject: [PATCH] EgtGeomKernel : - nella get Edges3D per sup di Bezier gestito il caso di sup trimmate. --- SurfBezier.cpp | 210 ++++++++++++++++++++++++++--------------- SurfBezier.h | 13 ++- Tree.cpp | 249 ++++++++++++++++++++++++++++++++----------------- Tree.h | 14 ++- 4 files changed, 320 insertions(+), 166 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 6ddd9ee..91899e1 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -162,13 +162,13 @@ SurfBezier::SetTrimRegion( ISurfFlatRegion& sfrTrimReg, bool bIntersectOrSubtrac } ResetAuxSurf() ; // assegno la regione di trim - m_bTrimmed = true ; if ( m_pTrimReg != nullptr ) { if ( ! m_pTrimReg->Intersect( *pSfrTrim)) return false ; } else m_pTrimReg = GetBasicSurfFlatRegion( Release( pSfrTrim)) ; + m_bTrimmed = true ; return true ; } @@ -771,7 +771,6 @@ SurfBezier::Load( NgeReader& ngeIn) } // se trimmata, lettura della regione if ( bTrimmed) { - m_bTrimmed = true ; // creo l'oggetto ResetTrimRegion() ; m_pTrimReg = CreateBasicSurfFlatRegion() ; @@ -781,6 +780,7 @@ SurfBezier::Load( NgeReader& ngeIn) IGeoObjRW* pGObjRW = dynamic_cast( m_pTrimReg) ; if ( pGObjRW == nullptr || ! pGObjRW->Load( ngeIn)) return false ; + m_bTrimmed = true ; } // eseguo validazione @@ -1439,6 +1439,38 @@ SurfBezier::GetCurveOnVApproxLen( double dU) const return dLen ; } +//---------------------------------------------------------------------------- +bool +SurfBezier::UpdateEdgeFromTree( POLYLINEMATRIX& mPl) const +{ + bool bComposed = true ; + m_mCCEdge.clear() ; + for ( int i= 0 ; i < int( mPl.size()); ++i) { + m_mCCEdge.emplace_back() ; + for ( int j = 0 ; j < int ( mPl[i].size()) ; ++j) { + m_mCCEdge.back().emplace_back(CreateBasicCurveComposite()) ; + PolyLine pl3D ; + Point3d pt ; mPl[i][j].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( mPl[i][j].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 ; + } + if ( ! m_mCCEdge.back().back()->FromPolyLine( pl3D)) + bComposed = false ; + } + } + // se degli edge hanno delle curve non valide allora salvo anche le polyline + if ( ! bComposed) + m_mPlEdge = mPl ; + + return true ; +} + //---------------------------------------------------------------------------- const SurfTriMesh* SurfBezier::GetAuxSurf( void) const @@ -1459,6 +1491,7 @@ SurfBezier::GetAuxSurf( void) const BIPNTVECTOR vTrees ; Tree.GetIndependentTrees( vTrees) ; bool bTest = false ; // per debug + POLYLINEMATRIX mPlEdges(4) ; for ( int i = 0 ; i < (int) vTrees.size() ; ++ i) { Point3d ptMin = std::get<0>( vTrees[i]) ; Point3d ptMax = std::get<1>( vTrees[i]) ; @@ -1472,8 +1505,13 @@ SurfBezier::GetAuxSurf( void) const Tree.BuildTree( 5 * LIN_TOL_FINE, 0.1) ; } Tree.GetPolygons( vvPL) ; - //Tree.GetPolygonsBasic( vPL) ; // per usare i polygon basic + + // aggiorno la chiusura della superficie + m_bClosedU = m_bClosedU || Tree.IsClosedU() ; + m_bClosedV = m_bClosedU || Tree.IsClosedV() ; + // salvo i bordi in 3d, che servono in caso si voglia trimmare la superficie DOPO aver costruito la trimesh ausiliaria + Tree.GetEdges3D( mPlEdges) ; } //// per usare i polygon basic////////////////////// //for (int k = 0 ; k < (int)vPL.size(); ++k) { @@ -1482,28 +1520,35 @@ SurfBezier::GetAuxSurf( void) const //} //// per usare i polygon basic/////////////////// + UpdateEdgeFromTree( mPlEdges) ; - /////////////////// così facendo sto recuperando gli Edge e la chiusura solo dell'ULTIMO TREE analizzato!!!!! (in caso di trim che creano più chunk analizzo più tree separatamente)/////////////// - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // aggiorno la chiusura della superficie - m_bClosedU = Tree.IsClosedU() ; - m_bClosedV = Tree.IsClosedV() ; - //m_vbPole = Tree.GetPoles() ; + /////////////////////da testare///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // bool bComposed = true ; + // m_mCCEdge.clear() ; + // for ( int i= 0 ; i < int( mPlEdges.size()); ++i) { + // m_mCCEdge.emplace_back() ; + // for ( int j = 0 ; j < int ( mPlEdges[i].size()) ; ++j) { + // m_mCCEdge.back().emplace_back(CreateBasicCurveComposite()) ; + // PolyLine pl3D ; + // Point3d pt ; mPlEdges[i][j].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( mPlEdges[i][j].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 ; + // } + // if ( ! m_mCCEdge.back().back()->FromPolyLine( mPlEdges[i][j]) ) + // bComposed = false ; + // } + // } - // salvo i bordi in 3d, che servono in caso si voglia trimmare la superficie DOPO aver costruito la trimesh ausiliaria - POLYLINEVECTOR vPLEdges ; - Tree.GetEdge3D( vPLEdges) ; - bool bComposed = true ; - for ( int i= 0 ; i < int( vPLEdges.size()); ++i) { - m_vCCEdge.emplace_back( CreateBasicCurveComposite()) ; - if ( ! m_vCCEdge.back()->FromPolyLine( vPLEdges[i])) - bComposed = false ; - } - if ( ! bComposed) - m_vPLEdge = vPLEdges ; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // if ( ! bComposed) + // m_mPLEdge = mPlEdges ; + // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // qui non sarebbe male stampare un messaggio di errore nel log se avevo un'area da disegnare ma non sono usciti dei poligoni if ( int(vvPL.size()) == 0) LOG_DBG_ERR( GetEGkLogger(), "ERROR : Bezier Surface couldn't be triangulated, hence wasn't drawn") ; @@ -2227,7 +2272,7 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // imposto ricalcolo della grafica m_OGrMgr.Reset() ; - + return true ; } @@ -2257,21 +2302,24 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in // se sono in polo e mi hanno passato un punto precedente allora devo prendere il triangolo di quel punto bool bIsPole = false ; int nInters = 0 ; - INTVECTOR vInters ; + INTVECTOR vInters(4) ; + fill( vInters.begin(), vInters.end(), 0) ; // se il vettore dei poli non è stato riempito vuol dire che quando è stata creata la superficie non è stata chiamata la funzione CalcPoles if ( int( m_vbPole.size()) == 0) return false ; if ( m_vbPole[0] || m_vbPole[1] || m_vbPole[2] || m_vbPole[3] || m_bClosedU || m_bClosedV) { for ( int c = 0 ; c < 4 ; ++c) { - if ( ! m_vCCEdge[c]->IsValid()) { - Point3d pt ; - m_vPLEdge[c].GetFirstPoint( pt) ; - vInters.push_back( AreSamePointApprox( pt, ptI) ? 1 : 0) ; - nInters += vInters.back() ; - } - else { - vInters.push_back( m_vCCEdge[c]->IsPointOn( ptI) ? 1 : 0) ; - nInters += vInters.back() ; + for ( int i = 0 ; i < int( m_mCCEdge[c].size()) ; ++i) { + if ( ! m_mCCEdge[c][i]->IsValid() ) { + Point3d pt ; + m_mPlEdge[c][i].GetFirstPoint(pt) ; + vInters[c] = AreSamePointApprox( pt, ptI) ? 1 : 0 ; + nInters += vInters.back() ; + } + else { + vInters[c] = m_mCCEdge[c][i]->IsPointOn(ptI) ? 1 : 0 ; + nInters += vInters.back() ; + } } } @@ -2333,18 +2381,20 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in int nVertOnPole = -1 ; for ( int p = 0 ; p < 3; ++p ) { for ( int ed = 0 ; ed < 4; ++ed) { - if ( ! m_vCCEdge[ed]->IsValid()) { - Point3d pt ; - m_vPLEdge[ed].GetFirstPoint( pt) ; - if ( AreSamePointApprox( pt, vPT[p])) { - vOn[p] = ed ; - // se un vertice sta su un polo me lo segno - nVertOnPole = p ; + for ( int i = 0 ; i < int( m_mCCEdge[ed].size()) ; ++i) { + if ( ! m_mCCEdge[ed][i]->IsValid() ) { + Point3d pt ; + m_mPlEdge[ed][i].GetFirstPoint(pt) ; + if ( AreSamePointApprox( pt, vPT[p])) { + vOn[p] = ed ; + // se un vertice sta su un polo me lo segno + nVertOnPole = p ; + } + } + else { + if (m_mCCEdge[ed][i]->IsPointOn(vPT[p]) && vOn[p] == -1 ) + vOn[p] = ed ; } - } - else { - if (m_vCCEdge[ed]->IsPointOn( vPT[p]) && vOn[p] == -1) - vOn[p] = ed ; } } } @@ -2380,18 +2430,20 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in int nVertOnPole = -1 ; for ( int p = 0 ; p < 3; ++p ) { for (int ed = 0 ; ed < 4 ; ++ed) { - if ( ! m_vCCEdge[ed]->IsValid()) { - Point3d pt ; - m_vPLEdge[ed].GetFirstPoint( pt) ; - if ( AreSamePointApprox( pt, vPT[p])) { - vOn[p] = ed ; - // se un vertice sta su un polo me lo segno - nVertOnPole = p ; + for ( int i = 0 ; i < int( m_mCCEdge[ed].size()) ; ++i) { + if ( ! m_mCCEdge[ed][i]->IsValid()) { + Point3d pt ; + m_mPlEdge[ed][i].GetFirstPoint( pt) ; + if ( AreSamePointApprox( pt, vPT[p])) { + vOn[p] = ed ; + // se un vertice sta su un polo me lo segno + nVertOnPole = p ; + } + } + else { + if( m_mCCEdge[ed][i]->IsPointOn( vPT[p]) && vOn[p] == -1) + vOn[p] = ed ; } - } - else { - if( m_vCCEdge[ed]->IsPointOn( vPT[p]) && vOn[p] == -1) - vOn[p] = ed ; } } } @@ -2440,13 +2492,15 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in std::fill( vbOn.begin(), vbOn.end(), false) ; for ( int p = 0 ; p < 3; ++p ) { for ( int c = 0 ; c < 4; ++c) { - if ( ! m_vCCEdge[c]->IsValid()) { - Point3d pt ; - m_vPLEdge[c].GetFirstPoint( pt) ; - vbOn[p] = vbOn[p] || AreSamePointApprox( pt, vPT[p]) ; + for( int i = 0 ; int( m_mCCEdge[c].size()) ; ++i) { + if ( ! m_mCCEdge[c][i]->IsValid()) { + Point3d pt ; + m_mPlEdge[c][i].GetFirstPoint( pt) ; + vbOn[p] = vbOn[p] || AreSamePointApprox( pt, vPT[p]) ; + } + else + vbOn[p] = vbOn[p] || m_mCCEdge[c][i]->IsPointOn( vPT[p]) ; } - else - vbOn[p] = vbOn[p] || m_vCCEdge[c]->IsPointOn( vPT[p]) ; } } // trovo la coordinata giusta da tenere ( x o y a seconda dell'edge) @@ -2667,14 +2721,23 @@ SurfBezier::GetEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) c if ( m_pSTM == nullptr) GetAuxSurf() ; - if ( nEdge == -1 ) { - vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 0)) ; - vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 1)) ; - vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 2)) ; - vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 3)) ; + // se la superficie non è trimmata mi basta recuperare gli edge della superficie + if ( ! m_bTrimmed) { + // se decidessi di non restituire gli edge chiusi e i poli posso discriminare qui + if ( nEdge == -1 ) { + vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 0)) ; + vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 1)) ; + vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 2)) ; + vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 3)) ; + } + else + vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, nEdge)) ; + } + // se la superficie è trimmata devo recuperare i loop dello spazio parametrico + else { + for ( int i = 0 ; i < int(m_vCCLoop.size()) ; ++i) + vCC.emplace_back( m_vCCLoop[i]->Clone()) ; } - else - vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, nEdge)) ; return true ; } @@ -2682,14 +2745,15 @@ SurfBezier::GetEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) c ICurveComposite* SurfBezier::GetSingleEdge3D( bool bLineOrBezier, int nEdge) const { - if ( nEdge < 0 || nEdge > 3) + // questa funzione dà per scontato che la superficie NON sia trimmata + if ( nEdge < 0 || nEdge > 3 || m_bTrimmed) return nullptr ; ICurveComposite* pCrvCompo( CreateBasicCurveComposite()) ; switch ( nEdge) { case 0 : { // se il bool è true allora restituisco gli edge con la loro approssimazione in forma di linea spezzata 3D if ( bLineOrBezier) - pCrvCompo = m_vCCEdge[nEdge]->Clone() ; + pCrvCompo = m_mCCEdge[nEdge][0]->Clone() ; // se il bool è falso restituisco le curve Bezier di edge else { //edge 0, scorro sulle patch in U @@ -2711,7 +2775,7 @@ SurfBezier::GetSingleEdge3D( bool bLineOrBezier, int nEdge) const } case 1 : { if ( bLineOrBezier) - pCrvCompo = m_vCCEdge[nEdge]->Clone() ; + pCrvCompo = m_mCCEdge[nEdge][0]->Clone() ; else { //edge 1, scorro sulle patch in V for ( int i = 0 ; i < m_nSpanV ; ++i) { @@ -2732,7 +2796,7 @@ SurfBezier::GetSingleEdge3D( bool bLineOrBezier, int nEdge) const } case 2 : { if ( bLineOrBezier) - pCrvCompo = m_vCCEdge[nEdge]->Clone() ; + pCrvCompo = m_mCCEdge[nEdge][0]->Clone() ; else { // edge 2, scorro sulle patch in U for ( int i = 0 ; i < m_nSpanU ; ++i) { @@ -2752,7 +2816,7 @@ SurfBezier::GetSingleEdge3D( bool bLineOrBezier, int nEdge) const } case 3 : { if ( bLineOrBezier) - pCrvCompo = m_vCCEdge[nEdge]->Clone() ; + pCrvCompo = m_mCCEdge[nEdge][0]->Clone() ; else { // edge 3, scorro sulle patch in V for ( int i = 0 ; i < m_nSpanV ; ++i) { diff --git a/SurfBezier.h b/SurfBezier.h index cbf44e6..b01b1a7 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -19,9 +19,12 @@ #include "CurveComposite.h" #include "SurfTriMesh.h" #include "SurfFlatRegion.h" +//#include "Tree.h" #include "/EgtDev/Include/EGkSurfBezier.h" #include "/EgtDev/Include/EGkGeoCollection.h" +using namespace std ; +class Tree ; //---------------------------------------------------------------------------- class SurfBezier : public ISurfBezier, public IGeoObjRW @@ -132,6 +135,8 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW // funzioni per incrementare le coordinate restando dentro lo spazio parametrico bool IncreaseUV( double& dU, double dx, bool bUOrV, double* dUVCopy = nullptr, bool bModifyOrig = true) const override ; bool IncreaseUV( Point3d& ptUV, Vector3d vtH , Point3d* ptUVCopy, bool bModifyOrig) const override ; + // funzione che restituisce gli edge della superficie o in forma di linea spezzata o in forma di curva di Bezier + // se la superficie è trimmata restituisce i loop dello spazio parametrico in forma di linee spezzate bool GetEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge = -1) const override ; public : // IGeoObjRW @@ -182,7 +187,9 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW double GetCurveOnVApproxLen( double dU) const ; // funzione che proietta nello spazio parametrico un trim derivante da un taglio con un piano, categorizzandolo come aperto o chiuso ( nel parametrico) bool AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, double dToler = EPS_SMALL, const Plane3d* pPlCut = nullptr) const ; + // restituisce il singolo edge della superficie non trimmata ICurveComposite* GetSingleEdge3D( bool bLineOrBezier, int nEdge) const ; + bool UpdateEdgeFromTree( POLYLINEMATRIX& mPl) const ; private : ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto @@ -202,8 +209,10 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW SurfFlatRegion* m_pTrimReg ; // eventuale regione di trim int m_nTempProp[2] ; // vettore proprietà temporanee double m_dTempParam[2] ; // vettore parametri temporanei - mutable ICRVCOMPOPVECTOR m_vCCEdge ;// vettore delle curve compo degli edge nello spazio 3D - mutable POLYLINEVECTOR m_vPLEdge ; // vettore delle polyline degli edge nello spazio 3D + mutable vector m_mCCEdge ;// vettore dei vettori che contengono le curve compo degli edge della superficie nello spazio 3D + mutable POLYLINEMATRIX m_mPlEdge ; // vettoredei vettori delle polyline degli edge della superficie nello spazio 3D + mutable ICRVCOMPOPOVECTOR m_vCCLoop ; // vettore dei loop della superficie trimmata + mutable POLYLINEVECTOR m_vPLLoop ; // vettore delle polyline dei loop della superficie trimmata } ; //----------------------------------------------------------------------------- diff --git a/Tree.cpp b/Tree.cpp index 8b56faf..ad80b37 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -1395,6 +1395,12 @@ Tree::GetPolygons( POLYLINEMATRIX& vPolygons) else { POLYLINEVECTOR vPolygonsBasic ; GetPolygonsBasic( vPolygonsBasic) ; + // aggiungo 4 elementi al vettore che contiene ciò che resta degli edge dopo il trim + for ( int i = 0 ; i < 4 ; ++i) { + m_vCEdge2D.emplace_back() ; + m_vCEdge2D.back().second.Init( false, EPS_SMALL, 1) ; + } + // percorro i loop, trovo le intersezioni con le celle e le categorizzo if ( ! TraceLoopLabelCell( vPolygonsBasic)) return false ; // scorro sulle celle e costruisco i poligoni @@ -1808,6 +1814,40 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells return nCells ; } +//---------------------------------------------------------------------------- +bool +Tree::UpdateSplitLoop( PolyLine& pl, int& nCount, Point3d& pt) +{ + Point3d ptLast ; + pl.GetLastPoint( ptLast) ; + if ( pl.AddUPoint( nCount, pt)) + ++ nCount ; + if ( pl.GetPointNbr() != 1 ) { + Vector3d vtDir = pt - ptLast ; + if ( ! vtDir.Normalize()) + return false ; + // se sono allineato con gli edge della cella ROOT + int nEdge = -1 ; + if ( abs( vtDir.x) > 1 - EPS_SMALL) { + if ( pt.y < EPS_SMALL) + nEdge = 2 ; + else if ( m_nSpanV * SBZ_TREG_COEFF - pt.y < EPS_SMALL) + nEdge = 0 ; + } + else if ( abs( vtDir.y) > 1 - EPS_SMALL) { + if ( pt.x < EPS_SMALL ) + nEdge = 1 ; + else if ( m_nSpanU * SBZ_TREG_COEFF - pt.x < EPS_SMALL ) + nEdge = 3 ; + } + if ( nEdge != -1) { + m_vCEdge2D[nEdge].second.AddCurve( m_vCEdge2D[nEdge].first.size() + 1, ptLast, vtDir, pt, vtDir) ; + m_vCEdge2D[nEdge].first.emplace_back( BIPOINT( ptLast, pt)) ; + } + } + return true ; +} + //---------------------------------------------------------------------------- bool Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) @@ -1820,6 +1860,9 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& 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) m_vPlApprox.size() ; ++ i) { PolyLine plLoop = get<0>( m_vPlApprox[i]) ; + // creo la polyline che aggiunge alla polyline originale degli split dove interseca le celle ( serve per ricostruire gli edge aperti della superficie) + PolyLine plLoopSplit ; + int nPtLoopSplit = 0 ; // controllo se il loop è CCW o CW bool bCCW = get<1>( m_vPlApprox[i]) ; // trovo in quale cella è il ptStart @@ -1831,6 +1874,8 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) advance( ptSecond, 1) ; CurveLine clFirst ; clFirst.Set( ptFirst->first, ptSecond->first) ; + // aggiorno la polyline splittata + UpdateSplitLoop( plLoopSplit, nPtLoopSplit, ptFirst->first) ; // individuo la cella da cui parte il loop INTVECTOR nCells = FindCell( ptStart, clFirst) ; int nId ; @@ -1895,9 +1940,13 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) m_mTree[nId].m_vInters.back().bCCW = bCCW ; // salvo il chunk del loop m_mTree[nId].m_vInters.back().nChunk = m_mChunk[i] ; + // aggiorno la polyline splittata + UpdateSplitLoop( plLoopSplit, nPtLoopSplit, vptInters.back()) ; } // aggiungo la fine del segmento nel vettore delle intersezioni vptInters.push_back( ptCurr) ; + // aggiorno la polyline splittata + UpdateSplitLoop( plLoopSplit, nPtLoopSplit, ptCurr) ; } if ( nId == nFirstCell) vptInters.pop_back() ; @@ -1946,6 +1995,8 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) m_mTree[nId].m_vInters[nPass].nOut = nOut ; } } + // salvo la polyline splittata + m_vPlLoop2D.emplace_back( plLoopSplit) ; } // riordino i vettori di intersezione per ogni cella e setto il flag RightEdgeIn @@ -3556,106 +3607,130 @@ Tree::OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const //---------------------------------------------------------------------------- bool -Tree::GetEdge3D( POLYLINEVECTOR& vPLEdges) -{ - INTMATRIX vEdges ; // le righe sono gli edge a partire dallo 0, le colonne sono le celle che compongono quell'edge - // recupero le celle sui quattro bordi - vEdges.emplace_back() ; - GetRootNeigh( 0, vEdges[0]) ; - // le celle sui bordi orizzontali sono ordinate per x o y crescente, ma i io voglio costruire gli edge in senso antiorario a partire dal ptTR, - // quindi devo invertire gli Edge 0 e 1 - reverse( vEdges[0].begin(), vEdges[0].end()) ; - vEdges.emplace_back() ; - GetRootNeigh( 1, vEdges[1]) ; - reverse( vEdges[1].begin(), vEdges[1].end()) ; - vEdges.emplace_back() ; - GetRootNeigh( 2, vEdges[2]) ; - vEdges.emplace_back() ; - GetRootNeigh( 3, vEdges[3]) ; +Tree::GetEdges3D( POLYLINEMATRIX& mPLEdges) +{ + // se la superficie non è trimmata ricostruisco dalle celle al bordo + if ( ! m_bTrimmed) { + INTMATRIX vEdges ; // le righe sono gli edge a partire dallo 0, le colonne sono le celle che compongono quell'edge + // recupero le celle sui quattro bordi + vEdges.emplace_back() ; + GetRootNeigh( 0, vEdges[0]) ; + // le celle sui bordi orizzontali sono ordinate per x o y crescente, ma i io voglio costruire gli edge in senso antiorario a partire dal ptTR, + // quindi devo invertire gli Edge 0 e 1 + reverse( vEdges[0].begin(), vEdges[0].end()) ; + vEdges.emplace_back() ; + GetRootNeigh( 1, vEdges[1]) ; + reverse( vEdges[1].begin(), vEdges[1].end()) ; + vEdges.emplace_back() ; + GetRootNeigh( 2, vEdges[2]) ; + vEdges.emplace_back() ; + GetRootNeigh( 3, vEdges[3]) ; - // recupero i poligoni base delle celle sui bordi - POLYLINEMATRIX mPL ; - mPL.emplace_back() ; - GetPolygonsBasic( mPL[0], vEdges[0]) ; - mPL.emplace_back() ; - GetPolygonsBasic( mPL[1], vEdges[1]) ; - mPL.emplace_back() ; - GetPolygonsBasic( mPL[2], vEdges[2]) ; - mPL.emplace_back() ; - GetPolygonsBasic( mPL[3], vEdges[3]) ; + // recupero i poligoni base delle celle sui bordi + POLYLINEMATRIX mPL ; + mPL.emplace_back() ; + GetPolygonsBasic( mPL[0], vEdges[0]) ; + mPL.emplace_back() ; + GetPolygonsBasic( mPL[1], vEdges[1]) ; + mPL.emplace_back() ; + GetPolygonsBasic( mPL[2], vEdges[2]) ; + mPL.emplace_back() ; + GetPolygonsBasic( mPL[3], vEdges[3]) ; - // scorro sui gruppi di polyline che rappresentano i poligoni delle celle lungo un lato - for ( int i = 0 ; i < int( mPL.size()) ; ++i) { - vPLEdges.emplace_back() ; - int nPtCount = 0 ; - // scorro sui poligoni delle celle di un lato - for ( int c = 0 ; c < int( mPL[i].size()) ; ++c) { - 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 - if ( i == 0) { - while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[0][c]).GetTopRight()) && mPL[i][c].GetNextPoint( pt)) { - continue ; - } - vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[0][c])[2]) ; - ++ nPtCount ; - // scorro fino alla fine di quel lato - while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[0][c]).GetTopLeft())) { - m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; - vPLEdges.back().AddUPoint( nPtCount, pt3d) ; + // scorro sui gruppi di polyline che rappresentano i poligoni delle celle lungo un lato + for ( int i = 0 ; i < int( mPL.size()) ; ++i) { + //mPLEdges.emplace_back() ; + mPLEdges.back().emplace_back() ; + int nPtCount = 0 ; + // scorro sui poligoni delle celle di un lato + for ( int c = 0 ; c < int( mPL[i].size()) ; ++c) { + 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 + if ( i == 0) { + while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[0][c]).GetTopRight()) && mPL[i][c].GetNextPoint( pt)) { + continue ; + } + mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[0][c])[2]) ; + ++ nPtCount ; + // scorro fino alla fine di quel lato + while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[0][c]).GetTopLeft())) { + m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + mPLEdges.back().back().AddUPoint( nPtCount, pt3d) ; + ++ nPtCount ; + } + mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[0][c])[3]) ; ++ nPtCount ; } - vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[0][c])[3]) ; - ++ nPtCount ; - } - else if ( i == 1 ) { - while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetTopLeft()) && mPL[i][c].GetNextPoint( pt)) { - continue ; - } - vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[1][c])[3]) ; - ++ nPtCount ; - // scorro fino alla fine di quel lato - while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetBottomLeft())) { - m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; - vPLEdges.back().AddUPoint( nPtCount, pt3d) ; + else if ( i == 1 ) { + while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetTopLeft()) && mPL[i][c].GetNextPoint( pt)) { + continue ; + } + mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[1][c])[3]) ; + ++ nPtCount ; + // scorro fino alla fine di quel lato + while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetBottomLeft())) { + m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + mPLEdges.back().back().AddUPoint( nPtCount, pt3d) ; + ++ nPtCount ; + } + mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[1][c])[0]) ; ++ nPtCount ; } - vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[1][c])[0]) ; - ++ nPtCount ; - } - else if ( i == 2) { - while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomLeft()) && mPL[i][c].GetNextPoint( pt)) { - continue ; - } - vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[2][c])[0]) ; - ++ nPtCount ; - // scorro fino alla fine di quel lato - while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomRight())) { - m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; - vPLEdges.back().AddUPoint( nPtCount, pt3d) ; + else if ( i == 2) { + while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomLeft()) && mPL[i][c].GetNextPoint( pt)) { + continue ; + } + mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[2][c])[0]) ; + ++ nPtCount ; + // scorro fino alla fine di quel lato + while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomRight())) { + m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + mPLEdges.back().back().AddUPoint( nPtCount, pt3d) ; + ++ nPtCount ; + } + mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[2][c])[1]) ; ++ nPtCount ; } - vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[2][c])[1]) ; - ++ nPtCount ; - } - else if ( i == 3) { - while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetBottomRight()) && mPL[i][c].GetNextPoint( pt)) { - continue ; - } - vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[3][c])[1]) ; - ++ nPtCount ; - // scorro fino alla fine di quel lato - while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetTopRight())) { - m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; - vPLEdges.back().AddUPoint( nPtCount, pt3d) ; + else if ( i == 3) { + while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetBottomRight()) && mPL[i][c].GetNextPoint( pt)) { + continue ; + } + mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[3][c])[1]) ; + ++ nPtCount ; + // scorro fino alla fine di quel lato + while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetTopRight())) { + m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + mPLEdges.back().back().AddUPoint( nPtCount, pt3d) ; + ++ nPtCount ; + } + mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[3][c])[2]) ; ++ nPtCount ; } - vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[3][c])[2]) ; - ++ nPtCount ; } } } - + // se la superficie è trimmata ricostruisco dai loop splittati ricostruiti durante il TraceLoop + 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) { + INTVECTOR vId ; + Point3d ptNear = m_mTree.at(-1).GetBottomLeft() ; + while( m_vCEdge2D[i].second.GetChainFromNear(ptNear, false, vId) ) { + PolyLine pl2D ; + int nInd = abs( vId[0]) - 1 ; + pl2D.AddUPoint( 0, m_vCEdge2D[i].first[nInd].first) ; + int nCount = 1 ; + for ( int j = 1 ; j < int( vId.size()) ; ++j) { + nInd = abs( vId[j]) - 1 ; + if ( pl2D.AddUPoint( nCount, m_vCEdge2D[i].first[nInd].second)) + ++ nCount ; + } + // qui devo fare dei controlli prima di aggiungere questa polyline? + mPLEdges[i].emplace_back( pl2D) ; + } + } + } return true ; } diff --git a/Tree.h b/Tree.h index d3ee8be..8c45bc7 100644 --- a/Tree.h +++ b/Tree.h @@ -18,6 +18,7 @@ #include "GeoConst.h" #include "CurveLine.h" #include "/EgtDev/Include/EGkPolyLine.h" +#include "/EgtDev/Include/EGkChainCurves.h" #include //---------------------------------------------------------------------------- @@ -241,13 +242,15 @@ class Tree bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells = {}) ; // 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 bool GetLeaves ( std::vector& vLeaves) const ; // restituisce gli indici delle foglie nell'albero - bool GetEdge3D ( POLYLINEVECTOR& vPLEdges) ; // restituisce gli edge 3D come curve composite + bool GetEdges3D ( POLYLINEMATRIX& mPLEdges) ; // restituisce gli edge 3D come polyline + bool GetSplitLoops( POLYLINEVECTOR& vPl) const // funzione che restituisce i loop splitatti ai confini delle celle + { for ( int i = 0 ; i < int( m_vPlLoop2D.size()); ++i) vPl.emplace_back( m_vPlLoop2D[i]) ; return true ; }; void SetTestMode( void) { m_bTestMode = true ;} ; // attivando la test mode, per la costruzione dell'albero viene usata la funzione BuiltTree_test e viene corretta di conseguenza la FindCell // funzioni da usare per ricostruire tagli che vanno aggiunti allo spazio parametrico bool AddCutsToRoot( POLYLINEVECTOR& vCuts) ; // aggiunge i tagli al tree bool CreateCellContour( POLYLINEMATRIX& vPolygons) ; // crea il nuovo contorno esterno, tenendo conto dei tagli - bool IsClosedU( void) { return m_bClosedU ;} ; // funzione che riferisce se la superficie è chiusa lungo il parametro U - bool IsClosedV( void) { return m_bClosedV ;} ; // funzione che riferisce se la superficie è chiusa lungo il parametro V + bool IsClosedU( void) const { return m_bClosedU ;} ; // funzione che riferisce se la superficie è chiusa lungo il parametro U + bool IsClosedV( void) const { return m_bClosedV ;} ; // funzione che riferisce se la superficie è chiusa lungo il parametro V std::vector GetPoles( void) { return m_vbPole ;} ; // funzione che restituisce i flag che indicano se i lati sono collassati in dei poli private : @@ -280,6 +283,7 @@ class Tree bool CheckIfBetween( const Inters& inA, const Inters& inB) const ; // / controllo se inB è compreso tra l'end e lo start di inA (in senso CCW) bool OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const ; // indica a quale edge o vertice il punto è vicino entro EPS_SMALL bool AdjustCuts( void) ; + bool UpdateSplitLoop( PolyLine& pl, int& nCount, Point3d& pt) ; private : @@ -289,7 +293,7 @@ class Tree INTMATRIX m_vChunk ; // elenco dei loop divisi per chunk std::map m_mChunk ; // mappa in cui vengono salvati chunk di appartenza per ogni loop di trim ICURVEPOVECTOR m_vLoop ; // curve di loop - std::vector> m_vPlApprox ; // vettore contenente le approssimazioni dei loop + std::vector> m_vPlApprox ; // vettore contenente le approssimazioni dei loop // il bool indica se la curva è CCW bool m_bBilinear ; // superficie bilineare bool m_bMulti ; // superficie multi-patch bool m_bClosedU ; // superficie chiusa lungo il parametro U @@ -306,4 +310,6 @@ class Tree INTVECTOR m_vnLeaves ; // vettore delle foglie INTVECTOR m_vnParents ; // vettore delle celle ottenute dalla divisione preliminare in singole patch bool m_bTestMode ; // bool che indica se la test mode è attiva + POLYLINEVECTOR m_vPlLoop2D ; // vettore che contiene le polyline che rappresentano i loop di trim tenendo conto della divisione in celle + std::vector> m_vCEdge2D ; // vettore che le chain che rappresentano ciò che resta degli edge originali, tenendo conto dei trim. } ; \ No newline at end of file