From 7e286c1c8e2ccc350287eb355487a73e9f79d954 Mon Sep 17 00:00:00 2001 From: SaraP Date: Fri, 21 May 2021 14:51:29 +0200 Subject: [PATCH] EgtMachKernel : - svuotatura nel caso di materiale residuo negli angoli, nuova implementazione. --- Pocketing.cpp | 329 +++++++++++++++++++++++++++++++++++++------------- Pocketing.h | 4 + 2 files changed, 249 insertions(+), 84 deletions(-) diff --git a/Pocketing.cpp b/Pocketing.cpp index 0a58f6a..55dab33 100644 --- a/Pocketing.cpp +++ b/Pocketing.cpp @@ -3118,6 +3118,9 @@ bool Pocketing::CalcSpiral( const ICurveComposite* pCompo, int nReg, bool bSplitArcs, ICurveComposite* pMCrv, ICurveComposite* pRCrv) { + ISurfFlatRegion * pCutRegion = CreateSurfFlatRegion() ; // regione lavorata + bool bFirst = false ; + // inizializzo i risultati pMCrv->Clear() ; pRCrv->Clear() ; @@ -3144,14 +3147,15 @@ Pocketing::CalcSpiral( const ICurveComposite* pCompo, int nReg, bool bSplitArcs, const int MAX_ITER = 1000 ; int nIter = 0 ; ICURVEPOVECTOR vOffs ; - ICURVEPOVECTOR vCrvStack ; - DBLVECTOR vOffsValStack ; // valori dell'offset con cui sono state calcolate le cruve in vCrvStack + ICURVEPOVECTOR vCrvStack ; DBLVECTOR vRadStack ; PtrOwner pOffs ; - double dOffsVal ; // valore dell'offset con cui è stato calcolato pOffs double dCurrRad = GetCurveRadius( pCompo) ; - - while ( nIter < MAX_ITER) { + + Vector3d vtExtr ; + pCompo->GetExtrusion( vtExtr) ; + + while ( nIter < MAX_ITER) { // calcolo OffsetCurve OffsCrv ; if ( ! OffsCrv.Make( ( nIter == 0 ? (ICurve*) pCompo : pOffs), - dOffs, ICurve::OFF_FILLET) || @@ -3169,7 +3173,6 @@ Pocketing::CalcSpiral( const ICurveComposite* pCompo, int nReg, bool bSplitArcs, while ( pCrv != nullptr) { if ( nIter != 0 || nReg == nCount) { vCrvStack.emplace_back( pCrv) ; - vOffsValStack.emplace_back( dOffs) ; vRadStack.emplace_back( dCurrRad) ; if ( nIter == 0) break ; @@ -3181,98 +3184,54 @@ Pocketing::CalcSpiral( const ICurveComposite* pCompo, int nReg, bool bSplitArcs, } // recupero la prossima curva di offset se ho ottenuto un offset valido oppure ho fallito ma non è ulteriormente riducibile PtrOwner pNextOffs ; - double dNextOffsVal ; if ( ! vCrvStack.empty() && ( bOffsOk || dOffs < dTRad + EPS_ZERO)) { pNextOffs.Set( Release( vCrvStack.back())) ; - dNextOffsVal = vOffsValStack.back() ; vCrvStack.pop_back() ; - vOffsValStack.pop_back() ; dCurrRad = vRadStack.back() ; vRadStack.pop_back() ; } - // analizzo pOffs per aggiungere tratti lineari in corrispondenza degli angoli critici - PtrOwner pNewOffs ; // curva con tratti aggiuntivi - if ( nIter > 1) - pNewOffs.Set( CreateCurveComposite()) ; - else if ( ! IsNull( pOffs)) - pNewOffs.Set( pOffs->Clone()) ; - - if ( ! IsNull( pOffs) && nIter > 1) { - - double dOverlap = 1 - dOffsVal / m_TParams.m_dDiam ; - double dSharpSin = 1 - 2 * dOverlap ; // valore critico - - const ICurve * pCrv = pOffs->GetFirstCurve() ; - while ( pCrv != nullptr) { - - pNewOffs->AddCurve( pCrv->Clone()) ; - - // curva successiva - const ICurve * pCrvNext = pOffs->GetNextCurve() ; - if ( pCrvNext == nullptr) { - pCrvNext = pOffs->GetFirstCurve() ; - pOffs->GetLastCurve() ; - } - else - pOffs->GetPrevCurve() ; - - // angolo fra le curve - Vector3d vtS, vtE ; - Point3d ptVertex ; - pCrv->GetEndPoint( ptVertex) ; - pCrv->GetEndDir( vtE) ; - pCrvNext->GetStartDir( vtS) ; - vtS.Normalize() ; - vtE.Normalize() ; - vtS.Invert() ; - double dCosAng = vtS * vtE ; - double dAngSin = sqrt( (1 - dCosAng) / 2) ; - - // se angolo critico - if ( dAngSin < dSharpSin) { - - double dLen = ( m_TParams.m_dDiam / 2 - m_TParams.m_dDiam * dOverlap) / dAngSin - m_TParams.m_dDiam / 2 ; - - Vector3d vtDir = vtE ; - double dCosRot = sqrt( ( 1 + dCosAng) / 2) ; - double dSinRot = sqrt( ( 1 - dCosAng) / 2) ; - vtDir.Rotate( vtE ^ vtS, dCosRot, dSinRot) ; - vtDir.Normalize() ; - - Point3d ptNew = ptVertex + dLen * vtDir ; - - // curva da aggiungere - PtrOwner pAddCrv ; - pAddCrv.Set( CreateCurveComposite()) ; - pAddCrv->AddPoint( ptVertex) ; - pAddCrv->AddLine( ptNew) ; - pAddCrv->AddLine( ptVertex) ; - - pNewOffs->AddCurve( Release( pAddCrv)) ; - } - - pCrv = pOffs->GetNextCurve() ; - } - } - double dRad = GetCurveRadius( pNextOffs) ; bool bNextOk = ( dRad > EPS_ZERO && dRad < dCurrRad) ; bool bSmallRad = ( nIter == 0 ? dOffs < dTRad + GetOffsR() + EPS_ZERO : dOffs < dTRad + EPS_ZERO) ; // se completato step di offset, accodo la curva offsettata al percorso di lavoro - if ( ! IsNull( pNewOffs) && ( bNextOk || bSmallRad)) { + + if ( ! IsNull( pOffs) && ( bNextOk || bSmallRad)) { + + // Superficie coperta dal tool quando percorre quell'offset ( senza tener conto delle parti aggiuntive) + ICurve * pCrvTmp = pOffs->Clone() ; + OffsetCurve OffsCrv2 ; + OffsCrv2.Make( pCrvTmp, m_TParams.m_dDiam/2, ICurve::OFF_FILLET) ; + ICurve * pCrvOff = OffsCrv2.GetLongerCurve() ; + ISurfFlatRegion * pSrf = CreateSurfFlatRegion() ; + pSrf->AddExtLoop( pCrvOff) ; + OffsetCurve OffsCrv3 ; + OffsCrv3.Make( pCrvTmp, - m_TParams.m_dDiam/2, ICurve::OFF_FILLET) ; + ICurve * pCrvOff3 = OffsCrv3.GetLongerCurve() ; + while ( pCrvOff3 != nullptr) { + pSrf->AddIntLoop( pCrvOff3) ; + pCrvOff3 = OffsCrv3.GetCurve() ; + } + if ( ! bFirst) { + bFirst = true ; + pCutRegion = pSrf->Clone() ; + } + else { + pCutRegion->Add( *(pSrf->Clone())) ; + } + // inserisco l'offset nel vettore - vOffs.emplace_back( Release( pNewOffs)) ; + vOffs.emplace_back( Release( pOffs)) ; + } // se offset va bene if ( bNextOk) { - // sistemo per prossimo step + // sistemo per prossimo step dCurrRad = dRad ; pOffs.Set( GetCurveComposite( Release( pNextOffs))) ; - dOffsVal = dNextOffsVal ; // nuovo valore pari allo step - dOffs = GetSideStep() ; + dOffs = GetSideStep() ; } // se altrimenti riducibile, provo con offset ridotto al raggio utensile else if ( ! bSmallRad) { @@ -3296,8 +3255,35 @@ Pocketing::CalcSpiral( const ICurveComposite* pCompo, int nReg, bool bSplitArcs, vOffs[i]->GetStartPoint( ptEnd) ; // calcolo il collegamento (garantendo che non esca dalla svuotatura) PtrOwner pCrvLink( CreateCurveComposite()) ; - if ( CalcBoundedLink( ptStart, ptEnd, vOffs[0], pCrvLink)) + if ( CalcBoundedLink( ptStart, ptEnd, vOffs[0], pCrvLink)) { + + // Superficie coperta dal tool quando percorre il collegamento + pCrvLink->SetExtrusion( vtExtr) ; + const ICurve * pCrvTmp = pCrvLink->GetFirstCurve() ; + while ( pCrvTmp != nullptr) { + if ( pCrvTmp->GetType() == CRV_LINE) { + Point3d ptS, ptE ; + pCrvTmp->GetStartPoint( ptS) ; + pCrvTmp->GetEndPoint( ptE) ; + ICurveComposite * Crv2 = CreateCurveComposite() ; + Crv2->AddPoint( ptS) ; + Crv2->AddLine( ptE) ; + Crv2->AddLine( ptS) ; + Crv2->SetExtrusion( vtExtr) ; + OffsetCurve OffsCrvPlus ; + OffsCrvPlus.Make( Crv2, m_TParams.m_dDiam/2, ICurve::OFF_FILLET) ; + ICurve * pCrvOffPlus = OffsCrvPlus.GetLongerCurve() ; + + ISurfFlatRegion * pSrf = CreateSurfFlatRegion() ; + pSrf->AddExtLoop( pCrvOffPlus) ; + pCutRegion->Add( *(pSrf->Clone())) ; + } + pCrvTmp = pCrvLink->GetNextCurve() ; + } + + // Aggiungo il collegamento vLinks[i].Set( Release( pCrvLink)) ; + } else { m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; return false ; @@ -3316,7 +3302,7 @@ Pocketing::CalcSpiral( const ICurveComposite* pCompo, int nReg, bool bSplitArcs, if ( CalcBoundedLink( ptStart, ptEnd, vOffs[0], pCrvLink)) { pRCrv->AddCurve( Release( pCrvLink)) ; pRCrv->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, false) ; - // se necessario, approssimo archi con rette + // se necessario, approssimo archi con rette if ( bSplitArcs && ! ApproxWithLines( pRCrv)) { m_pMchMgr->SetLastError( 2421, "Error in Pocketing : Linear Approx not computable") ; return false ; @@ -3329,6 +3315,10 @@ Pocketing::CalcSpiral( const ICurveComposite* pCompo, int nReg, bool bSplitArcs, } } + // Verifico la presenza di aree non lavorate + if ( pCutRegion->GetLoopCount( 0) > 1 && ! RemoveUncutRegions( pCutRegion, vOffs)) + return false ; + // creo il percorso di lavoro a partire dalla raccolta degli offset e dei collegamenti for ( int i = 0 ; i < int( vOffs.size()) ; ++ i) { // se collegamento da aggiungere @@ -3339,8 +3329,8 @@ Pocketing::CalcSpiral( const ICurveComposite* pCompo, int nReg, bool bSplitArcs, // se richiesta percorrenza invertita if ( m_Params.m_bInvert) vOffs[i]->Invert() ; - // aggiungo la curva - pMCrv->AddCurve( Release( vOffs[i])) ; + // aggiungo la curva + pMCrv->AddCurve( Release( vOffs[i])) ; } // verifico il percorso di lavoro @@ -3348,7 +3338,7 @@ Pocketing::CalcSpiral( const ICurveComposite* pCompo, int nReg, bool bSplitArcs, m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; return false ; } - // se necessario, approssimo archi con rette + // se necessario, approssimo archi con rette if ( bSplitArcs && ! ApproxWithLines( pMCrv)) { m_pMchMgr->SetLastError( 2421, "Error in Pocketing : Linear Approx not computable") ; return false ; @@ -4183,3 +4173,174 @@ Pocketing::VerifyLeadInZigZag( const ICurveComposite* pCompo, const Point3d& ptP return false ; return ( dMinDistPa > 0.5 * m_TParams.m_dDiam - 10 * EPS_SMALL && dMinDistPb > 0.5 * m_TParams.m_dDiam - 10 * EPS_SMALL) ; } + +//---------------------------------------------------------------------------- +bool +Pocketing::RemoveUncutRegions( const ISurfFlatRegion * pSTot, ICURVEPOVECTOR& vOffs) +{ + // Conservo le curve vOffs originali in vettore Tmp da usare per i calcoli sui percorsi aggiuntivi + ICRVCOMPOPOVECTOR vOffsTmp( vOffs.size()) ; + for ( size_t i = 0 ; i < vOffs.size(); i++) + vOffsTmp[i].Set( GetCurveComposite( vOffs[i]->Clone())) ; + + Vector3d vtExtr ; + vOffs[0]->GetExtrusion( vtExtr) ; + + // Analizzo tutte le aree non lavorate + int nLoops = pSTot->GetLoopCount(0) ; + for ( size_t i = 1 ; i < nLoops ; i++) { + + // Regione non lavorata + ICurveComposite * pResidualCrv = GetCurveComposite( pSTot->GetLoop( 0, i)) ; + ISurfFlatRegion * pResidualSrf = CreateSurfFlatRegion() ; + pResidualCrv->Invert() ; + bool bAdd = pResidualSrf->AddExtLoop( pResidualCrv->Clone()) ; + + // cerco la curva di vOffs su cui andrà il pezzo aggiuntivo e il punto in cui aggiungerlo + size_t idx ; + Point3d ptCrit, ptCen ; + if ( ! FindCurveForPathAdd( pResidualCrv, vOffs, idx, ptCrit)) + return false ; + + pResidualCrv->GetCentroid( ptCen) ; + + // Se ho angolo calcolo la lunghezza del primo tratto da aggiungere basandomi sull'angolo e sull'overlap + Point3d ptNew ; + bool bUsePtNew = false ; + double dParTmp ; + vOffsTmp[idx]->GetParamAtPoint( ptCrit, dParTmp) ; + // se sono su un vertice + if ( vOffsTmp[idx]->IsParamAtJoint( dParTmp)) { + const ICurve* pCrv1 = dParTmp < EPS_SMALL ? vOffsTmp[idx]->GetLastCurve() : vOffsTmp[idx]->GetCurve( round( dParTmp) - 1) ; + const ICurve* pCrv2 = vOffsTmp[idx]->GetCurve( round( dParTmp)) ; + // se il vertice è l'intersezione di due linee + if ( pCrv1->GetType() == CRV_LINE && pCrv2->GetType() == CRV_LINE) { + // calcolo angolo formato dalle due linee + Vector3d vt1, vt2 ; + vOffsTmp[idx]->GetPointTang( dParTmp, ICurve::FROM_MINUS, Point3d(), vt1) ; + vOffsTmp[idx]->GetPointTang( dParTmp, ICurve::FROM_PLUS, Point3d(), vt2) ; + vt2.Invert() ; + double dCosAng = vt1 * vt2 ; + + // calcolo lunghezza + double dAngSin = sqrt( (1 - dCosAng) / 2) ; + double dOverlap = 1 - GetSideStep() / m_TParams.m_dDiam ; + double dLen = ( m_TParams.m_dDiam / 2 - m_TParams.m_dDiam * dOverlap) / dAngSin - m_TParams.m_dDiam / 2 ; + Vector3d vtDir = ptCen - ptCrit ; + vtDir.Normalize() ; + ptNew = ptCrit + dLen * vtDir ; + bUsePtNew = dLen > 0 ; + } + } + + // Percorso aggiuntivo + ICurveComposite * pAddPath = CreateCurveComposite() ; + pAddPath->AddPoint( ptCrit) ; + pAddPath->SetExtrusion( vtExtr) ; // setto estrusione corretta per farne offset + + if ( ! ComputeAdditionalPath( pAddPath, pResidualSrf, ptNew, bUsePtNew)) + return false ; + + // Nuova curva di offset con tratti aggiuntivi + PtrOwner pNewOffs ; + pNewOffs.Set( CreateCurveComposite()) ; + double dPar, dParS, dParE ; + vOffs[idx]->GetDomain( dParS, dParE) ; + vOffs[idx]->GetParamAtPoint( ptCrit, dPar) ; + pNewOffs->AddCurve( vOffs[idx]->CopyParamRange( dParS, dPar)) ; // fino al punto critico è il vecchio offset + pNewOffs->AddCurve( pAddPath->Clone()) ; // al punto critico aggiungo il nuovo percorso + if ( abs( dPar - dParS) > EPS_SMALL && abs( dPar - dParE) > EPS_SMALL) + pNewOffs->AddCurve( vOffs[idx]->CopyParamRange( dPar, dParE)) ; // aggiungo la parte rimanente del vecchio offset + + vOffs[idx].Set( Release( pNewOffs)) ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +Pocketing::FindCurveForPathAdd( const ICurveComposite * pCrv, const ICURVEPOVECTOR& vOffs, size_t& idxMin, Point3d& ptMinDist) +{ + idxMin = -1 ; + Point3d ptCen ; + pCrv->GetCentroid( ptCen) ; + double distMin = INFINITO ; + double dist ; + + for ( size_t i = 0 ; i < vOffs.size() ; i ++) { + // verifico se la regione da rimuovere ( pCrv) è esterna alla regione racchiusa da vOffs + ISurfFlatRegion * pSrf = CreateSurfFlatRegion() ; + pSrf->AddExtLoop( vOffs[i]->Clone()) ; + CRVCVECTOR ccClass ; + pSrf->GetCurveClassification( *pCrv, ccClass) ; + + if ( ccClass.size() != 1) + return false ; + + // se è esterna calcolo la sua distanza dal centro della regione da rimuovere + if ( ccClass[0].nClass == CRVC_OUT) { + DistPointCurve distPtCrv( ptCen, *(vOffs[i]->Clone())) ; + if ( distPtCrv.GetDist( dist) && dist < distMin) { + distMin = dist ; + idxMin = i ; + int nFlag ; + distPtCrv.GetMinDistPoint( 0, ptMinDist, nFlag) ; + } + } + } + + // se la regione da rimuovere ( pCrv) è interna a tutte le curve di offset errore + if ( idxMin == -1 ) + return false ; + + return true ; +} + + +//---------------------------------------------------------------------------- +bool +Pocketing::ComputeAdditionalPath( ICurveComposite * pAddPath, ISurfFlatRegion * pResidualSrf, Point3d ptNew, bool bUsePtNew) +{ + if ( ! bUsePtNew) + pResidualSrf->GetCentroid( ptNew) ; + + // Aggiungo il nuovo tratto al percorso + pAddPath->AddLine( ptNew) ; + + Vector3d vtExtr ; + pAddPath->GetExtrusion( vtExtr) ; + + // Area coperta dal nuovo pezzo aggiunto + ICurveComposite * pAddPathTmp = CreateCurveComposite() ; + Point3d ptS ; + pAddPath->GetStartPoint( ptS) ; + pAddPathTmp->AddPoint( ptS) ; + pAddPathTmp->AddLine( ptNew) ; + pAddPathTmp->AddLine( ptS) ; + pAddPathTmp->SetExtrusion( vtExtr) ; + OffsetCurve OffsCrv ; + OffsCrv.Make( pAddPathTmp, m_TParams.m_dDiam / 2, ICurve::OFF_FILLET) ; + ICurve * pCrvOffs = OffsCrv.GetLongerCurve() ; + ISurfFlatRegion * pToolSrf = CreateSurfFlatRegion() ; + pToolSrf->AddExtLoop( pCrvOffs) ; + + // Se tutta l'area è stata lavorata + if ( ! pResidualSrf->Subtract( *pToolSrf) || pResidualSrf == nullptr) { + pAddPath->AddLine( ptS) ; // percorso di ritorno + return true ; + } + + // Scorro tutte le regioni non lavorate rimaste + for ( size_t i = 0 ; i < pResidualSrf->GetChunkCount() ; i++) { + ICurveComposite * pNewAddPath = CreateCurveComposite() ; + pNewAddPath->SetExtrusion( vtExtr) ; + pNewAddPath->AddPoint( ptNew) ; + ComputeAdditionalPath( pNewAddPath, pResidualSrf->CloneChunk( i), ptNew, false) ; + pAddPath->AddCurve( pNewAddPath->Clone()) ; + } + + pAddPath->AddLine( ptS) ; // percorso di ritorno + + return true ; +} \ No newline at end of file diff --git a/Pocketing.h b/Pocketing.h index 89ec6e3..8290fd8 100644 --- a/Pocketing.h +++ b/Pocketing.h @@ -18,6 +18,7 @@ #include "ToolData.h" #include "/EgtDev/Include/EGkCurveComposite.h" #include "/EgtDev/Include/EgtNumUtils.h" +#include "/EgtDev/Include/EgkSurfFlatRegion.h" //---------------------------------------------------------------------------- class Pocketing : public Machining @@ -86,6 +87,9 @@ class Pocketing : public Machining double dDepth, double dElev, double dOkStep, bool bSplitArcs) ; bool CalcSpiral( const ICurveComposite* pCompo, int nReg, bool bSplitArcs, ICurveComposite* pMCrv, ICurveComposite* pRCrv) ; + bool RemoveUncutRegions( const ISurfFlatRegion * pSTot, ICURVEPOVECTOR& vOffs) ; + bool FindCurveForPathAdd( const ICurveComposite * pCrvLoop, const ICURVEPOVECTOR& vOffs, size_t& idxMin, Point3d& ptMinDist) ; + bool ComputeAdditionalPath( ICurveComposite * pAddPath, ISurfFlatRegion * pResidualSrf, Point3d ptNew, bool bUsePtNew) ; bool CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, const ICurve* pCrvBound, ICurveComposite* pCrvLink) ; bool CalcCircleSpiral( const Point3d& ptCen, const Vector3d& vtN, double dOutRad, double dIntRad,