diff --git a/Trimming.cpp b/Trimming.cpp index a197ba6..d0e892e 100644 --- a/Trimming.cpp +++ b/Trimming.cpp @@ -63,7 +63,7 @@ #define DEBUG_EDGES 0 #define DEBUG_SHAPE_STM 0 #define DEBUG_HOLES 0 -#define DEBUG_SMOOTH_CURVATURE 0 +#define DEBUG_SMOOTH_CURVATURE 1 #if DEBUG_BASIC_BORDERS || DEBUG_CHAIN_CURVES || DEBUG_ANG_APPROX || DEBUG_BEZIER_INTERP || \ DEBUG_FACE_SEARCH || DEBUG_FACE_SEARCH_TRIA_MODIF || DEBUG_BRK_POINTS || DEBUG_BRK_THICK || \ DEBUG_BRK || DEBUG_BORDERS_BY_NORMALS || DEBUG_SYNC_POINTS || DEBUG_SYNC_INTERPOLATION || \ @@ -4943,9 +4943,10 @@ RemoveInflexionPoints( PNTVECTOR& vPnt, PNTINFOVECTOR& vPntInfo, PNTINFOVECTOR& // se trovo tre punti di fila che sono dallo stesso lato, opposto a quello degli altri punti attorno, allora cerco di spostarli lungo la // normale alla superficie in modo da evitare cambi di concavità bool bSameSideAsPrev = true ; + double dSmallDist = 5 * EPS_SMALL ; for ( int i = 2 ; i < ssize( vPntInfo) - 2 ; ++i) { // se è un punto di split o sta sulla curva vado avanti - if ( vPntInfo[i].dDist < EPS_ZERO) + if ( vPntInfo[i].dDist < dSmallDist) continue ; int nPrev = vPntInfo[i-1].dDist < EPS_ZERO ? i - 2 : i - 1 ; double dProj = vPntInfo[i].vtPos * vPntInfo[nPrev].vtPos ; @@ -4972,23 +4973,29 @@ RemoveInflexionPoints( PNTVECTOR& vPnt, PNTINFOVECTOR& vPntInfo, PNTINFOVECTOR& int nNext = bCurrOrPrev ? i + 2 : i + 1 ; // se il successivo è diverso ho un terzetto anomalo da aggiustare // altrimenti ho un cambio naturale di concavità - if ( vPntInfo[i].vtPos * vPntInfo[nNext].vtPos < 0) { + if ( vPntInfo[i].vtPos * vPntInfo[nNext].vtPos < 0 || vPntInfo[nNext].dDist < dSmallDist) { // ruoto il terzetto fino a matchare la tangente sull'altra curva - Vector3d vtCurr = vPntInfo[nNext].pt - vPntInfo[i].pt ; - Vector3d vtRef = vPntRefInfo[nNext].pt - vPntRefInfo[i].pt ; - Vector3d vtAx = vPntRefInfo[nSecond].pt - vPntInfo[nSecond].pt ; - bool bDet = false ; - double dAng = 0 ; vtCurr.GetRotation(vtRef, vtAx, dAng, bDet) ; - if ( dAng > 170) { - dAng = 180 - dAng ; - // devo capire quale delle due curve ha i punti di controllo incrociati (come conseguenza della correzione precedente) e rimediare - // DA IMPLEMENTARE, eventualmente - } // ruoto il punto solo se non stava già esattamente sulla SubCrv ( che suppongo essere un tratto rettilineo) - if ( vPntInfo[nFirst].dDist > EPS_ZERO) + if ( vPntInfo[nFirst].dDist > dSmallDist) { + Vector3d vtCurr = vPntInfo[nSecond].pt - vPntInfo[nFirst].pt ; + Vector3d vtRef = vPntRefInfo[nSecond].pt - vPntRefInfo[nFirst].pt ; + Vector3d vtAx = vPntRefInfo[nSecond].pt - vPntInfo[nSecond].pt ; + bool bDet = false ; + double dAng = 0 ; vtCurr.GetRotation(vtRef, vtAx, dAng, bDet) ; + if ( abs(dAng) > 170) + dAng = 180 - dAng ; vPnt[nFirst].Rotate( vPnt[nSecond], vtAx, dAng) ; - if ( vPntInfo[nThird].dDist > EPS_ZERO) + } + if ( vPntInfo[nThird].dDist > dSmallDist) { + Vector3d vtCurr = vPntInfo[nThird].pt - vPntInfo[nSecond].pt ; + Vector3d vtRef = vPntRefInfo[nThird].pt - vPntRefInfo[nSecond].pt ; + Vector3d vtAx = vPntRefInfo[nSecond].pt - vPntInfo[nSecond].pt ; + bool bDet = false ; + double dAng = 0 ; vtCurr.GetRotation(vtRef, vtAx, dAng, bDet) ; + if ( abs(dAng) > 170) + dAng = 180 - dAng ; vPnt[nThird].Rotate( vPnt[nSecond], vtAx, dAng) ; + } if ( bCurrOrPrev) i += 2 ; } @@ -4998,235 +5005,14 @@ RemoveInflexionPoints( PNTVECTOR& vPnt, PNTINFOVECTOR& vPntInfo, PNTINFOVECTOR& return true ; } -//------------------------------------------------------------------------------ -// Funzione per la regolarizzazione delle curve di bordo di una lavorazione di trim -// Le curve vengono modificate entro una data tolleranza, in modo che -ISurfBezier* -RegolarizeBordersLocally( const ISurfBezier* pSurfBz, const BIPOINT& bpIsoStart, const BIPOINT& bpIsoEnd, double dTol) -{ - #if DEBUG_SMOOTH_CURVATURE - VT.clear() ; - #endif - - // prendo per buone le isocurve di inizio e fine tratto e devo identificare tra loro le isocurve che creano troppo twist e che sono da raddrizzare - Point3d ptS1 = bpIsoStart.first ; - Point3d ptS2 = bpIsoEnd.first ; - Vector3d vtDir1 = bpIsoStart.second - ptS1 ; - Vector3d vtDir2 = bpIsoEnd.second - ptS2 ; - double dInterpolateAngTol = 4 ; - double dAngInterp = 0 ; - vtDir1.GetAngle( vtDir2, dAngInterp) ; - bool bInterpolate = dAngInterp > dInterpolateAngTol ; - - int nDegU, nDegV, nSpanU, nSpanV ; - bool bRat, bTrimmed ; - pSurfBz->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bRat, bTrimmed) ; - if ( nDegU != 3) - return nullptr ; - // individuo quali isocurve sono state indicate come inizio e fine - PtrOwner pCrv1( pSurfBz->GetSingleEdge3D( false, 2)) ; - PtrOwner pCrv2( pSurfBz->GetSingleEdge3D( false, 0)) ; - // inverto la curva corrispondente al bordo 2 della bezier per avere le due guide concordi - pCrv2->Invert() ; - double dParS1 = -1 ; double dParS2 = -1 ; - if ( ! pCrv1->GetParamAtPoint( ptS1, dParS1) || ! pCrv1->GetParamAtPoint( ptS2, dParS2)) - return nullptr ; - int nUS1 = int ( dParS1) * nDegU ; - int nUS2 = int ( dParS2) * nDegU ; - bool bInverted = false ; - if ( nUS1 > nUS2) { - swap( nUS1, nUS2) ; - swap( dParS1, dParS2) ; - swap( ptS1, ptS2) ; - swap( vtDir1, vtDir2) ; - bInverted = true ; - } - PtrOwner pCrvOrig1( pCrv1->CopyParamRange( dParS1, dParS2)) ; - PtrOwner pCrvOrig2( pCrv2->CopyParamRange( dParS1, dParS2)) ; - - ///// versione con correzioni a mano - Point3d ptPrevS = ptS1 ; - Point3d ptPrevE = ! bInverted ? bpIsoStart.second : bpIsoEnd.second ; - Vector3d vtIsoPrev = ptPrevE - ptPrevS ; vtIsoPrev.Normalize() ; - Point3d ptBez ; Vector3d vtNPrev ; - pSurfBz->GetPointNrmD1D2( dParS1, 0.5, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez, vtNPrev) ; - int nPoints = ( nUS2 - nUS1) * nDegU + 1 ; - PNTVECTOR vPnt0 ; vPnt0.reserve( nPoints) ; vPnt0.push_back( ptPrevS) ; - PNTVECTOR vPnt1 ; vPnt1.reserve( nPoints) ; vPnt1.push_back( ptPrevE) ; - // salvo il secondo punto di controllo della patch - bool bOk = false ; - Point3d ptSecond1Curr = pSurfBz->GetControlPoint( nUS1 + 1, 0, &bOk) ; - vPnt0.push_back( ptSecond1Curr) ; - Point3d ptSecond2Curr = pSurfBz->GetControlPoint( nUS1 + 1, 1, &bOk) ; - vPnt1.push_back( ptSecond2Curr) ; - // scorro le isocurve di separazione tra patch - for ( int i = nUS1 + 3 ; i < nUS2 ; i +=3) { - // recupero precedente e successivo - Point3d ptThird1Prev = pSurfBz->GetControlPoint( i - 1, 0, &bOk) ; - Point3d ptThird2Prev = pSurfBz->GetControlPoint( i - 1, 1, &bOk) ; - Point3d ptSecond1Next = pSurfBz->GetControlPoint( i + 1, 0, &bOk) ; - Point3d ptSecond2Next = pSurfBz->GetControlPoint( i + 1, 1, &bOk) ; - // recupero corrente e verifico la torsione - Point3d ptCurr1 = pSurfBz->GetControlPoint( i, 0, &bOk) ; - Point3d ptCurr2 = pSurfBz->GetControlPoint( i, 1, &bOk) ; - Vector3d vtIsoCurr = ptCurr2 - ptCurr1 ; - double dDist = vtIsoCurr.Len() ; - vtIsoCurr.Normalize() ; - Vector3d vtDirPrev = vtIsoPrev ^ vtNPrev ; - Vector3d vtCurrInPlane = OrthoCompo( vtIsoCurr, vtDirPrev) ; - bool bDet = false ; - double dAng = 0 ; vtIsoPrev.GetRotation( vtCurrInPlane, vtDirPrev, dAng, bDet) ; - double dSinAngTol = sin( 5 * DEGTORAD) ; - Vector3d vtPrev1 = ptCurr1 - ptThird1Prev ; vtPrev1.Normalize() ; - Vector3d vtNext1 = ptSecond1Next - ptCurr1 ; vtNext1.Normalize() ; - bool bAngularPoint1 = ! AreSameVectorEpsilon( vtPrev1, vtNext1, dSinAngTol) ; - Vector3d vtPrev2 = ptCurr2 - ptThird2Prev ; vtPrev2.Normalize() ; - Vector3d vtNext2 = ptSecond2Next - ptCurr2 ; vtNext2.Normalize() ; - bool bAngularPoint2 = ! AreSameVectorEpsilon( vtPrev2, vtNext2, dSinAngTol) ; - if ( abs( dAng) > 0) { - // se l'isocurva di separazione dalla patch successiva è torta rispetto alla precedente - // allora prendo il penultimo punto della curva precedente, il punto di joint e il secondo della prossima e li sposto lungo la normale della superficie - dDist *= dAng * DEGTORAD / 2 ; - if ( ! bAngularPoint1) { - // se non ho un punto angoloso muovo tutto il terzetto insieme - ptThird1Prev += vtNPrev * dDist ; - ptSecond1Next += vtNPrev * dDist ; - ptCurr1 += vtNPrev * dDist ; - } - else { - // altrimenti sposto solo il punto corrente verso la congiungente tra il precedente e il successivo - DistPointLine dpl( ptCurr1, ptThird1Prev, ptSecond1Next, true) ; - Point3d ptMinDist ; dpl.GetMinDistPoint( ptMinDist) ; - Vector3d vtCorrDir = ptMinDist - ptCurr1 ; vtCorrDir.Normalize() ; - double dProjDir = vtNPrev * vtCorrDir ; - if ( dProjDir < 0) - LOG_ERROR( GetEGkLogger(), "Error : regolarizing crv0 near an angular point") ; - double dDistCorr = min( dDist, Dist( ptMinDist, ptCurr1)) ; - ptCurr1 += vtCorrDir * dDistCorr ; - } - if ( ! bAngularPoint2) { - ptThird2Prev -= vtNPrev * dDist ; - ptSecond2Next -= vtNPrev * dDist ; - ptCurr2 -= vtNPrev * dDist ; - } - else { - // altrimenti sposto solo il punto corrente verso la congiungente tra il precedente e il successivo - DistPointLine dpl( ptCurr2, ptThird2Prev, ptSecond2Next, true) ; - Point3d ptMinDist ; dpl.GetMinDistPoint( ptMinDist) ; - Vector3d vtCorrDir = ptMinDist - ptCurr2 ; vtCorrDir.Normalize() ; - double dProjDir = vtNPrev * vtCorrDir ; - if ( dProjDir < 0) - LOG_ERROR( GetEGkLogger(), "Error : regolarizing crv1 near an angular point") ; - double dDistCorr = min( dDist, Dist( ptMinDist, ptCurr2)) ; - ptCurr2 -= vtCorrDir * dDistCorr ; - } - } - vPnt0.push_back( ptThird1Prev) ; - vPnt0.push_back( ptCurr1) ; - vPnt0.push_back( ptSecond1Next) ; - - vPnt1.push_back( ptThird2Prev) ; - vPnt1.push_back( ptCurr2) ; - vPnt1.push_back( ptSecond2Next) ; - - vtIsoPrev = ptCurr2 - ptCurr1 ; vtIsoPrev.Normalize() ; - vtNPrev = ( ptSecond1Next - ptCurr1) ^ vtIsoPrev ; vtNPrev.Normalize() ; - } - // aggiungo gli ultimi due punti - Point3d ptThird1Prev = pSurfBz->GetControlPoint( nUS2 - 1, 0, &bOk) ; - vPnt0.push_back( ptThird1Prev) ; - Point3d ptFourth1Curr = pSurfBz->GetControlPoint( nUS2, 0, &bOk) ; - vPnt0.push_back( ptFourth1Curr) ; - Point3d ptThird2Prev = pSurfBz->GetControlPoint( nUS2 - 1, 1, &bOk) ; - vPnt1.push_back( ptThird2Prev) ; - Point3d ptFourth2Curr = pSurfBz->GetControlPoint( nUS2, 1, &bOk) ; - vPnt1.push_back( ptFourth2Curr) ; - - PtrOwner pCC1( CreateCurveComposite()) ; - PtrOwner pCC2( CreateCurveComposite()) ; - for ( int i = 0 ; i < ssize( vPnt0) - 3 ; i+=3) { - PtrOwner cb1( CreateCurveBezier()) ; cb1->Init( 3, false) ; - cb1->SetControlPoint( 0, vPnt0[i]) ; - cb1->SetControlPoint( 1, vPnt0[i+1]) ; - cb1->SetControlPoint( 2, vPnt0[i+2]) ; - cb1->SetControlPoint( 3, vPnt0[i+3]) ; - pCC1->AddCurve( Release( cb1)) ; - - PtrOwner cb2( CreateCurveBezier()) ; cb2->Init( 3, false) ; - cb2->SetControlPoint( 0, vPnt1[i]) ; - cb2->SetControlPoint( 1, vPnt1[i+1]) ; - cb2->SetControlPoint( 2, vPnt1[i+2]) ; - cb2->SetControlPoint( 3, vPnt1[i+3]) ; - pCC2->AddCurve( Release( cb2)) ; - } - - ////// N.B.:dovrei tener conto anche della patch PRECEDENTE e SUCCESSIVA a quelle indicate, altrimenti non vedo se ho creato flessi al bordo della zona -#if DEBUG_SMOOTH_CURVATURE - VT.push_back( pCC1->Clone()) ; - VT.push_back( pCC2->Clone()) ; - SaveGeoObj( VT, "C:\\Temp\\bezier\\ruled\\smoothness\\regolarized_first_step.nge") ; -#endif - - // ora verifico l'eventuale presenza di cambi di concavità non desiderati - // se ne trovo su una curva e non sull'altra allora ruoto il terzetto di punti della curva con flesso in modo - // da matchare la tangente dell'altra curva - PNTINFOVECTOR vPntInfo1, vPntInfo2 ; - FillPntInfo( vPnt0, pCC1, vPntInfo1) ; - FillPntInfo( vPnt1, pCC2, vPntInfo2) ; - - RemoveInflexionPoints( vPnt0, vPntInfo1, vPntInfo2) ; - RemoveInflexionPoints( vPnt1, vPntInfo2, vPntInfo1) ; - - pCC1->Clear() ; - pCC2->Clear() ; - for ( int i = 0 ; i < ssize( vPnt0) - 3 ; i+=3) { - PtrOwner cb1( CreateCurveBezier()) ; cb1->Init( 3, false) ; - cb1->SetControlPoint( 0, vPnt0[i]) ; - cb1->SetControlPoint( 1, vPnt0[i+1]) ; - cb1->SetControlPoint( 2, vPnt0[i+2]) ; - cb1->SetControlPoint( 3, vPnt0[i+3]) ; - pCC1->AddCurve( Release( cb1)) ; - - PtrOwner cb2( CreateCurveBezier()) ; cb2->Init( 3, false) ; - cb2->SetControlPoint( 0, vPnt1[i]) ; - cb2->SetControlPoint( 1, vPnt1[i+1]) ; - cb2->SetControlPoint( 2, vPnt1[i+2]) ; - cb2->SetControlPoint( 3, vPnt1[i+3]) ; - pCC2->AddCurve( Release( cb2)) ; - } - - // controllo di essere rimasto in tolleranza - double dErr = 0 ; - CalcApproxError( pCrvOrig1, pCC1, dErr, 20) ; - if ( dErr > dTol) - return nullptr ; - CalcApproxError( pCrvOrig2, pCC2, dErr, 20) ; - if ( dErr > dTol) - return nullptr ; - - PtrOwner pNewSurf( pSurfBz->Clone()) ; - // aggiorno i punti di controllo della superficie di bezier - for ( int i = 0 ; i < ssize( vPnt0) ; ++i) { - pNewSurf->SetControlPoint( nUS1 + i, 0, vPnt0[i]) ; - pNewSurf->SetControlPoint( nUS1 + i, 1, vPnt1[i]) ; - } - #if DEBUG_SMOOTH_CURVATURE - VT.push_back( Release(pCC1)) ; - VT.push_back( Release(pCC2)) ; - SaveGeoObj( VT, "C:\\Temp\\bezier\\ruled\\smoothness\\regolarized.nge") ; - #endif - - return Release( pNewSurf) ; -} - // Funzione per la regolarizzazione delle curve di bordo di una lavorazione di trim // Le curve vengono modificate entro una data tolleranza, in modo che ISurfBezier* RegolarizeBordersLocallyRMF( const ISurfBezier* pSurfBz, const BIPOINT& bpIsoStart, const BIPOINT& bpIsoEnd, double dTol) { - #if DEBUG_SMOOTH_CURVATURE - VT.clear() ; - #endif +#if DEBUG_SMOOTH_CURVATURE + VT.clear() ; +#endif // prendo per buone le isocurve di inizio e fine tratto e devo identificare tra loro le isocurve che creano troppo twist e che sono da raddrizzare Point3d ptS1 = bpIsoStart.first ; @@ -5322,19 +5108,19 @@ RegolarizeBordersLocallyRMF( const ISurfBezier* pSurfBz, const BIPOINT& bpIsoSta if ( IsNull( pCC1) || ! pCC1->IsValid()) return nullptr ; - #if DEBUG_SMOOTH_CURVATURE - for( int i = 0 ; i < ssize( vPnt1) ; ++i) { - PtrOwner pPT( CreateGeoPoint3d()) ; pPT->Set( vPnt1[i]) ; - VT.push_back( Release( pPT)) ; - } - for( int i = 0 ; i < ssize( vPnt0) ; ++i) { - PtrOwner pPT( CreateGeoPoint3d()) ; pPT->Set( vPnt0[i]) ; - VT.push_back( Release( pPT)) ; - } - VT.push_back( pCC1->Clone()) ; - VT.push_back( pCC2->Clone()) ; - SaveGeoObj( VT, "C:\\Temp\\bezier\\ruled\\smoothness\\regolarized_RMF.nge") ; - #endif +#if DEBUG_SMOOTH_CURVATURE + for( int i = 0 ; i < ssize( vPnt1) ; ++i) { + PtrOwner pPT( CreateGeoPoint3d()) ; pPT->Set( vPnt1[i]) ; + VT.push_back( Release( pPT)) ; + } + for( int i = 0 ; i < ssize( vPnt0) ; ++i) { + PtrOwner pPT( CreateGeoPoint3d()) ; pPT->Set( vPnt0[i]) ; + VT.push_back( Release( pPT)) ; + } + VT.push_back( pCC1->Clone()) ; + VT.push_back( pCC2->Clone()) ; + SaveGeoObj( VT, "C:\\Temp\\bezier\\ruled\\smoothness\\regolarized_RMF.nge") ; +#endif // controllo di essere rimasto in tolleranza double dErr = 0 ; @@ -5347,4 +5133,229 @@ RegolarizeBordersLocallyRMF( const ISurfBezier* pSurfBz, const BIPOINT& bpIsoSta return nullptr ; return nullptr ; +} + +//------------------------------------------------------------------------------ +// Funzione per la regolarizzazione delle curve di bordo di una lavorazione di trim +// Le curve vengono modificate entro una data tolleranza, in modo che +ISurfBezier* +RegolarizeBordersLocally( const ISurfBezier* pSurfBz, const BIPOINT& bpIsoStart, const BIPOINT& bpIsoEnd, double dTol, int nType) +{ + if ( nType == RegolarizeType::RMF) + return RegolarizeBordersLocallyRMF( pSurfBz, bpIsoStart, bpIsoEnd, dTol) ; + + #if DEBUG_SMOOTH_CURVATURE + VT.clear() ; + #endif + + // prendo per buone le isocurve di inizio e fine tratto e devo identificare tra loro le isocurve che creano troppo twist e che sono da raddrizzare + Point3d ptS1 = bpIsoStart.first ; + Point3d ptS2 = bpIsoEnd.first ; + Vector3d vtDir1 = bpIsoStart.second - ptS1 ; + Vector3d vtDir2 = bpIsoEnd.second - ptS2 ; + //double dInterpolateAngTol = 4 ; + //double dAngInterp = 0 ; + //vtDir1.GetAngle( vtDir2, dAngInterp) ; + //bool bInterpolate = dAngInterp > dInterpolateAngTol ; + + int nDegU, nDegV, nSpanU, nSpanV ; + bool bRat, bTrimmed ; + pSurfBz->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bRat, bTrimmed) ; + if ( nDegU != 3) + return nullptr ; + // individuo quali isocurve sono state indicate come inizio e fine + PtrOwner pCrv1( pSurfBz->GetSingleEdge3D( false, 2)) ; + PtrOwner pCrv2( pSurfBz->GetSingleEdge3D( false, 0)) ; + // inverto la curva corrispondente al bordo 2 della bezier per avere le due guide concordi + pCrv2->Invert() ; + double dParS1 = -1 ; double dParS2 = -1 ; + if ( ! pCrv1->GetParamAtPoint( ptS1, dParS1) || ! pCrv1->GetParamAtPoint( ptS2, dParS2)) + return nullptr ; + int nUS1 = int ( dParS1) * nDegU ; + int nUS2 = int ( dParS2) * nDegU ; + bool bInverted = false ; + if ( nUS1 > nUS2) { + swap( nUS1, nUS2) ; + swap( dParS1, dParS2) ; + swap( ptS1, ptS2) ; + swap( vtDir1, vtDir2) ; + bInverted = true ; + } + PtrOwner pCrvOrig1( pCrv1->CopyParamRange( dParS1, dParS2)) ; + PtrOwner pCrvOrig2( pCrv2->CopyParamRange( dParS1, dParS2)) ; + double dLen = 0 ; pCrvOrig1->GetLength( dLen) ; + + ///// versione con correzioni a mano + Point3d ptPrevS = ptS1 ; + Point3d ptPrevE = ! bInverted ? bpIsoStart.second : bpIsoEnd.second ; + Vector3d vtIsoPrev = ptPrevE - ptPrevS ; vtIsoPrev.Normalize() ; + Point3d ptBez ; Vector3d vtNPrev ; + pSurfBz->GetPointNrmD1D2( dParS1, 0.5, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez, vtNPrev) ; + int nPoints = ( nUS2 - nUS1) * nDegU + 1 ; + PNTVECTOR vPnt0 ; vPnt0.reserve( nPoints) ; vPnt0.push_back( ptPrevS) ; + PNTVECTOR vPnt1 ; vPnt1.reserve( nPoints) ; vPnt1.push_back( ptPrevE) ; + // salvo il secondo punto di controllo della patch + bool bOk = false ; + Point3d ptSecond1Curr = pSurfBz->GetControlPoint( nUS1 + 1, 0, &bOk) ; + vPnt0.push_back( ptSecond1Curr) ; + Point3d ptSecond2Curr = pSurfBz->GetControlPoint( nUS1 + 1, 1, &bOk) ; + vPnt1.push_back( ptSecond2Curr) ; + // scorro le isocurve di separazione tra patch + for ( int i = nUS1 + 3 ; i < nUS2 ; i +=3) { + // recupero precedente e successivo + Point3d ptThird1Prev = pSurfBz->GetControlPoint( i - 1, 0, &bOk) ; + Point3d ptThird2Prev = pSurfBz->GetControlPoint( i - 1, 1, &bOk) ; + Point3d ptSecond1Next = pSurfBz->GetControlPoint( i + 1, 0, &bOk) ; + Point3d ptSecond2Next = pSurfBz->GetControlPoint( i + 1, 1, &bOk) ; + // recupero corrente e verifico la torsione + Point3d ptCurr1 = pSurfBz->GetControlPoint( i, 0, &bOk) ; + Point3d ptCurr2 = pSurfBz->GetControlPoint( i, 1, &bOk) ; + Vector3d vtIsoCurr = ptCurr2 - ptCurr1 ; + double dDist = vtIsoCurr.Len() ; + vtIsoCurr.Normalize() ; + Vector3d vtDirPrev = vtIsoPrev ^ vtNPrev ; + bool bDet = false ; + double dAng = 0 ; vtIsoCurr.GetRotation( vtIsoPrev, vtDirPrev, dAng, bDet) ; + double dSinAngTol = sin( 5 * DEGTORAD) ; + Vector3d vtPrev1 = ptCurr1 - ptThird1Prev ; vtPrev1.Normalize() ; + Vector3d vtNext1 = ptSecond1Next - ptCurr1 ; vtNext1.Normalize() ; + bool bAngularPoint1 = ! AreSameVectorEpsilon( vtPrev1, vtNext1, dSinAngTol) ; + Vector3d vtPrev2 = ptCurr2 - ptThird2Prev ; vtPrev2.Normalize() ; + Vector3d vtNext2 = ptSecond2Next - ptCurr2 ; vtNext2.Normalize() ; + bool bAngularPoint2 = ! AreSameVectorEpsilon( vtPrev2, vtNext2, dSinAngTol) ; + if ( abs( dAng) > 0) { + // se l'isocurva di separazione dalla patch successiva è torta rispetto alla precedente + // allora prendo il penultimo punto della curva precedente, il punto di joint e il secondo della prossima e li sposto lungo la normale della superficie + dDist *= dAng * DEGTORAD / 2 ; + if ( ! bAngularPoint1) { + // se non ho un punto angoloso muovo tutto il terzetto insieme + ptThird1Prev -= vtNPrev * dDist ; + ptSecond1Next -= vtNPrev * dDist ; + ptCurr1 -= vtNPrev * dDist ; + } + else { + // altrimenti sposto solo il punto corrente verso la congiungente tra il precedente e il successivo + DistPointLine dpl( ptCurr1, ptThird1Prev, ptSecond1Next, true) ; + Point3d ptMinDist ; dpl.GetMinDistPoint( ptMinDist) ; + Vector3d vtCorrDir = ptMinDist - ptCurr1 ; vtCorrDir.Normalize() ; + double dProjDir = vtNPrev * vtCorrDir ; + if ( dProjDir < 0) + LOG_ERROR( GetEGkLogger(), "Error : regolarizing crv0 near an angular point") ; + double dDistCorr = min( dDist, Dist( ptMinDist, ptCurr1)) ; + ptCurr1 -= vtCorrDir * dDistCorr ; + } + if ( ! bAngularPoint2) { + ptThird2Prev += vtNPrev * dDist ; + ptSecond2Next += vtNPrev * dDist ; + ptCurr2 += vtNPrev * dDist ; + } + else { + // altrimenti sposto solo il punto corrente verso la congiungente tra il precedente e il successivo + DistPointLine dpl( ptCurr2, ptThird2Prev, ptSecond2Next, true) ; + Point3d ptMinDist ; dpl.GetMinDistPoint( ptMinDist) ; + Vector3d vtCorrDir = ptMinDist - ptCurr2 ; vtCorrDir.Normalize() ; + double dProjDir = vtNPrev * vtCorrDir ; + if ( dProjDir < 0) + LOG_ERROR( GetEGkLogger(), "Error : regolarizing crv1 near an angular point") ; + double dDistCorr = min( dDist, Dist( ptMinDist, ptCurr2)) ; + ptCurr2 += vtCorrDir * dDistCorr ; + } + } + vPnt0.push_back( ptThird1Prev) ; + vPnt0.push_back( ptCurr1) ; + vPnt0.push_back( ptSecond1Next) ; + + vPnt1.push_back( ptThird2Prev) ; + vPnt1.push_back( ptCurr2) ; + vPnt1.push_back( ptSecond2Next) ; + + vtIsoPrev = ptCurr2 - ptCurr1 ; vtIsoPrev.Normalize() ; + vtNPrev = ( ptSecond1Next - ptCurr1) ^ vtIsoPrev ; vtNPrev.Normalize() ; + } + // aggiungo gli ultimi due punti + Point3d ptThird1Prev = pSurfBz->GetControlPoint( nUS2 - 1, 0, &bOk) ; + vPnt0.push_back( ptThird1Prev) ; + Point3d ptFourth1Curr = pSurfBz->GetControlPoint( nUS2, 0, &bOk) ; + vPnt0.push_back( ptFourth1Curr) ; + Point3d ptThird2Prev = pSurfBz->GetControlPoint( nUS2 - 1, 1, &bOk) ; + vPnt1.push_back( ptThird2Prev) ; + Point3d ptFourth2Curr = pSurfBz->GetControlPoint( nUS2, 1, &bOk) ; + vPnt1.push_back( ptFourth2Curr) ; + + PtrOwner pCC1( CreateCurveComposite()) ; + PtrOwner pCC2( CreateCurveComposite()) ; + for ( int i = 0 ; i < ssize( vPnt0) - 3 ; i+=3) { + PtrOwner cb1( CreateCurveBezier()) ; cb1->Init( 3, false) ; + cb1->SetControlPoint( 0, vPnt0[i]) ; + cb1->SetControlPoint( 1, vPnt0[i+1]) ; + cb1->SetControlPoint( 2, vPnt0[i+2]) ; + cb1->SetControlPoint( 3, vPnt0[i+3]) ; + pCC1->AddCurve( Release( cb1)) ; + + PtrOwner cb2( CreateCurveBezier()) ; cb2->Init( 3, false) ; + cb2->SetControlPoint( 0, vPnt1[i]) ; + cb2->SetControlPoint( 1, vPnt1[i+1]) ; + cb2->SetControlPoint( 2, vPnt1[i+2]) ; + cb2->SetControlPoint( 3, vPnt1[i+3]) ; + pCC2->AddCurve( Release( cb2)) ; + } + + ////// N.B.:dovrei tener conto anche della patch PRECEDENTE e SUCCESSIVA a quelle indicate, altrimenti non vedo se ho creato flessi al bordo della zona +#if DEBUG_SMOOTH_CURVATURE + VT.push_back( pCC1->Clone()) ; + VT.push_back( pCC2->Clone()) ; + SaveGeoObj( VT, "C:\\Temp\\bezier\\ruled\\smoothness\\regolarized_first_step.nge") ; +#endif + + // ora verifico l'eventuale presenza di cambi di concavità non desiderati + // se ne trovo su una curva e non sull'altra allora ruoto il terzetto di punti della curva con flesso in modo + // da matchare la tangente dell'altra curva + PNTINFOVECTOR vPntInfo1, vPntInfo2 ; + FillPntInfo( vPnt0, pCC1, vPntInfo1) ; + FillPntInfo( vPnt1, pCC2, vPntInfo2) ; + + RemoveInflexionPoints( vPnt0, vPntInfo1, vPntInfo2) ; + RemoveInflexionPoints( vPnt1, vPntInfo2, vPntInfo1) ; + + pCC1->Clear() ; + pCC2->Clear() ; + for ( int i = 0 ; i < ssize( vPnt0) - 3 ; i+=3) { + PtrOwner cb1( CreateCurveBezier()) ; cb1->Init( 3, false) ; + cb1->SetControlPoint( 0, vPnt0[i]) ; + cb1->SetControlPoint( 1, vPnt0[i+1]) ; + cb1->SetControlPoint( 2, vPnt0[i+2]) ; + cb1->SetControlPoint( 3, vPnt0[i+3]) ; + pCC1->AddCurve( Release( cb1)) ; + + PtrOwner cb2( CreateCurveBezier()) ; cb2->Init( 3, false) ; + cb2->SetControlPoint( 0, vPnt1[i]) ; + cb2->SetControlPoint( 1, vPnt1[i+1]) ; + cb2->SetControlPoint( 2, vPnt1[i+2]) ; + cb2->SetControlPoint( 3, vPnt1[i+3]) ; + pCC2->AddCurve( Release( cb2)) ; + } + + // controllo di essere rimasto in tolleranza + double dErr = 0 ; + CalcApproxError( pCrvOrig1, pCC1, dErr, 20) ; + if ( dErr > dTol) + return nullptr ; + CalcApproxError( pCrvOrig2, pCC2, dErr, 20) ; + if ( dErr > dTol) + return nullptr ; + + PtrOwner pNewSurf( pSurfBz->Clone()) ; + // aggiorno i punti di controllo della superficie di bezier + for ( int i = 0 ; i < ssize( vPnt0) ; ++i) { + pNewSurf->SetControlPoint( nUS1 + i, 0, vPnt0[i]) ; + pNewSurf->SetControlPoint( nUS1 + i, 1, vPnt1[i]) ; + } + #if DEBUG_SMOOTH_CURVATURE + VT.clear() ; + VT.push_back( Release(pCC1)) ; + VT.push_back( Release(pCC2)) ; + SaveGeoObj( VT, "C:\\Temp\\bezier\\ruled\\smoothness\\regolarized.nge") ; + #endif + + return Release( pNewSurf) ; } \ No newline at end of file