From 979597084db59f9316bc2de20e9fe751dd369992 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Tue, 26 May 2026 11:27:27 +0200 Subject: [PATCH] EgtGeomKernel : - migliorie e correzioni a RuledSmooth. --- CurveAux.cpp | 79 +++++++++++++++----- SurfBezier.cpp | 192 ++++++++++++++----------------------------------- 2 files changed, 115 insertions(+), 156 deletions(-) diff --git a/CurveAux.cpp b/CurveAux.cpp index e330f0a..1580d02 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -2703,6 +2703,18 @@ GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert) return true ; } +//---------------------------------------------------------------------------- +double +CalcWeightVal( double dLen, const ICurve* pCrv, const Vector3d vtCurr1, const Point3d& ptCurr1, double dCoeff, double dMyDist, double& dUStep2) +{ + pCrv->GetParamAtLength( dLen, dUStep2) ; + Point3d ptStep2 ; Vector3d vtStep2 = V_NULL ; + pCrv->GetPointD1D2( dUStep2, ICurve::FROM_MINUS, ptStep2, &vtStep2) ; vtStep2.Normalize() ; + double dStepCos2 = vtCurr1 * vtStep2 ; + double dDist = Dist( ptCurr1, ptStep2) ; + return (1 - dStepCos2) + dCoeff * dDist / dMyDist ; +} + //---------------------------------------------------------------------------- bool GetIsoPointOnSecondCurve( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2, double dUCurr1, double& dUCurr2, double dMyDist, double dUPrev2, @@ -2711,6 +2723,7 @@ GetIsoPointOnSecondCurve( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2, doub Point3d ptCurr1 ; Vector3d vtCurr1 ; pCrvEdge1->GetPointD1D2( dUCurr1, ICurve::FROM_MINUS, ptCurr1, &vtCurr1) ; + vtCurr1.Normalize() ; // --- Piano di taglio per punto a minima distanza IntersCurvePlane ICP( *pCrvEdge2, ptCurr1, vtCurr1) ; int nIndParCloser = - 1, nIndPointCloser = -1 ; @@ -2786,31 +2799,59 @@ GetIsoPointOnSecondCurve( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2, doub // Verifico se le direzioni tangenti sono tra di loro circa parallele const double COS_ANG_TOL = cos( 15. * DEGTORAD) ; - if ( vtCurr1 * vtCurr2 < COS_ANG_TOL) { - // Se fuori dalla tolleranza, recupero il miglior versore tangente sul secondo bordo nell'intervallo successivo di lunghezza ( 2. * dMyDist) + const double COS_SMALL_ANG_TOL = cos( 4. * DEGTORAD) ; + double dSearchLen = dMyDist / 2 ; + int NUM_STEP = 10 ; + const double dCoeff = 0.1 ; + double dCos = vtCurr1 * vtCurr2 ; + double dDistCurr = Dist( ptCurr1, ptCurr2) ; + double dMin = (1 - dCos) + dCoeff * dDistCurr / dMyDist ; + double bUpdated = false ; + // se poco fuori tolleranza controllo se ho un punto abbastanza vicino con la stessa tangente + if ( vtCurr1 * vtCurr2 < COS_SMALL_ANG_TOL) { + // Se tanto fuori dalla tolleranza, recupero il miglior versore tangente sul secondo bordo nell'intervallo successivo di lunghezza ( 2. * dMyDist) + if ( vtCurr1 * vtCurr2 < COS_ANG_TOL) { + dSearchLen = dMyDist ; + NUM_STEP = 20 ; + } pCrvEdge2->GetLengthAtPoint( ptCurr2, dLenCurr2) ; - double dLimInfLen2 = Clamp( dLenCurr2 - dMyDist, dLenPrev2, dLen2) ; - double dLimSupLen2 = Clamp( dLenCurr2 + dMyDist, dLenPrev2, dLen2) ; - // [Controllo migliorabile, magari mendiante metodo di bisezione (?)] - const int NUM_STEP = 20 ; - double dMinCos = - 1. - EPS_ZERO ; - const double DEGTOL = 5. ; + double dLimInfLen2 = Clamp( dLenCurr2 - dSearchLen, dLenPrev2, dLen2) ; + double dLimSupLen2 = Clamp( dLenCurr2 + dSearchLen, dLenPrev2, dLen2) ; + + // faccio un campionamento grossolano e poi campiono più finemente in prossimità dei minimi + DBLVECTOR vVal ; for ( int i = 0 ; i <= NUM_STEP ; ++ i) { double dLen = dLimInfLen2 + i * ( dLimSupLen2 - dLimInfLen2) / NUM_STEP ; - double dUStep2 ; pCrvEdge2->GetParamAtLength( dLen, dUStep2) ; - Point3d ptStep2 ; Vector3d vtStep2 = V_NULL ; - pCrvEdge2->GetPointD1D2( dUStep2, ICurve::FROM_MINUS, ptStep2, &vtStep2) ; vtStep2.Normalize() ; - double dStepCos2 = vtCurr1 * vtStep2 ; - double dAngTol = ( i < NUM_STEP / 2 ? ( 2. * DEGTOL) / NUM_STEP * i : - ( - 2. * DEGTOL) / NUM_STEP * ( i - NUM_STEP)) ; - double dCosTol = 1. - cos( dAngTol * DEGTORAD) ; - if ( dStepCos2 + dCosTol > dMinCos) { - ptCurr2 = ptStep2 ; - vtCurr2 = vtStep2 ; + double dUStep2 ; + vVal.push_back( CalcWeightVal( dLen, pCrvEdge2, vtCurr1, ptCurr1, dCoeff, dMyDist, dUStep2)) ; + if ( vVal.back() < dMin) { + dMin = vVal.back() ; dUCurr2 = dUStep2 ; - dMinCos = dStepCos2 + dCosTol ; + } + } + DBLDBLVECTOR vInterv ; + for ( int i = 1 ; i < ssize(vVal) - 1 ; ++i) { + if ( vVal[i] < vVal[i-1] && vVal[i] < vVal[i+1]) + vInterv.emplace_back( dLimInfLen2 + ( i - 1) * ( dLimSupLen2 - dLimInfLen2) / NUM_STEP, + dLimInfLen2 + ( i + 1) * ( dLimSupLen2 - dLimInfLen2) / NUM_STEP) ; + } + if ( ssize( vInterv) != 0) { + for ( int j = 0 ; j < ssize( vInterv) ; ++j) { + for ( int i = 0 ; i <= NUM_STEP ; ++ i) { + double dLen = vInterv[j].first + i * ( vInterv[j].second - vInterv[j].first) / NUM_STEP ; + double dUStep2 ; + double dVal = CalcWeightVal( dLen, pCrvEdge2, vtCurr1, ptCurr1, dCoeff, dMyDist, dUStep2) ; + if ( dVal < dMin) { + dUCurr2 = dUStep2 ; + dMin = dVal ; + bUpdated = true ; + } + } } } } + // se il parametro è cambiato devo ricalcolare la lunghezza, che viene restituita + if ( bUpdated) + pCrvEdge2->GetLengthAtParam( dUCurr2, dLenCurr2) ; return true ; } \ No newline at end of file diff --git a/SurfBezier.cpp b/SurfBezier.cpp index fbb82b7..7fe348b 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -5976,103 +5976,6 @@ CalcSyncPointFromEdge( const SHARPEDGEVECTOR& vSharpEdge, const ICurveComposite* return true ; } -// --------------------------------------------------------------------------- -// Calcolo della curva di Sync tra un punto di una curva di Bordo (calcolato come il punto a curvatura massima) e il suo -// associato sull'altra Curva di Bordo -// -> Restituisce la singola Linea di Sincronizzazione -static bool -CalcSyncPointFromCurvature( const CurvaturePoint& PointK, const ICurveComposite* pCompoSubEdge, BIPOINT& SyncLine) -{ - // Verifico la validità del SubEdge su cui trovare il punto di Sincronizzazione - if ( pCompoSubEdge == nullptr || ! pCompoSubEdge->IsValid()) - return false ; - - // --- Piano di taglio per punto a distanza minima - double dUCurrSubEdge = 0. ; - IntersCurvePlane ICP( *pCompoSubEdge, PointK.ptCurvature, Media( PointK.vtTanPrev, PointK.vtTanNext)) ; - int nIndParCloser = -1, nIndPointCloser = -1 ; - double dSqMinDist = INFINITO ; - for ( int nInfo = 0 ; nInfo < ICP.GetIntersCount() ; ++ nInfo) { - IntCrvPlnInfo aInfo ; - if ( ICP.GetIntCrvPlnInfo( nInfo, aInfo)) { - if ( nIndParCloser == -1) - nIndParCloser = nInfo ; - double dSqDist = SqDist( PointK.ptCurvature, aInfo.Ici[0].ptI) ; - if ( dSqDist < dSqMinDist) { - dSqMinDist = dSqDist ; - nIndPointCloser = nInfo ; - } - } - } - bool bOkPlane = ( nIndParCloser != -1 && nIndPointCloser != -1) ; - if ( bOkPlane) { - // Se gli indici sono tra loro coerenti allora ho individuato il punto - if ( nIndParCloser == nIndPointCloser) { - IntCrvPlnInfo aInfo ; - ICP.GetIntCrvPlnInfo( nIndParCloser, aInfo) ; - dUCurrSubEdge = aInfo.Ici[0].dU ; - } - // Se gli indici sono discordi, devo scegliere quale dei due punti tenere - else { - // scelgo il punto più vicino al corrente - IntCrvPlnInfo aInfoPt, aInfoPar ; - ICP.GetIntCrvPlnInfo( nIndPointCloser, aInfoPt) ; - ICP.GetIntCrvPlnInfo( nIndParCloser, aInfoPar) ; - dUCurrSubEdge = ( SqDist( PointK.ptCurvature, aInfoPt.Ici[0].ptI) < SqDist( PointK.ptCurvature, aInfoPar.Ici[0].ptI) ? - aInfoPt.Ici[0].dU : aInfoPar.Ici[0].dU) ; - } - } - if ( ! bOkPlane) { - // --- Altrimenti, cerco il punto a minima distanza - DistPointCurve DPC( PointK.ptCurvature, *pCompoSubEdge) ; - int nFlag ; - bool bOkMinDist = ( DPC.GetParamAtMinDistPoint( 0., dUCurrSubEdge, nFlag)) ; - if ( ! bOkMinDist) { - // --- Alla peggio mi posiziono a metà tra la posizione corrente e quella finale - double dPrevLen ; pCompoSubEdge->GetLengthAtParam( 0., dPrevLen) ; - double dLen ; pCompoSubEdge->GetLength( dLen) ; - pCompoSubEdge->GetParamAtLength( ( dPrevLen + dLen) / 2., dUCurrSubEdge) ; - } - } - - // Definisco il primo estremo della linea di Sincronizzazione corrente - SyncLine.first = PointK.ptCurvature ; - - // Verifico se posso muovermi attorno al punto trovato per allinearmi meglio con le normali alla curva - // NB. Si cerca di privilgiare i punti più vicini ( in parametro) al punto calcolato sopra, in modo da cercare di - // non discostare troppo la Linea di sincronizzazione dal punto trovato. - const double MAX_DIST = 2.5 ; - const int NUM_SAMPLE_PNT = 20 ; - double dLen ; pCompoSubEdge->GetLength( dLen) ; - double dSyncLen ; pCompoSubEdge->GetLengthAtParam( dUCurrSubEdge, dSyncLen) ; - Vector3d vtSyncTanPrev, vtSyncTanNext ; - pCompoSubEdge->GetPointD1D2( dUCurrSubEdge, ICurve::FROM_MINUS, SyncLine.second, &vtSyncTanPrev) ; vtSyncTanPrev.Normalize() ; - pCompoSubEdge->GetPointD1D2( dUCurrSubEdge, ICurve::FROM_PLUS, SyncLine.second, &vtSyncTanNext) ; vtSyncTanNext.Normalize() ; - double dLimInfLen = Clamp( dSyncLen - MAX_DIST, 0., dLen) ; - double dLimSupLen = Clamp( dSyncLen + MAX_DIST, 0., dLen) ; - int nSamplePnt = int( ceil( NUM_SAMPLE_PNT / 4.)) ; - double dMaxCos = ( Media( PointK.vtTanPrev, PointK.vtTanNext) * Media( vtSyncTanPrev, vtSyncTanNext)) ; - double dShiftR = ( dLimSupLen - dSyncLen) / nSamplePnt ; - double dShiftL = ( dSyncLen - dLimInfLen) / nSamplePnt ; - array vdLens = { dSyncLen, dSyncLen} ; - for ( int i = 1 ; i <= nSamplePnt ; ++ i) { - vdLens[0] += dShiftR ; - vdLens[1] -= dShiftL ; - for ( int j = 0 ; j < 2 ; ++ j) { - double dU ; pCompoSubEdge->GetParamAtLength( vdLens[j], dU) ; - Point3d ptCurr ; Vector3d vtTan ; - pCompoSubEdge->GetPointD1D2( dU, ICurve::FROM_MINUS, ptCurr, &vtTan) ; vtTan.Normalize() ; - double dCos = ( vtTan * Media( PointK.vtTanPrev, PointK.vtTanNext)) ; - if ( dCos > dMaxCos) { - dMaxCos = dCos ; - SyncLine.second = ptCurr ; - } - } - } - - return true ; -} - // --------------------------------------------------------------------------- // Gestione degli spigoli all'interno della Quadrangolazione corrente static bool @@ -6184,7 +6087,7 @@ ManageEdgesInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp // --------------------------------------------------------------------------- // Calcolo delle Curve di Sync per evitare Twist static bool -ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComposite* pSubEdge2, BIPNTVECTOR& vSyncLines) +ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComposite* pSubEdge2, BIPNTVECTOR& vSyncLines, bool& bEraseLastIso) { // Verifica validità delle curve if ( pSubEdge1 == nullptr || ! pSubEdge1->IsValid() || pSubEdge2 == nullptr || ! pSubEdge2->IsValid()) @@ -6192,6 +6095,7 @@ ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp const double COS_LIMIT = cos( 50. * DEGTORAD) ; const int NUM_SAMPLE_PNT = 20 ; + const int nStepSkip = NUM_SAMPLE_PNT / 10 ; #if DEBUG_CURVATURE vector> _vPtK1 ; vector> _vPtK2 ; @@ -6203,13 +6107,16 @@ ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp Vector3d vtS1 ; pSubEdge1->GetStartDir( vtS1) ; Vector3d vtE1 ; pSubEdge1->GetEndDir( vtE1) ; double dLen1 = - EPS_SMALL ; + double dLen2 = - EPS_SMALL ; + pSubEdge1->GetLength( dLen1) ; + pSubEdge2->GetLength( dLen2) ; + double dMyDist = min( dLen1, dLen2) * 0.85 ; bool bSplit1 = ( vtS1 * vtE1 < COS_LIMIT) ; if ( bSplit1) { // Individuo il punto a Curvatura Massima - pSubEdge1->GetLength( dLen1) ; double dKMax1 = - INFINITO + 1, dUK1Max = - EPS_SMALL ; Point3d ptKMax1 ; Vector3d vtTanKMax1Prev, vtTanKMax1Next ; - for ( int i = 0 ; i <= NUM_SAMPLE_PNT ; ++ i) { + for ( int i = nStepSkip ; i <= NUM_SAMPLE_PNT - nStepSkip ; ++ i) { // Ricavo la Lunghezza corrente e il parametro dU associato double dCurrLen1 = Clamp( i * ( dLen1 / NUM_SAMPLE_PNT), 0., dLen1) ; double dUCurr1 ; pSubEdge1->GetParamAtLength( dCurrLen1, dUCurr1) ; @@ -6237,22 +6144,21 @@ ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp vtTanKMax1Next.Normalize() ; // Calcolo la nuova linea di sincronizzazione CurvaturePoint myCurvaturePoint( dUK1Max, ptKMax1, vtTanKMax1Prev, vtTanKMax1Next) ; - BIPOINT SyncLine ; - CalcSyncPointFromCurvature( myCurvaturePoint, pSubEdge2, SyncLine) ; - vSyncLines.emplace_back( SyncLine) ; + double dUOn2 ; double dLenCurr2 ; + GetIsoPointOnSecondCurve( pSubEdge1, pSubEdge2, dUK1Max, dUOn2, dMyDist, 0, 0, dLenCurr2, dLen2) ; + Point3d ptOn2 ; pSubEdge2->GetPointD1D2( dUOn2, ICurve::FROM_MINUS, ptOn2) ; + vSyncLines.emplace_back( ptKMax1, ptOn2) ; } // --- Verifico il cambiamento di Deviazione angolare tra Inizio-Fine del tratto per la prima curva di Bordo Vector3d vtS2 ; pSubEdge2->GetStartDir( vtS2) ; Vector3d vtE2 ; pSubEdge2->GetEndDir( vtE2) ; - double dLen2 = - EPS_SMALL ; bool bSplit2 = ( vtS2 * vtE2 < COS_LIMIT) ; if ( bSplit2) { // Individuo il punto a Curvatura Massima - pSubEdge2->GetLength( dLen2) ; double dKMax2 = - INFINITO + 1, dUK2Max = - EPS_SMALL ; Point3d ptKMax2 ; Vector3d vtTanKMax2Prev, vtTanKMax2Next ; - for ( int i = 0 ; i <= NUM_SAMPLE_PNT ; ++ i) { + for ( int i = nStepSkip ; i <= NUM_SAMPLE_PNT - nStepSkip ; ++ i) { // Ricavo la Lunghezza corrente e il parametro dU associato double dCurrLen2 = Clamp( i * ( dLen2 / NUM_SAMPLE_PNT), 0., dLen2) ; double dUCurr2 ; pSubEdge2->GetParamAtLength( dCurrLen2, dUCurr2) ; @@ -6280,11 +6186,10 @@ ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp vtTanKMax2Next.Normalize() ; // Calcolo la nuova linea di sincronizzazione CurvaturePoint myCurvaturePoint( dUK2Max, ptKMax2, vtTanKMax2Prev, vtTanKMax2Next) ; - BIPOINT SyncLine ; - CalcSyncPointFromCurvature( myCurvaturePoint, pSubEdge1, SyncLine) ; - // !<-- Inverto la curva di Sincronizzaione per coerenza con la prima -->! - swap( SyncLine.first, SyncLine.second) ; - vSyncLines.emplace_back( SyncLine) ; + double dUOn1 ; double dLenCurr1 ; + GetIsoPointOnSecondCurve( pSubEdge2, pSubEdge1, dUK2Max, dUOn1, dMyDist, 0, 0, dLenCurr1, dLen1) ; + Point3d ptOn1 ; pSubEdge1->GetPointD1D2( dUOn1, ICurve::FROM_MINUS, ptOn1) ; + vSyncLines.emplace_back( ptOn1, ptKMax2) ; } #if DEBUG_CURVATURE // Curvatura minima -> AQUA | Curvatura massima -> ORANGE @@ -6338,17 +6243,25 @@ ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp // NB. Risultano ridondanti, creano SottoQuadrangolazioni molto strette o possono Inclinare eccssivamente l'Utensile // NB. Così facendo evito anche di creare curve di Sync lungo le diagonali della Quadrangolazione const double LEN_TOL = 2. ; + const double dParTol = 0.1 ; + double dLenPrev1 = - LEN_TOL, dLenPrev2 = - LEN_TOL ; for ( int i = 0 ; i < ssize( vSyncLines) ; ++ i) { double dSyncLen1 ; pSubEdge1->GetLengthAtPoint( vSyncLines[i].first, dSyncLen1, TOL) ; - bool bErase = ( dSyncLen1 < max( LEN_TOL, 0.2 * dLen1) || dSyncLen1 > min( dLen1 - LEN_TOL, 0.8 * dLen1)) ; + bool bErase = ( dSyncLen1 < max( LEN_TOL, dParTol * dLen1) || dSyncLen1 - dLenPrev1 < LEN_TOL) ; + bEraseLastIso = dSyncLen1 > min( dLen1 - LEN_TOL, ( 1 - dParTol) * dLen1) ; if ( ! bErase) { double dSyncLen2 ; pSubEdge2->GetLengthAtPoint( vSyncLines[i].second, dSyncLen2, TOL) ; - bErase = ( dSyncLen2 < max( LEN_TOL, 0.2 * dLen2) || dSyncLen2 > min( dLen2 - LEN_TOL, 0.8 * dLen2)) ; + bErase = ( dSyncLen2 < max( LEN_TOL, dParTol * dLen2) || dSyncLen2 - dLenPrev2 < LEN_TOL) ; + bEraseLastIso = bEraseLastIso || dSyncLen2 > min( dLen2 - LEN_TOL, ( 1 - dParTol) * dLen2) ; + dLenPrev2 = dSyncLen2 ; } - if ( bErase) { + if ( bErase && ! bEraseLastIso) { vSyncLines.erase( vSyncLines.begin() + i) ; -- i ; } + dLenPrev1 = dSyncLen1 ; + if ( bEraseLastIso) + break ; } if ( vSyncLines.empty()) return true ; @@ -6374,6 +6287,10 @@ ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp vSyncLines.pop_back() ; // lascio solo la prima... ( bisognerebbe scegliere quale lasciare con un criterio migliore ?) } + // se ne ho due tengo solo la prima + if ( ssize( vSyncLines) == 2) + vSyncLines.pop_back() ; + return true ; } @@ -6420,11 +6337,11 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p // Recupero dU, Point3d e dLen corrente sul primo bordo, per un incremento del passo di campionamento dLenCurr1 = Clamp( dLenPrev1 + dMyDist, 0., dLen1) ; pCrvEdge1->GetParamAtLength( dLenCurr1, dUCurr1) ; - //// se sono abbastanza vicino ad una joint allora prendo quel punto - //double dUClosestJoint1 = round( dUCurr1) ; - //double dLenAlt1 = 0 ; pCrvEdge1->GetLengthAtParam( dUClosestJoint1, dLenAlt1) ; - //if ( abs( dLenCurr1 - dLenAlt1) < 1) - // dUCurr1 = dUClosestJoint1 ; + // se sono abbastanza vicino ad una joint allora prendo quel punto + double dUClosestJoint1 = round( dUCurr1) ; + double dLenAlt1 = 0 ; pCrvEdge1->GetLengthAtParam( dUClosestJoint1, dLenAlt1) ; + if ( abs( dLenCurr1 - dLenAlt1) < 1) + dUCurr1 = dUClosestJoint1 ; pCrvEdge1->GetPointD1D2( dUCurr1, ICurve::FROM_MINUS, ptCurr1, &vtCurr1) ; vtCurr1.Normalize() ; @@ -6437,14 +6354,17 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p GetIsoPointOnSecondCurve( pCrvEdge1, pCrvEdge2, dUCurr1, dUCurr2, dMyDist, dUPrev2, dLenPrev2, dLenCurr2, dLen2) ; + //////////////////////////N.B.: se si aggiunge questo pezzo bisogna anche gestire il fatto che i punti precedentemente aggiunti potrebbero non stare più sulla curva modificata!!! //// verifico se sono vicino ad una joint esistente allora modifico la curva 2 //double dUClosestJoint2 = round( dUCurr2) ; //double dLenAlt2 = 0 ; pCrvEdge2->GetLengthAtParam( dUClosestJoint2, dLenAlt2) ; - //if ( abs( dLenCurr1 - dLenAlt2) < 1) { - // Point3d ptNewJoint ; pCrvEdge2->GetPointD1D2( dUClosestJoint2, ICurve::FROM_MINUS, ptNewJoint) ; - // pCrvEdge2->ModifyJoint( int( dUClosestJoint2), ptNewJoint) ; - // dUCurr2 = dUClosestJoint2 ; + //if ( abs( dLenCurr2 - dLenAlt2) < 1) { + // Point3d ptNewJoint ; pCrvEdge2->GetPointD1D2( dUCurr2, ICurve::FROM_MINUS, ptNewJoint) ; + // if ( pCrvEdge2->ModifyJoint( int( dUClosestJoint2), ptNewJoint)) + // dUCurr2 = dUClosestJoint2 ; //} + + pCrvEdge2->GetPointD1D2( dUCurr2, ICurve::FROM_MINUS, ptCurr2, &vtCurr2) ; #if DEBUG_SYNCLINES @@ -6455,10 +6375,6 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p #endif vSyncLines.emplace_back( ptCurr1, ptCurr2) ; - //// Inserisco le curve di sincronizzazione nel Layer di destinazine - //PtrOwner pLine( CreateCurveLine()) ; pLine->Set( ptCurr1, ptCurr2) ; - //pGeomDB->AddGeoObj( GDB_ID_NULL, nDestGrp, Release( pLine)) ; - // --- Analisi degli spigoli all'interno della Quadrangolazione corrente --- // NB. Non è sempre detto che uno spigolo di una curva sia sincronizzato con lo spigolo di un'altra ( se questi esistono)... // Pertanto la Bezier Ruled ricavata non è detto che sia in grado di approssimare lo spigolo correttamente, potrebbe sdondarlo @@ -6466,19 +6382,15 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p PtrOwner pCrvQuad2( ConvertCurveToComposite( pCrvEdge2->CopyParamRange( dUPrev2, dUCurr2))) ; BIPNTVECTOR vEdgeSyncLines ; ManageEdgesInQuadrangulation( pCrvQuad1, pCrvQuad2, vEdgeSyncLines) ; - //for ( int i = 0 ; i < ssize( vEdgeSyncLines) ; ++ i) { - // PtrOwner pLine( CreateCurveLine()) ; pLine->Set( vEdgeSyncLines[i].first, vEdgeSyncLines[i].second) ; - // int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nDestGrp, Release( pLine)) ; - // pGeomDB->SetMaterial( nNewId, GREEN) ; - //} // --- Aggiunta di Linee di Sync all'interno della Quandrangolazione corrente --- // Perchè parametrizzando per la lunghezza i SottoTratti ricavati, nel caso di elevate variazioni angolari tra l'inizio e la fine // ( tra due curva di Sync) si potrebbero generare delle torsioni non volute // -->! NB. Queste linee vengono create considerando le SubQuadrangolazioni con gli Spigoli. !<-- BIPNTVECTOR vTwistSyncLines ; + bool bEraseLastIso = false ; if ( vEdgeSyncLines.empty()) - ManageTwistInQuadrangulation( pCrvQuad1, pCrvQuad2, vTwistSyncLines) ; + ManageTwistInQuadrangulation( pCrvQuad1, pCrvQuad2, vTwistSyncLines, bEraseLastIso) ; else { BIPOINT SyncLinePrev, SyncLineNext ; pCrvQuad1->GetStartPoint( SyncLinePrev.first) ; @@ -6500,12 +6412,20 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p pCrvQuad2->GetParamAtPoint( SyncLineNext.second, dUE2) ; PtrOwner pCrvSubQuad1( ConvertCurveToComposite( pCrvQuad1->CopyParamRange( dUS1, dUE1))) ; PtrOwner pCrvSubQuad2( ConvertCurveToComposite( pCrvQuad2->CopyParamRange( dUE1, dUE2))) ; - ManageTwistInQuadrangulation( pCrvSubQuad1, pCrvSubQuad2, vTwistSyncLines) ; + ManageTwistInQuadrangulation( pCrvSubQuad1, pCrvSubQuad2, vTwistSyncLines, bEraseLastIso) ; // Aggiorno i parametri SyncLinePrev = SyncLineNext ; } + bEraseLastIso = false ; } - // aggiungo le nuove curve ( non importa che siano in ordine di parametro) + if ( bEraseLastIso) { + vSyncLines.pop_back() ; + double dQuadLen1 ; pCrvQuad1->GetLengthAtPoint( vTwistSyncLines[0].first, dQuadLen1) ; + dLenCurr1 = dLenPrev1 + dQuadLen1 ; + double dQuadLen2 ; pCrvQuad2->GetLengthAtPoint( vTwistSyncLines[0].second, dQuadLen2) ; + dLenCurr2 = dLenPrev2 + dQuadLen2 ; + } + // aggiungo le nuove curve ( non importa che siano ordinate per parametro) vSyncLines.insert( vSyncLines.end(), vEdgeSyncLines.begin(), vEdgeSyncLines.end()) ; vSyncLines.insert( vSyncLines.end(), vTwistSyncLines.begin(), vTwistSyncLines.end()) ; @@ -6518,8 +6438,6 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p SaveGeoObj( vGeo, vCol, "D:\\Temp\\bezier\\ruled\\trimming\\smooth.nge") ; #endif - - // devo riempire vSyncLines return CreateByIsoParamSet( pCrvEdge1, pCrvEdge2, vSyncLines) ; }