From 54dba7ab4149af0b316e2069e58670a66727cd88 Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Thu, 18 Jul 2024 20:18:18 +0200 Subject: [PATCH 01/11] EgtGeomKernel 2.6g5 : - aggiunta classe DistPointSurfFr (distanza punto regione) . a SurfFlatRegion aggiunte funzioni EraseChunk, GetChunkArea, GetChunkPerimeter, ResetAllCurveTempProps e ResetAllCurveTempParams - piccoli adattamenti in CalcPocketing. --- CalcPocketing.cpp | 45 +-------- DistPointSurfFr.cpp | 156 ++++++++++++++++++++++++++++++ EgtGeomKernel.rc | Bin 11710 -> 11710 bytes EgtGeomKernel.vcxproj | 1 + EgtGeomKernel.vcxproj.filters | 3 + SurfFlatRegion.cpp | 172 ++++++++++++++++++++++++++++++---- SurfFlatRegion.h | 25 +++-- 7 files changed, 335 insertions(+), 67 deletions(-) create mode 100644 DistPointSurfFr.cpp diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 966bf33..d51fb4e 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -24,14 +24,14 @@ #include "/EgtDev/Include/EGkCalcPocketing.h" #include "/EgtDev/Include/EGkFilletChamfer.h" #include "/EgtDev/Include/EGkDistPointCurve.h" -#include "/EgtDev/Include/EGkDistPointCurve.h" +#include "/EgtDev/Include/EGkDistPointSurfFr.h" #include "/EgtDev/Include/EGkCurveLocal.h" #include "/EgtDev/Include/EGkMedialAxis.h" #include "/EgtDev/Include/EGkLinePntTgCurve.h" #include "/EgtDev/Include/EGkOffsetCurve.h" #include "/EgtDev/Include/EGkIntervals.h" -#include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EGkChainCurves.h" +#include "/EgtDev/Include/EgtNumUtils.h" #include using namespace std ; @@ -721,42 +721,6 @@ AssignFeedSpiralOpt( const int nOptType, const PocketParams& PockParams, ICurveC return true ; } -//---------------------------------------------------------------------------- -static bool -IsPointInsideSfr( const ISurfFlatRegion* pSfr, const Point3d& pt, bool& bIsInside) -{ - // controllo dei parametri - if ( pSfr == nullptr || ! pSfr->IsValid() || ! pt.IsValid()) - return false ; - bIsInside = false ; - - // ciclo sui chunk della FlatRegion - for ( int i = 0 ; i < pSfr->GetChunkCount() ; i ++) { - // verifico se è contenuto nel loop esterno - PtrOwner pCrv( pSfr->GetLoop( i, 0)) ; - PolyLine PL ; - pCrv->ApproxWithLines( 10 * EPS_SMALL, 15, ICurve::APL_STD, PL) ; - if ( IsPointInsidePolyLine( pt, PL, EPS_SMALL)) { - bool bInsideHole = false ; - // verifico se è contenuto in un loop interno - for ( int j = 1 ; j < pSfr->GetLoopCount( i) ; j ++) { - PtrOwner pCrv( pSfr->GetLoop( i, j)) ; - pCrv->ApproxWithLines( 10 * EPS_SMALL, 15, ICurve::APL_STD, PL) ; - PL.Invert() ; - if ( IsPointInsidePolyLine( pt, PL, EPS_SMALL)) - bInsideHole = true ; - } - // se è contenuto nel loop esterno ma non è contenuto in nessuno dei loop interni allora il punto è interno - if ( ! bInsideHole) { - bIsInside = true ; - return true ; - } - } - } - - return true ; -} - //---------------------------------------------------------------------------- static bool GetCoeffLinArc( const ICurveArc* pArc, double dDiam, double& dSubArc) @@ -6989,15 +6953,16 @@ AddZigZag( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, con vpCrvs[u]->ToGlob( frPocket) ; // controllo se il punto iniziale e finale sono esterni alla superficie originale + double dMinDist = max( 0., -PockParams.dRadialOffset) ; Point3d ptStart ; vpCrvs[u]->GetStartPoint( ptStart) ; bool bIsInside = false ; - if ( IsPointInsideSfr( pSfrOrig, ptStart, bIsInside) && ! bIsInside) { + if ( IsPointInsideSurfFr( ptStart, pSfrOrig, dMinDist, bIsInside) && ! bIsInside) { Vector3d vtMidOut ; vpCrvs[u]->GetStartDir( vtMidOut) ; vtMidOut.Invert() ; ExtendPathOnOpenEdge( vpCrvs[u], PockParams, pSrfChunk->GetNormVersor(), vtMidOut, false) ; } Point3d ptEnd ; vpCrvs[u]->GetEndPoint( ptEnd) ; - if ( IsPointInsideSfr( pSfrOrig, ptEnd, bIsInside) && ! bIsInside) { + if ( IsPointInsideSurfFr( ptEnd, pSfrOrig, dMinDist, bIsInside) && ! bIsInside) { Vector3d vtMidOut ; vpCrvs[u]->GetEndDir( vtMidOut) ; ExtendPathOnOpenEdge( vpCrvs[u], PockParams, pSrfChunk->GetNormVersor(), vtMidOut, true) ; } diff --git a/DistPointSurfFr.cpp b/DistPointSurfFr.cpp new file mode 100644 index 0000000..ca318ed --- /dev/null +++ b/DistPointSurfFr.cpp @@ -0,0 +1,156 @@ +//---------------------------------------------------------------------------- +// EgalTech 2018-2020 +//---------------------------------------------------------------------------- +// File : DistPointSurfTm.cpp Data : 19.12.20 Versione : 2.2l3 +// Contenuto : Implementazione della classe distanza Punto da Trimesh. +// +// +// +// Modifiche : 07.12.18 LM Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +#include "stdafx.h" +#include "SurfFlatRegion.h" +#include "/EgtDev/Include/EGkDistPointCurve.h" +#include "/EgtDev/Include/EGkDistPointSurfFr.h" + +using namespace std ; + +//---------------------------------------------------------------------------- +DistPointSurfFr::DistPointSurfFr( const Point3d& ptP, const ISurfFlatRegion& frSurf) + : m_dDist( -1) +{ + // FlatRegion non valida + if ( &frSurf == nullptr || ! frSurf.IsValid()) + return ; + // Calcolo la distanza + Calculate( ptP, frSurf) ; +} + +//---------------------------------------------------------------------------- +void +DistPointSurfFr::Calculate( const Point3d& ptP, const ISurfFlatRegion& frSurf) +{ + // Inizializzo distanza non calcolata + m_dDist = -1 ; + + // Converto regione in classe base + const SurfFlatRegion* pSfr = GetBasicSurfFlatRegion( &frSurf) ; + if ( pSfr == nullptr) + return ; + + // ciclo sulle parti della regione + for ( int nC = 0 ; nC < pSfr->GetChunkCount() ; nC ++) { + // ciclo sui loop della parte di regione + for ( int nL = 0 ; nL < pSfr->GetLoopCount( nC) ; nL ++) { + PtrOwner pLoop( pSfr->GetLoop( nC, nL)) ; + if ( IsNull( pLoop)) { + m_dDist = -1 ; + return ; + } + DistPointCurve DPL( ptP, *pLoop) ; + double dDist ; + if ( DPL.GetDist( dDist) && ( m_dDist < -EPS_SMALL || dDist < m_dDist)) { + m_dDist = dDist ; + int nFlag ; + m_nMinChunk = nC ; + m_nMinLoop = nL ; + DPL.GetParamAtMinDistPoint( 0, m_dMinPar, nFlag) ; + DPL.GetMinDistPoint( 0, m_ptMinDistPoint, nFlag) ; + DPL.GetSideAtMinDistPoint( 0, pSfr->GetNormVersor(), m_nSide) ; + } + } + } + // se trovata, aggiorno minima distanza sul piano + if ( m_dDist > - EPS_SMALL) { + Point3d ptOn = ptP - ( ptP - pSfr->GetPlanePoint()) * pSfr->GetNormVersor() * pSfr->GetNormVersor() ; + m_dDistOnPlane = min( Dist( ptOn, m_ptMinDistPoint), m_dDist) ; + } +} + +//---------------------------------------------------------------------------- +bool +DistPointSurfFr::GetDist( double& dDist) const +{ + if ( m_dDist < 0) + return false ; + dDist = m_dDist ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +DistPointSurfFr::GetDistOnRegionPlane( double& dDist) const +{ + if ( m_dDist < 0) + return false ; + dDist = m_dDistOnPlane ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +DistPointSurfFr::GetPointAtMinDist( Point3d& ptMinDist) const +{ + if ( m_dDist < 0) + return false ; + ptMinDist = m_ptMinDistPoint ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +DistPointSurfFr::GetParamAtMinDist( int& nMinChunk, int& nMinLoop, double& dMinPar) const +{ + if ( m_dDist < 0) + return false ; + nMinChunk = m_nMinChunk ; + nMinLoop = m_nMinLoop ; + dMinPar = m_dMinPar ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +DistPointSurfFr::GetSideAtMinDist( int& nSide) const +{ + if ( m_dDist < 0) + return false ; + nSide = m_nSide ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +IsPointInsideSurfFr( const Point3d& ptP, const ISurfFlatRegion* pSfr, double dMinDist, bool& bInside, int& nChunk) +{ + // default non include + bInside = false ; + nChunk = -1 ; + // verifica regione + if ( pSfr == nullptr || ! pSfr->IsValid()) + return false ; + // verifico se la proiezione del punto sul piano della regione sta nel suo box + Point3d ptOn = ptP - ( ptP - pSfr->GetPlanePoint()) * pSfr->GetNormVersor() * pSfr->GetNormVersor() ; + BBox3d b3Box ; + pSfr->GetLocalBBox( b3Box) ; + b3Box.Expand( dMinDist) ; + if ( ! b3Box.Encloses( ptOn)) + return true ; + // determino dove sta il punto + DistPointSurfFr DPR( ptP, *pSfr) ; + double dDist ; int nMinCh, nMinL; double dMinPar ; int nSide ; + if ( DPR.GetDistOnRegionPlane( dDist) && DPR.GetParamAtMinDist( nMinCh, nMinL, dMinPar) && DPR.GetSideAtMinDist( nSide)) { + if ( abs( dMinDist) < EPS_SMALL) + bInside = ( nSide != PRS_OUT) ; + else if ( dMinDist < 0) + bInside = ( nSide == PRS_IN && dDist > abs( dMinDist) - EPS_SMALL) ; + else + bInside = ( nSide != PRS_OUT || dDist < dMinDist + EPS_SMALL) ; + if ( bInside) + nChunk = nMinCh ; + } + return true ; +} diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 11258eabd423711fc8d2dc29016137c3e926e7b1..2af9636e01343f91b5cc367700e21457a7f2c64e 100644 GIT binary patch delta 236 zcmdlNy)SyhI%aKGhCGIJh8%`WhGK>c1_cHUhESkLCPN8BDnkm89}HwAf_cT0PijeT z{=m$}%xJp#yqqG4`lwjSxVewp10r;uY4S3`JfN_k6i~QJ7*lvJ3$os9QmsEYnTvVZ l + false false diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index 7b4369b..0eff6b3 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -546,6 +546,9 @@ File di origine\GeoCreate + + File di origine\GeoDist + diff --git a/SurfFlatRegion.cpp b/SurfFlatRegion.cpp index 41b74cb..4c60547 100644 --- a/SurfFlatRegion.cpp +++ b/SurfFlatRegion.cpp @@ -922,9 +922,6 @@ SurfFlatRegion::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) bool SurfFlatRegion::GetArea( double& dArea) const { - // controllo parametro di ritorno - if ( &dArea == nullptr) - return false ; // inizio con area nulla dArea = 0 ; // la regione deve essere validata @@ -947,9 +944,6 @@ SurfFlatRegion::GetArea( double& dArea) const bool SurfFlatRegion::GetGrossArea( double& dArea) const { - // controllo parametro di ritorno - if ( &dArea == nullptr) - return false ; // inizio con area nulla dArea = 0 ; // la regione deve essere validata @@ -973,9 +967,6 @@ SurfFlatRegion::GetGrossArea( double& dArea) const bool SurfFlatRegion::GetCentroid( Point3d& ptCen) const { - // controllo parametro di ritorno - if ( &ptCen == nullptr) - return false ; // la regione deve essere validata if ( m_nStatus != OK || m_vpLoop.empty()) return false ; @@ -1001,13 +992,20 @@ SurfFlatRegion::GetCentroid( Point3d& ptCen) const return true ; } +//---------------------------------------------------------------------------- +int +SurfFlatRegion::GetChunkCount( void) const +{ + // la regione deve essere validata + if ( m_nStatus != OK) + return 0 ; + return int( m_vExtInd.size()) ; +} + //---------------------------------------------------------------------------- bool SurfFlatRegion::GetChunkCentroid( int nChunk, Point3d& ptCen) const { - // controllo parametro di ritorno - if ( &ptCen == nullptr) - return false ; // la regione deve essere validata if ( m_nStatus != OK || m_vpLoop.empty()) return false ; @@ -1021,13 +1019,53 @@ SurfFlatRegion::GetChunkCentroid( int nChunk, Point3d& ptCen) const } //---------------------------------------------------------------------------- -int -SurfFlatRegion::GetChunkCount( void) const +bool +SurfFlatRegion::GetChunkArea( int nChunk, double& dArea) const { + // default, area nulla + dArea = 0 ; // la regione deve essere validata - if ( m_nStatus != OK) - return 0 ; - return int( m_vExtInd.size()) ; + if ( m_nStatus != OK || m_vpLoop.empty()) + return false ; + // il chunk deve esistere + if ( nChunk < 0 || nChunk >= GetChunkCount()) + return false ; + // calcolo l'area + bool bOk = true ; + for ( int nL = 0 ; nL < GetLoopCount( nChunk) ; ++ nL) { + const ICurve* pLoop = GetMyLoop( nChunk, nL) ; + double dLoopArea ; + if ( pLoop != nullptr && pLoop->GetAreaXY( dLoopArea)) + dArea += dLoopArea ; + else + bOk = false ; + } + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SurfFlatRegion::GetChunkPerimeter( int nChunk, double& dLen) const +{ + // default, perimetro nullo + dLen = 0 ; + // la regione deve essere validata + if ( m_nStatus != OK || m_vpLoop.empty()) + return false ; + // il chunk deve esistere + if ( nChunk < 0 || nChunk >= GetChunkCount()) + return false ; + // calcolo il perimetro + bool bOk = true ; + for ( int nL = 0 ; nL < GetLoopCount( nChunk) ; ++ nL) { + const ICurve* pLoop = GetMyLoop( nChunk, nL) ; + double dLoopLen ; + if ( pLoop != nullptr && pLoop->GetLength( dLoopLen)) + dLen += dLoopLen ; + else + bOk = false ; + } + return bOk ; } //---------------------------------------------------------------------------- @@ -1236,6 +1274,56 @@ SurfFlatRegion::CloneChunk( int nChunk) const return Release( pSfr) ; } +//---------------------------------------------------------------------------- +bool +SurfFlatRegion::EraseChunk(int nChunk) +{ + // la regione deve essere validata + if ( m_nStatus != OK || m_vpLoop.empty()) + return false ; + // il chunk deve esistere + if ( nChunk < 0 || nChunk >= GetChunkCount()) + return false ; + // se un solo chunk, resetto la regione + if ( GetChunkCount() == 1) { + Clear() ; + return true ; + } + // se ultimo chunk + if ( nChunk == m_vExtInd.size() - 1) { + // elimino i loop + for ( int i = m_vExtInd[nChunk] ; i < int( m_vpLoop.size()) ; ++ i) { + delete m_vpLoop[i] ; + m_vpLoop[i] = nullptr ; + } + m_vpLoop.erase( m_vpLoop.begin() + m_vExtInd[nChunk], m_vpLoop.end()) ; + // elimino indice di loop esterno + m_vExtInd.pop_back() ; + } + // altrimenti + else { + // numero di loop da eliminare + int nLoopCnt = m_vExtInd[nChunk+1] - m_vExtInd[nChunk] ; + // elimino i loop + for ( int i = m_vExtInd[nChunk] ; i < m_vExtInd[nChunk+1] ; ++ i) { + delete m_vpLoop[i] ; + m_vpLoop[i] = nullptr ; + } + m_vpLoop.erase( m_vpLoop.begin() + m_vExtInd[nChunk], m_vpLoop.begin() + m_vExtInd[nChunk+1]) ; + // elimino indice di loop esterno + m_vExtInd.erase( m_vExtInd.begin() + nChunk) ; + // aggiorno indice inizio chunk successivi + for ( int i = nChunk ; i < int( m_vExtInd.size()) ; ++i) + m_vExtInd[i] -= nLoopCnt ; + } + // imposto ricalcolo della grafica + m_OGrMgr.Reset() ; + ResetAuxSurf() ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; + return true ; +} + //---------------------------------------------------------------------------- bool SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const @@ -1560,6 +1648,31 @@ SurfFlatRegion::GetCurveTempProp( int nChunk, int nLoop, int nCrv, int& nProp, i return GetBasicCurveComposite( pLoop)->GetCurveTempProp( nCrv, nProp, nPropInd) ; } +//---------------------------------------------------------------------------- +bool +SurfFlatRegion::ResetAllCurveTempProps( void) +{ + for ( int nC = 0 ; nC < GetChunkCount() ; ++ nC) { + for ( int nL = 0 ; nL < GetLoopCount( nC) ; ++ nL) { + ICurve* pLoop = GetMyLoop( nC, nL) ; + if ( pLoop != nullptr) { + if ( pLoop->GetType() != CRV_COMPO) { + pLoop->SetTempProp( 0, 0) ; + pLoop->SetTempProp( 0, 1) ; + } + else { + CurveComposite* pCompoLoop = GetBasicCurveComposite( pLoop) ; + for ( int nI = 0 ; nI < pCompoLoop->GetCurveCount() ; ++ nI) { + pCompoLoop->SetCurveTempProp( nI, 0, 0) ; + pCompoLoop->SetCurveTempProp( nI, 0, 1) ; + } + } + } + } + } + return true ; +} + //---------------------------------------------------------------------------- bool SurfFlatRegion::SetCurveTempParam( int nChunk, int nLoop, int nCrv, double dParam, int nParamInd) @@ -1591,3 +1704,28 @@ SurfFlatRegion::GetCurveTempParam( int nChunk, int nLoop, int nCrv, double& dPar } return GetBasicCurveComposite( pLoop)->GetCurveTempParam( nCrv, dParam, nParamInd) ; } + +//---------------------------------------------------------------------------- +bool +SurfFlatRegion::ResetAllCurveTempParams( void) +{ + for ( int nC = 0 ; nC < GetChunkCount() ; ++ nC) { + for ( int nL = 0 ; nL < GetLoopCount( nC) ; ++ nL) { + ICurve* pLoop = GetMyLoop( nC, nL) ; + if ( pLoop != nullptr) { + if ( pLoop->GetType() != CRV_COMPO) { + pLoop->SetTempParam( 0, 0) ; + pLoop->SetTempParam( 0, 1) ; + } + else { + CurveComposite* pCompoLoop = GetBasicCurveComposite( pLoop) ; + for ( int nI = 0 ; nI < pCompoLoop->GetCurveCount() ; ++ nI) { + pCompoLoop->SetCurveTempParam( nI, 0, 0) ; + pCompoLoop->SetCurveTempParam( nI, 0, 1) ; + } + } + } + } + } + return true ; +} diff --git a/SurfFlatRegion.h b/SurfFlatRegion.h index d257fce..be42bea 100644 --- a/SurfFlatRegion.h +++ b/SurfFlatRegion.h @@ -94,24 +94,29 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW { return m_frF.Orig() ; } const Vector3d& GetNormVersor( void) const override { return m_frF.VersZ() ; } + bool CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound = 3) const override ; + void ResetVoronoiObject( void) const override ; + bool GetMaxOffset( double& dOffs) const override ; + bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const override ; + const SurfTriMesh* GetAuxSurf( void) const override ; + bool GetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const override ; int GetChunkCount( void) const override ; + SurfFlatRegion* CloneChunk( int nChunk) const override ; + bool EraseChunk(int nChunk) override ; + bool GetChunkCentroid( int nChunk, Point3d& ptCen) const override ; + bool GetChunkArea( int nChunk, double& dArea) const override ; + bool GetChunkPerimeter( int nChunk, double& dLen) const override ; + int GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion& Other, int nOthChunk) const override ; // compare only outsides + bool GetChunkMaxOffset( int nChunk, double& dOffs) const override ; int GetLoopCount( int nChunk) const override ; ICurve* GetLoop( int nChunk, int nLoop) const override ; // nChunk 0-based, nLoop 0-based (1°esterno, successivi interni) bool ApproxLoopWithLines( int nChunk, int nLoop, double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const override ; - const SurfTriMesh* GetAuxSurf( void) const override ; - SurfFlatRegion* CloneChunk( int nChunk) const override ; - bool GetChunkCentroid( int nChunk, Point3d& ptCen) const override ; - bool GetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const override ; - int GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion& Other, int nOthChunk) const override ; // compare only outsides - bool CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound = 3) const override ; - bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const override ; - bool GetChunkMaxOffset( int nChunk, double& dOffs) const override ; - bool GetMaxOffset( double& dOffs) const override ; - void ResetVoronoiObject( void) const override ; bool SetCurveTempProp( int nChunk, int nLoop, int nCrv, int nProp, int nPropInd = 0) override ; bool GetCurveTempProp( int nChunk, int nLoop, int nCrv, int& nProp, int nPropInd = 0) const override ; + bool ResetAllCurveTempProps( void) override ; bool SetCurveTempParam( int nChunk, int nLoop, int nCrv, double dParam, int nParamInd = 0) override ; bool GetCurveTempParam( int nChunk, int nLoop, int nCrv, double& dParam, int nParamInd = 0) const override ; + bool ResetAllCurveTempParams( void) override ; public : // IGeoObjRW int GetNgeId( void) const override ; From b04d1ed7a985d864bc5f88ec226a74513a16a21e Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Fri, 19 Jul 2024 12:01:58 +0200 Subject: [PATCH 02/11] EgtGeomKernel : - migliorie nella gestione dei lati Aperti/Chiusi in CalcPocketing. --- CalcPocketing.cpp | 521 +++++++++++++++++++++++++++++++++------------- 1 file changed, 382 insertions(+), 139 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index d51fb4e..43cdea4 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -24,6 +24,7 @@ #include "/EgtDev/Include/EGkCalcPocketing.h" #include "/EgtDev/Include/EGkFilletChamfer.h" #include "/EgtDev/Include/EGkDistPointCurve.h" +#include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EGkDistPointSurfFr.h" #include "/EgtDev/Include/EGkCurveLocal.h" #include "/EgtDev/Include/EGkMedialAxis.h" @@ -59,12 +60,15 @@ struct PocketParams { bool bSmooth = false ; // curve smussate bool bInvert = false ; // inversione dei percorsi bool bAvoidOpt = false ; // flag per evitare casi ottimizzati + bool bAllowZigZagOneWayBorders = false ; // flag per abilitare le curve di bordo per ZigZag/OneWay Point3d ptStart = P_INVALID ; // punto d'inizio Point3d ptEnd = P_INVALID ; // punto di fine SurfFlatRegion SfrLimit ; // superficie limite per estensione lati aperti bool bCalcFeed = true ; // flag per calcolo della Feed double dFeed = 1000 ; // feed di riferimento per frazione double dToolFeed = 1000 ; // feed del tool + // ------------------------------------------------------- + bool bAllClosed = true ; // flag per indicare se tutti i bordi sono chiusi } ; static double TOL_TRAPEZOID = 50 * EPS_SMALL ; // tolleranza per casi a trapezio SpiralPocket @@ -372,10 +376,10 @@ CheckSimpleOverlap( const ICurve* pCrv, const ICurveComposite* pCrvOri, int& nSt //---------------------------------------------------------------------------- static bool AssignFeedForOpenEdge( ICurveComposite* pCrv, const ICurveComposite* pCrvOF_orig, - const PocketParams& PockParams) + const PocketParams& PockParams, bool bAllowOverWrite) { // se non rischiesto il calcolo della Feed, lascio quella standard - if ( ! PockParams.bCalcFeed) + if ( ! PockParams.bCalcFeed && bAllowOverWrite) return AssignMaxFeed( pCrv, PockParams) ; // controllo se qualche curva passa sopra ad un lato aperto... @@ -515,7 +519,7 @@ AssignFeedSpiral( ICurveComposite* pCrv, const ISurfFlatRegion* pSrfRemoved_offs // se non ho una superificie svuotata, allora esco ( con Feed Minima) if ( pSrfRemoved_offs == nullptr || ! pSrfRemoved_offs->IsValid() || pSrfRemoved_offs->GetChunkCount() == 0) { // controllo eventuali sovrapposizioni con lati aperti - AssignFeedForOpenEdge( pCrv, pCrv_orig, PockParams) ; + AssignFeedForOpenEdge( pCrv, pCrv_orig, PockParams, true) ; return true ; } @@ -666,7 +670,7 @@ AssignFeedSpiral( ICurveComposite* pCrv, const ISurfFlatRegion* pSrfRemoved_offs } // controllo eventuali sovrapposizioni con lati aperti - AssignFeedForOpenEdge( pCrv, pCrv_orig, PockParams) ; + AssignFeedForOpenEdge( pCrv, pCrv_orig, PockParams, true) ; return true ; } @@ -721,6 +725,71 @@ AssignFeedSpiralOpt( const int nOptType, const PocketParams& PockParams, ICurveC return true ; } +//---------------------------------------------------------------------------- +static bool +ResetCurveTempProps( ICurveComposite* pCrvCompo) +{ + // controllo parametri + if ( pCrvCompo == nullptr || ! pCrvCompo->IsValid()) + return false ; + + // scorro le curve + for ( int nU = 0 ; nU < pCrvCompo->GetCurveCount() ; ++ nU) { + pCrvCompo->SetCurveTempProp( nU, 0, 0) ; + pCrvCompo->SetCurveTempProp( nU, 0, 1) ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +IsChunkAllClosed( const ISurfFlatRegion* pSfr, int nChunk, bool& bAllClose) +{ + // controllo dei parametri + if ( pSfr == nullptr || ! pSfr->IsValid() || nChunk < 0 || nChunk > pSfr->GetChunkCount()) + return false ; + bAllClose = true ; + + // scorro tutti i loop del Chunk + for ( int nL = 0 ; nL < pSfr->GetLoopCount( nChunk) ; ++ nL) { + // recupero il loop + PtrOwner pCrvLoop( ConvertCurveToComposite( pSfr->GetLoop( nChunk, nL))) ; + if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid()) + return false ; + // scorro le curve semplici + int nCurrProp = TEMP_PROP_INVALID ; + for ( int nU = 0 ; nU < pCrvLoop->GetCurveCount() ; ++ nU) { + bAllClose = ( pCrvLoop->GetCurveTempProp( nU, nCurrProp, 0) && + nCurrProp == TEMP_PROP_CLOSE_EDGE) ; + if ( ! bAllClose) + return true ; + } + } + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +IsSfrAllClosed( const ISurfFlatRegion* pSfr, bool& bAllClose) +{ + // controllo dei parametri + if ( pSfr == nullptr || ! pSfr->IsValid()) + return false ; + bAllClose = true ; + + // ciclo sui Chunk della regione + for ( int nC = 0 ; nC < pSfr->GetChunkCount() ; ++ nC) { + if ( ! IsChunkAllClosed( pSfr, nC, bAllClose)) + return false ; + if ( ! bAllClose) + return true ; + } + + return true ; +} + //---------------------------------------------------------------------------- static bool GetCoeffLinArc( const ICurveArc* pArc, double dDiam, double& dSubArc) @@ -820,10 +889,9 @@ GetParamForPtStartOnEdge( const ICurve* pCrvCheck, const ICurveComposite* pCrvCo if ( ! pCrv->GetLength( dLen)) return false ; double dSubArc = -1 ; - if ( pCrv->GetType() == CRV_ARC) { - if ( ! GetCoeffLinArc( GetCurveArc( pCrv), dDiam, dSubArc)) - return false ; - } + if ( pCrv->GetType() == CRV_ARC) + GetCoeffLinArc( GetCurveArc( pCrv), dDiam, dSubArc) ; + double dDiv = dSubArc < 0 ? dDiam : dSubArc ; double dMaxInt = floor( dLen / dDiv) ; @@ -1004,7 +1072,7 @@ ExtendPathOnOpenEdge( ICurveComposite* pCrvPath, const PocketParams& PockParams, // controllo dei parametri if ( pCrvPath == nullptr || ! pCrvPath->IsValid()) return false ; - // recupero il punto iniziale della curva + // recupero il punto iniziale/finale della curva Point3d ptMidOpen ; if ( bEndOrStart) { if ( ! pCrvPath->GetEndPoint( ptMidOpen)) @@ -1014,12 +1082,55 @@ ExtendPathOnOpenEdge( ICurveComposite* pCrvPath, const PocketParams& PockParams, if ( ! pCrvPath->GetStartPoint( ptMidOpen)) return false ; } - // calcolo il punto fuori + // calcolo il punto di caduta dell'utensile Point3d ptOut = ptMidOpen + vtMidOut * ( PockParams.dRad + PockParams.dOpenMinSafe) ; - // aggiungo al ritorno l'uscita - pCrvPath->AddLine( ptOut, bEndOrStart) ; - pCrvPath->SetCurveTempProp( ( bEndOrStart ? pCrvPath->GetCurveCount() - 1 : 0), TMP_PROP_CRV_OPEN_SIDE, 0) ; // nProp 2 per le curve LeadIn/Out - pCrvPath->SetCurveTempParam( ( bEndOrStart ? pCrvPath->GetCurveCount() - 1 : 0), GetMinFeed( PockParams) , 0) ; // Feed minima + // se non ho una superficie limite, allora aggiungo il tratto + if ( ! PockParams.SfrLimit.IsValid()) { + // aggiungo al ritorno l'uscita + pCrvPath->AddLine( ptOut, bEndOrStart) ; + pCrvPath->SetCurveTempProp( ( bEndOrStart ? pCrvPath->GetCurveCount() - 1 : 0), TMP_PROP_CRV_OPEN_SIDE, 0) ; // nProp 2 per le curve LeadIn/Out + pCrvPath->SetCurveTempParam( ( bEndOrStart ? pCrvPath->GetCurveCount() - 1 : 0), GetMinFeed( PockParams) , 0) ; // Feed minima + return true ; + } + // recupero la regione limite + PtrOwner pSfrLimit( PockParams.SfrLimit.Clone()) ; + if ( IsNull( pSfrLimit) || ! pSfrLimit->IsValid()) + return false ; + // Offset della regione + pSfrLimit->Offset( PockParams.dRad + PockParams.dRadialOffset, ICurve::OFF_FILLET) ; + + // creo sistema di riferimento locale per piano XY + Point3d ptFr ; pCrvPath->GetStartPoint( ptFr) ; + Frame3d frLoc ; + if ( ! frLoc.Set( ptFr, vtN)) + return false ; + + // porto la superficie limite in questo frame + pSfrLimit->ToLoc( frLoc) ; + + // ruoto il versore di uscita cercando un'entrata valida + Vector3d vtRotMidOut = vtMidOut ; + for ( int i = 0 ; i < 4 ; ++ i) { + // creo l'ombra del Tool centrato in ptOut + PtrOwner pCrvToolShape( CreateCurveArc()) ; + if ( IsNull( pCrvToolShape) || ! pCrvToolShape->Set( ptOut, Z_AX, PockParams.dRad)) + return false ; + // porto la curva nel frame locale + pCrvToolShape->ToLoc( frLoc) ; + // controllo l'intersezione ( pSfrLimit e pCrvToolShape sono nel piano XY) + CRVCVECTOR ccClass ; + if ( pSfrLimit->GetCurveClassification( *pCrvToolShape, EPS_SMALL, ccClass) && + int( ccClass.size()) == 1 && ccClass[0].nClass == CRVC_OUT) { + // aggiungo al ritorno l'uscita + pCrvPath->AddLine( ptOut, bEndOrStart) ; + pCrvPath->SetCurveTempProp( ( bEndOrStart ? pCrvPath->GetCurveCount() - 1 : 0), TMP_PROP_CRV_OPEN_SIDE, 0) ; // nProp 2 per le curve LeadIn/Out + pCrvPath->SetCurveTempParam( ( bEndOrStart ? pCrvPath->GetCurveCount() - 1 : 0), GetMinFeed( PockParams) , 0) ; // Feed minima + return true ; + } + vtRotMidOut.Rotate( vtN, - ANG_RIGHT) ; + ptOut = ptMidOpen + vtRotMidOut * ( PockParams.dRad + PockParams.dOpenMinSafe) ; + } + return true ; } @@ -1703,7 +1814,7 @@ ChainCompoCurves( ICRVCOMPOPOVECTOR& vCrvCompo) //---------------------------------------------------------------------------- static bool -AdjustOpenCurves( ICRVCOMPOPOVECTOR& vCrvCompo, const PocketParams& PockParams) +AdjustOpenCurves( ICRVCOMPOPOVECTOR& vCrvCompo, const PocketParams& PockParams, bool bCalcFeed) { /* sistemazione punto di inizio, segmento per LeadIn, e Feed @@ -1778,21 +1889,23 @@ AdjustOpenCurves( ICRVCOMPOPOVECTOR& vCrvCompo, const PocketParams& PockParams) } } - // imposto le Feed per tali curve - for ( int i = 0 ; i < int( vCrvCompo.size()) ; ++ i) { - /* - Idea : Feed proporzionale al minimo Offset per annullare la regione - -> Massimo parametro sui bisettori di VORONOI - */ + // imposto le Feed per tali curve se richiesto + if ( bCalcFeed) { + for ( int i = 0 ; i < int( vCrvCompo.size()) ; ++ i) { + /* + Idea : Feed proporzionale al minimo Offset per annullare la regione + -> Massimo parametro sui bisettori di VORONOI + */ - // recupero il MaxOffset per la curva - double dMaxOffs = vCrvCompo[i]->GetTempParam( 0) ; - // calcolo la Feed proporzionale a tale Offset - double dFeed ; - GetFeedForParam( 2 * dMaxOffs, PockParams, dFeed) ; - AssignCustomFeed( vCrvCompo[i], PockParams, dFeed) ; - // imposto il flag di curva singola - vCrvCompo[i]->SetTempProp( TMP_PROP_SINGLE_CURVE, 0) ; //nProp per curva singola + // recupero il MaxOffset per la curva + double dMaxOffs = vCrvCompo[i]->GetTempParam( 0) ; + // calcolo la Feed proporzionale a tale Offset + double dFeed ; + GetFeedForParam( 2 * dMaxOffs, PockParams, dFeed) ; + AssignCustomFeed( vCrvCompo[i], PockParams, dFeed) ; + // imposto il flag di curva singola + vCrvCompo[i]->SetTempProp( TMP_PROP_SINGLE_CURVE, 0) ; //nProp per curva singola + } } return true ; @@ -1981,7 +2094,7 @@ GetPocketCurvesByCloseEdges( const ISurfFlatRegion* pSfrChunk, const PocketParam //---------------------------------------------------------------------------- static bool -ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, const PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvCompoRes, +ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvCompoRes, bool& bSkipPocket) { // controllo parametri : @@ -1989,6 +2102,13 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, const PocketParams& PockParams, IC return true ; // <- se superficie non valida, allora non ho niente da impostare sui suoi lati bSkipPocket = false ; + // controllo se esistono dei lati aperti + if ( ! IsSfrAllClosed( pSfr, PockParams.bAllClosed)) + return false ; + // se lati tutti chiusi, allora non devo fare nulla + if ( PockParams.bAllClosed) + return true ; + // NB. Tutti i Loop che presentano dei lati aperti possono essere estesi ; sia per loop esterni che per isole... // I lati aperti vanno estesi seguendo lo geometria dei lati chiusi adiacenti e tenendo conto delle isole chiuse // vicine ad essi @@ -1998,133 +2118,138 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, const PocketParams& PockParams, IC if ( IsNull( pSrfFinal)) return false ; - int nChunkOneCurve = 0 ; // numero di chunk rimovibili mediante una sola curva di Offset - int nChunk = pSfr->GetChunkCount() ; // numero complessivo di Chunk da svuotare + // numero di chunk rimovibili mediante una sola curva di Offset seguente il tratto chiuso + int nChunkOneCurve = 0 ; + // numero complessivo di Chunk da svuotare + int nChunk = pSfr->GetChunkCount() ; // per ogni Chunck della superificie ottenuta... - for ( int c = 0 ; c < nChunk ; ++ c) { + for ( int nC = 0 ; nC < nChunk ; ++ nC) { - // 0) controllo se seguendo i chiusi posso svuotare l'interno chunk + // controllo se seguendo i chiusi posso svuotare l'interno chunk /* - nel caso in cui il chunk c-esimo può essere svuotata da una o più curve che seguono + nel caso in cui il chunk c-esimo può essere svuotato da una o più curve che seguono il/i tratto/i chiuso/i, queste vengono salvate direttamente nei percorsi di svuotatura. Il chuck c-esimo verrà poi ignorato ( quindi nessuna estensione presso gli aperti) */ - PtrOwner pSfrChunk( pSfr->CloneChunk( c)) ; + PtrOwner pSfrChunk( pSfr->CloneChunk( nC)) ; if ( IsNull( pSfrChunk) || ! pSfrChunk->IsValid()) return false ; bool bIsAllRemoved = false ; GetPocketCurvesByCloseEdges( pSfrChunk, PockParams, vCrvCompoRes, bIsAllRemoved) ; - if ( bIsAllRemoved) { // se ho rimosso tutto, allora passo la chunk successivo - ++ nChunkOneCurve ; // aumento il contatore - continue ; // ignoro il chunk c-esimo + if ( bIsAllRemoved) { + // se ho rimosso tutto, allora passo la chunk successivo + ++ nChunkOneCurve ; + continue ; } // vettore delle isole che userò ( le isole aperte piccole sono trascurate) ICRVCOMPOPOVECTOR vCrvToTIsland ; - // Flag per sapere se c'è stata almeno una modifica in un loop + // flag per sapere se c'è stata almeno una modifica in un loop del Chunk nC-esimo bool bIsChunkModified = false ; - // 1) ricavo il Loop esterno - PtrOwner pCrvEL( ConvertCurveToComposite( pSfr->GetLoop( c, 0))) ; + // ricavo il Loop esterno ( External Loop) + PtrOwner pCrvEL( ConvertCurveToComposite( pSfr->GetLoop( nC, 0))) ; if ( IsNull( pCrvEL) || ! pCrvEL->IsValid()) return false ; - // 2) creo un vettore di curve con le isole del Chunk + // creo un vettore di curve con le isole del Chunk ( Internal Loops) ICRVCOMPOPOVECTOR vCrvIsl ; - for ( int l = 1 ; l < pSfr->GetLoopCount( c) ; ++ l) { - PtrOwner pCrvIL( ConvertCurveToComposite( pSfr->GetLoop( c, l))) ; + for ( int nL = 1 ; nL < pSfr->GetLoopCount( nC) ; ++ nL) { + PtrOwner pCrvIL( ConvertCurveToComposite( pSfr->GetLoop( nC, nL))) ; if ( IsNull( pCrvIL) || ! pCrvIL->IsValid()) return false ; vCrvIsl.emplace_back( Release( pCrvIL)) ; } - // 3) se la curva esterna presenta dei lati aperti -> devo modificarla + // se la curva esterna presenta dei lati aperti -> devo modificarla bool bSomeOpen = false ; - int nProp0 = -1 ; + int nProp0 = TEMP_PROP_INVALID ; for ( int u = 0 ; u < pCrvEL->GetCurveCount() && ! bSomeOpen ; ++ u) - if ( pCrvEL->GetCurveTempProp( u, nProp0, 0) && nProp0 == 1) - bSomeOpen = true ; - if ( bSomeOpen) { // se trovo dei lati aperti - // 3.1) sistemo la superificie + bSomeOpen = ( pCrvEL->GetCurveTempProp( u, nProp0, 0) && nProp0 == TEMP_PROP_OPEN_EDGE) ; + + // se trovo dei lati aperti + if ( bSomeOpen) { + // allorargo il Loop esterno presso i lati aperti if ( ! AdjustContourWithOpenEdges( pCrvEL, vCrvIsl, PockParams)) return false ; - bIsChunkModified = true ; // la curva è stata modificata + bIsChunkModified = true ; } - // 4) Controllo i bordi delle isole ottenute - // NB. L'isola può essere tutta aperta o tutta chiusa ( se non uniforme, passo a tutta chiusa ) + // controllo i bordi delle isole ottenute + // NB. L'isola può essere tutta aperta o tutta chiusa ( se non uniforme, passo a tutta chiusa) // La definizione di isola con proprietà non uniformi non è definita... - for ( int i = 0 ; i < int( vCrvIsl.size()) ; ++ i) { + for ( int nI = 0 ; nI < int( vCrvIsl.size()) ; ++ nI) { // controllo uniformità - int nCurrTmpProp = -1 ; - int nPrecTmpProp = -1 ; + int nCurrTmpProp = TEMP_PROP_INVALID ; + int nPrecTmpProp = TEMP_PROP_INVALID ; bool bIsMixed = false ; - PtrOwner pCrvIsl( vCrvIsl[i]->Clone()) ; + PtrOwner pCrvIsl( CloneCurveComposite( vCrvIsl[nI])) ; if ( IsNull( pCrvIsl) || ! pCrvIsl->IsValid()) return false ; - for ( int u = 0 ; u < pCrvIsl->GetCurveCount() && ! bIsMixed ; ++ u) { - pCrvIsl->GetCurveTempProp( u, nCurrTmpProp, 0) ; - bIsMixed = ( u != 0 && nCurrTmpProp != nPrecTmpProp) ; + for ( int nU = 0 ; nU < pCrvIsl->GetCurveCount() && ! bIsMixed ; ++ nU) { + pCrvIsl->GetCurveTempProp( nU, nCurrTmpProp, 0) ; + bIsMixed = ( nU != 0 && nCurrTmpProp != nPrecTmpProp) ; nPrecTmpProp = nCurrTmpProp ; } // se proprità non uniformi -> tutta chiusa if ( bIsMixed) { - for ( int u = 0 ; u < pCrvIsl->GetCurveCount() ; ++ u) - pCrvIsl->SetTempProp( u, 0) ; - nCurrTmpProp = 0 ; // aggiorno il Flag - bIsChunkModified = true ; // la curva è stata modificata + for ( int nU = 0 ; nU < pCrvIsl->GetCurveCount() ; ++ nU) + pCrvIsl->SetTempProp( nU, TEMP_PROP_CLOSE_EDGE) ; + nCurrTmpProp = TEMP_PROP_CLOSE_EDGE ; + bIsChunkModified = true ; } // se curva tutta aperta, controllo se l'isola può essere trascurata - if ( nCurrTmpProp == 1) { + if ( nCurrTmpProp == TEMP_PROP_OPEN_EDGE) { // calcolo il massimo Offset double dMaxOffs ; CalcCurveLimitOffset( *pCrvIsl, dMaxOffs) ; + // se l'isola è trascurabile passo alla successiva if ( dMaxOffs < 2 * PockParams.dRad + 2 * PockParams.dRadialOffset) continue ; - // altrimenti, estendo l'isola aperta ( considero il loop esterno come "isola" per l'estensione) + // altrimenti, estendo l'isola aperta ICRVCOMPOPOVECTOR vCrvExtLoop ; vCrvExtLoop.emplace_back( pCrvEL->Clone()) ; if ( ! AdjustContourWithOpenEdges( pCrvIsl, vCrvExtLoop, PockParams)) return false ; bIsChunkModified = true ; } - vCrvToTIsland.emplace_back( pCrvIsl->Clone()) ; // entra nelle curve della regione da svuotare + // conservo l'isola ( estesa o meno) + vCrvToTIsland.emplace_back( pCrvIsl->Clone()) ; } - // 6) Se c'è stata almeno una modifica di lato aperto al chunk (c-esimo), devo ricreare il Chunk - // nuovi loop ricavati ( Chunk dopo Chunk creo la superficie finale) + // se c'è stata almeno una modifica di lato aperto al Chunk (nC-esimo), devo ricreare il Chunk + // con i nuovi loop ricavati ( Chunk dopo Chunk creo la superficie finale) if ( bIsChunkModified) { - - SurfFlatRegionByContours SfrBC ; // per sicurezza analizzo ancora i Loop + /* + l'estensione degli aperti, può unire il loop esterno con il loop delle sue isole. + Creo una nuova regione dai nuovi contorni ottenuti + */ + SurfFlatRegionByContours SfrBC ; + // loop Esterno pCrvEL->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, true, true) ; - SfrBC.AddCurve( Release( pCrvEL)) ; // <--- Loop esterno - for ( int i = 0 ; i < int( vCrvToTIsland.size()) ; ++ i) { - vCrvToTIsland[i]->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, true, true) ; - SfrBC.AddCurve( Release( vCrvToTIsland[i])) ; // <--- isole "valide" + SfrBC.AddCurve( Release( pCrvEL)) ; + // isole non trascurate + for ( int nI = 0 ; nI < int( vCrvToTIsland.size()) ; ++ nI) { + vCrvToTIsland[nI]->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, true, true) ; + SfrBC.AddCurve( Release( vCrvToTIsland[nI])) ; } - - // ricavo il nuovo Chunk + // ricavo il nuovo Chunk nC-esimo esteso presso i lati aperti PtrOwner pNewChunk( SfrBC.GetSurf()) ; if ( IsNull( pNewChunk) || ! pNewChunk->IsValid()) return false ; - - // aggiungo il Chunk alla superficie finale + // aggiungo il Chunk nC-esimo alla superficie finale if ( pSrfFinal->GetChunkCount() == 0) pSrfFinal.Set( pNewChunk) ; - else - if ( ! pSrfFinal->Add( *pNewChunk)) - return false ; + else if ( ! pSrfFinal->Add( *pNewChunk)) + return false ; } - // se il Chunk c-esimo non è mai stato modificato... + // se il Chunk c-esimo non è mai stato modificato else { // aggiungo il Chunk alla superficie finale if ( pSrfFinal->GetChunkCount() == 0) - pSrfFinal.Set( pSfr->CloneChunk( c)) ; - else { - PtrOwner pSfrToAdd( pSfr->CloneChunk( c)) ; - if ( IsNull( pSfrToAdd) || ! pSrfFinal->Add( *pSfrToAdd)) - return false ; - } + pSrfFinal.Set( pSfrChunk) ; + else if ( ! pSrfFinal->Add( *pSfrChunk)) + return false ; } } @@ -2134,10 +2259,10 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, const PocketParams& PockParams, IC if ( ! ChainCompoCurves( vCrvCompoRes)) return false ; // determino ora il punto di inizio, il tratto per il LeadIn e la Feed delle curve singole - if ( ! AdjustOpenCurves( vCrvCompoRes, PockParams)) + if ( ! AdjustOpenCurves( vCrvCompoRes, PockParams, true)) return false ; - // se ho rimosso tutti i Chunk con una singola curva... + // se ho rimosso tutti i Chunk con una singola curva, allora ho terminato la svuotatura bSkipPocket = ( nChunk == nChunkOneCurve) ; if ( bSkipPocket) return true ; @@ -2147,7 +2272,6 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, const PocketParams& PockParams, IC return false ; pSfr->Clear() ; pSfr->CopyFrom( pSrfFinal) ; - return ( pSrfFinal->IsValid() && pSrfFinal->GetChunkCount() > 0) ; } @@ -6825,7 +6949,7 @@ AddSpiralIn( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, AssignFeedSpiralOpt( 1, PockParams, pMCrv) ; pMCrv->SetTempProp( TMP_PROP_OPT_TRAPEZOID, 0) ; } - else if ( bSomeOpen) { // se presenza di lati aperti + else if ( bSomeOpen) { // se presenza di lati aperti validi if ( ! ExtendPathOnOpenEdge( pMCrv, PockParams, pSrfChunk->GetNormVersor(), vtMidOut, false)) return false ; } @@ -6905,6 +7029,111 @@ AddSpiralOut( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, return true ; } +//---------------------------------------------------------------------------- +static bool +GetZigZagOneWayBorderCrvs( const ISurfFlatRegion* pSfrPock, const PocketParams& PockParams, + ICRVCOMPOPOVECTOR& vCrvRes) +{ + /* + Restituisce le curve di Primo Offset dei lati chiusi per i percorsi a ZigZag e OneWay. + Vengono calcolate le Feed ed eventuali entrate da fuori per i percorsi ricavati + */ + + // controllo validità della regione + if ( pSfrPock == nullptr || ! pSfrPock->IsValid()) + return false ; + + // recupero la superficie limite e calcolo Offset + PtrOwner pSfrLimit( CreateSurfFlatRegion()) ; + if ( IsNull( pSfrLimit)) + return false ; + if ( PockParams.SfrLimit.IsValid()) { + pSfrLimit.Set( PockParams.SfrLimit.Clone()) ; + if ( IsNull( pSfrLimit) || ! pSfrLimit->IsValid()) + return false ; + pSfrLimit->Offset( PockParams.dRad + PockParams.dRadialOffset, ICurve::OFF_FILLET) ; + } + + // vettore delle curve chiuse Offsettate + ICRVCOMPOPOVECTOR vClosedOffs ; + + // scorro i Chunk e i Loop della regione + for ( int nC = 0 ; nC < pSfrPock->GetChunkCount() ; ++ nC) { + for ( int nL = 0 ; nL < pSfrPock->GetLoopCount( nC) ; ++ nL) { + // Loop come curva composita + PtrOwner pCrvLoop( ConvertCurveToComposite( pSfrPock->GetLoop( nC, nL))) ; + if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid()) + return false ; + // recupero i tratti con proprietà uniformi + ICRVCOMPOPOVECTOR vpCrvs ; + GetHomogeneousParts( pCrvLoop, PockParams, vpCrvs) ; + if ( vpCrvs.size() > 1) { // unisco il primo e l'ultimo se estremi compatibili + // NB. GetHomogeneousParts() cambia il punto di inizio nel lato chiuso più lungo ( se presente) + Point3d ptE ; vpCrvs.back()->GetEndPoint( ptE) ; + Point3d ptS ; vpCrvs[0]->GetStartPoint( ptS) ; + if ( AreSamePointApprox( ptS, ptE)) { + vpCrvs[0]->AddCurve( Release( vpCrvs.back()), false) ; + vpCrvs.erase( vpCrvs.end() - 1) ; + } + } + // scorro tutti i tratti chiusi e calcolo l'Offset + for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) { + if ( vpCrvs[i]->GetTempProp( 0) == 0) { // se tratto chiuso... + OffsetCurve OffsCrv ; // con offset verso l'interno + if ( OffsCrv.Make( vpCrvs[i], - PockParams.dRad - PockParams.dRadialOffset, ICurve::OFF_FILLET)) { + PtrOwner pOffLongestCrv( OffsCrv.GetLongerCurve()) ; + while ( ! IsNull( pOffLongestCrv)) { + // recupero solo i tratti di curva al di fuori della superficie limite + if ( pSfrLimit->IsValid()) { + CRVCVECTOR ccClass ; + if ( pSfrLimit->GetCurveClassification( *pOffLongestCrv, EPS_SMALL, ccClass)) { + for ( int j = 0 ; j < int( ccClass.size()) ; ++ j) { + if ( ccClass[j].nClass == CRVC_OUT) { + // recupero il tratto di curva + PtrOwner pCrv( pOffLongestCrv->CopyParamRange( ccClass[j].dParS, ccClass[j].dParE)) ; + if ( ! IsNull( pCrv) && pCrv->IsValid()) + vClosedOffs.emplace_back( ConvertCurveToComposite( Release( pCrv))) ; + } + } + } + } + else + vClosedOffs.emplace_back( ConvertCurveToComposite( Release( pOffLongestCrv))) ; + + // passo alla successiva + pOffLongestCrv.Set( OffsCrv.GetLongerCurve()) ; + } + } + } + } + } + } + // se non ho percorsi ho finito + if ( vClosedOffs.empty()) + return true ; + + // concateno eventuali percorsi + if ( ! ChainCompoCurves( vClosedOffs)) + return false ; + // determino ora il punto di inizio, il tratto per il LeadIn + if ( ! AdjustOpenCurves( vClosedOffs, PockParams, false)) + return false ; + + // Calcolo ora le Feed e restituisco le curve ottenute + for ( int i = 0 ; i < int( vClosedOffs.size()) ; ++ i) { + // se ZigZag -> ho percorso i tratti a ZigZag, quindi posso andare a Feed massima + if ( PockParams.nType == POCKET_ZIGZAG) + AssignMaxFeed( vClosedOffs[i], PockParams) ; + // se OneWay -> prima percorro queste curva, quindi la Feed è minima + if ( PockParams.nType == POCKET_ONEWAY) + AssignMinFeed( vClosedOffs[i], PockParams) ; + // restituisco le curve ottenute + vCrvRes.emplace_back( Release( vClosedOffs[i])) ; + } + + return true ; +} + //---------------------------------------------------------------------------- static bool AddZigZag( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, const PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvCompoRes) @@ -6912,67 +7141,81 @@ AddZigZag( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, con // Offset della regione per curva ZigZag double dOffs = PockParams.dRad + PockParams.dRadialOffset ; + // determino il sistema di riferimento in base alla svuotatura + Frame3d frPocket ; + Point3d ptCen ; pSrfPock->GetCentroid( ptCen) ; + if ( ! frPocket.Set( ptCen, pSrfPock->GetNormVersor()) || + ! frPocket.Rotate( ptCen, pSrfPock->GetNormVersor(), PockParams.dAngle)) + return false ; + // ciclo su tutti i chunks della superficie originale - for ( int c = 0 ; c < pSrfPock->GetChunkCount() ; ++ c) { + for ( int nC = 0 ; nC < pSrfPock->GetChunkCount() ; ++ nC) { - // copio il chunk c-esimo - PtrOwner pSrfChunk( pSrfPock->CloneChunk( c)) ; - if ( IsNull( pSrfChunk)) + // creo la regione per il percorso a ZigZag ( mediante primo Offset) portandola + // nel sistema di riferimento creato + PtrOwner pSrfZigZag( pSrfPock->CloneChunk( nC)) ; + if ( ! pSrfZigZag->ToLoc( frPocket) || ! pSrfZigZag->Offset( - dOffs, ICurve::OFF_FILLET)) return false ; - - // determino il riferimento in base alla svuotatura ( per poter orientare il frame per m_dSideAngle) - Frame3d frPocket ; - Point3d ptCen ; pSrfChunk->GetCentroid( ptCen) ; - frPocket.Set( ptCen, pSrfChunk->GetNormVersor()) ; - frPocket.Rotate( ptCen, pSrfChunk->GetNormVersor(), PockParams.dAngle) ; - - // porto la superficie nel nuovo sistema di riferimento - pSrfChunk->ToLoc( frPocket) ; - - // creo la regione per il percorso a ZigZag - PtrOwner pSrfZigZag( pSrfChunk->Clone()) ; - if ( ! pSrfZigZag->Offset( - dOffs, ICurve::OFF_FILLET)) - return false ; - - // vettore con i percorsi a ZigZag + // vettore con i percorsi a ZigZag relativi al Chunk nC-esimo ICRVCOMPOPOVECTOR vpCrvs ; - // ciclo sui Chunk ottenuti... - for ( int cfz = 0 ; cfz < pSrfZigZag->GetChunkCount() ; ++ cfz) { - // considero un chunk per volta... - PtrOwner pSrfZigZagChunk( pSrfZigZag->CloneChunk( cfz)) ; - if ( IsNull( pSrfZigZagChunk)) + // ciclo sui Chunk ottenuti dal primo offset + for ( int nC1 = 0 ; nC1 < pSrfZigZag->GetChunkCount() ; ++ nC1) { + // recupero il Chunk attuale + PtrOwner pSrfZigZagChunk( pSrfZigZag->CloneChunk( nC1)) ; + if ( IsNull( pSrfZigZagChunk) || ! pSrfZigZagChunk->IsValid()) return false ; + // calcolo i percorsi di ZigZag if ( ! CalcZigZag( pSrfZigZagChunk, PockParams, vpCrvs, false)) return false ; + + // Flag per esistenza di lati aperti per il Chunk nC-esimo + bool bIsChunkClosed = true ; + if ( ! PockParams.bAllClosed) { + if ( ! IsChunkAllClosed( pSrfPock, nC, bIsChunkClosed)) + return false ; + } // aggiorno il vettore delle curve risultati - for ( int u = 0 ; u < int( vpCrvs.size()) ; ++ u) { - - // riportando prima in Globale - vpCrvs[u]->ToGlob( frPocket) ; - - // controllo se il punto iniziale e finale sono esterni alla superficie originale - double dMinDist = max( 0., -PockParams.dRadialOffset) ; - Point3d ptStart ; vpCrvs[u]->GetStartPoint( ptStart) ; - bool bIsInside = false ; - if ( IsPointInsideSurfFr( ptStart, pSfrOrig, dMinDist, bIsInside) && ! bIsInside) { - Vector3d vtMidOut ; vpCrvs[u]->GetStartDir( vtMidOut) ; - vtMidOut.Invert() ; - ExtendPathOnOpenEdge( vpCrvs[u], PockParams, pSrfChunk->GetNormVersor(), vtMidOut, false) ; + for ( int nU = 0 ; nU < int( vpCrvs.size()) ; ++ nU) { + // pulisco le tempProp + ResetCurveTempProps( vpCrvs[nU]) ; + // porto la curva in globale + vpCrvs[nU]->ToGlob( frPocket) ; + // se il Chunk originale aveva lati aperti, estendo il percorso a ZigZag + if ( ! bIsChunkClosed) { + bool bIsInside = false ; + // controllo se il punto iniziale è interno alla superficie originale + Point3d ptStart ; vpCrvs[nU]->GetStartPoint( ptStart) ; + Vector3d vtStart ; vpCrvs[nU]->GetStartDir( vtStart) ; + vtStart.Invert() ; + ptStart.Translate( 0.25 * PockParams.dRad * vtStart) ; + double dMinDist = max( 0., - PockParams.dRadialOffset) ; + if ( IsPointInsideSurfFr( ptStart, pSfrOrig, dMinDist, bIsInside) && ! bIsInside) + ExtendPathOnOpenEdge( vpCrvs[nU], PockParams, pSrfPock->GetNormVersor(), vtStart, false) ; + // controllo se il punto finale è esterno alla superficie originale + Point3d ptEnd ; vpCrvs[nU]->GetEndPoint( ptEnd) ; + Vector3d vtEnd ; vpCrvs[nU]->GetEndDir( vtEnd) ; + ptEnd.Translate( ( 0.25 * PockParams.dRad) * vtEnd) ; + if ( IsPointInsideSurfFr( ptEnd, pSfrOrig, dMinDist, bIsInside) && ! bIsInside) + ExtendPathOnOpenEdge( vpCrvs[nU], PockParams, pSrfPock->GetNormVersor(), vtEnd, true) ; } - Point3d ptEnd ; vpCrvs[u]->GetEndPoint( ptEnd) ; - if ( IsPointInsideSurfFr( ptEnd, pSfrOrig, dMinDist, bIsInside) && ! bIsInside) { - Vector3d vtMidOut ; vpCrvs[u]->GetEndDir( vtMidOut) ; - ExtendPathOnOpenEdge( vpCrvs[u], PockParams, pSrfChunk->GetNormVersor(), vtMidOut, true) ; - } - // inserisco le curve nel vettore risultante - vCrvCompoRes.emplace_back( Release( vpCrvs[u])) ; + vCrvCompoRes.emplace_back( Release( vpCrvs[nU])) ; } // libero il vettore di curve ZigZag per il chunk successivo vpCrvs.clear() ; } + + // se richiesto, aggiungo le curve chiuso di Bordo + if ( PockParams.bAllowZigZagOneWayBorders) { + ICRVCOMPOPOVECTOR vCrvOffs ; + // recupero il Chunk nC-esimo + PtrOwner pSfrChunk( pSrfPock->CloneChunk( nC)) ; + if ( IsNull( pSfrChunk) || ! pSfrChunk->IsValid() || + ! GetZigZagOneWayBorderCrvs( pSfrChunk, PockParams, vCrvCompoRes)) + return false ; + } } return true ; From dfb8fd21601ace88f1e55dc43b0df406d8480b31 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 22 Jul 2024 10:22:36 +0200 Subject: [PATCH 03/11] EgtGeomKernel : - correzione bug nella triangolazione bezier. --- Tree.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Tree.cpp b/Tree.cpp index 57ef219..3f9ee28 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -2642,6 +2642,13 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, plSimplePolygon.RemoveAlignedPoints() ; pCC->FromPolyLine( plSimplePolygon) ; IntersCurveCurve icc( clTrim, *pCC) ; + if ( icc.GetCrossOrOverlapIntersCount() < 1) { + CurveLine clTrimExtended = clTrim ; + clTrimExtended.ExtendEndByLen( 5 * EPS_SMALL) ; + clTrimExtended.ExtendStartByLen( 5 * EPS_SMALL) ; + IntersCurveCurve iccRetry( clTrimExtended, *pCC) ; + icc = iccRetry ; + } IntCrvCrvInfo iccInfo ; if ( icc.GetOverlaps()) { for ( int i = 0 ; i < icc.GetIntersCount() ; ++i) { @@ -2654,12 +2661,15 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, } else { int nLastInters = icc.GetIntersCount() -1 ; + if( nLastInters < 0) + return false ; icc.GetIntCrvCrvInfo( nLastInters, iccInfo) ; ptInters = iccInfo.IciA[0].ptI ; } // determino il lato/vertice di uscita - OnWhichEdge( nId, ptInters, nEdge) ; + if( ! OnWhichEdge( nId, ptInters, nEdge)) + return false ; m_mTree[nId].m_vInters.back().nOut = nEdge ; // se è risultato che sono abbastanza vicino( di EPS_SMALL) ad un vertice allora il punto aggiunto sarà il vertice vero e proprio // se è abbastanza vicino ad un lato allora modifico le sue coordinate in modo che sia esattamente sul lato From d491536eb4a55c45e25d2456063dd06de1f9ff3f Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 22 Jul 2024 11:18:01 +0200 Subject: [PATCH 04/11] EgtGeomKernel : - piccola aggiunta al CopyFrom delle Surf Bezier. --- SurfBezier.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index d46de25..d695a22 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -628,6 +628,8 @@ SurfBezier::CopyFrom( const SurfBezier& sbSrc) m_bTrimmed = true ; m_pTrimReg = sbSrc.m_pTrimReg->Clone() ; } + if ( sbSrc.m_pSTM != nullptr) + m_pSTM = sbSrc.m_pSTM->Clone() ; m_nTempProp[0] = sbSrc.m_nTempProp[0] ; m_nTempProp[1] = sbSrc.m_nTempProp[1] ; m_dTempParam[0] = sbSrc.m_dTempParam[0] ; From 71f3bf88093ffa599bb90afdadc0a9b1b8b68e89 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Mon, 22 Jul 2024 11:46:39 +0200 Subject: [PATCH 05/11] EgtMachKernel : - in calcPocketing, migliorata la gestione di superfici con isole sia aperte che chiuse, gestito caso di circonferenza tutta aperta e modifica del parametro MinSafe. --- CalcPocketing.cpp | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 43cdea4..86fb4b8 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -51,7 +51,7 @@ struct PocketParams { double dRadialOffset = 0. ; // offset radiale double dRadialOffset_prec = -1. ; // offset radiale precedente double dOpenEdgeRad = 0. ; // massimo raggio per estensione lati aperti - double dOpenMinSafe = 2. ; // estensione minima di sicurezza + double dOpenMinSafe = 5. ; // estensione minima di sicurezza double dMaxOptSize = 0. ; // dimensione per ottimizzazione double dAngle = 0. ; // angolo per orientare le passate OneWay e ZigZag bool bOptOffsets = true ; // flag per evitare Offset non necessari in SpiralIn/Out @@ -1858,7 +1858,7 @@ AdjustOpenCurves( ICRVCOMPOPOVECTOR& vCrvCompo, const PocketParams& PockParams, Point3d ptStart ; vCrvCompo[i]->GetStartPoint( ptStart) ; Vector3d vtStart ; vCrvCompo[i]->GetStartDir( vtStart) ; // recupero il punto di caduta dell'utensile - Point3d ptFall = ptStart - vtStart * ( 2 * PockParams.dRad + PockParams.dOpenMinSafe) ; + Point3d ptFall = ptStart - vtStart * ( PockParams.dRad + PockParams.dOpenMinSafe) ; // controllo che il tool non sia interno alla regione limite bool bAllowLeadIn = ( ! pSfrLimit->IsValid()) ; if ( ! bAllowLeadIn) { @@ -1872,7 +1872,7 @@ AdjustOpenCurves( ICRVCOMPOPOVECTOR& vCrvCompo, const PocketParams& PockParams, // se esiste intersezione con la limite Offsettata, provo a ruotare di 90° il tratto lineare if ( ! bAllowLeadIn) { vtStart.Rotate( Z_AX, PockParams.bInvert ? - ANG_RIGHT : ANG_RIGHT) ; - ptFall = ptStart + vtStart * ( 2 * PockParams.dRad + PockParams.dOpenMinSafe) ; + ptFall = ptStart + vtStart * ( PockParams.dRad + PockParams.dOpenMinSafe) ; if ( ! pCrvToolShape->Set( ptFall, Z_AX, PockParams.dRad - 100 * EPS_SMALL)) return false ; ccClass.clear() ; @@ -2208,8 +2208,13 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams, ICRVCOMP if ( dMaxOffs < 2 * PockParams.dRad + 2 * PockParams.dRadialOffset) continue ; // altrimenti, estendo l'isola aperta - ICRVCOMPOPOVECTOR vCrvExtLoop ; vCrvExtLoop.emplace_back( pCrvEL->Clone()) ; - if ( ! AdjustContourWithOpenEdges( pCrvIsl, vCrvExtLoop, PockParams)) + ICRVCOMPOPOVECTOR vCrvOther ; + vCrvOther.emplace_back( pCrvEL->Clone()) ; + for ( int nII = 0 ; nII < int( vCrvIsl.size()) ; ++ nII) { + if ( nII != nI) + vCrvOther.emplace_back( vCrvIsl[nII]->Clone()) ; + } + if ( ! AdjustContourWithOpenEdges( pCrvIsl, vCrvOther, PockParams)) return false ; bIsChunkModified = true ; } @@ -6187,6 +6192,14 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int bool bOk = CalcCircleSpiral( ptCen, vtN, dRad - dOffs, dIntRad, PockParams, pMCrv, pRCrv) ; if ( bOk) { pMCrv->GetStartPoint( ptStart) ; + for ( int u = 0 ; u < pCrvBorder->GetCurveCount() ; ++ u) { + if ( pCrvBorder->GetCurve( u)->GetTempProp( 0) == TEMP_PROP_OPEN_EDGE) { + bMidOut = true ; + pMCrv->GetStartDir( vtMidOut) ; + vtMidOut.Rotate( pSrfPock->GetNormVersor(), PockParams.bInvert ? ANG_RIGHT : - ANG_RIGHT) ; + break ; + } + } nReg = 1 ; return true ; } From 5375752609b4f4e02c74cfa4eb3fe34aae833174 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Tue, 23 Jul 2024 11:52:43 +0200 Subject: [PATCH 06/11] EgtGeomKernel : - in CalcPocketing aggiunto un frame Locale XY per semplificazione conti e migliorata la gestione della svuotature a trapezio. --- CalcPocketing.cpp | 278 ++++++++++++++++++---------------------------- 1 file changed, 109 insertions(+), 169 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 86fb4b8..393edbc 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -69,12 +69,10 @@ struct PocketParams { double dToolFeed = 1000 ; // feed del tool // ------------------------------------------------------- bool bAllClosed = true ; // flag per indicare se tutti i bordi sono chiusi + Frame3d frLocXY ; // frame per conti nel piano XY } ; static double TOL_TRAPEZOID = 50 * EPS_SMALL ; // tolleranza per casi a trapezio SpiralPocket -static int TMP_PROP_SINGLE_CURVE = 3 ; // percorso singola curva aperta ( seguendo i chiusi) -static int TMP_PROP_CRV_OPEN_SIDE = 2 ; // segmento per entrata da fuori -static int TMP_PROP_OPT_TRAPEZOID = 4 ; // caso ottimizzato Trapezio //--------------------------------------------------------------------------- @@ -1066,8 +1064,8 @@ AdjustTrapezoidSpiralForLeadInLeadOut( ICurveComposite* pCompo, const PocketPara //---------------------------------------------------------------------------- static bool -ExtendPathOnOpenEdge( ICurveComposite* pCrvPath, const PocketParams& PockParams, const Vector3d& vtN, - Vector3d& vtMidOut, bool bEndOrStart) +ExtendPathOnOpenEdge( ICurveComposite* pCrvPath, const PocketParams& PockParams, Vector3d& vtMidOut, + bool bEndOrStart) { // controllo dei parametri if ( pCrvPath == nullptr || ! pCrvPath->IsValid()) @@ -1088,7 +1086,7 @@ ExtendPathOnOpenEdge( ICurveComposite* pCrvPath, const PocketParams& PockParams, if ( ! PockParams.SfrLimit.IsValid()) { // aggiungo al ritorno l'uscita pCrvPath->AddLine( ptOut, bEndOrStart) ; - pCrvPath->SetCurveTempProp( ( bEndOrStart ? pCrvPath->GetCurveCount() - 1 : 0), TMP_PROP_CRV_OPEN_SIDE, 0) ; // nProp 2 per le curve LeadIn/Out + pCrvPath->SetCurveTempProp( ( bEndOrStart ? pCrvPath->GetCurveCount() - 1 : 0), TEMP_PROP_OUT_START, 0) ; // nProp 2 per le curve LeadIn/Out pCrvPath->SetCurveTempParam( ( bEndOrStart ? pCrvPath->GetCurveCount() - 1 : 0), GetMinFeed( PockParams) , 0) ; // Feed minima return true ; } @@ -1099,14 +1097,6 @@ ExtendPathOnOpenEdge( ICurveComposite* pCrvPath, const PocketParams& PockParams, // Offset della regione pSfrLimit->Offset( PockParams.dRad + PockParams.dRadialOffset, ICurve::OFF_FILLET) ; - // creo sistema di riferimento locale per piano XY - Point3d ptFr ; pCrvPath->GetStartPoint( ptFr) ; - Frame3d frLoc ; - if ( ! frLoc.Set( ptFr, vtN)) - return false ; - - // porto la superficie limite in questo frame - pSfrLimit->ToLoc( frLoc) ; // ruoto il versore di uscita cercando un'entrata valida Vector3d vtRotMidOut = vtMidOut ; @@ -1115,19 +1105,17 @@ ExtendPathOnOpenEdge( ICurveComposite* pCrvPath, const PocketParams& PockParams, PtrOwner pCrvToolShape( CreateCurveArc()) ; if ( IsNull( pCrvToolShape) || ! pCrvToolShape->Set( ptOut, Z_AX, PockParams.dRad)) return false ; - // porto la curva nel frame locale - pCrvToolShape->ToLoc( frLoc) ; // controllo l'intersezione ( pSfrLimit e pCrvToolShape sono nel piano XY) CRVCVECTOR ccClass ; if ( pSfrLimit->GetCurveClassification( *pCrvToolShape, EPS_SMALL, ccClass) && int( ccClass.size()) == 1 && ccClass[0].nClass == CRVC_OUT) { // aggiungo al ritorno l'uscita pCrvPath->AddLine( ptOut, bEndOrStart) ; - pCrvPath->SetCurveTempProp( ( bEndOrStart ? pCrvPath->GetCurveCount() - 1 : 0), TMP_PROP_CRV_OPEN_SIDE, 0) ; // nProp 2 per le curve LeadIn/Out + pCrvPath->SetCurveTempProp( ( bEndOrStart ? pCrvPath->GetCurveCount() - 1 : 0), TEMP_PROP_OUT_START, 0) ; // nProp 2 per le curve LeadIn/Out pCrvPath->SetCurveTempParam( ( bEndOrStart ? pCrvPath->GetCurveCount() - 1 : 0), GetMinFeed( PockParams) , 0) ; // Feed minima return true ; } - vtRotMidOut.Rotate( vtN, - ANG_RIGHT) ; + vtRotMidOut.Rotate( Z_AX, - ANG_RIGHT) ; ptOut = ptMidOpen + vtRotMidOut * ( PockParams.dRad + PockParams.dOpenMinSafe) ; } @@ -1814,13 +1802,17 @@ ChainCompoCurves( ICRVCOMPOPOVECTOR& vCrvCompo) //---------------------------------------------------------------------------- static bool -AdjustOpenCurves( ICRVCOMPOPOVECTOR& vCrvCompo, const PocketParams& PockParams, bool bCalcFeed) +AdjustBorderCurves( ICRVCOMPOPOVECTOR& vCrvCompo, const PocketParams& PockParams, bool bCalcFeed) { /* sistemazione punto di inizio, segmento per LeadIn, e Feed ( Se la curva è chiusa, allora si può cambiare il punto d'inizio) */ + // se non ho curve, allora non faccio nulla + if ( vCrvCompo.empty()) + return true ; + // controllo validità delle curve for ( int i = 0 ; i < int( vCrvCompo.size()) ; ++ i) if ( IsNull( vCrvCompo[i]) || ! vCrvCompo[i]->IsValid()) @@ -1835,8 +1827,6 @@ AdjustOpenCurves( ICRVCOMPOPOVECTOR& vCrvCompo, const PocketParams& PockParams, pSfrLimit.Set( PockParams.SfrLimit.Clone()) ; if ( IsNull( pSfrLimit) || ! pSfrLimit->IsValid()) return false ; - // effettuo un Offset della regione, tutto ciò che dista più del raggio utensile non la rovina - pSfrLimit->Offset( PockParams.dRad - 250 * EPS_SMALL, ICurve::OFF_FILLET) ; // c'è un offset radiale, quindi tengo tolleranza alta } // per ogni curva signola, aggiungo l'entrata da fuori se ammissibile @@ -1882,7 +1872,7 @@ AdjustOpenCurves( ICRVCOMPOPOVECTOR& vCrvCompo, const PocketParams& PockParams, } if ( bAllowLeadIn) { // se ammessa entrata da fuori vCrvCompo[i]->AddLine( ptFall, false) ; - vCrvCompo[i]->SetCurveTempProp( 0, TMP_PROP_CRV_OPEN_SIDE, 0) ; // nProp 2 per le curve LeadIn/Out + vCrvCompo[i]->SetCurveTempProp( 0, TEMP_PROP_OUT_START, 0) ; // nProp 2 per le curve LeadIn/Out vCrvCompo[i]->SetCurveTempParam( 0, GetMinFeed( PockParams) , 0) ; // Feed massima break ; // interrompo a prescindere l'iterazione per i punti iniziali } @@ -1904,7 +1894,7 @@ AdjustOpenCurves( ICRVCOMPOPOVECTOR& vCrvCompo, const PocketParams& PockParams, GetFeedForParam( 2 * dMaxOffs, PockParams, dFeed) ; AssignCustomFeed( vCrvCompo[i], PockParams, dFeed) ; // imposto il flag di curva singola - vCrvCompo[i]->SetTempProp( TMP_PROP_SINGLE_CURVE, 0) ; //nProp per curva singola + vCrvCompo[i]->SetTempProp( TEMP_PROP_SINGLE_CURVE, 0) ; //nProp per curva singola } } @@ -2264,7 +2254,7 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams, ICRVCOMP if ( ! ChainCompoCurves( vCrvCompoRes)) return false ; // determino ora il punto di inizio, il tratto per il LeadIn e la Feed delle curve singole - if ( ! AdjustOpenCurves( vCrvCompoRes, PockParams, true)) + if ( ! AdjustBorderCurves( vCrvCompoRes, PockParams, true)) return false ; // se ho rimosso tutti i Chunk con una singola curva, allora ho terminato la svuotatura @@ -2289,7 +2279,7 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams, ICRVCOMP //---------------------------------------------------------------------------- static bool GetParamOnOpenSide( const ICurveComposite* pCompo, const ICRVCOMPOPOVECTOR& vOtherCrv, - const Frame3d& frPocket, const PocketParams& PockParams, Point3d& ptMid, Vector3d& vtMidOrt) + const PocketParams& PockParams, Point3d& ptMid, Vector3d& vtMidOrt) { // recupero il vettore estrusione Vector3d vtExtr = Z_AX ; @@ -2386,14 +2376,6 @@ GetParamOnOpenSide( const ICurveComposite* pCompo, const ICRVCOMPOPOVECTOR& vOth ptFirstOpenValid = ptMid ; vtFirstOpenValid = vtMidOrt ; } - // controllo se questa quantità è effettivamente fuori dal grezzo - // ( privilegio i lati aperti che sono effettivamente sul bordo del grezzo) - // punto iniziale nel sistema di riferimento globale - Point3d ptStart ; pCompoClone->GetStartPoint( ptStart) ; - ptStart.ToGlob( frPocket) ; - // vettore d'uscita nel sistema di riferimento globale - Vector3d vtMidOut = vtMidOrt ; - vtMidOut.ToGlob( frPocket) ; } } dLenPrev = dLen ; @@ -2419,13 +2401,12 @@ GetParamOnOpenSide( const ICurveComposite* pCompo, const ICRVCOMPOPOVECTOR& vOth //---------------------------------------------------------------------------- static bool -SetSpecialPtStartForOpenEdges( const ICurveComposite* pCrvOrig, const Frame3d& frPocket, - const PocketParams& PockParams, ICurveComposite* pCrvCompo, Point3d& ptStart, +SetSpecialPtStartForOpenEdges( const ICurveComposite* pCrvOrig, const PocketParams& PockParams, + ICurveComposite* pCrvCompo, Point3d& ptStart, Vector3d& vtMidOut, bool& bMidOut) { // controllo dei parametri if ( pCrvOrig == nullptr || ! pCrvOrig->IsValid() || - ! frPocket.IsValid() || pCrvCompo == nullptr || ! pCrvCompo->IsValid()) return false ; @@ -2559,8 +2540,8 @@ AssignOpenCloseTmpPropToFirstOffsCurve( ICurveComposite* pCrv, const PocketParam //---------------------------------------------------------------------------- static bool SetPtStartForPath( ICurveComposite* pCrvOffsAct, const PocketParams& PockParams, const ISurfFlatRegion* pSrfToWork, - const Point3d& ptEndPrec, const Frame3d& frPocket, Point3d& ptStart, - Vector3d& vtMidOut, bool& bMidOut, int nOffs, const ICurveComposite* pCrvOrig) + const Point3d& ptEndPrec, Point3d& ptStart, Vector3d& vtMidOut, bool& bMidOut, + int nOffs, const ICurveComposite* pCrvOrig) { // ============================= INFO ============================================================== // pCrvOffsAct -> Curva di Offset su cui cercare ptStart, vtMidOut, bMidOpen @@ -2678,10 +2659,10 @@ SetPtStartForPath( ICurveComposite* pCrvOffsAct, const PocketParams& PockParams, if ( nOffs == 1 && pCrvOrig != nullptr && pCrvOrig->IsValid()) { // in questo caso le curve a fagiolo dei lati aperti a sinistra e a destra potrebbero // intersecarsi tra loro -> risulta difficile calcolare il versore direzione d'uscita - bOK = SetSpecialPtStartForOpenEdges( pCrvOrig, frPocket, PockParams, pCrv, ptStart, vtMidOut, bMidOut) ; + bOK = SetSpecialPtStartForOpenEdges( pCrvOrig, PockParams, pCrv, ptStart, vtMidOut, bMidOut) ; } if ( ! bOK) /* ( 2.2 ) */ - bMidOut = GetParamOnOpenSide( pCrv, vOtherCrv, frPocket, PockParams, ptStart, vtMidOut) ; + bMidOut = GetParamOnOpenSide( pCrv, vOtherCrv, PockParams, ptStart, vtMidOut) ; } if ( bMidOut) { // se ho trovato e valido, allora imposto il punto inziale trovato const double LEN_OUT = 5 ; @@ -2705,9 +2686,8 @@ SetPtStartForPath( ICurveComposite* pCrvOffsAct, const PocketParams& PockParams, //---------------------------------------------------------------------------- static bool SetAdvancedPtStartForPath( ICRVCOMPOPOVECTOR& vCrvOffsAct, const PocketParams& PockParams, const ISurfFlatRegion* pSrfToWork, - const Point3d& ptEndPrec, const Frame3d& frPocket, Point3d& ptStart, - Vector3d& vtMidOut, bool& bMidOut, int& nIndex, int nOffs, - ICRVCOMPOPOVECTOR& vCrvOrigChunkLoops) + const Point3d& ptEndPrec, Point3d& ptStart, Vector3d& vtMidOut, + bool& bMidOut, int& nIndex, int nOffs, ICRVCOMPOPOVECTOR& vCrvOrigChunkLoops) { // controllo dei parametri for ( int i = 0 ; i < int( vCrvOffsAct.size()) ; ++ i) @@ -2725,9 +2705,8 @@ SetAdvancedPtStartForPath( ICRVCOMPOPOVECTOR& vCrvOffsAct, const PocketParams& P Point3d ptStart_first ; for ( int i = 0 ; i < int( vCrvOffsAct.size()) ; ++ i) { // cambio il suo punto d'inizio dell'Offset attuale - if ( SetPtStartForPath( vCrvOffsAct[i], PockParams, pSrfToWork, ptEndPrec, frPocket, ptStart, - vtMidOut, bMidOut, nOffs, - ( int( vCrvOrigChunkLoops.size()) < i) ? Get( vCrvOrigChunkLoops[i]) : nullptr)) + if ( SetPtStartForPath( vCrvOffsAct[i], PockParams, pSrfToWork, ptEndPrec, ptStart, vtMidOut, + bMidOut, nOffs, ( int( vCrvOrigChunkLoops.size()) < i) ? Get( vCrvOrigChunkLoops[i]) : nullptr)) vCrvOffsAct[i]->GetStartPoint( ptStart) ; else return false ; @@ -2776,7 +2755,7 @@ GetOptCrvIndex( const ISurfFlatRegion* pSfrOrig, const ISurfFlatRegion* pSfrChun // se la superficie originale ha un solo Chunk, allora le curve originali sono già trovate for ( int l = 0 ; l < pSfrOrig->GetLoopCount( 0) ; ++ l) - vCrvOrig.emplace_back( ConvertCurveToComposite( pSfrOrig->GetLoop( 0, l))) ; // sono inizializzate... + vCrvOrig.emplace_back( ConvertCurveToComposite( pSfrOrig->GetLoop( 0, l))) ; if ( pSfrOrig->GetChunkCount() == 1) return true ; @@ -3227,7 +3206,12 @@ GetTrapezoidFromShape( const ICurveComposite* pCrvCompo, ICurveComposite* pCrvTr // se la curva è già un trapezio, non sempre devo adattarla... Point3d pt ; Vector3d vtDir, vtB2, vtOtherDir ; if ( pCrvCompo->IsATrapezoid( 100 * EPS_SMALL, pt, vtDir, vtOtherDir, vtB2)) { - pCrvTrap->AddCurve( pCrvCompo->Clone()) ; + // data la tolleranza, creo la curva a trapezio dai 4 punti + pCrvTrap->AddPoint( pt) ; + pCrvTrap->AddLine( pt + vtDir) ; + pCrvTrap->AddLine( pt + vtOtherDir + vtB2) ; + pCrvTrap->AddLine( pt + vtOtherDir) ; + pCrvTrap->Close() ; // se parallelogramma scelgo come base i lati lunghi Vector3d vtL2( - vtDir + vtOtherDir + vtB2) ; if ( AreSameOrOppositeVectorApprox( vtOtherDir, vtL2)) { @@ -3237,13 +3221,6 @@ GetTrapezoidFromShape( const ICurveComposite* pCrvCompo, ICurveComposite* pCrvTr vtDir.Normalize() ; Vector3d vtOrtho = OrthoCompo( vtOtherDir, vtDir) ; dPocketSize = vtOrtho.Len() ; - // eventuale approssimazione della curva con polyline per ottenere la stessa curva calcolata in ICurveComposite::IsATrapezoid - if ( pCrvCompo->GetCurveCount() > 4) { - PolyLine PL ; - if ( ! pCrvCompo->ApproxWithLines( 100 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, PL)) - return false ; - pCrvTrap->FromPolyLine( PL) ; - } if ( ! CalcTrapezoidSpiralLocalFrame( pCrvTrap, vtDir, frTrap)) return false ; bool bBaseOpen = false ; @@ -6064,7 +6041,7 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con //---------------------------------------------------------------------------- static bool CheckIfOffsetIsNecessary( const ICurveComposite* pCrvOffs, const double dOffs, const int nOffsCount, - const int nIter, const Vector3d& vtN, const PocketParams& PockParams, bool& bInsert) + const int nIter, const PocketParams& PockParams, bool& bInsert) { // controllo dei parametri @@ -6124,7 +6101,7 @@ CheckIfOffsetIsNecessary( const ICurveComposite* pCrvOffs, const double dOffs, c return true ; // frame locale, recupero DimX e DimY - Frame3d frLoc ; frLoc.Set( ptC, vtN, vtX) ; + Frame3d frLoc ; frLoc.Set( ptC, Z_AX, vtX) ; if ( ! frLoc.IsValid()) return true ; BBox3d bBox ; @@ -6163,18 +6140,11 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int if ( IsNull( pSrfToWork) || pSrfToWork->GetChunkCount() == 0) return false; - // porto il Chunk c-esimo nel sistema di riferimento locale - Vector3d vtExtr = pSrfToWork->GetNormVersor() ; - Point3d ptCen ; pSrfToWork->GetCentroid( ptCen) ; - Frame3d frPocket ; frPocket.Set( ptCen, vtExtr) ; - - - // CONTROLLO PER CASI OTTIMIZZATI + // ---------------------------------- Casi ottimizzati ---------------------------------- bool bHasIsland = ( pSrfPock->GetLoopCount( 0) > 1) ; // se non ho isole e curva valida allora controllo casi ottimizzati if ( ! PockParams.bAvoidOpt && ! bHasIsland && ( ! vCrvOrigChunkLoops.empty()) && ! IsNull( vCrvOrigChunkLoops[0])) { - // --------------------------- caso spirale --------------------------------------- PtrOwner pCrvBorder( ConvertCurveToComposite( pSrfPock->GetLoop( 0, 0))) ; if ( IsNull( pCrvBorder) || ! pCrvBorder->IsValid()) @@ -6209,7 +6179,6 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int else return true ; } - // -------------------------- caso trapezoide --------------------------------------- PtrOwner pCrvTrap( CreateCurveComposite()) ; if ( IsNull( pCrvTrap)) @@ -6217,17 +6186,13 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int Frame3d frTrap ; double dPocketSize ; int nBase, nSecondBase ; - vCrvOrigChunkLoops[0]->ToLoc( frPocket) ; if ( ! GetTrapezoidFromShape( vCrvOrigChunkLoops[0], pCrvTrap, frTrap, PockParams, dPocketSize, nBase, nSecondBase)) return false ; - vCrvOrigChunkLoops[0]->ToGlob( frPocket) ; if ( pCrvTrap->IsValid()) { - pCrvTrap->SetExtrusion( vtExtr) ; + pCrvTrap->SetExtrusion( Z_AX) ; if ( nReg == 0) { CalcTrapezoidSpiral( pCrvTrap, frTrap, dPocketSize, nBase, nSecondBase, PockParams, pMCrv, pRCrv, bOptimizedTrap) ; if ( bOptimizedTrap) { - pMCrv->ToGlob( frPocket) ; - pRCrv->ToGlob( frPocket) ; nReg = 1 ; return true ; } @@ -6238,9 +6203,6 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int } - // porto la superficie nel frame corrente - pSrfToWork->ToLoc( frPocket) ; - // ciclo di offset verso l'interno const int MAX_ITER = 1000 ; int nIter = 0 ; @@ -6294,7 +6256,7 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int pCrvCompoBorder->Invert() ; // controllo quali regioni di Offset possono essere sostituite bool bInsert = true ; - if ( ! CheckIfOffsetIsNecessary( pCrvCompoBorder, dOffs - dOffsPrec, int( vOffs.size()), nIter, vtExtr, PockParams, bInsert)) + if ( ! CheckIfOffsetIsNecessary( pCrvCompoBorder, dOffs - dOffsPrec, int( vOffs.size()), nIter, PockParams, bInsert)) return false ; if ( bInsert) vOffs.emplace_back( Release( pCrvCompoBorder)) ; @@ -6335,29 +6297,25 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int return true ; // cambio il punto iniziale della prima Curva di Offset - Point3d ptRef = PockParams.ptEnd ; ptRef.ToLoc( frPocket) ; + Point3d ptRef = PockParams.ptEnd ; Point3d ptNewStart ; - if ( ! IsNull( vCrvOrigChunkLoops[0])) - vCrvOrigChunkLoops[0]->ToLoc( frPocket) ; // Se ho come lavorazione uno SpiralIn posso poter entrare dalle isole aperte... int nIndexSwap = 0 ; // indice del vettore di curve per identificare la curva su cui entrare if ( PockParams.nType == POCKET_SPIRALIN) { - if ( SetAdvancedPtStartForPath( vOffsFirstCurve, PockParams, pSrfToWork, ptRef, frPocket, - ptStart, vtMidOut, bMidOut, nIndexSwap, int( vOffs.size()), vCrvOrigChunkLoops)) + if ( SetAdvancedPtStartForPath( vOffsFirstCurve, PockParams, pSrfToWork, ptRef, ptStart, + vtMidOut, bMidOut, nIndexSwap, int( vOffs.size()), vCrvOrigChunkLoops)) vOffsFirstCurve[nIndexSwap]->GetStartPoint( ptNewStart) ; else return false ; } else { - if ( SetPtStartForPath( vOffs[0], PockParams, pSrfToWork, ptRef, frPocket, ptStart, vtMidOut, bMidOut, + if ( SetPtStartForPath( vOffs[0], PockParams, pSrfToWork, ptRef, ptStart, vtMidOut, bMidOut, int( vOffs.size()), vCrvOrigChunkLoops[0])) vOffs[0]->GetStartPoint( ptNewStart) ; else return false ; } - if ( ! IsNull( vCrvOrigChunkLoops[0])) - vCrvOrigChunkLoops[0]->ToGlob( frPocket) ; // se richiesta inversione for ( int i = 0 ; i < int( vOffs.size()) && PockParams.bInvert ; ++ i) @@ -6387,8 +6345,6 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int return false ; // controllo eventuali parti non svuotate... - if ( ! IsNull( vCrvOrigChunkLoops[0])) - vCrvOrigChunkLoops[0]->ToLoc( frPocket) ; PtrOwner pSrfToCut( CreateSurfFlatRegion()) ; if ( GetUnclearedRegion( vOffsFirstCurve, vOffs, vLinks, vCrvOrigChunkLoops[0], PockParams, pSrfToCut)) { // Modifico i percorsi @@ -6422,15 +6378,7 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int } // setto estrusione - pMCrv->SetExtrusion( vtExtr) ; - - // riporto tutto nel sistema di riferimento originale - pMCrv->ToGlob( frPocket) ; - ptStart.ToGlob( frPocket) ; - vtMidOut.ToGlob( frPocket) ; - if ( ! IsNull( vCrvOrigChunkLoops[0])) - vCrvOrigChunkLoops[0]->ToGlob( frPocket) ; - + pMCrv->SetExtrusion( Z_AX) ; return true ; } @@ -6960,10 +6908,10 @@ AddSpiralIn( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, if ( bOptimizedTrap) { // se caso a trapezio AdjustTrapezoidSpiralForLeadInLeadOut( pMCrv, PockParams) ; AssignFeedSpiralOpt( 1, PockParams, pMCrv) ; - pMCrv->SetTempProp( TMP_PROP_OPT_TRAPEZOID, 0) ; + pMCrv->SetTempProp( TEMP_PROP_OPT_TRAPEZOID, 0) ; } else if ( bSomeOpen) { // se presenza di lati aperti validi - if ( ! ExtendPathOnOpenEdge( pMCrv, PockParams, pSrfChunk->GetNormVersor(), vtMidOut, false)) + if ( ! ExtendPathOnOpenEdge( pMCrv, PockParams, vtMidOut, false)) return false ; } @@ -7026,7 +6974,7 @@ AddSpiralOut( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, if ( bOptimizedTrap) { // se caso a trapezio AdjustTrapezoidSpiralForLeadInLeadOut( pMCrv, PockParams) ; AssignFeedSpiralOpt( 1, PockParams, pMCrv) ; - pMCrv->SetTempProp( TMP_PROP_OPT_TRAPEZOID, 0) ; + pMCrv->SetTempProp( TEMP_PROP_OPT_TRAPEZOID, 0) ; } // inverto i percorsi, perchè sono calcolati dall'esterno all'interno (solo nel caso non ottimizzato) @@ -7064,7 +7012,7 @@ GetZigZagOneWayBorderCrvs( const ISurfFlatRegion* pSfrPock, const PocketParams& pSfrLimit.Set( PockParams.SfrLimit.Clone()) ; if ( IsNull( pSfrLimit) || ! pSfrLimit->IsValid()) return false ; - pSfrLimit->Offset( PockParams.dRad + PockParams.dRadialOffset, ICurve::OFF_FILLET) ; + pSfrLimit->Offset( PockParams.dRad + PockParams.dRadialOffset - 50 * EPS_SMALL, ICurve::OFF_FILLET) ; } // vettore delle curve chiuse Offsettate @@ -7080,8 +7028,8 @@ GetZigZagOneWayBorderCrvs( const ISurfFlatRegion* pSfrPock, const PocketParams& // recupero i tratti con proprietà uniformi ICRVCOMPOPOVECTOR vpCrvs ; GetHomogeneousParts( pCrvLoop, PockParams, vpCrvs) ; - if ( vpCrvs.size() > 1) { // unisco il primo e l'ultimo se estremi compatibili - // NB. GetHomogeneousParts() cambia il punto di inizio nel lato chiuso più lungo ( se presente) + if ( vpCrvs.size() > 1) { + // unisco il primo e l'ultimo se estremi compatibili Point3d ptE ; vpCrvs.back()->GetEndPoint( ptE) ; Point3d ptS ; vpCrvs[0]->GetStartPoint( ptS) ; if ( AreSamePointApprox( ptS, ptE)) { @@ -7089,11 +7037,20 @@ GetZigZagOneWayBorderCrvs( const ISurfFlatRegion* pSfrPock, const PocketParams& vpCrvs.erase( vpCrvs.end() - 1) ; } } + // le isole aperte vanno percorse + bool bOpenIsland = ( nL > 0 && int( vpCrvs.size()) == 1 && + vpCrvs[0]->GetTempProp() == TEMP_PROP_OPEN_EDGE) ; // scorro tutti i tratti chiusi e calcolo l'Offset for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) { - if ( vpCrvs[i]->GetTempProp( 0) == 0) { // se tratto chiuso... - OffsetCurve OffsCrv ; // con offset verso l'interno - if ( OffsCrv.Make( vpCrvs[i], - PockParams.dRad - PockParams.dRadialOffset, ICurve::OFF_FILLET)) { + // se tratto chiuso o isola aperta + if ( vpCrvs[i]->GetTempProp( 0) == TEMP_PROP_CLOSE_EDGE || bOpenIsland) { + // Offset per le curve + OffsetCurve OffsCrv ; + double dOffs = - PockParams.dRad - PockParams.dRadialOffset ; + // se isole, l'Offset è di segno opposto + if ( nL > 0) + dOffs *= -1 ; + if ( OffsCrv.Make( vpCrvs[i], dOffs, ICurve::OFF_FILLET)) { PtrOwner pOffLongestCrv( OffsCrv.GetLongerCurve()) ; while ( ! IsNull( pOffLongestCrv)) { // recupero solo i tratti di curva al di fuori della superficie limite @@ -7129,7 +7086,7 @@ GetZigZagOneWayBorderCrvs( const ISurfFlatRegion* pSfrPock, const PocketParams& if ( ! ChainCompoCurves( vClosedOffs)) return false ; // determino ora il punto di inizio, il tratto per il LeadIn - if ( ! AdjustOpenCurves( vClosedOffs, PockParams, false)) + if ( ! AdjustBorderCurves( vClosedOffs, PockParams, false)) return false ; // Calcolo ora le Feed e restituisco le curve ottenute @@ -7149,25 +7106,19 @@ GetZigZagOneWayBorderCrvs( const ISurfFlatRegion* pSfrPock, const PocketParams& //---------------------------------------------------------------------------- static bool -AddZigZag( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, const PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvCompoRes) +AddZigZag( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, const PocketParams& PockParams, + ICRVCOMPOPOVECTOR& vCrvCompoRes) { // Offset della regione per curva ZigZag double dOffs = PockParams.dRad + PockParams.dRadialOffset ; - // determino il sistema di riferimento in base alla svuotatura - Frame3d frPocket ; - Point3d ptCen ; pSrfPock->GetCentroid( ptCen) ; - if ( ! frPocket.Set( ptCen, pSrfPock->GetNormVersor()) || - ! frPocket.Rotate( ptCen, pSrfPock->GetNormVersor(), PockParams.dAngle)) - return false ; - // ciclo su tutti i chunks della superficie originale for ( int nC = 0 ; nC < pSrfPock->GetChunkCount() ; ++ nC) { // creo la regione per il percorso a ZigZag ( mediante primo Offset) portandola // nel sistema di riferimento creato PtrOwner pSrfZigZag( pSrfPock->CloneChunk( nC)) ; - if ( ! pSrfZigZag->ToLoc( frPocket) || ! pSrfZigZag->Offset( - dOffs, ICurve::OFF_FILLET)) + if ( ! pSrfZigZag->Offset( - dOffs, ICurve::OFF_FILLET)) return false ; // vettore con i percorsi a ZigZag relativi al Chunk nC-esimo ICRVCOMPOPOVECTOR vpCrvs ; @@ -7193,8 +7144,6 @@ AddZigZag( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, con for ( int nU = 0 ; nU < int( vpCrvs.size()) ; ++ nU) { // pulisco le tempProp ResetCurveTempProps( vpCrvs[nU]) ; - // porto la curva in globale - vpCrvs[nU]->ToGlob( frPocket) ; // se il Chunk originale aveva lati aperti, estendo il percorso a ZigZag if ( ! bIsChunkClosed) { bool bIsInside = false ; @@ -7205,13 +7154,13 @@ AddZigZag( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, con ptStart.Translate( 0.25 * PockParams.dRad * vtStart) ; double dMinDist = max( 0., - PockParams.dRadialOffset) ; if ( IsPointInsideSurfFr( ptStart, pSfrOrig, dMinDist, bIsInside) && ! bIsInside) - ExtendPathOnOpenEdge( vpCrvs[nU], PockParams, pSrfPock->GetNormVersor(), vtStart, false) ; + ExtendPathOnOpenEdge( vpCrvs[nU], PockParams, vtStart, false) ; // controllo se il punto finale è esterno alla superficie originale Point3d ptEnd ; vpCrvs[nU]->GetEndPoint( ptEnd) ; Vector3d vtEnd ; vpCrvs[nU]->GetEndDir( vtEnd) ; - ptEnd.Translate( ( 0.25 * PockParams.dRad) * vtEnd) ; + ptEnd.Translate( 0.25 * PockParams.dRad * vtEnd) ; if ( IsPointInsideSurfFr( ptEnd, pSfrOrig, dMinDist, bIsInside) && ! bIsInside) - ExtendPathOnOpenEdge( vpCrvs[nU], PockParams, pSrfPock->GetNormVersor(), vtEnd, true) ; + ExtendPathOnOpenEdge( vpCrvs[nU], PockParams, vtEnd, true) ; } // inserisco le curve nel vettore risultante vCrvCompoRes.emplace_back( Release( vpCrvs[nU])) ; @@ -7220,9 +7169,8 @@ AddZigZag( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, con vpCrvs.clear() ; } - // se richiesto, aggiungo le curve chiuso di Bordo + // se richiesto, aggiungo le curve chiuse di Bordo if ( PockParams.bAllowZigZagOneWayBorders) { - ICRVCOMPOPOVECTOR vCrvOffs ; // recupero il Chunk nC-esimo PtrOwner pSfrChunk( pSrfPock->CloneChunk( nC)) ; if ( IsNull( pSfrChunk) || ! pSfrChunk->IsValid() || @@ -7319,42 +7267,21 @@ AddOneWay( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, con PtrOwner pSrfToPock( pSrfPock->Clone()) ; if ( IsNull( pSrfToPock)) return false ; - - // creo le regioni ideali -------------------------------------------- - // creo un frame di riferimento della svuotatura - Frame3d frLoc ; - Point3d ptC ; pSrfToPock->GetCentroid( ptC) ; - Vector3d vtN = pSrfToPock->GetNormVersor() ; - frLoc.Set( ptC, vtN) ; - pSrfToPock->ToLoc( frLoc) ; - ISURFFRPOVECTOR vSrfFlat ; // vettore delle regioni ideali + // vettore delle regioni ideali + ISURFFRPOVECTOR vSrfFlat ; if ( ! OptimizeChunkOneWay( pSrfToPock, vSrfFlat)) return false ; - // riporto le superfici ideali nel sistema di riferimento globale ( Ogni chunk verrà poi messo nel suo frame) - for ( int i = 0 ; i < int( vSrfFlat.size()) ; ++ i) - vSrfFlat[i]->ToGlob( frLoc) ; - // ------------------------------------------------------------------ - // scorro le regioni ideali for ( int nIs = 0 ; nIs < int( vSrfFlat.size()) ; ++ nIs) { - // copio la superficie ideale - PtrOwner pSrfIdeal( vSrfFlat[nIs]->Clone()) ; - if ( IsNull( pSrfIdeal)) + // copio la superficie ideale ed effettuo il primo Offset + PtrOwner pSrfIdeal( CloneSurfFlatRegion( vSrfFlat[nIs])) ; + if ( IsNull( pSrfIdeal) || ! pSrfIdeal->Offset( - dOffs, ICurve::OFF_FILLET)) return false ; - // effettuo Offset interno - if ( ! pSrfIdeal->Offset( - dOffs, ICurve::OFF_FILLET)) - return false ; - - // creo un frame coerente con i parametri - Frame3d frPocket ; - Point3d ptCen ; pSrfIdeal->GetCentroid( ptCen) ; - frPocket.Set( ptCen, pSrfIdeal->GetNormVersor()) ; - frPocket.Rotate ( ptCen, pSrfIdeal->GetNormVersor(), PockParams.dAngle) ; - pSrfIdeal->ToLoc( frPocket) ; + // recupero il Box della superficie attuale da svuotare BBox3d b3Pocket ; pSrfIdeal->GetLocalBBox( b3Pocket) ; Point3d ptMin ; double dDimX, dDimY, dDimZ ; b3Pocket.GetMinDim( ptMin, dDimX, dDimY, dDimZ) ; @@ -7417,7 +7344,6 @@ AddOneWay( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, con pCrvSegCompo->AddCurve( Release( pCrvSeg)) ; // calcolo la Feed AssignFeedZigZagOneWay( pCrvSegCompo, false, vCrvNull, vLineUnder, vCrvCompoNull, PockParams) ; - pCrvSegCompo->ToGlob( frPocket) ; vCrvCompoRes.emplace_back( Release( pCrvSegCompo)) ; } } @@ -7457,47 +7383,61 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double myParams.bAvoidOpt = bAvoidOpt ; if ( pSfrLimit != nullptr && pSfrLimit->IsValid()) myParams.SfrLimit.CopyFrom( pSfrLimit) ; - - // ------------ gestione dei lati aperti ------------------- - // creo un sistema di riferimento locale Point3d ptCenter ; pSfr->GetCentroid( ptCenter) ; - Vector3d vtN = pSfr->GetNormVersor() ; - Frame3d frLoc ; - if ( ! frLoc.Set( ptCenter, vtN)) + if ( ! myParams.frLocXY.Set( ptCenter, pSfr->GetNormVersor()) || + ! myParams.frLocXY.Rotate( ptCenter, pSfr->GetNormVersor() , myParams.dAngle)) return false ; + // porto la superficie da svuotare in tale sistema PtrOwner pSfrAdj( pSfr->Clone()) ; - if ( IsNull( pSfrAdj) || ! pSfrAdj->ToLoc( frLoc)) + if ( IsNull( pSfrAdj) || ! pSfrAdj->ToLoc( myParams.frLocXY)) return false ; // porto la superficie limite ( se valida) in tale sistema if ( myParams.SfrLimit.IsValid()) - myParams.SfrLimit.ToLoc( frLoc) ; + myParams.SfrLimit.ToLoc( myParams.frLocXY) ; + + // ------------ gestione dei lati aperti ------------------- // modifico la superficie da svuotare estendendo i lati aperti bool bSkipPocket = false ; // se la superficie si svuota mediante curve singole di primo Offset dei chiusi if ( ! ModifySurfByOpenEdges( pSfrAdj, myParams, vCrvCompoRes, bSkipPocket)) return false ; - // se ottengo delle curve si svuotatura di primo Offset, le riporto in globale - for ( int i = 0 ; i < int( vCrvCompoRes.size()) ; ++ i) - vCrvCompoRes[i]->ToGlob( frLoc) ; - if ( bSkipPocket) // se tali curva rimuovono tutta la regione, allora non faccio nulla + // se le curve di primo offset che ho ottenuto, svuotano tutta la superficie, allora ho finito + if ( bSkipPocket) { + // riporto le curve in Globale + for ( int i = 0 ; i < int( vCrvCompoRes.size()) ; ++ i) + vCrvCompoRes[i]->ToGlob( myParams.frLocXY) ; return true ; - // riporto tutto nel frame originale - pSfrAdj->ToGlob( frLoc) ; - if ( myParams.SfrLimit.IsValid()) - myParams.SfrLimit.ToGlob( frLoc) ; + } + // porto una copia della superficie originale nel frame creato + PtrOwner pSfr_Loc( CloneSurfFlatRegion( pSfr)) ; + if ( IsNull( pSfr_Loc) || ! pSfr_Loc->IsValid() || ! pSfr_Loc->ToLoc( myParams.frLocXY)) + return false ; // ------------ calcolo delle curve elementari della superficie ------------------- switch ( nType) { case POCKET_ZIGZAG : - return AddZigZag( pSfrAdj, pSfr, myParams, vCrvCompoRes) ; + if ( ! AddZigZag( pSfrAdj, pSfr_Loc, myParams, vCrvCompoRes)) + return false ; + break ; case POCKET_ONEWAY : - return AddOneWay( pSfrAdj, pSfr, myParams, vCrvCompoRes) ; + if ( ! AddOneWay( pSfrAdj, pSfr_Loc, myParams, vCrvCompoRes)) + return false ; + break ; case POCKET_SPIRALIN : - return AddSpiralIn( pSfrAdj, pSfr, myParams, vCrvCompoRes) ; + if ( ! AddSpiralIn( pSfrAdj, pSfr_Loc, myParams, vCrvCompoRes)) + return false ; + break ; case POCKET_SPIRALOUT : - return AddSpiralOut( pSfrAdj, pSfr, myParams, vCrvCompoRes) ; + if ( ! AddSpiralOut( pSfrAdj, pSfr, myParams, vCrvCompoRes)) + return false ; + break ; } - return false ; + + // riporto tutte le curve ottenute in globale + for ( int i = 0 ; i < int( vCrvCompoRes.size()) ; ++ i) + vCrvCompoRes[i]->ToGlob( myParams.frLocXY) ; + + return true ; } //---------------------------------------------------------------------------- From 5bab4a9aa832a0e5ad120961b62c6088a863215e Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Thu, 25 Jul 2024 12:30:08 +0200 Subject: [PATCH 07/11] EgtGeomKernel : - aggiunti percorsi di bordo In CalcPocketing per ZigZag e OneWay - correzione punti per entrate - migliorie varie. --- CalcPocketing.cpp | 517 +++++++++++++++++++++------------------------- 1 file changed, 235 insertions(+), 282 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 393edbc..70e0aed 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -69,6 +69,7 @@ struct PocketParams { double dToolFeed = 1000 ; // feed del tool // ------------------------------------------------------- bool bAllClosed = true ; // flag per indicare se tutti i bordi sono chiusi + double dOffsExtra = 2. ; // Offset aggiuntivo per percosi a ZigZag/OneWay se richieste le curve di bordo Frame3d frLocXY ; // frame per conti nel piano XY } ; @@ -976,149 +977,61 @@ GetParamForPtStartOnEdge( const ICurve* pCrvCheck, const ICurveComposite* pCrvCo return false ; } -//---------------------------------------------------- -static bool -ComputeTrapezoidSpiralLeadInLeadOut( ICurveComposite* pCompo, const Vector3d& vtMainDir, bool bLeadIn, - const PocketParams& PockParams, bool& bIsOutsideRaw) -{ - // inizializzazione come interno al grezzo - bIsOutsideRaw = false ; - Point3d ptP ; - Vector3d vtDir ; - if ( bLeadIn) { - pCompo->GetStartPoint( ptP) ; - pCompo->GetStartDir( vtDir) ; - } - else { - pCompo->GetEndPoint( ptP) ; - pCompo->GetEndDir( vtDir) ; - } - - // recupero estrusione della curva - Vector3d vtExtr ; pCompo->GetExtrusion( vtExtr) ; - - // recupero info sui lati aperti - int nPropOpen = pCompo->GetTempProp( 0) ; - bool bEdgeOpen = (( nPropOpen & ( bLeadIn ? 8 : 2)) > 0) ; - bool bBase0Open = (( nPropOpen & 1) > 0) ; - bool bBase1Open = (( nPropOpen & 4) > 0) ; - - // recupero info per capire se sto considerando un lato aggiuntivo per pulire angoli - int nIdCrv = ( bLeadIn ? 0 : pCompo->GetCurveCount() - 1) ; - int nExtraEdge ; - pCompo->GetCurveTempProp( nIdCrv, nExtraEdge) ; - - // tento con allungamento se lato inclinato è aperto oppure se sto considerando un lato aggiuntivo per pulire angoli - if ( bEdgeOpen || nExtraEdge == 1) { - - Vector3d vtDirP = ( bLeadIn ? -vtDir : vtDir) ; - Point3d ptNewStart = ptP + vtDirP * ( PockParams.dRad + PockParams.dOpenMinSafe) ; - pCompo->AddLine( ptNewStart, ! bLeadIn) ; - pCompo->SetCurveTempProp( bLeadIn ? 0 : pCompo->GetCurveCount() - 1, 2) ; - bIsOutsideRaw = true ; - } - // tento con attacco ruotato di 90° se non sto considerando un tratto aggiuntivo per pulire angoli - else if (( bBase0Open || bBase1Open) && ! bIsOutsideRaw && nExtraEdge == 0) { - - Vector3d vtDirO = bBase0Open ? vtDir : - vtDir ; - vtDirO.Rotate( vtExtr, ( PockParams.bInvert ? -90 : 90)) ; - - // se vicino al bordo del grezzo - Point3d ptNewStart = ptP + vtDirO * ( PockParams.dRad + PockParams.dOpenMinSafe) ; - pCompo->AddLine( ptNewStart, ! bLeadIn) ; - pCompo->SetCurveTempProp( bLeadIn ? 0 : pCompo->GetCurveCount() - 1, 2) ; - bIsOutsideRaw = true ; - } - - return true ; -} - -//---------------------------------------------------- -static bool -AdjustTrapezoidSpiralForLeadInLeadOut( ICurveComposite* pCompo, const PocketParams& PockParams) -{ - // recupero la direzione principale della svuotatura - Vector3d vtMainDir ; - for ( int i = 0 ; i < pCompo->GetCurveCount() ; i++) { - int nProp ; - if ( pCompo->GetCurveTempProp( i, nProp) && nProp == 0) { - // se non è lato aggiuntivo per la pulitura angoli recupero la sua direzione - pCompo->GetCurve( i)->GetStartDir( vtMainDir) ; - break ; - } - } - - // start point - bool bStartOutside = false ; - ComputeTrapezoidSpiralLeadInLeadOut( pCompo, vtMainDir, true, PockParams, bStartOutside) ; - // end point - bool bEndOutside = false ; - ComputeTrapezoidSpiralLeadInLeadOut( pCompo, vtMainDir, false, PockParams, bEndOutside) ; - - // eventuale inversione della curva per partire sempre dall'esterno del grezzo - if ( bEndOutside && ! bStartOutside) - pCompo->Invert() ; - - return true ; -} - //---------------------------------------------------------------------------- static bool -ExtendPathOnOpenEdge( ICurveComposite* pCrvPath, const PocketParams& PockParams, Vector3d& vtMidOut, - bool bEndOrStart) +ExtendPath( ICurveComposite* pCompo, const ISurfFlatRegion* pSfr, const PocketParams& PockParams, + Vector3d& vtFirstOut, bool bEndOrStart, bool& bOkExtended) { + /* + Estensione della curva pCompo con un segmento lineare. + bEndOrStart: definisce se la curva va estesa all'inizio o alla fine + vtFirstOut: prima direzione su cui tentare l'entrata, se questa non andasse bene + ruoto progressivamente di 90° + La curva viene estesa di un tratto lineare in direzione vtRotOut per una lunghezza + pari a Rad + OffsR + OpenMinSafe. + */ + // controllo dei parametri - if ( pCrvPath == nullptr || ! pCrvPath->IsValid()) + if ( pCompo == nullptr || ! pCompo->IsValid() || + pSfr == nullptr || ! pSfr->IsValid()) return false ; + bOkExtended = false ; + // recupero il punto iniziale/finale della curva - Point3d ptMidOpen ; + Point3d pt ; if ( bEndOrStart) { - if ( ! pCrvPath->GetEndPoint( ptMidOpen)) + if ( ! pCompo->GetEndPoint( pt)) return false ; } else { - if ( ! pCrvPath->GetStartPoint( ptMidOpen)) + if ( ! pCompo->GetStartPoint( pt)) return false ; } - // calcolo il punto di caduta dell'utensile - Point3d ptOut = ptMidOpen + vtMidOut * ( PockParams.dRad + PockParams.dOpenMinSafe) ; - // se non ho una superficie limite, allora aggiungo il tratto - if ( ! PockParams.SfrLimit.IsValid()) { - // aggiungo al ritorno l'uscita - pCrvPath->AddLine( ptOut, bEndOrStart) ; - pCrvPath->SetCurveTempProp( ( bEndOrStart ? pCrvPath->GetCurveCount() - 1 : 0), TEMP_PROP_OUT_START, 0) ; // nProp 2 per le curve LeadIn/Out - pCrvPath->SetCurveTempParam( ( bEndOrStart ? pCrvPath->GetCurveCount() - 1 : 0), GetMinFeed( PockParams) , 0) ; // Feed minima - return true ; - } - // recupero la regione limite - PtrOwner pSfrLimit( PockParams.SfrLimit.Clone()) ; - if ( IsNull( pSfrLimit) || ! pSfrLimit->IsValid()) - return false ; - // Offset della regione - pSfrLimit->Offset( PockParams.dRad + PockParams.dRadialOffset, ICurve::OFF_FILLET) ; - // ruoto il versore di uscita cercando un'entrata valida - Vector3d vtRotMidOut = vtMidOut ; + Vector3d vtRotOut = vtFirstOut ; + double dMinDist = PockParams.dRad + PockParams.dRadialOffset ; for ( int i = 0 ; i < 4 ; ++ i) { - // creo l'ombra del Tool centrato in ptOut - PtrOwner pCrvToolShape( CreateCurveArc()) ; - if ( IsNull( pCrvToolShape) || ! pCrvToolShape->Set( ptOut, Z_AX, PockParams.dRad)) - return false ; - // controllo l'intersezione ( pSfrLimit e pCrvToolShape sono nel piano XY) - CRVCVECTOR ccClass ; - if ( pSfrLimit->GetCurveClassification( *pCrvToolShape, EPS_SMALL, ccClass) && - int( ccClass.size()) == 1 && ccClass[0].nClass == CRVC_OUT) { + // calcolo il punto di caduta dell'utensile + Point3d ptFall = pt + vtRotOut * ( PockParams.dRad + PockParams.dOpenMinSafe) ; + // controllo che sia sufficientemente distante dalla superficie limite + bool bInside = true ; + bool bOkOut = true ; + if ( PockParams.SfrLimit.IsValid()) + bOkOut = ( IsPointInsideSurfFr( ptFall, &PockParams.SfrLimit, dMinDist, bInside) && ! bInside) ; + if ( bOkOut) + bOkOut = ( IsPointInsideSurfFr( ptFall, pSfr, dMinDist, bInside) && ! bInside) ; + if ( bOkOut) { // aggiungo al ritorno l'uscita - pCrvPath->AddLine( ptOut, bEndOrStart) ; - pCrvPath->SetCurveTempProp( ( bEndOrStart ? pCrvPath->GetCurveCount() - 1 : 0), TEMP_PROP_OUT_START, 0) ; // nProp 2 per le curve LeadIn/Out - pCrvPath->SetCurveTempParam( ( bEndOrStart ? pCrvPath->GetCurveCount() - 1 : 0), GetMinFeed( PockParams) , 0) ; // Feed minima + pCompo->AddLine( ptFall, bEndOrStart) ; + pCompo->SetCurveTempProp( ( bEndOrStart ? pCompo->GetCurveCount() - 1 : 0), TEMP_PROP_OUT_START, 0) ; + pCompo->SetCurveTempParam( ( bEndOrStart ? pCompo->GetCurveCount() - 1 : 0), + ( bEndOrStart ? GetMaxFeed( PockParams) : GetMinFeed( PockParams), 0)) ; + bOkExtended = true ; return true ; } - vtRotMidOut.Rotate( Z_AX, - ANG_RIGHT) ; - ptOut = ptMidOpen + vtRotMidOut * ( PockParams.dRad + PockParams.dOpenMinSafe) ; + vtRotOut.Rotate( Z_AX, - ANG_RIGHT) ; } - return true ; } @@ -1668,6 +1581,10 @@ AdjustContourWithOpenEdges( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vCrvI double dRad = dOutEdge + dOffR ; if ( abs( PockParams.dOpenEdgeRad) > 0 && PockParams.dOpenEdgeRad < dRad) dRad = PockParams.dOpenEdgeRad ; + // se lavorazione ZigZag/OneWay con richiesta di curve di Bordo, gli aperti vanno leggermente allargati + if ( PockParams.bAllowZigZagOneWayBorders && + ( PockParams.nType == POCKET_ZIGZAG || PockParams.nType == POCKET_ONEWAY)) + dRad += PockParams.dOffsExtra ; // ricavo i tratti omogenei ICRVCOMPOPOVECTOR vpCrvs ; @@ -1802,12 +1719,8 @@ ChainCompoCurves( ICRVCOMPOPOVECTOR& vCrvCompo) //---------------------------------------------------------------------------- static bool -AdjustBorderCurves( ICRVCOMPOPOVECTOR& vCrvCompo, const PocketParams& PockParams, bool bCalcFeed) +AdvanceExtendCurves( ICRVCOMPOPOVECTOR& vCrvCompo, const ISurfFlatRegion* pSfr, const PocketParams& PockParams) { - /* - sistemazione punto di inizio, segmento per LeadIn, e Feed - ( Se la curva è chiusa, allora si può cambiare il punto d'inizio) - */ // se non ho curve, allora non faccio nulla if ( vCrvCompo.empty()) @@ -1818,83 +1731,65 @@ AdjustBorderCurves( ICRVCOMPOPOVECTOR& vCrvCompo, const PocketParams& PockParams if ( IsNull( vCrvCompo[i]) || ! vCrvCompo[i]->IsValid()) return false ; - // recupero la superficie limite ( se esiste ed è valida) - PtrOwner pSfrLimit( CreateSurfFlatRegion()) ; - if ( IsNull( pSfrLimit)) - return false ; - if ( PockParams.SfrLimit.IsValid()) { // se esiste, allora classifico - // recupero la superficie limite - pSfrLimit.Set( PockParams.SfrLimit.Clone()) ; - if ( IsNull( pSfrLimit) || ! pSfrLimit->IsValid()) - return false ; - } + /* + L'estensione della curva permettendo un'entrata da fuori è valida se il + nuovo punto di Inizio ( ptFall) : + - E' al di fuori della superficie Limite ( di almeno Rad + OffsR) + - E' al di fuori della superifice di svuotatura ( di almeno dRad + OffsR) + */ - // per ogni curva signola, aggiungo l'entrata da fuori se ammissibile + // scorro ogni singola curva composita for ( int i = 0 ; i < int( vCrvCompo.size()) ; ++ i) { + // se la curva è chiusa modifico il punto iniziale nel tratto più lungo + // ne creo una copia resettando le proprietà temporane + if ( vCrvCompo[i]->IsClosed()) { + PtrOwner pCompo( CloneCurveComposite( vCrvCompo[i])) ; + if ( IsNull( pCompo) || ! pCompo->IsValid()) + return false ; + ResetCurveTempProps( pCompo) ; + ICRVCOMPOPOVECTOR vCrvEmpty ; + AdjustContourStart( pCompo, PockParams, vCrvEmpty, false, P_INVALID) ; + Point3d ptStart ; pCompo->GetStartPoint( ptStart) ; + double dUS = 0. ; + vCrvCompo[i]->GetParamAtPoint( ptStart, dUS) ; + vCrvCompo[i]->ChangeStartPoint( dUS) ; + } + + + // calcolo il numero massimo di punti in cui testare l'entrata da fuori int nMaxIter = ( vCrvCompo[i]->IsClosed() ? 4 : 1) ; double dLen = EPS_SMALL ; if ( nMaxIter == 4) vCrvCompo[i]->GetLength( dLen) ; - + // se richiesta inversione della curva, allora inverto if ( PockParams.bInvert) vCrvCompo[i]->Invert() ; - + // scorro il numero di punti su cui tentare l'entrata da fuori for ( int j = 0 ; j < nMaxIter ; ++ j) { - if ( j > 0) - vCrvCompo[i]->ChangeStartPoint( dLen / nMaxIter) ; - - // ricavo punto di inizio e vettore tangente - Point3d ptStart ; vCrvCompo[i]->GetStartPoint( ptStart) ; - Vector3d vtStart ; vCrvCompo[i]->GetStartDir( vtStart) ; - // recupero il punto di caduta dell'utensile - Point3d ptFall = ptStart - vtStart * ( PockParams.dRad + PockParams.dOpenMinSafe) ; - // controllo che il tool non sia interno alla regione limite - bool bAllowLeadIn = ( ! pSfrLimit->IsValid()) ; - if ( ! bAllowLeadIn) { - // calcolo l'ombra del tool centrata in ptFall - PtrOwner pCrvToolShape( CreateCurveArc()) ; - if ( IsNull( pCrvToolShape) || ! pCrvToolShape->Set( ptFall, Z_AX, PockParams.dRad - 100 * EPS_SMALL)) + if ( j > 0) { + double dParAtLen = EPS_SMALL ; + vCrvCompo[i]->GetParamAtLength( dLen / nMaxIter, dParAtLen) ; + vCrvCompo[i]->ChangeStartPoint( dParAtLen) ; + } + // ricavo vettore tangente iniziale e cerco di estendere + Vector3d vtStart ; + vCrvCompo[i]->GetStartDir( vtStart) ; + vtStart.Invert() ; + bool bIsStartExtended = false ; + if ( ! ExtendPath( vCrvCompo[i], pSfr, PockParams, vtStart, false, bIsStartExtended)) + return false ; + if ( ! vCrvCompo[i]->IsClosed()) { + // 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)) return false ; - CRVCVECTOR ccClass ; - bAllowLeadIn = ( pSfrLimit->GetCurveClassification( *pCrvToolShape, EPS_SMALL, ccClass) && - int( ccClass.size()) == 1 && ccClass[0].nClass == CRVC_OUT) ; - // se esiste intersezione con la limite Offsettata, provo a ruotare di 90° il tratto lineare - if ( ! bAllowLeadIn) { - vtStart.Rotate( Z_AX, PockParams.bInvert ? - ANG_RIGHT : ANG_RIGHT) ; - ptFall = ptStart + vtStart * ( PockParams.dRad + PockParams.dOpenMinSafe) ; - if ( ! pCrvToolShape->Set( ptFall, Z_AX, PockParams.dRad - 100 * EPS_SMALL)) - return false ; - ccClass.clear() ; - bAllowLeadIn = ( pSfrLimit->GetCurveClassification( *pCrvToolShape, EPS_SMALL, ccClass) && - int( ccClass.size()) == 1 && ccClass[0].nClass == CRVC_OUT) ; - } + if ( bIsEndExtended) + break ; } - if ( bAllowLeadIn) { // se ammessa entrata da fuori - vCrvCompo[i]->AddLine( ptFall, false) ; - vCrvCompo[i]->SetCurveTempProp( 0, TEMP_PROP_OUT_START, 0) ; // nProp 2 per le curve LeadIn/Out - vCrvCompo[i]->SetCurveTempParam( 0, GetMinFeed( PockParams) , 0) ; // Feed massima - break ; // interrompo a prescindere l'iterazione per i punti iniziali - } - } - } - - // imposto le Feed per tali curve se richiesto - if ( bCalcFeed) { - for ( int i = 0 ; i < int( vCrvCompo.size()) ; ++ i) { - /* - Idea : Feed proporzionale al minimo Offset per annullare la regione - -> Massimo parametro sui bisettori di VORONOI - */ - - // recupero il MaxOffset per la curva - double dMaxOffs = vCrvCompo[i]->GetTempParam( 0) ; - // calcolo la Feed proporzionale a tale Offset - double dFeed ; - GetFeedForParam( 2 * dMaxOffs, PockParams, dFeed) ; - AssignCustomFeed( vCrvCompo[i], PockParams, dFeed) ; - // imposto il flag di curva singola - vCrvCompo[i]->SetTempProp( TEMP_PROP_SINGLE_CURVE, 0) ; //nProp per curva singola + if ( bIsStartExtended) + break ; } } @@ -1902,7 +1797,7 @@ AdjustBorderCurves( ICRVCOMPOPOVECTOR& vCrvCompo, const PocketParams& PockParams } //---------------------------------------------------------------------------- static bool -GetPocketCurvesByCloseEdges( const ISurfFlatRegion* pSfrChunk, const PocketParams& PockParams, +GetPocketCurvesByClosedEdges( const ISurfFlatRegion* pSfrChunk, const PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvCompoRes, bool& bAllRemoved) { // controllo parametri @@ -1986,7 +1881,6 @@ GetPocketCurvesByCloseEdges( const ISurfFlatRegion* pSfrChunk, const PocketParam 1) La curva esterna e mista e non ho isole ( ho già il percorso) 2) La curva esterna è tutta aperta e le isole sono tutte chiuse 3) La curva esterna è tutta chiusa e ho una sola isola aperta ( ho già il percorso) - */ // 1) @@ -2126,7 +2020,7 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams, ICRVCOMP if ( IsNull( pSfrChunk) || ! pSfrChunk->IsValid()) return false ; bool bIsAllRemoved = false ; - GetPocketCurvesByCloseEdges( pSfrChunk, PockParams, vCrvCompoRes, bIsAllRemoved) ; + GetPocketCurvesByClosedEdges( pSfrChunk, PockParams, vCrvCompoRes, bIsAllRemoved) ; if ( bIsAllRemoved) { // se ho rimosso tutto, allora passo la chunk successivo ++ nChunkOneCurve ; @@ -2253,9 +2147,25 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams, ICRVCOMP // potrei doverle riconcatenare if ( ! ChainCompoCurves( vCrvCompoRes)) return false ; - // determino ora il punto di inizio, il tratto per il LeadIn e la Feed delle curve singole - if ( ! AdjustBorderCurves( vCrvCompoRes, PockParams, true)) + // estendo le curve, calcolando anche le Feeds + if ( ! AdvanceExtendCurves( vCrvCompoRes, pSfr, PockParams)) return false ; + // imposto le Feed per tali curve se richiesto + for ( int i = 0 ; i < int( vCrvCompoRes.size()) ; ++ i) { + /* + Idea : Feed proporzionale al minimo Offset per annullare la regione + -> Massimo parametro sui bisettori di VORONOI + */ + + // recupero il MaxOffset per la curva + double dMaxOffs = vCrvCompoRes[i]->GetTempParam( 0) ; + // calcolo la Feed proporzionale a tale Offset + double dFeed ; + GetFeedForParam( 2 * dMaxOffs, PockParams, dFeed) ; + AssignCustomFeed( vCrvCompoRes[i], PockParams, dFeed) ; + // imposto il flag di curva singola + vCrvCompoRes[i]->SetTempProp( TEMP_PROP_SINGLE_CURVE, 0) ; + } // se ho rimosso tutti i Chunk con una singola curva, allora ho terminato la svuotatura bSkipPocket = ( nChunk == nChunkOneCurve) ; @@ -6905,15 +6815,23 @@ AddSpiralIn( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, if ( pMCrv->GetCurveCount() == 0) break ; // passo al chunk originale successivo - if ( bOptimizedTrap) { // se caso a trapezio - AdjustTrapezoidSpiralForLeadInLeadOut( pMCrv, PockParams) ; + bool bIsExtended = false ; + // se caso a trapezio + if ( bOptimizedTrap) { + Vector3d vtRef ; + pMCrv->GetStartDir( vtRef) ; + vtRef.Invert() ; + if ( ! ExtendPath( pMCrv, pSrfPock, PockParams, vtRef, false, bIsExtended)) + return false ; + pMCrv->GetEndDir( vtRef) ; + if ( ! ExtendPath( pMCrv, pSrfPock, PockParams, vtRef, true, bIsExtended)) + return false ; AssignFeedSpiralOpt( 1, PockParams, pMCrv) ; pMCrv->SetTempProp( TEMP_PROP_OPT_TRAPEZOID, 0) ; } - else if ( bSomeOpen) { // se presenza di lati aperti validi - if ( ! ExtendPathOnOpenEdge( pMCrv, PockParams, vtMidOut, false)) - return false ; - } + // se esistenza di lati aperti validi + else if ( bSomeOpen) + ExtendPath( pMCrv, pSfrOrig, PockParams, vtMidOut, false, bIsExtended) ; // inserisco le curve nel vettore vCrvCompoRes.emplace_back( Release( pMCrv)) ; @@ -6971,8 +6889,17 @@ AddSpiralOut( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, if ( pMCrv->GetCurveCount() == 0) break ; // passo al chunk originale successivo + if ( bOptimizedTrap) { // se caso a trapezio - AdjustTrapezoidSpiralForLeadInLeadOut( pMCrv, PockParams) ; + Vector3d vtRef ; + pMCrv->GetStartDir( vtRef) ; + vtRef.Invert() ; + bool bIsExtended = false ; + if ( ! ExtendPath( pMCrv, pSrfPock, PockParams, vtRef, false, bIsExtended)) + return false ; + pMCrv->GetEndDir( vtRef) ; + if ( ! ExtendPath( pMCrv, pSrfPock, PockParams, vtRef, true, bIsExtended)) + return false ; AssignFeedSpiralOpt( 1, PockParams, pMCrv) ; pMCrv->SetTempProp( TEMP_PROP_OPT_TRAPEZOID, 0) ; } @@ -6992,8 +6919,8 @@ AddSpiralOut( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, //---------------------------------------------------------------------------- static bool -GetZigZagOneWayBorderCrvs( const ISurfFlatRegion* pSfrPock, const PocketParams& PockParams, - ICRVCOMPOPOVECTOR& vCrvRes) +GetZigZagOneWayBorderCrvs( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, + const PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvRes) { /* Restituisce le curve di Primo Offset dei lati chiusi per i percorsi a ZigZag e OneWay. @@ -7021,7 +6948,7 @@ GetZigZagOneWayBorderCrvs( const ISurfFlatRegion* pSfrPock, const PocketParams& // scorro i Chunk e i Loop della regione for ( int nC = 0 ; nC < pSfrPock->GetChunkCount() ; ++ nC) { for ( int nL = 0 ; nL < pSfrPock->GetLoopCount( nC) ; ++ nL) { - // Loop come curva composita + // loop come curva composita PtrOwner pCrvLoop( ConvertCurveToComposite( pSfrPock->GetLoop( nC, nL))) ; if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid()) return false ; @@ -7040,15 +6967,15 @@ GetZigZagOneWayBorderCrvs( const ISurfFlatRegion* pSfrPock, const PocketParams& // le isole aperte vanno percorse bool bOpenIsland = ( nL > 0 && int( vpCrvs.size()) == 1 && vpCrvs[0]->GetTempProp() == TEMP_PROP_OPEN_EDGE) ; - // scorro tutti i tratti chiusi e calcolo l'Offset + // scorro tutti i tratti omogenei for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) { // se tratto chiuso o isola aperta if ( vpCrvs[i]->GetTempProp( 0) == TEMP_PROP_CLOSE_EDGE || bOpenIsland) { // Offset per le curve OffsetCurve OffsCrv ; double dOffs = - PockParams.dRad - PockParams.dRadialOffset ; - // se isole, l'Offset è di segno opposto - if ( nL > 0) + // se isola aperta, allora l'offset è verso il suo interno + if ( bOpenIsland) dOffs *= -1 ; if ( OffsCrv.Make( vpCrvs[i], dOffs, ICurve::OFF_FILLET)) { PtrOwner pOffLongestCrv( OffsCrv.GetLongerCurve()) ; @@ -7082,11 +7009,39 @@ GetZigZagOneWayBorderCrvs( const ISurfFlatRegion* pSfrPock, const PocketParams& if ( vClosedOffs.empty()) return true ; + // le curve che ricavo devono essere sempre conenute nella regione che sto svuotando + /* + Se siamo in presenza di isole chiuse molto vicine a lati chiusi non posso estendere il bordo + dell'isola chiusa a piacere, devo limitarlo alla regione di svuotatura + */ + PtrOwner pSfrBucket( CloneSurfFlatRegion( pSfrPock)) ; + if ( IsNull( pSfrBucket) || ! pSfrBucket->IsValid() || + ! pSfrBucket->Offset( - PockParams.dRad - PockParams.dRadialOffset + 50 * EPS_SMALL, ICurve::OFF_FILLET)) + return false ; + ICRVCOMPOPOVECTOR vClosedOffs1 ; + // scorro le curve di Offset chiuse ricavate + for ( int i = 0 ; i < int( vClosedOffs.size()) ; ++ i) { + CRVCVECTOR ccClass ; + if ( pSfrBucket->GetCurveClassification( *vClosedOffs[i], EPS_SMALL, ccClass)) { + for ( int j = 0 ; j < int( ccClass.size()) ; ++ j) { + if ( ccClass[j].nClass == CRVC_IN) { + // recupero il tratto di curva + PtrOwner pCrv( vClosedOffs[i]->CopyParamRange( ccClass[j].dParS, ccClass[j].dParE)) ; + if ( ! IsNull( pCrv) && pCrv->IsValid()) + vClosedOffs1.emplace_back( ConvertCurveToComposite( Release( pCrv))) ; + } + } + } + } + if ( vClosedOffs1.empty()) + return true ; + swap( vClosedOffs, vClosedOffs1) ; + // concateno eventuali percorsi if ( ! ChainCompoCurves( vClosedOffs)) return false ; // determino ora il punto di inizio, il tratto per il LeadIn - if ( ! AdjustBorderCurves( vClosedOffs, PockParams, false)) + if ( ! AdvanceExtendCurves( vClosedOffs, pSfrOrig, PockParams)) return false ; // Calcolo ora le Feed e restituisco le curve ottenute @@ -7097,6 +7052,8 @@ GetZigZagOneWayBorderCrvs( const ISurfFlatRegion* pSfrPock, const PocketParams& // se OneWay -> prima percorro queste curva, quindi la Feed è minima if ( PockParams.nType == POCKET_ONEWAY) AssignMinFeed( vClosedOffs[i], PockParams) ; + // assegno la proprità alla curva composita + vClosedOffs[i]->SetTempProp( TEMP_PROP_BORDER_CURVE, 0) ; // restituisco le curve ottenute vCrvRes.emplace_back( Release( vClosedOffs[i])) ; } @@ -7109,8 +7066,10 @@ static bool AddZigZag( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, const PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvCompoRes) { - // Offset della regione per curva ZigZag + // offset della regione per curva ZigZag double dOffs = PockParams.dRad + PockParams.dRadialOffset ; + if ( PockParams.bAllowZigZagOneWayBorders) + dOffs += PockParams.dOffsExtra ; // ciclo su tutti i chunks della superficie originale for ( int nC = 0 ; nC < pSrfPock->GetChunkCount() ; ++ nC) { @@ -7134,37 +7093,28 @@ AddZigZag( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, con if ( ! CalcZigZag( pSrfZigZagChunk, PockParams, vpCrvs, false)) return false ; - // Flag per esistenza di lati aperti per il Chunk nC-esimo + // controllo esistenza di lati aperti per il Chunk nC-esimo bool bIsChunkClosed = true ; if ( ! PockParams.bAllClosed) { if ( ! IsChunkAllClosed( pSrfPock, nC, bIsChunkClosed)) return false ; - } - // aggiorno il vettore delle curve risultati - for ( int nU = 0 ; nU < int( vpCrvs.size()) ; ++ nU) { - // pulisco le tempProp - ResetCurveTempProps( vpCrvs[nU]) ; // se il Chunk originale aveva lati aperti, estendo il percorso a ZigZag - if ( ! bIsChunkClosed) { - bool bIsInside = false ; - // controllo se il punto iniziale è interno alla superficie originale - Point3d ptStart ; vpCrvs[nU]->GetStartPoint( ptStart) ; - Vector3d vtStart ; vpCrvs[nU]->GetStartDir( vtStart) ; - vtStart.Invert() ; - ptStart.Translate( 0.25 * PockParams.dRad * vtStart) ; - double dMinDist = max( 0., - PockParams.dRadialOffset) ; - if ( IsPointInsideSurfFr( ptStart, pSfrOrig, dMinDist, bIsInside) && ! bIsInside) - ExtendPathOnOpenEdge( vpCrvs[nU], PockParams, vtStart, false) ; - // controllo se il punto finale è esterno alla superficie originale - Point3d ptEnd ; vpCrvs[nU]->GetEndPoint( ptEnd) ; - Vector3d vtEnd ; vpCrvs[nU]->GetEndDir( vtEnd) ; - ptEnd.Translate( 0.25 * PockParams.dRad * vtEnd) ; - if ( IsPointInsideSurfFr( ptEnd, pSfrOrig, dMinDist, bIsInside) && ! bIsInside) - ExtendPathOnOpenEdge( vpCrvs[nU], PockParams, vtEnd, true) ; + for ( int nU = 0 ; nU < int( vpCrvs.size()) ; ++ nU) { + Vector3d vtRef ; vpCrvs[nU]->GetStartDir( vtRef) ; + vtRef.Invert() ; + bool bIsExtended = false ; + if ( ! ExtendPath( vpCrvs[nU], pSfrOrig, PockParams, vtRef, false,bIsExtended)) + return false ; + vpCrvs[nU]->GetEndDir( vtRef) ; + if ( ! ExtendPath( vpCrvs[nU], pSfrOrig, PockParams, vtRef, true, bIsExtended)) + return false ; } - // inserisco le curve nel vettore risultante - vCrvCompoRes.emplace_back( Release( vpCrvs[nU])) ; } + + // inserisco le curve nel vettore risultante + for ( int nU = 0 ; nU < int( vpCrvs.size()) ; ++ nU) + vCrvCompoRes.emplace_back( Release( vpCrvs[nU])) ; + // libero il vettore di curve ZigZag per il chunk successivo vpCrvs.clear() ; } @@ -7174,7 +7124,7 @@ AddZigZag( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, con // recupero il Chunk nC-esimo PtrOwner pSfrChunk( pSrfPock->CloneChunk( nC)) ; if ( IsNull( pSfrChunk) || ! pSfrChunk->IsValid() || - ! GetZigZagOneWayBorderCrvs( pSfrChunk, PockParams, vCrvCompoRes)) + ! GetZigZagOneWayBorderCrvs( pSfrChunk, pSfrOrig, PockParams, vCrvCompoRes)) return false ; } } @@ -7184,73 +7134,69 @@ AddZigZag( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, con //---------------------------------------------------------------------------- static bool -OptimizeChunkOneWay( ISurfFlatRegion* pSrfOrig, ISURFFRPOVECTOR& vSrfIdeal) +OptimizeChunkOneWay( const ISurfFlatRegion* pSfrOrig, ISURFFRPOVECTOR& vSrfIdeal) { // controllo parametri - if ( pSrfOrig == nullptr || pSrfOrig->GetChunkCount() == 0) + if ( pSfrOrig == nullptr || pSfrOrig->GetChunkCount() == 0) return false ; vSrfIdeal.clear() ; - // clono la superficie passata alla funzione - PtrOwner pSrfToPock( pSrfOrig->Clone()) ; - if ( IsNull( pSrfToPock) || pSrfToPock->GetChunkCount() == 0) - return false ; + /* + classifico i chunks in modo da creare delle regioni ideali; una regione ideale è formata + da un chunk principale con tutti gli altri contenuti in esso ( in questo modo ottimizzo i + percorsi per i bordi) + */ - // classifico i chunks in modo da creare delle regioni ideali; una regione ideale è formata da un chunk principale - // con tutti gli altri contenuti in esso ( in questo modo ottimizzo i percorsi per i bordi) - - INTVECTOR vChunksAvailable( pSrfToPock->GetChunkCount(), 1) ; - - for ( int c = 0 ; c < pSrfToPock->GetChunkCount() ; ++ c) { + INTVECTOR vChunksAvailable( pSfrOrig->GetChunkCount(), 1) ; + for ( int nC = 0 ; nC < pSfrOrig->GetChunkCount() ; ++ nC) { PtrOwner pSrfIdeal( CreateSurfFlatRegion()) ; if ( IsNull( pSrfIdeal)) - return false ; - if ( vChunksAvailable[c] == 1) { // se Chunk valido... + return false ; + // se Chunk valido... + if ( vChunksAvailable[nC] == 1) { // prendo la curva esterna - PtrOwner pCrvExt( pSrfToPock->GetLoop( c, 0)) ; + PtrOwner pCrvExt( pSfrOrig->GetLoop( nC, 0)) ; if ( IsNull( pCrvExt)) return false ; - // inserisco il chunk c-esimo ( curva per curva, così non perdo le temp prop) - pSrfIdeal->AddExtLoop( pCrvExt->Clone()) ; // ... inizio a creare la regione ideale da esso - for ( int l = 1 ; l < pSrfToPock->GetLoopCount( c) ; ++ l) - pSrfIdeal->AddIntLoop( pSrfToPock->GetLoop( c, l)) ; - // il chunk c-esimo non è più disponibile... - vChunksAvailable[c] = -1 ; + // inserisco il chunk nC-esimo ( curva per curva, così non perdo le temp prop) + pSrfIdeal->AddExtLoop( pCrvExt->Clone()) ; + for ( int nL = 1 ; nL < pSfrOrig->GetLoopCount( nC) ; ++ nL) + pSrfIdeal->AddIntLoop( pSfrOrig->GetLoop( nC, nL)) ; + // il chunk nC-esimo non è più disponibile... + vChunksAvailable[nC] = -1 ; // scorro tutti gli altri chunk i-esimi ancora disponibili for ( int i = 0 ; i < int( vChunksAvailable.size()) ; ++ i) { if ( vChunksAvailable[i] == 1) { // prendo la curva esterna del chunk i-esimo disponibile - PtrOwner pCrvExtC( pSrfToPock->GetLoop( i, 0)) ; + PtrOwner pCrvExtC( pSfrOrig->GetLoop( i, 0)) ; if ( IsNull( pCrvExtC)) return false ; - // classifico i bordi esterni ( se il bordo del chunk c-esimo contiene o è contenuto nel loop + // classifico i bordi esterni ( se il bordo del chunk nC-esimo contiene o è contenuto nel loop // esterno del chunk i-esimo -> sono chunks appartenenti alla stessa superficie ideale) IntersCurveCurve intCC( *pCrvExtC, *pCrvExt) ; CRVCVECTOR ccClass, ccClass1 ; intCC.GetCurveClassification( 0, EPS_SMALL, ccClass) ; intCC.GetCurveClassification( 1, EPS_SMALL, ccClass1) ; - if (( ccClass.size() == 1 && ccClass[0].nClass == CRVC_IN) || - ( ccClass1.size() == 1 && ccClass1[0].nClass == CRVC_IN)) { + if (( int( ccClass.size()) == 1 && ccClass[0].nClass == CRVC_IN) || + ( int( ccClass1.size()) == 1 && ccClass1[0].nClass == CRVC_IN)) { // inserisco il chunk i-esimo ( curva per curva, così non perdo le temp prop) - pSrfIdeal->AddExtLoop( pSrfToPock->GetLoop( i, 0)) ; - for ( int l = 1 ; l < pSrfToPock->GetLoopCount( i) ; ++ l) - pSrfIdeal->AddIntLoop( pSrfToPock->GetLoop( i, l)) ; + pSrfIdeal->AddExtLoop( pSfrOrig->GetLoop( i, 0)) ; + for ( int nL = 1 ; nL < pSfrOrig->GetLoopCount( i) ; ++ nL) + pSrfIdeal->AddIntLoop( pSfrOrig->GetLoop( i, nL)) ; vChunksAvailable[i] = -1 ; // chunk j-esimo non più disponibile // NB: Se il chunk i-esimo contiene la pSrfIdeal ( quindi chunk i-esimo unito ad eventuali altri chunk // j-esimi precedenti -> prendo come bordo esterno di riferimento il suo e ricontrollo dall'inizio i // chunk disponibili - if (( int)ccClass1.size() == 1 && ccClass1[0].nClass == CRVC_IN) { - pCrvExt.Set( pCrvExtC->Clone()) ; + if ( int( ccClass1.size()) == 1 && ccClass1[0].nClass == CRVC_IN) { + pCrvExt.Set( pCrvExtC) ; i = 0 ; } } } } } - if ( pSrfIdeal->GetChunkCount() > 0) vSrfIdeal.emplace_back( Release( pSrfIdeal)) ; - } return ( ! vSrfIdeal.empty()) ; @@ -7258,19 +7204,18 @@ OptimizeChunkOneWay( ISurfFlatRegion* pSrfOrig, ISURFFRPOVECTOR& vSrfIdeal) //---------------------------------------------------------------------------- static bool -AddOneWay( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, const PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvCompoRes) +AddOneWay( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, const PocketParams& PockParams, + ICRVCOMPOPOVECTOR& vCrvCompoRes) { + // offset della regione per segmenti a ZigZag double dOffs = PockParams.dRad + PockParams.dRadialOffset ; double dExtra = 0. ; - - // copio la regione da svuotare - PtrOwner pSrfToPock( pSrfPock->Clone()) ; - if ( IsNull( pSrfToPock)) - return false ; + if ( PockParams.bAllowZigZagOneWayBorders) + dExtra = PockParams.dOffsExtra ; // vettore delle regioni ideali ISURFFRPOVECTOR vSrfFlat ; - if ( ! OptimizeChunkOneWay( pSrfToPock, vSrfFlat)) + if ( ! OptimizeChunkOneWay( pSrfPock, vSrfFlat)) return false ; // scorro le regioni ideali @@ -7281,6 +7226,12 @@ AddOneWay( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, con if ( IsNull( pSrfIdeal) || ! pSrfIdeal->Offset( - dOffs, ICurve::OFF_FILLET)) return false ; + // se sono richieste le curve di Bordo, le aggiungo + if ( PockParams.bAllowZigZagOneWayBorders) { + if ( ! GetZigZagOneWayBorderCrvs( vSrfFlat[nIs], pSfrOrig, PockParams, vCrvCompoRes)) + return false ; + } + // recupero il Box della superficie attuale da svuotare BBox3d b3Pocket ; pSrfIdeal->GetLocalBBox( b3Pocket) ; Point3d ptMin ; double dDimX, dDimY, dDimZ ; @@ -7291,7 +7242,7 @@ AddOneWay( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, con double dYStep = ( nYStep > 0 ? ( dDimY + 2 * dExtra) / nYStep : 0) ; -- nYStep ; - // vettore dei segmenti al di sotto della linea corrente + // vettore dei segmenti al di sotto della linea corrente ( per le Feed) ICURVEPOVECTOR vLineUnder ; ICURVEPOVECTOR vCrvNull ; ICRVCOMPOPOVECTOR vCrvCompoNull ; @@ -7310,7 +7261,7 @@ AddOneWay( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, con if ( PockParams.bInvert) pLine->Invert() ; - // linea come composita per Feed ( la dovrò spezzare) + // linea come composita per Feed ( la dovrò spezzare in tratti uniformi di Feed) PtrOwner pCrvCompo( CreateCurveComposite()) ; if ( IsNull( pCrvCompo)) return false ; @@ -7359,8 +7310,9 @@ AddOneWay( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, con //---------------------------------------------------------------------------- bool -CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double dStep, double dAngle, - int nType, bool bSmooth, bool bInvert, bool bAvoidOpt, ISurfFlatRegion* pSfrLimit, ICRVCOMPOPOVECTOR& vCrvCompoRes) +CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double dStep, double dAngle, + int nType, bool bSmooth, bool bInvert, bool bAvoidOpt, bool bAllowZigZagOneWayBorders, + const ISurfFlatRegion* pSfrLimit, ICRVCOMPOPOVECTOR& vCrvCompoRes) { // controllo dei parametri if ( pSfr == nullptr || ! pSfr->IsValid() || @@ -7381,6 +7333,7 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double myParams.dSideStep = dStep ; myParams.bInvert = bInvert ; myParams.bAvoidOpt = bAvoidOpt ; + myParams.bAllowZigZagOneWayBorders = bAllowZigZagOneWayBorders ; if ( pSfrLimit != nullptr && pSfrLimit->IsValid()) myParams.SfrLimit.CopyFrom( pSfrLimit) ; Point3d ptCenter ; pSfr->GetCentroid( ptCenter) ; From 1261de4dbbff9cf0d52277d66909111cb1b1d4ce Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Mon, 29 Jul 2024 10:14:02 +0200 Subject: [PATCH 08/11] EgtGeomKernel 2.6g6 : - ricompilazione con cambio versione. --- EgtGeomKernel.rc | Bin 11710 -> 11710 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 2af9636e01343f91b5cc367700e21457a7f2c64e..60be838cbc3d28a4c4f2e03fb90529807f3d2b3b 100644 GIT binary patch delta 94 zcmdlNy)SyhFE&QA&A-_cnHkL{D{|{@_Trkr0u;H;XNwSVW8B;$>;>dw2zN+>g;Df- LFmBFL4&ed-XmlGI delta 94 zcmdlNy)SyhFE&Qg&A-_cnHfzdD{|{@_Trkr0u;H;XNwSVW8B;$>;>dw2zN+>g;Df- LFmBFL4&ed-X4V@L From df10b45c6b8ce5b2aa7776da80412d7ff3a565a2 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Tue, 30 Jul 2024 14:01:17 +0200 Subject: [PATCH 09/11] EgtGeomKernel : - in CalcPocketing aggiunta lavorazione CONFORMAL_ZIGZAG - migliorie varie. --- CalcPocketing.cpp | 667 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 600 insertions(+), 67 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 70e0aed..60dcfd1 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -71,6 +71,7 @@ struct PocketParams { bool bAllClosed = true ; // flag per indicare se tutti i bordi sono chiusi double dOffsExtra = 2. ; // Offset aggiuntivo per percosi a ZigZag/OneWay se richieste le curve di bordo Frame3d frLocXY ; // frame per conti nel piano XY + int nOffsType = ICurve::OFF_FILLET ; // tipologia di Offset per estensione degli aperti } ; static double TOL_TRAPEZOID = 50 * EPS_SMALL ; // tolleranza per casi a trapezio SpiralPocket @@ -724,6 +725,62 @@ AssignFeedSpiralOpt( const int nOptType, const PocketParams& PockParams, ICurveC return true ; } +//---------------------------------------------------------------------------- +static bool +AssignFeedConformalZigZag( ICurveComposite* pCompoPath, const ICurveComposite* pCrvLoop, + const PocketParams& PockParams) +{ + // controllo dei parametri + if ( pCompoPath == nullptr || ! pCompoPath->IsValid()) + return false ; + + // controllo se il Flag per assegnare la Feed è attivo + if ( ! PockParams.bCalcFeed) + return AssignMaxFeed( pCompoPath, PockParams) ; + + // imposto di Default la Feed minima per ogni sottocurva + AssignMinFeed( pCompoPath, PockParams) ; + + // creo la superficie rimossa ( creata con il raggio utensile) + // creo la superficie di classificazione ( creata mediante raggio utensile e SideStep) + // creo la curva da restituire con le Feed Assegnate + PtrOwner pSfrRemoved( CreateSurfFlatRegion()) ; + PtrOwner pSfrClass( CreateSurfFlatRegion()) ; + PtrOwner pCompoPathWithFeed( CreateCurveComposite()) ; + if ( IsNull( pSfrRemoved) || IsNull( pSfrClass) || IsNull( pCompoPathWithFeed)) + return false ; + ICRVCOMPOPOVECTOR vCrvEmpty ; + + // scorro tutte le curve del percorso + for ( int i = 0 ; i < pCompoPath->GetCurveCount() ; ++ i) { + // recupero la singola curva come composita + PtrOwner pSingleCompo( ConvertCurveToComposite( pCompoPath->GetCurve( i)->Clone())) ; + if ( IsNull( pSingleCompo) || ! pSingleCompo->IsValid()) + return false ; + + // calcolo la Feed per tale curva + AssignFeedSpiral( pSingleCompo, pSfrClass, false, vCrvEmpty, pCrvLoop, PockParams, 2 * PockParams.dRad / 3) ; + + // aggiorno la regione svuotata dal Tool + PtrOwner pSfrSingleCompo( GetSurfFlatRegionFromFatCurve( pSingleCompo->Clone(), PockParams.dRad + 5 * EPS_SMALL, false, false)) ; + if ( ! IsNull( pSfrSingleCompo) || ! pSfrSingleCompo->IsValid()) { + if ( ! pSfrClass->IsValid()) + pSfrClass->CopyFrom( pSfrSingleCompo) ; + else + pSfrClass->Add( *pSfrSingleCompo) ; + } + + if ( ! pCompoPathWithFeed->AddCurve( Release( pSingleCompo))) + return false ; + } + + // restituisco la curva se valida + if ( pCompoPathWithFeed->IsValid()) + pCompoPath->CopyFrom( pCompoPathWithFeed) ; + + return true ; +} + //---------------------------------------------------------------------------- static bool ResetCurveTempProps( ICurveComposite* pCrvCompo) @@ -1026,7 +1083,7 @@ ExtendPath( ICurveComposite* pCompo, const ISurfFlatRegion* pSfr, const PocketPa pCompo->AddLine( ptFall, bEndOrStart) ; pCompo->SetCurveTempProp( ( bEndOrStart ? pCompo->GetCurveCount() - 1 : 0), TEMP_PROP_OUT_START, 0) ; pCompo->SetCurveTempParam( ( bEndOrStart ? pCompo->GetCurveCount() - 1 : 0), - ( bEndOrStart ? GetMaxFeed( PockParams) : GetMinFeed( PockParams), 0)) ; + ( bEndOrStart ? GetMaxFeed( PockParams) : GetMinFeed( PockParams)), 0) ; bOkExtended = true ; return true ; } @@ -1231,8 +1288,9 @@ GetHomogeneousParts( ICurveComposite* pCrvCompo, const PocketParams& PockParams, //--------------------------------------------------------------------------- static bool -CreateSurfFrIncidence( const ICurveComposite* pCrv, const Vector3d& vtTanS_, const Vector3d& vtTanE_, - const double dRad, ISurfFlatRegion* pSfrInc) +CreateSurfFrIncidence( const ICurveComposite* pCrv, const PocketParams& PockParams, + const Vector3d& vtTanS_, const Vector3d& vtTanE_, const double dRad, + ISurfFlatRegion* pSfrInc) { // controllo dei parametri if ( pCrv == nullptr || ! pCrv->IsValid()) @@ -1252,7 +1310,7 @@ CreateSurfFrIncidence( const ICurveComposite* pCrv, const Vector3d& vtTanS_, con OffsetCurve OffsCrv ; PtrOwner pOffsExt( CreateCurveComposite()) ; if ( IsNull( pOffsExt) || - ! OffsCrv.Make( pCrv, dRad, ICurve::OFF_FILLET) || + ! OffsCrv.Make( pCrv, dRad, PockParams.nOffsType) || ! pOffsExt.Set( OffsCrv.GetLongerCurve()) || IsNull( pOffsExt)) return false ; @@ -1261,7 +1319,7 @@ CreateSurfFrIncidence( const ICurveComposite* pCrv, const Vector3d& vtTanS_, con PtrOwner pOffsInt( CreateCurveComposite()) ; if ( IsNull( pOffsInt)) return false ; - if ( OffsCrv.Make( pCrv, - dRad, ICurve::OFF_FILLET)) { + if ( OffsCrv.Make( pCrv, - dRad, PockParams.nOffsType)) { PtrOwner pMyCrv( OffsCrv.GetLongerCurve()) ; if ( ! IsNull( pMyCrv) && pMyCrv->IsValid()) pOffsInt.Set( pMyCrv) ; @@ -1336,7 +1394,7 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI // definisco la regione di incidenza PtrOwner pSfrInc( CreateSurfFlatRegion()) ; if ( IsNull( pSfrInc) || - ! CreateSurfFrIncidence( pCrvBorder, vtTanS, vtTanE, dRad + 75 * EPS_SMALL, pSfrInc)) + ! CreateSurfFrIncidence( pCrvBorder, PockParams, vtTanS, vtTanE, dRad + 75 * EPS_SMALL, pSfrInc)) return false ; // creo un vettore con tutte le curve che potrebbero cadere, in parte, nella regione di incidenza @@ -1376,13 +1434,15 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI continue ; // 4) effettuo l'Offset della curva di metà dDiamJ OffsetCurve OffsCrv ; - if ( ! OffsCrv.Make( vpCrvs[cl], - dDiamJ * 0.5 - 20 * EPS_SMALL, ICurve::OFF_FILLET)) + if ( ! OffsCrv.Make( vpCrvs[cl], - dDiamJ * 0.5 - 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 pOffLongestCrv( OffsCrv.GetLongerCurve()) ; while ( ! IsNull( pOffLongestCrv)) { // 6) creo la regione di incidenza di tale curva ( "Curva a fagiolo") - PtrOwner pSfrBean( GetSurfFlatRegionFromFatCurve( Release( pOffLongestCrv), dDiamJ * 0.5, false, false)) ; + bool bSquareEnds = ( PockParams.nOffsType == ICurve::OFF_CHAMFER) ; + bool bSquareMids = ( PockParams.nOffsType == ICurve::OFF_CHAMFER) ; + PtrOwner pSfrBean( GetSurfFlatRegionFromFatCurve( Release( pOffLongestCrv), dDiamJ * 0.5, bSquareEnds, bSquareMids)) ; if ( IsNull( pSfrBean) || ! pSfrBean->IsValid()) return false ; // inverto se necessario @@ -1585,6 +1645,10 @@ 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 + if ( PockParams.nType == POCKET_ZIGZAG && PockParams.bSmooth) + dRad += max( PockParams.dSideStep / 2, PockParams.dRad / 8) ; + // ricavo i tratti omogenei ICRVCOMPOPOVECTOR vpCrvs ; @@ -2026,6 +2090,9 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams, ICRVCOMP ++ nChunkOneCurve ; continue ; } + // controllo se la lavorazione ammatte estensione da aperti + if ( PockParams.nType == POCKET_CONFORMAL_ZIGZAG) + continue ; // vettore delle isole che userò ( le isole aperte piccole sono trascurate) ICRVCOMPOPOVECTOR vCrvToTIsland ; @@ -5950,7 +6017,7 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con //---------------------------------------------------------------------------- static bool -CheckIfOffsetIsNecessary( const ICurveComposite* pCrvOffs, const double dOffs, const int nOffsCount, +CheckIfOffsetIsNecessary( const ICurveComposite* pCrvOffs, const double dOffs, const int nIter, const PocketParams& PockParams, bool& bInsert) { @@ -5964,73 +6031,534 @@ CheckIfOffsetIsNecessary( const ICurveComposite* pCrvOffs, const double dOffs, c return true ; if ( nIter != 0) { // controllo se sono almeno al secondo offset... - - // per ogni curva controllo se il controOffset + 5 * EPS_SMALL genera una regione ... - OffsetCurve OffsCrv ; // considero anche i casi in cui ho bSmallRad - if ( OffsCrv.Make( pCrvOffs, - PockParams.dRad + dOffs - 5 * EPS_SMALL , ICurve::OFF_FILLET)) { - // se questa curva sparisce -> non serve inserirla come offset, non svuota parti aggiuntive - if ( OffsCrv.GetCurveCount() == 0) { - bInsert = false ; - return true ; - } - } - else - return true ; - - // controllo se richista ottimizzazione per Offsets mediante centroidi e medial Axis - if ( ! PockParams.bOptOffsetsAdv || OffsCrv.GetCurveCount() > 1) - return true ; - - PtrOwner pCrvOffLonger( OffsCrv.GetLongerCurve()) ; - if ( IsNull( pCrvOffLonger) || ! pCrvOffLonger->IsValid()) - return true ; - - // Immagine del tool con centro nel centroide della zona da svuotare - Point3d ptC ; pCrvOffLonger->GetCentroid( ptC) ; - PtrOwner pCrvTool( CreateCurveArc()) ; - if( IsNull( pCrvTool)) + // per ogni curva controllo se il suo Offset massimo non genera alcuna regione + double dMaxOffs ; + if ( ! CalcCurveLimitOffset( *pCrvOffs, dMaxOffs)) return false ; - pCrvTool->SetXY( ptC, PockParams.dRad - 5 * EPS_SMALL) ; - - CRVCVECTOR ccClass ; - IntersCurveCurve intCC( *pCrvOffLonger, *pCrvTool) ; - intCC.GetCurveClassification( 1, EPS_SMALL, ccClass) ; - if ( int(ccClass.size()) == 1 && ccClass[0].nClass == CRVC_OUT) { - // centroide + // se questa curva sparisce -> non serve inserirla come offset, non svuota parti aggiuntive + if ( dMaxOffs < PockParams.dRad - dOffs + 5 * EPS_SMALL) { bInsert = false ; return true ; } + } + else + return true ; - // recupero la PolyLine per altezza e lunghezza del Box2D ( rettangolo) - PolyLine pl ; - if ( ! pCrvOffLonger->ApproxWithLines( 100 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, pl)) - return true ; - Vector3d vtX ; - double dLen = 0 ; double dHeight = 0 ; - if ( ! pl.GetMinAreaRectangleXY( ptC, vtX, dLen, dHeight)) - return true ; + // se non richiesto percorso avanzato + if ( ! PockParams.bOptOffsetsAdv) + return true ; - // frame locale, recupero DimX e DimY - Frame3d frLoc ; frLoc.Set( ptC, Z_AX, vtX) ; - if ( ! frLoc.IsValid()) - return true ; - BBox3d bBox ; - frLoc.Invert() ; - pCrvOffLonger->GetBBox( frLoc, bBox) ; - double dDimX = bBox.GetDimX() ; - double dDimY = bBox.GetDimY() ; + OffsetCurve OffsCrv ; // considero anche i casi in cui ho bSmallRad + if ( ! OffsCrv.Make( pCrvOffs, - PockParams.dRad + dOffs - 5 * EPS_SMALL , ICurve::OFF_FILLET)) + return false ; - // se dimensioni accettabili, inserisco - if ( dDimX < 2 * PockParams.dRad - 100 * EPS_SMALL || - dDimY < 2 * 2 * PockParams.dRad - 100 * EPS_SMALL) { - bInsert = false ; - return true ; - } + // controllo se richista ottimizzazione per Offsets mediante centroidi e medial Axis + if ( OffsCrv.GetCurveCount() > 1) + return true ; + + PtrOwner pCrvOffLonger( OffsCrv.GetLongerCurve()) ; + if ( IsNull( pCrvOffLonger) || ! pCrvOffLonger->IsValid()) + return true ; + + // Immagine del tool con centro nel centroide della zona da svuotare + Point3d ptC ; pCrvOffLonger->GetCentroid( ptC) ; + PtrOwner pCrvTool( CreateCurveArc()) ; + if( IsNull( pCrvTool)) + return false ; + pCrvTool->SetXY( ptC, PockParams.dRad - 5 * EPS_SMALL) ; + + CRVCVECTOR ccClass ; + IntersCurveCurve intCC( *pCrvOffLonger, *pCrvTool) ; + intCC.GetCurveClassification( 1, EPS_SMALL, ccClass) ; + if ( int(ccClass.size()) == 1 && ccClass[0].nClass == CRVC_OUT) { + // centroide + bInsert = false ; + return true ; + } + + // recupero la PolyLine per altezza e lunghezza del Box2D ( rettangolo) + PolyLine pl ; + if ( ! pCrvOffLonger->ApproxWithLines( 100 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, pl)) + return true ; + Vector3d vtX ; + double dLen = 0 ; double dHeight = 0 ; + if ( ! pl.GetMinAreaRectangleXY( ptC, vtX, dLen, dHeight)) + return true ; + + // frame locale, recupero DimX e DimY + Frame3d frLoc ; frLoc.Set( ptC, Z_AX, vtX) ; + if ( ! frLoc.IsValid()) + return true ; + BBox3d bBox ; + frLoc.Invert() ; + pCrvOffLonger->GetBBox( frLoc, bBox) ; + double dDimX = bBox.GetDimX() ; + double dDimY = bBox.GetDimY() ; + + // se dimensioni accettabili, inserisco + if ( dDimX < 2 * PockParams.dRad - 100 * EPS_SMALL || + dDimY < 2 * 2 * PockParams.dRad - 100 * EPS_SMALL) { + bInsert = false ; + return true ; } return true ; } +//---------------------------------------------------------------------------- +static bool +ExtendGuideByIteration( ICurveComposite* pCompoTempGuide, const ICurveComposite* pCompoPerimeter, + bool bInverted) +{ + // controllo dei parametri + if ( pCompoTempGuide == nullptr || ! pCompoTempGuide->IsValid() || + pCompoPerimeter == nullptr || ! pCompoPerimeter->IsValid()) + return false ; + + const double EXTENSION_VAL = 1000. ; + + // ricavo il punto finale della guida + Point3d ptEndGuide ; pCompoTempGuide->GetEndPoint( ptEndGuide) ; + // direzione finale della guida + Vector3d vtEndGuide ; pCompoTempGuide->GetEndDir( vtEndGuide) ; + // creo un segmento diretto come il chiuso + PtrOwner pSeg( CreateCurveLine()) ; + if ( IsNull( pSeg) || + ! pSeg->Set( ptEndGuide, ptEndGuide + EXTENSION_VAL * vtEndGuide)) + return false ; + // calcolo l'intersezione tra questo segmento e la curva di perimetro aperta + IntersCurveCurve ICC( *pSeg, *pCompoPerimeter) ; + // se l'unica intersezione è il punto iniziale del segmento, allora non estendo la guida + // ( vale anche nel caso di intersezione con Overlap) + if ( ICC.GetIntersCount() == 1) { + IntCrvCrvInfo aInfo ; + if ( ICC.GetIntCrvCrvInfo( 0, aInfo)) { + if ( AreSamePointApprox( aInfo.IciB[0].ptI, ptEndGuide)) + return true ; + } + } + // passo alla PolyLine del perimetro + PolyLine PL ; + pCompoPerimeter->ApproxWithLines( EPS_SMALL, EPS_ANG_SMALL, ICurve::APL_STD, PL) ; + // cerco il punto più esterno rispetto alla direzione del chiuso + Point3d ptPoly ; + PL.GetFirstPoint( ptPoly) ; + while ( PL.GetNextPoint( ptPoly)) { + if ( ! pSeg->Set( ptEndGuide, ptEndGuide + ( ptPoly - ptEndGuide) * EXTENSION_VAL)) + return false ; + // calcolo l'intersezione tra questo segmento e la curva di perimetro aperta + IntersCurveCurve ICC( *pSeg, *pCompoPerimeter) ; + // se una intersezione, allora di Overlap con punto iniziale e finale definito + if ( ICC.GetIntersCount() == 1) { + IntCrvCrvInfo aInfo ; + if ( ICC.GetIntCrvCrvInfo( 0, aInfo)) { + if ( aInfo.bOverlap) { + if ( AreSamePointApprox( aInfo.IciB[0].ptI, ptEndGuide) && + AreSamePointApprox( aInfo.IciB[1].ptI, ptPoly)) + return ( pCompoTempGuide->AddLine( ptPoly)) ; + } + else { + if ( AreSamePointApprox( aInfo.IciB[0].ptI, ptEndGuide)) + return ( pCompoTempGuide->AddLine( ptPoly)) ; + } + } + } + // se più di una intersezione, allora il perimetro deve essere tutto Interno al segmento + // ( Out nel caso in cui ho le curve invertite) + IntCrvCrvInfo aInfo ; + bool bOk = true ; + for ( int i = 0 ; i < ICC.GetIntersCount() && bOk ; ++ i) { + bOk = ( ICC.GetIntCrvCrvInfo( i, aInfo)) ; + bOk = ( aInfo.bOverlap || + ( aInfo.IciB[0].nPrevTy != ( ! bInverted ? CRVC_OUT : CRVC_IN) && + aInfo.IciB[0].nNextTy != ( ! bInverted ? CRVC_OUT : CRVC_IN))) ; + } + if ( bOk) + return ( pCompoTempGuide->AddLine( ptPoly)) ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +IsCompoMadeBy2DifferentHomogeneousParts( const ICurveComposite* pCompo, const PocketParams& PockParams, + bool& bOk, ICRVCOMPOPOVECTOR& vpCrvs) +{ + // controllo dei parametri + if ( pCompo == nullptr || ! pCompo->IsValid()) + return false ; + bOk = false ; + vpCrvs.clear() ; + + // clono la curva composita ( cambierà il suo punto iniziale) + PtrOwner pCompoCL( CloneCurveComposite( pCompo)) ; + if ( IsNull( pCompoCL) || ! pCompoCL->IsValid()) + return false ; + + // recupero i tratti con proprietà uniformi + GetHomogeneousParts( pCompoCL, PockParams, vpCrvs) ; + if ( vpCrvs.size() > 1) { + // unisco il primo e l'ultimo se estremi compatibili + Point3d ptE ; vpCrvs.back()->GetEndPoint( ptE) ; + Point3d ptS ; vpCrvs[0]->GetStartPoint( ptS) ; + if ( AreSamePointApprox( ptS, ptE)) { + vpCrvs[0]->AddCurve( Release( vpCrvs.back()), false) ; + vpCrvs.erase( vpCrvs.end() - 1) ; + } + } + + // controlloo che la curva abbia esattamente due tratti omogenei + bOk = ( int( vpCrvs.size()) == 2) ; + if ( ! bOk) + vpCrvs.clear() ; + return true ; + +} + +//---------------------------------------------------------------------------- +static bool +CalcCrvGuideConformalZigZag( const ISurfFlatRegion* pSfrChunk, PocketParams& PockParams, ICurveComposite* pCompoGuide, + ICurveComposite* pCompoClass) +{ + // controllo dei parametri + if ( pCompoGuide == nullptr || pCompoClass == nullptr || + pSfrChunk == nullptr || ! pSfrChunk->IsValid()) + return false ; + pCompoGuide->Clear() ; + pCompoClass->Clear() ; + + // la superficie deve avere un Chunk e non avere isole + if ( pSfrChunk->GetChunkCount() > 1 || pSfrChunk->GetLoopCount( 0) > 1) + return true ; + + // ricavo la curva di bordo ( la curva che definisce il perimetro) + PtrOwner pCompoPerimeter( ConvertCurveToComposite( pSfrChunk->GetLoop( 0, 0))) ; + if ( IsNull( pCompoPerimeter) || ! pCompoPerimeter->IsValid()) + return false ; + // controllo che sia formata da esattamente due tratti omogenei + bool b2HP = false ; + ICRVCOMPOPOVECTOR vpCrvs ; + if ( ! IsCompoMadeBy2DifferentHomogeneousParts( pCompoPerimeter, PockParams, b2HP, vpCrvs)) + return false ; + if ( ! b2HP) + return true ; + + // allargo curva di Bordo secondo le specifiche di una lavorazione a SpiralIn + double dRad = PockParams.dRad ; + int nOffsType = PockParams.nOffsType ; + PockParams.dRad = max( dRad / 8, PockParams.dSideStep / 2) ; + PockParams.nOffsType = ICurve::OFF_CHAMFER ; + ICRVCOMPOPOVECTOR vCrvEmpty ; + if ( ! AdjustContourWithOpenEdges( pCompoPerimeter, vCrvEmpty, PockParams)) + return false ; + PockParams.dRad = dRad ; + PockParams.nOffsType = nOffsType ; + + // reucupero ora i due tratti uniformi ( della curva allargata) + if ( ! IsCompoMadeBy2DifferentHomogeneousParts( pCompoPerimeter, PockParams, b2HP, vpCrvs) || + ! b2HP) + return false ; + + // la guida inizialmente è data dal tratto chiuso + // il perimetro coincide con il tratto aperto + PtrOwner pCompoTempGuide( Release( vpCrvs[0])) ; + if ( IsNull( pCompoTempGuide) || ! pCompoTempGuide->IsValid()) + return false ; + + // estendo la curva nel suo tratto finale ed iniziale + for ( int i = 0 ; i < 2 ; ++ i) { + if ( ! ExtendGuideByIteration( pCompoTempGuide, vpCrvs[1], ( i == 1))) + return false ; + // se la guida diventa diventa chiusa, allora esco + if ( ! pCompoTempGuide->IsValid() || pCompoTempGuide->IsClosed()) + return true ; + pCompoTempGuide->Invert() ; + vpCrvs[1]->Invert() ; + } + + // tratto iniziale + Vector3d vtStart ; pCompoTempGuide->GetStartDir( vtStart) ; + Point3d ptStart ; pCompoTempGuide->GetStartPoint( ptStart) ; + PtrOwner pLineStart( CreateCurveLine()) ; + if ( IsNull( pLineStart) || ! pLineStart->Set( ptStart - 1000. * vtStart, ptStart)) + return false ; + // tratto finale ( potrebbe intersecare il tratto iniziale) + Vector3d vtEnd ; pCompoTempGuide->GetEndDir( vtEnd) ; + Point3d ptEnd ; pCompoTempGuide->GetEndPoint( ptEnd) ; + PtrOwner pLineEnd( CreateCurveLine()) ; + if ( IsNull( pLineEnd) || ! pLineEnd->Set( ptEnd, ptEnd + 1000. * vtEnd)) + return false ; + IntersCurveCurve ICC( *pLineStart, *pLineEnd) ; + if ( ICC.GetIntersCount() > 0) { + IntCrvCrvInfo aInfo ; + if ( ICC.GetIntCrvCrvInfo( 0, aInfo)) { + pLineStart->TrimStartAtParam( aInfo.IciA[0].dU) ; + pLineEnd->TrimEndAtParam( aInfo.IciB[0].dU) ; + } + } + // le due estensioni vanno tagliate presso i bordi dei lati aperti estesi + IntersCurveCurve ICCLS( *pLineStart, *vpCrvs[1]) ; + if ( ICCLS.GetIntersCount() > 0) { + IntCrvCrvInfo aInfo ; + for ( int i = 0 ; i < ICCLS.GetCrossIntersCount() ; ++ i) { + if ( ICCLS.GetIntCrvCrvInfo( i, aInfo)) { + if ( ! AreSamePointApprox( aInfo.IciA[ aInfo.bOverlap ? 1 : 0].ptI, ptStart)) + pLineStart->ModifyStart( aInfo.IciA[aInfo.bOverlap ? 1 : 0].ptI) ; + } + } + } + IntersCurveCurve ICCLE( *pLineEnd, *vpCrvs[1]) ; + if ( ICCLE.GetIntersCount() > 0) { + IntCrvCrvInfo aInfo ; + for ( int i = 0 ; i < ICCLE.GetCrossIntersCount() ; ++ i) { + if ( ICCLE.GetIntCrvCrvInfo( 0, aInfo)) { + if ( ! AreSamePointApprox( aInfo.IciA[0].ptI, ptEnd)) + pLineEnd->ModifyEnd( aInfo.IciA[0].ptI) ; + } + } + } + pCompoTempGuide->AddCurve( Release( pLineStart), false) ; + pCompoTempGuide->AddCurve( Release( pLineEnd), true) ; + + // recupero la curva guida + pCompoGuide->CopyFrom( pCompoTempGuide) ; + + // recupero la curva di classificazione ( abballendola) + PolyLine PL ; + pCompoPerimeter->ApproxWithLines( 10 * LIN_TOL_MIN, ANG_TOL_STD_DEG, ICurve::APL_STD, PL) ; + PL.RemoveAlignedPoints( 500 * EPS_SMALL) ; + pCompoPerimeter->Clear() ; + pCompoPerimeter->FromPolyLine( PL) ; + pCompoPerimeter->RemoveSmallDefects( 10 * LIN_TOL_MIN, ANG_TOL_STD_DEG, true) ; + pCompoPerimeter->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG) ; + pCompoClass->CopyFrom( pCompoPerimeter) ; + ResetCurveTempProps( pCompoClass) ; + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +AddAddConformalZigZag( const ISurfFlatRegion* pSfr, PocketParams& PockParams, + ICRVCOMPOPOVECTOR& vCrvCompoRes) +{ + /* + Calcolo ottimizzato di svuotatura mediante Offset progressivi di una guida, raccordati + rispetto al bordo della superficie di Pocketing mediante logica ZigZag + */ + + // controllo dei parametri + if ( pSfr == nullptr || ! pSfr->IsValid()) + return false ; + vCrvCompoRes.clear() ; + + // ciclo sui chunk della regione + for ( int nC = 0 ; nC < pSfr->GetChunkCount() ; ++ nC) { + // recupero il Chunk nC-esimo + PtrOwner pSfrChunk( pSfr->CloneChunk( nC)) ; + if ( IsNull( pSfrChunk) || ! pSfrChunk->IsValid()) + return false ; + + // recupero il massimo Offset del Chunk nC-esimo + double dMaxOffs ; + pSfrChunk->GetMaxOffset( dMaxOffs) ; + // se inferiore del Tool ( ho già svuotato tale Chunk in precedenza) + if ( dMaxOffs < PockParams.dRad + 200 * EPS_SMALL) + continue ; + + // ricavo la guida ideale e la curva su cui tagliare gli Offset a partire dal Chunk nC-esimo + PtrOwner pCrvGuideExt( CreateCurveComposite()) ; + PtrOwner pCrvClass( CreateCurveComposite()) ; + if ( IsNull( pCrvGuideExt) || IsNull( pCrvClass) || + ! CalcCrvGuideConformalZigZag( pSfr, PockParams, pCrvGuideExt, pCrvClass)) + return false ; + // se non è stata trovata una guida ideale, allora passo al Chunk successivo + if ( ! pCrvGuideExt->IsValid() || pCrvGuideExt->GetCurveCount() == 0 || + ! pCrvClass->IsValid() || pCrvClass->GetCurveCount() == 0) { + return true ; + } + + // memorizzo le curve di Offset tagliate a seconda dalla geometria del perimetro + ICRVCOMPOPOVECTOR vCompoInternalOffs ; + const int MAX_ITER = 100 ; + double dOffs = PockParams.dRad + PockParams.dRadialOffset ; + for ( int i = 0 ; i < MAX_ITER ; ++ i) { + OffsetCurve OffsCrv ; + if ( ! OffsCrv.Make( pCrvGuideExt, - dOffs, ICurve::OFF_FILLET)) + return false ; + // se invece ne ottengo più di una, controllo se è necessaria + if ( OffsCrv.GetCurveCount() > 1) { + // recupero le curve extra ( tutte tranne la più lunga) + for ( int j = 0 ; j < OffsCrv.GetCurveCount() - 1 ; ++ j) { + // recupero la curva più corta + PtrOwner pCrvShorter( ConvertCurveToComposite( OffsCrv.GetShorterCurve())) ; + if ( ! IsNull( pCrvShorter) && pCrvShorter->IsValid()) { + // controllo se è davvero necessaria per non lasciare materiale + bool bSkip = false ; + if ( pCrvShorter->IsClosed()) { + CheckIfOffsetIsNecessary( pCrvShorter, ( i == 0 ? dOffs : PockParams.dSideStep), + i, PockParams, bSkip) ; + if ( bSkip) + return true ; + } + } + } + } + // se non ottengo nessuna curva, allora ho finito + PtrOwner pCrvOffs( OffsCrv.GetLongerCurve()) ; + if ( IsNull( pCrvOffs) || ! pCrvOffs->IsValid()) + break ; + // se ottengo una curva chiusa, lavorazione non ammessa + if ( pCrvOffs->IsClosed()) + return true ; + // la inverto se numero di Offset progressivo dispari + if ( ( ! IsEven( i) && ! PockParams.bInvert) || + ( IsEven( i) && PockParams.bInvert)) + pCrvOffs->Invert() ; + // classifico la curva rispetto al perimetro, devo tenere solo le parti interne + CRVCVECTOR ccClass ; + IntersCurveCurve ICC( *pCrvOffs, *pCrvClass) ; + if ( ! ICC.GetCurveClassification( 0, EPS_SMALL, ccClass)) + return true ; + // scorro tutte le classificazioni ottenute + for ( int j = 0 ; j < int( ccClass.size()) ; ++ j) { + // tengo quelle strettamente interne + if ( ccClass[j].nClass == CRVC_IN) { + // recupero la porzione di Offset + PtrOwner pCrvOffs_Int( pCrvOffs->CopyParamRange( ccClass[j].dParS, ccClass[j].dParE)) ; + if ( ! IsNull( pCrvOffs_Int) && pCrvOffs_Int->IsValid()) { + // salvo la curva + vCompoInternalOffs.emplace_back( ConvertCurveToComposite( Release( pCrvOffs_Int))) ; + // salvo come prima propeità temporanea, il numero di Offset progressivo + vCompoInternalOffs.back()->SetTempProp( i, 0) ; + } + } + } + dOffs += PockParams.dSideStep ; + } + // se non ho ottenuto Offset, passo al Chunk successivo + if ( vCompoInternalOffs.empty()) + return true ; + + /* + Creo la curva di Svuotatura come unione di due curve : + - La curva che non deve essere smussata ( curve di primo Offset e raccordi) + - La Curva che necessita di smusso ( le altre) + NB. Nel caso non sia richiesto lo smusso, allora la seconda curva non viene smussata, ma la + logica rimane la stessa. + */ + + PtrOwner pCompoNoSmooth( CreateCurveComposite()) ; + PtrOwner pCompoSmooth( CreateCurveComposite()) ; + if ( IsNull( pCompoNoSmooth) || IsNull( pCompoSmooth)) + return false ; + + + // scorro i tratti di Offset interni e aggiungo i raccordi sul bordo esterno + // raccordo il tratto di Offset interno corrente al successivo + const double TOL_JOINT = 25. * EPS_SMALL ; + double dHalfLenPerimeter ; + pCrvClass->GetLength( dHalfLenPerimeter) ; + dHalfLenPerimeter /= 2. ; + for ( int i = 0 ; i < int( vCompoInternalOffs.size()) - 1 ; ++ i) { + // recupero il parametro iniziale del raccordo sulla curva di perimetro + Point3d ptS ; vCompoInternalOffs[i]->GetEndPoint( ptS) ; + double dUS ; pCrvClass->GetParamAtPoint( ptS, dUS) ; + // recupero il parametro finale del raccordo sulla curva di perimetro + Point3d ptE ; vCompoInternalOffs[i+1]->GetStartPoint( ptE) ; + double dUE ; pCrvClass->GetParamAtPoint( ptE, dUE) ; + // aggiungo il tratto di Offset interno corrente alla curva di svuotatura + if ( vCompoInternalOffs[i]->GetTempProp() == 0) { + // se deriva dal primo Offset + if ( ! pCompoNoSmooth->AddCurve( Release( vCompoInternalOffs[i]), true, TOL_JOINT)) + return false ; + } + else { + // se deriva da Offset successivi + if ( ! pCompoSmooth->AddCurve( Release( vCompoInternalOffs[i]), true, TOL_JOINT)) + return false ; + } + // recupero il tratto di curva di interesse + PtrOwner pCrvJoint( pCrvClass->CopyParamRange( dUS, dUE)) ; + if ( ! IsNull( pCrvJoint) && pCrvJoint->IsValid()) { + double dLen ; + pCrvJoint->GetLength( dLen) ; + if ( dLen > dHalfLenPerimeter) { + pCrvJoint.Set( pCrvClass->CopyParamRange( dUE, dUS)) ; + pCrvJoint->Invert() ; + } + // aggiungo il tratto di percorso + if ( vCompoInternalOffs[i+1]->GetTempProp() == 0) { + // se l'offset successivo deriva ancora dal primo + if ( ! pCompoNoSmooth->AddCurve( Release( pCrvJoint), true, TOL_JOINT)) + return false ; + } + else { + // se l'Offset successivo non deriva dal primo Offset + if ( ! pCompoSmooth->AddCurve( Release( pCrvJoint), true, TOL_JOINT)) + return false ; + } + } + } + // aggiungo l'ultimo tratto di Offset + if ( vCompoInternalOffs.back()->GetTempProp() == 0) { + if ( ! pCompoNoSmooth->AddCurve( Release( vCompoInternalOffs.back()), true, TOL_JOINT)) + return false ; + } + else { + if ( ! pCompoSmooth->AddCurve( vCompoInternalOffs.back()->Clone(), true, TOL_JOINT)) + return false ; + } + // porto l'ultima curva del percorso NoSmooth nel percorso Smooth per avere un raccordo anche + // sul tratto di giunzione tra esse + if ( pCompoSmooth->IsValid() && pCompoNoSmooth->IsValid()) { + PtrOwner pCrv( pCompoNoSmooth->GetLastCurve()->Clone()) ; + if ( IsNull( pCrv) || ! pCrv->IsValid() || + ! pCompoSmooth->AddCurve( Release( pCrv), false, TOL_JOINT)) + return false ; + delete( pCompoNoSmooth->RemoveFirstOrLastCurve( true)) ; + } + + // smusso dove necessario + ModifyCurveToSmoothed( pCompoSmooth, PockParams, PockParams.dRad / 8, PockParams.dRad / 8, false) ; + // creo il percorso di svuotatura + PtrOwner pCompoTempPath( CreateCurveComposite()) ; + if ( IsNull( pCompoTempPath)) + return false ; + if ( pCompoNoSmooth->IsValid() && pCompoNoSmooth->GetCurveCount() > 0) { + if ( ! pCompoTempPath.Set( pCompoNoSmooth)) + return false ; + } + if ( pCompoSmooth->IsValid()) { + if ( ! pCompoTempPath->AddCurve( Release( pCompoSmooth), true, TOL_JOINT)) + return false ; + } + // se la curva finale di Pocketing è valida, allora la resituisco + if ( pCompoTempPath->IsValid()) { + // inverto l'ordine delle curve di Offset ( in modo da partire sempre ad eseguire il percorso + // più lontano dal dai lati chiusi) + pCompoTempPath->Invert() ; + // calcolo la Feed del percorso trovato + if ( ! AssignFeedConformalZigZag( pCompoTempPath, pCrvClass, PockParams)) + return false ; + // aggiugno il tratto iniziale e finale per entrate da fuori + Vector3d vtStart ; pCompoTempPath->GetStartDir( vtStart) ; + vtStart.Invert() ; + bool bExt = false ; + if ( ! ExtendPath( pCompoTempPath, pSfr, PockParams, vtStart, false, bExt)) + return false ; + Vector3d vtEnd ; pCompoTempPath->GetEndDir( vtEnd) ; + if ( ! ExtendPath( pCompoTempPath, pSfr, PockParams, vtEnd, true, bExt)) + return false ; + // sostituisco la curva + if ( pCompoTempPath->IsValid()) + vCrvCompoRes.emplace_back( Release( pCompoTempPath)) ; + } + } + + return true ; +} //---------------------------------------------------------------------------- static bool @@ -6166,7 +6694,7 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int pCrvCompoBorder->Invert() ; // controllo quali regioni di Offset possono essere sostituite bool bInsert = true ; - if ( ! CheckIfOffsetIsNecessary( pCrvCompoBorder, dOffs - dOffsPrec, int( vOffs.size()), nIter, PockParams, bInsert)) + if ( ! CheckIfOffsetIsNecessary( pCrvCompoBorder, dOffs - dOffsPrec, nIter, PockParams, bInsert)) return false ; if ( bInsert) vOffs.emplace_back( Release( pCrvCompoBorder)) ; @@ -7317,7 +7845,8 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double // controllo dei parametri if ( pSfr == nullptr || ! pSfr->IsValid() || dStep < 10 * EPS_SMALL || - ( nType != POCKET_ZIGZAG && nType != POCKET_ONEWAY && nType != POCKET_SPIRALIN && nType != POCKET_SPIRALOUT)) + ( nType != POCKET_ZIGZAG && nType != POCKET_ONEWAY && nType != POCKET_SPIRALIN && + nType != POCKET_SPIRALOUT && nType != POCKET_CONFORMAL_ZIGZAG)) return false ; // pulizia vettore delle curve elementari @@ -7381,7 +7910,11 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double return false ; break ; case POCKET_SPIRALOUT : - if ( ! AddSpiralOut( pSfrAdj, pSfr, myParams, vCrvCompoRes)) + if ( ! AddSpiralOut( pSfrAdj, pSfr_Loc, myParams, vCrvCompoRes)) + return false ; + break ; + case POCKET_CONFORMAL_ZIGZAG : + if ( ! AddAddConformalZigZag( pSfr_Loc, myParams, vCrvCompoRes)) return false ; break ; } From b28102a8cc504976cda20469636f254b4a4b3e4f Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Tue, 30 Jul 2024 18:34:37 +0200 Subject: [PATCH 10/11] EgtGeomKernel : In CalcPocketing per lavorazioni CONFORMAL_ZIGZAG aggiunta gestione aree non svuotate. --- CalcPocketing.cpp | 69 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 22 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 60dcfd1..c36d618 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -728,7 +728,7 @@ AssignFeedSpiralOpt( const int nOptType, const PocketParams& PockParams, ICurveC //---------------------------------------------------------------------------- static bool AssignFeedConformalZigZag( ICurveComposite* pCompoPath, const ICurveComposite* pCrvLoop, - const PocketParams& PockParams) + const PocketParams& PockParams, ISurfFlatRegion* pSfrToRemove) { // controllo dei parametri if ( pCompoPath == nullptr || ! pCompoPath->IsValid()) @@ -736,18 +736,15 @@ AssignFeedConformalZigZag( ICurveComposite* pCompoPath, const ICurveComposite* p // controllo se il Flag per assegnare la Feed è attivo if ( ! PockParams.bCalcFeed) - return AssignMaxFeed( pCompoPath, PockParams) ; + AssignMaxFeed( pCompoPath, PockParams) ; + else + AssignMinFeed( pCompoPath, PockParams) ; - // imposto di Default la Feed minima per ogni sottocurva - AssignMinFeed( pCompoPath, PockParams) ; - - // creo la superficie rimossa ( creata con il raggio utensile) // creo la superficie di classificazione ( creata mediante raggio utensile e SideStep) // creo la curva da restituire con le Feed Assegnate PtrOwner pSfrRemoved( CreateSurfFlatRegion()) ; - PtrOwner pSfrClass( CreateSurfFlatRegion()) ; PtrOwner pCompoPathWithFeed( CreateCurveComposite()) ; - if ( IsNull( pSfrRemoved) || IsNull( pSfrClass) || IsNull( pCompoPathWithFeed)) + if ( IsNull( pSfrRemoved) || IsNull( pCompoPathWithFeed)) return false ; ICRVCOMPOPOVECTOR vCrvEmpty ; @@ -759,21 +756,30 @@ AssignFeedConformalZigZag( ICurveComposite* pCompoPath, const ICurveComposite* p return false ; // calcolo la Feed per tale curva - AssignFeedSpiral( pSingleCompo, pSfrClass, false, vCrvEmpty, pCrvLoop, PockParams, 2 * PockParams.dRad / 3) ; + AssignFeedSpiral( pSingleCompo, pSfrRemoved, false, vCrvEmpty, pCrvLoop, PockParams, 2 * PockParams.dRad / 3) ; // aggiorno la regione svuotata dal Tool PtrOwner pSfrSingleCompo( GetSurfFlatRegionFromFatCurve( pSingleCompo->Clone(), PockParams.dRad + 5 * EPS_SMALL, false, false)) ; if ( ! IsNull( pSfrSingleCompo) || ! pSfrSingleCompo->IsValid()) { - if ( ! pSfrClass->IsValid()) - pSfrClass->CopyFrom( pSfrSingleCompo) ; + if ( ! pSfrRemoved->IsValid()) + pSfrRemoved->CopyFrom( pSfrSingleCompo) ; else - pSfrClass->Add( *pSfrSingleCompo) ; + pSfrRemoved->Add( *pSfrSingleCompo) ; } if ( ! pCompoPathWithFeed->AddCurve( Release( pSingleCompo))) return false ; } + // definisco la regione da svuotare + PtrOwner pMyLoop( CloneCurveComposite( pCrvLoop)) ; + pSfrToRemove->Clear() ; + + if ( ! pSfrToRemove->AddExtLoop( Release( pMyLoop)) || + ! pSfrToRemove->Offset( - PockParams.dRad - PockParams.dRadialOffset, ICurve::OFF_FILLET) || + ! pSfrToRemove->Subtract( *pSfrRemoved)) + pSfrToRemove->Clear() ; // alla peggio non rimuovo le Uncleared Regions... + // restituisco la curva se valida if ( pCompoPathWithFeed->IsValid()) pCompoPath->CopyFrom( pCompoPathWithFeed) ; @@ -2240,12 +2246,13 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams, ICRVCOMP return true ; // restituisco la superficie aggiornata ricavata - if ( ! pSrfFinal->IsValid()) - return false ; - pSfr->Clear() ; - pSfr->CopyFrom( pSrfFinal) ; - return ( pSrfFinal->IsValid() && pSrfFinal->GetChunkCount() > 0) ; - + if ( PockParams.nType != POCKET_CONFORMAL_ZIGZAG) { + if ( ! pSrfFinal->IsValid()) + return false ; + pSfr->Clear() ; + pSfr->CopyFrom( pSrfFinal) ; + } + return ( pSfr->IsValid() && pSfr->GetChunkCount() > 0) ; } // *************************************************************************** @@ -6421,6 +6428,9 @@ AddAddConformalZigZag( const ISurfFlatRegion* pSfr, PocketParams& PockParams, IntersCurveCurve ICC( *pCrvOffs, *pCrvClass) ; if ( ! ICC.GetCurveClassification( 0, EPS_SMALL, ccClass)) return true ; + // se curva tutta esterna ho finito + if ( int( ccClass.size()) == 1 && ccClass[0].nClass == CRVC_OUT) + break ; // scorro tutte le classificazioni ottenute for ( int j = 0 ; j < int( ccClass.size()) ; ++ j) { // tengo quelle strettamente interne @@ -6428,10 +6438,10 @@ AddAddConformalZigZag( const ISurfFlatRegion* pSfr, PocketParams& PockParams, // recupero la porzione di Offset PtrOwner pCrvOffs_Int( pCrvOffs->CopyParamRange( ccClass[j].dParS, ccClass[j].dParE)) ; if ( ! IsNull( pCrvOffs_Int) && pCrvOffs_Int->IsValid()) { + // salvo come prima proprietà temporanea, il numero di Offset progressivo + pCrvOffs_Int->SetTempProp( i, 0) ; // salvo la curva vCompoInternalOffs.emplace_back( ConvertCurveToComposite( Release( pCrvOffs_Int))) ; - // salvo come prima propeità temporanea, il numero di Offset progressivo - vCompoInternalOffs.back()->SetTempProp( i, 0) ; } } } @@ -6454,7 +6464,6 @@ AddAddConformalZigZag( const ISurfFlatRegion* pSfr, PocketParams& PockParams, if ( IsNull( pCompoNoSmooth) || IsNull( pCompoSmooth)) return false ; - // scorro i tratti di Offset interni e aggiungo i raccordi sul bordo esterno // raccordo il tratto di Offset interno corrente al successivo const double TOL_JOINT = 25. * EPS_SMALL ; @@ -6539,9 +6548,25 @@ AddAddConformalZigZag( const ISurfFlatRegion* pSfr, PocketParams& PockParams, // inverto l'ordine delle curve di Offset ( in modo da partire sempre ad eseguire il percorso // più lontano dal dai lati chiusi) pCompoTempPath->Invert() ; + // controllo eventuali parti non svuotate... // calcolo la Feed del percorso trovato - if ( ! AssignFeedConformalZigZag( pCompoTempPath, pCrvClass, PockParams)) + PtrOwner pSfrToRemove( CreateSurfFlatRegion()) ; + ICRVCOMPOPOVECTOR vOffs ; vOffs.emplace_back( CloneCurveComposite( pCompoTempPath)) ; + ICRVCOMPOPOVECTOR vOffsClosedCrv ; + OffsetCurve OffsCrv ; + if ( ! OffsCrv.Make( pCrvClass, - PockParams.dRad - PockParams.dRadialOffset + 15 * EPS_SMALL, ICurve::OFF_FILLET)) return false ; + PtrOwner pCrvFirstOffs( ConvertCurveToComposite( OffsCrv.GetLongerCurve())) ; + if ( IsNull( pCrvFirstOffs) || ! pCrvFirstOffs->IsValid()) + return false ; + vOffsClosedCrv.emplace_back( Release( pCrvFirstOffs)) ; + ICURVEPOVECTOR vCompoEmpty ; + if ( IsNull( pSfrToRemove) || + ! AssignFeedConformalZigZag( pCompoTempPath, pCrvClass, PockParams, pSfrToRemove) || + ! RemoveExtraParts( pSfrToRemove, vOffs, vOffsClosedCrv, vOffsClosedCrv, vCompoEmpty, PockParams)) + return false ; + if ( ! vOffs.empty() && ! IsNull( vOffs[0]) && vOffs[0]->IsValid()) + pCompoTempPath.Set( vOffs[0]) ; // aggiugno il tratto iniziale e finale per entrate da fuori Vector3d vtStart ; pCompoTempPath->GetStartDir( vtStart) ; vtStart.Invert() ; From fde952499df4bf4deb01c4da63f15e95dd04570c Mon Sep 17 00:00:00 2001 From: SaraP Date: Wed, 31 Jul 2024 14:22:22 +0200 Subject: [PATCH 11/11] EgtGeomKernel : - correzione in AssociatePolyLinesMinDistPoints. --- PolyLine.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/PolyLine.cpp b/PolyLine.cpp index 4678ce9..9557017 100644 --- a/PolyLine.cpp +++ b/PolyLine.cpp @@ -1608,7 +1608,7 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV // distanza del punto dal segmento della polilinea DistPointLine PointLineDistCalc( vPnt1[i].first, vPnt2[j-1].first, vPnt2[j].first) ; double dPlDist ; - if ( PointLineDistCalc.GetDist( dPlDist) && dPlDist < dDist) { + if ( PointLineDistCalc.GetDist( dPlDist) && dPlDist < dDist - EPS_SMALL) { dDist = dPlDist ; PointLineDistCalc.GetParamAtMinDistPoint( dMinDistPar) ; dMinDistPar += j - 1 ; @@ -1639,8 +1639,7 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV // distanza del punto dal segmento della polilinea DistPointLine PointLineDistCalc( vPnt2[j].first, vPnt1[i-1].first, vPnt1[i].first) ; double dPlDist ; - PointLineDistCalc.GetDist( dPlDist) ; - if ( dPlDist < dDist) { + if ( PointLineDistCalc.GetDist( dPlDist) && dPlDist < dDist - EPS_SMALL) { dDist = dPlDist ; PointLineDistCalc.GetParamAtMinDistPoint( dMinDistPar) ; dMinDistPar += i - 1 ;