EgtGeomKernel :

- correzioni e migliorie a regolarize dei bordi per trimming.
This commit is contained in:
Daniele Bariletti
2026-04-21 15:04:24 +02:00
parent ae2cac48d1
commit e7d25b2d0e
4 changed files with 80 additions and 92 deletions
+2 -2
View File
@@ -735,7 +735,7 @@ GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, dou
//-------------------------------------------------------------------------------
ISurfBezier*
GetSurfBezierRuledSmooth( const ICurve* pCurve1, const ICurve* pCurve2, double dSampleLen)
GetSurfBezierRuledSmooth( const ICurve* pCurve1, const ICurve* pCurve2, BIPNTVECTOR& vSyncLines, double dSampleLen)
{
// verifica parametri
if ( pCurve1 == nullptr || pCurve2 == nullptr)
@@ -762,7 +762,7 @@ GetSurfBezierRuledSmooth( const ICurve* pCurve1, const ICurve* pCurve2, double d
// creo e setto la superficie trimesh
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
if ( IsNull( pSbz) || ! pSbz->CreateSmoothRuledByTwoCurves( pCC1, pCC2, dSampleLen))
if ( IsNull( pSbz) || ! pSbz->CreateSmoothRuledByTwoCurves( pCC1, pCC2, dSampleLen, vSyncLines))
return nullptr ;
// restituisco la superficie
+14 -2
View File
@@ -6429,6 +6429,14 @@ ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp
//----------------------------------------------------------------------------
bool
SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, double dSampleLen)
{
BIPNTVECTOR vSyncLines ;
return CreateSmoothRuledByTwoCurves( pCurve0, pCurve1, dSampleLen, vSyncLines) ;
}
//----------------------------------------------------------------------------
bool
SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, double dSampleLen, BIPNTVECTOR& vSyncLines)
{
// converto in bezier le curve iniziali
PtrOwner<ICurve> pCrvEdge1( CurveToBezierCurve( pCurve0, 3, false)) ;
@@ -6444,7 +6452,6 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
// Verifico che la distanza di campionamento sia ammissibile
double dSampleDist = Clamp( dSampleLen, 2., 30.) ; // 20.0 sembra un passo di campionamento ideale
// Recupero parametri iniziali
double dLen1 ; pCrvEdge1->GetLength( dLen1) ;
double dLen2 ; pCrvEdge2->GetLength( dLen2) ;
@@ -6457,7 +6464,6 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
Point3d ptPrev1, ptCurr1 ; pCrvEdge1->GetStartPoint( ptPrev1) ;
Point3d ptPrev2, ptCurr2 ; pCrvEdge2->GetStartPoint( ptPrev2) ;
Vector3d vtCurr1 = V_NULL, vtCurr2 = V_NULL ;
BIPNTVECTOR vSyncLines ;
while ( dLenPrev1 + dSampleDist < dLen1 - EPS_ZERO) {
// Recupero dU, Point3d e dLen corrente sul primo bordo, per un incremento del passo di campionamento
dLenCurr1 = Clamp( dLenPrev1 + dSampleDist, 0., dLen1) ;
@@ -6585,6 +6591,7 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
vGeo.push_back( Release( pLine)) ;
vCol.push_back( LIME) ;
#endif
vSyncLines.emplace_back( ptCurr1, ptCurr2) ;
// --- 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)...
@@ -6634,6 +6641,9 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
SyncLinePrev = SyncLineNext ;
}
}
// aggiungo le nuove curve ( non importa che siano in ordine di parametro)
vSyncLines.insert( vSyncLines.end(), vEdgeSyncLines.begin(), vEdgeSyncLines.end()) ;
vSyncLines.insert( vSyncLines.end(), vTwistSyncLines.begin(), vTwistSyncLines.end()) ;
#if SAVEPACEDISO
for ( int i = 0 ; i < ssize( vTwistSyncLines) ; ++ i) {
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ; pLine->Set( vTwistSyncLines[i].first, vTwistSyncLines[i].second) ;
@@ -6651,6 +6661,8 @@ 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) ;
}
+1
View File
@@ -155,6 +155,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
bool SwapParameters( void) ;
bool LimitSurfToTrimmedRegion( void) override ;
bool CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, double dSampleLen) override ;
bool CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, double dSampleLen, BIPNTVECTOR& vSyncLines) override ;
public : // IGeoObjRW
int GetNgeId( void) const override ;
+63 -88
View File
@@ -284,58 +284,6 @@ GetPointSetByAngTol( const PolyLine& PL, double dAngTol, POLYLINEVECTOR& vPL)
return true ;
}
//-----------------------------------------------------------------------------
// Funzione per spezzare una curva compo in diversi tratti in corrispondenza
// di cambi di direzione maggiori della tolleranza angolare passata
static bool
SplitCurveCompoByAngTol( const ICurveComposite* pCC, double dAngTol, ICRVCOMPOPOVECTOR& vCC)
{
int nCurves = pCC->GetCurveCount() ;
vCC.emplace_back( CreateCurveComposite()) ;
vCC.back()->AddCurve( pCC->GetCurve(0)->Clone()) ;
// Cos della tolleranza angolare massima
double dCosTol = cos( dAngTol * DEGTORAD) ;
for ( int nC = 0 ; nC < nCurves - 2; ++ nC) {
// Recupero l'angolo tra la fine della curva corrente e l'inizio della successiva
const ICurve* pCrvCurr = pCC->GetCurve( nC) ;
const ICurve* pCrvNext = pCC->GetCurve( nC + 1) ;
Vector3d vtCurrEnd ; pCrvCurr->GetEndDir( vtCurrEnd) ;
Vector3d vtNextStart ; pCrvNext->GetStartDir( vtNextStart) ;
// Calcolo il Coseno tra i due versori
double dCos = vtCurrEnd * vtNextStart ;
// Se dentro alla tolleranza, allora i punti apparterranno alla stessa curva
if ( dCos > dCosTol) {
// Aggiungo la curva
vCC.back()->AddCurve( pCrvNext->Clone()) ;
}
// Se tratto al di fuori della tolleranza, devo definire una nuova curva
else {
vCC.emplace_back( CreateCurveComposite()) ;
vCC.back()->AddCurve( pCrvNext->Clone()) ;
}
}
// Se curva originale chiusa
if ( pCC->IsClosed() && ssize( vCC) > 1) {
// Se ho più tratti, potrei riunire il primo con l'ultimo
const ICurve* pCrvFirst = pCC->GetCurve( 0) ;
const ICurve* pCrvLast = pCC->GetCurve( nCurves - 1) ;
Vector3d vtFirstStart ; pCrvFirst->GetEndDir( vtFirstStart) ;
Vector3d vtLastEnd ; pCrvLast->GetStartDir( vtLastEnd) ;
// Calcolo il Coseno tra i due versori
double dCos = vtFirstStart * vtLastEnd ;
// Se dentro alla tolleranza, allora i punti appartengono alla stessa curva
if ( dCos > dCosTol) {
// Aggiungo la curva
vCC.back()->AddCurve( Release( vCC.front())) ;
vCC.erase( vCC.begin()) ;
}
}
return true ;
}
////-----------------------------------------------------------------------------
//// Funzione che approssima la curva di bordo per la costruzione della Bezier Ruled mediante
//// Patches di curve di Bezier
@@ -3959,26 +3907,26 @@ GetTrimmingSurfBzSyncPoints( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2,
#endif
// Definisco la superficie di Bezier rigata
PtrOwner<SurfBezier> pSBzRuled( GetBasicSurfBezier( GetSurfBezierRuledSmooth( pCompoEdge1, pCompoEdge2, 10))) ;
PtrOwner<SurfBezier> pSBzRuled( GetBasicSurfBezier( GetSurfBezierRuledSmooth( pCompoEdge1, pCompoEdge2, vSyncPoints, 10))) ;
if ( IsNull( pSBzRuled) || ! pSBzRuled->IsValid())
return false ;
// Recupero i punti di sincronizzazione e li restituisco
ICURVEPOVECTOR vCrv ;
pSBzRuled->GetAllPatchesIsocurves( false, vCrv) ;
vSyncPoints.reserve( vCrv.size()) ;
for ( int i = 0 ; i < ssize( vCrv) ; ++ i) {
if ( ! IsNull( vCrv[i]) && vCrv[i]->IsValid()) {
#if DEBUG_SYNC_POINTS
VT.emplace_back( vCrv[i]->Clone()) ;
VC.emplace_back( LIME) ;
#endif
Point3d ptStart ; vCrv[i]->GetStartPoint( ptStart) ;
Point3d ptEnd ; vCrv[i]->GetEndPoint( ptEnd) ;
if ( ! AreSamePointApprox( ptStart, ptEnd))
vSyncPoints.emplace_back( make_pair( ptStart, ptEnd)) ;
}
}
//// Recupero i punti di sincronizzazione e li restituisco
// ICURVEPOVECTOR vCrv ;
// pSBzRuled->GetAllPatchesIsocurves( false, vCrv) ;
// vSyncPoints.reserve( vCrv.size()) ;
// for ( int i = 0 ; i < ssize( vCrv) ; ++ i) {
// if ( ! IsNull( vCrv[i]) && vCrv[i]->IsValid()) {
// #if DEBUG_SYNC_POINTS
// VT.emplace_back( vCrv[i]->Clone()) ;
// VC.emplace_back( LIME) ;
// #endif
// Point3d ptStart ; vCrv[i]->GetStartPoint( ptStart) ;
// Point3d ptEnd ; vCrv[i]->GetEndPoint( ptEnd) ;
// if ( ! AreSamePointApprox( ptStart, ptEnd))
// vSyncPoints.emplace_back( make_pair( ptStart, ptEnd)) ;
// }
// }
#if DEBUG_SYNC_POINTS
SaveGeoObj( VT, VC, "C:\\Temp\\BorderSyncPoints.nge") ;
@@ -4219,7 +4167,8 @@ GetTrimmingRuledBezier( const CISURFPVECTOR& vSurf, const ICurve* pCrvEdge1,
// Se non ho punti di controllo forzati
if ( vSyncPoints.empty()) {
pSurfBz.Set( GetSurfBezierRuledSmooth( pCompoEdge1, pCompoEdge2, 10)) ;
BIPNTVECTOR vSyncLines ;
pSurfBz.Set( GetSurfBezierRuledSmooth( pCompoEdge1, pCompoEdge2, vSyncLines, 10)) ;
if ( IsNull( pSurfBz) || ! pSurfBz->IsValid()) {
LOG_ERROR( GetEGkLogger(), "Error in Trimming : Ruled Bezier invalid") ;
return nullptr ;
@@ -4972,38 +4921,44 @@ typedef vector<PntInfo> PNTINFOVECTOR ;
// Funzione per la regolarizzazione delle curve di bordo di una lavorazione di trim
// Le curve vengono modificate entro una data tolleranza, in modo che
bool
RegolarizeBordersLocally( const ICurve* pCrv1, const ICurve* pCrv2, ISurfBezier* pSurfBz, const BIPOINT& bpIsoStart, const BIPOINT& bpIsoEnd, double dTol)
RegolarizeBordersLocally( 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
int nUS1 = - 1, nUS2 = -1 ;
const Point3d& ptS1 = bpIsoStart.first ;
const Point3d& ptS2 = bpIsoEnd.first ;
const Point3d& ptE1 = bpIsoStart.second ;
const Point3d& ptE2 = bpIsoEnd.second ;
int nDegU, nDegV, nSpanU, nSpanV ;
bool bRat, bTrimmed ;
pSurfBz->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bRat, bTrimmed) ;
if ( nDegU != 3)
return false ;
// individuo quali isocurve sono state indicate come inizio e fine
for ( int i = 0 ; i < nDegU * nSpanU + 1 ; ++i) {
bool bOk = false ;
Point3d pt = pSurfBz->GetControlPoint( i, 0, &bOk) ;
if ( nUS1 == -1 && AreSamePointExact(pt, ptS1))
nUS1 = i ;
else if ( AreSamePointExact( pt, ptS2)) {
nUS2 = i ;
break ;
}
PtrOwner<ICurveComposite> pCrv1( pSurfBz->GetSingleEdge3D( false, 2)) ;
PtrOwner<ICurveComposite> pCrv2( pSurfBz->GetSingleEdge3D( false, 0)) ;
double dParS1 = -1 ; double dParS2 = -1 ;
if ( ! pCrv1->GetParamAtPoint( ptS1, dParS1) || ! pCrv1->GetParamAtPoint( ptS2, dParS2))
return false ;
double dParE1 = -1 ; double dParE2 = -1 ;
if ( ! pCrv2->GetParamAtPoint( ptE1, dParE1) || ! pCrv2->GetParamAtPoint( ptE2, dParE2))
return false ;
int nUS1 = int ( dParS1) ;
int nUS2 = int ( dParS2) ;
bool bInverted = false ;
if ( nUS1 > nUS2) {
swap( nUS1, nUS2) ;
swap( dParE1, dParE2) ;
bInverted = true ;
}
// scorro le isocurve a partire dallo start e dell'end della zona indicata
// controllo il twist rispetto alla isocurva precedente
int nMid = ( nUS2 + nUS1) / 2 ;
Point3d ptPrevS = ptS1 ;
Point3d ptPrevE = bpIsoStart.second ;
Point3d ptPrevE = ! bInverted ? bpIsoStart.second : bpIsoEnd.second ;
Vector3d vtIsoPrev = ptPrevE - ptPrevS ; vtIsoPrev.Normalize() ;
Point3d ptBez ; Vector3d vtNPrev ;
pSurfBz->GetPointNrmD1D2( nUS1, 0.5, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez, vtNPrev) ;
@@ -5017,7 +4972,7 @@ RegolarizeBordersLocally( const ICurve* pCrv1, const ICurve* pCrv2, ISurfBezier*
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) { /////////////////// scorro fino in fondo??
for ( int i = nUS1 + 3 ; i < nUS2 ; i +=3) {
// recupero precedente e successivo
Point3d ptThird1Curr = pSurfBz->GetControlPoint( i - 1, 0, &bOk) ;
Point3d ptThird2Curr = pSurfBz->GetControlPoint( i - 1, 1, &bOk) ;
@@ -5036,7 +4991,7 @@ RegolarizeBordersLocally( const ICurve* pCrv1, const ICurve* pCrv2, ISurfBezier*
if ( abs( dAng) > 0) {
// se l'isocurva di separazione dalla patch successiva è torta rispetto alla precedente
// allora prendo il penultimo punto della curva corrente, l'ultimo e il secondo della prossima e li sposto lungo la normale della superficie
dDist *= dAng * DEGTORAD ;
dDist *= dAng * DEGTORAD / 2 ;
ptThird1Curr += vtNPrev * dDist ;
ptCurrS += vtNPrev * dDist ;
ptSecond1Next += vtNPrev * dDist ;
@@ -5074,13 +5029,33 @@ RegolarizeBordersLocally( const ICurve* pCrv1, const ICurve* pCrv2, ISurfBezier*
pCC2->AddCurve( Release( cb2)) ;
}
// controllo di essere rimasto in tolleranza
PtrOwner<ICurve> pCrvOrig1( pCrv1->CopyParamRange( nUS1, dParE1)) ;
PtrOwner<ICurve> pCrvOrig2( pCrv2->CopyParamRange( nUS2, dParE2)) ;
double dErr = 0 ;
CalcApproxError( pCrvOrig1, pCC1, dErr, 20) ;
if ( dErr > dTol)
return false ;
CalcApproxError( pCrvOrig2, pCC2, dErr, 20) ;
if ( dErr > dTol)
return false ;
//PtrOwner<ISurfBezier> pSB( CreateSurfBezier()) ;
//pSB->CreateSmoothRuledByTwoCurves( pCrv1, pCrv2, 10) ;
// controllo di non aver creato dei cambi di concavità
// se ne trovo allora ruoto i terzetti attorno alla nuova isocurva
////////////////// DA IMPLEMENTARE (prendendo dalla versione precedente della Regolarize)
// aggiorno i punti di controllo della superficie di bezier
for ( int i = 0 ; i < ssize( vPnt0) ; ++i) {
pSurfBz->SetControlPoint( nUS1 + i, 0, vPnt0[i]) ;
pSurfBz->SetControlPoint( nUS1 + i, 1, vPnt1[i]) ;
}
#if DEBUG_SMOOTH_CURVATURE
VT.push_back( Release(pCC1)) ;
VT.push_back( Release(pCC2)) ;
SaveGeoObj( VT, "D:\\Temp\\bezier\\ruled\\smoothness\\regolarized.nge") ;
VT.push_back( Release(pCrv1)) ;
VT.push_back( Release(pCrv2)) ;
VT.push_back(pSurfBz->Clone());
SaveGeoObj( VT, "C:\\Temp\\bezier\\ruled\\smoothness\\regolarized.nge") ;
#endif
return true ;