From a1c448d8dd61b4cce70e76cb27e3f4a22b614f7a Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Tue, 3 Feb 2026 16:13:07 +0100 Subject: [PATCH] EgtGeomKernel : - tentativo di miglioria alle ruled. Da debuggare. --- SurfBezier.cpp | 601 +++++++++++++++++++++++++++++++------------------ Trimming.cpp | 109 +++++++++ 2 files changed, 494 insertions(+), 216 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 8be2b0d..5fb57ac 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -45,11 +45,13 @@ #include "/EgtDev/Extern/Eigen/Dense" #define SAVEFAILEDTRIANGULATION 0 -#define SAVEISO 0 -#define SAVERULEDISO 0 +#define SAVEREBUILTISO 0 +#define SAVERULEDISO 1 #define SAVERULEDGUIDEDISO 0 -#if SAVEFAILEDTRIANGULATION || SAVEISO || SAVERULEDISO || SAVERULEDGUIDEDISO +#define SAVEMATCHCURVES 0 +#if SAVEFAILEDTRIANGULATION || SAVEREBUILTISO || SAVERULEDISO || SAVERULEDGUIDEDISO || SAVEMATCHCURVES #include "/EgtDev/Include/EGkGeoObjSave.h" + std::vector vGeo ; #endif using namespace std ; @@ -1071,10 +1073,10 @@ SurfBezier::Load( NgeReader& ngeIn) m_bTrimmed = true ; } -#if SAVEISO +#if SAVEREBUILTISO ICURVEPOVECTOR vCrv ; GetAllPatchesIsocurves( false, vCrv) ; - vector vGeo ; + vGeo.clear() ; for( int i = 0 ; i < ssize(vCrv) ; ++i) vGeo.push_back( vCrv[i]->Clone()) ; SaveGeoObj( vGeo, "D:\\Temp\\bezier\\ruled\\rebuild\\isoCrv.nge") ; @@ -4460,7 +4462,7 @@ ChangeStartForClosed( PolyLine& plU0, PolyLine& plU1, ICurveComposite* pCrvU0, I } static bool -GetEdgeSplitByAngTol( const PolyLine& PL, double dAngTol, INTVECTOR& vEdgeSplit) +GetEdgeSplitByAngTol( const PolyLine& PL, double dAngTol, BOOLVECTOR& vEdgeSplit) { int nPoints = PL.GetPointNbr() ; vEdgeSplit.clear() ; @@ -4935,30 +4937,39 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } } // spezzo le curve di bezier dove è necessario aggiungere dei punti - else if ( nRuledType == RLT_B_MINDIST_PLUS ) { + else if ( nRuledType == RLT_B_MINDIST_PLUS) { // scorro la prima curva e per ogni punto di fine sottocurva cerco il minDistPoint sull'altra curva // in quel punto la curva verrà spezzata, a meno che non si trovi una joint già sufficientemente vicina +#if SAVEMATCHCURVES + vector> vvGeo0(4) ; + vector> vvCol0(4) ; +#endif + // prima trovo le associazioni senza aggiunte di punti bool bIsClosed0 = plU0.IsClosed() ; bool bIsClosed1 = plU1.IsClosed() ; CurveComposite ccPoly0 ; ccPoly0.FromPolyLine( plU0) ; CurveComposite ccPoly1 ; ccPoly1.FromPolyLine( plU1) ; Point3d ptP1 ; plU1.GetFirstPoint( ptP1) ; - vector> vMatch1 ; + PNTUVECTOR vMatch1 ; + PNTUVECTOR vMatch1b ; PNTVECTOR vPnt1 ; vPnt1.emplace_back( ptP1) ; while ( plU1.GetNextPoint( ptP1, true)) { Vector3d vtDir ; CrvU1.GetCurve( vPnt1.size() - 1)->GetEndDir( vtDir) ; IntersCurvePlane icp( ccPoly0, ptP1, vtDir) ; double dParam ; Point3d ptJoint ; + + DistPointCurve dpc( ptP1, CrvU0, false) ; + int nFlag = 0 ; + dpc.GetParamAtMinDistPoint( 0, dParam, nFlag) ; + dpc.GetMinDistPoint( 0, ptJoint, nFlag) ; + vMatch1b.emplace_back( ptJoint, dParam) ; if ( icp.GetIntersCount() > 0) icp.GetIntersPointNearTo( ptP1, ptJoint, dParam) ; else { - DistPointCurve dpc( ptP1, CrvU0, false) ; - int nFlag = 0 ; - dpc.GetParamAtMinDistPoint( 0, dParam, nFlag) ; - dpc.GetMinDistPoint( 0, ptJoint, nFlag) ; + ; } // capisco se il punto avrà bisogno di aggiungere uno split sull'altra curva o no int nParam = int( dParam) ; @@ -4972,31 +4983,44 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int //se sono troppo vicino ad uno split esistente allora non faccio nulla if ( abs(dParam - round( dParam)) < 100 * EPS_PARAM || Dist( ptJoint, ptNearestJoint) < 50 * EPS_SMALL) { dParam = round( dParam) ; + ptJoint = ptNearestJoint ; } - vMatch1.push_back( pair( ptJoint, dParam)) ; + vMatch1.emplace_back( ptJoint, dParam) ; vPnt1.emplace_back( ptP1) ; + #if SAVEMATCHCURVES + CurveLine CLa ; CLa.Set( ptP1, ptJoint) ; + vvGeo0[0].push_back( CLa.Clone()) ; + CurveLine CLb ; CLb.Set( ptP1, vMatch1b.back().first) ; + vvGeo0[1].push_back( CLb.Clone()) ; + #endif } plU1.GetLastPoint( ptP1) ; vPnt1.emplace_back( ptP1) ; Point3d ptP0 ; plU0.GetLastPoint( ptP0) ; - vMatch1.push_back( pair( ptP0, nSpanU0)) ; + vMatch1.emplace_back( ptP0, nSpanU0) ; + vMatch1b.emplace_back( ptP0, nSpanU0) ; plU0.GetFirstPoint( ptP0) ; - vector> vMatch0 ; + PNTUVECTOR vMatch0 ; + PNTUVECTOR vMatch0b ; PNTVECTOR vPnt0 ; vPnt0.emplace_back( ptP0) ; while ( plU0.GetNextPoint( ptP0, true)) { double dParam ; Point3d ptJoint ; Vector3d vtDir ; CrvU0.GetCurve( vPnt0.size() - 1)->GetEndDir( vtDir) ; IntersCurvePlane icp( ccPoly1, ptP0, vtDir) ; + + DistPointCurve dpc( ptP0, CrvU1, false) ; + int nFlag = 0 ; + dpc.GetMinDistPoint( 0, ptJoint, nFlag) ; + dpc.GetParamAtMinDistPoint( 0, dParam, nFlag) ; + vMatch0b.emplace_back( ptJoint, dParam) ; + if ( icp.GetIntersCount() > 0) { icp.GetIntersPointNearTo( ptP0, ptJoint, dParam) ; } else { - DistPointCurve dpc( ptP0, CrvU1, false) ; - int nFlag = 0 ; - dpc.GetMinDistPoint( 0, ptJoint, nFlag) ; - dpc.GetParamAtMinDistPoint( 0, dParam, nFlag) ; + ; } // capisco se il punto avrà bisogno di aggiungere uno split sull'altra curva o no int nParam = int( dParam) ; @@ -5010,17 +5034,87 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // se sono già troppo vicino ad un split esistente allora non faccio nulla if ( abs(dParam - round( dParam)) < 100 * EPS_PARAM || Dist( ptJoint, ptNearestJoint) < 50 * EPS_SMALL) { dParam = round( dParam) ; + ptJoint = ptNearestJoint ; } - vMatch0.push_back( pair( ptJoint, dParam)) ; + vMatch0.emplace_back( ptJoint, dParam) ; vPnt0.emplace_back( ptP0) ; + #if SAVEMATCHCURVES + CurveLine CLa ; CLa.Set( ptP0, ptJoint) ; + vvGeo0[2].push_back( CLa.Clone()) ; + CurveLine CLb ; CLb.Set( ptP0, vMatch0b.back().first) ; + vvGeo0[3].push_back( CLb.Clone()) ; + #endif } plU0.GetLastPoint( ptP0) ; vPnt0.emplace_back( ptP0) ; plU1.GetLastPoint( ptP1) ; - vMatch0.push_back( pair( ptP1, nSpanU1)) ; + vMatch0.emplace_back( ptP1, nSpanU1) ; + vMatch0b.emplace_back( ptP1, nSpanU1) ; + + #if SAVEMATCHCURVES + vvCol0[0].resize( ssize(vvGeo0[0])) ; + fill( vvCol0[0].begin(), vvCol0[0].end(), Color( 128,128,255)) ; + vvCol0[1].resize( ssize(vvGeo0[1])) ; + fill( vvCol0[1].begin(), vvCol0[1].end(), Color( 0,128,192)) ; + vvCol0[2].resize( ssize(vvGeo0[2])) ; + fill( vvCol0[2].begin(), vvCol0[2].end(), Color( 255,128,128)) ; + vvCol0[3].resize( ssize(vvGeo0[3])) ; + fill( vvCol0[3].begin(), vvCol0[3].end(), Color( 192,128,0)) ; + SaveGeoObj( vvGeo0, vvCol0, "D:\\Temp\\bezier\\ruled\\match.nge") ; + #endif + + // salvo le coppie di punti su ogni curva che indicano l'inizio e la fine di regioni di mismatch tra i valori di accoppiamento rilevati + // tramite due misure diverse della distanza + INTINTVECTOR vMismatch0 ; + INTINTVECTOR vMismatch1 ; + double dMaxDist = Dist( vPnt0[0], vPnt1[0]) / 20 ; + for( int i = 0 ; i < ssize( vMatch0) ; ++i) { + if( ! AreSamePointEpsilon( vMatch0[i].first, vMatch0b[i].first, dMaxDist)) { + int c = i + 1 ; + while( ! AreSamePointEpsilon( vMatch0[c].first, vMatch0b[c].first, dMaxDist)) + ++c ; + vMismatch0.emplace_back( i, c) ; + i = c ; + } + } + // faccio un merge di regioni adiacenti di mismatch + int nCurr = 0, nNext = 1 ; + while( nNext < ssize( vMismatch0)) { + if( vMismatch0[nNext].first - vMismatch0[nCurr].second < 2 + EPS_SMALL) { + vMismatch0[nCurr].second = vMismatch0[nNext].second ; + } + else { + ++nCurr ; + vMismatch0[nCurr] = vMismatch0[nNext] ; + } + ++nNext ; + } + vMismatch0.resize( nCurr + 1) ; + + for( int i = 0 ; i < ssize( vMatch1) ; ++i) { + if( ! AreSamePointEpsilon( vMatch1[i].first, vMatch1b[i].first, dMaxDist)) { + int c = i + 1 ; + while( ! AreSamePointEpsilon( vMatch1[c].first, vMatch1b[c].first, dMaxDist)) + ++c ; + vMismatch1.emplace_back( i, c) ; + i = c ; + } + } + nCurr = 0, nNext = 1 ; + while( nNext < ssize( vMismatch1)) { + if( vMismatch1[nNext].first - vMismatch1[nCurr].second < 2 + EPS_SMALL) { + vMismatch1[nCurr].second = vMismatch1[nNext].second ; + } + else { + ++nCurr ; + vMismatch1[nCurr] = vMismatch1[nNext] ; + } + ++nNext ; + } + vMismatch1.resize( nCurr + 1) ; // verifico la presenza di eventuali "edge" lungo le polyline ( punti di passaggio di un edge e quindi cambi bruschi di direzione della polyline) - INTVECTOR vEdgeSplit0, vEdgeSplit1 ; + BOOLVECTOR vEdgeSplit0, vEdgeSplit1 ; double dAngTol = 55 ; GetEdgeSplitByAngTol( plU0, dAngTol, vEdgeSplit0) ; GetEdgeSplitByAngTol( plU1, dAngTol, vEdgeSplit1) ; @@ -5038,12 +5132,23 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int INTINTVECTOR vPairs ; vPairs.emplace_back( 0, 0) ; bool bAdvance = true ; + int m0 = 0, m1 = 0 ; // contatori delle zone di mismatch // verifico i match effettivi tra le polyline while ( bAdvance) { if ( c > ssize(vMatch0) - 1 || j > ssize( vMatch1) - 1) { LOG_DBG_ERR( GetEGkLogger(), "RLT_B_MINDIST_PLUS: le due curve potrebbero non avere forme coerenti") ; return false ; } + // aggiorno il contatore delle eventuali zone di mismatch + if( ssize(vMismatch0) > 0) { + while( m0 < ssize(vMismatch0) && c > vMismatch0[m0].second) + ++m0 ; + } + if( ssize(vMismatch1) > 0) { + while( m1 < ssize(vMismatch1) && j > vMismatch1[m1].second) + ++m1 ; + } + double dParam0 = vMatch0[c].second ; Point3d ptJoint0 = vMatch0[c].first ; double dParam1 = vMatch1[j].second ; @@ -5069,8 +5174,20 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int bAdvance0 = false ; if ( j == vMatch1.size()) bAdvance1 = false ; + + bool bMismatch = false ; + bool bMismatch0 = false ; + bool bMismatch1 = false ; + // controllo la presenza di eventuali zone di mismatch + if ( ssize( vMismatch0) > 0 || ssize( vMismatch1) > 0) { + if ( m0 < ssize( vMismatch0) && c >= vMismatch0[m0].first && c < vMismatch0[m0].second) + bMismatch0 = true ; + if ( m1 < ssize( vMismatch1) && j >= vMismatch1[m1].first && j < vMismatch1[m1].second) + bMismatch1 = true ; + bMismatch = (bMismatch0 && bMismatch1) || (bMismatch0 && ! bAdvance1) || (bMismatch1 && ! bAdvance0); + } // se trovo che ho uno spigolo allora procedo con la gestione spigoli - if( vEdgeSplit0[c+1] && vEdgeSplit1[j+1]) { + else if( vEdgeSplit0[c+1] && vEdgeSplit1[j+1]) { // se ho uno spigolo su entrambe le curve forzo l'accoppiamento bAdvance0 = true ; bPerfectMatch = true ; @@ -5080,11 +5197,12 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int ptJoint1 = vPnt0[c+1] ; } else if ( (vEdgeSplit0[c+1] && ! bAdvance1) || (vEdgeSplit1[j+1] && ! bAdvance0)) { + // da una parte ho uno spigolo e dall'altra non posso avanzare bAdvance0 = false ; bAdvance1 = false ; } - if ( bAdvance0) { + if ( bAdvance0 && ! bMismatch) { if ( c < dLastParamMatch1 + EPS_SMALL) ++c ; // ho match con lo start @@ -5121,7 +5239,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int if ( bPerfectMatch) ++j ; } - if ( bAdvance1 && ! bPerfectMatch) { + if ( bAdvance1 && ! bPerfectMatch && ! bMismatch) { if ( j < dLastParamMatch0 + EPS_SMALL) ++j ; // ho un match con lo start @@ -5156,16 +5274,17 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int dLastParamMatch0 = j ; ptLastPointMatch0 = vPnt1[j] ; } - if ( ! bAdvance0 && ! bAdvance1) { + if ( ( ! bAdvance0 && ! bAdvance1) || bMismatch) { // sono arrivato ad un caso di incrocio!! - //1. se sono vicino ad uno spigolo su entrambe le curve allora aggiungo dei rep - //2. sennò accoppio comunque + //1. se sono vicino ad uno spigolo su entrambe le curve allora accoppio gli spigoli e il resto lo aggiusto di conseguenza + //2. se sono in una zona di mismatch faccio il match usando la parametrizzazione sulla lunghezza dei tratti di curve interessati + //3. sennò accoppio comunque ( la coppia corrente) bool bEdgeFoundOnSecond = false ; if ( vEdgeSplit0[c+1] && vEdgeSplit1[j+1]) { // questo caso non è previsto !!!!! e non mi aspetto che avvenga LOG_DBG_ERR( GetEGkLogger(), "RLT_B_MINDIST_PLUS: a not handled mismatch was found, type 0") ; } - if ( vEdgeSplit0[c+1]) { + if ( vEdgeSplit0[c+1] && ! bMismatch) { ++c ; ++j ; //cerco se ho uno split anche su U1 entro una distanza che sia al massimo il doppio di quella che c'è col punto a mindist @@ -5188,11 +5307,10 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int dLastParamMatch0 = j - 1 ; ptLastPointMatch0 = vPnt1[j] ; } - else { - LOG_DBG_ERR( GetEGkLogger(), "RLT_B_MINDIST_PLUS: a not handled mismatch was found, type 1") ; - } + else + bMismatch = true ; } - else if ( vEdgeSplit1[j+1]) { + else if ( vEdgeSplit1[j+1] && ! bMismatch) { ++c ; ++j ; //cerco se ho uno split anche su U1 entro una distanza che sia al massimo il doppio di quella che c'è col punto a mindist @@ -5215,194 +5333,245 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int dLastParamMatch1 = c - 1 ; ptLastPointMatch1 = vPnt0[c] ; } - else { - LOG_DBG_ERR( GetEGkLogger(), "RLT_B_MINDIST_PLUS: a not handled mismatch was found, type 2") ; - } + else + bMismatch = true ; } - else { - /////////OLD VRESION - ++c ; - ++j ; - vPairs.emplace_back( c + nSplit0, j + nSplit1) ; - dLastParamMatch1 = c ; - ptLastPointMatch1 = vPnt0[c] ; - dLastParamMatch0 = j ; - ptLastPointMatch0 = vPnt1[j] ; + + if( ( ! vEdgeSplit0[c+1] && ! vEdgeSplit1[j+1]) || bMismatch) { + // non ci sono riferimenti per fare un match, quindi li cerco io + + ///////////OLD VRESION + //++c ; + //++j ; + //vPairs.emplace_back( c + nSplit0, j + nSplit1) ; + //dLastParamMatch1 = c ; + //ptLastPointMatch1 = vPnt0[c] ; + //dLastParamMatch0 = j ; + //ptLastPointMatch0 = vPnt1[j] ; - ////// potrei avere un mismatch, senza però avere degli spigoli.. + //// potrei avere un mismatch, senza però avere degli spigoli.. - // // identifico la zona in cui ho il mismatch e parametrizzo localmente + // identifico la zona in cui ho il mismatch e parametrizzo localmente - // //conto quanti punti ho nel mezzo - // int c_temp = c, j_temp = j ; - // bAdvance0 = true ; - // bAdvance1 = true ; - // int nParam0, nParam1 ; - // while( bAdvance0) { - // dParam0 = vMatch0[c_temp].second ; - // nParam0 = int( round( dParam0)) ; - // dParam1 = vMatch1[nParam0].second ; - // nParam1 = int( round( dParam1)) ; - // if( abs( nParam1 - c_temp) <= 2) - // bAdvance0 = false ; - // else - // ++ c_temp ; - // } - // while( bAdvance1) { - // dParam1 = vMatch1[j_temp].second ; - // nParam1 = int( round( dParam1)) ; - // dParam0 = vMatch0[nParam1].second ; - // nParam0 = int( round( dParam0)) ; - // if( abs( nParam0 - j_temp) <= 2) - // bAdvance1 = false ; - // else - // ++ j_temp ; - // } - // // se non sono avanzato, allora mi basta accoppiare i due punti in questione - // if( c_temp == c || j_temp == j) { - // ++c ; - // ++j ; - // vPairs.emplace_back( c + nSplit0, j + nSplit1) ; - // dLastParamMatch1 = c ; - // ptLastPointMatch1 = vPnt0[c] ; - // dLastParamMatch0 = j ; - // ptLastPointMatch0 = vPnt1[j] ; - // } - // // se sono dovuto avanzare per trovare delle coppie che tornano a matchare allora ho effettivamente trovato una zona di mismatch - // else { - // // determino quale delle due coppie è il confine effettivo con la zona di mismatch e quale sarà la prima dopo il mismamtch - // dParam0 = vMatch0[c_temp].second ; - // dParam1 = vMatch1[j_temp].second ; - // bool bIntParam0 = false ; - // bool bIntParam1 = false ; - // if ( abs( dParam0 - round( dParam0)) < EPS_SMALL) { - // dParam0 = round( dParam0) ; - // bIntParam0 = true ; - // } - // if ( abs( dParam1 - round( dParam1)) < EPS_SMALL) { - // dParam1 = round( dParam1) ; - // bIntParam1 = true ; - // } - // bAdvance0 = dParam0 < j_temp + 1 + EPS_SMALL ; - // bAdvance1 = dParam1 < c_temp + 1 + EPS_SMALL ; - // PtrOwner pCC0 ; - // PtrOwner pCC1 ; - // int nPointsBetween0 = 0 ; - // int nPointsBetween1 = 0 ; - // if( bAdvance0 && bAdvance1) { - // pCC0.Set( CrvU0.CopyParamRange( dLastParamMatch1, c_temp + 1)) ; - // pCC1.Set( CrvU1.CopyParamRange( dLastParamMatch0, j_temp + 1)) ; - // nPointsBetween0 = c_temp - c ; - // nPointsBetween1 = j_temp - j ; - // } - // else if( bAdvance0){ - // pCC0.Set( CrvU0.CopyParamRange( dLastParamMatch1, c_temp + 1)) ; - // pCC1.Set( CrvU1.CopyParamRange( dLastParamMatch0, dParam0)) ; - // nPointsBetween0 = c_temp - c ; - // nPointsBetween1 = int( dParam0) - ( j + 1) ; - // if ( bIntParam0) - // nPointsBetween1 -= 1 ; - // } - // else if( bAdvance1){ - // pCC0.Set( CrvU0.CopyParamRange( dLastParamMatch1, dParam1)) ; - // pCC1.Set( CrvU1.CopyParamRange( dLastParamMatch0, j_temp + 1)) ; - // nPointsBetween0 = int( dParam1) - ( c + 1) ; - // nPointsBetween1 = j_temp - j ; - // if ( bIntParam1) - // nPointsBetween0 -= 1 ; - // } - // - // double dLen0 ; pCC0->GetLength( dLen0) ; - // double dLen1 ; pCC1->GetLength( dLen1) ; - // DBLVECTOR vdParamPos0 ; vdParamPos0.reserve( nPointsBetween0) ; - // DBLVECTOR vdParamPos1 ; vdParamPos1.reserve( nPointsBetween1) ; - // for ( int k = 0 ; k <= nPointsBetween0 ; ++k) { - // double dLen = 0 ; pCC0->GetLengthAtParam( k, dLen) ; - // vdParamPos0.push_back( dLen / dLen0) ; - // } - // vdParamPos0.push_back( 1) ; - // for ( int k = 0 ; k <= nPointsBetween1 ; ++k) { - // double dLen = 0 ; pCC1->GetLengthAtParam( k, dLen) ; - // vdParamPos1.push_back( dLen / dLen1) ; - // } - // vdParamPos1.push_back( 1) ; + //conto quanti punti ho nel mezzo + int c_temp, j_temp ; + if( ! bMismatch) { + c_temp = c, j_temp = j ; + bAdvance0 = true ; + bAdvance1 = true ; + int nParam0, nParam1 ; + while( bAdvance0) { + dParam0 = vMatch0[c_temp].second ; + nParam0 = int( round( dParam0)) ; + dParam1 = vMatch1[nParam0].second ; + nParam1 = int( round( dParam1)) ; + if( abs( nParam1 - c_temp) <= 2) + bAdvance0 = false ; + else + ++ c_temp ; + } + while( bAdvance1) { + dParam1 = vMatch1[j_temp].second ; + nParam1 = int( round( dParam1)) ; + dParam0 = vMatch0[nParam1].second ; + nParam0 = int( round( dParam0)) ; + if( abs( nParam0 - j_temp) <= 2) + bAdvance1 = false ; + else + ++ j_temp ; + } + } + else { + // cerco se ho degli spigoli nella zona di mismatch + // se ne ho definisco una regione compresa tra un estremo( start o end) e uno spigolo (presente su entrambe le curve) + INTVECTOR vnEdges0, vnEdges1 ; + for( int i = vMismatch0[m0].first ; i < vMismatch0[m0].second ; ++i) { + if ( vEdgeSplit0[i]) + vnEdges0.push_back(i) ; + } + for( int i = vMismatch1[m1].first ; i < vMismatch1[m1].second ; ++i) { + if ( vEdgeSplit1[i]) + vnEdges1.push_back(i) ; + } + // se ho degli edge che non matchano tra loro semplicemente tratto tutta la regione di mismatch insieme + if( ssize( vnEdges0) != ssize( vnEdges1) || ssize( vnEdges0) == 0 || ssize( vnEdges1) == 0) { + if( bMismatch0) { + c_temp = vMismatch0[m0].second ; + j_temp = int( vMatch0[c_temp].second) ; + } + else if ( bMismatch1){ + j_temp = vMismatch1[m1].second ; + c_temp = int( vMatch1[j_temp].second) ; + } + } + // se ho corrispondenza tra gli edge (in numero) allora (do per scontato di accoppiarli e ) li prendo come estremi di zone da trattare separatamente + else { + // definisco gli estremi della zona da riparametrizzare + // controllo se ho già matchato parte della zona di mismatch + // cerco la coppia successiva alla corrente per determinare la zona su cui lavorare ora + for( int i = 0 ; i < ssize( vnEdges0) ; ++i) { + if( c == vnEdges0[i]) { + if( i < ssize( vnEdges0) - 1) { + c_temp = vnEdges0[i+1] ; + j_temp = vnEdges1[i+1] ; + } + else { + if ( bMismatch0) { + c_temp = vMismatch0[m0].second ; + j_temp = int( vMatch0[c_temp].second) ; + ++m0 ; + } + else if( bMismatch1) { + j_temp = vMismatch1[m1].second ; + c_temp = int( vMatch1[j_temp].second) ; + ++m1 ; + } + } + break ; + } + } + } + } + // se non sono avanzato, allora mi basta accoppiare i due punti in questione + if( c_temp == c || j_temp == j) { + ++c ; + ++j ; + vPairs.emplace_back( c + nSplit0, j + nSplit1) ; + dLastParamMatch1 = c ; + ptLastPointMatch1 = vPnt0[c] ; + dLastParamMatch0 = j ; + ptLastPointMatch0 = vPnt1[j] ; + } + // se sono dovuto avanzare per trovare delle coppie che tornano a matchare allora ho effettivamente trovato una zona di mismatch + else { + // determino quale delle due coppie è il confine effettivo con la zona di mismatch e quale sarà la prima dopo il mismamtch + dParam0 = vMatch0[c_temp].second ; + dParam1 = vMatch1[j_temp].second ; + bAdvance0 = dParam0 < j_temp + 1 + EPS_SMALL ; + bAdvance1 = dParam1 < c_temp + 1 + EPS_SMALL ; + PtrOwner pCC0 ; + PtrOwner pCC1 ; + int nPointsBetween0 = 0 ; + int nPointsBetween1 = 0 ; + if( bAdvance0 && bAdvance1) { + pCC0.Set( CrvU0.CopyParamRange( dLastParamMatch1, c_temp + 1)) ; + pCC1.Set( CrvU1.CopyParamRange( dLastParamMatch0, j_temp + 1)) ; + nPointsBetween0 = int( c_temp + 1 - floor( dLastParamMatch1) - 1) ; + nPointsBetween1 = int( j_temp + 1 - floor( dLastParamMatch0) - 1) ; + } + else if( bAdvance0){ + pCC0.Set( CrvU0.CopyParamRange( dLastParamMatch1, c_temp + 1)) ; + pCC1.Set( CrvU1.CopyParamRange( dLastParamMatch0, dParam0)) ; + nPointsBetween0 = int( c_temp + 1 - floor( dLastParamMatch1) - 1) ; + nPointsBetween1 = int( ceil( dParam0) - floor( dLastParamMatch0) - 1) ; + } + else if( bAdvance1){ + pCC0.Set( CrvU0.CopyParamRange( dLastParamMatch1, dParam1)) ; + pCC1.Set( CrvU1.CopyParamRange( dLastParamMatch0, j_temp + 1)) ; + nPointsBetween0 = int( ceil( dParam1) - floor( dLastParamMatch1) - 1) ; + nPointsBetween1 = int( j_temp + 1 - floor( dLastParamMatch0) - 1) ; + } - // bool bSplitToAdd = true ; - // int c0 = 1, c1 = 1 ; - // //debug - // int nCBerfore = c ; - // int nJBefore = j ; - // //debug - // while ( bSplitToAdd) { - // if ( c0 > ssize( vdParamPos0) - 1 && c1 > ssize( vdParamPos1) - 1) { - // LOG_DBG_ERR( GetEGkLogger(), "Surf Bez Ruled Guided: error 1 while reparametrizing some section") ; - // return false ; - // } - // // se ho una corrispondenza tra punti ( e non sono alla fine del tratto) allora non aggiungo split - // if ( abs( vdParamPos0[c0] - vdParamPos1[c1]) < EPS_PARAM && vdParamPos0[c0] < 1) { - // ++c0 ; - // ++c1 ; - // ++c ; - // ++j ; - // vPairs.emplace_back( c + nSplit0, j + nSplit1) ; - // } - // // se non ho corrispondenza allora aggiungo uno split sulla curva a cui manca il punto corrispondente - // else if ( vdParamPos0[c0] < vdParamPos1[c1]) { - // double dPar ; CrvU1.GetParamAtLength( dLen1 * vdParamPos0[c0], dPar) ; - // if ( abs( dPar - round( dPar)) > EPS_SMALL) { - // vdSplit1.push_back( dPar + dLastParamMatch0) ; - // nSplit1 = vdSplit1.size() ; - // } - // else if ( dPar = round( dPar) ; dPar > j){ - // ++ j ; - // } - // ++c ; - // vPairs.emplace_back( c + nSplit0, j + nSplit1) ; - // ++c0 ; - // } - // else if ( vdParamPos0[c0] > vdParamPos1[c1]) { - // double dPar ; CrvU0.GetParamAtLength( dLen0 * vdParamPos1[c1], dPar) ; - // // se lo split non è in prossimità di una joint già esistente allora lo aggiungo - // if ( abs( dPar - round( dPar)) > EPS_SMALL) { - // vdSplit0.push_back( dPar + dLastParamMatch1) ; - // nSplit0 = vdSplit0.size() ; - // } - // else if ( dPar = round( dPar) ; dPar > c){ - // ++ c ; - // } - // ++j ; - // vPairs.emplace_back( c + nSplit0, j + nSplit1) ; - // ++c1 ; - // } - // else { - // LOG_DBG_ERR( GetEGkLogger(), "Surf Bez Ruled Guided: error 2 while reparametrizing some section") ; - // return false ; - // } - // bSplitToAdd = ! ( c0 == ssize( vdParamPos0) - 1 && c1 == ssize( vdParamPos1) - 1) ; - // } - // // aggiorno i dati dell'ultima aggiunta - // if( bAdvance0 && ! bAdvance1) { - // ptLastPointMatch0 = vMatch0[c_temp].first ; - // dLastParamMatch0 = vMatch0[c_temp].second ; - // ptLastPointMatch1 = vPnt0[c_temp] ; - // dLastParamMatch0 = c_temp ; - // } - // else if( ! bAdvance0 && bAdvance1) { - // ptLastPointMatch0 = vPnt1[j_temp] ; - // dLastParamMatch0 = j_temp ; - // ptLastPointMatch1 = vMatch1[j_temp].first ; - // dLastParamMatch0 = vMatch1[j_temp].second ; - // } - // else { - // ptLastPointMatch0 = vPnt1[j_temp] ; - // dLastParamMatch0 = j_temp ; - // ptLastPointMatch1 = vPnt0[c_temp] ; - // dLastParamMatch0 = c_temp ; - // } - // vPairs.emplace_back( c + nSplit0, j + nSplit1) ; - // } + if( IsNull(pCC0) || ! pCC0->IsValid() || IsNull(pCC1) || ! pCC1->IsValid()) { + LOG_DBG_ERR( GetEGkLogger(), "RLT_B_MINDIST_PLUS: failed attempt to identify mismatch region, type0") ; + return false ; + } + + double dLen0 ; pCC0->GetLength( dLen0) ; + double dLen1 ; pCC1->GetLength( dLen1) ; + + if( nPointsBetween0 < 0 || nPointsBetween1 < 0) { + LOG_DBG_ERR( GetEGkLogger(), "RLT_B_MINDIST_PLUS: failed attempt to identify mismatch region, type1") ; + return false ; + } + DBLVECTOR vdParamPos0 ; vdParamPos0.reserve( nPointsBetween0 + 2) ; + DBLVECTOR vdParamPos1 ; vdParamPos1.reserve( nPointsBetween1 + 2) ; + for ( int k = 0 ; k <= nPointsBetween0 ; ++k) { + double dLen = 0 ; pCC0->GetLengthAtParam( k, dLen) ; + vdParamPos0.push_back( dLen / dLen0) ; + } + vdParamPos0.push_back( 1) ; + for ( int k = 0 ; k <= nPointsBetween1 ; ++k) { + double dLen = 0 ; pCC1->GetLengthAtParam( k, dLen) ; + vdParamPos1.push_back( dLen / dLen1) ; + } + vdParamPos1.push_back( 1) ; + + bool bSplitToAdd = true ; + int c0 = 1, c1 = 1 ; + //debug + int nCBerfore = c ; + int nJBefore = j ; + //debug + double dLastParamMatch0Before = dLastParamMatch0 ; + double dLastParamMatch1Before = dLastParamMatch1 ; + while ( bSplitToAdd) { + if ( c0 > ssize( vdParamPos0) - 1 && c1 > ssize( vdParamPos1) - 1) { + LOG_DBG_ERR( GetEGkLogger(), "Surf Bez Ruled Guided: error 1 while reparametrizing some section") ; + return false ; + } + // se ho una corrispondenza tra punti ( e non sono alla fine del tratto) allora non aggiungo split + if ( abs( vdParamPos0[c0] - vdParamPos1[c1]) < EPS_PARAM && vdParamPos0[c0] < 1) { + ++c ; + ++j ; + vPairs.emplace_back( c + nSplit0, j + nSplit1) ; + ptLastPointMatch0 = vPnt0[c] ; + dLastParamMatch0 = c ; + ptLastPointMatch1 = vPnt1[j] ; + dLastParamMatch1 = j ; + ++c0 ; + ++c1 ; + } + // se non ho corrispondenza allora aggiungo uno split sulla curva a cui manca il punto corrispondente + else if ( vdParamPos0[c0] < vdParamPos1[c1]) { + double dPar ; pCC1->GetParamAtLength( dLen1 * vdParamPos0[c0], dPar) ; + Point3d ptMatch ; pCC1->GetPointD1D2( dPar, ICurve::Side::FROM_MINUS, ptMatch) ; + ptLastPointMatch1 = ptMatch ; + double dParamMatch ; CrvU1.GetParamAtPoint( ptMatch, dParamMatch) ; + dLastParamMatch1 = dParamMatch ; + // se lo split non è in prossimità di una joint già esistente allora lo aggiungo + if ( abs( dParamMatch - round( dParamMatch)) > EPS_SMALL) { + vdSplit1.push_back( dParamMatch) ; + nSplit1 = vdSplit1.size() ; + } + else if ( dParamMatch = round( dParamMatch) ; dParamMatch > j){ + ++ j ; + } + ++c ; + vPairs.emplace_back( c + nSplit0, j + nSplit1) ; + ptLastPointMatch0 = vPnt0[c] ; + dLastParamMatch0 = c ; + ++c0 ; + } + else if ( vdParamPos0[c0] > vdParamPos1[c1]) { + double dPar ; pCC0->GetParamAtLength( dLen0 * vdParamPos1[c1], dPar) ; + Point3d ptMatch ; pCC0->GetPointD1D2( dPar, ICurve::Side::FROM_MINUS, ptMatch) ; + ptLastPointMatch0 = ptMatch ; + double dParamMatch ; CrvU0.GetParamAtPoint( ptMatch, dParamMatch) ; + dLastParamMatch0 = dParamMatch ; + // se lo split non è in prossimità di una joint già esistente allora lo aggiungo + if ( abs( dParamMatch - round( dParamMatch)) > EPS_SMALL) { + vdSplit0.push_back( dParamMatch) ; + nSplit0 = vdSplit0.size() ; + } + else if ( dParamMatch = round( dParamMatch) ; dParamMatch > c){ + ++ c ; + } + ++j ; + vPairs.emplace_back( c + nSplit0, j + nSplit1) ; + ptLastPointMatch1 = vPnt1[j] ; + dLastParamMatch1 = j ; + ++c1 ; + } + else { + LOG_DBG_ERR( GetEGkLogger(), "Surf Bez Ruled Guided: error 2 while reparametrizing some section") ; + return false ; + } + bSplitToAdd = ! ( c0 == ssize( vdParamPos0) - 1 && c1 == ssize( vdParamPos1) - 1) ; + } + } } } bAdvance = ! (c >= int(vMatch0.size()) - 1 && j >= int(vMatch1.size()) - 1) ; @@ -5497,7 +5666,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int #if SAVERULEDISO //debug - vector vGeo ; + vGeo.clear() ; ICURVEPOVECTOR vCrv ; GetAllPatchesIsocurves( false, vCrv) ; for( int i = 0 ; i < ssize( vCrv) ; ++i) { @@ -6182,7 +6351,7 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c #if SAVERULEDGUIDEDISO //debug - vector vGeo ; + vGeo.clear() ; ICURVEPOVECTOR vCrvIso ; GetAllPatchesIsocurves( false, vCrvIso) ; for( int i = 0 ; i < ssize( vCrvIso) ; ++i) { diff --git a/Trimming.cpp b/Trimming.cpp index f8c0f99..bf8199c 100644 --- a/Trimming.cpp +++ b/Trimming.cpp @@ -288,6 +288,115 @@ GetPointSetByAngTol( const PolyLine& PL, double dAngTol, POLYLINEVECTOR& vPL) return true ; } +//----------------------------------------------------------------------------- +// Funzione per spezzare una curva compo in diversi tratti in corrispondenza +// di cambi di direzione maggiori della tolleranza angolare passata +static bool +SplitCurveCompoByAngTol( const ICurveComposite* pCC, double dAngTol, ICRVCOMPOPOVECTOR& vCC) +{ + int nCurves = pCC->GetCurveCount() ; + vCC.emplace_back( CreateCurveComposite()) ; + vCC.back()->AddCurve( pCC->GetCurve(0)->Clone()) ; + // Cos della tolleranza angolare massima + double dCosTol = cos( dAngTol * DEGTORAD) ; + + for ( int nC = 0 ; nC < nCurves - 2; ++ nC) { + // Recupero l'angolo tra la fine della curva corrente e l'inizio della successiva + const ICurve* pCrvCurr = pCC->GetCurve( nC) ; + const ICurve* pCrvNext = pCC->GetCurve( nC + 1) ; + Vector3d vtCurrEnd ; pCrvCurr->GetEndDir( vtCurrEnd) ; + Vector3d vtNextStart ; pCrvNext->GetStartDir( vtNextStart) ; + // Calcolo il Coseno tra i due versori + double dCos = vtCurrEnd * vtNextStart ; + // Se dentro alla tolleranza, allora i punti apparterranno alla stessa curva + if ( dCos > dCosTol) { + // Aggiungo la curva + vCC.back()->AddCurve( pCrvNext->Clone()) ; + } + // Se tratto al di fuori della tolleranza, devo definire una nuova curva + else { + vCC.emplace_back( CreateCurveComposite()) ; + vCC.back()->AddCurve( pCrvNext->Clone()) ; + } + } + + // Se curva originale chiusa + if ( pCC->IsClosed() && ssize( vCC) > 1) { + // Se ho più tratti, potrei riunire il primo con l'ultimo + const ICurve* pCrvFirst = pCC->GetCurve( 0) ; + const ICurve* pCrvLast = pCC->GetCurve( nCurves - 1) ; + Vector3d vtFirstStart ; pCrvFirst->GetEndDir( vtFirstStart) ; + Vector3d vtLastEnd ; pCrvLast->GetStartDir( vtLastEnd) ; + // Calcolo il Coseno tra i due versori + double dCos = vtFirstStart * vtLastEnd ; + // Se dentro alla tolleranza, allora i punti appartengono alla stessa curva + if ( dCos > dCosTol) { + // Aggiungo la curva + vCC.back()->AddCurve( Release( vCC.front())) ; + vCC.erase( vCC.begin()) ; + } + } + + return true ; +} + +////----------------------------------------------------------------------------- +//// Funzione che approssima la curva di bordo per la costruzione della Bezier Ruled mediante +//// Patches di curve di Bezier +//static bool +//ApproxBorder( ICurveComposite* pCrvCompo, double dLinTol, double dAngTol, double dAngTolSplit) +//{ +// // N.B.:in futuro bisognerebbe fare l'approssimazione direttamente con le bezier. +// +// // Controllo dei parametri +// if ( pCrvCompo == nullptr || ! pCrvCompo->IsValid()) +// return false ; +// +// // splitto la curva considerando la tolleranza angolare +// ICRVCOMPOPOVECTOR vCC ; +// SplitCurveCompoByAngTol( pCrvCompo, dAngTolSplit, vCC) ; +// #if DEBUG_BEZIER_INTERP +// VT.clear() ; +// for( int i = 0 ; i < ssize(vCC) ; ++i) +// VT.push_back( vCC[i]->Clone()) ; +// SaveGeoObj( VT, "D:\\Temp\\trimming\\AngBorderApprox.nge") ; +// VT.clear() ; +// #endif +// +// pCrvCompo->Clear() ; +// +// // Ogni PolyLine ricavata viene approssimata con un tratto di Bezier +// const double MAXLEN = 1.5 ; +// for ( ICurveComposite* pCC : vCC) { +// // Se meno di due curve, non la considero ( non dovrebbe mai capitare ) +// if ( pCC->GetCurveCount() < 2) +// continue ; +// PolyArc PA ; +// if ( ! pCC->ApproxWithArcs( dLinTol, dAngTol, PA)) +// return false ; +// CurveComposite CrvTemp ; +// if ( ! CrvTemp.FromPolyArc( PA) || ! CrvTemp.MergeCurves( dLinTol, dAngTol)) +// return false ; +// #if DEBUG_BEZIER_INTERP +// VT.emplace_back( CrvTemp->Clone()) ; +// #endif +// // Converto in Bezier +// PtrOwner pCrvBz( CurveToBezierCurve( &CrvTemp)) ; +// if ( IsNull( pCrvBz) || ! pCrvBz->IsValid()) { +// LOG_ERROR( GetEGkLogger(), "Error : converrting curve to bezier") ; +// return false ; +// } +// // Aggiungo il tratto approssimato alla curva finale complessiva +// if ( ! pCrvCompo->AddCurve( Release( pCrvBz))) +// return false ; +// } +// #if DEBUG_BEZIER_INTERP +// SaveGeoObj( VT, VC, "D:\\Temp\\trimming\\bezier_edge.nge") ; +// #endif +// +// return ( pCrvCompo->IsValid()) ; +//} + //----------------------------------------------------------------------------- // Funzione che approssima la curva di bordo per la costruzione della Bezier Ruled mediante // Patches di curve di Bezier