Merge branch 'master' into MoreBezier

This commit is contained in:
Daniele Bariletti
2024-09-04 15:56:45 +02:00
2 changed files with 68 additions and 53 deletions
+16 -10
View File
@@ -895,7 +895,8 @@ ApproxBezierWithCubics(const ICurveBezier* pCrvBezier, double dTol)
PtrOwner<ICurveComposite> pCC( CreateBasicCurveComposite()) ;
// approssimo l'ultimo tratto
while ( dErr > dTol) {
int nCount = 0 ;
while ( dErr > dTol && nCount < 100) {
PtrOwner<ICurveBezier> pCrvPart( pCrvBezier->Clone()) ;
pCrvPart->TrimStartEndAtParam( double( nParts - 1) / nParts, 1) ;
PtrOwner<ICurveBezier> pCrvCubic ;
@@ -920,18 +921,23 @@ ApproxBezierWithCubics(const ICurveBezier* pCrvBezier, double dTol)
if( bOneIsEnough)
break ;
}
++ nCount ;
}
// approssimo annche tutti gli altri tratti con una cubica
for ( int i = nParts - 1 ; i > 0 ; --i) {
PtrOwner<ICurveBezier> pCrvPart( pCrvBezier->Clone()) ;
pCrvPart->TrimStartEndAtParam( double( i - 1) / nParts, double(i) / nParts) ;
PtrOwner<ICurveBezier> pCrvCubic( ApproxCurveBezierWithSingleCubic( pCrvPart)) ;
if ( ! pCC->AddCurve( Release( pCrvCubic), false))
return nullptr ;
}
if( nCount < 100) {
// approssimo annche tutti gli altri tratti con una cubica
for ( int i = nParts - 1 ; i > 0 ; --i) {
PtrOwner<ICurveBezier> pCrvPart( pCrvBezier->Clone()) ;
pCrvPart->TrimStartEndAtParam( double( i - 1) / nParts, double(i) / nParts) ;
PtrOwner<ICurveBezier> pCrvCubic( ApproxCurveBezierWithSingleCubic( pCrvPart)) ;
if ( ! pCC->AddCurve( Release( pCrvCubic), false))
return nullptr ;
}
return Release( pCC) ;
return Release( pCC) ;
}
else
return nullptr ;
}
//----------------------------------------------------------------------------
+52 -43
View File
@@ -2297,12 +2297,16 @@ CurveBezier::MakeNonRational( double dTol)
return true ;
// controllo se i pesi sono tutti == 1 allora è una finta razionale e mi basta fare una copia dei punti di controllo
bool bIsActualRat = true ;
for ( int i = 0 ; i < m_nDeg && bIsActualRat ; ++i)
bIsActualRat = bIsActualRat && abs(m_vWeCtrl[i] - 1) > EPS_SMALL ;
bool bIsActualRat = false ;
for ( int i = 0 ; i < m_nDeg ; ++i) {
if ( abs(m_vWeCtrl[i] - 1) > EPS_SMALL) {
bIsActualRat = true ;
break ;
}
}
bool bOk = true ;
if ( ! bIsActualRat ) {
if ( ! bIsActualRat) {
PtrOwner<CurveBezier> pNewBez( CreateBasicCurveBezier()) ;
for ( int p = 0 ; p < m_nDeg ; ++p) {
Point3d pt = GetControlPoint( p) ;
@@ -2311,49 +2315,54 @@ CurveBezier::MakeNonRational( double dTol)
}
else {
// provo ad approssimare la curva di bezier con una controparte non razionale
PtrOwner<CurveBezier> pNewBez( CreateBasicCurveBezier()) ;
int nDeg = m_nDeg + 2 ;
pNewBez->Init( nDeg, false) ;
PNTVECTOR vPntCtrl ;
PNTVECTOR vPntSampling ;
for ( int p = 0 ; p < nDeg + 1; ++p) {
Point3d pt ; GetPointD1D2( double(p) / nDeg, pt) ;
pNewBez->SetControlPoint( p, pt) ;
vPntCtrl.push_back( pt) ;
}
vPntSampling = vPntCtrl ;
int c = 0 ;
double dErr = INFINITO ;
while ( dErr > dTol && c < 100) {
double dErrMax = 0 ;
// calcolo le differenze tra i punti di sampling sulla nuova curva e quelli sulla curva originale
int nDeg = m_nDeg ;
// punto di rientro in caso fallisca il primo tentativo
retry :
nDeg += 2 ;
PtrOwner<CurveBezier> pNewBez( CreateBasicCurveBezier()) ;
pNewBez->Init( nDeg, false) ;
PNTVECTOR vPntCtrl ;
PNTVECTOR vPntSampling ;
for ( int p = 0 ; p < nDeg + 1; ++p) {
Point3d pt ; pNewBez->GetPointD1D2( double(p) / nDeg, pt) ;
Vector3d vDiff = vPntSampling[p] - pt ;
double dErrLoc = vDiff.Len() ;
if( dErrLoc > dErrMax)
dErrMax = dErrLoc ;
// aggiorno il vettore dei punti di controllo della nuova curva
vPntCtrl[p] += vDiff ;
Point3d pt ; GetPointD1D2( double(p) / nDeg, pt) ;
pNewBez->SetControlPoint( p, pt) ;
vPntCtrl.push_back( pt) ;
}
vPntSampling = vPntCtrl ;
int c = 0 ;
double dErr = INFINITO ;
while ( dErr > dTol && c < 100) {
double dErrMax = 0 ;
// calcolo le differenze tra i punti di sampling sulla nuova curva e quelli sulla curva originale
for ( int p = 0 ; p < nDeg + 1; ++p) {
Point3d pt ; pNewBez->GetPointD1D2( double(p) / nDeg, pt) ;
Vector3d vDiff = vPntSampling[p] - pt ;
double dErrLoc = vDiff.Len() ;
if( dErrLoc > dErrMax)
dErrMax = dErrLoc ;
// aggiorno il vettore dei punti di controllo della nuova curva
vPntCtrl[p] += vDiff ;
}
dErr = dErrMax ;
// aggiorno i punti di controllo della nuova curva
for ( int i = 0 ; i < nDeg + 1 ; ++i)
pNewBez->SetControlPoint( i, vPntCtrl[i]) ;
++c ;
}
dErr = dErrMax ;
// aggiorno i punti di controllo della nuova curva
for ( int i = 0 ; i < nDeg + 1 ; ++i)
pNewBez->SetControlPoint( i, vPntCtrl[i]) ;
++c ;
}
// calcolo l'errore di approssimazione sulla curva
CalcBezierApproxError( this, pNewBez, dErr) ;
bOk = dErr < dTol ;
if( bOk) {
// aggiorno la curva di bezier originale con quella approssimata
Init( nDeg, false) ;
for( int i = 0 ; i < nDeg + 1 ; ++i) {
SetControlPoint( i, pNewBez->GetControlPoint( i)) ;
SetControlWeight( i, pNewBez->GetControlWeight( i)) ;
// calcolo l'errore di approssimazione sulla curva
CalcBezierApproxError( this, pNewBez, dErr) ;
bOk = dErr < dTol ;
if( bOk) {
// aggiorno la curva di bezier originale con quella approssimata
Init( nDeg, false) ;
for( int i = 0 ; i < nDeg + 1 ; ++i) {
SetControlPoint( i, pNewBez->GetControlPoint( i)) ;
SetControlWeight( i, pNewBez->GetControlWeight( i)) ;
}
}
}
else if( nDeg < m_nDeg + 4)
goto retry ;
}
return bOk ;