From d57198ac19fc8dd8bd864287c134b3e8820ce8f0 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Fri, 19 Jan 2024 13:35:19 +0100 Subject: [PATCH] EgtMachKernel : - percorsi di ritorno con Vroni smussati ( algoritmo Douglas-Peucker). --- Pocketing.cpp | 159 +++++++++++++++++++++++++++++++++++++++++++++++++- Pocketing.h | 2 +- 2 files changed, 159 insertions(+), 2 deletions(-) diff --git a/Pocketing.cpp b/Pocketing.cpp index 99846c8..0bea04f 100644 --- a/Pocketing.cpp +++ b/Pocketing.cpp @@ -98,7 +98,7 @@ using namespace std ; // 2438 = "Error in Pocketing : Projecting volume failed" // 2439 = "Error in Pocketing : Detecting open edges failed" // 2440 = "Error in Pocketing : Computing second pocket failed" -// 2441 = "Error in Pocketing : Return apth not computable" +// 2441 = "Error in Pocketing : Return path not computable" // 2451 = "Warning in Pocketing : Skipped entity (xx)" // 2452 = "Warning in Pocketing : No machinable pocket" // 2453 = "Warning in Pocketing : Tool name changed (xx)" @@ -6533,6 +6533,132 @@ Pocketing::AddSpiralIn( ISURFFRPOVECTOR& vSfr, const vector& return true ; } +//---------------------------------------------------------------------------- +bool DecimateDP( const double dToll, const PNTVECTOR& vPts, BOOLVECTOR& vbMarks, const int nIndS, const int nIndE) +{ + // controllo dei parametri + if ( int( vPts.size()) < 2 || int( vPts.size()) != int( vbMarks.size()) || dToll < EPS_SMALL || + nIndE >= int( vPts.size()) || nIndS < 0) + return false ; + + // se l'indice di partenza supera quello finale, allora ho finito + if ( nIndS >= nIndE - 1) + return true ; + + // creo un segmento tra i due punti correnti + PtrOwner pSeg( CreateCurveLine()) ; + if ( IsNull( pSeg) || ! pSeg->Set( vPts[nIndS], vPts[nIndE])) + return false ; + + // distanza massima e indice del punto a tale distanza dal segmento creato + double dMaxDist = 0. ; + int nIndMaxDist = nIndE ; + + // scrorro tutti i vertici tra l'inidice inziale e l'indice finale + for ( int i = nIndS ; i < nIndE ; ++ i) { + // distanza attuale + double dCurrDist = INFINITO ; + DistPointCurve DPC( vPts[i], *pSeg) ; + if ( DPC.GetDist( dCurrDist) && dCurrDist > dMaxDist) { // se maggiore della massima... + // aggiorno + dMaxDist = dCurrDist ; + nIndMaxDist = i ; + } + } + + // se la distanza trovata supera la tolleranza, continuo a Splittare + if ( dMaxDist > dToll) { + vbMarks[ nIndMaxDist] = true ; + if ( ! DecimateDP( dToll, vPts, vbMarks, nIndS, nIndMaxDist) || + ! DecimateDP( dToll, vPts, vbMarks, nIndMaxDist, nIndE)) + return false ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool ApproxPolyLinesDP( PolyLine& PL, const double dToll) +{ + // controllo dei parametri + if ( PL.GetPointNbr() < 2 || dToll < EPS_SMALL) + return false ; + // se due punti, la PolyLine è se stessa + if ( PL.GetPointNbr() == 2) + return true ; + // variabili per algoritmo Douglas-Peucker + PNTVECTOR vPts ; + Point3d ptNext ; + PL.GetFirstPoint( ptNext) ; + vPts.push_back( ptNext) ; + while ( PL.GetNextPoint( ptNext)) + vPts.push_back( ptNext) ; + BOOLVECTOR vbMarks ; vbMarks.resize( int( vPts.size()), false) ; + // marco il primo e l'ultimo punto + vbMarks.front() = true ; + vbMarks.back() = true ; + // decimazione della PolyLine + if ( ! DecimateDP( dToll, vPts, vbMarks, 0, int( vPts.size()) - 1)) + return false ; + // costruzione dei punti + PL.Clear() ; + for ( int i = 0 ; i < int( vbMarks.size()) ; ++ i) { + if ( ! vbMarks[i]) // non considero gli indici non marcati + continue ; + PL.AddUPoint( i, vPts[i]) ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool GetApproxCurveDP( const ICurveComposite* pCrvCompo, const double dToll, ICurveComposite* pCrvRes) +{ + // controllo dei parametri + if ( pCrvCompo == nullptr || ! pCrvCompo->IsValid() || dToll < EPS_SMALL || pCrvRes == nullptr) + return false ; + pCrvRes->Clear() ; + + // creo la PolyLine dalla composita + PolyLine PL ; + int nU = 0 ; + for ( int u = 0 ; u < pCrvCompo->GetCurveCount() ; ++ u) { + Point3d ptS ; + if ( pCrvCompo->GetCurve( u)->GetType() == CRV_LINE) { + if ( ! pCrvCompo->GetCurve( u)->GetStartPoint( ptS) || + ! PL.AddUPoint( nU, ptS)) + return false ; + ++ nU ; + } + else { + // se arco prendo più punti + PolyLine PL_tmp ; + if ( ! pCrvCompo->GetCurve( u)->ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL_tmp)) + return false ; + Point3d ptNext ; + PL_tmp.GetFirstPoint( ptNext) ; + PL.AddUPoint( nU, ptNext) ; + ++ nU ; + while ( PL_tmp.GetNextPoint( ptNext)) { + PL.AddUPoint( nU, ptNext) ; + ++ nU ; + } + } + } + Point3d ptE ; + if ( ! pCrvCompo->GetEndPoint( ptE) || + ! PL.AddUPoint( nU, ptE)) + return false ; + + // approssimazione Douglas-Peucker + if ( ! ApproxPolyLinesDP( PL, dToll) || PL.GetPointNbr() < 2) + return false ; + + // dalla PolyLine recupero la composita + return pCrvRes->FromPolyLine( PL) && pCrvRes->IsValid() ; + +} + //---------------------------------------------------------------------------- bool Pocketing::CalcLinkOnStep( const Point3d& ptS, const Point3d& ptE, const ISurfFlatRegion* pSfr, @@ -6656,9 +6782,40 @@ Pocketing::CalcLinkOnStep( const Point3d& ptS, const Point3d& ptE, const ISurfFl pCrvStepLink->IsValid() && pCrvStepLink->ToGlob( frCurr) ; + // ricavo il parametro massimo sui bisettori da VRONI + double dMinPar = INFINITO ; + for ( int i = 1 ; i < pCrvPath->GetCurveCount() - 1; ++ i) { + double dParS = pCrvPath->GetCurve( i)->GetTempParam( 0) ; + if ( dParS < dMinPar) + dMinPar = dParS ; + } + + int r = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSfr->Clone()) ; + m_pGeomDB->SetMaterial( r, RED) ; + int g = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSfrSafe->Clone()) ; + m_pGeomDB->SetMaterial( g, GREEN) ; + PtrOwner pCrvPathH( pCrvPath->Clone()) ; + pCrvPathH->ToGlob( frCurr) ; + int b = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCrvPathH->Clone()) ; + m_pGeomDB->SetMaterial( b, BLUE) ; + + + // approssimo il percorso + PtrOwner pCrvRes( CreateCurveComposite()) ; + if ( ! IsNull( pCrvRes) && GetApproxCurveDP( pCrvPath, dMinPar, pCrvRes)) + pCrvPath.Set( Release( pCrvRes)) ; + + ModifyCurveToSmoothed( pCrvPath, dMinPar, dMinPar, false) ; + PtrOwner pCrvPathHH( pCrvPath->Clone()) ; + pCrvPathHH->ToGlob( frCurr) ; + b = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCrvPathHH->Clone()) ; + m_pGeomDB->SetMaterial( b, BLACK) ; + return false ; + // aggiungo un tratto lineare per avere il percorso completo pCrvPath->AddLine( ORIG, false) ; pCrvPath->AddLine( ptEProj, true) ; + // calcolo la sua lunghezza double dCurrLen ; diff --git a/Pocketing.h b/Pocketing.h index 1490b6b..7ec2890 100644 --- a/Pocketing.h +++ b/Pocketing.h @@ -96,7 +96,7 @@ class Pocketing : public Machining const Point3d& ptE, ICurveComposite* pCrvPath) ; bool GetSpecialElevation( const ISurfFlatRegion* pSfr, const ICurveLine* pLine, const bool bInVsOut, double& dElev) ; - + bool GetDangerSfrForSideStep( const ISurfFlatRegion* pSfr, const ISurfTriMesh* pStm_Part, const double dExtraLenInOut, ISurfFlatRegion* pSfrDanger) ; bool AdjustTrapezoidSpiralLeadInLeadOutForSideAngle( ICurveComposite* pMCrv, const double dExtraLenInOut,