From ae52115bdab3f9f09cfcfb48948330cdc3d0740c Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 24 Apr 2024 10:47:50 +0200 Subject: [PATCH] EgtGeomKernel : - aggiunto il contro OFFSET alla SetTrimRegion delle Bezier - aggiunte funzioni varie al tree delle Bezier. --- SurfBezier.cpp | 2 + Tree.cpp | 445 ++++++++++++++++++++++++++++++++++++++++++------- Tree.h | 8 +- 3 files changed, 395 insertions(+), 60 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 87568ca..3364e5a 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -157,6 +157,7 @@ SurfBezier::SetTrimRegion( ISurfFlatRegion& sfrTrimReg, bool bIntersectOrSubtrac pSfrTrim->Offset( 10* EPS_SMALL, ICurve::OFF_EXTEND) ; if ( ! pSfrTrim->Intersect( sfrTrimReg) || ! pSfrTrim->IsValid()) return false ; + pSfrTrim->Offset( -10* EPS_SMALL, ICurve::OFF_EXTEND) ; } } // bIntersectOrSubtract == false per ottenere lo spazio parametrico trimmato devo fare la SOTTRAZIONE tra il rettangolo totale e l'area passata @@ -166,6 +167,7 @@ SurfBezier::SetTrimRegion( ISurfFlatRegion& sfrTrimReg, bool bIntersectOrSubtrac pSfrTrim->Offset( 10* EPS_SMALL, ICurve::OFF_EXTEND) ; if ( ! pSfrTrim->Subtract( sfrTrimReg) || ! pSfrTrim->IsValid()) return false ; + pSfrTrim->Offset( -10* EPS_SMALL, ICurve::OFF_EXTEND) ; } } ResetAuxSurf() ; diff --git a/Tree.cpp b/Tree.cpp index f7f4224..7981f74 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -20,6 +20,7 @@ #include "CurveComposite.h" #include "SurfFlatRegion.h" #include "IntersLineLine.h" +#include "AdjustLoops.h" #include "/EgtDev/Include/EGkPolyLine.h" #include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EGkCurve.h" @@ -27,6 +28,7 @@ #include "/EgtDev/Include/EGkSfrCreate.h" #include #include +#include "/EgtDev/Include/EGkGeoObjSave.h" using namespace std ; @@ -64,36 +66,144 @@ Tree::Tree( const Point3d ptBl, const Point3d ptTr) //---------------------------------------------------------------------------- bool -Tree::LimitLoop( PolyLine& pl, POLYLINEVECTOR& vPl) const +Tree::LimitLoop( PolyLine& pl, POLYLINEVECTOR& vPl, BOOLVECTOR& vbOrientation) const { - // creo la flat region di trim, quella del parametrico e li interseco - PtrOwner pSfrTrim( GetSurfFlatRegionFromPolyLine( pl)) ; - bool bInverted = false ; - if ( ! pSfrTrim->GetNormVersor().IsZplus()) { - pSfrTrim->Invert() ; - bInverted = true ; - } - PtrOwner pParamTrim( GetSurfFlatRegionRectangle( SBZ_TREG_COEFF * m_nSpanU, SBZ_TREG_COEFF * m_nSpanV)) ; - if ( ! pParamTrim->Intersect( *pSfrTrim) || ! pParamTrim->IsValid()) { - pParamTrim->Offset( 10 * EPS_SMALL, ICurve::OFF_EXTEND) ; - if ( ! pParamTrim->Intersect( *pSfrTrim) || ! pParamTrim->IsValid()) - return false ; + // //questo metodo NON VA BENE perchè tiene anche parte dei loop che stanno fuori dal parametrico e quindi il FINDCELL può fallire + // + //// creo la flat region di trim, quella del parametrico e li interseco + //PtrOwner pSfrTrim( GetSurfFlatRegionFromPolyLine( pl)) ; + //bool bInverted = false ; + //if ( ! pSfrTrim->GetNormVersor().IsZplus()) { + // pSfrTrim->Invert() ; + // bInverted = true ; + //} + //PtrOwner pParamTrim( GetSurfFlatRegionRectangle( SBZ_TREG_COEFF * m_nSpanU, SBZ_TREG_COEFF * m_nSpanV)) ; + //if ( ! pParamTrim->Intersect( *pSfrTrim) || ! pParamTrim->IsValid()) { + // if ( ! pParamTrim->Offset( 10 * EPS_SMALL, ICurve::OFF_EXTEND)) + // return false ; + // if ( ! pParamTrim->Intersect( *pSfrTrim) || ! pParamTrim->IsValid()) + // return false ; + // if ( ! pParamTrim->Offset( -10 * EPS_SMALL, ICurve::OFF_EXTEND)) + // return false ; + //} + + //// ricostruisco la curva tenendo solo le parti dentro lo spazio parametrico + //// devo recuperare la polyline dei bordi dei vari chunk creati + //for ( int c = 0 ; c < int( pParamTrim->GetChunkCount()) ; ++c) { + // for ( int l = 0 ; l < pParamTrim->GetLoopCount(c) ; ++l) { + // PtrOwner pCrv ( pParamTrim->GetLoop( c, l)) ; + // if ( bInverted) + // pCrv->Invert() ; + // PolyLine plApprox ; + // double dLinTol = 10 * EPS_SMALL, dAngTolDeg = 5 ; + // int nType = 0 ; + // pCrv->ApproxWithLines( dLinTol, dAngTolDeg, nType, plApprox) ; + // // aggiungo la polyline del chunk + // vPl.push_back( plApprox) ; + // } + //} + + + + //// CON LE CURVE ( INTERSEZIONI CON BORDO PARAMETRICO) + PtrOwner pCCEdge( CreateCurveComposite()) ; + pCCEdge->AddPoint( m_mTree.at(-1).GetTopRight()) ; + pCCEdge->AddLine( m_mTree.at(-1).GetTopLeft()) ; + pCCEdge->AddLine( m_mTree.at(-1).GetBottomLeft()) ; + pCCEdge->AddLine( m_mTree.at(-1).GetBottomRight()) ; + pCCEdge->Close() ; + + PtrOwner pCC( CreateCurveComposite()) ; + pCC->FromPolyLine( pl) ; + ICURVEPLIST vCrv ; + AdjustLoops( Release( pCC), vCrv, false) ; + + if ( vCrv.size() > 1) + VerifyLoopOrientation( vCrv, vbOrientation) ; + for ( auto itCrv = vCrv.begin() ; itCrv != vCrv.end() ; ++itCrv) { + IntersCurveCurve icc( *pCCEdge, *(*itCrv)) ; + CRVCVECTOR vCrvClass ; + ICRVCOMPOPOVECTOR vCC ; + if ( ! icc.GetCurveClassification( 1, 0.01, vCrvClass)) + return false ; // se non riesco a calcolare la classificazione potrei provare a ricostruire a mano usando le intersezioni trovate + int nLast = 0 ; + if ( vCrvClass.size() > 1) { + for ( int i = 0 ; i < int( vCrvClass.size()) ; ++i) { + if ( vCrvClass[i].nClass != CRVC_OUT) { + // se continua la curva precedente allora la giunta + if ( vCC.size() != 0 && vCrvClass[i].dParS == vCrvClass[nLast].dParE) + vCC.back()->AddCurve( (*itCrv)->CopyParamRange( vCrvClass[i].dParS, vCrvClass[i].dParE)) ; + // sennò creo una nuova curva + else + vCC.emplace_back( GetCurveComposite( (*itCrv)->CopyParamRange( vCrvClass[i].dParS, vCrvClass[i].dParE))) ; + nLast = i ; + } + } + + POLYLINEVECTOR vPL ; + // qui devo ricostruire la curva con i pezzi da tenere + for ( int i = 0 ; i < int( vCC.size()) ; ++i) { + PolyLine plApprox ; + vCC[i]->ApproxWithLines( 0.01,15, 0, plApprox) ; + vPL.push_back( plApprox) ; + } + PolyLine plNew ; + // ricostruzione col bordo + CloseOpenCuts( vPL, plNew) ; + vPl.push_back( plNew) ; + } + else { + PolyLine plApprox ; (*itCrv)->ApproxWithLines( 0.01, 15, 0, plApprox) ; + vPl.push_back( plApprox) ; + } } - // ricostruisco la curva tenendo solo le parti dentro lo spazio parametrico - // devo recuperare la polyline dei bordi dei vari chunk creati - for ( int c = 0 ; c < int( pParamTrim->GetChunkCount()) ; ++c) { - PtrOwner pCrv ( pParamTrim->GetLoop( c, 0)) ; - if ( bInverted) - pCrv->Invert() ; - PolyLine plApprox ; - double dLinTol = 10 * EPS_SMALL, dAngTolDeg = 5 ; - int nType = 0 ; - pCrv->ApproxWithLines( dLinTol, dAngTolDeg, nType, plApprox) ; - // aggiungo la polyline del chunk + for ( auto it = vCrv.begin() ; it != vCrv.end() ; ++it) + delete (*it) ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +Tree::VerifyLoopOrientation( ICURVEPLIST& vpCrv, BOOLVECTOR& vbOrientation) const +{ + // verifico che il verso dei loop sia corretto controllando le relazioni tra loop + vpCrv.sort( []( ICurve* a, ICurve* b) { double AreaA, AreaB ; a->GetAreaXY( AreaA) ; b->GetAreaXY( AreaB) ; return abs(AreaA) > abs(AreaB) ;}) ; + auto it = vpCrv.begin() ; + for ( ++it ; it != vpCrv.end() ; ++it) { + bool bIdentified = false ; + for ( auto k = it ; k != vpCrv.begin() ;) { + --k ; + IntersCurveCurve icc( **k, **it) ; + int nRes = icc.GetRegionCurveClassification() ; + if ( nRes == CCREGC_IN1) { + bIdentified = true ; + vbOrientation.push_back( ! vbOrientation[ distance( vpCrv.begin(), k)]) ; // l'orientazione deve essere opposta alla prima curva che contiene la corrente + break ; + } + } + if ( ! bIdentified) + vbOrientation.push_back( vbOrientation[0]) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +Tree::AdjustLoop( PolyLine& pl, POLYLINEVECTOR& vPl, BOOLVECTOR& vbOrientation) const +{ + PtrOwner pCC( CreateCurveComposite()) ; + pCC->FromPolyLine( pl) ; + ICURVEPLIST vCrv ; + AdjustLoops( Release( pCC), vCrv, false) ; + + if ( vCrv.size() > 1) + VerifyLoopOrientation( vCrv, vbOrientation) ; + for ( auto itCrv = vCrv.begin() ; itCrv != vCrv.end() ; ++itCrv) { + PolyLine plApprox ; (*itCrv)->ApproxWithLines( 0.01, 15, 0, plApprox) ; vPl.push_back( plApprox) ; } - return true ; } @@ -108,7 +218,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi m_vnLeaves.clear() ; m_vnParents.clear() ; m_mVert.clear() ; - m_vLoop.clear() ; + //m_vLoop.clear() ; m_mChunk.clear() ; m_vPlApprox.clear() ; m_vPolygons.clear() ; @@ -129,6 +239,15 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi m_bBilinear = true ; if ( nSpanU * nSpanV != 1) m_bMulti = true ; + // creo la cella Root + Point3d ptTop( nSpanU * SBZ_TREG_COEFF, nSpanV * SBZ_TREG_COEFF) ; + bool bLimited = false ; + if ( ! AreSamePointExact( ptMax,ORIG) && ! AreSamePointExact( ptMax,ptTop)) { + ptTop = ptMax ; + bLimited = true ; + } + Cell cRoot( ptMin, ptTop) ; + m_mTree.insert( pair< int, Cell>( -1, cRoot)) ; // recupero i loop di trim e li divido per chunk if ( m_bTrimmed) { int nLoop = 0 ; @@ -139,7 +258,6 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi for ( int i = 0 ; i < pTrimReg->GetChunkCount() ; ++ i) { PtrOwner pChunk( pTrimReg->CloneChunk( i)) ; for ( int j = 0 ; j < pChunk->GetLoopCount( 0) ; ++ j) { - //vChunk.push_back( nLoop) ; // i chunk della falt region sono ancora flat region composte da 1 chunk PtrOwner pLoop ( pChunk->GetLoop( 0, j)) ; // rimuovo i difetti dei loop prima di salvarli @@ -148,9 +266,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi pCrvCompo->RemoveSmallDefects( dLinTol, dAngTolDeg, true) ; pCrvCompo->RemoveSmallParts( dLinTol, dAngTolDeg) ; PtrOwner pCrv( pCrvCompo->Clone()) ; - m_vLoop.emplace_back( Release( pLoop)) ; - m_mChunk[nLoop] = i ; - ++ nLoop ; + // approssimo i loop di trim con delle spezzate PolyLine plApprox ; int nType = 0 ; @@ -164,25 +280,23 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi bCCW = true ; else bCCW = false ; - // limito il loop allo spazio parametrico // potrei ottenere più loop a partire da quello originale - POLYLINEVECTOR vPlLimited ; - if ( ! LimitLoop( plApprox, vPlLimited)) - return false ; - for ( int k = 0 ; k < int( vPlLimited.size()) ; ++k) - m_vPlApprox.push_back( tuple(vPlLimited[k], bCCW)) ; + + POLYLINEVECTOR vPlAdjusted ; + BOOLVECTOR vbOrientation ; + vbOrientation.push_back( bCCW) ; + AdjustLoop( plApprox, vPlAdjusted, vbOrientation) ; + + nLoop = int ( m_vPlApprox.size()) ; + for ( int k = 0 ; k < int( vPlAdjusted.size()) ; ++k ) + m_vPlApprox.push_back( tuple(vPlAdjusted[k], vbOrientation[k])) ; + // aggiorno la mappa del chunk di appartenenza per tutti i loop aggiunti // do per scontato che siano tutti dello stesso chunk anche se li ho separati + //m_vLoop.emplace_back( Release( pLoop)) ; + for ( int k = nLoop ; k < int( m_vPlApprox.size()); ++k) + m_mChunk[k] = i ; } } } // salvo i vertici 3d della cella root - Point3d ptTop( nSpanU * SBZ_TREG_COEFF, nSpanV * SBZ_TREG_COEFF) ; - bool bLimited = false ; - if ( ! AreSamePointExact( ptMax,ORIG) && ! AreSamePointExact( ptMax,ptTop)) { - ptTop = ptMax ; - bLimited = true ; - } - //m_mTree.clear() ; - Cell cRoot( ptMin, ptTop) ; - m_mTree.insert( pair< int, Cell>( -1, cRoot)) ; Point3d ptP00, ptP10, ptP11, ptP01 ; bool bOk = false ; if ( ! bLimited) { @@ -1049,7 +1163,7 @@ Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const for ( int k : vTopNeighs) vCells.push_back( m_mTree.at( k)) ; // le celle restituite sono ordinate per x crescente - sort( vCells.begin(), vCells.end(), Cell::minorX) ; + std::sort( vCells.begin(), vCells.end(), Cell::minorX) ; vTopNeighs.clear() ; for ( Cell c : vCells) vTopNeighs.push_back( c.m_nId) ; @@ -1131,7 +1245,7 @@ Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const for ( int k : vBottomNeighs) vCells.push_back( m_mTree.at( k)) ; // le celle restituite sono ordinate per x crescente - sort( vCells.begin(), vCells.end(), Cell::minorX) ; + std::sort( vCells.begin(), vCells.end(), Cell::minorX) ; vBottomNeighs.clear() ; for ( Cell c : vCells) vBottomNeighs.push_back( c.m_nId) ; @@ -1212,7 +1326,7 @@ Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const for ( int k : vLeftNeighs) vCells.push_back( m_mTree.at( k)) ; // le celle restituite sono ordinate per y crescente - sort( vCells.begin(), vCells.end(), Cell::minorY) ; + std::sort( vCells.begin(), vCells.end(), Cell::minorY) ; vLeftNeighs.clear() ; for ( Cell c : vCells) vLeftNeighs.push_back( c.m_nId) ; @@ -1293,7 +1407,7 @@ Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const for ( int k : vRightNeighs) vCells.push_back( m_mTree.at( k)) ; // le celle restituite sono ordinate per y crescente - sort( vCells.begin(), vCells.end(), Cell::minorY) ; + std::sort( vCells.begin(), vCells.end(), Cell::minorY) ; vRightNeighs.clear() ; for ( Cell c : vCells) vRightNeighs.push_back( c.m_nId) ; @@ -1428,6 +1542,7 @@ Tree::GetPolygons( POLYLINEMATRIX& vPolygons) POLYLINEVECTOR vPolygonsBasic ; GetPolygonsBasic( vPolygonsBasic) ; // aggiungo 4 elementi al vettore che contiene ciò che resta degli edge dopo il trim + m_vCEdge2D.clear() ; for ( int i = 0 ; i < 4 ; ++i) { m_vCEdge2D.emplace_back() ; m_vCEdge2D.back().second.Init( false, EPS_SMALL, 1) ; @@ -1560,7 +1675,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells) vNeigh.clear() ; vVertices.push_back( m_mTree.at( nId).GetTopRight()) ; GetTopNeigh ( nId, vNeigh) ; - reverse( vNeigh.begin(), vNeigh.end()) ; + std::reverse( vNeigh.begin(), vNeigh.end()) ; // aggiungo i vertici che sono sul lato top, solo se ho più di un vicino top if ( ! vNeigh.empty() && vNeigh.size() != 1) { // se la superficie è chiusa lungo il parametro V e la cella è sul lato top @@ -1581,7 +1696,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells) bTopLeft = false ; vNeigh.clear() ; GetLeftNeigh ( nId, vNeigh) ; - reverse( vNeigh.begin(), vNeigh.end()) ; + std::reverse( vNeigh.begin(), vNeigh.end()) ; // aggiungo i vertici che sono sul lato left, solo se ho più di un vicino left if ( (int) vNeigh.size() != 0 && (int) vNeigh.size() != 1) { // se la superficie è chiusa lungo il parametro U e la cella è sul lato left @@ -2034,7 +2149,7 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) // riordino i vettori di intersezione per ogni cella e setto il flag RightEdgeIn for ( int nId : m_vnLeaves) { - sort( m_mTree[nId].m_vInters.begin(), m_mTree[nId].m_vInters.end()) ; + std::sort( m_mTree[nId].m_vInters.begin(), m_mTree[nId].m_vInters.end()) ; SetRightEdgeIn( nId) ; } @@ -2319,7 +2434,7 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool INTVECTOR vNeigh, vNeigh1 ; if ( nEdge == 0) { GetTopNeigh( nId, vNeigh) ; - reverse( vNeigh.begin(), vNeigh.end()) ; + std::reverse( vNeigh.begin(), vNeigh.end()) ; for ( int j : vNeigh) { if ( ptInters.x >= m_mTree[j].GetBottomLeft().x) { nId = j ; @@ -2339,7 +2454,7 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool } else if ( nEdge == 1) { GetLeftNeigh( nId, vNeigh) ; - reverse( vNeigh.begin(), vNeigh.end()) ; + std::reverse( vNeigh.begin(), vNeigh.end()) ; for ( int j : vNeigh) { if ( ptInters.y >= m_mTree[j].GetBottomLeft().y) { nId = j ; @@ -3641,6 +3756,8 @@ Tree::OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const nEdge = 2 ; else if ( ptToAssign.y > ptBL.y && ptToAssign.y < ptTR.y && abs( ptToAssign.x - ptTR.x) < EPS_SMALL) nEdge = 3 ; + else if ( ptToAssign.y > ptBL.y && ptToAssign.y < ptTR.y && ptToAssign.x > ptBL.x && ptToAssign.x < ptTR.x) + nEdge = -1 ; else return false ; return true ; @@ -3658,10 +3775,10 @@ Tree::GetEdges3D( POLYLINEMATRIX& mPLEdges) 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()) ; + std::reverse( vEdges[0].begin(), vEdges[0].end()) ; vEdges.emplace_back() ; GetRootNeigh( 1, vEdges[1]) ; - reverse( vEdges[1].begin(), vEdges[1].end()) ; + std::reverse( vEdges[1].begin(), vEdges[1].end()) ; vEdges.emplace_back() ; GetRootNeigh( 2, vEdges[2]) ; vEdges.emplace_back() ; @@ -3871,12 +3988,12 @@ Tree::AdjustCuts( void) if ( int( m_mTree.at( -1).m_vInters.size()) == 1) return true ; // li riordino per ordine di quali taglio incontrerei percorrendo il bordo della cella a partire da ptTR - sort( m_mTree.at( -1).m_vInters.begin(), m_mTree.at( -1).m_vInters.end(), [](Inters& a, Inters& b){ return Inters::FirstEncounter(a,b) ;}) ; + std::sort( m_mTree.at( -1).m_vInters.begin(), m_mTree.at( -1).m_vInters.end(), [](Inters& a, Inters& b){ return Inters::FirstEncounter(a,b) ;}) ; // ora controllo che le intersezioni che trovo siano ingressi alternati ad uscite, sennò inverto l'intersezione bool bPreviousWasStart = m_mTree.at( -1).m_vInters.at(0).bSortedbyStart ; for ( int i = 0 ; i < int( m_mTree.at( -1).m_vInters.size()); ++i) { if ( m_mTree.at( -1).m_vInters.at(i).bSortedbyStart == bPreviousWasStart) { - reverse( m_mTree.at( -1).m_vInters.at(i).vpt.begin(), m_mTree.at( -1).m_vInters.at(i).vpt.end()) ; + std::reverse( m_mTree.at( -1).m_vInters.at(i).vpt.begin(), m_mTree.at( -1).m_vInters.at(i).vpt.end()) ; int nEdgeOutNew = m_mTree.at( -1).m_vInters.at(i).nIn ; m_mTree.at( -1).m_vInters.at(i).nIn = m_mTree.at( -1).m_vInters.at(i).nOut ; m_mTree.at( -1).m_vInters.at(i).nOut = nEdgeOutNew ; @@ -3916,5 +4033,217 @@ Tree::CreateCellContour( POLYLINEMATRIX& vPolygons) if ( nPolyBefore == nPoly) break ; } + return true ; +} + +//---------------------------------------------------------------------------- +bool +Tree::CloseOpenCuts( POLYLINEVECTOR& vPL, PolyLine& plNew) const // da verificare e comunque funzione probabilmente inutile +{ + if ( vPL.size() == 1 && vPL[0].IsClosed()) { + plNew = vPL[0] ; + return true ; + } + + vector vInters ; + for ( int i = 0 ; i < int( vPL.size()) ; ++i) { + vInters.emplace_back() ; + Point3d ptStart ; vPL[i].GetFirstPoint( ptStart) ; + OnWhichEdge( -1, ptStart, vInters.back().nIn) ; + Point3d ptEnd ; vPL[i].GetLastPoint( ptEnd) ; + OnWhichEdge( -1, ptEnd, vInters.back().nOut) ; + PNTULIST lPnt = vPL[i].GetUPointList() ; + for ( auto it = lPnt.begin() ; it != lPnt.end() ; ++it) + vInters.back().vpt.push_back( (*it).first) ; + } + + std::sort( vInters.begin(), vInters.end(), [](Inters &left, Inters &right) { return left < right;}) ; + bool bNotCameBack = true ; + int nEdge = vInters[0].nOut ; + PNTULIST lPnt = vPL[0].GetUPointList() ; + for ( auto it = lPnt.begin() ; it != lPnt.end() ; ++it) + plNew.AddUPoint( (*it).second, (*it).first) ; + // se ero in un vertice passo all'edge successivo + if ( nEdge > 3 && nEdge != 7) + nEdge = nEdge - 4 ; + else if ( nEdge == 7) + nEdge = 0 ; + int nInters = 0 ; + while ( bNotCameBack) { + bool bAtNextStart = false ; + //PolyLine plEdge ; + double dCount ; plNew.GetLastU( dCount) ; + plNew.AddUPoint( dCount, vInters[nInters].vpt.back()) ; + ++ dCount ; + ++ nInters ; + if ( nInters == vInters.size()) + nInters = 0 ; + // scorro tutti i lati finché non torno allo start del loop + while( ! bAtNextStart) { + Point3d ptToAdd ; + if ( nEdge == 0) + ptToAdd = m_mTree.at(-1).GetTopLeft() ; + else if ( nEdge == 1) + ptToAdd = m_mTree.at(-1).GetBottomLeft() ; + else if ( nEdge == 2) + ptToAdd = m_mTree.at(-1).GetBottomRight() ; + else if ( nEdge == 3) + ptToAdd = m_mTree.at(-1).GetTopRight() ; + if ( plNew.AddUPoint( dCount, ptToAdd)) + ++ dCount ; + if ( nEdge > 3 && nEdge != 7) + nEdge = nEdge - 4 ; + else if ( nEdge < 3) + ++ nEdge ; + else + nEdge = 0 ; + if ( AreSameEdge(nEdge,vInters[nInters].nIn)) + bAtNextStart = true ; + } + if ( nInters != 0 && nInters < int(vPL.size())) { + // aggiungo la polyline successiva + PNTULIST lPnt = vPL[nInters].GetUPointList() ; + double dLastU ; vPL[nInters-1].GetLastU( dLastU) ; + ++ dLastU ; + for ( auto it = lPnt.begin() ; it != lPnt.end() ; ++it) + plNew.AddUPoint( dLastU + (*it).second, (*it).first) ; + } + if ( AreSameEdge(nEdge, vInters[0].nIn)) { + plNew.Close() ; + bNotCameBack = false ; + } + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +Tree::CloseOpenCuts( void) +{ + int nRoot = -1 ; + // tra i loop del parametrico seleziono quelli aperti + // creo il vettore inters, lo riordino e poi rendo chiusi i loop ( che possono restare indipendenti o unirsi ad altri loop aperti) + INTVECTOR vOpen ; + for ( int i = 0 ; i < int(m_vPlApprox.size()) ; ++i ) { + if ( ! get<0>(m_vPlApprox[i]).IsClosed()) { + m_mTree.at( nRoot).m_vInters.emplace_back() ; + Point3d ptStart ; get<0>(m_vPlApprox[i]).GetFirstPoint( ptStart) ; + OnWhichEdge( nRoot, ptStart, m_mTree.at( nRoot).m_vInters.back().nIn) ; + Point3d ptEnd ; get<0>(m_vPlApprox[i]).GetLastPoint( ptEnd) ; + OnWhichEdge( nRoot, ptEnd, m_mTree.at( nRoot).m_vInters.back().nOut) ; + vOpen.push_back( i) ; + } + } + // riordino le intersezioni + std::sort( m_mTree.at(nRoot).m_vInters.begin(), m_mTree.at(nRoot).m_vInters.end()) ; + + m_vnLeaves.push_back( -1) ; + // chiamo la GetPolygons + POLYLINEMATRIX mPL ; + GetPolygons( mPL) ; + + //creo il nuovo vettore di polyline di trim + // tengo quelli che erano i trim chiusi + for ( int t = int(vOpen.size()) - 1 ; t > -1 ; ++t ) { + m_vPlApprox.erase( m_vPlApprox.begin() + vOpen[t]) ; + } + + // aggiungo i nuovi trim creati + for ( int t = 0 ; t < int( mPL[0].size()) ; ++t) { + m_vPlApprox.push_back( pair(mPL[0][t], true)) ; + } + + m_vnLeaves.clear() ; + m_mTree.at( nRoot).m_vInters.clear() ; + + //// tra i loop del parametrico seleziono quelli aperti + //// creo il vettore inters, lo riordino e poi rendo chiusi i loop ( che possono restare indipendenti o unirsi ad altri loop aperti) + //vector> vInters ; + //INTVECTOR vClosed ; + //for ( int i = 0 ; i < int(m_vPlApprox.size()) ; ++i ) { + // if ( ! get<0>(m_vPlApprox[i]).IsClosed()) { + // vInters.emplace_back() ; + // vInters.back().first = i ; + // Point3d ptStart ; get<0>(m_vPlApprox[i]).GetFirstPoint( ptStart) ; + // OnWhichEdge( -1, ptStart, vInters.back().second.nIn) ; + // Point3d ptEnd ; get<0>(m_vPlApprox[i]).GetLastPoint( ptEnd) ; + // OnWhichEdge( -1, ptEnd, vInters.back().second.nOut) ; + // } + // else + // vClosed.push_back( i) ; + //} + + //// A MANO + //// chiudo le curve aperte e se necessario le giunto tra loro + //if ( vInters.size() != 0) { + // ICurveComposite* pCCOpen ( CreateBasicCurveComposite()) ; + // pCCOpen->FromPolyLine( get<0>(m_vPlApprox[vInters[0].first])) ; + // //sort( vInters.begin(), vInters.end()) ; + // sort( vInters.begin(), vInters.end(), [](pair &left, pair &right) { return left.second < right.second;}) ; + // bool bNotCameBack = true ; + // int nEdge = vInters[0].second.nOut ; + + // // se ero in un vertice passo all'edge successivo + // if ( nEdge > 3 && nEdge != 7) + // nEdge = nEdge - 4 ; + // else if ( nEdge == 7) + // nEdge = 0 ; + // int nInters = 0 ; + // while ( bNotCameBack) { + // bool bAtNextStart = false ; + // PolyLine plEdge ; + // int nCount = 0 ; + // plEdge.AddUPoint( nCount, vInters[nInters].ptEnd) ; + // ++ nCount ; + // ++ nInters ; + // if ( nInters == vInters.size()) + // nInters = 0 ; + // // scorro tutti i lati finché non torno allo start del loop + // while( ! bAtNextStart) { + // Point3d ptToAdd ; + // if ( nEdge == 0) + // ptToAdd = m_mTree.at(-1).GetTopLeft() ; + // else if ( nEdge == 1) + // ptToAdd = m_mTree.at(-1).GetBottomLeft() ; + // else if ( nEdge == 2) + // ptToAdd = m_mTree.at(-1).GetBottomRight() ; + // else if ( nEdge == 3) + // ptToAdd = m_mTree.at(-1).GetTopRight() ; + // if ( plEdge.AddUPoint( nCount, ptToAdd)) + // ++ nCount ; + // if ( nEdge > 3 && nEdge != 7) + // nEdge = nEdge - 4 ; + // else if ( nEdge < 3) + // ++ nEdge ; + // else + // nEdge = 0 ; + // if ( AreSameEdge(nEdge,vInters[nInters].second.nIn)) + // bAtNextStart = true ; + // } + // ICurveComposite* pCC( CreateCurveComposite()) ; + // pCC->FromPolyLine( plEdge) ; + // // aggiungo il tratto di edge + // pCCOpen->AddCurve( pCC) ; + // // agggiungo il prossio taglio + // if ( nInters != 0) + // pCCOpen->AddCurve( Release( vInters[nInters].pCrv)) ; + // if ( AreSameEdge(nEdge, vInters[0].second.nIn)) { + // pCCOpen->Close() ; + // bNotCameBack = false ; + // } + // } + // if ( ! pCCOpen->IsClosed()) { + // LOG_ERROR( pGenLog, "Error creating the contour from open trims") ; + // return nullptr ; + // } + // if ( ! bPlanarSurf) { + // if ( ! SimplifyCurve( pCCOpen)) { + // LOG_ERROR( pGenLog, "Error simplifying the contour recreated from the open trims") ; + // return nullptr ; + // } + // } + // SfrCntr.AddCurve( pCCOpen) ; + //} + return true ; } \ No newline at end of file diff --git a/Tree.h b/Tree.h index e656220..39a6cd1 100644 --- a/Tree.h +++ b/Tree.h @@ -254,7 +254,7 @@ class Tree std::vector GetPoles( void) { return m_vbPole ;} ; // funzione che restituisce i flag che indicano se i lati sono collassati in dei poli private : - bool LimitLoop( PolyLine& pl, POLYLINEVECTOR& vPl) const ; // funzione che limita i loop di trim allo spazio parametrico + bool LimitLoop( PolyLine& pl, POLYLINEVECTOR& vPl, BOOLVECTOR& vbOrientation) const ; // funzione che limita i loop di trim allo spazio parametrico bool Split( int nId, double dSplitValue) ; // funzione di split di una cella al parametro indicato nella direzione data da bVert bool Split( int nId) ; // funzione di split di una cella dell'albero a met� nella direzione data da bVert void Balance( void) ; // creo rami in modo che tutte tutte le foglie abbiano come adiacenti foglie ad una profondit� di +- 1 @@ -285,6 +285,10 @@ class Tree 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) ; + bool CloseOpenCuts( void) ; + bool CloseOpenCuts( POLYLINEVECTOR& vPL, PolyLine& pl) const ; + bool VerifyLoopOrientation( ICURVEPLIST& vpCrv, BOOLVECTOR& vbOrientation) const ; // verifico l'orientazione ( CCW o CW) delle polyline in base a come sono contenute le une nelle altre + bool AdjustLoop( PolyLine& pl, POLYLINEVECTOR& vPl, BOOLVECTOR& vbOrientation) const ; private : @@ -293,7 +297,7 @@ class Tree bool m_bTrimmed ; // superficie trimmata //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 + //ICURVEPOVECTOR m_vLoop ; // curve di 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