From 3a623996d2317b4e2e34e666044e4d6119af909d Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 26 Feb 2024 09:48:02 +0100 Subject: [PATCH] =?UTF-8?q?EgtGeomKernel=20:=20-=20corretta=20la=20funzion?= =?UTF-8?q?e=20per=20il=20trim=20di=20sup.=20di=20Bezier=20con=20piani,=20?= =?UTF-8?q?in=20zone=20di=20salto=20per=20periodicit=C3=A0=20e=20in=20caso?= =?UTF-8?q?=20di=20tagli=20multipli.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SurfBezier.cpp | 337 +++++++++++++++++++++++-------------------------- 1 file changed, 159 insertions(+), 178 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index c40e390..26d8e37 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -36,6 +36,7 @@ #include "/EgtDev/Extern/Eigen/Dense" #include "/EgtDev/Include/EGkCurveComposite.h" #include "/EgtDev/Include/EGkGeoObjSave.h" +#include using namespace std ; @@ -1647,6 +1648,22 @@ SurfBezier::AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& return true ; } +typedef tuple TRINT ; + +//static bool operator==(TRINT& ta, TRINT& tb) +//{ +// return get<0>(ta) == get<0>(tb) && get<1>(ta) == get<1>(tb) && get<2>(ta) == get<2>(tb) ; +//} + +template<> +struct hash { + std::size_t operator()(const TRINT& t) const + { + // Compute individual hash values for first, second and third and combine them using XOR and bit shifting: + return ((hash()(get<0>(t))) ^ (hash()(get<1>(t)) << 1) >> 1) ^ (hash()(get<2>(t)) << 1) ; + } +}; + //---------------------------------------------------------------------------- bool SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) @@ -1772,12 +1789,12 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) } AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed) ; } - ////debug - //vector vGeoObj ; - //for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) - // vGeoObj.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; - //SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\sphere_openCuts_beforeJoint.nge") ; - ////debug + //debug + vector vGeoObj ; + for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) + vGeoObj.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; + SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\sphere_openCuts_beforeJoint.nge") ; + //debug if ( int( vpCCOpen.size()) != 0) { // devo verificare se devo giuntare la prima curva aperta con l'ultima Point3d ptStartOpen, ptEndOpen ; @@ -1790,188 +1807,162 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) } } - // creo il nuovo bordo usando i loop aperti - //POLYLINEMATRIX vPolygons ; + + //comincio a creare la superficie aggiungendo i tagli aperti ai bordi attualmente esistenti + SurfFlatRegionByContours sfrContour ; if ( int(vpCCOpen.size()) != 0 ) { - //Tree Tree(Point3d( 0, 0, 0), Point3d( m_nSpanU * SBZ_TREG_COEFF, m_nSpanV * SBZ_TREG_COEFF)) ; - //POLYLINEVECTOR vPL ; - //for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) { - // PolyLine pl ; - // vpCCOpen[i]->ApproxWithLines( LIN_TOL_FINE, ANG_TOL_STD_DEG, ICurveComposite::APL_STD, pl) ; - // vPL.emplace_back( pl) ; - //} - //Tree.AddCutsToRoot( vPL) ; - - //////debug - ////vector vGeoObj ; - ////for ( int k = 0 ; k < int( vPL.size()) ; ++ k) { - //// PtrOwner pCrv( CreateCurveComposite()) ; - //// pCrv->FromPolyLine( vPL[k]) ; - //// vGeoObj.emplace_back( static_cast(Release( pCrv))) ; - ////} - ////SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\sphere_openCuts.nge") ; - //////debug - - //Tree.CreateCellContour( vPolygons) ; - - - // qui devo aggiungere tutto del codice nuovo per ricostruire in altro modo il nuovo bordo della superficie // recupero la regione attuale - PtrOwner pNewTrim( GetTrimRegion()->Clone()) ; - + unordered_map mInters ; + // costruisco la mappa delle intersezioni + PtrOwner pNewTrim( CreateBasicSurfFlatRegion()) ; + if ( m_bTrimmed) + pNewTrim.Set( GetTrimRegion()->Clone()) ; + else + pNewTrim.Set( GetSurfFlatRegionRectangle( SBZ_TREG_COEFF * m_nSpanU, SBZ_TREG_COEFF * m_nSpanV)) ; + //debug + PtrOwner pSrfCopy( pNewTrim->Clone()) ; + SaveGeoObj( Release(pSrfCopy), "D:\\Temp\\inters\\sphere_actualTrimRegion.nge") ; + //debug + + ////debug + //PtrOwner pCrvCopy( pNewTrim->GetLoop(0,0)) ; + //SaveGeoObj( Release(pCrvCopy), "D:\\Temp\\inters\\sphere_actualTrimRegionEdge.nge") ; + ////debug + + for ( int c = 0 ; c < pNewTrim->GetChunkCount() ; ++c) { + for ( int l = 0 ; l < pNewTrim->GetLoopCount( c) ; ++l) { + for ( int t = 0 ; t < int( vpCCOpen.size()); ++t) { + PtrOwner pLoop( pNewTrim->GetLoop( c, l)) ; + // prima curva è il loop, seconda curva è il loop + IntersCurveCurve icc( *pLoop, *vpCCOpen[t]) ; + if ( icc.GetIntersCount() != 0) { + ICCIVECTOR vICC ; + for ( int i = 0 ; i < int( icc.GetIntersCount()); ++i) { + IntCrvCrvInfo iccInfo ; + icc.GetIntCrvCrvInfo( i, iccInfo) ; + vICC.emplace_back( iccInfo) ; + } + mInters.insert( pair( TRINT(c,l,t), vICC)) ; + } + } + } + } // vettore di flag che mi indica quali tagli aperti sono stati aggiunti al nuovo bordo BOOLVECTOR vbAdded( vpCCOpen.size()) ; fill(vbAdded.begin(), vbAdded.end(), false) ; PtrOwner pCCNewEdge( CreateCurveComposite()) ; PtrOwner pCL( CreateCurveLine()) ; - bool bAddedAll = false ; - int nFirstIntersChunck = -1 ; - int nFirstIntersLoop = -1 ; + //bool bAddedAll = false ; + TRINT tiFirstInters ; double dParamFirstInters = -1 ; // parto aggiungendo il primo taglio int nNewToAdd = 0 ; - //while ( ! bAddedAll) { + bool bFirstCurveOfEdge = true ; while ( nNewToAdd != -1) { // aggiungo il taglio - PtrOwner pLastCC( vpCCOpen[nNewToAdd]->Clone()) ; + //PtrOwner pLastCC( vpCCOpen[nNewToAdd]->Clone()) ; pCCNewEdge->AddCurve( Release( vpCCOpen[nNewToAdd])) ; // aggiorno la lista degli aggiunti vbAdded[nNewToAdd] = true ; - - - - // ora devo trovare la sua intersezione con un edge - // visto che scorro tutto ogni volta posso almeno evitare il conto se incontro l'edge da cui avevo già trovato lo start - int nChunkE = -1 ; - int nLoopE = -1 ; - int nChunkS = -1 ; - int nLoopS = -1 ; - // scorro tutti i chunk e tutti i loop per trovare l'intersezione - int nInters = 0 ; // per ogni loop devo trovare due intersezioni, una di partenza e una di arrivo - IntCrvCrvInfo iccInfo0 ; - IntCrvCrvInfo iccInfo1 ; - bool bStartInters0 = false ; - for ( int c = 0 ; c < pNewTrim->GetChunkCount() ; ++c) { - for ( int l = 0 ; l < pNewTrim->GetLoopCount( c) ; ++l) { - if ( c == nChunkS && l == nLoopS) - continue ; - PtrOwner pLoop( pNewTrim->GetLoop( c, l)) ; - IntersCurveCurve icc( *pLastCC, *pLoop) ; - if ( icc.GetIntersCount() == 0) - continue ; - if ( icc.GetIntersCount() == 1){ - if ( nInters == 0) { - icc.GetIntCrvCrvInfo( 0, iccInfo0) ; - // do per scontato di avere solo intersezioni all'inizio o alla fine del taglio - if ( iccInfo0.IciA->dU < EPS_SMALL ) { - nChunkS = c ; - nLoopS = l ; - bStartInters0 = true ; - } - else { - nChunkE = c ; - nLoopE = l ; - bStartInters0 = false ; - } - } - else if ( nInters == 1) { - icc.GetIntCrvCrvInfo( 1, iccInfo1) ; - // do per scontato di avere solo intersezioni all'inizio o alla fine del taglio - if ( iccInfo0.IciA->dU < EPS_SMALL ) { - nChunkS = c ; - nLoopS = l ; - } - else { - nChunkE = c ; - nLoopE = l ; + // di questo taglio mi salvo il chunk e loop di start e end + TRINT tiStart, tiEnd ; + for (const auto& pair : mInters) { + if ( get<2>(pair.first) == nNewToAdd ) { + for (int p = 0 ; p < int(pair.second.size()) ; ++p) { + if ( pair.second[p].IciB->dU < EPS_SMALL) { + tiStart = pair.first ; + if ( bFirstCurveOfEdge){ + // salvo l'inizio del taglio che è la prima curva di questa curva compo + tiFirstInters = pair.first ; + dParamFirstInters = pair.second[p].IciA->dU ; // parametro di intersezione sul loop + bFirstCurveOfEdge = false ; } } else - return false ; - ++nInters ; + tiEnd = pair.first ; } - else if (icc.GetIntersCount() == 2) { - icc.GetIntCrvCrvInfo( 0, iccInfo0) ; - // do per scontato di avere solo intersezioni all'inizio o alla fine del taglio - if ( iccInfo0.IciA->dU < EPS_SMALL ) { - nChunkS = c ; - nLoopS = l ; - bStartInters0 = true ; - } - else { - nChunkE = c ; - nLoopE = l ; - bStartInters0 = false ; - } - icc.GetIntCrvCrvInfo( 1, iccInfo1) ; - // do per scontato di avere solo intersezioni all'inizio o alla fine del taglio - if ( iccInfo1.IciA->dU < EPS_SMALL ) { - nChunkS = c ; - nLoopS = l ; - } - else { - nChunkE = c ; - nLoopE = l ; - } - ++nInters ; - ++nInters ; - } - // quando ho trovato due intersezioni esco - if ( nInters == 2) - break ; } - // quando ho trovato due intersezioni esco - if ( nInters == 2) - break ; - } - // se ho appena aggiunto il primo taglio mi salvo il suo start che mi indicherà dove terminare la ricostruzione del bordo - if ( nNewToAdd == 0 ) { - nFirstIntersChunck = nChunkS ; - nFirstIntersLoop = nLoopS ; - dParamFirstInters = bStartInters0 ? iccInfo0.IciB->dU : iccInfo1.IciB->dU ; } + // devo trovare fino a che punto seguire il loop che ho trovato come prosecuzione del taglio corrente // devo quindi trovare la prossima intersezione con un taglio - ICCIVECTOR vICCI ; - PtrOwner pLoop( pNewTrim->GetLoop( nChunkE, nLoopE)) ; - for ( int t = 0 ; t < int( vpCCOpen.size()); ++t) { - IntersCurveCurve icc( *pLoop, *vpCCOpen[t]) ; - if ( icc.GetIntersCount() == 0) - continue ; - else if ( icc.GetIntersCount() == 1) { - vICCI.emplace_back() ; - icc.GetIntCrvCrvInfo( 0, vICCI.back()) ; - } - - + int nInters = -1 ; + double dNextCut = numeric_limits::infinity() ; + double dEndCurrentCut ; + for ( int i = 0 ; i < int( mInters[tiEnd].size()); ++i) { + // se ho trovato l'intersezione con la fine del taglio corrente, salvo il parametro sul loop + if ( mInters[tiEnd][0].IciB->dU > EPS_SMALL) + dEndCurrentCut = mInters[tiEnd][0].IciA->dU ; } - + // se non trovo nessuna altra intersezione prima della fine del loop allora devo ripetere tutto cercando a partire dall'inizio del loop + for ( const auto& pair : mInters) { + if ( get<0>(pair.first) == get<0>(tiEnd) && get<1>(pair.first) == get<1>(tiEnd)) { + for ( int i = 0 ; i < int(pair.second.size()); ++i ) { + // se trovo una nuova intersezione che incontro prima di quella che mi ero salvato precedentemente allora + // mi salvo questa nuova che ho trovato + if ( pair.second[i].IciA->dU < dNextCut && pair.second[i].IciA->dU > dEndCurrentCut) { + dNextCut = pair.second[i].IciA->dU ; + nInters = get<2>(pair.first) ; + } + } + } + } + bool bRestart = false ; + if ( nInters == -1) { + bRestart = true ; + dNextCut = numeric_limits::infinity() ; + for ( const auto& pair : mInters) { + if ( get<0>(pair.first) == get<0>(tiEnd) && get<1>(pair.first) == get<1>(tiEnd)) { + for ( int i = 0 ; i < int(pair.second.size()); ++i ) { + // se trovo una nuova intersezione che incontro prima di quella che mi ero salvato precedentemente allora + // mi salvo questa nuova che ho trovato + if ( pair.second[i].IciA->dU < dNextCut) { + dNextCut = pair.second[i].IciA->dU ; + nInters = get<2>(pair.first) ; + } + } + } + } + } + PtrOwner pLoopTrimmed( pNewTrim->GetLoop( get<0>(tiEnd), get<1>(tiEnd))) ; // trimmo il loop che ho trovato come prosecuzione del taglio corrente e la aggiungo al taglio - pLoop->TrimStartAtParam(bStartInters0 ? iccInfo0.IciB->dU : iccInfo1.IciB->dU) ; - pLoop->TrimEndAtParam() ; - // se arrivo fino alla fine del loop devo ricominciare a seguire il loop fino ad un'intersezione? - PtrOwner pLoop2( pNewTrim->GetLoop( nChunkE, nLoopE)) ; - pLoop->TrimEndAtParam() ;// appiccico un pezzo dall'inizio - - - - - // trovo il prossimo taglio ancora da aggiungere - nNewToAdd = -1 ; - for ( int b = 0 ; b < int(vbAdded.size()) ; ++b ) { - if ( ! vbAdded[b]) { - nNewToAdd = b ; - //vbAdded[b] = true ; - break ; + pLoopTrimmed->TrimEndAtParam( dNextCut) ; + // se non sono ripassato per lo start del loop mi basta aggiungere il pezzo di loop che ho trimmato + if ( ! bRestart) { + pLoopTrimmed->TrimStartAtParam( dEndCurrentCut) ; + pCCNewEdge->AddCurve( Release( pLoopTrimmed)) ; + } + else { + // prima di aggiungere il pezzo che ho identificato devo aggiungere quello che dal parametro corrente mi fa + // andare al punto finale e quindi tornare al punto iniziale + PtrOwner pLoopTrimmed0( pNewTrim->GetLoop( get<0>(tiEnd), get<1>(tiEnd))) ; + pLoopTrimmed0->TrimStartAtParam( dEndCurrentCut) ; + pCCNewEdge->AddCurve( Release(pLoopTrimmed0)) ; + // e poi aggiungo il tratto che ho identificato per arrivare al prossimo taglio + pCCNewEdge->AddCurve( Release(pLoopTrimmed)) ; + } + // se il prossimo taglio identificato è quello da cui sono partito allora aggiungo il bordo ricostruito fino a questo momento + // alla flat region e comincio a costruire un altro bordo + // altrimenti continuo ad aggiungere curve al bordo corrente + if ( nInters == get<2>(tiFirstInters) ) { + pCCNewEdge->Close() ; + sfrContour.AddCurve( Release( pCCNewEdge)) ; + pCCNewEdge.Set( CreateBasicCurveComposite()) ; + bFirstCurveOfEdge = true ; + // trovo il prossimo taglio ancora da aggiungere + nNewToAdd = -1 ; + for ( int b = 0 ; b < int(vbAdded.size()) ; ++b ) { + if ( ! vbAdded[b]) { + nNewToAdd = b ; + //vbAdded[b] = true ; + break ; + } } } - //// controllo se ho aggiunto tutti i tagli - //bAddedAll = true ; - //for ( int b = 0 ; b < int( vbAdded.size()) ; ++b ) { - // bAddedAll = bAddedAll && vbAdded[b] ; - //} + else + nNewToAdd = nInters; } } @@ -1992,19 +1983,6 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) pNewStm->GetLoops( vPLTria) ; } - SurfFlatRegionByContours sfrContour ; - // aggiungo i tagli sul bordo - for ( int i = 0 ; i < int( vPolygons.size()); ++i ) { - for ( int j = 0 ; j < int( vPolygons[i].size()); ++j) { - PtrOwner pCC( CreateCurveComposite()) ; - pCC->FromPolyLine( vPolygons[i][j]) ; - ////debug - //PtrOwner pCrvCopy( pCC->Clone()) ; - //SaveGeoObj( Release(pCrvCopy), "D:\\Temp\\inters\\sphere_trim_curve2D.nge") ; - ////debug - sfrContour.AddCurve( Release( pCC)) ; - } - } // aggiungo i loop chiusi for ( int i = 0 ; i < int( vpCCClosed.size()); ++i ) sfrContour.AddCurve( Release( vpCCClosed[i])) ; @@ -2076,10 +2054,10 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // 1. se il punto è sopra il piano ed era dentro una curva CCW // 2. se il punto è sotto il piano ed era interno ad una curva CW - //debug - PtrOwner pSrfFR_Copy( pSFR->Clone()) ; - SaveGeoObj( Release(pSrfFR_Copy), "D:\\Temp\\inters\\failed_trim.nge", GDB_SV_BIN) ; - //debug + ////debug + //PtrOwner pSrfFR_Copy( pSFR->Clone()) ; + //SaveGeoObj( Release(pSrfFR_Copy), "D:\\Temp\\inters\\failed_trim.nge", GDB_SV_BIN) ; + ////debug // la SetTrimRegion controlla se avevo trim precedenti ed eventualmente fa l'intersezione con lo spazio esistente if ( ( dDist > 0 && bPos) || ( dDist < 0 && ! bPos)) { @@ -2211,9 +2189,12 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in } } } + // questa è ancora da sviluppare ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // devo anche tener conto della possibilità che i lati siano collassati in poli - //if ( m_vbPole[0]) - // ; + if ( m_vbPole[0] ) { + ; + } + // se l'intersezione era su un vertice restituisco le coordinate parametriche del vertice if ( nIL == 3 ) { if ( AreSamePointApprox(ptI, vPT[0]))