EgtGeomKernel 2.7j1 :

- in CalcPocketing migliorata la gestione delle svuotature Conformal.
This commit is contained in:
Riccardo Elitropi
2025-10-07 14:38:07 +02:00
parent ecef487746
commit fee6604d5e
2 changed files with 276 additions and 164 deletions
+276 -164
View File
@@ -55,6 +55,7 @@ struct PocketParams {
double dOpenMinSafe = 5. ; // estensione minima di sicurezza
double dMaxOptSize = 0. ; // dimensione per ottimizzazione
double dAngle = 0. ; // angolo per orientare le passate OneWay e ZigZag
double dSmooth = 5. ; // parametro di smusso per link ( raccordo )
double dLiTang = INFINITO ; // valore di LeadIn in ingresso
bool bCalcUnclearedRegs = true ; // flag per calcolare o meno le regioni non svuotate
bool bOptOffsets = true ; // flag per evitare Offset non necessari
@@ -1015,7 +1016,7 @@ GetIndOfHypoteticalChunk( const ICRVCOMPOPOVECTOR& vCrv, const ICurveComposite*
//----------------------------------------------------------------------------
static bool
ExtendPath( ICurveComposite* pCompo, const ISurfFlatRegion* pSfr, const PocketParams& PockParams,
const Vector3d& vtFirstOut, bool bEndOrStart, bool& bOkExtended)
const Vector3d& vtFirstOut, bool bEndOrStart, double dExtension, bool& bOkExtended)
{
/*
Estensione della curva pCompo con un segmento lineare.
@@ -1056,7 +1057,7 @@ ExtendPath( ICurveComposite* pCompo, const ISurfFlatRegion* pSfr, const PocketPa
// ruoto il versore d'uscita
Vector3d vtRotOut = GetRotate( vtFirstOut, Z_AX, - vAngles[i]) ;
// calcolo il punto di caduta dell'utensile
Point3d ptFall = pt + vtRotOut * ( PockParams.dRad + PockParams.dOpenMinSafe) ;
Point3d ptFall = pt + vtRotOut * dExtension ;
// controllo che sia sufficientemente distante dalla superficie limite
bool bInside = true ;
bool bOkOut = true ;
@@ -1170,29 +1171,10 @@ GetHomogeneousParts( ICurveComposite* pCrvCompo, const PocketParams& PockParams,
return true ;
}
//----------------------------------------------------------------------------
static bool
GetFirstOffsCrvFromSfr( const ISurfFlatRegion* pSfr, double dOffs, ICRVCOMPOPOVECTOR& vCrvFirstOffs)
{
// controllo dei parametri
if ( pSfr == nullptr || ! pSfr->IsValid())
return false ;
vCrvFirstOffs.clear() ;
// creo la regione mediante Offset
PtrOwner<ISurfFlatRegion> pSfrOffs( pSfr->CreateOffsetSurf( dOffs, ICurve::OFF_FILLET)) ;
if ( IsNull( pSfrOffs) || ! pSfrOffs->IsValid())
return false ;
// inserisco le curve orientante
return ( GetSfrCrvCompoLoops( pSfrOffs, vCrvFirstOffs)) ;
}
//---------------------------------------------------------------------------
static bool
CreateSurfFrIncidence( const ICurveComposite* pCrv, const PocketParams& PockParams,
const Vector3d& vtTanS_, const Vector3d& vtTanE_, const double dRad,
ISurfFlatRegion* pSfrInc)
const double dRad, ISurfFlatRegion* pSfrInc)
{
// controllo dei parametri
if ( pCrv == nullptr || ! pCrv->IsValid())
@@ -1318,11 +1300,11 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI
pCrvBorder == nullptr || ! pCrvBorder->IsValid() || pCrvBorder->GetCurveCount() == 0)
return false ;
// definisco la regione di incidenza
// definisco la regione di incidenza ( leggermente più grande )
PtrOwner<ISurfFlatRegion> pSfrInc( CreateSurfFlatRegion()) ;
if ( IsNull( pSfrInc))
return false ;
if ( ! CreateSurfFrIncidence( pCrvBorder, PockParams, vtTanS, vtTanE, dRad + 75 * EPS_SMALL, pSfrInc)) {
if ( ! CreateSurfFrIncidence( pCrvBorder, PockParams, dRad + 75. * EPS_SMALL, pSfrInc)) {
pSfrInc.Set( GetSurfFlatRegionFromFatCurve( CloneCurveComposite( pCrvBorder), dRad + 75 * EPS_SMALL, false, false)) ;
if ( IsNull( pSfrInc) || ! pSfrInc->IsValid())
return false ;
@@ -1347,12 +1329,12 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI
double dArea ; Plane3d plCheck ;
if ( ! pCrvCompo->GetArea( plCheck, dArea))
return false ;
bIsIsland = AreSameVectorEpsilon( plCheck.GetVersN(), - Z_AX, 10 * EPS_SMALL) ;
bIsIsland = AreSameVectorEpsilon( plCheck.GetVersN(), - Z_AX, 10. * EPS_SMALL) ;
// scorro il vettore creato...
for ( int c = 0 ; c < int( vCrvToCheck.size()) ; ++ c) {
for ( int i = 0 ; i < int( vCrvToCheck.size()) ; ++ i) {
// 1) recupero la curva corrente
PtrOwner<ICurveComposite> pCrvCurr( vCrvToCheck[c]->Clone()) ;
PtrOwner<ICurveComposite> pCrvCurr( vCrvToCheck[i]->Clone()) ;
if ( IsNull( pCrvCurr) || ! pCrvCurr->IsValid())
return false ;
// 2) ricavo i tratti con proprietà uniformi ( Aperti/Chiusi )
@@ -1360,12 +1342,12 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI
if ( ! GetHomogeneousParts( pCrvCurr, PockParams, vpCrvs))
return false ;
// 3) considero solo i tratti chiusi
for ( int cl = 0 ; cl < int( vpCrvs.size()) ; ++ cl) {
if ( vpCrvs[cl]->GetTempProp() == TEMP_PROP_OPEN_EDGE)
for ( int nU = 0 ; nU < int( vpCrvs.size()) ; ++ nU) {
if ( vpCrvs[nU]->GetTempProp() == TEMP_PROP_OPEN_EDGE)
continue ;
// 4) effettuo l'Offset della curva di metà dDiamJ
OffsetCurve OffsCrv ;
if ( ! OffsCrv.Make( vpCrvs[cl], - dDiamJ * 0.5 - 20 * EPS_SMALL, PockParams.nOffsType))
if ( ! OffsCrv.Make( vpCrvs[nU], - dDiamJ / 2. - 20. * EPS_SMALL, PockParams.nOffsType))
return false ;
// 5) scorro tutte le curve di Offset che si sono formate, prendendo sempre la più lunga tra le rimanenti
PtrOwner<ICurve> pOffLongestCrv( OffsCrv.GetLongerCurve()) ;
@@ -1373,7 +1355,7 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI
// 6) creo la regione di incidenza di tale curva ( "Curva a fagiolo")
bool bSquareEnds = ( PockParams.nOffsType == ICurve::OFF_CHAMFER) ;
bool bSquareMids = ( PockParams.nOffsType == ICurve::OFF_CHAMFER) ;
PtrOwner<ISurfFlatRegion> pSfrBean( GetSurfFlatRegionFromFatCurve( Release( pOffLongestCrv), dDiamJ * 0.5, bSquareEnds, bSquareMids)) ;
PtrOwner<ISurfFlatRegion> pSfrBean( GetSurfFlatRegionFromFatCurve( Release( pOffLongestCrv), dDiamJ / 2., bSquareEnds, bSquareMids)) ;
if ( IsNull( pSfrBean) || ! pSfrBean->IsValid())
return false ;
// inverto se necessario
@@ -1381,7 +1363,8 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI
pSfrBean->Invert() ;
// 7) se la "Regione a fagiolo" non influenza la regione di incidenza, la transcuro
bool bDiscard = false ;
if ( ! bIsIsland) { // se tratto un loop esterno
if ( ! bIsIsland) {
// se tratto un loop esterno
PtrOwner<ISurfFlatRegion> pSfrBean_test( CloneSurfFlatRegion( pSfrBean)) ;
if ( IsNull( pSfrBean_test) || ! pSfrBean_test->IsValid())
return false ;
@@ -1390,7 +1373,8 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI
! pSfrBean_test->IsValid() ||
pSfrBean_test->GetChunkCount() == 0) ;
}
else if ( bIsAllOpen && bIsIsland) { // se isola aperta
else if ( bIsAllOpen && bIsIsland) {
// se isola aperta
for ( int cI = 0 ; cI < pSfrInc->GetChunkCount() && ! bDiscard ; ++ cI) {
for ( int cB = 0 ; cB < pSfrBean->GetChunkCount() && ! bDiscard ; ++ cB) {
if ( pSfrInc->GetChunkSimpleClassification( cI, *pSfrBean, cB) == REGC_IN1) {
@@ -1424,8 +1408,7 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI
PtrOwner<ISurfFlatRegion> pSfrLimit( PockParams.SfrLimit.Clone()) ;
if ( IsNull( pSfrLimit) || ! pSfrLimit->IsValid())
return false ;
// piccolo Offset per sicurezza
pSfrLimit->Offset( 50 * EPS_SMALL, ICurve::OFF_FILLET) ;
pSfrLimit->Offset( 50. * EPS_SMALL, ICurve::OFF_FILLET) ;
pSfrInc->Subtract( *pSfrLimit) ; // rimuovo la regione limite
// può capitare che la regione Limite mi crei più Chunk sulla pSfrInc
@@ -1574,7 +1557,6 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI
}
return true ;
}
//----------------------------------------------------------------------------
@@ -1601,9 +1583,14 @@ AdjustContourWithOpenEdges( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vCrvI
if ( PockParams.bAllowZigZagOneWayBorders &&
( PockParams.nType == POCKET_ZIGZAG || PockParams.nType == POCKET_ONEWAY))
dRad += PockParams.dOffsExtra ;
// se lavorazione a ZigZag con smusso, esco di Step/2 per pulire gli aperti
// se lavorazione a ZigZag con smusso
if ( PockParams.nType == POCKET_ZIGZAG && PockParams.bSmooth)
dRad += max( PockParams.dSideStep / 2, PockParams.dRad / 8) ;
dRad += PockParams.bSmooth ;
// se lavorazione Conformal
if ( PockParams.nType == POCKET_CONFORMAL_ZIGZAG || PockParams.nType == POCKET_CONFORMAL_ONEWAY) {
if ( PockParams.dRad - PockParams.dSideStep > 0)
dRad -= PockParams.dSideStep ;
}
// salvo il raggio trovato
PockParams.dOpenEdgeRad = dRad ;
@@ -1639,25 +1626,21 @@ AdjustContourWithOpenEdges( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vCrvI
// controllo che sia almeno lungo quanto il diametro utensile
double dLen = 0. ;
vpCrvs[i]->GetLength( dLen) ;
if ( dLen > PockParams.dRad * 2 - 5 * EPS_SMALL) {
// ricavo la tangenze dei lati chiusi agli estremi di questa curva
Vector3d vtTanS = V_INVALID ;
Vector3d vtTanE = V_INVALID ;
if ( i != 0) {
if ( ! vpCrvs[i-1]->GetEndDir( vtTanS) || // tangente finale del chiuso precedente
! vpCrvs[( i + 1) % int( vpCrvs.size())]->GetStartDir( vtTanE)) // tangente iniziale del chiuso successivo...
return false ;
vtTanE.Invert() ; // invertita
}
if ( ! AdjustOpenEdge( pCrvCompo, vCrvIsl, dParS, dParE, vtTanS, vtTanE, dRad, dDiamJ, PockParams, vpCrvs[i]))
// ricavo la tangenze dei lati chiusi agli estremi di questa curva
Vector3d vtTanS = V_INVALID ;
Vector3d vtTanE = V_INVALID ;
if ( i != 0) {
if ( ! vpCrvs[i-1]->GetEndDir( vtTanS) || // tangente finale del chiuso precedente
! vpCrvs[( i + 1) % int( vpCrvs.size())]->GetStartDir( vtTanE)) // tangente iniziale del chiuso successivo...
return false ;
vtTanE.Invert() ; // invertita
}
else
nCurrTmpProp = TEMP_PROP_CLOSE_EDGE ;
if ( ! AdjustOpenEdge( pCrvCompo, vCrvIsl, dParS, dParE, vtTanS, vtTanE, dRad, dDiamJ, PockParams, vpCrvs[i]))
return false ;
}
// assegno le proprietà di lato Aperto/Chiuso per la curva corrente
for ( int u = 0 ; u < vpCrvs[i]->GetCurveCount() ; ++ u)
vpCrvs[i]->SetCurveTempProp( u, nCurrTmpProp, 0) ;
vpCrvs[i]->SetCurveTempProp( u, nCurrTmpProp, TEMP_PROP_CLOSE_EDGE) ;
// aggiungo la curva ricavata ( se chiusa -> la copio, se aperta -> copio l'estesa)
if ( ! pCrvCompo_final->AddCurve( vpCrvs[i]->Clone())) {
// per sicurezza, se gli estremi non coincidono, creo un piccolo raccordo lineare
@@ -1840,14 +1823,14 @@ AdvanceExtendCurves( ICRVCOMPOPOVECTOR& vCrvCompo, const ISurfFlatRegion* pSfr,
Vector3d vtStart ; vCrvCompo[i]->GetStartDir( vtStart) ;
vtStart.Invert() ;
bool bIsStartExtended = false ;
if ( ! ExtendPath( vCrvCompo[i], pSfr, PockParams, vtStart, false, bIsStartExtended))
if ( ! ExtendPath( vCrvCompo[i], pSfr, PockParams, vtStart, false, PockParams.dRad + PockParams.dOpenMinSafe, bIsStartExtended))
return false ;
// se aperta, controllo la fine
if ( ! bIsClosed) {
// ricavo vettore tangente finale e provo ad estendere
Vector3d vtEnd ; vCrvCompo[i]->GetEndDir( vtEnd) ;
bool bIsEndExtended = false ;
if ( ! ExtendPath( vCrvCompo[i], pSfr, PockParams, vtEnd, true, bIsEndExtended))
if ( ! ExtendPath( vCrvCompo[i], pSfr, PockParams, vtEnd, true, PockParams.dRad + PockParams.dOpenMinSafe, bIsEndExtended))
return false ;
if ( bIsEndExtended)
break ;
@@ -2155,7 +2138,6 @@ GetSinglePocketingCurves( ISurfFlatRegion* pSfr, PocketParams& PockParams,
return true ;
}
//----------------------------------------------------------------------------
static bool
ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams)
@@ -2295,7 +2277,6 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams)
if ( ! pSrfFinal->IsValid())
return false ;
// chiudo le isole che risultano ambigue ( quindi non omgenee)
for ( int nC = 0 ; nC < pSrfFinal->GetChunkCount() ; ++ nC) {
for ( int nL = 1 ; nL < pSrfFinal->GetLoopCount( nC) ; ++ nL) {
@@ -3662,7 +3643,7 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams&
pCrvRes->GetStartDir( vtMidOut) ;
vtMidOut.Rotate( pSfrChunk->GetNormVersor(), PockParam.bInvert ? ANG_RIGHT : - ANG_RIGHT) ;
bool bIsExtended ;
ExtendPath( pCrvRes, pSfrChunk, PockParam, vtMidOut, false, bIsExtended) ;
ExtendPath( pCrvRes, pSfrChunk, PockParam, vtMidOut, false, PockParam.dRad + PockParam.dOpenMinSafe, bIsExtended) ;
}
// se invece lavorazione in SpiralOut, inverto il percorso
else if ( PockParam.nType == POCKET_SPIRALOUT)
@@ -3694,11 +3675,11 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams&
Vector3d vtRef ; pCrvRes->GetStartDir( vtRef) ;
vtRef.Invert() ;
bool bIsStartExtended = false ;
if ( ! ExtendPath( pCrvRes, pSfrChunk, PockParam, vtRef, false, bIsStartExtended))
if ( ! ExtendPath( pCrvRes, pSfrChunk, PockParam, vtRef, false, PockParam.dRad + PockParam.dOpenMinSafe, bIsStartExtended))
return false ;
pCrvRes->GetEndDir( vtRef) ;
bool bIsEndExtended = false ;
if ( ! ExtendPath( pCrvRes, pSfrChunk, PockParam, vtRef, true, bIsEndExtended))
if ( ! ExtendPath( pCrvRes, pSfrChunk, PockParam, vtRef, true, PockParam.dRad + PockParam.dOpenMinSafe, bIsEndExtended))
return false ;
if ( bIsEndExtended && ! bIsStartExtended)
pCrvRes->Invert() ;
@@ -4943,7 +4924,7 @@ CalcBoundedSmoothedLink( const Point3d& ptStart, const Vector3d& vtStart, const
return false ;
}
// La curva necessita di un ulteriore smusso, in quanto tagliata su un bordo
ModifyCurveToSmoothed( pCompoTest, PockParams, PockParams.dRad / 4., PockParams.dRad / 4., false) ;
ModifyCurveToSmoothed( pCompoTest, PockParams, PockParams.dSmooth, PockParams.dSmooth, false) ;
// nel caso speciale della circonferenza, devo impostare il punto iniziale
if ( dParMeet < EPS_ZERO) {
if ( pCompoTest->IsClosed()) { // sempre...
@@ -6064,7 +6045,7 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
}
// smusso le curve di offset ( ad eccezione di quelle di primo Offset)
double dSmoothPar = PockParams.dRad / 8. ;
double dSmoothPar = PockParams.dSmooth / SQRT2 ;
for ( int i = 0 ; i < int( vOffs.size()) ; ++ i) {
if ( i >= nCrvFirstOffs)
ModifyCurveToSmoothed( vOffs[i], PockParams, dSmoothPar, dSmoothPar, false) ;
@@ -6664,7 +6645,7 @@ AddSpiralIn( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig,
bool bIsExtended = false ;
if ( bSomeOpen)
ExtendPath( pMCrv, pSfrOrig, PockParams, vtMidOut, false, bIsExtended) ;
ExtendPath( pMCrv, pSfrOrig, PockParams, vtMidOut, false, PockParams.dRad + PockParams.dOpenMinSafe, bIsExtended) ;
// inserisco le curve nel vettore
vCrvCompoRes.emplace_back( Release( pMCrv)) ;
@@ -6946,10 +6927,10 @@ AddZigZag( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketPar
Vector3d vtRef ; vpCrvs[nU]->GetStartDir( vtRef) ;
vtRef.Invert() ;
bool bIsExtended = false ;
if ( ! ExtendPath( vpCrvs[nU], pSfrOrig, PockParams, vtRef, false,bIsExtended))
if ( ! ExtendPath( vpCrvs[nU], pSfrOrig, PockParams, vtRef, false, PockParams.dRad + PockParams.dOpenMinSafe, bIsExtended))
return false ;
vpCrvs[nU]->GetEndDir( vtRef) ;
if ( ! ExtendPath( vpCrvs[nU], pSfrOrig, PockParams, vtRef, true, bIsExtended))
if ( ! ExtendPath( vpCrvs[nU], pSfrOrig, PockParams, vtRef, true, PockParams.dRad + PockParams.dOpenMinSafe, bIsExtended))
return false ;
}
}
@@ -7147,10 +7128,10 @@ AddOneWay( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketPar
Vector3d vtRef ; pCrvSegCompo->GetStartDir( vtRef) ;
vtRef.Invert() ;
bool bIsExtended = false ;
if ( ! ExtendPath( pCrvSegCompo, pSfrOrig, PockParams, vtRef, false,bIsExtended))
if ( ! ExtendPath( pCrvSegCompo, pSfrOrig, PockParams, vtRef, false, PockParams.dRad + PockParams.dOpenMinSafe, bIsExtended))
return false ;
pCrvSegCompo->GetEndDir( vtRef) ;
if ( ! ExtendPath( pCrvSegCompo, pSfrOrig, PockParams, vtRef, true, bIsExtended))
if ( ! ExtendPath( pCrvSegCompo, pSfrOrig, PockParams, vtRef, true, PockParams.dRad + PockParams.dOpenMinSafe, bIsExtended))
return false ;
}
vCrvCompoRes.emplace_back( Release( pCrvSegCompo)) ;
@@ -7412,7 +7393,7 @@ CalcConformalLink( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, Pocke
if ( PockParams.nType == POCKET_CONFORMAL_ZIGZAG) {
// effettuo smusso del tratto lineare
SmoothLinkByOffs( pCrvOffs0, pCrvOffs1, pCrvLink, PockParams, bFirstIterOffs0, bFirstIterOffs1,
PockParams.dRad / 5., TOL) ;
PockParams.dSmooth, TOL) ;
// per sicurezza aggiorno i nuovi punti e i nuovi parametri
double dUNewE ;
Point3d ptStartNext ;
@@ -7953,21 +7934,37 @@ ExtendConformalOffsAndSetFeed( const ISurfFlatRegion* pSfrPock, const ISurfFlatR
return false ;
if ( vCrvOffs.empty())
return true ;
/*
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
*/
ICRVCOMPOPOVECTOR vCrvFirstOffs ;
if ( ! GetFirstOffsCrvFromSfr( pSfrPock, - PockParams.dRad - PockParams.dRadialOffset, vCrvFirstOffs))
// definisco la regione di ricerca delle aree non svuotate come la regione originale
PtrOwner<ISurfFlatRegion> pSfrBorder( CloneSurfFlatRegion( pSfrPock)) ;
if ( IsNull( pSfrBorder) || ! pSfrBorder->IsValid())
return false ;
// dalla superficie originale, rimuovo le parti definite dai lati chiusi
double dOffs = PockParams.dRad + PockParams.dRadialOffset - 2. * EPS_SMALL ;
ICRVCOMPOPOVECTOR vpCrvs ;
for ( int nC = 0 ; nC < pSfrPock->GetChunkCount() ; ++ nC) {
for ( int nL = 0 ; nL < pSfrPock->GetLoopCount( nC) ; ++ nL) {
PtrOwner<ICurveComposite> pCompoLoop( ConvertCurveToComposite( pSfrPock->GetLoop( nC, nL))) ;
if ( IsNull( pCompoLoop) || ! pCompoLoop->IsValid())
return false ;
PtrOwner<ISurfFlatRegion> pSfrToDiscard( GetSurfFlatRegionFromFatCurve( pCompoLoop->Clone(), dOffs, false, false)) ;
if ( IsNull( pSfrToDiscard) || ! pSfrToDiscard->IsValid())
return false ;
if ( ! pSfrBorder->Subtract( *pSfrToDiscard))
return false ;
}
}
ICRVCOMPOPOVECTOR vCrvBorder ;
if ( ! GetSfrCrvCompoLoops( pSfrBorder, vCrvBorder))
return false ;
// determino eventuale regioni con parti non svuotate e imposto la Feed alle curve
PtrOwner<ISurfFlatRegion> pSfrUncleared( CreateSurfFlatRegion()) ;
if ( IsNull( pSfrUncleared))
return false ;
if ( GetUnclearedRegionAndSetFeed( vCrvFirstOffs, vCrvOffs, vCrvLinks, pSfrOrig, PockParams, pSfrUncleared)) {
if ( GetUnclearedRegionAndSetFeed( vCrvBorder, vCrvOffs, vCrvLinks, pSfrOrig, PockParams, pSfrUncleared)) {
// estendo i percorsi di Offset se richiesto
if ( ! RemoveUnclearedRegions( pSfrUncleared, vCrvOffs, vCrvFirstOffs, PockParams))
if ( ! RemoveUnclearedRegions( pSfrUncleared, vCrvOffs, vCrvBorder, PockParams))
return false ;
}
@@ -8058,14 +8055,24 @@ 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 bOkExtension ;
if ( ! ExtendPath( vCrvPaths[i], pSfrOrig, PockParams, vtTan, false, bOkExtension))
return false ;
vCrvPaths[i]->GetEndDir( vtTan) ;
if ( ! ExtendPath( vCrvPaths[i], pSfrOrig, PockParams, vtTan, true, bOkExtension))
return false ;
Vector3d vtTanS, vtTanE ;
vCrvPaths[i]->GetStartDir( vtTanS) ; vtTanS.Invert() ;
vCrvPaths[i]->GetEndDir( vtTanE) ;
const int MAXTRY = 8 ;
bool bOkStartExtension = false, bOkEndExtension = false ;
for ( int j = 0 ; j <= MAXTRY ; ++ j) {
if ( bOkStartExtension && bOkEndExtension)
break ;
double dDist = PockParams.dOpenMinSafe + j * ( PockParams.dRad / ( 1. * MAXTRY)) ;
if ( ! bOkStartExtension) {
if ( ! ExtendPath( vCrvPaths[i], pSfrOrig, PockParams, vtTanS, false, dDist, bOkStartExtension))
return false ;
}
if ( ! bOkEndExtension) {
if ( ! ExtendPath( vCrvPaths[i], pSfrOrig, PockParams, vtTanE, true, dDist, bOkEndExtension))
return false ;
}
}
}
return true ;
@@ -8336,7 +8343,7 @@ ExtendGuideByIteration( ICurveComposite* pCompoTempGuide, const ICurveComposite*
pCompoPerimeter == nullptr || ! pCompoPerimeter->IsValid())
return false ;
const double EXTENSION_VAL = 1000. ;
const double EXTENSION_VAL = 5000. ;
// ricavo il punto finale della guida
Point3d ptEndGuide ; pCompoTempGuide->GetEndPoint( ptEndGuide) ;
@@ -8365,7 +8372,9 @@ ExtendGuideByIteration( ICurveComposite* pCompoTempGuide, const ICurveComposite*
Point3d ptPoly ;
PL.GetFirstPoint( ptPoly) ;
while ( PL.GetNextPoint( ptPoly)) {
if ( ! pSeg->Set( ptEndGuide, ptEndGuide + ( ptPoly - ptEndGuide) * EXTENSION_VAL))
Vector3d vtDir = ptPoly - ptEndGuide ;
vtDir.Normalize() ;
if ( ! pSeg->Set( ptEndGuide, ptEndGuide + vtDir * EXTENSION_VAL))
return false ;
// calcolo l'intersezione tra questo segmento e la curva di perimetro aperta
IntersCurveCurve ICC( *pSeg, *pCompoPerimeter) ;
@@ -8582,7 +8591,6 @@ GetConformalOffsets( const ISurfFlatRegion* pSfrChunk, const ISurfFlatRegion* pS
ICRVCOMPOPOVECTOR vpCrvs ;
PtrOwner<ICurveComposite> pCrvExtLoop( ConvertCurveToComposite( pSfrChunk->GetLoop( 0, 0))) ;
if ( IsNull( pCrvExtLoop) || ! pCrvExtLoop->IsValid() ||
! AdjustCloseEdgesForConformalGuide( pCrvExtLoop, PockParam) ||
! IsCompoMadeBy2DifferentHomogeneousParts( pCrvExtLoop, PockParam, bOk, vpCrvs))
return false ;
if ( ! bOk)
@@ -8747,10 +8755,94 @@ GetConformalOffsets( const ISurfFlatRegion* pSfrChunk, const ISurfFlatRegion* pS
}
// smusso le curve di Offset ( ad eccezione di quelle generate alla prima iterazione)
double dSmoothPar = PockParam.dRad / 8. ;
for ( int i = 1 ; i < int( vCrvOffs.size()) ; ++ i) {
for ( int j = 0 ; j < int( vCrvOffs[i].size()) ; ++ j)
ModifyCurveToSmoothed( vCrvOffs[i][j], PockParam, dSmoothPar, dSmoothPar, false) ;
ModifyCurveToSmoothed( vCrvOffs[i][j], PockParam, PockParam.dSmooth, PockParam.dSmooth, false) ;
}
return true ;
}
//----------------------------------------------------------------------------
static bool
CalcSpiralPocketing( const ISurfFlatRegion* pSfr, int nType, const PocketParams& PockParams,
ICRVCOMPOPOVECTOR& vCrvCompoRes)
{
// verifica validità della superficie
if ( pSfr == nullptr || ! pSfr->IsValid())
return false ;
// il tipo può essere solo SpiralIn o SpiralOut
if ( nType != POCKET_SPIRALIN && nType != POCKET_SPIRALOUT)
return false ;
// calcolo il percorso di svuotatura spiral
return ( CalcPocketing( pSfr, PockParams.dRad, PockParams.dRadialOffset, PockParams.dSideStep,
PockParams.dAngle, PockParams.dOpenMinSafe, nType, PockParams.bSmooth,
PockParams.bCalcUnclearedRegs, PockParams.bInvert, PockParams.bAvoidOpt,
PockParams.bAllowZigZagOneWayBorders, PockParams.bCalcFeed, PockParams.ptStart,
PockParams.SfrLimit.IsValid() ? PockParams.SfrLimit.Clone() : CreateSurfFlatRegion(),
PockParams.bAvoidOpt, PockParams.dMaxOptSize, PockParams.dLiTang, PockParams.nLiType,
vCrvCompoRes)) ;
}
//----------------------------------------------------------------------------
static bool
GetOrigChunkForConformal( const ISurfFlatRegion* pSfrChunk, const ISurfFlatRegion* pSfrOrig,
set<int>& setChunks)
{
// NB. funzione migliorabile... potrei calcolare tutto all'inizio senza ripetere le intersezioni
// controllo validità delle regioni
if ( pSfrChunk == nullptr || ! pSfrChunk->IsValid() ||
pSfrOrig == nullptr || ! pSfrOrig->IsValid())
return false ;
// se la superficie originale ha un solo Chunk allora è lui stesso
if ( pSfrOrig->GetChunkCount() == 1) {
setChunks.insert( 0) ;
return true ;
}
// essendo la pSfrChunk estesa, cerco quale chunk di pSfrOrig ha una intersezione valida
for ( int nC = 0 ; nC < pSfrOrig->GetChunkCount() ; ++ nC) {
// se il Chunk è già stato analizzato in precedenza, passo al successivo
if ( setChunks.find( nC) != setChunks.end())
continue ;
// recupero il Chunk corrente
PtrOwner<ISurfFlatRegion> pSfrChunkOrig( pSfrOrig->CloneChunk( nC)) ;
if ( IsNull( pSfrChunkOrig) || ! pSfrChunkOrig->IsValid())
return false ;
// controllo se esiste l'intersezione
if ( pSfrChunkOrig->Intersect( *pSfrChunk) && pSfrChunkOrig->IsValid())
setChunks.insert( nC) ;
}
return true ;
}
//----------------------------------------------------------------------------
static bool
CreateSurfFromOtherChunks( ISurfFlatRegion* pSfr, const ISurfFlatRegion* pSfrOther, const set<int>& setChunks)
{
// controllo della regione
if ( pSfr == nullptr ||
pSfrOther == nullptr || ! pSfrOther->IsValid())
return false ;
// se non ho indici di Chunk non faccio nulla
if ( setChunks.empty())
return true ;
// scorro gli indici dei Chunks
for ( auto it = setChunks.begin() ; it != setChunks.end() ; ++ it) {
// recupero l'indice del Chunk
int nChunk = *it ;
// recupero il Chunk come regione piana
PtrOwner<ISurfFlatRegion> pSfrChunk( pSfrOther->CloneChunk( nChunk)) ;
if ( ! IsNull( pSfrChunk) && pSfrChunk->IsValid()) {
if ( ! pSfr->IsValid())
pSfr->CopyFrom( pSfrChunk) ;
else if ( ! pSfr->Add( *pSfrChunk))
return false ;
}
}
return true ;
@@ -8767,99 +8859,119 @@ AddConformal( ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig,
return true ;
// se superifice tutta aperta, lavoro in SPIRAL_IN
if ( PockParams.bAllOpen) {
PockParams.nType = POCKET_SPIRALIN ;
return ( AddSpiralIn( pSfrPock, pSfrOrig, PockParams, vCrvCompoRes)) ;
}
if ( PockParams.bAllOpen)
return ( CalcSpiralPocketing( pSfrOrig, POCKET_SPIRALIN, PockParams, vCrvCompoRes)) ;
// se superficie tutta chiusa, lavoro in SPIRAL_OUT
if ( PockParams.bAllClosed) {
PockParams.nType = POCKET_SPIRALOUT ;
return ( AddSpiralOut( pSfrPock, pSfrOrig, PockParams, vCrvCompoRes)) ;
}
if ( PockParams.bAllClosed)
return ( CalcSpiralPocketing( pSfrOrig, POCKET_SPIRALOUT, PockParams, vCrvCompoRes)) ;
// definisco eventuali regioni da lavorare in SpiralIn e SpiralOut
PtrOwner<ISurfFlatRegion> pSfrSpiralIn( CreateSurfFlatRegion()) ;
PtrOwner<ISurfFlatRegion> pSfrSpiralOut( CreateSurfFlatRegion()) ;
if ( IsNull( pSfrSpiralIn) || IsNull( pSfrSpiralOut))
return false ;
// NB. La supercicie pSfrPock è estesa presso i lati aperti, quindi il suo numero di Chunk potrebbe
// essere differente dal numero di Chunk della superficie originale di svuotatura. Tengo un insieme di
// di indici dei Chunk che devono essere lavorati in SpiralIn e in SpiralOut
set<int> setIndChunkSpiralIn ;
set<int> setIndChunkSpiralOut ;
// scorro i chunk della superficie da lavorare
for ( int nC = 0 ; nC < pSfrPock->GetChunkCount() ; ++ nC) {
// controllo se il Chunk ha tutte proprietà omogenee tra loro
bool bClose, bOpen ;
if ( ! IsChunkAllHomogeneous( pSfrPock, nC, bClose, bOpen))
return false ;
// recupero il Chunk come regione piana
PtrOwner<ISurfFlatRegion> pSfrChunk( pSfrPock->CloneChunk( nC)) ;
if ( IsNull( pSfrChunk) || ! pSfrChunk->IsValid())
return false ;
// se Chunk tutto aperto, lo lavoro in SPIRAL_IN
// --- se Chunk tutto aperto, aggiorno i Chunk della superficie originale da lavorare in SpiralIn
if ( bOpen) {
int nType = PockParams.nType ;
PockParams.nType = POCKET_SPIRALIN ;
if ( ! AddSpiralIn( pSfrChunk, pSfrOrig, PockParams, vCrvCompoRes))
if ( ! GetOrigChunkForConformal( pSfrChunk, pSfrOrig, setIndChunkSpiralIn))
return false ;
PockParams.nType = nType ;
continue ;
}
// se Chunk tutto chiuso, lo lavoro in SPIRAL_OUT
// --- se Chunk tutto chiuso, lo lavoro in SPIRAL_OUT
else if ( bClose) {
int nType = PockParams.nType ;
PockParams.nType = POCKET_SPIRALOUT ;
if ( ! AddSpiralOut( pSfrChunk, pSfrOrig, PockParams, vCrvCompoRes))
return false ;
PockParams.nType = nType ;
if ( ! GetOrigChunkForConformal( pSfrChunk, pSfrOrig, setIndChunkSpiralOut))
continue ;
}
// se Chunk non omogeneo
else {
// ricavo gli Offset ( se possibili) dei tratti chiusi del Chunk
VICRVCOMPOPOVECTOR vvCrvOffs ;
if ( ! GetConformalOffsets( pSfrChunk, pSfrChunk, pSfrOrig, PockParams, vvCrvOffs))
// --- se chunk non omogoneo, ricavo gli Offset ( se possibili) dei tratti chiusi del Chunk
VICRVCOMPOPOVECTOR vvCrvOffs ;
if ( ! GetConformalOffsets( pSfrChunk, pSfrChunk, pSfrOrig, PockParams, vvCrvOffs))
return false ;
// se non ottengo Curve di Offset, lavoro in SpiralIn ( il Chunk ha dei lati aperti)
if ( vvCrvOffs.empty()) {
if ( ! GetOrigChunkForConformal( pSfrChunk, pSfrOrig, setIndChunkSpiralIn))
return false ;
// se non ottengo Curve di Offset, lavoro in SpiralIn ( il Chunk ha dei lati aperti)
if ( vvCrvOffs.empty()) {
int nType = PockParams.nType ;
PockParams.nType = POCKET_SPIRALIN ;
PtrOwner<ISurfFlatRegion> pSfrChunk_cl( CloneSurfFlatRegion( pSfrChunk)) ;
if ( IsNull( pSfrChunk_cl) || ! pSfrChunk_cl->IsValid() ||
! AddSpiralIn( pSfrChunk_cl, pSfrOrig, PockParams, vCrvCompoRes))
return false ;
PockParams.nType = nType ;
}
else {
// definisco vettore degli Offset e dei Link
ICRVCOMPOPOVECTOR vCrvOffs ;
ICURVEPOVECTOR vCrvLink ;
// ordino le curve di Offset e raccordo
if ( ! CalcConformalOffsAndLinks( vvCrvOffs, pSfrChunk, pSfrPock, PockParams, vCrvOffs, vCrvLink)) {
// se calcolare i raccordi risulta troppo ambiguo o complesso, ritorno a SpiralIn
int nType = PockParams.nType ;
PockParams.nType = POCKET_SPIRALIN ;
PtrOwner<ISurfFlatRegion> pSfrChunk_cl( CloneSurfFlatRegion( pSfrChunk)) ;
if ( IsNull( pSfrChunk_cl) || ! pSfrChunk_cl->IsValid() ||
! AddSpiralIn( pSfrChunk_cl, pSfrOrig, PockParams, vCrvCompoRes))
return false ;
PockParams.nType = nType ;
continue ;
}
// flag per controllo
bool bOk = true ;
// estendo i percorsi per eventuali regioni non svuotate e calcolo le Feed
bOk = bOk && ExtendConformalOffsAndSetFeed( pSfrPock, pSfrOrig, PockParams, vCrvOffs, vCrvLink) ;
// concateno Offset e Links
ICRVCOMPOPOVECTOR vCrvPaths ;
bOk = bOk && ChainConformalOffsWithLinks( vCrvOffs, vCrvLink, vCrvPaths) ;
// estendo per lati aperti ed ordino i percorsi trovati
bOk = bOk && OrderAndExtendConformalPaths( vCrvPaths, pSfrChunk, pSfrOrig, PockParams) ;
if ( ! bOk) {
// se qualche passaggio restituisce errore, provo in SpiralIn
int nType = PockParams.nType ;
PockParams.nType = POCKET_SPIRALIN ;
PtrOwner<ISurfFlatRegion> pSfrChunk_cl( CloneSurfFlatRegion( pSfrChunk)) ;
if ( IsNull( pSfrChunk_cl) || ! pSfrChunk_cl->IsValid() ||
! AddSpiralIn( pSfrChunk_cl, pSfrOrig, PockParams, vCrvCompoRes))
return false ;
PockParams.nType = nType ;
}
else {
// aggiungo i percorsi ricavati
for ( int i = 0 ; i < int( vCrvPaths.size()) ; ++ i)
vCrvCompoRes.emplace_back( Release( vCrvPaths[i])) ;
}
}
continue ;
}
// definisco i vettori ordinati degli Offset e dei Link
ICRVCOMPOPOVECTOR vCrvOffs ;
ICURVEPOVECTOR vCrvLink ;
if ( ! CalcConformalOffsAndLinks( vvCrvOffs, pSfrChunk, pSfrPock, PockParams, vCrvOffs, vCrvLink)) {
if ( ! GetOrigChunkForConformal( pSfrChunk, pSfrOrig, setIndChunkSpiralIn))
return false ;
continue ;
}
// flag per controllo
bool bOk = true ;
// estendo i percorsi per eventuali regioni non svuotate e calcolo le Feed
bOk = bOk && ExtendConformalOffsAndSetFeed( pSfrPock, pSfrOrig, PockParams, vCrvOffs, vCrvLink) ;
// concateno Offset e Links
ICRVCOMPOPOVECTOR vCrvPaths ;
bOk = bOk && ChainConformalOffsWithLinks( vCrvOffs, vCrvLink, vCrvPaths) ;
// estendo per lati aperti ed ordino i percorsi trovati
bOk = bOk && OrderAndExtendConformalPaths( vCrvPaths, pSfrChunk, pSfrOrig, PockParams) ;
// se qualche passaggio restituisce errore, provo in SpiralIn
if ( ! bOk) {
if ( ! GetOrigChunkForConformal( pSfrChunk, pSfrOrig, setIndChunkSpiralIn))
return false ;
continue ;
}
// altrimenti aggiungo i percorsi ricavati
for ( int i = 0 ; i < int( vCrvPaths.size()) ; ++ i)
vCrvCompoRes.emplace_back( Release( vCrvPaths[i])) ;
}
// se ho superfici da lavorare in SpiralIn, aggiungo le curve
if ( ! setIndChunkSpiralIn.empty()) {
// costruisco la regione di SpiralIn
PtrOwner<ISurfFlatRegion> pSfrSpiralIn( CreateSurfFlatRegion()) ;
if ( IsNull( pSfrSpiralIn) ||
! CreateSurfFromOtherChunks( pSfrSpiralIn, pSfrOrig, setIndChunkSpiralIn))
return false ;
// recupero le curve di Pocketing SpiralIn
ICRVCOMPOPOVECTOR vCrvSpiralIn ;
if ( ! CalcSpiralPocketing( pSfrSpiralIn, POCKET_SPIRALIN, PockParams, vCrvSpiralIn))
return false ;
for ( int i = 0 ; i < int( vCrvSpiralIn.size()) ; ++ i) {
if ( vCrvSpiralIn[i] != nullptr && vCrvSpiralIn[i]->IsValid())
vCrvCompoRes.emplace_back( Release( vCrvSpiralIn[i])) ;
}
}
// se ho superfici da lavorare in SpiralOut, aggiungo le curve
if ( ! setIndChunkSpiralOut.empty()) {
// costruisco la regione di SpiralOut
PtrOwner<ISurfFlatRegion> pSfrSpiralOut( CreateSurfFlatRegion()) ;
if ( IsNull( pSfrSpiralIn) ||
! CreateSurfFromOtherChunks( pSfrSpiralOut, pSfrOrig, setIndChunkSpiralOut))
return false ;
// recupero le curve di Pocketing SpiralOut
ICRVCOMPOPOVECTOR vCrvSpiralOut ;
if ( ! CalcSpiralPocketing( pSfrSpiralOut, POCKET_SPIRALOUT, PockParams, vCrvSpiralOut))
return false ;
for ( int i = 0 ; i < int( vCrvSpiralOut.size()) ; ++ i) {
if ( vCrvSpiralOut[i] != nullptr && vCrvSpiralOut[i]->IsValid())
vCrvCompoRes.emplace_back( Release( vCrvSpiralOut[i])) ;
}
}
BIN
View File
Binary file not shown.