Merge branch 'master' into NewRuled

This commit is contained in:
Daniele Bariletti
2026-02-23 09:12:05 +01:00
2 changed files with 241 additions and 4 deletions
BIN
View File
Binary file not shown.
+241 -4
View File
@@ -34,6 +34,7 @@
#include "/EgtDev/Include/EGkSbzFromCurves.h"
#include "/EgtDev/Include/EGkStmFromTriangleSoup.h"
#include "/EgtDev/Include/EGkIntersLineBox.h"
#include "/EgtDev/Include/EGkIntersCurvePlane.h"
#include "/EgtDev/Include/EGkSurfTriMeshAux.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include <thread>
@@ -53,6 +54,7 @@
#define DEBUG_BRK 0
#define DEBUG_BORDERS_BY_NORMALS 0
#define DEBUG_SYNC_POINTS 0
#define DEBUG_SYNC_INTERPOLATION 0
#define DEBUG_BEZIER_RULED 0
#define DEBUG_CURVATURE 0
#define DEBUG_SIMPLE_PATCHES 0
@@ -63,9 +65,9 @@
#define DEBUG_HOLES 0
#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_BEZIER_RULED || DEBUG_CURVATURE || \
DEBUG_SIMPLE_PATCHES || DEBUG_SURF_PATCHES || DEBUG_RAW_EDGES || DEBUG_EDGES || DEBUG_SHAPE_STM || \
DEBUG_HOLES || DEBUG
DEBUG_BRK || DEBUG_BORDERS_BY_NORMALS || DEBUG_SYNC_POINTS || DEBUG_SYNC_INTERPOLATION || \
DEBUG_BEZIER_RULED || DEBUG_CURVATURE || DEBUG_SIMPLE_PATCHES || DEBUG_SURF_PATCHES || \
DEBUG_RAW_EDGES || DEBUG_EDGES || DEBUG_SHAPE_STM || DEBUG_HOLES || DEBUG
#include "CurveLine.h"
#include "/EgtDev/Include/EGkGeoObjSave.h"
#include "/EgtDev/Include/EgtPerfCounter.h"
@@ -3577,6 +3579,95 @@ IsBorderAButtonHole( const PolyLine& PL, double dLinTol, double dAngTol, Frame3d
return false ;
}
//-----------------------------------------------------------------------------
//-------------------------------- Interpolazioni -----------------------------
//-----------------------------------------------------------------------------
static bool
InterpolateSyncCurvesOnEndGuidePoints( const ICurveComposite* pGuide, const ICurveComposite* pOtherGuide,
const Plane3d& plStart, const Plane3d& plEnd, double dLinTol,
BIPNTVECTOR& vBiPts)
{
vBiPts.clear() ;
// Verifico che le curve siano valide
if ( pGuide == nullptr || ! pGuide->IsValid() ||
pOtherGuide == nullptr || ! pOtherGuide->IsValid())
return false ;
// Recupero la sua lunghezza
double dGuideLen = 0. ;
if ( ! pGuide->GetLength( dGuideLen) || dGuideLen < dLinTol)
return false ;
// Scorro le curve da restituire
double dProgLen = 0. ;
vBiPts.reserve( pGuide->GetCurveCount() - 1) ;
for ( int i = 0 ; i < pGuide->GetCurveCount() - 1 ; ++ i) {
// Recupero la curva corrente
const ICurve* pCrv = pGuide->GetCurve( i) ;
if ( pCrv == nullptr || ! pCrv->IsValid())
return false ;
// Ne recupero la lunghezza e aggiorno la lunghezza progressiva
double dLen = 0. ;
if ( ! pCrv->GetLength( dLen))
return false ;
dProgLen += dLen ;
// Recupero la percentuale di interpolazione rispetto alla lunghezze
double dInterPar = dProgLen / dGuideLen ;
// Interpolo le normali dei piani rispetto a tale valore
Vector3d vtN = Media( plStart.GetVersN(), plEnd.GetVersN(), dInterPar) ;
vtN.Normalize() ;
// Definisco il piano di intersezione
Point3d ptCurr ;
if ( ! pCrv->GetEndPoint( ptCurr))
return false ;
#if DEBUG_SYNC_INTERPOLATION
Frame3d frPl ; frPl.Set( ptCurr, vtN) ;
PtrOwner<IGeoFrame3d> frCurr( CreateGeoFrame3d()) ; frCurr->Set( frPl) ;
VT.emplace_back( Release( frCurr)) ;
VC.emplace_back( WHITE) ;
SaveGeoObj( VT, VC, "C:\\Temp\\SyncLinesPlanes.nge") ;
#endif
// Recupero il parametro di intersezione tra la curva e il piano
#if 0
VT.clear() ; VC.clear() ;
PtrOwner<IGeoPoint3d> PT( CreateGeoPoint3d()) ; PT->Set( ptCurr) ;
VT.emplace_back( Release( PT)) ;
VC.emplace_back( AQUA) ;
PtrOwner<IGeoVector3d> VECT( CreateGeoVector3d()) ; VECT->Set( vtN) ;
VECT->ChangeBase( ptCurr) ;
PtrOwner<ICurveArc> pArc( CreateCurveArc()) ; pArc->Set( ptCurr, vtN, 1000.) ;
PtrOwner<ISurfFlatRegion> pSfrPlane( CreateSurfFlatRegion()) ;
pSfrPlane->AddExtLoop( Release( pArc)) ;
VT.emplace_back( Release( pSfrPlane)) ;
VC.emplace_back( Color( 0., 0., 0., .5)) ;
VT.emplace_back( Release( VECT)) ;
VC.emplace_back( BLUE) ;
VT.emplace_back( pOtherGuide->Clone()) ;
VC.emplace_back( WHITE) ;
SaveGeoObj( VT, VC, "C:\\Temp\\SyncLinesPlanes.nge") ;
#endif
IntersCurvePlane IntCP( *pOtherGuide, ptCurr, vtN) ;
if ( IntCP.GetIntersCount() == 0)
return false ; // ambiguità
// Recupero il punto della prima intersezione trovata
Point3d ptInt ;
double dPar ;
if ( ! IntCP.GetIntersPointNearTo( ptCurr, ptInt, dPar))
return false ;
#if DEBUG_SYNC_INTERPOLATION
PtrOwner<IGeoPoint3d> ptG( CreateGeoPoint3d()) ; ptG->Set( ptInt) ;
VT.emplace_back( Release( ptG)) ;
VC.emplace_back( WHITE) ;
SaveGeoObj( VT, VC, "C:\\Temp\\SyncLinesPlanes.nge") ;
#endif
// Memorizzo tale punto
vBiPts.emplace_back( make_pair( ptCurr, ptInt)) ;
}
return true ;
}
//-----------------------------------------------------------------------------
//-------------------------------- Funzioni Export ----------------------------
//-----------------------------------------------------------------------------
@@ -3847,10 +3938,14 @@ bool
GetTrimmingSurfBzSyncPoints( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2,
double dLinTol, BIPNTVECTOR& vSyncPoints)
{
vSyncPoints.clear() ;
// Verifica validità delle curve per la creazione della Bezier rigata
PtrOwner<ICurveComposite> pCompoEdge1( ConvertCurveToComposite( pCrvEdge1->Clone())) ;
PtrOwner<ICurveComposite> pCompoEdge2( ConvertCurveToComposite( pCrvEdge2->Clone())) ;
vSyncPoints.clear() ;
if ( IsNull( pCompoEdge1) || IsNull( pCompoEdge2) ||
! pCompoEdge1->IsValid() || ! pCompoEdge2->IsValid())
return false ;
// Controllo sulla tolleranza lineare
double dMyLinTol = Clamp( dLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ;
@@ -3892,6 +3987,148 @@ GetTrimmingSurfBzSyncPoints( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2,
return true ;
}
//------------------------------------------------------------------------------
// Funzione per interpolare le Curve di Sincronizzazione tra due Curve di Bordo
bool
GetTrimmingSyncInterpolation( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2,
const ICurve* pSync1, const ICurve* pSync2, double dLinTol,
double dAngTol, BIPNTVECTOR& vSyncPoints)
{
vSyncPoints.clear() ;
// Verifico la validità dei parametri
if ( pCrvEdge1 == nullptr || ! pCrvEdge1->IsValid() ||
pCrvEdge2 == nullptr || ! pCrvEdge2->IsValid() ||
pSync1 == nullptr || ! pSync1->IsValid() ||
pSync2 == nullptr || ! pSync2->IsValid())
return false ;
// Le curve di Bordo devono essere entrambe aperte o entrambe chiuse
if ( pCrvEdge1->IsClosed() != pCrvEdge2->IsClosed())
return false ;
// Verifico i valori delle tolleranze
double dMyLinTol = Clamp( dLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ;
double dMyAngTol = Clamp( dAngTol, EPS_ANG_SMALL, 60.) ;
// Verifico le due curve di sincronizzazione abbiano gli estremi sulle due curve di bordo
Point3d ptS1 ; pSync1->GetStartPoint( ptS1) ;
Point3d ptE1 ; pSync1->GetEndPoint( ptE1) ;
if ( AreSamePointEpsilon( ptS1, ptE1, dMyLinTol))
return false ;
double dUA, dUB, dUC, dUD ; // [A,C]->Edge1 | [B,D]->Edge2
if ( ( ! pCrvEdge1->GetParamAtPoint( ptS1, dUA, dMyLinTol) || ! pCrvEdge2->GetParamAtPoint( ptE1, dUB, dMyLinTol)) &&
( ! pCrvEdge1->GetParamAtPoint( ptE1, dUA, dMyLinTol) || ! pCrvEdge2->GetParamAtPoint( ptS1, dUB, dMyLinTol)))
return false ;
Point3d ptS2 ; pSync2->GetStartPoint( ptS2) ;
Point3d ptE2 ; pSync2->GetEndPoint( ptE2) ;
if ( AreSamePointEpsilon( ptS2, ptE2, dMyLinTol))
return false ;
if ( ( ! pCrvEdge1->GetParamAtPoint( ptS2, dUC, dMyLinTol) || ! pCrvEdge2->GetParamAtPoint( ptE2, dUD, dMyLinTol)) &&
( ! pCrvEdge1->GetParamAtPoint( ptE2, dUC, dMyLinTol) || ! pCrvEdge2->GetParamAtPoint( ptS2, dUD, dMyLinTol)))
return false ;
// Recupero i due tratti di curva
PtrOwner<CurveComposite> pCompoGuide1( ConvertCurveToBasicComposite( pCrvEdge1->CopyParamRange( dUA, dUC))) ;
PtrOwner<CurveComposite> pCompoGuide2( ConvertCurveToBasicComposite( pCrvEdge2->CopyParamRange( dUB, dUD))) ;
if ( IsNull( pCompoGuide1) || IsNull( pCompoGuide2) ||
! pCompoGuide1->IsValid() || ! pCompoGuide2->IsValid())
return false ;
// Determino quale curva è la più lunga, servirà come riferimento per la parametrizzazione e l'interpolazione
double dLen1, dLen2 ;
if ( ! pCompoGuide1->GetLength( dLen1) || ! pCompoGuide2->GetLength( dLen2) ||
dLen1 < dMyLinTol || dLen2 < dMyLinTol)
return false ;
if ( dLen2 > dLen1) {
swap( pCompoGuide1, pCompoGuide2) ;
swap( dLen1, dLen2) ;
}
if ( pCompoGuide2->IsPointOn( ptS1))
swap( ptS1, ptE1) ;
if ( pCompoGuide2->IsPointOn( ptS2))
swap( ptS2, ptE2) ;
#if DEBUG_SYNC_INTERPOLATION
VT.clear() ; VC.clear() ;
VT.emplace_back( pCompoGuide1->Clone()) ;
VC.emplace_back( AQUA) ;
VT.emplace_back( pCompoGuide2->Clone()) ;
VC.emplace_back( ORANGE) ;
PtrOwner<IGeoPoint3d> ptG( CreateGeoPoint3d()) ; ptG->Set( ptS1) ;
VT.emplace_back( ptG->Clone()) ; VC.emplace_back( AQUA) ;
ptG->Set( ptE1) ;
VT.emplace_back( ptG->Clone()) ; VC.emplace_back( ORANGE) ;
ptG->Set( ptS2) ;
VT.emplace_back( ptG->Clone()) ; VC.emplace_back( AQUA) ;
ptG->Set( ptE2) ;
VT.emplace_back( ptG->Clone()) ; VC.emplace_back( ORANGE) ;
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ; pLine->Set( ptS1, ptE1) ;
VT.emplace_back( pLine->Clone()) ; VC.emplace_back( PURPLE) ;
pLine->Set( ptS2, ptE2) ;
VT.emplace_back( pLine->Clone()) ; VC.emplace_back( PURPLE) ;
SaveGeoObj( VT, VC, "C:\\Temp\\SyncLinesPlanes.nge") ;
#endif
// Determino le Normali dei piani di taglio agli agli estremi delle due curve
Vector3d vtStart1, vtStart2 ;
if ( ! pCompoGuide1->GetStartDir( vtStart1) || ! pCompoGuide2->GetStartDir( vtStart2))
return false ;
Vector3d vtAux = ptE1 - ptS1 ; vtAux.Normalize() ;
Vector3d vtMTan = Media( vtStart1, vtStart2) ; vtMTan.Normalize() ;
Vector3d vtN = OrthoCompo( vtMTan, vtAux) ; vtN.Normalize() ;
Plane3d plStart ;
if ( ! plStart.Set( ptS1, vtN))
return false ;
Vector3d vtEnd1, vtEnd2 ;
if ( ! pCompoGuide1->GetEndDir( vtEnd1) || ! pCompoGuide2->GetEndDir( vtEnd2))
return false ;
vtAux = ptE2 - ptS2 ; vtAux.Normalize() ;
vtMTan = Media( vtEnd1, vtEnd2) ; vtMTan.Normalize() ;
vtN = OrthoCompo( vtMTan, vtAux) ; vtN.Normalize() ;
Plane3d plEnd ;
if ( ! plEnd.Set( ptS2, vtN))
return false ;
#if DEBUG_SYNC_INTERPOLATION
Frame3d frPlStart ; frPlStart.Set( ptS1, plStart.GetVersN()) ;
Frame3d frPlEnd ; frPlEnd.Set( ptS2, plEnd.GetVersN()) ;
PtrOwner<IGeoFrame3d> frS( CreateGeoFrame3d()) ; frS->Set( frPlStart) ;
PtrOwner<IGeoFrame3d> frE( CreateGeoFrame3d()) ; frE->Set( frPlEnd) ;
VT.emplace_back( Release( frS)) ;
VC.emplace_back( WHITE) ;
VT.emplace_back( Release( frE)) ;
VC.emplace_back( WHITE) ;
SaveGeoObj( VT, VC, "C:\\Temp\\SyncLinesPlanes.nge") ;
#endif
// Curve di Sincronizzazione del Bordo 1 sul Bordo 2
BIPNTVECTOR vBiPts1 ;
if ( ! InterpolateSyncCurvesOnEndGuidePoints( pCompoGuide1, pCompoGuide2, plStart, plEnd, dMyLinTol, vBiPts1))
return false ;
// Curve di Sincronizzazione del Bordo 2 sul Bordo 1
BIPNTVECTOR vBiPts2 ;
if ( ! InterpolateSyncCurvesOnEndGuidePoints( pCompoGuide2, pCompoGuide1, plStart, plEnd, dMyLinTol, vBiPts2))
return false ;
// Restituisco le Curve di Sincronizzazione
// [Da Bordo 1 a Bordo 2 originale]
vSyncPoints.reserve( ssize( vBiPts1) + ssize( vBiPts2)) ;
for ( int i = 0 ; i < ssize( vBiPts1) ; ++ i) {
vSyncPoints.emplace_back( vBiPts1[i]) ;
if ( pCrvEdge1->IsPointOn( vBiPts1[i].second, dMyLinTol))
swap( vSyncPoints.back().first, vSyncPoints.back().second) ;
}
for ( int i = 0 ; i < ssize( vBiPts2) ; ++ i) {
vSyncPoints.emplace_back( vBiPts2[i]) ;
if ( pCrvEdge1->IsPointOn( vBiPts2[i].second, dMyLinTol))
swap( vSyncPoints.back().first, vSyncPoints.back().second) ;
}
return true ;
}
//------------------------------------------------------------------------------
// Funzione per il calcolo della superficie di Bezier rigata
// NB. Possono essere passati dei parametri opzionali come vIndPriority e vIndVisible :