EgtMachKernel :

- migliorata gestione lati aperti e scelta ordine degli Offset.
- migliorie generali.
This commit is contained in:
Riccardo Elitropi
2024-02-26 16:08:59 +01:00
parent ecc2c66fac
commit 85258fe4c4
2 changed files with 278 additions and 167 deletions
+269 -162
View File
@@ -741,10 +741,8 @@ Pocketing::Apply( bool bRecalc, bool bPostApply)
}
// se necessario, eseguo concatenamento ed inserisco i percorsi sotto la geometria ausiliaria
if ( bChain && ! Chain( nAuxId)) {
// m_pMchMgr->SetLastError( 2421, "Error in Pocketing : Chaining failed") ;
if ( bChain && ! Chain( nAuxId))
return false ;
}
// lavoro ogni singola catena
bool bOk = true ;
@@ -2200,6 +2198,8 @@ Pocketing::ProcessPath( int nPathId, int nPvId, int nClId)
pStm_PartVolume->ToGlob( frElevation) ;
// calcolo l'elevazione massima su ogni faccia del volume con normale circa - vtTool ( il volume è interno)
double dElev = 0. ;
// Flat Region per regione di calcolo dell'elevazione
SurfFlatRegionByContours SfrBC ;
pStm_PartVolume->Invert() ; // ho curve e normali orientate correttamente
for ( int i = 0 ; i < pStm_PartVolume->GetFacetCount() ; ++ i) {
Vector3d vtN_f ;
@@ -2212,17 +2212,36 @@ Pocketing::ProcessPath( int nPathId, int nPvId, int nClId)
if ( ! pStm_PartVolume->GetFacetLoops( i, vPL) ||
vPL.empty())
return false ;
// ricavo le curve Composite associate e calcolo l'elevazione
// ricavo le curve Composite associate e creo la FlatRegion assocoiata per l'orientamento
// NB. CalcRegionElevation calcola l'elevazione nella regione definita dalle curve, quindi serve che siano orientate
for ( int j = 0 ; j < int( vPL.size()) ; ++ j) {
PtrOwner<ICurveComposite> pCompo( CreateCurveComposite()) ;
double dCurrElev = 0. ;
if ( IsNull( pCompo) ||
! pCompo->FromPolyLine( vPL[j]) ||
! pCompo->IsValid() ||
! CalcRegionElevation( pCompo, vtTool, 0., 0.5 * ( m_dDiam_Prec > 0 ? m_dDiam_Prec : m_TParams.m_dDiam),
! SfrBC.AddCurve( Release( pCompo)))
return false ;
}
}
// ricavo la Flat region per il calcolo dell'elevazione
PtrOwner<ISurfFlatRegion> pSfrElevation( SfrBC.GetSurf()) ;
if ( IsNull( pSfrElevation) || ! pSfrElevation->IsValid())
return false ;
if ( AreOppositeVectorApprox( pSfrElevation->GetNormVersor(), vtTool))
pSfrElevation->Invert() ;
// calcolo l'elevazione
for ( int c = 0 ; c < pSfrElevation->GetChunkCount() ; ++ c) {
for ( int l = 0 ; l < pSfrElevation->GetLoopCount( c) ; ++ l) {
PtrOwner<ICurveComposite> pCrvLoop( ConvertCurveToComposite( pSfrElevation->GetLoop( c, l))) ;
if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid())
return false ;
if ( l > 0)
pCrvLoop->Invert() ;
double dCurrElev = 0. ;
if ( ! CalcRegionElevation( pCrvLoop, vtTool, 0., 0.5 * ( m_dDiam_Prec > 0 ? m_dDiam_Prec : m_TParams.m_dDiam),
m_dLen_Prec > 0 ? m_dLen_Prec : m_TParams.m_dLen, dCurrElev))
return false ;
dElev = max( dElev, dCurrElev) ;
dElev = max( dElev, dCurrElev) ; // l'elevazione è la massima tra quelle trovate
}
}
pStm_PartVolume->Invert() ; // riporto come in orginale
@@ -7822,6 +7841,7 @@ Pocketing::CalcSpiral( const ISurfFlatRegion* pSrfPock, int& nReg, Point3d& ptSt
PtrOwner<ISurfFlatRegion> pSfrOffsVR( pSrfAct->CreateOffsetSurf( - dOffs, ICurve::OFF_FILLET)) ;
if ( IsNull( pSfrOffsVR))
return false ;
// se l'offset della regione la la annulla, allora ritento con una piccola tolleranza
if ( ! pSfrOffsVR->IsValid()) {
pSfrOffsVR.Set( pSrfAct->CreateOffsetSurf( - dOffs + 5 * EPS_SMALL, ICurve::OFF_FILLET)) ;
if ( IsNull( pSfrOffsVR))
@@ -7843,20 +7863,23 @@ Pocketing::CalcSpiral( const ISurfFlatRegion* pSrfPock, int& nReg, Point3d& ptSt
for ( int i = 0 ; i < nChunks ; ++ i) {
// per ogni chunk...
int nLoops = pSfrOffsVR->GetLoopCount( i) ;
for ( int j = 0 ; j < nLoops ; ++ j) {
for ( int j = 0 ; j < nLoops ; ++ j) {
// per ogni loop...
PtrOwner<ICurveComposite> pCrvCompoBorder( ConvertCurveToComposite( pSfrOffsVR->GetLoop( i, j))) ;
if ( IsNull( pCrvCompoBorder) || ! pCrvCompoBorder->IsValid())
return false ;
// assegno come
if ( j > 0) // inverto l'orientamento delle curve interne ( offset delle isole trovate)
pCrvCompoBorder->Invert() ;
// salvo l'iterazione come primo parametro della curva
pCrvCompoBorder->SetTempParam( nIter * 1., 0) ;
// controllo quali regioni di Offset possono essere sostituite
bool bInsert = true ;
if ( ! CheckIfOffsetIsNecessary( pCrvCompoBorder, dOffs - dOffsPrec, ( int)vOffs.size(), nIter, vtExtr, bInsert))
if ( ! CheckIfOffsetIsNecessary( pCrvCompoBorder, dOffs - dOffsPrec, int( vOffs.size()), nIter, vtExtr, bInsert))
return false ;
if ( bInsert)
vOffs.emplace_back( Release( pCrvCompoBorder)) ;
if ( nIter == 0) { // salvo il bordo per i link (non invertiti)
if ( nIter == 0) { // salvo il bordo per i link ( non invertiti, devo sapere IN/OUT)
PtrOwner<ICurveComposite> pCrvCompoExtBorder( ConvertCurveToComposite( pSfrOffsVR->GetLoop( i, j))) ;
vOffsFirstCurve.emplace_back( Release( pCrvCompoExtBorder)) ;
}
@@ -7883,7 +7906,7 @@ Pocketing::CalcSpiral( const ISurfFlatRegion* pSrfPock, int& nReg, Point3d& ptSt
}
// se non ho trovato curve di Offset allora esco
if (( int)vOffs.size() == 0)
if ( vOffs.empty())
return true ;
// cambio il punto iniziale della prima Curva di Offset
@@ -7891,136 +7914,44 @@ Pocketing::CalcSpiral( const ISurfFlatRegion* pSrfPock, int& nReg, Point3d& ptSt
Point3d ptNewStart ;
if ( SetBetterPtStartForSubChunks( vOffs[0], pSrfToWork, ptRef, frPocket, ptStart, vtMidOut, bMidOut))
vOffs[0]->GetStartPoint( ptNewStart) ;
else
else
return false ;
// se richiesta inversione
for ( int i = 0 ; i < ( int)vOffs.size() && m_Params.m_bInvert ; ++ i)
for ( int i = 0 ; i < int( vOffs.size()) && m_Params.m_bInvert ; ++ i)
vOffs[i]->Invert() ;
// smusso le curve di offset ( ad eccezione della prima)
ICRVCOMPOPOVECTOR vOffsClosedCurves( vOffs.size()) ; // vettore con tutte le curve di Offset Chiuse
double dSmoothPar = m_TParams.m_dDiam / 16 ;
for ( int i = 0 ; i < int( vOffs.size()) ; ++i ) {
for ( int i = 0 ; i < int( vOffs.size()) ; ++ i) {
if ( i != 0)
ModifyCurveToSmoothed( vOffs[i], dSmoothPar, dSmoothPar, false) ;
vOffs[i]->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, true, true) ;
vOffsClosedCurves[i].Set( vOffs[i]->Clone()) ;
}
for ( int i = 0 ; i < int( vOffsFirstCurve.size()) ; ++ i) {
if ( i != 0)
ModifyCurveToSmoothed( vOffsFirstCurve[i], dSmoothPar, dSmoothPar, false) ;
vOffsFirstCurve[i]->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL) ;
}
// setto il punto iniziale della svuotatura
double dNewUS ;
vOffs[0]->GetParamAtPoint( ptNewStart, dNewUS) ;
vOffs[0]->ChangeStartPoint( dNewUS) ;
vOffs[0]->SetTempParam( 0., 0) ; // prima iterazione
// riordino le curve cambiando il loro punto di inizio e creando poi i collegamenti
int nClosestInd = -1 ; int nFlag ;
double dDist = INFINITO ;
Point3d ptHelp ;
// riordino le curve cambiando e creo i collegamenti
ICURVEPOVECTOR vLinks( vOffs.size()) ;
for ( int i = 0 ; i < int( vOffs.size()) - 1 ; ++ i) {
Point3d ptS ;
if ( ! vOffs[i]->GetStartPoint( ptS))
return false ;
// setto i default delle variabili
if ( ! DistPointCurve( ptS, *vOffs[i+1]).GetMinDistPoint( EPS_SMALL, ptHelp, nFlag))
return false ;
dDist = INFINITO ;
for ( int j = i + 1 ; j <= int( vOffs.size()) - 1 ; ++ j) {
// cerco il punto più vicino della curva
Point3d ptE ;
if ( ! DistPointCurve( ptS, *vOffs[j]).GetMinDistPoint( EPS_SMALL, ptE, nFlag))
return false ;
if ( dDist > Dist( ptS, ptE) ) {
dDist = Dist( ptS, ptE) ;
nClosestInd = j ;
ptHelp.Set( ptE.x, ptE.y, ptE.z) ;
}
}
// avendo la curva più vicina ...
// 1) scambio la curva i con la curva nClosestInd
if ( nClosestInd != i + 1) {
PtrOwner<ICurveComposite> ptoCCHelp( Release( vOffs[i + 1])) ;
vOffs[i + 1].Set( vOffs[nClosestInd]) ;
vOffs[nClosestInd].Set( ptoCCHelp) ;
}
// 2) cambio il suo punto iniziale ...
double dU ;
Point3d ptNE( ptHelp.x, ptHelp.y, ptHelp.z) ;
if ( ! vOffs[i + 1]->GetParamAtPoint( ptNE, dU))
return false ;
vOffs[i + 1]->ChangeStartPoint( dU) ;
// 2.1) Accorcio la curva per velocizzare ...
if (( int)vOffs.size() > 1) { // accorcio se ho almeno due Offset
// copio le curve i e i+1 nel caso non riesca a tagliarle ...
double dUNS, dUNE ;
PtrOwner<ICurveComposite> pCrvTest( CreateCurveComposite()) ; // possibile collegamento tra la curva i ed i+1
PtrOwner<ICurveComposite> pOff_i0( CloneCurveComposite( vOffs[i])) ;
PtrOwner<ICurveComposite> pOff_i1( CloneCurveComposite( vOffs[i + 1])) ;
// cerco di tagliare le curve, ottenendo il collegamento
// NB. se la curva di offset è la prima, non devo tagliarla, accorcio solo le successive ...
if ( ! CutCurveToConnect( vOffs[i], vOffs[i+1], vOffsClosedCurves, vOffsFirstCurve, pCrvTest, i == 0 ? 0 : 0.01, 0.01, 2)) {
// se non sono riuscito, ritorno alla configurazione iniziale
PtrOwner<ICurveComposite> pCrvLink( CreateCurveComposite()) ;
Vector3d vS, vE ;
vOffs[i].Set( pOff_i0) ; vOffs[i+1].Set( pOff_i1) ;
if ( ! vOffs[i]->GetStartDir( vS) || ! vOffs[i+1]->GetStartDir( vE))
return false ;
if ( CalcBoundedSmootedLink( ptS, vS, ptNE, vE, 0.5, vOffsFirstCurve, pCrvLink))
vLinks[i + 1].Set( pCrvLink) ; // aggiorno il collegamento
else {
m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ;
return false ;
}
continue ;
}
if ( ! pCrvTest->GetStartPoint( ptS) ||
! pCrvTest->GetEndPoint( ptNE) ||
! vOffs[i]->GetParamAtPoint( ptS, dUNS) ||
! vOffs[i+1]->GetParamAtPoint( ptNE, dUNE))
return false ;
// imposto il nuovo punto inziale della curva successiva
vOffs[i+1]->ChangeStartPoint( dUNE) ;
PtrOwner<ICurveComposite> pCrvNewOffS( CloneCurveComposite( vOffs[i])) ;
if ( dUNS > EPS_SMALL) { // se parametro di trim sufficientemente grande
pCrvNewOffS.Set( GetCurveComposite( vOffs[i]->CopyParamRange( 0, dUNS))) ;
// sostituisco la curva i-esima con quella tagliata
vOffs[i]->Clear() ;
vOffs[i].Set( pCrvNewOffS) ;
}
// aggiorno il collegamento
vLinks[i + 1].Set( pCrvTest) ;
}
}
if ( ! CreateSpiralPocketingPath( vOffs, vLinks, vOffsClosedCurves, vOffsFirstCurve))
return false ;
// copio il vettore degli Offset per settare poi la Feed
ICRVCOMPOPOVECTOR vOffsFeed ; vOffsFeed.reserve(( int)vOffs.size()) ;
for ( int i = 0 ; i < ( int)vOffs.size() ; ++ i)
vOffsFeed.emplace_back( vOffs[i]->Clone()) ;
//ICRVCOMPOPOVECTOR vOffsFeed ; vOffsFeed.reserve(( int)vOffs.size()) ;
//for ( int i = 0 ; i < ( int)vOffs.size() ; ++ i)
// vOffsFeed.emplace_back( vOffs[i]->Clone()) ;
// 3) controllo eventuali parti non svuotate...
// controllo eventuali parti non svuotate...
pCrvOEWithFlags->ToLoc( frPocket) ;
PtrOwner<ISurfFlatRegion> pSrfToCut( CreateSurfFlatRegion()) ;
if ( GetUnclearedRegion( vOffsFirstCurve, vOffs, vLinks, pCrvOEWithFlags, pSrfToCut)) {
// 4) Modifico i percorsi
// Modifico i percorsi
if ( ! RemoveExtraParts( pSrfToCut, vOffs, vOffsClosedCurves, vOffsFirstCurve, vLinks))
return false ;
}
@@ -8067,6 +7998,141 @@ Pocketing::CalcSpiral( const ISurfFlatRegion* pSrfPock, int& nReg, Point3d& ptSt
return true ;
}
//----------------------------------------------------------------------------
bool
Pocketing::CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks,
const ICRVCOMPOPOVECTOR& vOffsClosedCurves, const ICRVCOMPOPOVECTOR& vOffsFirstCurve)
{
// controllo dei parametri
if ( vOffs.empty() || vOffsFirstCurve.empty())
return false ;
vLinks.clear() ;
vLinks.resize( int( vOffs.size())) ;
// scorro tutte le curva di Offset
for ( int i = 0 ; i < int( vOffs.size()) - 1 ; ++ i) {
// ricavo il punto inziale della curva corrente
Point3d ptS ;
if ( ! vOffs[i]->GetStartPoint( ptS))
return false ;
// ricavo l'iterazione corrente
int nCurrIter = int( vOffs[i]->GetTempParam( 0)) ;
int nNextInd = -1 ; // indice della curva successiva
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
for ( int j = i + 1 ; j < int( vOffs.size()) ; ++ j) {
IntersCurveCurve IntCC( *vOffs[i], *vOffs[j]) ;
CRVCVECTOR ccClass ;
// se interna
if ( IntCC.GetCurveClassification( 1, EPS_SMALL, ccClass) &&
int( ccClass.size()) == 1 && ccClass[0].nClass == CRVC_IN) {
// calcolo la distanza minima tra essa
int nFlag ;
Point3d ptClosest ;
if ( DistPointCurve( ptS, *vOffs[j]).GetMinDistPoint( EPS_SMALL, ptClosest, nFlag)) {
double dCurrDist = SqDist( ptS, ptClosest) ;
if ( dCurrDist < dMinDist) {
dMinDist = dCurrDist ;
nNextInd = j ;
ptStartNext = ptClosest ;
}
}
}
}
// se non ho trovato nessuna curva interna... cerco semplicemente la curva più vicina
if ( nNextInd == -1) {
for ( int j = i + 1 ; j < int( vOffs.size()) ; ++ j) {
int nFlag ;
Point3d ptClosest ;
if ( DistPointCurve( ptS, *vOffs[j]).GetMinDistPoint( EPS_SMALL, ptClosest, nFlag)) {
double dCurrDist = SqDist( ptS, ptClosest) ;
if ( dCurrDist < dMinDist) {
dMinDist = dCurrDist ;
nNextInd = j ;
ptStartNext = ptClosest ;
}
}
}
}
// se non ho trovato nessuna curva, errore
if ( nNextInd == -1)
return false ;
// scambio la curva i+1 esima con la j-esima ( se non sono già in ordine)
if ( nNextInd != i + 1)
swap( vOffs[nNextInd], vOffs[i+1]) ;
// cambio il suo punto iniziale nel punto più vicino tovato
double dUS ;
if ( ! vOffs[i+1]->GetParamAtPoint( ptStartNext, dUS, EPS_SMALL))
return false ;
vOffs[i+1]->ChangeStartPoint( dUS) ;
// accorcio la curva per raccordarmi in tangenza con la successiva
if ( int( vOffs.size()) > 1) {
// clono le curve i ed i+1 esime ( nel caso non riuscissi ad accorciarle o raccordarle )
PtrOwner<ICurveComposite> pCrv_i( CloneCurveComposite( vOffs[i])) ;
PtrOwner<ICurveComposite> pCrv_ii( CloneCurveComposite( vOffs[i+1])) ;
if ( IsNull( pCrv_i) || IsNull( pCrv_ii) || ! pCrv_i->IsValid() || ! pCrv_ii->IsValid())
return false ;
// creo la curva che le collegherà
PtrOwner<ICurveComposite> pCrvLink( CreateCurveComposite()) ;
if ( IsNull( pCrvLink))
return false ;
// NB. Le curve di Offset da tagliare non devono essere quelle di primo Offset
if ( ! CutCurveToConnect( vOffs[i], vOffs[i+1], vOffsClosedCurves, vOffsFirstCurve, pCrvLink,
i == 0 ? 0 : 0.01, 0.01, 2)) {
// se non sono riuscito, cerco una strada più semplice
// ripristino le curve
pCrvLink->Clear() ;
vOffs[i].Set( Release( pCrv_i)) ; // chiuso
vOffs[i+1].Set( Release( pCrv_ii)) ; // chiuso
// recupero i vettori tangente iniziali ( le curve sono chiuse )
Vector3d vtS, vtE ;
if ( ! vOffs[i]->GetStartDir( vtS) || ! vOffs[i+1]->GetStartDir( vtE))
return false ;
// creo il bi-arco tra esse
if ( CalcBoundedSmootedLink( ptS, vtS, ptStartNext, vtE, 0.5, vOffsFirstCurve, pCrvLink))
vLinks[i + 1].Set( pCrvLink) ; // aggiorno il collegamento
else {
m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ;
return false ;
}
continue ; // passo alla curva i+1 esima successiva
}
// per sicurezza aggiorno i nuovi punti e i nuovi parametri
double dUNewS, dUNewE ;
if ( ! pCrvLink->GetStartPoint( ptS) ||
! pCrvLink->GetEndPoint( ptStartNext) ||
! vOffs[i]->GetParamAtPoint( ptS, dUNewS) ||
! vOffs[i+1]->GetParamAtPoint( ptStartNext, dUNewE))
return false ;
// imposto il punto iniziale della curva successiva ( i+1 esima)
vOffs[i+1]->ChangeStartPoint( dUNewE) ;
PtrOwner<ICurveComposite> pCrvNewOffs( CloneCurveComposite( vOffs[i])) ;
if ( dUNewS > EPS_SMALL) {
pCrvNewOffs.Set( ConvertCurveToComposite( vOffs[i]->CopyParamRange( 0, dUNewS))) ;
// sostituisco la curva i esima con quella tagliata
vOffs[i].Set( pCrvNewOffs) ;
}
// aggiorno il collegamento
vLinks[i+1].Set( Release( pCrvLink)) ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
Pocketing::OptimizedSpiralCirle( const ICurveComposite* pCrvCompo, const double dToll, double& dRad,
@@ -8180,7 +8246,7 @@ Pocketing::ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, doubl
Vector3d vtS, vtE ;
if ( ! vCrvStepsToFill[i]->GetEndDir( vtS) || ! vCrvStepsToFill[i+1]->GetStartDir( vtE))
continue ;
if ( AreSameVectorApprox( vtS, vtE)) {
if ( AreSameVectorEpsilon( vtS, vtE, 5 * EPS_SMALL)) {
vCrvArcs.emplace_back( CreateCurveComposite()) ; // arco nullo
vArcsToJump.push_back( i) ; // da scartare
continue ;
@@ -8199,7 +8265,9 @@ Pocketing::ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, doubl
// se valori trattati come parametri...
if ( bAsParam) {
// ... cerco i parametri corrispondenti sulle due curve
double dU_cm_S = 0 ; double dULast1 = 1 ; double dULast2 = 1 ;
double dU_cm_S = 0 ;
double dULast1 = 1 ;
double dULast2 = 1 ;
vCrvStepsToFill[i]->GetDomain( dU_cm_S, dULast1) ;
dUE_ref = ( 1 - dRightLen) * dULast1 ;
vCrvStepsToFill[i+1]->GetDomain( dU_cm_S, dULast2) ;
@@ -8209,10 +8277,12 @@ Pocketing::ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, doubl
// prendo i punti sulle due curve rispetto a tali parametri
Point3d ptS, ptE ;
if ( ! vCrvStepsToFill[i]->GetPointD1D2( dUE_ref, ICurve::FROM_PLUS, ptS) ||
! vCrvStepsToFill[i+1]->GetPointD1D2( dUS_ref, ICurve::FROM_MINUS, ptE))
! vCrvStepsToFill[i+1]->GetPointD1D2( dUS_ref, ICurve::FROM_MINUS, ptE))
return false ;
dRadius = Dist( ptS, ptE) ; // uso come raggio la distanza tra i due punti
// NB. Due curve non è detto che siano raccordabili con una circonferenza ai parametri stabiliti
// -> cerco di stare vicino a tale quantità
int nMaxTestForArcs = 3 ; // tentativi per creare l'arco
int nIterForArcs = 0 ;
@@ -8223,21 +8293,25 @@ Pocketing::ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, doubl
// controllo che l'arco creato non sia troppo piccolo
double dArcLen ;
if ( ! IsNull( pCrvArc) && pCrvArc->IsValid() && (! pCrvArc->GetLength( dArcLen) || dArcLen < 5 * EPS_SMALL)) {
if ( ! IsNull( pCrvArc) && pCrvArc->IsValid() &&
( ! pCrvArc->GetLength( dArcLen) || dArcLen < 5 * EPS_SMALL)) {
vCrvArcs.emplace_back( Release( pCrvArc)) ; // arco nullo
vArcsToJump.push_back( i) ; // da scartare
continue ;
}
if ( i != 0 && vArcsToJump[i-1] == -1 && ! IsNull( pCrvArc) && pCrvArc->IsValid()) { // dal secondo arco in poi controllo che non ci siano intersezioni tra essi
// dal secondo arco in poi di raccordo controllo che non ci siano intersezioni tra essi
if ( i != 0 && vArcsToJump[i-1] == -1 && ! IsNull( pCrvArc) && pCrvArc->IsValid()) {
IntersCurveCurve intCCH( *pCrvArc, *vCrvArcs[i-1]) ;
if ( intCCH.GetIntersCount() > 0 )
IntersBTWArcs = true ;
}
// se ho intersezioni tra archi o l'arco creato non è valido, allora provo altre nMaxTestForArcs volte a ricrearlo avvicinando i punti
// se ho intersezioni tra archi o l'arco creato non è valido, allora provo altre
// nMaxTestForArcs volte a ricrearlo avvicinando i punti
while (( IsNull( pCrvArc) || IntersBTWArcs) && nIterForArcs < nMaxTestForArcs) {
// aggiorno i parametri di riferimento ( mi avvicino sempre della metà)
dUE_ref = ( 1 + dUE_ref ) * 0.5 ;
dUS_ref = dUS_ref * 0.5 ;
@@ -8248,8 +8322,16 @@ Pocketing::ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, doubl
dRadius = Dist( ptS, ptE) ;
pCrvArc.Set( CreateFillet( *vCrvStepsToFill[i], ptS, *vCrvStepsToFill[i+1], ptE, Z_AX, dRadius, dPar1, dPar2)) ;
nIterForArcs++ ;
++ nIterForArcs;
// controllo ancora lunghezza ed intersezioni
double dArcLen ;
if ( ! IsNull( pCrvArc) && pCrvArc->IsValid() &&
( ! pCrvArc->GetLength( dArcLen) || dArcLen < 5 * EPS_SMALL)) {
vCrvArcs.emplace_back( Release( pCrvArc)) ; // arco nullo
vArcsToJump.push_back( i) ; // da scartare
continue ;
}
IntersBTWArcs = false ;
if ( i != 0 && vArcsToJump[i-1] == -1 && ! IsNull( pCrvArc) && pCrvArc->IsValid()) { // dal secondo arco in poi controllo che non ci siano intersezioni tra essi
IntersCurveCurve intCCH( *pCrvArc, *vCrvArcs[i-1]) ;
@@ -8258,7 +8340,9 @@ Pocketing::ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, doubl
}
}
if ( IsNull( pCrvArc) || ! pCrvArc->IsValid()) { // se ancora non riesco... salto l'arco
// se ancora non valido... salto l'arco
if ( IsNull( pCrvArc) || ! pCrvArc->IsValid()) {
vCrvArcs.emplace_back( CreateCurveArc()) ; // arco nullo
vArcsToJump.push_back( i) ; // da scartare
continue ;
@@ -8360,8 +8444,8 @@ Pocketing::ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, doubl
//----------------------------------------------------------------------------
bool
Pocketing::CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, ICRVCOMPOPOVECTOR& vOffsCL,
ICRVCOMPOPOVECTOR& vFirstOffset, ICurveComposite* pCrvLink, double dLenPercS,
Pocketing::CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, const ICRVCOMPOPOVECTOR& vOffsCL,
const ICRVCOMPOPOVECTOR& vFirstOffset, ICurveComposite* pCrvLink, double dLenPercS,
double dLenPercE, int nMaxIter)
{
// controllo i parametri
@@ -8373,7 +8457,7 @@ Pocketing::CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, IC
if ( IsNull( ptCrvFinal))
return false ;
// Prendo i punti, i vettori tangenti e i parametri di essi per le curve
// Prendo i punti, i vettori tangenti e i parametri di essi per le curve
Point3d ptSS, ptSE, ptES, ptEE ;
Vector3d vS, vE ;
double dUSS, dUSE, dUES, dUEE, dLenS, dLenE ;
@@ -9425,7 +9509,8 @@ Pocketing::RemoveExtraPartByMedialAxis( const ISurfFlatRegion* pChunkToCut, ICRV
//----------------------------------------------------------------------------
bool
Pocketing::CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, ICRVCOMPOPOVECTOR& vOffIslands, ICurveComposite* pCrvLink)
Pocketing::CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, const ICRVCOMPOPOVECTOR& vOffIslands,
ICurveComposite* pCrvLink)
{
pCrvLink->Clear() ;
@@ -9491,8 +9576,9 @@ Pocketing::CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, ICRVCO
PtrOwner<ICurve> pCrvA( GetCurve( vOffIslands[i]->CopyParamRange( dOffS, dOffE))) ;
PtrOwner<ICurve> pCrvB( GetCurve( vOffIslands[i]->CopyParamRange( dOffE, dOffS))) ;
if ( IsNull( pCrvA) || IsNull( pCrvB) )
if ( IsNull( pCrvA) || IsNull( pCrvB)) {
return false ;
}
double dLenA ; pCrvA->GetLength( dLenA) ;
double dLenB ; pCrvB->GetLength( dLenB) ;
if ( dLenA < dLenB ) {
@@ -9525,7 +9611,7 @@ Pocketing::CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, ICRVCO
//------------------------------------------------------------------------------
bool
Pocketing::CalcBoundedSmootedLink( const Point3d& ptStart, const Vector3d& vtStart, const Point3d& ptEnd,
const Vector3d& vtEnd, double dParMeet, ICRVCOMPOPOVECTOR& vOffIslands,
const Vector3d& vtEnd, const double dParMeet, const ICRVCOMPOPOVECTOR& vOffIslands,
ICurveComposite* pCrvLink)
{
// creo il BiArc che unisce i due punti
@@ -9551,7 +9637,14 @@ Pocketing::CalcBoundedSmootedLink( const Point3d& ptStart, const Vector3d& vtSta
if ( SqDist( ptStart, ptEnd) > 25 * ( GetSideStep() + m_TParams.m_dDiam * m_TParams.m_dDiam)) {
Point3d ptS_shift = ptStart + ( m_TParams.m_dDiam / 2) * vtStart ;
Point3d ptE_shift = ptEnd - ( m_TParams.m_dDiam / 2) * vtEnd ;
if ( ! CalcBoundedLink( ptS_shift, ptE_shift, vOffIslands, pCrvLink))
// controllo che tali punti siano effettivamente interni alla regione da svuotare
bool bOk = true ;
for ( int i = 0 ; i < int( vOffIslands.size()) && bOk ; ++ i) {
PolyLine PL ; vOffIslands[i]->ApproxWithLines( EPS_SMALL, EPS_ANG_SMALL, ICurve::APL_STD, PL) ;
bOk = IsPointInsidePolyLine( ptS_shift, PL, EPS_SMALL) ||
IsPointInsidePolyLine( ptE_shift, PL, EPS_SMALL) ;
}
if ( ! CalcBoundedLink( bOk ? ptS_shift : ptStart, bOk ? ptE_shift : ptEnd, vOffIslands, pCrvLink))
return false ;
pCrvLink->AddLine( ptStart, false) ;
pCrvLink->AddLine( ptEnd, true) ;
@@ -9601,8 +9694,9 @@ Pocketing::CalcBoundedSmootedLink( const Point3d& ptStart, const Vector3d& vtSta
PtrOwner<ICurve> pCrvA( GetCurve( vOffIslands[i]->CopyParamRange( dOffS, dOffE))) ;
PtrOwner<ICurve> pCrvB( GetCurve( vOffIslands[i]->CopyParamRange( dOffE, dOffS))) ;
if ( IsNull( pCrvA) || IsNull( pCrvB))
if ( IsNull( pCrvA) || IsNull( pCrvB)) {
return CalcBoundedLink( ptStart, ptEnd, vOffIslands, pCrvLink) ;
}
double dLenA ; pCrvA->GetLength( dLenA) ;
double dLenB ; pCrvB->GetLength( dLenB) ;
@@ -10882,7 +10976,7 @@ Pocketing::AdjustContourWithOpenEdges( ICurveComposite* pCrvCompo, ICRVCOMPOPOVE
// 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) ;
// aggiungo la curva ricavata
// aggiungo la curva ricavata ( se chiusa -> la copio, se aperta -> copio l'estesa)
if ( ! pCrvCompo_final->AddCurve( vpCrvs[i]->Clone())) {
Point3d ptH ; vpCrvs[i]->GetStartPoint( ptH) ;
if ( ! pCrvCompo_final->AddLine( ptH) ||
@@ -10935,11 +11029,10 @@ Pocketing::AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVE
! CreateSurfFrIncidence( pCrvBorder, dRad, pSfrInc))
return false ;
// creo un vettore con tutte le curve che potrebbero cadere in parte nella regione di incidenza
// creo un vettore con tutte le curve che potrebbero cadere, in parte, nella regione di incidenza
ICRVCOMPOPOVECTOR vCrvToCheck ;
for ( int i = 0 ; i < ( int)vCrvIsland.size() ; ++ i)
vCrvToCheck.emplace_back( vCrvIsland[i]->Clone()) ; // aggiungo le isole
// se la curva originale non è tutta Aperta -> devo aggiungere anche essa nelle curve da controllare
bool bIsAllOpen = abs( abs( dParE - dParS) - pCrvCompo->GetCurveCount()) < EPS_SMALL ;
if ( ! bIsAllOpen) {
@@ -10947,45 +11040,50 @@ Pocketing::AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVE
PtrOwner<ICurveComposite> pCompoOther( ConvertCurveToComposite( pCrvCompo->CopyParamRange( dParE, dParS))) ;
if ( IsNull( pCompoOther) || ! pCompoOther->IsValid())
return false ;
vCrvToCheck.emplace_back( Release( pCompoOther)) ;
vCrvToCheck.emplace_back( Release( pCompoOther)) ; // aggiungo il bordo
}
// scorro il vettore creato...
for ( int c = 0 ; c < ( int)vCrvToCheck.size() ; ++ c) {
for ( int c = 0 ; c < int( vCrvToCheck.size()) ; ++ c) {
// 1) recupero la curva corrente
PtrOwner<ICurveComposite> pCrvCurr( CloneCurveComposite( vCrvToCheck[c])) ;
if ( IsNull( pCrvCurr) || ! pCrvCurr->IsValid())
return false ;
// 2) ricavo i tratti con proprietà uniformi ( Aperti/Chiusi )
ICRVCOMPOPOVECTOR vpCrvs ;
if ( ! GetHomogeneousParts( pCrvCurr, vpCrvs))
return false ;
// 5) considero solo i tratti chiusi
// 3) considero solo i tratti chiusi
for ( int cl = 0 ; cl < int( vpCrvs.size()) ; ++ cl) {
if ( vpCrvs[cl]->GetTempProp() == 1)
continue ;
// 6) effettuo l'Offset della curva di metà dDiamJ
// 4) effettuo l'Offset della curva di metà dDiamJ
OffsetCurve OffsCrv ;
if ( ! OffsCrv.Make( vpCrvs[cl], - dDiamJ * 0.5, ICurve::OFF_FILLET)) {
m_pMchMgr->SetLastError( 2412, "Error in Pocketing : Offset not computable") ;
return false ;
}
// 7) scorro tutte le curve di Offset che si sono formate, prendendo sempre la più lunga tra le rimanenti
// 5) scorro tutte le curve di Offset che si sono formate, prendendo sempre la più lunga tra le rimanenti
PtrOwner<ICurve> pOffLongestCrv( OffsCrv.GetLongerCurve()) ;
while ( ! IsNull( pOffLongestCrv)) {
// 8) tengo solo le curve che non si chiudono su loro stesse
if ( ! pOffLongestCrv->IsClosed()) {
// 9) creo la regione di incidenza di tale curva ( "Curva a fagiolo")
PtrOwner<ISurfFlatRegion> pSfrBean( GetSurfFlatRegionFromFatCurve( Release( pOffLongestCrv), dDiamJ * 0.5, false, false)) ;
if ( IsNull( pSfrBean) || ! pSfrBean->IsValid())
return false ;
// inverto se necessario
if ( AreOppositeVectorApprox( pSfrBean->GetNormVersor(), pSfrInc->GetNormVersor()))
pSfrBean->Invert() ;
// 10) aggiorno la regione di incidenza
// 6) creo la regione di incidenza di tale curva ( "Curva a fagiolo")
PtrOwner<ISurfFlatRegion> pSfrBean( GetSurfFlatRegionFromFatCurve( Release( pOffLongestCrv), dDiamJ * 0.5, false, false)) ;
if ( IsNull( pSfrBean) || ! pSfrBean->IsValid())
return false ;
// inverto se necessario
if ( AreOppositeVectorApprox( pSfrBean->GetNormVersor(), pSfrInc->GetNormVersor()))
pSfrBean->Invert() ;
// 7) se la "Regione a fagiolo" non influenza la regione di incidenza, la transcuro
bool bDiscard = true ;
for ( int cI = 0 ; cI < pSfrInc->GetChunkCount() && bDiscard ; ++ cI)
for ( int cB = 0 ; cB < pSfrBean->GetChunkCount() && bDiscard ; ++ cB)
bDiscard = ( pSfrInc->GetChunkSimpleClassification( cI, *pSfrBean, cB) != REGC_INTERS) ;
if ( ! bDiscard) {
// 8) aggiorno la regione di incidenza
if ( ! pSfrInc->Add( *pSfrBean))
return false ;
}
pOffLongestCrv.Set( OffsCrv.GetLongerCurve()) ;
pOffLongestCrv.Set( OffsCrv.GetLongerCurve()) ; // passo al tratto offsettato successivo
}
}
}
@@ -10999,39 +11097,46 @@ Pocketing::AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVE
return false ;
// può capitare che la regione Limite mi crei più Chunk sulla pSfrInc
// I chunk da togliere sono tutti quelli che si sono separati dalla pCrvBorder
if ( pSfrInc->GetChunkCount() > 1) {
// NB. Il mio obiettivo è quello di avere un'unica curva con estremi i due tratti aperti estremanti
if ( pSfrInc->GetChunkCount() > 1) { // se ottengo più chunks
PtrOwner<ISurfFlatRegion> pNewSfrInc( CreateSurfFlatRegion()) ;
if ( IsNull( pNewSfrInc))
return false ;
// ricavo i punti iniziali e finali della curva di bordo
Point3d ptS, ptE ;
if ( ! pCrvBorder->GetStartPoint( ptS) || ! pCrvBorder->GetEndPoint( ptE))
return false ;
// per ogni Chunk ( > 1 )
for ( int i = 0 ; i < pSfrInc->GetChunkCount() ; ++ i) {
// bordo esterno
PtrOwner<ICurveComposite> pCrvEL( ConvertCurveToComposite( pSfrInc->GetLoop( i, 0))) ;
if ( IsNull( pCrvEL) || ! pCrvEL->IsValid())
return false ;
// se estremi in comune, la curva cercata è la seguente
if ( pCrvEL->IsPointOn( ptS, 300 * EPS_SMALL) && pCrvEL->IsPointOn( ptE, 300 * EPS_SMALL)) {
if ( ! pNewSfrInc->IsValid())
pNewSfrInc.Set( pSfrInc->CloneChunk( i)) ;
else
if ( ! pNewSfrInc->Add( * pSfrInc->CloneChunk( i)))
if ( ! pNewSfrInc->IsValid()) // se la nuova regione di incidenza è vuota...
pNewSfrInc.Set( pSfrInc->CloneChunk( i)) ; // aggiorno....
else // se la nuova regione di incidenza non è vuota...
if ( ! pNewSfrInc->Add( * pSfrInc->CloneChunk( i))) // aggiungo...
return false ;
}
}
// definisco quinfi la nuova regione di incidenza
if ( ! pNewSfrInc->IsValid())
return false ;
pSfrInc.Set( Release( pNewSfrInc)) ;
}
}
// controllo se la curva è un'isola
// controllo se la curva è un'isola ( dall'area )
bool bIsIsland = false ;
double dArea ; Plane3d plCheck ;
if ( ! pCrvCompo->GetArea( plCheck, dArea))
return false ;
bIsIsland = AreSameVectorEpsilon( plCheck.GetVersN(), - Z_AX, 10 * EPS_SMALL) ;
// recupero la curva di bordo del lato aperto corrente
// dalla regione di incidenza devo estrarre il tratto di bordo che ha per estremi i lati chiusi
// ( stando al di fuori, quindi estendendomi all'esterno, della regione da svuotare )
PtrOwner<ICurveComposite> pCrvNewBorder( ConvertCurveToComposite( pSfrInc->GetLoop( 0, 0))) ;
if ( IsNull( pCrvNewBorder) || ! pCrvNewBorder->IsValid())
return false ;
@@ -11039,7 +11144,7 @@ Pocketing::AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVE
for ( int u = 0 ; u < pCrvNewBorder->GetCurveCount() ; ++ u)
pCrvNewBorder->SetCurveTempProp( u, 1, 0) ;
// se la curva originale era tutta aperta...
// se la curva originale era tutta aperta... ( il nuovo lato è il loop esterno della regione di incidenza)
if ( bIsAllOpen) {
// pulisco la curva originale
pCrvBorder->Clear() ;
@@ -11089,14 +11194,16 @@ Pocketing::CreateSurfFrIncidence( const ICurveComposite* pCrv, const double dRad
return false ;
pSfrInc->CopyFrom( pSfrInc_tmp) ; // pSfrInc ha sempre normale Z_AX !
// La regione di incidenza non deve avere un bordo distante dRad dagli estremi del tratto aperto
// per questo motivo, creo due FlatRegion a rettangolo che andrò a sottrarre alla pSfrInc_tmp
if ( pCrv->IsClosed()) {
// se la curva è chiusa, allora tutto il bordo è aperto
if ( pCrv->IsClosed()) {
pSfrInc->CopyFrom( pSfrInc_tmp) ;
return pSfrInc->IsValid() && pSfrInc->GetChunkCount() > 0 ;
}
// La regione di incidenza non deve avere un bordo distante dRad dagli estremi del tratto aperto
// per questo motivo, creo due FlatRegion a rettangolo che andrò a sottrarre alla pSfrInc_tmp
// ( tolgo i semi-dischi agli estremi )
// Rettangolo all'inizio
Vector3d vtTanS ; pCrv->GetStartDir( vtTanS) ;
Point3d ptS ; pCrv->GetStartPoint( ptS) ;
+9 -5
View File
@@ -195,6 +195,8 @@ class Pocketing : public Machining
bool vbChangedPrec, bool& bOptimizedTrap) ;
bool CheckIfOffsetIsNecessary( const ICurveComposite* pCrvOffs, const double dOffs, const int nIter,
const int nOffsCount, const Vector3d& vtN, bool& bInsert) ;
bool CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks,
const ICRVCOMPOPOVECTOR& vOffsClosedCurves, const ICRVCOMPOPOVECTOR& vOffsFirstCurve) ;
bool GetUnclearedRegion( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& vCrvs, ICURVEPOVECTOR& vLinks,
const ICurveComposite* pCrv_orig, ISurfFlatRegion* pSrfToCut) ;
bool GetDynamicClearedRegion( ISurfFlatRegion* pSrfPrec, const ICurveComposite* pCrv) ;
@@ -215,14 +217,16 @@ class Pocketing : public Machining
ICurveComposite* pPath2, ICRVCOMPOPOVECTOR& vOffsCL) ;
bool GetCurveWeightInfo( const ICurveComposite* pCrvCompo, double dMaxLen, double& dToTRot, int& nSmallArcs, int& nSmallLines) ;
bool ChoosePath( const ICurveComposite* pCrv1, const ICurveComposite* pCrv2, int nP, double dPerP, double dMaxLen, int& nC) ;
bool CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, ICRVCOMPOPOVECTOR& vOffIslands,
bool CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, const ICRVCOMPOPOVECTOR& vOffIslands,
ICurveComposite* pCrvLink) ;
bool CalcBoundedSmootedLink( const Point3d& ptStart, const Vector3d& vtStart, const Point3d& ptEnd, const Vector3d& vtEnd, double dParMeet,
ICRVCOMPOPOVECTOR& vOffIslands, ICurveComposite* pCrvLink) ;
bool CalcBoundedSmootedLink( const Point3d& ptStart, const Vector3d& vtStart, const Point3d& ptEnd,
const Vector3d& vtEnd, const double dParMeet,
const ICRVCOMPOPOVECTOR& vOffIslands, ICurveComposite* pCrvLink) ;
bool ModifyBiArc( ICurve* pCrvBiArc, double dCutToll, ICurveComposite* pNewCrv) ;
bool CutCurveByOffsets( ICurveComposite* pCurve, ICRVCOMPOPOVECTOR& vOffs) ;
bool CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, ICRVCOMPOPOVECTOR& vOffs, ICRVCOMPOPOVECTOR& vOffIslands,
ICurveComposite* pCrvLink, double dLenPercS = 0.01, double dLenPercE = 0.01, int nMaxIter = 2) ;
bool CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, const ICRVCOMPOPOVECTOR& vOffs,
const ICRVCOMPOPOVECTOR& vOffIslands, ICurveComposite* pCrvLink,
double dLenPercS = 0.01, double dLenPercE = 0.01, int nMaxIter = 2) ;
bool CalcBoundedLinkWithBiArcs( const Point3d& ptStart, const Vector3d& vtStart, const Point3d& ptEnd, const Vector3d& vtEnd,
const ICurve* pCrvBound, ICurveComposite* pCrvLink) ;
bool CalcCircleSpiral( const Point3d& ptCen, const Vector3d& vtN, double dOutRad, double dIntRad,