EgtMachKernel :

- in Pocketing correzione errori nella rimozione delle regioni residue
- modifica nel calcolo dei percorsi aggiuntivi  (ci si basa sulle curve e non più sulle flat regions).
This commit is contained in:
SaraP
2021-06-11 16:08:14 +02:00
parent 01ee329431
commit 392a5305ec
2 changed files with 188 additions and 130 deletions
+186 -128
View File
@@ -35,6 +35,8 @@
#include "/EgtDev/Include/EGnStringKeyVal.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include "/EgtDev/Include/EgkStmFromCurves.h"
#include "/EgtDev/Include/EGkDistPointSurfTm.h"
using namespace std ;
@@ -3198,7 +3200,7 @@ Pocketing::CalcSpiral( const ICurveComposite* pCompo, int nReg, bool bSplitArcs,
if ( ! IsNull( pOffs) && ( bNextOk || bSmallRad)) {
// Superficie coperta dal tool quando percorre pOffs
// Superficie coperta dal tool quando percorre pOffs
OffsetCurve OffsCrvPlus ;
OffsCrvPlus.Make( pOffs, m_TParams.m_dDiam / 2 + 5 * EPS_SMALL, ICurve::OFF_FILLET) ;
ICurve * pCrvOffPlus = OffsCrvPlus.GetLongerCurve() ;
@@ -3210,17 +3212,18 @@ Pocketing::CalcSpiral( const ICurveComposite* pCompo, int nReg, bool bSplitArcs,
ICurveComposite * pCrvOffMinus = GetCurveComposite( OffsCrvMinus.GetLongerCurve()) ;
while ( pCrvOffMinus != nullptr) {
if ( GetCurveRadius( pCrvOffMinus) > EPS_ZERO)
pSrf->AddIntLoop( pCrvOffMinus) ;
pSrf->AddIntLoop( pCrvOffMinus) ;
pCrvOffMinus = GetCurveComposite( OffsCrvMinus.GetCurve()) ;
}
if ( bFirst) {
bFirst = false ;
pCutRegion = pSrf->Clone() ;
pCutRegion = pSrf->Clone() ;
}
else
pCutRegion->Add( *(pSrf->Clone())) ;
// inserisco l'offset nel vettore
// inserisco l'offset nel vettore
vOffs.emplace_back( Release( pOffs)) ;
}
@@ -3347,6 +3350,7 @@ Pocketing::CalcSpiral( const ICurveComposite* pCompo, int nReg, bool bSplitArcs,
// eventuale sistemazione archi
VerifyArcs( pMCrv) ;
int id = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCutRegion->Clone()) ;
m_pGeomDB->SetMaterial( id, Color(128,64,0,50)) ;
@@ -4181,45 +4185,43 @@ Pocketing::VerifyLeadInZigZag( const ICurveComposite* pCompo, const Point3d& ptP
//----------------------------------------------------------------------------
bool
Pocketing::RemoveUncutRegions( const ISurfFlatRegion * pSTot, ICURVEPOVECTOR& vOffs)
{
Pocketing::RemoveUncutRegions( const ISurfFlatRegion * pCutRegion, 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())) ;
vOffsTmp[i].Set( GetCurveComposite( vOffs[i]->Clone())) ;
// 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() ;
pResidualSrf->AddExtLoop( pResidualCrv->Clone()) ;
// verifico che area sia sufficientemente grande
double dArea ;
pResidualSrf->GetGrossArea( dArea) ;
if ( abs( dArea) < 10 * EPS_SMALL)
continue ;
ISurfFlatRegion * pNewCutRegion = pCutRegion->Clone() ;
bool bAddedPaths = false ;
// analizzo tutte le aree non lavorate
int nLoops = pCutRegion->GetLoopCount(0) ;
for ( int i = 1 ; i < nLoops ; i++) {
// regione non lavorata
ICurveComposite * pResidualCrv = GetCurveComposite( pCutRegion->GetLoop( 0, i)) ;
if ( pResidualCrv == nullptr || ! pResidualCrv->IsValid())
continue ;
// cerco la curva di vOffs su cui andrà il percorso aggiuntivo
size_t idx ; // indice della curva in vOffs
Point3d ptCrit ; // punto in cui aggiungere il percorso extra
double dParCrit ; // parametro corrispondente a ptCrit
size_t idx ; // indice della curva in vOffs
Point3d ptCrit ; // punto in cui aggiungere il percorso extra
double dParCrit ; // parametro corrispondente a ptCrit
if ( ! FindCurveForPathAdd( pResidualCrv, vOffsTmp, idx, ptCrit, dParCrit, vOffs[0]))
return false ;
// Calcolo la lunghezza del primo tratto da aggiungere basandomi sull'angolo e sull'overlap
if ( ! FindCurveForPathAdd( pResidualCrv, vOffsTmp, idx, ptCrit, dParCrit, vOffs[0]))
return false ;
// Calcolo la lunghezza del tratto da aggiungere basandomi sull'angolo e sull'overlap
Point3d ptNew ;
bool bUsePtNew = false ;
// se sono sul punto di congiunzione fra due curve
if ( vOffsTmp[idx]->IsParamAtJoint( dParCrit)) {
const ICurve* pCrv1 = dParCrit < EPS_SMALL ? vOffsTmp[idx]->GetLastCurve() : vOffsTmp[idx]->GetCurve( round( dParCrit) - 1) ;
const ICurve* pCrv2 = vOffsTmp[idx]->GetCurve( round( dParCrit)) ;
// se le due cruve sono due linee
const ICurve* pCrv1 = dParCrit < EPS_SMALL ? vOffsTmp[idx]->GetLastCurve() : vOffsTmp[idx]->GetCurve( int( dParCrit + 0.5) - 1) ;
const ICurve* pCrv2 = vOffsTmp[idx]->GetCurve( int( dParCrit + 0.5)) ;
// se le due curve sono due linee
if ( pCrv1->GetType() == CRV_LINE && pCrv2->GetType() == CRV_LINE) {
// calcolo angolo formato dalle due linee
Vector3d vt1, vt2 ;
@@ -4227,12 +4229,12 @@ Pocketing::RemoveUncutRegions( const ISurfFlatRegion * pSTot, ICURVEPOVECTOR& vO
vOffsTmp[idx]->GetPointTang( dParCrit, ICurve::FROM_PLUS, Point3d(), vt2) ;
vt2.Invert() ;
double dCosAng = vt1 * vt2 ;
// calcolo lunghezza basandomi sull'angolo e sull'overlap
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 ;
double dLen = dAngSin > EPS_ANG_SMALL ? (( m_TParams.m_dDiam / 2 - m_TParams.m_dDiam * dOverlap) / dAngSin - m_TParams.m_dDiam / 2) : - 1.0 ;
Point3d ptCen ;
pResidualCrv->GetCentroid( ptCen) ;
Vector3d vtDir = ptCen - ptCrit ;
@@ -4241,26 +4243,41 @@ Pocketing::RemoveUncutRegions( const ISurfFlatRegion * pSTot, ICURVEPOVECTOR& vO
bUsePtNew = dLen > 0 ;
}
}
// Percorso aggiuntivo
ICurveComposite * pAddPath = CreateCurveComposite() ;
if ( ! ComputeAdditionalPath( ptCrit, ptNew, bUsePtNew, pAddPath, pResidualSrf, vOffsTmp[0]))
return false ;
// Nuova curva di offset con tratti aggiuntivi
ISurfFlatRegion * pAddSrf = pCutRegion->Clone() ;
if ( ! ComputeAdditionalPath( ptCrit, ptNew, bUsePtNew, pAddPath, pResidualCrv, vOffsTmp[0], pAddSrf))
return false ;
// se non ho aggiunto alcun percorso passo alla prossima regione
if ( pAddPath->GetCurveCount() == 0)
continue ;
// aggiorno la superficie lavorata
if ( pAddSrf->IsValid() && ! pNewCutRegion->Add( *pAddSrf))
return false ;
// nuova curva di offset con tratti aggiuntivi
bAddedPaths = true ;
PtrOwner<ICurveComposite> 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
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
pNewOffs->AddCurve( vOffs[idx]->CopyParamRange( dPar, dParE)) ; // aggiungo la parte rimanente del vecchio offset
vOffs[idx].Set( Release( pNewOffs)) ;
}
// Se ho aggiunto nuovi percorsi, verifico se sono rimaste aree non lavorate e le rimuovo
if ( bAddedPaths && pNewCutRegion->GetLoopCount( 0) > 1)
if ( ! RemoveUncutRegions( pNewCutRegion, vOffs))
return false ;
return true ;
}
@@ -4271,46 +4288,37 @@ Pocketing::FindCurveForPathAdd( const ICurveComposite * pCrv, const ICRVCOMPOPOV
{
nIdxMin = -1 ;
Point3d ptCen ;
pCrv->GetCentroid( ptCen) ;
double dDistMin = INFINITO ;
double dDist ;
if ( ! pCrv->GetCentroid( ptCen))
return false ;
double dDistMin = INFINITO ;
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()) ;
Vector3d vtExtr ;
vOffs[0]->GetExtrusion( vtExtr) ;
Frame3d frLoc ;
frLoc.Set( ORIG, vtExtr) ;
// porto le curve in questo riferimento
CurveLocal pCrvLoc( pCrv, GLOB_FRM, frLoc) ;
CRVCVECTOR ccClass ;
if ( ! pSrf->GetCurveClassification( *pCrv, ccClass))
continue ;
for ( size_t i = 1 ; i < vOffs.size() ; i ++) {
if ( ccClass.size() != 1)
return false ;
// verifico se la regione da rimuovere ( pCrv) è esterna alla regione racchiusa da vOffs
CurveLocal pOffsLoc( vOffs[i]->Clone(), GLOB_FRM, frLoc) ;
IntersCurveCurve intersCC( *pCrvLoc, *pOffsLoc) ;
if ( intersCC.GetRegionCurveClassification() != CCREGC_NULL && intersCC.GetRegionCurveClassification() != CCREGC_IN1) {
// se è esterna calcolo la sua distanza dal centro della regione da rimuovere
if ( ccClass[0].nClass == CRVC_OUT) {
// versione 1 : trovo il punto di vOffs[i] a distanza minima da ptCen
// DistPointCurve distPtCrv( ptCen, *(vOffs[i]->Clone())) ;
// if ( distPtCrv.GetDist( dist) && dist < distMin) {
// distMin = dist ;
// idxMin = i ;
// int nFlag ;
// distPtCrv.GetMinDistPoint( 0, ptMinDist, nFlag) ;
// }
// versione 2 : trovo il punto di congiunzione di due curve di vOffs[i] a distanza minima da ptCen, dove la distanza
// non è calcolata lungo una linea retta, ma tenendo conto che deve restare sempre all'interno della regione da svuotare
// cerco il punto sulla curva di offset a distanza minima da ptCen
double dParS, dParE ;
vOffs[i]->GetDomain( dParS, dParE) ;
// scorro tutti i vertici ( i punti di congiunzione di due curve)
for ( int j = dParS ; j < dParE ; j ++) {
for ( int j = int( dParS + 0.5) ; j < int( dParE + 0.5) ; j ++) {
ICurveComposite * pLinkPath = CreateCurveComposite() ;
Point3d ptCrv ;
vOffs[i]->GetPointD1D2( j, ICurve::FROM_MINUS, ptCrv) ;
// calcolo la distanza come il percorso inerno alla regione che li congiunge
CalcBoundedLink( ptCrv, ptCen, pCrvBound, pLinkPath) ;
double dLen ;
if ( ! CalcBoundedLink( ptCrv, ptCen, pCrvBound, pLinkPath))
continue ;
double dLen ;
if ( pLinkPath->GetLength( dLen) && dLen < dDistMin) {
dDistMin = dLen ;
nIdxMin = i ;
@@ -4320,69 +4328,119 @@ Pocketing::FindCurveForPathAdd( const ICurveComposite * pCrv, const ICRVCOMPOPOV
}
}
}
if ( nIdxMin == -1 )
return false ;
if ( nIdxMin == -1 )
return false ;
return true ;
}
//----------------------------------------------------------------------------
bool
Pocketing::ComputeAdditionalPath( const Point3d ptStart, Point3d ptEnd, bool bUsePtEnd, ICurveComposite * pAddPath,
ISurfFlatRegion * pResidualSrf, const ICurveComposite * pCrvBound)
{
// verifico che area non sia troppo piccola
double dArea ;
if ( pResidualSrf->GetGrossArea( dArea) && abs( dArea) < EPS_SMALL)
return true ;
if ( ! bUsePtEnd) {
pResidualSrf->GetCentroid( ptEnd) ;
}
// creo il percorso fra ptStart e ptEnd senza uscire dalla svuotatura
CalcBoundedLink( ptStart, ptEnd, pCrvBound, pAddPath) ;
ICurveComposite * pReturnPath = pAddPath->Clone() ; // percorso di ritorno
pReturnPath->Invert() ;
// Area coperta dal nuovo tratto aggiuntivo
ICurveComposite * pAddPathTmp = CreateCurveComposite() ;
pAddPathTmp->AddPoint( ptStart) ;
pAddPathTmp->AddCurve( pAddPath->Clone()) ;
pAddPathTmp->AddCurve( pReturnPath->Clone()) ;
pAddPathTmp->SetExtrusion( pResidualSrf->GetNormVersor()) ; // setto estrusione per l'offset in modo da essere compatibile con quella di ResidualSrf
//----------------------------------------------------------------------------
bool
Pocketing::ComputeAdditionalPath( const Point3d ptStart, Point3d ptEnd, bool bUsePtEnd, ICurveComposite * pAddPath,
ICurve * pResidualCrv, const ICurve * pCrvBound, ISurfFlatRegion * pAddSrf)
{
ICurveComposite * pResidualCrvClosed = GetCurveComposite( pResidualCrv->Clone()) ;
if ( ! pResidualCrv->IsClosed())
pResidualCrvClosed->Close() ;
OffsetCurve OffsCrv ;
OffsCrv.Make( pAddPathTmp, m_TParams.m_dDiam / 2 + 10 * EPS_SMALL, ICurve::OFF_FILLET) ;
ICurve * pCrvOffs = OffsCrv.GetLongerCurve() ;
ISurfFlatRegion * pToolSrf = CreateSurfFlatRegion() ;
pToolSrf->AddExtLoop( pCrvOffs) ;
// m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pToolSrf->Clone()) ;
// verifico che area non sia troppo piccola
double dArea = 0.0 ;
if ( ! pResidualCrvClosed->GetArea( Plane3d(), dArea) && dArea < EPS_SMALL)
return true ;
// scelta del punto finale
if ( ! bUsePtEnd) {
pResidualCrv->GetCentroid( ptEnd) ;
// se il centroide non è interno alla regione, prendo come punto finale un punto interno
ISurfTriMesh* pResidualSrfTm = GetSurfTriMeshByFlatContour( pResidualCrvClosed) ;
DistPointSurfTm DistPtSTm( ptEnd, *pResidualSrfTm) ;
Point3d ptMinDist ;
if ( DistPtSTm.GetMinDistPoint( ptMinDist) && ! AreSamePointApprox( ptEnd, ptMinDist))
ptEnd = ptMinDist ;
}
// se il punto iniziale e finale coincidono, sceglo un nuovo ptEnd
if ( AreSamePointApprox( ptStart, ptEnd)) {
Point3d ptMid ;
pResidualCrv->GetMidPoint( ptMid) ;
Vector3d vtDir = ptMid - ptStart ;
vtDir.Normalize() ;
double len = Dist( ptStart, ptMid) + 10 * EPS_SMALL - m_TParams.m_dDiam / 2 ;
ptEnd = ptStart + len * vtDir ;
}
// m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pAddPathTmp->Clone()) ;
// m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCrvOffs->Clone()) ;
// creo il percorso fra ptStart e ptEnd senza uscire dalla svuotatura
if ( ! CalcBoundedLink( ptStart, ptEnd, pCrvBound, pAddPath))
return false ;
// int id = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pResidualSrf->Clone()) ;
// LOG_ERROR( GetEMkLogger(), ("id " + to_string(id)).c_str()) ;
// m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pToolSrf->Clone()) ;
ICurveComposite * pReturnPath = pAddPath->Clone() ; // percorso di ritorno
pReturnPath->Invert() ;
if ( ! pResidualSrf->Subtract( *pToolSrf) )
return false ;
// regione svuotata da pAddPath
ICurveComposite * pAddPathTmp = CreateCurveComposite() ;
pAddPathTmp->AddPoint( ptStart) ;
pAddPathTmp->AddCurve( pAddPath->Clone()) ;
pAddPathTmp->AddCurve( pReturnPath->Clone()) ;
if ( pResidualSrf != nullptr && pResidualSrf->IsValid()) {
// Scorro tutte le regioni non lavorate rimaste
for ( size_t i = 0 ; i < pResidualSrf->GetChunkCount() ; i++) {
ICurveComposite * pNewAddPath = CreateCurveComposite() ;
ComputeAdditionalPath( ptEnd, Point3d(), false, pNewAddPath, pResidualSrf->CloneChunk( i), pCrvBound) ;
pAddPath->AddCurve( pNewAddPath->Clone()) ;
Vector3d vtExtr ;
pResidualCrv->GetExtrusion( vtExtr) ;
pAddPathTmp->SetExtrusion( vtExtr) ;
OffsetCurve OffsCrv ;
OffsCrv.Make( pAddPathTmp, m_TParams.m_dDiam / 2 + 10 * EPS_SMALL, ICurve::OFF_FILLET) ;
ICurve * pCrvOffs = OffsCrv.GetLongerCurve() ;
ISurfFlatRegion * pToolSrf = CreateSurfFlatRegion() ;
pToolSrf->AddExtLoop( pCrvOffs->Clone()) ;
// aggiorno la superficie lavorata
if ( ! pAddSrf->IsValid())
pAddSrf = pToolSrf->Clone() ;
else
pAddSrf->Add( *pToolSrf->Clone()) ;
// porto le curva in locale per farne intersezione
Frame3d frLoc ;
frLoc.Set( ORIG, vtExtr) ;
CurveLocal pResidualCrvLoc( pResidualCrv, GLOB_FRM, frLoc) ;
CurveLocal pOffsCrvLoc( pCrvOffs, GLOB_FRM, frLoc) ;
IntersCurveCurve intersCC( *pResidualCrvLoc, *pOffsCrvLoc) ;
CRVCVECTOR ccClass ;
intersCC.GetCurveClassification( 0, ccClass) ;
// ricorsione su eventuali aree non lavorate rimaste
size_t nFirst = 0 ;
size_t nLast = ccClass.size() ;
// verifico se posso trattare in una volta sola la parte inziale e finale della curva
if ( pResidualCrv->IsClosed() && ccClass.front().nClass == CRVC_OUT && ccClass.back().nClass == CRVC_OUT) {
ICurveComposite* pNewResidualCrv = CreateCurveComposite() ;
pNewResidualCrv->AddCurve( pResidualCrv->CopyParamRange( ccClass.back().dParS, ccClass.back().dParE)) ;
pNewResidualCrv->AddCurve( pResidualCrv->CopyParamRange( ccClass.front().dParS, ccClass.front().dParE)) ;
ICurveComposite * pNewAddPath = CreateCurveComposite() ;
if ( ! ComputeAdditionalPath( ptEnd, Point3d(), false, pNewAddPath, pNewResidualCrv, pCrvBound, pAddSrf))
return false ;
pAddPath->AddCurve( pNewAddPath->Clone()) ;
nFirst = 1 ;
nLast = ccClass.size() - 1 ;
}
for ( size_t i = nFirst ; i < nLast ; i++) {
if ( ccClass[i].nClass == CRVC_OUT ) {
ICurve * pNewResidualCrv = pResidualCrv->CopyParamRange( ccClass[i].dParS, ccClass[i].dParE) ;
ICurveComposite * pNewAddPath = CreateCurveComposite() ;
if ( ! ComputeAdditionalPath( ptEnd, Point3d(), false, pNewAddPath, pNewResidualCrv, pCrvBound, pAddSrf))
return false ;
pAddPath->AddCurve( pNewAddPath->Clone()) ;
}
}
pAddPath->AddCurve( pReturnPath->Clone()) ; // percorso di ritorno
return true ;
}
}
pAddPath->AddCurve( pReturnPath->Clone()) ; // percorso di ritorno
return true ;
}
+2 -2
View File
@@ -87,11 +87,11 @@ 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 RemoveUncutRegions( const ISurfFlatRegion * pCutRegion, ICURVEPOVECTOR& vOffs) ;
bool FindCurveForPathAdd( const ICurveComposite * pCrv, const ICRVCOMPOPOVECTOR& vOffs, size_t& nIdxMin, Point3d& ptMinDist,
double& dMinDistPar, const ICurve * pCrvBound) ;
bool ComputeAdditionalPath( const Point3d ptStart, Point3d ptNew, bool bUsePtEnd, ICurveComposite * pAddPath,
ISurfFlatRegion * pResidualSrf, const ICurveComposite * pCrvBound) ;
ICurve * pResidualCrv, const ICurve * pCrvBound, ISurfFlatRegion * pAddSrf) ;
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,