EgtGeomKernel :

- miglioramenti alla regolarize.
This commit is contained in:
Daniele Bariletti
2026-05-06 12:51:20 +02:00
parent f5059166ed
commit 68a9848748
+263 -252
View File
@@ -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<ICurveComposite> pCrv1( pSurfBz->GetSingleEdge3D( false, 2)) ;
PtrOwner<ICurveComposite> 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<ICurve> pCrvOrig1( pCrv1->CopyParamRange( dParS1, dParS2)) ;
PtrOwner<ICurve> 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<ICurveComposite> pCC1( CreateCurveComposite()) ;
PtrOwner<ICurveComposite> pCC2( CreateCurveComposite()) ;
for ( int i = 0 ; i < ssize( vPnt0) - 3 ; i+=3) {
PtrOwner<ICurveBezier> 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<ICurveBezier> 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<ICurveBezier> 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<ICurveBezier> 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<ISurfBezier> 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<IGeoPoint3d> pPT( CreateGeoPoint3d()) ; pPT->Set( vPnt1[i]) ;
VT.push_back( Release( pPT)) ;
}
for( int i = 0 ; i < ssize( vPnt0) ; ++i) {
PtrOwner<IGeoPoint3d> 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<IGeoPoint3d> pPT( CreateGeoPoint3d()) ; pPT->Set( vPnt1[i]) ;
VT.push_back( Release( pPT)) ;
}
for( int i = 0 ; i < ssize( vPnt0) ; ++i) {
PtrOwner<IGeoPoint3d> 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<ICurveComposite> pCrv1( pSurfBz->GetSingleEdge3D( false, 2)) ;
PtrOwner<ICurveComposite> 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<ICurve> pCrvOrig1( pCrv1->CopyParamRange( dParS1, dParS2)) ;
PtrOwner<ICurve> 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<ICurveComposite> pCC1( CreateCurveComposite()) ;
PtrOwner<ICurveComposite> pCC2( CreateCurveComposite()) ;
for ( int i = 0 ; i < ssize( vPnt0) - 3 ; i+=3) {
PtrOwner<ICurveBezier> 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<ICurveBezier> 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<ICurveBezier> 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<ICurveBezier> 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<ISurfBezier> 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) ;
}