EgtGeomKernel :

- In CalcPocketing aggiunto merge dei percorsi nel caso di intersezione delle estensioni presso le uscite libere.
This commit is contained in:
Riccardo Elitropi
2025-05-07 15:00:04 +02:00
parent 0ce477a3e7
commit cbdeffd93a
+130 -102
View File
@@ -85,48 +85,10 @@ typedef vector<ICRVCOMPOPOVECTOR> VICRVCOMPOPOVECTOR ;
#include "EgtDev/Include/EGkGeoObjSave.h"
#include "EgtDev/Include/EGkGeoPoint3d.h"
#include "EgtDev/Include/EGkGeoVector3d.h"
string sPockDebug = "C:\\Temp\\PockDebug.nge" ;
vector<IGeoObj*> VT ;
vector<Color> VC ;
//----------------------------------------------------------------------------
// Debug Functions
//----------------------------------------------------------------------------
void
DrawObjs( const ISURFFRPOVECTOR& vSfr, bool bSfrUniform, bool bAlphaCoverage,
const ICRVCOMPOPOVECTOR& vCompo, bool bCompoUniform, string sName)
{
// definisco i vettori per geometrie e colori
vector<IGeoObj*> VT ;
vector<Color> VC ;
// disegno le superfici
for ( int nS = 0 ; nS < int( vSfr.size()) ; ++ nS) {
if ( vSfr[nS] == nullptr || ! vSfr[nS]->IsValid())
return ;
VT.emplace_back( static_cast<IGeoObj*>( vSfr[nS]->Clone())) ;
VC.emplace_back( bAlphaCoverage ? Color( 0., 64., 0., .5) : Color( 0., 255., 0., .5)) ;
for ( int nC = 0 ; nC < vSfr[nS]->GetChunkCount() ; ++ nC) {
for ( int nL = 0 ; nL < vSfr[nS]->GetLoopCount( nC) ; ++ nL) {
PtrOwner<ICurveComposite> pCrvCompo( ConvertCurveToComposite( vSfr[nS]->GetLoop( nC, nL))) ;
for ( int nU = 0 ; nU < pCrvCompo->GetCurveCount() ; ++ nU) {
int nProp0 ; pCrvCompo->GetCurveTempProp( nU, nProp0, 0) ;
VT.emplace_back( static_cast<IGeoObj*>( pCrvCompo->GetCurve( nU)->Clone())) ;
VC.emplace_back( bSfrUniform ? WHITE : ( nProp0 == 0 ? ( bAlphaCoverage ? AQUA : BLUE) : ( bAlphaCoverage ? ORANGE : RED))) ;
}
}
}
}
// disegno le curve
for ( int nC = 0 ; nC < int( vCompo.size()) ; ++ nC) {
if ( vCompo[nC] == nullptr || ! vCompo[nC]->IsValid())
continue ;
VT.emplace_back( static_cast<IGeoObj*>( vCompo[nC]->Clone())) ;
VC.emplace_back( Color( double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, 1.)) ;
}
SaveGeoObj( VT, VC, sName) ;
return ;
inline Color GetRandomColor() {
return Color( double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, 1.) ;
}
#endif
@@ -5436,7 +5398,7 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con
double dMinDist = INFINITO ; // distanza tra questa curva e la successiva
Point3d ptStartNext ; // punto iniziale della curva successiva
// tra le curva successive cerco la curva interna e più vicina ad essa
// tra le curve successive cerco la curva interna e più vicina ad essa
for ( int j = i + 1 ; j < int( vOffs.size()) ; ++ j) {
IntersCurveCurve IntCC( *vOffs[i], *vOffs[j]) ;
CRVCVECTOR ccClass ;
@@ -5599,7 +5561,7 @@ CheckIfOffsetIsNecessary( const ICurveComposite* pCrvOffs, const double dOffs,
CRVCVECTOR ccClass ;
IntersCurveCurve intCC( *pCrvOffLonger, *pCrvTool) ;
intCC.GetCurveClassification( 1, EPS_SMALL, ccClass) ;
if ( int(ccClass.size()) == 1 && ccClass[0].nClass == CRVC_OUT) {
if ( int( ccClass.size()) == 1 && ccClass[0].nClass == CRVC_OUT) {
// centroide
bInsert = false ;
return true ;
@@ -5625,8 +5587,7 @@ CheckIfOffsetIsNecessary( const ICurveComposite* pCrvOffs, const double dOffs,
double dDimY = bBox.GetDimY() ;
// se dimensioni accettabili, inserisco
if ( dDimX < 2 * PockParams.dRad - 100 * EPS_SMALL ||
dDimY < 2 * 2 * PockParams.dRad - 100 * EPS_SMALL) {
if ( dDimX < 2 * PockParams.dRad - 100 * EPS_SMALL || dDimY < 4 * PockParams.dRad - 100 * EPS_SMALL) {
bInsert = false ;
return true ;
}
@@ -5672,9 +5633,8 @@ IsCompoMadeBy2DifferentHomogeneousParts( const ICurveComposite* pCompo, const Po
//----------------------------------------------------------------------------
static bool
CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int& nReg, Point3d& ptStart,
ICRVCOMPOPOVECTOR& vCrvOrigChunkLoops, ICurveComposite* pMCrv, bool& bOptimizedTrap,
bool& bMidOut, Vector3d& vtMidOut)
CalcSpiral( const ISurfFlatRegion* pSfrPock, const PocketParams& PockParams, int& nReg, Point3d& ptStart,
ICRVCOMPOPOVECTOR& vCrvOrigChunkLoops, ICurveComposite* pMCrv, bool& bMidOut, Vector3d& vtMidOut)
{
// inizializzo il percorso come vuoto
pMCrv->Clear() ;
@@ -5682,28 +5642,26 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int
// Offset corrente ( il primo è definito dal raggio utensile)
double dOffs = PockParams.dRad + PockParams.dRadialOffset ;
// recupero il versore normale della superficie, ruotandola nel piano XY
PtrOwner<ISurfFlatRegion> pSrfToWork( pSrfPock->Clone()) ;
if ( IsNull( pSrfToWork) || pSrfToWork->GetChunkCount() == 0)
return false;
// ciclo di offset verso l'interno
const int MAX_ITER = 1000 ;
int nIter = 0 ;
ICRVCOMPOPOVECTOR vOffs ; // vettore delle curve di offset
ICRVCOMPOPOVECTOR vOffsFirstCurve ; // curve di primo offset
PtrOwner<ISurfFlatRegion> pSrfAct( CloneSurfFlatRegion( pSrfToWork)) ; // regione attuale
// tengo una copia della regione corrente da svuotare
PtrOwner<ISurfFlatRegion> pSrfAct( CloneSurfFlatRegion( pSfrPock)) ;
if ( IsNull( pSrfAct) || pSrfAct->GetChunkCount() == 0)
return false ;
// ricavo le regioni progressive
double dOffsPrec = 0. ;
int nCrvFirstOffs = 0 ;
while ( nIter < MAX_ITER) {
// ricavo la regione piana da VRONI
// Offset della regione attuale
PtrOwner<ISurfFlatRegion> pSfrOffsVR( pSrfAct->CreateOffsetSurf( - dOffs, ICurve::OFF_FILLET)) ;
if ( IsNull( pSfrOffsVR))
return false ;
// se la regione sparisce allora riprovo con un Offset leggermente più piccolo
if ( ! pSfrOffsVR->IsValid()) {
pSfrOffsVR.Set( pSrfAct->CreateOffsetSurf( - dOffs + 5 * EPS_SMALL, ICurve::OFF_FILLET)) ;
if ( IsNull( pSfrOffsVR))
@@ -5756,7 +5714,8 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int
nCrvFirstOffs = int( vOffs.size()) ;
// controllo se serve un raggio più piccolo di svuotatura
bool bSmallRad = ( nIter == 0 ? dOffs < PockParams.dRad + EPS_ZERO : dOffs - dOffsPrec < PockParams.dRad + EPS_ZERO) ;
bool bSmallRad = ( nIter == 0 ? ( dOffs < PockParams.dRad + EPS_ZERO) :
( dOffs - dOffsPrec < PockParams.dRad + EPS_ZERO)) ;
// se ho trovato dei chunk, allora aggiorno l'Offset per la passata successiva
if ( nChunks > 0) {
@@ -5791,14 +5750,14 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int
// Se ho come lavorazione uno SpiralIn posso poter entrare dalle isole aperte...
int nIndexSwap = 0 ; // indice del vettore di curve per identificare la curva su cui entrare
if ( PockParams.nType == POCKET_SPIRALIN) {
if ( SetAdvancedPtStartForPath( vOffsFirstCurve, PockParams, pSrfToWork, ptRef, ptStart,
if ( SetAdvancedPtStartForPath( vOffsFirstCurve, PockParams, pSfrPock, ptRef, ptStart,
vtMidOut, bMidOut, nIndexSwap, vCrvOrigChunkLoops))
vOffsFirstCurve[nIndexSwap]->GetStartPoint( ptNewStart) ;
else
return false ;
}
else {
if ( SetPtStartForPath( vOffs[0], PockParams, pSrfToWork, ptRef, ptStart, vtMidOut, bMidOut,
if ( SetPtStartForPath( vOffs[0], PockParams, pSfrPock, ptRef, ptStart, vtMidOut, bMidOut,
vCrvOrigChunkLoops[0]))
vOffs[0]->GetStartPoint( ptNewStart) ;
else
@@ -5806,23 +5765,23 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int
}
// se richiesta inversione
for ( int i = 0 ; i < int( vOffs.size()) && PockParams.bInvert ; ++ i)
vOffs[i]->Invert() ;
if ( PockParams.bInvert) {
for ( int i = 0 ; i < int( vOffs.size()) ; ++ i)
vOffs[i]->Invert() ;
}
// smusso le curve di offset ( ad eccezione di quelle di primo Offset)
ICRVCOMPOPOVECTOR vOffsClosedCurves( vOffs.size()) ; // vettore con tutte le curve di Offset Chiuse
double dSmoothPar = PockParams.dRad / 8 ;
double dSmoothPar = PockParams.dRad / 8. ;
for ( int i = 0 ; i < int( vOffs.size()) ; ++ i) {
if ( i >= nCrvFirstOffs)
ModifyCurveToSmoothed( vOffs[i], PockParams, dSmoothPar, dSmoothPar, false) ;
vOffs[i]->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, true, true) ;
vOffsClosedCurves[i].Set( vOffs[i]->Clone()) ;
}
// setto il punto iniziale della svuotatura
double dNewUS ;
if ( nIndexSwap != 0)
swap( vOffs[0], vOffs[nIndexSwap]) ; // se entro da un'isola aperta
swap( vOffs[0], vOffs[nIndexSwap]) ;
vOffs[0]->GetParamAtPoint( ptNewStart, dNewUS) ;
vOffs[0]->ChangeStartPoint( dNewUS) ;
vOffs[0]->SetTempParam( 0., 0) ; // prima iterazione
@@ -6394,7 +6353,6 @@ AddSpiralIn( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig,
int nRegTot = nReg ;
Point3d ptStart ;
bool bOptimizedTrap = false ;
// cerco le curve originali del chunk cc-esimo ( per casi ottimizzati)
ICRVCOMPOPOVECTOR vCrvOrigChunkLoops ;
@@ -6404,8 +6362,7 @@ AddSpiralIn( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig,
// calcolo il percorso di svuotatura
bool bSomeOpen ;
Vector3d vtMidOut ;
if ( ! CalcSpiral( pSfrChunk, PockParams, nRegTot, ptStart, vCrvOrigChunkLoops, pMCrv, bOptimizedTrap,
bSomeOpen, vtMidOut))
if ( ! CalcSpiral( pSfrChunk, PockParams, nRegTot, ptStart, vCrvOrigChunkLoops, pMCrv, bSomeOpen, vtMidOut))
return false ;
// se terminate le regioni, esco
@@ -6413,21 +6370,7 @@ AddSpiralIn( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig,
break ; // passo al chunk originale successivo
bool bIsExtended = false ;
// se caso a trapezio
if ( bOptimizedTrap) {
Vector3d vtRef ;
pMCrv->GetStartDir( vtRef) ;
vtRef.Invert() ;
if ( ! ExtendPath( pMCrv, pSrfPock, PockParams, vtRef, false, bIsExtended))
return false ;
pMCrv->GetEndDir( vtRef) ;
if ( ! ExtendPath( pMCrv, pSrfPock, PockParams, vtRef, true, bIsExtended))
return false ;
AssignFeedSpiralOpt( 1, PockParams, pMCrv) ;
pMCrv->SetTempProp( TEMP_PROP_OPT_TRAPEZOID, 0) ;
}
// se esistenza di lati aperti validi
else if ( bSomeOpen)
if ( bSomeOpen)
ExtendPath( pMCrv, pSfrOrig, PockParams, vtMidOut, false, bIsExtended) ;
// inserisco le curve nel vettore
@@ -6487,7 +6430,6 @@ AddSpiralOut( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig,
int nRegTot = nReg ;
Point3d ptStart ;
bool bOptimizedTrap = false ;
// cerco la curva originale del chunk cc-esimo ( per casi ottimizzati)
ICRVCOMPOPOVECTOR vCrvOrig ;
@@ -6497,28 +6439,13 @@ AddSpiralOut( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig,
// calcolo il percorso di svuotatura
bool bSomeOpen ;
Vector3d vtMidOut ;
if ( ! CalcSpiral( pSfrChunk, PockParams, nRegTot, ptStart, vCrvOrig, pMCrv, bOptimizedTrap,
bSomeOpen, vtMidOut))
if ( ! CalcSpiral( pSfrChunk, PockParams, nRegTot, ptStart, vCrvOrig, pMCrv, bSomeOpen, vtMidOut))
return false ;
// se terminate le regioni, esco
if ( pMCrv->GetCurveCount() == 0)
break ; // passo al chunk originale successivo
if ( bOptimizedTrap) { // se caso a trapezio
Vector3d vtRef ;
pMCrv->GetStartDir( vtRef) ;
vtRef.Invert() ;
bool bIsExtended = false ;
if ( ! ExtendPath( pMCrv, pSrfPock, PockParams, vtRef, false, bIsExtended))
return false ;
pMCrv->GetEndDir( vtRef) ;
if ( ! ExtendPath( pMCrv, pSrfPock, PockParams, vtRef, true, bIsExtended))
return false ;
AssignFeedSpiralOpt( 1, PockParams, pMCrv) ;
pMCrv->SetTempProp( TEMP_PROP_OPT_TRAPEZOID, 0) ;
}
// inverto il percorso, perchè sono calcolati dall'esterno all'interno (solo nel caso non ottimizzato)
pMCrv->Invert() ;
@@ -7711,7 +7638,7 @@ ExtendConformalOffsAndSetFeed( const ISurfFlatRegion* pSfrPock, const PocketPara
//----------------------------------------------------------------------------
static bool
AddLeadInLeadOutToCurveConformalPaths( const ISurfFlatRegion* pSfrOrig, const ISurfFlatRegion* pSfrPock,
const PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvPaths)
const PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvPaths)
{
// controllo dei parametri
if ( pSfrOrig == nullptr || ! pSfrOrig->IsValid() ||
@@ -7796,11 +7723,11 @@ AddLeadInLeadOutToCurveConformalPaths( const ISurfFlatRegion* pSfrOrig, const IS
// estendo il percorso sul tratto iniziale e finale ( se ammissibile)
Vector3d vtTan ; vCrvPaths[i]->GetStartDir( vtTan) ;
vtTan.Invert() ;
bool bOkExtended ;
if ( ! ExtendPath( vCrvPaths[i], pSfrOrig, PockParams, vtTan, false, bOkExtended))
bool bOkExtension ;
if ( ! ExtendPath( vCrvPaths[i], pSfrOrig, PockParams, vtTan, false, bOkExtension))
return false ;
vCrvPaths[i]->GetEndDir( vtTan) ;
if ( ! ExtendPath( vCrvPaths[i], pSfrOrig, PockParams, vtTan, true, bOkExtended))
if ( ! ExtendPath( vCrvPaths[i], pSfrOrig, PockParams, vtTan, true, bOkExtension))
return false ;
}
@@ -8540,6 +8467,101 @@ AddConformal( ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig,
return true ;
}
//----------------------------------------------------------------------------
static bool
SmoothExtensionLinesByIntersection( ICRVCOMPOPOVECTOR& vCrvPaths, const PocketParams& PockParams)
{
// estendendo i percorsi con tratti in ingresso e in uscita, può capitare che si creino autointersezioni
// se ho meno di due percorsi non faccio nulla
if ( int( vCrvPaths.size()) < 2)
return true ;
// cerco le autointersezioni tra i percorsi successivi tra loro
double dTol = 50 * EPS_SMALL ;
for ( int i = 0 ; i < int( vCrvPaths.size()) - 1 ; ++ i) {
// se uno dei due percorsi presenta meno di 3 curve, non faccio nulla
if ( ! vCrvPaths[i]->IsValid() || vCrvPaths[i]->GetCurveCount() < 3 ||
! vCrvPaths[i+1]->IsValid() || vCrvPaths[i+1]->GetCurveCount() < 3)
continue ;
// se il percorso i-esimo non presenta una estensione in uscita e il percorso (i+1)-esimo
// non presenta una estensione in entrata, non faccio nulla
if ( vCrvPaths[i]->GetLastCurve()->GetTempProp() != TEMP_PROP_OUT_START ||
vCrvPaths[i+1]->GetFirstCurve()->GetTempProp() != TEMP_PROP_OUT_START)
continue ;
// recupero i due tratti lineari del percorso
const ICurveLine* pLineA = GetCurveLine( vCrvPaths[i]->GetLastCurve()) ;
const ICurveLine* pLineB = GetCurveLine( vCrvPaths[i+1]->GetFirstCurve()) ;
if ( pLineA == nullptr || ! pLineA->IsValid() ||
pLineB == nullptr || ! pLineB->IsValid())
continue ;
// se non esistono intersezioni tra i segmenti, non faccio nulla
IntersCurveCurve ICC( *pLineA, *pLineB) ;
if ( ICC.GetIntersCount() == 0)
continue ;
// definisco la curva di collegamento
PtrOwner<ICurveComposite> pCrvLink( CreateCurveComposite()) ;
if ( IsNull( pCrvLink))
return false ;
Point3d ptS_A ; pLineA->GetStartPoint( ptS_A) ;
pCrvLink->AddPoint( ptS_A) ;
IntCrvCrvInfo aInfo ;
if ( ! ICC.GetIntCrvCrvInfo( 0, aInfo))
continue ;
pCrvLink->AddLine( aInfo.IciA[0].ptI) ;
if ( aInfo.bOverlap)
pCrvLink->AddLine( aInfo.IciA[1].ptI) ;
Point3d ptE_B ; pLineB->GetEndPoint( ptE_B) ;
pCrvLink->AddLine( ptE_B) ;
// se tutti i punti sono coincidenti, allora non ho bisogno di entrambe le estensioni
if ( ! pCrvLink->IsValid() || pCrvLink->GetCurveCount() == 0) {
delete( vCrvPaths[i]->RemoveFirstOrLastCurve( true)) ;
delete( vCrvPaths[i+1]->RemoveFirstOrLastCurve( false)) ;
vCrvPaths[i]->AddCurve( Release( vCrvPaths[i+1]), dTol) ;
vCrvPaths.erase( vCrvPaths.begin() + i + 1) ;
-- i ;
continue ;
}
// raccordo del Link con percorso attuale e successivo
double dLen ;
double dLenExtension ;
pLineA->GetLength( dLenExtension) ;
if ( vCrvPaths[i]->GetLength( dLen) && ( dLen - dLenExtension) > PockParams.dRad / 2.) {
double dUS, dUE ;
vCrvPaths[i]->GetDomain( dUS, dUE) ;
double dU ;
vCrvPaths[i]->GetParamAtLength( dLen - dLenExtension - ( PockParams.dRad / 2.), dU) ;
pCrvLink->AddCurve( ConvertCurveToComposite( vCrvPaths[i]->CopyParamRange( dU, dUE - 1)), false, dTol) ; ;
}
pLineB->GetLength( dLenExtension) ;
if ( vCrvPaths[i+1]->GetLength( dLen) && ( dLen - dLenExtension) > PockParams.dRad / 2.) {
double dUS, dUE ;
vCrvPaths[i+1]->GetDomain( dUS, dUE) ;
double dU ;
vCrvPaths[i+1]->GetParamAtLength( dLenExtension + ( PockParams.dRad / 2.), dU) ;
pCrvLink->AddCurve( ConvertCurveToComposite( vCrvPaths[i+1]->CopyParamRange( dUS + 1, dU)), true, dTol) ;
}
pCrvLink->MergeCurves( 10 * EPS_SMALL, ANG_TOL_STD_DEG) ;
ModifyCurveToSmoothed( pCrvLink, PockParams, PockParams.dRad / 8., PockParams.dRad / 8., false) ;
// assegno Feed massima
AssignMaxFeed( pCrvLink, PockParams) ;
// modifico i percorsi
Point3d ptLinkS ; pCrvLink->GetStartPoint( ptLinkS) ;
Point3d ptLinkE ; pCrvLink->GetEndPoint( ptLinkE) ;
double dUE, dUS ;
if ( ! vCrvPaths[i]->GetParamAtPoint( ptLinkS, dUE, dTol) ||
! vCrvPaths[i]->TrimEndAtParam( dUE) ||
! vCrvPaths[i+1]->GetParamAtPoint( ptLinkE, dUS, dTol) ||
! vCrvPaths[i+1]->TrimStartAtParam( dUS))
continue ;
vCrvPaths[i]->AddCurve( Release( pCrvLink), dTol) ;
vCrvPaths[i]->AddCurve( Release( vCrvPaths[i+1]), dTol) ;
vCrvPaths.erase( vCrvPaths.begin() + i + 1) ;
-- i ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double dStep, double dAngle,
@@ -8653,6 +8675,12 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double
break ;
}
// ------------ intersezione delle estensioni ----------------------------
if ( ! myParams.bAllClosed) {
if ( ! SmoothExtensionLinesByIntersection( vCrvCompoPock, myParams))
return false ;
}
// riporto tutte le curve ottenute in globale
for ( int i = 0 ; i < int( vCrvCompoPock.size()) ; ++ i) {
vCrvCompoPock[i]->ToGlob( myParams.frLocXY) ;