in CalcPocketing :

- migliorati percorsi conformal ZigZag/OneWay
- migliorie varie.
This commit is contained in:
Riccardo Elitropi
2024-12-24 17:25:58 +01:00
parent 9f1aad5e49
commit 50b8a8aa94
+223 -35
View File
@@ -708,6 +708,32 @@ ResetCurveTempProps( ICurveComposite* pCrvCompo)
return true ;
}
//----------------------------------------------------------------------------
static bool
IsCurveCompoHomogeneous( const ICurveComposite* pCrvCompo, bool& bAllClosed, bool& bAllOpen)
{
// controllo validità della curva
if ( pCrvCompo == nullptr || ! pCrvCompo->IsValid())
return false ;
bAllClosed = true ;
bAllOpen = true ;
if ( pCrvCompo->GetCurveCount() == 0)
return true ;
// scorro le curve
for ( int i = 0 ; i < pCrvCompo->GetCurveCount() && ( bAllOpen || bAllClosed) ; ++ i) {
// recupero la sottocurva i-esima
const ICurve* pCrv = pCrvCompo->GetCurve( i) ;
if ( pCrv == nullptr || ! pCrv->IsValid())
return false ;
int nTmpProp = pCrv->GetTempProp( 0) ;
bAllOpen = bAllOpen && ( nTmpProp == TEMP_PROP_OPEN_EDGE) ;
bAllClosed = bAllClosed && ( nTmpProp == TEMP_PROP_CLOSE_EDGE) ;
}
return true ;
}
//----------------------------------------------------------------------------
static bool
GetSfrCrvCompoLoops( const ISurfFlatRegion* pSfr, ICRVCOMPOPOVECTOR& vCrvCompo)
@@ -886,6 +912,9 @@ GetIndOfHypoteticalChunk( const ICRVCOMPOPOVECTOR& vCrv, const ICurveComposite*
return false ;
}
}
// piccolo Offset di correzione della superfice
pSfrTmp->Offset( 500 * EPS_SMALL, ICurve::OFF_FILLET) ;
// classifico le curve con il Chunk nC-esimo
CRVCVECTOR ccClass ;
if ( pSfrTmp->GetCurveClassification( *pCrvA, EPS_SMALL, ccClass) &&
@@ -1609,14 +1638,14 @@ ChainCompoCurves( ICRVCOMPOPOVECTOR& vCrvCompo)
//----------------------------------------------------------------------------
static bool
ChangePtStartForSinglePocketCurve( ICurveComposite* pCrvCompo, const PocketParams& PockParams,
const Point3d& ptRef)
const Point3d& ptRef, bool bInvertOpenCrv)
{
// controllo dei parametri
if ( pCrvCompo == nullptr || ! pCrvCompo->IsValid())
return false ;
// se la curva è aperta
if ( ! pCrvCompo->IsClosed()) {
if ( ! pCrvCompo->IsClosed() && bInvertOpenCrv) {
// se non ho un punto di riferimento, allora non faccio nulla
if ( ! ptRef.IsValid())
return true ;
@@ -1650,7 +1679,8 @@ ChangePtStartForSinglePocketCurve( ICurveComposite* pCrvCompo, const PocketParam
//----------------------------------------------------------------------------
static bool
AdvanceExtendCurves( ICRVCOMPOPOVECTOR& vCrvCompo, const ISurfFlatRegion* pSfr, const PocketParams& PockParams)
AdvanceExtendCurves( ICRVCOMPOPOVECTOR& vCrvCompo, const ISurfFlatRegion* pSfr,
const PocketParams& PockParams, bool bInvertOpenCrv)
{
// se non ho curve, allora non faccio nulla
@@ -1663,7 +1693,7 @@ AdvanceExtendCurves( ICRVCOMPOPOVECTOR& vCrvCompo, const ISurfFlatRegion* pSfr,
if ( IsNull( vCrvCompo[i]) || ! vCrvCompo[i]->IsValid())
return false ;
// cambio il punto iniziale della curva
if ( ! ChangePtStartForSinglePocketCurve( vCrvCompo[i], PockParams, PockParams.ptStart))
if ( ! ChangePtStartForSinglePocketCurve( vCrvCompo[i], PockParams, PockParams.ptStart, bInvertOpenCrv))
return false ;
}
@@ -1764,7 +1794,7 @@ GetPocketCurvesByClosedEdges( const ISurfFlatRegion* pSfrChunk, const PocketPara
bool bExtAllClose = false ;
bool bExtAllOpen = false ;
if ( int( vpCrvs.size()) == 1) {
if ( vpCrvs[0]->GetTempProp( 0) == 0)
if ( vpCrvs[0]->GetTempProp( 0) == TEMP_PROP_CLOSE_EDGE)
bExtAllClose = true ;
else
bExtAllOpen = true ;
@@ -1918,7 +1948,7 @@ GetPocketCurvesByClosedEdges( const ISurfFlatRegion* pSfrChunk, const PocketPara
// salvo come primo tempParam l'offset massimo della regione ( servirà per la Feed)
for ( int i = 0 ; i < int( vCrvCompoRes_tmp.size()) ; ++ i) {
vCrvCompoRes_tmp[i]->SetTempParam( dMaxOffs, 0) ;
// se richiesta inversione della curva, allora inverto se chiusa
// se richiesta inversione della curva, allora inverto
if ( PockParams.bInvert)
vCrvCompoRes_tmp[i]->Invert() ;
vCrvCompoRes.emplace_back( Release( vCrvCompoRes_tmp[i])) ; // aggiungo la curva al vettore
@@ -1964,8 +1994,8 @@ GetSinglePocketingCurves( ISurfFlatRegion* pSfr, const PocketParams& PockParams,
// potrei doverle riconcatenare
if ( ! ChainCompoCurves( vCrvSingleCurves))
return false ;
// estendo le curve, definendo ptStart e calcolando le Feeds
if ( ! AdvanceExtendCurves( vCrvSingleCurves, pSfr_clone, PockParams))
// estendo le curve, definendo ptStart e calcolando le Feeds (non inverto le curve aperte)
if ( ! AdvanceExtendCurves( vCrvSingleCurves, pSfr_clone, PockParams, false))
return false ;
// imposto le Feed per tali curve se richiesto
for ( int i = 0 ; i < int( vCrvSingleCurves.size()) ; ++ i) {
@@ -6555,7 +6585,7 @@ GetZigZagOneWayBorderCrvs( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegio
if ( ! IsChunkAllHomogeneous( pSfrPock, nC, bIsChunkClosed, bIsChunkAllOpen))
return false ;
if ( ! bIsChunkClosed) {
if ( ! AdvanceExtendCurves( vClosedOffs_nC, pSfrOrig, PockParams))
if ( ! AdvanceExtendCurves( vClosedOffs_nC, pSfrOrig, PockParams, true))
return false ;
}
@@ -6904,15 +6934,44 @@ SmoothLinkByOffs( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, ICurve
pCrvOffs1 == nullptr || ! pCrvOffs1->IsValid() ||
pCrvLink == nullptr || ! pCrvLink->IsValid())
return false ;
// curva precedente e successiva
PtrOwner<ICurve> pCrvBef ;
if ( bFirstOffs0 && pCrvOffs0->IsClosed())
pCrvBef.Set( pCrvOffs0->GetFirstCurve()->Clone()) ;
else
pCrvBef.Set( pCrvOffs0->GetLastCurve()->Clone()) ;
PtrOwner<ICurve> pCrvAft( pCrvOffs1->GetFirstCurve()->Clone()) ;
if ( IsNull( pCrvBef) || IsNull( pCrvAft) ||
! pCrvBef->IsValid() || ! pCrvAft->IsValid())
// curva precedente
PtrOwner<ICurveComposite> pCrvBef( CreateCurveComposite()) ;
if ( IsNull( pCrvBef))
return false ;
if ( bFirstOffs0 && pCrvOffs0->IsClosed()) {
const ICurve* pCrvFirst = pCrvOffs0->GetFirstCurve() ;
if ( pCrvFirst == nullptr || ! pCrvFirst->IsValid())
return false ;
PtrOwner<ICurve> pMyCrv( pCrvFirst->Clone()) ;
if ( IsNull( pMyCrv) || ! pMyCrv->IsValid())
return false ;
pCrvBef->AddCurve( Release( pMyCrv)) ;
}
else {
const ICurve* pCrvLast = pCrvOffs0->GetLastCurve() ;
if ( pCrvLast == nullptr || ! pCrvLast->IsValid())
return false ;
PtrOwner<ICurve> pMyCrv( pCrvLast->Clone()) ;
if ( IsNull( pMyCrv) || ! pMyCrv->IsValid())
return false ;
pCrvBef->AddCurve( Release( pMyCrv)) ;
}
// curva successiva
PtrOwner<ICurveComposite> pCrvAft( CreateCurveComposite()) ;
if ( IsNull( pCrvAft))
return false ;
const ICurve* pCrvFirst = pCrvOffs1->GetFirstCurve() ;
if ( pCrvFirst == nullptr || ! pCrvFirst->IsValid())
return false ;
PtrOwner<ICurve> pMyCrv( pCrvFirst->Clone()) ;
if ( IsNull( pMyCrv) || ! pMyCrv->IsValid())
return false ;
pCrvAft->AddCurve( Release( pMyCrv)) ;
// controllo la validità delle curve precedenti e successive ricavate
if ( IsNull( pCrvBef) || IsNull( pCrvAft) || ! pCrvBef->IsValid() || ! pCrvAft->IsValid())
return false ;
// estendo il Link
pCrvLink->AddCurve( Release( pCrvBef), false, dTol) ;
@@ -6920,11 +6979,17 @@ SmoothLinkByOffs( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, ICurve
// smusso
ModifyCurveToSmoothed( pCrvLink, PockParams, dSmoothPar, dSmoothPar, false) ;
// toglo gli estremi
pCrvLink->RemoveFirstOrLastCurve( false) ;
pCrvLink->RemoveFirstOrLastCurve( true) ;
delete( pCrvLink->RemoveFirstOrLastCurve( false)) ;
delete( pCrvLink->RemoveFirstOrLastCurve( true)) ;
// modifico Offset0 per raccordarlo al nuovo Link
if ( bFirstOffs0 && pCrvOffs0->IsClosed()) {
pCrvOffs0->AddCurve( pCrvLink->GetFirstCurve()->Clone()) ;
const ICurve* pCrvFirst = pCrvLink->GetFirstCurve() ;
if ( pCrvFirst == nullptr || ! pCrvFirst->IsValid())
return false ;
PtrOwner<ICurve> pMyCrv( pCrvFirst->Clone()) ;
if ( IsNull( pMyCrv) || ! pMyCrv->IsValid())
return false ;
pCrvOffs0->AddCurve( Release( pMyCrv)) ;
pCrvLink->RemoveFirstOrLastCurve( false) ;
}
else {
@@ -6964,8 +7029,8 @@ GetConformalLinkForOpenCrv( const ICurveComposite* pCrvOffs0, const ICurveCompos
double dPar0 ; vCrvClassBorder[i]->GetParamAtPoint( ptLinkS, dPar0, dTol) ;
double dPar1 ; vCrvClassBorder[i]->GetParamAtPoint( ptLinkE, dPar1, dTol) ;
// ricavo le due curve possibili di Link
PtrOwner<ICurve> pCrvLinkA( vCrvClassBorder[i]->CopyParamRange( dPar0, dPar1)) ;
PtrOwner<ICurve> pCrvLinkB( vCrvClassBorder[i]->CopyParamRange( dPar1, dPar0)) ;
PtrOwner<ICurveComposite> pCrvLinkA( ConvertCurveToComposite( vCrvClassBorder[i]->CopyParamRange( dPar0, dPar1))) ;
PtrOwner<ICurveComposite> pCrvLinkB( ConvertCurveToComposite( vCrvClassBorder[i]->CopyParamRange( dPar1, dPar0))) ;
// scelgo quella migliore
double dLenA = 0. ;
if ( ! IsNull( pCrvLinkA) && pCrvLinkA->IsValid())
@@ -7590,7 +7655,8 @@ ExtendConformalOffsAndSetFeed( const ISurfFlatRegion* pSfrPock, const PocketPara
if ( vCrvOffs.empty())
return true ;
/* dalla superificie estesa presso i lati aperti, effettuo un Offset interno pari alla somma del
/*
dalla superificie estesa presso i lati aperti, effettuo un Offset interno pari alla somma del
raggio utensile e dell'offset radiale. La ricerca delle zone non svuotate avviene all'interno
di questa regione
*/
@@ -7740,7 +7806,7 @@ OrderConformalPaths( ICRVCOMPOPOVECTOR& vCrvPaths, const ISurfFlatRegion* pSfrCh
if ( vCrvPaths[i]->GetLastCurve()->GetTempProp( 0) == TEMP_PROP_OUT_START)
PtrOwner<ICurve> pLastCrv( pCompoPath->RemoveFirstOrLastCurve( true)) ;
// creo la regione di svuotatura di tale percorso
vSfrRemoved[i].Set( GetSurfFlatRegionFromFatCurve( CloneCurveComposite( pCompoPath), PockParams.dRad, false, false)) ;
vSfrRemoved[i].Set( GetSurfFlatRegionFromFatCurve( CloneCurveComposite( pCompoPath), PockParams.dRad + 500 * EPS_SMALL, false, false)) ;
if ( IsNull( vSfrRemoved[i]) || ! vSfrRemoved[i]->IsValid())
return false ;
}
@@ -7790,17 +7856,78 @@ OrderConformalPaths( ICRVCOMPOPOVECTOR& vCrvPaths, const ISurfFlatRegion* pSfrCh
else {
// se lavorazione conformal ZigZag
if ( PockParams.nType == POCKET_CONFORMAL_ZIGZAG) {
// se ne ho trovate di più, allora euristicamente prendo la più corta
// se ne ho trovate di più, allora euristicamente prendo la curve che effettua
// meno overlap con la regione da limite
double dMinLen = INFINITO ;
double dMinArea = INFINITO ;
for ( int k = 0 ; k < int( vTempInds.size()) ; ++ k) {
// privilegio le aperte
if ( vCrvPaths[vTempInds[k]]->IsClosed())
continue ;
double dLen ; vCrvPaths[vTempInds[k]]->GetLength( dLen) ;
if ( dLen < dMinLen) {
dMinLen = dLen ;
vInds[i] = vTempInds[k] ;
// se la regione di incidenza è valida
if ( PockParams.SfrLimit.IsValid()) {
dMinLen = 0. ; // non mi interessa in questo caso la lunghezza della curva
PtrOwner<ISurfFlatRegion> pSfrTest( CloneSurfFlatRegion( vSfrRemoved[vTempInds[k]])) ;
if ( IsNull( pSfrTest) || ! pSfrTest->IsValid())
return false ;
pSfrTest->Intersect( PockParams.SfrLimit) ;
double dArea ; pSfrTest->GetArea( dArea) ;
if ( dArea < dMinArea) {
dMinArea = dArea ;
vInds[i] = vTempInds[k] ;
if ( dArea < EPS_SMALL)
break ; // è ottima...
}
}
// se la regione di incidenza non è valida, scelgo erusiticamente la curva più corta
else {
double dLen ; vCrvPaths[vTempInds[k]]->GetLength( dLen) ;
if ( dLen < dMinLen) {
dMinLen = dLen ;
vInds[i] = vTempInds[k] ;
}
}
}
// se ho solo curve adiacenti a regioni di incidenza
if ( dMinArea > EPS_SMALL) {
struct MyCompoClass {
PtrOwner<ICurveComposite> pCrvExtLoop ;
int nIndex ;
int nBorders ;
} ;
// euristicamente scelgo quella il cui bordo esterno contiene più curve di bordo esterno
vector<MyCompoClass> vCrvExtBorder( vTempInds.size() ) ;
for ( int j = 0 ; j < int( vCrvExtBorder.size()) ; ++ j) {
// recupero il bordo esterno (mi auguro sia un solo chunk...)
PtrOwner<ICurveComposite> pCrvExtLoop( ConvertCurveToComposite( vSfrRemoved[vTempInds[j]]->GetLoop( 0, 0))) ;
if ( IsNull( pCrvExtLoop) || ! pCrvExtLoop->IsValid() ||
! vCrvExtBorder[j].pCrvExtLoop.Set( pCrvExtLoop))
return false ;
vCrvExtBorder[j].nIndex = vTempInds[j] ;
vCrvExtBorder[j].nBorders = 0 ;
}
for ( int j = 0 ; j < int( vCrvExtBorder.size()) - 1 ; ++ j) {
for ( int k = j + 1 ; k < int( vCrvExtBorder.size()) ; ++ k) {
IntersCurveCurve ICC( *vCrvExtBorder[j].pCrvExtLoop, *vCrvExtBorder[k].pCrvExtLoop) ;
CRVCVECTOR ccClass ;
if ( ICC.GetCurveClassification( 0, EPS_SMALL, ccClass) &&
int( ccClass.size()) == 1) {
// se i-esima interna a j-esima
if ( ccClass[0].nClass == CRVC_IN)
++ vCrvExtBorder[k].nBorders ;
else if ( ccClass[0].nClass == CRVC_OUT)
++ vCrvExtBorder[j].nBorders ;
}
}
}
// ordino il vettore delle curve sulla base di quante ne contiene
sort( vCrvExtBorder.begin(), vCrvExtBorder.end(),
[] ( const MyCompoClass& a, const MyCompoClass& b) {
return a.nBorders > b.nBorders ;
}) ;
// recupero l'indice migliore
if ( ! vCrvExtBorder.empty())
vInds[i] = vCrvExtBorder[0].nIndex ;
}
// cerco solo tra le chiuse se non ho aperte
if ( dMinLen > INFINITO - 1) {
@@ -8088,6 +8215,62 @@ CalcConformalGuide( const ICurveComposite* pCrvCloseEdge, const ICurveComposite*
}
//----------------------------------------------------------------------------
static bool
CombineClosedEdgesForConformalOffsets( const ISurfFlatRegion* pSfrChunk, const PocketParams& PockParam,
bool& bOk, ICRVCOMPOPOVECTOR& vpCrvs)
{
// controllo dei parametri
if ( pSfrChunk == nullptr || ! pSfrChunk->IsValid())
return false ;
vpCrvs.clear() ;
bOk = false ;
// se la superficie non ha isole, allora non calcolo nulla
if ( pSfrChunk->GetLoopCount( 0) == 1)
return true ;
// recupero il bordo esterno e l'eventuale guida associata
ICRVCOMPOPOVECTOR vpCrvHomo ;
PtrOwner<ICurveComposite> pCrvExtLoop( ConvertCurveToComposite( pSfrChunk->GetLoop( 0, 0))) ;
if ( IsNull( pCrvExtLoop) || ! pCrvExtLoop->IsValid() ||
! AdjustCloseEsgesForConformalGuide( pCrvExtLoop, PockParam) ||
! IsCompoMadeBy2DifferentHomogeneousParts( pCrvExtLoop, PockParam, bOk, vpCrvHomo))
return false ;
if ( ! bOk)
return true ;
// recupero la guida ideale
PtrOwner<ICurveComposite> pCrvGuide( CreateCurveComposite()) ;
if ( IsNull( pCrvGuide) ||
! CalcConformalGuide( vpCrvHomo[0], vpCrvHomo[1], PockParam, pCrvGuide))
return false ;
if ( ! pCrvGuide->IsValid())
return true ;
// la guida definisce il tratto chiuso per gli Offsets
vpCrvs.emplace_back( Release( pCrvGuide)) ;
// recupero il bordo esterno della superficie originale
pCrvExtLoop.Set( ConvertCurveToComposite( pSfrChunk->GetLoop( 0, 0))) ;
if ( IsNull( pCrvExtLoop) || ! pCrvExtLoop->IsValid())
return false ;
// considero questo bordo come tutto aperto
for ( int i = 0 ; i < pCrvExtLoop->GetCurveCount() ; ++ i)
pCrvExtLoop->SetCurveTempProp( i, 0, TEMP_PROP_OPEN_EDGE) ;
// recupero solo le isole chiuse (di sicuro esistono isole)
for ( int nL = 1 ; nL < pSfrChunk->GetLoopCount( 0) ; ++ nL) {
// recupero la curva dell'isola
PtrOwner<ICurveComposite> pCrvIsl( ConvertCurveToComposite( pSfrChunk->GetLoop( 0, nL))) ;
if ( IsNull( pCrvIsl) || ! pCrvIsl->IsValid())
return false ;
// se curva tutta chiusa, allora la inserisco come isola
bool bAllOpen, bAllClose ;
if ( IsCurveCompoHomogeneous( pCrvIsl, bAllClose, bAllOpen) && bAllClose)
vpCrvs.emplace_back( Release( pCrvIsl)) ;
}
return true ;
}
//----------------------------------------------------------------------------
static bool
GetConformalOffsets( const ISurfFlatRegion* pSfrChunk, const ISurfFlatRegion* pSfrClass, const PocketParams& PockParam,
@@ -8139,8 +8322,13 @@ GetConformalOffsets( const ISurfFlatRegion* pSfrChunk, const ISurfFlatRegion* pS
else {
if ( ! IsSfrChunkMadeOnlyByClosedIslands( pSfrChunk, PockParam, bOk, vCrvCloseEdges))
return false ;
if ( ! bOk)
return true ;
if ( ! bOk) {
// 3) provo a combinare punto 1) e 2)
if ( ! CombineClosedEdgesForConformalOffsets( pSfrChunk, PockParam, bOk, vCrvCloseEdges))
return false ;
if ( ! bOk)
return true ; // sarà in SpiralIn/Out...
}
}
/* Calcolo degli Offsets */
@@ -8148,8 +8336,9 @@ GetConformalOffsets( const ISurfFlatRegion* pSfrChunk, const ISurfFlatRegion* pS
Voronoi myVRONI ;
for ( int i = 0 ; i < int( vCrvCloseEdges.size()) ; ++ i) {
vCrvCloseEdges[i]->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL) ;
myVRONI.AddCurve( Release( vCrvCloseEdges[i])) ;
myVRONI.AddCurve( vCrvCloseEdges[i]) ;
}
int MAX_ITER = 1000 ;
int nIter = 0 ;
double dOffs = PockParam.dRad + PockParam.dRadialOffset ;
@@ -8280,8 +8469,7 @@ AddConformal( ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig,
if ( PockParams.bAllClosed)
return ( AddSpiralOut( pSfrPock, pSfrOrig, PockParams, vCrvCompoRes)) ;
// Definisco la superficie di classificazione ( su essa vengono tagliate le curve progressive
// di Offset
// Definisco la superficie di classificazione ( su essa vengono tagliate le curve progressive di Offset)
/* NB
La superficie di classificazione è ottenuta estendendo di R/4 i lati aperti ( in modo
da compensare il fattore di smusso R/8 sulle curve di Offset)