EgtGeomKernel :

- migliorie e correzioni a RuledSmooth.
This commit is contained in:
Daniele Bariletti
2026-05-26 11:27:27 +02:00
parent 02742ee80f
commit 979597084d
2 changed files with 115 additions and 156 deletions
+60 -19
View File
@@ -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 ;
}