diff --git a/SurfBezier.cpp b/SurfBezier.cpp index e31ed9a..296581d 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -48,7 +48,7 @@ #define SAVEREBUILTISO 0 #define SAVERULEDISO 1 #define SAVERULEDGUIDEDISO 0 -#define SAVEMATCHCURVES 0 +#define SAVEMATCHCURVES 1 #if SAVEFAILEDTRIANGULATION || SAVEREBUILTISO || SAVERULEDISO || SAVERULEDGUIDEDISO || SAVEMATCHCURVES #include "/EgtDev/Include/EGkGeoObjSave.h" std::vector vGeo ; @@ -4511,6 +4511,60 @@ GetEdgeSplitByAngTol( const PolyLine& PL, double dAngTol, BOOLVECTOR& vEdgeSplit return true ; } +static bool +GetEdgeSplitByAngTol( const ICurveComposite* pCC, double dAngTol, BOOLVECTOR& vEdgeSplit) +{ + int nCrvs = pCC->GetCurveCount() ; + vEdgeSplit.clear() ; + vEdgeSplit.resize( nCrvs) ; + fill( vEdgeSplit.begin(), vEdgeSplit.end(), false) ; + bool bClosed = pCC->IsClosed() ; + Vector3d vtTanCurr = V_INVALID, vtTanNext = V_INVALID ; + // cos della tolleranza angolare massima + double dCosTol = cos( dAngTol * DEGTORAD) ; + for ( int nC = 0 ; nC < nCrvs ; ++ nC) { + const ICurve* pSubCrvCurr = pCC->GetCurve( nC) ; + int nNext = nC < nCrvs - 1 ? nC + 1 : 0 ; + const ICurve* pSubCrvNext = pCC->GetCurve( nNext) ; + pSubCrvCurr->GetEndDir( vtTanCurr) ; vtTanCurr.Normalize() ; + pSubCrvNext->GetStartDir( vtTanNext) ; vtTanNext.Normalize() ; + // Calcolo il Coseno tra i due versori + double dCos = vtTanCurr * vtTanNext ; + // Se oltre la tolleranza allora ho incontrato un edge + if ( dCos < dCosTol) + vEdgeSplit[nC] = true ; + } + + if ( ! bClosed) + vEdgeSplit[nCrvs - 1] = false ; + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +AdjustParamFromApprox( const PolyLine& plApprox, double& dParam) +{ + // il parametro in ingresso è riferito al numero di linee della polilinea + // questa variabile verrà sostituita con il valore del parametro corrispondente alla curva che è stata approssimata dalla polilinea + int nCrv = int( dParam) ; + if ( nCrv > plApprox.GetPointNbr()) + return false ; + double dParamPrev = 0 ; + plApprox.GetFirstU( dParamPrev) ; + int c = 0 ; + while ( c < nCrv) { + plApprox.GetNextU( dParamPrev) ; + ++c ; + } + double dParamNext = 0 ; + plApprox.GetNextU( dParamNext) ; + double dFactor = dParam - nCrv ; + dParam = dFactor * dParamNext + ( 1 - dFactor) * dParamPrev ; + + return true ; +} + //---------------------------------------------------------------------------- bool SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int nRuledType) @@ -4947,11 +5001,18 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int vector> vvCol0(4) ; #endif + // approssimo le curve con delle polyline per il calcolo delle distanze + PolyLine plApproxU0, plApproxU1 ; + double dLinTol = 10 * EPS_SMALL ; + double dAngTol = 5 ; + CrvU0.ApproxWithLines( dLinTol, dAngTol, ICurve::APL_STD, plApproxU0) ; + CrvU1.ApproxWithLines( dLinTol, dAngTol, ICurve::APL_STD, plApproxU1) ; + // 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) ; + CurveComposite ccPoly0 ; ccPoly0.FromPolyLine( plApproxU0) ; + CurveComposite ccPoly1 ; ccPoly1.FromPolyLine( plApproxU1) ; Point3d ptP1 ; plU1.GetFirstPoint( ptP1) ; PNTUVECTOR vMatch1 ; PNTUVECTOR vMatch1b ; @@ -4962,13 +5023,23 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int double dParam ; Point3d ptJoint ; - DistPointCurve dpc( ptP1, CrvU0, false) ; + DistPointCurve dpc( ptP1, ccPoly0, false) ; int nFlag = 0 ; dpc.GetParamAtMinDistPoint( 0, dParam, nFlag) ; + AdjustParamFromApprox( plApproxU0, dParam) ; dpc.GetMinDistPoint( 0, ptJoint, nFlag) ; vMatch1b.emplace_back( ptJoint, dParam) ; - if ( icp.GetIntersCount() > 0) + + double dParamMinDist = dParam ; + Point3d ptMinDist = ptJoint ; + if ( icp.GetIntersCount() > 0) { icp.GetIntersPointNearTo( ptP1, ptJoint, dParam) ; + AdjustParamFromApprox( plApproxU0, dParam) ; + if ( Dist( ptP1, ptJoint) > 2 * Dist( ptP1, ptMinDist)) { + ptJoint = ptMinDist ; + dParam = dParamMinDist ; + } + } else { ; } @@ -5011,14 +5082,22 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int Vector3d vtDir ; CrvU0.GetCurve( vPnt0.size() - 1)->GetEndDir( vtDir) ; IntersCurvePlane icp( ccPoly1, ptP0, vtDir) ; - DistPointCurve dpc( ptP0, CrvU1, false) ; + DistPointCurve dpc( ptP0, ccPoly1, false) ; int nFlag = 0 ; dpc.GetMinDistPoint( 0, ptJoint, nFlag) ; dpc.GetParamAtMinDistPoint( 0, dParam, nFlag) ; + AdjustParamFromApprox( plApproxU1, dParam) ; vMatch0b.emplace_back( ptJoint, dParam) ; + double dParamMinDist = dParam ; + Point3d ptMinDist = ptJoint ; if ( icp.GetIntersCount() > 0) { icp.GetIntersPointNearTo( ptP0, ptJoint, dParam) ; + AdjustParamFromApprox( plApproxU1, dParam) ; + if ( Dist( ptP0, ptJoint) > 2 * Dist( ptP0, ptMinDist)) { + ptJoint = ptMinDist ; + dParam = dParamMinDist ; + } } else { ; @@ -5068,7 +5147,8 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // tramite due misure diverse della distanza INTINTVECTOR vMismatch0 ; INTINTVECTOR vMismatch1 ; - double dMaxDist = Dist( vPnt0[0], vPnt1[0]) / 20 ; + //double dMaxDist = Dist( vPnt0[0], vPnt1[0]) / 20 ; + double dMaxDist = Dist( vPnt0[0], vPnt1[0]) / 3 ; for( int i = 0 ; i < ssize( vMatch0) ; ++i) { if( ! AreSamePointEpsilon( vMatch0[i].first, vMatch0b[i].first, dMaxDist)) { int c = i + 1 ; @@ -5116,9 +5196,9 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // verifico la presenza di eventuali "edge" lungo le polyline ( punti di passaggio di un edge e quindi cambi bruschi di direzione della polyline) BOOLVECTOR vEdgeSplit0, vEdgeSplit1 ; - double dAngTol = 55 ; - GetEdgeSplitByAngTol( plU0, dAngTol, vEdgeSplit0) ; - GetEdgeSplitByAngTol( plU1, dAngTol, vEdgeSplit1) ; + double dAngTolSplit = 55 ; + GetEdgeSplitByAngTol( &CrvU0, dAngTolSplit, vEdgeSplit0) ; + GetEdgeSplitByAngTol( &CrvU1, dAngTolSplit, vEdgeSplit1) ; int c = 0 ; double dLastParamMatch0 = 0 ; @@ -5135,18 +5215,20 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int bool bAdvance = true ; int m0 = 0, m1 = 0 ; // contatori delle zone di mismatch // verifico i match effettivi tra le polyline - while ( bAdvance) { + int nPairs = 0 ; + while ( bAdvance && ssize( vPairs) > nPairs) { + nPairs = ssize( vPairs) ; 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) + if( ssize( vMismatch0) > 0) { + while( m0 < ssize( vMismatch0) - 1 && c > vMismatch0[m0].second) ++m0 ; } - if( ssize(vMismatch1) > 0) { - while( m1 < ssize(vMismatch1) && j > vMismatch1[m1].second) + if( ssize( vMismatch1) > 0) { + while( m1 < ssize( vMismatch1) - 1 && j > vMismatch1[m1].second) ++m1 ; } @@ -5165,9 +5247,12 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // capisco con quale delle due polyline avanzo bool bAdvance0 = dParam0 < j + 1 + EPS_SMALL ; bool bAdvance1 = dParam1 < c + 1 + EPS_SMALL ; - // controllo se ho un match biunivoco - bool bPerfectMatch = abs( dParam0 - round( dParam0)) < EPS_SMALL && round( dParam0) == j + 1 && - abs( dParam1 - round( dParam1)) < EPS_SMALL && round( dParam1) == c + 1 ; + // controllo se ho un match biunivoco ( controllo parametri e punti) + bool bPerfectMatch = ( abs( dParam0 - round( dParam0)) < 10 * EPS_SMALL && round( dParam0) == j + 1 && + abs( dParam1 - round( dParam1)) < 10 * EPS_SMALL && round( dParam1) == c + 1) || + ( AreSamePointEpsilon( vPnt0[c+1], ptJoint1, 100 * EPS_SMALL) && AreSamePointEpsilon( vPnt1[j+1], ptJoint0, 100 * EPS_SMALL)) ; + if ( bPerfectMatch) + bAdvance0 = true ; int nSplit1 = vdSplit1.size() ; int nSplit0 = vdSplit0.size() ; // se con una polyline sono arrivato alla fine non posso più avanzare @@ -5188,7 +5273,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int bMismatch = (bMismatch0 && bMismatch1) || (bMismatch0 && ! bAdvance1) || (bMismatch1 && ! bAdvance0); } // se trovo che ho uno spigolo allora procedo con la gestione spigoli - else if( vEdgeSplit0[c+1] && vEdgeSplit1[j+1]) { + if ( vEdgeSplit0[c] && vEdgeSplit1[j]) { // se ho uno spigolo su entrambe le curve forzo l'accoppiamento bAdvance0 = true ; bPerfectMatch = true ; @@ -5197,7 +5282,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int ptJoint0 = vPnt1[j+1] ; ptJoint1 = vPnt0[c+1] ; } - else if ( (vEdgeSplit0[c+1] && ! bAdvance1) || (vEdgeSplit1[j+1] && ! bAdvance0)) { + else if ( ( vEdgeSplit0[c] && ! bAdvance1) || (vEdgeSplit1[j] && ! bAdvance0)) { // da una parte ho uno spigolo e dall'altra non posso avanzare bAdvance0 = false ; bAdvance1 = false ; @@ -5220,8 +5305,8 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } else { // ho un match con una joint esistente - if ( dParam0 - int( dParam0) < EPS_SMALL) { - if ( dParam0 > dLastParamMatch0) + if ( abs( dParam0 - round( dParam0)) < EPS_SMALL) { + if ( dParam0 > dLastParamMatch0 + EPS_SMALL) vPairs.emplace_back( c + nSplit0, j + nSplit1 + 1) ; else vPairs.emplace_back( c + nSplit0, j + nSplit1) ; @@ -5257,8 +5342,8 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } else { // ho un match con una joint esistente - if ( dParam1 - int( dParam1) < EPS_SMALL) { - if ( dParam1 > dLastParamMatch1) + if ( abs( dParam1 - round( dParam1)) < EPS_SMALL) { + if ( dParam1 > dLastParamMatch1 + EPS_SMALL) vPairs.emplace_back( c + nSplit0 + 1, j + nSplit1) ; else vPairs.emplace_back( c + nSplit0, j + nSplit1) ; @@ -5281,11 +5366,11 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int //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]) { + if ( vEdgeSplit0[c] && vEdgeSplit1[j]) { // 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] && ! bMismatch) { + if ( vEdgeSplit0[c] && ! 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 @@ -5308,10 +5393,13 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int dLastParamMatch0 = j - 1 ; ptLastPointMatch0 = vPnt1[j] ; } - else + else { bMismatch = true ; + --c ; + --j ; + } } - else if ( vEdgeSplit1[j+1] && ! bMismatch) { + else if ( vEdgeSplit1[j] && ! 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 @@ -5334,11 +5422,14 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int dLastParamMatch1 = c - 1 ; ptLastPointMatch1 = vPnt0[c] ; } - else + else { bMismatch = true ; + --c ; + --j ; + } } - if( ( ! vEdgeSplit0[c+1] && ! vEdgeSplit1[j+1]) || bMismatch) { + if( ( ! vEdgeSplit0[c] && ! vEdgeSplit1[j]) || bMismatch) { // non ci sono riferimenti per fare un match, quindi li cerco io ///////////OLD VRESION @@ -5357,7 +5448,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // identifico la zona in cui ho il mismatch e parametrizzo localmente //conto quanti punti ho nel mezzo - int c_temp, j_temp ; + int c_temp = c, j_temp = j ; if( ! bMismatch) { c_temp = c, j_temp = j ; bAdvance0 = true ; @@ -5435,6 +5526,12 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } } } + + if ( j_temp == ssize( vMatch1)) + --j_temp ; + if ( c_temp == ssize( vMatch0)) + -- c_temp ; + // se non sono avanzato, allora mi basta accoppiare i due punti in questione if( c_temp == c || j_temp == j) { ++c ;