From 22aa1cebc80f2ce30c97d4d4ee59547be22e18fc Mon Sep 17 00:00:00 2001 From: SaraP Date: Wed, 28 Jul 2021 15:07:32 +0200 Subject: [PATCH] EgtMachKernel : - in Pocketing aggiunta la rimozione di regioni residue. --- Pocketing.cpp | 776 +++++++++++++++++++++++++++++++++++++++++--------- Pocketing.h | 7 + 2 files changed, 650 insertions(+), 133 deletions(-) diff --git a/Pocketing.cpp b/Pocketing.cpp index 6136ecd..f76ed90 100644 --- a/Pocketing.cpp +++ b/Pocketing.cpp @@ -35,6 +35,8 @@ #include "/EgtDev/Include/EGnStringKeyVal.h" #include "/EgtDev/Include/EgtPointerOwner.h" #include "/EgtDev/Include/EgtNumUtils.h" +#include "/EgtDev/Include/EgkStmFromCurves.h" +#include "/EgtDev/Include/EGkDistPointSurfTm.h" using namespace std ; @@ -465,15 +467,15 @@ Pocketing::SetParam( int nType, const string& sVal) bool Pocketing::SetGeometry( const SELVECTOR& vIds) { - // verifico validit� gestore DB geometrico + // verifico validità gestore DB geometrico if ( m_pGeomDB == nullptr) return false ; // reset della geometria corrente m_vId.clear() ; - // verifico che gli identificativi rappresentino delle entit� ammissibili (tutte curve o tutte facce) + // verifico che gli identificativi rappresentino delle entità ammissibili (tutte curve o tutte facce) int nType = GEO_NONE ; for ( const auto& Id : vIds) { - // test sull'entit� + // test sull'entità int nSubs ; if ( ! VerifyGeometry( Id, nSubs, nType)) { string sInfo = "Warning in Pocketing : Skipped entity " + ToString( Id) ; @@ -496,14 +498,14 @@ Pocketing::Preview( bool bRecalc) // reset numero percorsi di svuotatura generati m_nPockets = 0 ; - // verifico validit� gestore DB geometrico e Id del gruppo + // verifico validità gestore DB geometrico e Id del gruppo if ( m_pGeomDB == nullptr || ! m_pGeomDB->ExistsObj( m_nOwnerId)) return false ; // recupero gruppo per geometria ausiliaria int nAuxId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_AUX) ; bool bChain = false ; - // se non c'�, lo aggiungo + // se non c'è, lo aggiungo if ( nAuxId == GDB_ID_NULL) { nAuxId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ; if ( nAuxId == GDB_ID_NULL) @@ -544,7 +546,7 @@ Pocketing::Preview( bool bRecalc) // recupero gruppo per geometria di Preview int nPvId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_PV) ; - // se non c'�, lo aggiungo + // se non c'è, lo aggiungo if ( nPvId == GDB_ID_NULL) { nPvId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ; if ( nPvId == GDB_ID_NULL) @@ -577,7 +579,7 @@ Pocketing::Apply( bool bRecalc, bool bPostApply) // reset raggio massimo attacco ad elica nel caso di cerchi m_dMaxHelixRad = INFINITO ; - // verifico validit� gestore DB geometrico e Id del gruppo + // verifico validità gestore DB geometrico e Id del gruppo if ( m_pGeomDB == nullptr || ! m_pGeomDB->ExistsObj( m_nOwnerId)) return false ; @@ -600,7 +602,7 @@ Pocketing::Apply( bool bRecalc, bool bPostApply) // recupero gruppo per geometria ausiliaria int nAuxId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_AUX) ; bool bChain = false ; - // se non c'�, lo aggiungo + // se non c'è, lo aggiungo if ( nAuxId == GDB_ID_NULL) { nAuxId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ; if ( nAuxId == GDB_ID_NULL) @@ -635,7 +637,7 @@ Pocketing::Apply( bool bRecalc, bool bPostApply) // recupero gruppo per geometria di lavorazione (Cutter Location) int nClId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_CL) ; - // se non c'�, lo aggiungo + // se non c'è, lo aggiungo if ( nClId == GDB_ID_NULL) { nClId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ; if ( nClId == GDB_ID_NULL) @@ -679,7 +681,7 @@ Pocketing::Apply( bool bRecalc, bool bPostApply) bool Pocketing::Update( bool bPostApply) { - // verifico validit� gestore DB geometrico e Id del gruppo + // verifico validità gestore DB geometrico e Id del gruppo if ( m_pGeomDB == nullptr || ! m_pGeomDB->ExistsObj( m_nOwnerId)) return false ; @@ -914,7 +916,7 @@ Pocketing::UpdateToolData( bool* pbChanged) bool Pocketing::GetGeometry( SELVECTOR& vIds) const { - // restituisco l'elenco delle entit� + // restituisco l'elenco delle entità vIds = m_vId ; return true ; } @@ -927,7 +929,7 @@ Pocketing::VerifyGeometry( SelData Id, int& nSubs, int& nType) const IGeoObj* pGObj = m_pGeomDB->GetGeoObj( Id.nId) ; if ( pGObj == nullptr) return false ; - // se ammesse curve ed � tale + // se ammesse curve ed è tale if ( ( nType == GEO_NONE || nType == GEO_CURVE) && ( pGObj->GetType() & GEO_CURVE) != 0) { nType = GEO_CURVE ; const ICurve* pCurve = nullptr ; @@ -951,7 +953,7 @@ Pocketing::VerifyGeometry( SelData Id, int& nSubs, int& nType) } return true ; } - // se altrimenti ammessi testi ed � tale + // se altrimenti ammessi testi ed è tale else if ( ( nType == GEO_NONE || nType == EXT_TEXT) && pGObj->GetType() == EXT_TEXT) { nType = EXT_TEXT ; const IExtText* pText = ::GetExtText( pGObj) ; @@ -960,7 +962,7 @@ Pocketing::VerifyGeometry( SelData Id, int& nSubs, int& nType) nSubs = 0 ; return true ; } - // se altrimenti ammesse superfici trimesh ed � tale + // se altrimenti ammesse superfici trimesh ed è tale else if ( ( nType == GEO_NONE || nType == SRF_TRIMESH) && pGObj->GetType() == SRF_TRIMESH) { nType = SRF_TRIMESH ; const ISurfTriMesh* pSurf = ::GetSurfTriMesh( pGObj) ; @@ -982,7 +984,7 @@ Pocketing::VerifyGeometry( SelData Id, int& nSubs, int& nType) } return true ; } - // se altrimenti ammesse regioni ed � tale + // se altrimenti ammesse regioni ed è tale else if ( ( nType == GEO_NONE || nType == SRF_FLATRGN) && pGObj->GetType() == SRF_FLATRGN) { nType = SRF_FLATRGN ; const ISurfFlatRegion* pReg = ::GetSurfFlatRegion( pGObj) ; @@ -1051,7 +1053,7 @@ Pocketing::GetCurves( SelData Id, ICURVEPLIST& lstPC) return false ; // la duplico pCurve.Set( pOriCurve->Clone()) ; - // reset propriet� temporanee + // reset proprietà temporanee ResetCurveAllTempProp( pCurve) ; // recupero estrusione e spessore Vector3d vtExtr ; @@ -1079,7 +1081,7 @@ Pocketing::GetCurves( SelData Id, ICURVEPLIST& lstPC) // recupero l'outline del testo if ( ! pText->GetOutline( lstPC)) return false ; - // reset propriet� temporanee + // reset proprietà temporanee for ( auto pCrv : lstPC) ResetCurveAllTempProp( pCrv) ; // porto le curve in globale @@ -1109,16 +1111,16 @@ Pocketing::GetCurves( SelData Id, ICURVEPLIST& lstPC) if ( ! pCrvCompo->IsValid()) return false ; - // reset propriet� temporanee + // reset proprietà temporanee ResetCurveAllTempProp( pCrvCompo) ; - // determino eventuali lati aperti e aggiorno propriet� del contorno + // determino eventuali lati aperti e aggiorno proprietà del contorno int nInd = 0 ; double dPar ; bool bFound = vPL[k].GetFirstU( dPar, true) ; while ( bFound) { // recupero il flag int nFlag = int( dPar) ; - // se non c'� nulla di adiacente, lato aperto + // se non c'è nulla di adiacente, lato aperto if ( nFlag == SVT_NULL) pCrvCompo->SetCurveTempProp( nInd, 1) ; // altrimenti verifico se la faccia adiacente forma diedro convesso o concavo @@ -1181,7 +1183,7 @@ Pocketing::GetCurves( SelData Id, ICURVEPLIST& lstPC) PtrOwner pCrvCompo( CreateCurveComposite()) ; if ( IsNull( pCrvCompo) || ! pCrvCompo->AddCurve( pReg->GetLoop( nC, nL))) return false ; - // reset propriet� temporanee + // reset proprietà temporanee ResetCurveAllTempProp( pCrvCompo) ; // assegno l'estrusione dalla normale alla regione pCrvCompo->SetExtrusion( vtN) ; @@ -1208,7 +1210,7 @@ Pocketing::SetCurveAllTempProp( int nCrvId, ICurve* pCurve) { if ( pCurve == nullptr) return false ; - // reset propriet� temporanee + // reset proprietà temporanee ResetCurveAllTempProp( pCurve) ; // verifico se presenti info per lati aperti if ( ! m_pGeomDB->ExistsInfo( nCrvId, KEY_OPEN)) @@ -1436,7 +1438,7 @@ Pocketing::ProcessPath2( int nPathId, int nPvId, int nClId) // se una curva non � completamente contenuta la ignoro if ( ccClass.size() != 1 || ccClass[0].nClass != CRVC_IN) { m_pMchMgr->SetWarning( 2413, "Warining in Pocketing : curve " + to_string( it->first) + " is ignored") ; - vIdxArea.erase( it) ; + it = vIdxArea.erase( it) ; it -- ; } } @@ -2227,10 +2229,10 @@ Pocketing::CalcRegionElevation( const ICurveComposite* pCompo, const Vector3d& v bool Pocketing::VerifyPathFromBottom( const ICurveComposite* pCompo, const Vector3d& vtTool) { - // se non � svuotatura dal basso in alto, esco + // se non è svuotatura dal basso in alto, esco if ( vtTool.z > MIN_ZDIR_TOP_TOOL) return true ; - // se c'� testa non dall'alto o tavola basculante, esco + // se c'è testa non dall'alto o tavola basculante, esco if ( ! m_bAboveHead || m_bTiltingTab) return true ; // recupero dati di eventuale rinvio da sotto @@ -2363,7 +2365,7 @@ Pocketing::AddZigZag( const ISurfFlatRegion* pSrf, const Vector3d& vtTool, const // lunghezza di approccio/retrazione double dAppr = m_Params.m_dStartPos ; - // se utensile che non lavora di testa poich� ingresso non fuori dal pezzo, errore + // se utensile che non lavora di testa poichè ingresso non fuori dal pezzo, errore if ( m_TParams.m_nType == TT_MILL_NOTIP) { if ( ! LeadInIsOk()) { m_pMchMgr->SetLastError( 2431, "Error in Pocketing : LeadIn with Mill NoTip in material") ; @@ -2464,9 +2466,9 @@ Pocketing::AddZigZag( const ISurfFlatRegion* pSrf, const Vector3d& vtTool, const pCurve->ToGlob( frPocket) ; // aggiungo affondamento pCurve->Translate( - vtTool * ( dDepth - dElev + j * dStep)) ; - // se prima entit� + // se prima entità if ( i == 0 ) { - // dati inizio entit� + // dati inizio entità Point3d ptStart ; pCurve->GetStartPoint( ptStart) ; Vector3d vtStart ; @@ -2524,9 +2526,9 @@ Pocketing::AddZigZag( const ISurfFlatRegion* pSrf, const Vector3d& vtTool, const if ( AddArcMove( ptP3, ptCen, dAngCen, vtN) == GDB_ID_NULL) return false ; } - // se ultima entit� + // se ultima entità if ( i == nMaxInd) { - // dati fine entit� + // dati fine entità Point3d ptEnd ; pCurve->GetEndPoint( ptEnd) ; Vector3d vtEnd ; @@ -2594,7 +2596,7 @@ Pocketing::AddZigZag( const ISurfFlatRegion* pSrf, const Vector3d& vtTool, const if ( m_Params.m_bInvert) pOffs2->Invert() ; - // sposto l'inizio a met� del tratto pi� lungo + // sposto l'inizio a metà del tratto più lungo AdjustContourStart( pOffs2) ; // aggiungo la lavorazione di questa curva @@ -2611,9 +2613,9 @@ Pocketing::AddZigZag( const ISurfFlatRegion* pSrf, const Vector3d& vtTool, const return false ; // aggiungo affondamento pCurve->Translate( - vtTool * ( dDepth - dElev + j * dStep)) ; - // se prima entit� + // se prima entità if ( i == 0 ) { - // dati inizio entit� + // dati inizio entità Point3d ptStart ; pCurve->GetStartPoint( ptStart) ; Vector3d vtStart ; @@ -2680,11 +2682,11 @@ Pocketing::AddZigZag( const ISurfFlatRegion* pSrf, const Vector3d& vtTool, const if ( AddArcMove( ptP3, ptCen, dAngCen, vtN) == GDB_ID_NULL) return false ; } - // se ultima entit� + // se ultima entità if ( i == nMaxInd) { // se ultimo step, uscita e retrazione di collegamento if ( j == nStep) { - // dati fine entit� + // dati fine entità Point3d ptEnd ; pCurve->GetEndPoint( ptEnd) ; Vector3d vtEnd ; @@ -2970,7 +2972,7 @@ Pocketing::AddOneWay( const ISurfFlatRegion* pSrf, const Vector3d& vtTool, const // lunghezza di approccio/retrazione double dAppr = m_Params.m_dStartPos ; - // se utensile che non lavora di testa poich� ingresso non fuori dal pezzo, errore + // se utensile che non lavora di testa poichè ingresso non fuori dal pezzo, errore if ( m_TParams.m_nType == TT_MILL_NOTIP) { if ( ! LeadInIsOk()) { m_pMchMgr->SetLastError( 2431, "Error in Pocketing : LeadIn with Mill NoTip in material") ; @@ -3010,7 +3012,7 @@ Pocketing::AddOneWay( const ISurfFlatRegion* pSrf, const Vector3d& vtTool, const if ( m_Params.m_bInvert) pOffs->Invert() ; - // sposto l'inizio a met� del tratto pi� lungo + // sposto l'inizio a metà del tratto più lungo AdjustContourStart( pOffs) ; // coefficiente di riduzione feed di lavorazione di questa curva @@ -3030,9 +3032,9 @@ Pocketing::AddOneWay( const ISurfFlatRegion* pSrf, const Vector3d& vtTool, const return false ; // aggiungo affondamento pCurve->Translate( - vtTool * ( dDepth - dElev + j * dStep)) ; - // se prima entit� + // se prima entità if ( i == 0 ) { - // dati inizio entit� + // dati inizio entità Point3d ptStart ; pCurve->GetStartPoint( ptStart) ; Vector3d vtStart ; @@ -3045,11 +3047,10 @@ Pocketing::AddOneWay( const ISurfFlatRegion* pSrf, const Vector3d& vtTool, const // determino elevazione su inizio attacco double dStElev ; if ( ! GetElevation( m_nPhase, ptStart - 10 * EPS_SMALL * vtTool, vtTool, GetRadiusForStartEndElevation(), vtTool, dStElev)) - dStElev = dElev ; - bool bUnderStart = m_bAboveHead && GetPointUnderRaw( ptP1, vtTool, 0, - GetRadiusForStartEndElevation(), m_TParams.m_dLen, false, dSafeZ, dStElev) ; - if ( bUnderStart) - dStElev = max( dStElev, dElev) ; + dStElev = dStep ; + bool bUnderRaw = GetPointUnderRaw( ptP1, vtTool, 0, GetRadiusForStartEndElevation(), m_TParams.m_dLen, false, dSafeZ, dStElev) ; + if ( bUnderRaw == m_bAboveHead) + dStElev = max( dStElev, dStep) ; dStElev -= ( ptP1 - ptStart) * vtExtr ; // se attacco a zigzag o a spirale o a scivolo, l'elevazione va nell'attacco if ( GetLeadInType() == POCKET_LI_ZIGZAG || @@ -3099,11 +3100,11 @@ Pocketing::AddOneWay( const ISurfFlatRegion* pSrf, const Vector3d& vtTool, const if ( AddArcMove( ptP3, ptCen, dAngCen, vtN) == GDB_ID_NULL) return false ; } - // se ultima entit� + // se ultima entità if ( i == nMaxInd) { // se ultimo step, uscita e retrazione di collegamento if ( j == nStep) { - // dati fine entit� + // dati fine entità Point3d ptEnd ; pCurve->GetEndPoint( ptEnd) ; Vector3d vtEnd ; @@ -3336,9 +3337,9 @@ Pocketing::AddSpiralIn( const ISurfFlatRegion* pSrf, const Vector3d& vtTool, con return false ; // aggiungo affondamento pCurve->Translate( - vtTool * ( dDepth - dElev + j * dStep)) ; - // se prima entit� + // se prima entità if ( i == 0 ) { - // dati inizio entit� + // dati inizio entità Point3d ptStart ; pCurve->GetStartPoint( ptStart) ; Vector3d vtStart ; @@ -3348,7 +3349,7 @@ Pocketing::AddSpiralIn( const ISurfFlatRegion* pSrf, const Vector3d& vtTool, con // determino inizio attacco if ( ! CalcLeadInStart( ptStart, vtStart, vtExtr, pRCrv, ptP1)) return false ; - // determino elevazione su inizio attacco (se non trovata, elevazione � step) + // determino elevazione su inizio attacco (se non trovata, elevazione è step) double dStElev ; if ( ! GetElevation( m_nPhase, ptStart - 10 * EPS_SMALL * vtTool, vtTool, GetRadiusForStartEndElevation(), vtTool, dStElev)) dStElev = dStep ; @@ -3405,7 +3406,7 @@ Pocketing::AddSpiralIn( const ISurfFlatRegion* pSrf, const Vector3d& vtTool, con if ( AddArcMove( ptP3, ptCen, dAngCen, vtN) == GDB_ID_NULL) return false ; } - // se ultima entit� + // se ultima entità if ( i == nMaxInd) { // se step intermedio, ritorno all'inizio direttamente if ( j < nStep) { @@ -3433,7 +3434,7 @@ Pocketing::AddSpiralIn( const ISurfFlatRegion* pSrf, const Vector3d& vtTool, con } // atrimenti ultimo step, uscita e retrazione else { - // dati fine entit� + // dati fine entità Point3d ptEnd ; pCurve->GetEndPoint( ptEnd) ; Vector3d vtEnd ; @@ -3469,7 +3470,7 @@ Pocketing::AddSpiralOut( const ISurfFlatRegion* pSrf, const Vector3d& vtTool, co double dSafeAggrBottZ = m_pMchMgr->GetCurrMachiningsMgr()->GetSafeAggrBottZ() ; // lunghezza di approccio/retrazione double dAppr = m_Params.m_dStartPos ; - // se utensile che non lavora di testa poich� ingresso non fuori dal pezzo, errore + // se utensile che non lavora di testa poichè ingresso non fuori dal pezzo, errore if ( m_TParams.m_nType == TT_MILL_NOTIP) { if ( ! LeadInIsOk()) { m_pMchMgr->SetLastError( 2431, "Error in Pocketing : LeadIn with Mill NoTip in material") ; @@ -3493,7 +3494,7 @@ Pocketing::AddSpiralOut( const ISurfFlatRegion* pSrf, const Vector3d& vtTool, co if ( pMCrv->GetCurveCount() == 0) break ; ++ nReg ; - // inverto i percorsi, perch� sono calcolati dall'esterno all'interno + // inverto i percorsi, perchè sono calcolati dall'esterno all'interno pMCrv->Invert() ; pRCrv->Invert() ; @@ -3517,9 +3518,9 @@ Pocketing::AddSpiralOut( const ISurfFlatRegion* pSrf, const Vector3d& vtTool, co return false ; // aggiungo affondamento pCurve->Translate( - vtTool * ( dDepth - dElev + j * dStep)) ; - // se prima entit� + // se prima entità if ( i == 0 ) { - // dati inizio entit� + // dati inizio entità Point3d ptStart ; pCurve->GetStartPoint( ptStart) ; Vector3d vtStart ; @@ -3534,11 +3535,10 @@ Pocketing::AddSpiralOut( const ISurfFlatRegion* pSrf, const Vector3d& vtTool, co // determino elevazione su inizio attacco double dStElev ; if ( ! GetElevation( m_nPhase, ptStart - 10 * EPS_SMALL * vtTool, vtTool, GetRadiusForStartEndElevation(), vtTool, dStElev)) - dStElev = dElev ; - bool bUnderStart = m_bAboveHead && GetPointUnderRaw( ptP1, vtTool, 0, - GetRadiusForStartEndElevation(), m_TParams.m_dLen, false, dSafeZ, dStElev) ; - if ( bUnderStart) - dStElev = max( dStElev, dElev) ; + dStElev = dStep ; + bool bUnderRaw = GetPointUnderRaw( ptP1, vtTool, 0, GetRadiusForStartEndElevation(), m_TParams.m_dLen, false, dSafeZ, dStElev) ; + if ( bUnderRaw == m_bAboveHead) + dStElev = max( dStElev, dStep) ; dStElev -= ( ptP1 - ptStart) * vtExtr ; // se attacco a zigzag o a spirale o a scivolo, l'elevazione va nell'attacco if ( GetLeadInType() == POCKET_LI_ZIGZAG || @@ -3589,7 +3589,7 @@ Pocketing::AddSpiralOut( const ISurfFlatRegion* pSrf, const Vector3d& vtTool, co if ( AddArcMove( ptP3, ptCen, dAngCen, vtN) == GDB_ID_NULL) return false ; } - // se ultima entit� + // se ultima entità if ( i == nMaxInd) { // se step intermedio if ( j < nStep) { @@ -3617,7 +3617,7 @@ Pocketing::AddSpiralOut( const ISurfFlatRegion* pSrf, const Vector3d& vtTool, co } // atrimenti ultimo step, uscita e retrazione else { - // dati fine entit� + // dati fine entità Point3d ptEnd ; pCurve->GetEndPoint( ptEnd) ; Vector3d vtEnd ; @@ -3651,15 +3651,18 @@ bool Pocketing::CalcSpiral( const ISurfFlatRegion * pSrf , int nReg, bool bSplitArcs, ICurveComposite* pMCrv, ICurveComposite* pRCrv) { - // inizializzo i risultati + // inizializzo i risultati pMCrv->Clear() ; pRCrv->Clear() ; - // primo offset pari al raggio utensile + sovramateriale + ISurfFlatRegion * pCutRegion = CreateSurfFlatRegion() ; // regione lavorata + Vector3d vtExtr = pSrf->GetNormVersor() ; + + // primo offset pari al raggio utensile + sovramateriale double dTRad = 0.5 * m_TParams.m_dDiam ; double dOffs = dTRad + GetOffsR() ; - // ciclo di offset verso l'interno + // ciclo di offset verso l'interno const int MAX_ITER = 1000 ; int nIter = 0 ; @@ -3673,27 +3676,30 @@ Pocketing::CalcSpiral( const ISurfFlatRegion * pSrf , int nReg, bool bSplitArcs, ISURFFRPOVECTOR vSrfStack ; ICRVCOMPOPVECTOR vOffs ; PtrOwner pOffs ; + bool bCircleSpiral ; size_t LastExtLoopPos = 0 ; while ( nIter < MAX_ITER) { - // calcolo offset + // calcolo offset if ( ! pSrfOff->Offset( - dOffs, ICurve::OFF_FILLET)) { pSrfOff->Clear() ; m_pMchMgr->SetLastError( 2412, "Error in Pocketing : Offset not computable") ; - // return false ; + return false ; } - // salvo la prima surface di offset per CalcBoundedLink + + // salvo la prima surface di offset per CalcBoundedLink if ( nIter == 0 && pSrfOff->IsValid()) - pSrfOff1.Set( pSrfOff->Clone()) ; + pSrfOff1.Set( pSrfOff->Clone()) ; + if ( IsNull( pSrfOff1) || ! pSrfOff1->IsValid()) return false ; - // se primo offset e richiesta regione oltre il massimo, esco + // se primo offset e richiesta regione oltre il massimo, esco int nChunks = pSrfOff->GetChunkCount() ; if ( nIter == 0 && nReg >= nChunks) return true ; - // recupero le superfici di offset e le metto sullo stack (se primo offset solo quella voluta) + // recupero le superfici di offset e le metto sullo stack (se primo offset solo quella voluta) int nCount = 0 ; while ( nCount < nChunks) { if ( nIter != 0 || nReg == nCount) { @@ -3704,7 +3710,7 @@ Pocketing::CalcSpiral( const ISurfFlatRegion * pSrf , int nReg, bool bSplitArcs, nCount ++ ; } - // recupero la prossima superficie di offset + // recupero la prossima superficie di offset if ( ! vSrfStack.empty() && ( pSrfOff->IsValid() || dOffs < dTRad + EPS_ZERO)) { pSrfOff.Set( Release( vSrfStack.back())) ; vSrfStack.pop_back() ; @@ -3712,51 +3718,57 @@ Pocketing::CalcSpiral( const ISurfFlatRegion * pSrf , int nReg, bool bSplitArcs, bool bNextOk = pSrfOff->IsValid() ; bool bSmallRad = ( nIter == 0 ? dOffs < dTRad + GetOffsR() + EPS_ZERO : dOffs < dTRad + EPS_ZERO) ; - // se offset va bene aggiorno pSrfOffOld + // se offset va bene aggiorno pSrfOffOld if ( pSrfOff->IsValid()) pSrfOffOld.Set( pSrfOff->Clone()) ; - // se non valido ma riducibile, provo con offset ridotto al raggio utensile + // se non valido ma riducibile, provo con offset ridotto al raggio utensile else if ( ! bSmallRad) { pSrfOff.Set( pSrfOffOld->Clone()) ; - // nuovo valore pari al raggio + // nuovo valore pari al raggio dOffs = ( nIter == 0 ? dTRad + GetOffsR() : dTRad) ; continue ; } - // altrimenti esco + // altrimenti esco else break ; - // verifico se circonferenza o circonferenze concentriche - if ( CircleSpiral( pSrfOff, bSplitArcs, vOffs, pRCrv)) + // verifico se circonferenza o circonferenze concentriche + bCircleSpiral = CircleSpiral( pSrfOff, bSplitArcs, vOffs, pRCrv) ; + if ( bCircleSpiral) break ; - // Inserisco le curve che delimitano la superficie di offset nel vettore vOffs in modo che siano ordinate dalla - // pi� esterna alla pi� interna + // Inserisco le curve che delimitano la superficie di offset nel vettore vOffs in modo che siano ordinate dalla + // più esterna alla più interna for ( int nL = 0 ; nL < pSrfOff->GetLoopCount( 0) ; nL ++) { - pOffs.Set( GetCurveComposite( pSrfOff->GetLoop( 0, nL))) ; + pOffs.Set( GetCurveComposite( pSrfOff->GetLoop( 0, nL))) ; + + // oriento tutte le curve nello stesso senso + if ( nL > 0) + pOffs->Invert() ; + if ( IsNull( pOffs)) { m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; return false ; } - // Se sono al primo offset inserisco le curve senza preoccuparmi dell'ordine + // Se sono al primo offset inserisco le curve senza preoccuparmi dell'ordine if ( nIter == 0) { vOffs.emplace_back( Release( pOffs)) ; - LastExtLoopPos = vOffs.size() ; + LastExtLoopPos = vOffs.size() - 1 ; } - // altrimenti cerco il punto dove aggiungere la curva + // altrimenti cerco il punto dove aggiungere la curva else { - // creo la sua superficie racchiusa dalla curva da inserire + // creo la sua superficie racchiusa dalla curva da inserire PtrOwner pSrfTmp( CreateSurfFlatRegion()) ; if ( IsNull( pSrfTmp) || ! pSrfTmp->AddExtLoop( pOffs->Clone())) vOffs.push_back( Release( pOffs)) ; else { - // scorro vOffs fino a quando trovo una curva inclusa nella regione definita da pOffs + // scorro vOffs fino a quando trovo una curva inclusa nella regione definita da pOffs auto it = vOffs.begin() ; while ( it != vOffs.end()) { CRVCVECTOR ccClass ; - // se non riesco a classificare passo alla curva successiva + // se non riesco a classificare passo alla curva successiva if ( ! pSrfTmp->GetCurveClassification( **it, ccClass)) continue ; if ( ccClass.size() != 1) { @@ -3768,37 +3780,36 @@ Pocketing::CalcSpiral( const ISurfFlatRegion * pSrf , int nReg, bool bSplitArcs, it ++ ; } - // Inserisco pOffs in vOffs + // Inserisco pOffs in vOffs if ( it != vOffs.end()) { - // se loop esterno per quell'offset aggiorno il valore di LastExtCrvPos + // se loop esterno per quell'offset aggiorno il valore di LastExtCrvPos if ( nL == 0) LastExtLoopPos = it - vOffs.begin() ; vOffs.insert( it, Release( pOffs)) ; } - // se non ho trovato in vOffs una curva inclusa nella regione generata da pOffs, inserisco pOffs subito dopo - // il loop esterno dell'offset precedente (che si trova in LastExtCrvPos) + // se non ho trovato in vOffs una curva inclusa nella regione generata da pOffs, inserisco pOffs subito dopo + // il loop esterno dell'offset precedente (che si trova in LastExtCrvPos) else { vOffs.insert( vOffs.begin() + LastExtLoopPos + 1, Release( pOffs)) ; - // se loop esterno per quell'offset aggiorno il valore di LastExtCrvPos + // se loop esterno per quell'offset aggiorno il valore di LastExtCrvPos if ( nL == 0) - LastExtLoopPos = LastExtLoopPos + 1 ; - + LastExtLoopPos = LastExtLoopPos + 1 ; } } } } - // nuovo valore pari allo step + // nuovo valore pari allo step dOffs = GetSideStep() ; - // incremento contatore iterazioni + // incremento contatore iterazioni ++ nIter ; } - // start points per le curve + // start points per le curve Point3d ptOld ; AdjustContourStart( vOffs[0]) ; vOffs[0]->GetEndPoint( ptOld) ; - // per le curve successive scelgo come start point quello pi� vicino all'end point della curva precedente + // per le curve successive scelgo come start point quello più vicino all'end point della curva precedente for ( size_t i = 1 ; i < vOffs.size() ; i++) { double dParam ; int nFlag ; if ( DistPointCurve( ptOld, *vOffs[i]).GetParamAtMinDistPoint( 0, dParam, nFlag)) @@ -3806,38 +3817,116 @@ Pocketing::CalcSpiral( const ISurfFlatRegion * pSrf , int nReg, bool bSplitArcs, vOffs[i]->GetEndPoint( ptOld) ; } - // calcolo i collegamenti + // calcolo la superficie coperta dal tool quando percorre i percorsi in vOffs + for ( size_t i = 0 ; ! bCircleSpiral && i < vOffs.size() ; i++) { + + OffsetCurve OffsCrvPlus ; + OffsCrvPlus.Make( vOffs[i], m_TParams.m_dDiam / 2 + 5 * EPS_SMALL, ICurve::OFF_FILLET) ; + ICurve * pCrvOffPlus = OffsCrvPlus.GetLongerCurve() ; + if ( pCrvOffPlus == nullptr ) { + m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, vOffs[i]->Clone()) ; + return false ; + } + + ISurfFlatRegion * pSrfTool = CreateSurfFlatRegion() ; + pSrfTool->AddExtLoop( pCrvOffPlus) ; + if ( OffsCrvPlus.GetCurveCount() > 0) { + pCrvOffPlus = GetCurveComposite( OffsCrvPlus.GetCurve()) ; + while ( pCrvOffPlus != nullptr) { + if ( GetCurveRadius( pCrvOffPlus) > EPS_ZERO) + pSrfTool->AddIntLoop( pCrvOffPlus) ; + pCrvOffPlus = GetCurveComposite( OffsCrvPlus.GetCurve()) ; + } + } + + OffsetCurve OffsCrvMinus ; + OffsCrvMinus.Make( vOffs[i], - m_TParams.m_dDiam / 2 - 5 * EPS_SMALL, ICurve::OFF_FILLET) ; + ICurveComposite * pCrvOffMinus = GetCurveComposite( OffsCrvMinus.GetLongerCurve()) ; + while ( pCrvOffMinus != nullptr) { + if ( GetCurveRadius( pCrvOffMinus) > EPS_ZERO) + pSrfTool->AddIntLoop( pCrvOffMinus) ; + pCrvOffMinus = GetCurveComposite( OffsCrvMinus.GetCurve()) ; + } + + if ( i == 0) + pCutRegion = pSrfTool->Clone() ; + else + pCutRegion->Add( *(pSrfTool->Clone())) ; + } + + // calcolo i collegamenti ICURVEPOVECTOR vLinks( vOffs.size()) ; for ( int i = 1 ; i < int( vOffs.size()) ; ++ i) { - // punti di inizio e fine + // punti di inizio e fine Point3d ptStart ; vOffs[i-1]->GetEndPoint( ptStart) ; Point3d ptEnd ; vOffs[i]->GetStartPoint( ptEnd) ; - // calcolo il collegamento (garantendo che non esca dalla svuotatura) + if ( AreSamePointApprox( ptStart, ptEnd ) ) { + vLinks[i].Set( CreateCurveLine()) ; + continue ; + } + + // calcolo il collegamento (garantendo che non esca dalla svuotatura) PtrOwner pCrvLink( CreateCurveComposite()) ; - if ( CalcBoundedLink( ptStart, ptEnd, pSrfOff1, pCrvLink)) - vLinks[i].Set( Release( pCrvLink)) ; + if ( CalcBoundedLink( ptStart, ptEnd, pSrfOff1, pCrvLink)) { + + // Superficie coperta dal tool quando percorre il collegamento + const ICurve * pCrvLinkTmp = pCrvLink->GetFirstCurve() ; + while ( pCrvLinkTmp != nullptr) { + if ( pCrvLinkTmp->GetType() == CRV_LINE) { + Point3d ptS, ptE ; + pCrvLinkTmp->GetStartPoint( ptS) ; + pCrvLinkTmp->GetEndPoint( ptE) ; + ICurveComposite * pCrvTmp = CreateCurveComposite() ; + pCrvTmp->AddPoint( ptS) ; + pCrvTmp->AddLine( ptE) ; + pCrvTmp->AddLine( ptS) ; + pCrvTmp->SetExtrusion( vtExtr) ; + OffsetCurve OffsCrvPlus ; + OffsCrvPlus.Make( pCrvTmp, m_TParams.m_dDiam / 2 + 10 * EPS_SMALL, ICurve::OFF_FILLET) ; + ICurve * pCrvOffPlus = OffsCrvPlus.GetLongerCurve() ; + + ISurfFlatRegion * pSrf = CreateSurfFlatRegion() ; + pSrf->AddExtLoop( pCrvOffPlus) ; + pCutRegion->Add( *(pSrf->Clone())) ; + } + pCrvLinkTmp = pCrvLink->GetNextCurve() ; + } + + // aggiungo il collegamento + vLinks[i].Set( Release( pCrvLink)) ; + } else { m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; return false ; } } - // calcolo il percorso di ritorno + m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCutRegion->Clone()) ; + + // rimuovo le aree non lavorate + if ( pCutRegion->GetLoopCount( 0) > pSrfOff1->GetLoopCount( nReg)) { + if ( ! RemoveUncutRegions( pCutRegion, vOffs, pSrfOff1->CloneChunk( nReg))) { + m_pMchMgr->SetLastError( 2413, "Error in Pocketing : removal of uncut regions failed") ; + return false ; + } + } + + // calcolo il percorso di ritorno if ( vOffs.size() >= 2) { pRCrv->Clear() ; - // punti di inizio e fine + // punti di inizio e fine Point3d ptStart ; vOffs.back()->GetEndPoint( ptStart) ; Point3d ptEnd ; vOffs.front()->GetStartPoint( ptEnd) ; - // calcolo il ritorno (garantendo che non esca dalla svuotatura) + // calcolo il ritorno (garantendo che non esca dalla svuotatura) PtrOwner pCrvLink( CreateCurveComposite()) ; if ( CalcBoundedLink( ptStart, ptEnd, pSrfOff1, pCrvLink)) { pRCrv->AddCurve( Release( pCrvLink)) ; pRCrv->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, false) ; - // se necessario, approssimo archi con rette + // se necessario, approssimo archi con rette if ( bSplitArcs && ! ApproxWithLines( pRCrv)) { m_pMchMgr->SetLastError( 2421, "Error in Pocketing : Linear Approx not computable") ; return false ; @@ -3850,31 +3939,30 @@ Pocketing::CalcSpiral( const ISurfFlatRegion * pSrf , int nReg, bool bSplitArcs, } } - // creo il percorso di lavoro a partire dalla raccolta degli offset e dei collegamenti + // creo il percorso di lavoro a partire dalla raccolta degli offset e dei collegamenti for ( int i = 0 ; i < int( vOffs.size()) ; ++ i) { - // se collegamento da aggiungere + // se collegamento da aggiungere if ( ! IsNull( vLinks[i])) { - // accodo nel percorso di lavorazione + // accodo nel percorso di lavorazione pMCrv->AddCurve( Release( vLinks[i])) ; } - // se richiesta percorrenza invertita + // se richiesta percorrenza invertita if ( m_Params.m_bInvert) vOffs[i]->Invert() ; - // aggiungo la curva + // aggiungo la curva pMCrv->AddCurve( Release( (PtrOwner)vOffs[i])) ; - } - // verifico il percorso di lavoro + // verifico il percorso di lavoro if ( pMCrv->GetCurveCount() == 0) { m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; return false ; } - // se necessario, approssimo archi con rette + // se necessario, approssimo archi con rette if ( bSplitArcs && ! ApproxWithLines( pMCrv)) { m_pMchMgr->SetLastError( 2421, "Error in Pocketing : Linear Approx not computable") ; return false ; } - // eventuale sistemazione archi + // eventuale sistemazione archi VerifyArcs( pMCrv) ; return true ; @@ -3884,7 +3972,7 @@ Pocketing::CalcSpiral( const ISurfFlatRegion * pSrf , int nReg, bool bSplitArcs, //---------------------------------------------------------------------------- bool Pocketing::CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, const ISurfFlatRegion* pSrf, - ICurveComposite* pCrvLink) + ICurveComposite* pCrvLink) { // creo la retta PtrOwner pLine( CreateCurveLine()) ; @@ -3896,7 +3984,7 @@ Pocketing::CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, const CRVCVECTOR ccClass ; pSrf->GetCurveClassification( *pLine, ccClass) ; - // se nessuno o un solo tratto e interno, la retta � il collegamento + // se nessuno o un solo tratto e interno, la retta è il collegamento if ( ccClass.empty() || ( ccClass.size() == 1 && ccClass[0].nClass == CRVC_IN)) { pCrvLink->AddCurve( Release( pLine)) ; return true ; @@ -3942,19 +4030,19 @@ Pocketing::CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, const bFound = vpCrvBound[CrvIdx]->GetParamAtPoint( ptE, dOffE) ; // se non lo trovo sulla curva di ptS, cerco in ccClass un altro intervallo il cui ptE si trova sulla curva di ptS if ( ! bFound) { - while ( ! bFound && j < int( ccClass.size())) { + while ( ! bFound && j < int( ccClass.size()) - 1) { j ++ ; pLine->GetPointD1D2( ccClass[j].dParE, ICurve::FROM_MINUS, ptE) ; bFound = vpCrvBound[CrvIdx]->GetParamAtPoint( ptE, dOffE) ; } - // se intervallo non esiste, � errore + // se intervallo non esiste, è errore if ( ! bFound) { m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; return false ; } } - // recupero i due possibili percorsi e uso il pi� corto + // recupero i due possibili percorsi e uso il più corto PtrOwner pCrvA( vpCrvBound[CrvIdx]->CopyParamRange( dOffS, dOffE)) ; PtrOwner pCrvB( vpCrvBound[CrvIdx]->CopyParamRange( dOffE, dOffS)) ; if ( IsNull( pCrvA) || IsNull( pCrvB)) @@ -3993,7 +4081,7 @@ Pocketing::CircleSpiral( ISurfFlatRegion* pSrf, bool bSplitArcs, ICRVCOMPOPVECTO if ( ! pExt->IsACircle( 10 * EPS_SMALL, ptCen, vtN, dRad, bCCW )) return false ; - vOffs.push_back( CreateCurveComposite()) ; + vOffs.emplace_back( CreateCurveComposite()) ; // se ho solo il loop esterno if ( nLoops == 1) { double dIntRad = 0 ; @@ -4134,7 +4222,7 @@ Pocketing::AddApproach( const Point3d& ptP, const Vector3d& vtTool, double dSafe SetFlag( 0) ; } } - // se sopra attacco c'� spazio per sicurezza o approccio + // se sopra attacco c'è spazio per sicurezza o approccio double dSafeDist = ( m_bAggrBottom ? dSafeAggrBottZ : dSafeZ) ; if ( dElev + max( dSafeDist, dAppr) > 10 * EPS_SMALL) { // se distanza di sicurezza minore di distanza di inizio @@ -4180,7 +4268,7 @@ bool Pocketing::AddLinkApproach( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dSafeAggrBottZ, double dElev, double dAppr) { - // se sopra attacco c'� spazio per approccio + // se sopra attacco c'è spazio per approccio if ( ( dElev + dAppr) > 10 * EPS_SMALL) { // 1b -> punto appena sopra inizio Point3d ptP1b = ptP + vtTool * ( dElev + dAppr) ; @@ -4209,7 +4297,7 @@ bool Pocketing::AddLinkRetract( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dSafeAggrBottZ, double dElev, double dAppr) { - // se sopra uscita c'� spazio per approccio + // se sopra uscita c'è spazio per approccio if ( ( dElev + dAppr) > 10 * EPS_SMALL) { // 4 -> movimento di risalita sopra il punto finale SetFeed( GetEndFeed()) ; @@ -4225,7 +4313,7 @@ bool Pocketing::AddRetract( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dSafeAggrBottZ, double dElev, double dAppr) { - // se sopra uscita c'� spazio per sicurezza o approccio + // se sopra uscita c'è spazio per sicurezza o approccio double dSafeDist = ( m_bAggrBottom ? dSafeAggrBottZ : dSafeZ) ; if ( dElev + max( dSafeDist, dAppr) > 10 * EPS_SMALL) { if ( dSafeDist < dAppr + 10 * EPS_SMALL) { @@ -4515,7 +4603,7 @@ Pocketing::GetMidOfLongestOpenSide( const ICurveComposite* pCompo, Point3d& ptMi } pMyCrv = pCompo->GetNextCurve() ; } - // richiedo lunghezza superiore a diametro utensile pi� doppio offset radiale + // richiedo lunghezza superiore a diametro utensile più doppio offset radiale double dMaxLen = ( bAllOpen ? 0 : m_TParams.m_dDiam + 2 * GetOffsR() - EPS_SMALL) ; // ciclo sulle singole curve bool bFound = false ; @@ -4535,7 +4623,7 @@ Pocketing::GetMidOfLongestOpenSide( const ICurveComposite* pCompo, Point3d& ptMi pNextCrv->GetLength( dLenNext) ; // verifico la curva corrente if ( pCrv->GetTempProp() == 1) { - // contributo dalle entit� adiacenti (se non tutte aperte) + // contributo dalle entità adiacenti (se non tutte aperte) double dLenAgg = 0 ; if ( ! bAllOpen) { if ( pPrevCrv != nullptr && pPrevCrv->GetTempProp() == 1) { @@ -4549,7 +4637,7 @@ Pocketing::GetMidOfLongestOpenSide( const ICurveComposite* pCompo, Point3d& ptMi dLenAgg += max( 0., vtEnd * vtNextStart * dLenNext) ; } } - // entit� corrente + // entità corrente double dLen = 0 ; if ( pCrv->GetLength( dLen) && dLen + dLenAgg > dMaxLen) { dMaxLen = dLen + dLenAgg ; @@ -4581,7 +4669,7 @@ Pocketing::AdjustContourWithOpenEdges( ICurveComposite* pCompo) Frame3d frPocket ; Point3d ptStart ; pCompo->GetStartPoint( ptStart) ; frPocket.Set( ptStart, vtExtr) ; - // sposto l'inizio a met� del tratto pi� lungo + // sposto l'inizio a metà del tratto più lungo AdjustContourStart( pCompo) ; // raggio di riferimento per offset double dRad = 0.5 * m_TParams.m_dDiam + GetOffsR() ; @@ -4700,7 +4788,7 @@ Pocketing::AdjustContourWithOpenEdges( ICurveComposite* pCompo) bool Pocketing::AdjustContourStart( ICurveComposite* pCompo) { - // cerco il tratto lineare pi� lungo + // cerco il tratto lineare più lungo int i = 0 ; double dLenMax = 0 ; int nMax = - 1 ; @@ -4730,7 +4818,7 @@ Pocketing::AdjustContourStart( ICurveComposite* pCompo) } } - // sposto inizio a met� del tratto pi� lungo + // sposto inizio a metà del tratto più lungo bool bOk = true ; if ( nMax >= 0) bOk = pCompo->ChangeStartPoint( nMax + 0.5) ; @@ -4802,4 +4890,426 @@ Pocketing::VerifyLeadInZigZag( const ISurfFlatRegion* pSrf, const Point3d& ptPa, double dMinDistPb = *min_element( vMinDistPb.begin(), vMinDistPb.end()) ; return ( dMinDistPa > 0.5 * m_TParams.m_dDiam - 10 * EPS_SMALL && dMinDistPb > 0.5 * m_TParams.m_dDiam - 10 * EPS_SMALL) ; -} \ No newline at end of file +} + + +//---------------------------------------------------------------------------- +bool +Pocketing::RemoveUncutRegions( const ISurfFlatRegion * pCutRegion, ICRVCOMPOPVECTOR& vOffs, const ISurfFlatRegion * pSrfBound) +{ + // Conservo le curve vOffs originali in vettore Tmp da usare per i calcoli sui percorsi aggiuntivi + ICRVCOMPOPOVECTOR vOffsTmp( vOffs.size()) ; + for ( size_t i = 0 ; i < vOffs.size() ; i++) + vOffsTmp[i].Set( vOffs[i]->Clone()) ; + + ISurfFlatRegion * pNewCutRegion = pCutRegion->Clone() ; + bool bAddedPaths = false ; + + // analizzo tutte le aree non lavorate + int nLoops = pCutRegion->GetLoopCount( 0) ; + for ( int i = 1 ; i < nLoops ; i++) { + + ICurve * pResidualCrv = pCutRegion->GetLoop( 0, i) ; + + // verifico che la curva corrisponda ad una regione non lavorata + CRVCVECTOR ccClass ; + pSrfBound->GetCurveClassification( *pResidualCrv, ccClass) ; + if ( ccClass[0].nClass != CRVC_IN) + continue ; + + if ( pResidualCrv == nullptr || ! pResidualCrv->IsValid()) + continue ; + + // cerco la curva di vOffs su cui andrà il percorso aggiuntivo + size_t idx ; // indice della curva in vOffs + Point3d ptCrit ; // punto in cui aggiungere il percorso extra + double dParCrit ; // parametro corrispondente a ptCrit + + if ( ! FindCurveForPathAdd( pResidualCrv, vOffsTmp, idx, ptCrit, dParCrit, pSrfBound)) + return false ; + + // calcolo la lunghezza del tratto da aggiungere basandomi sull'angolo e sull'overlap + Point3d ptEnd ; + bool bUsePtEnd = false ; + + // se sono sul punto di congiunzione fra due curve + if ( vOffsTmp[idx]->IsParamAtJoint( dParCrit)) { + const ICurve* pCrv1 = dParCrit < EPS_SMALL ? vOffsTmp[idx]->GetLastCurve() : vOffsTmp[idx]->GetCurve( int( dParCrit + 0.5) - 1) ; + const ICurve* pCrv2 = vOffsTmp[idx]->GetCurve( int( dParCrit + 0.5)) ; + // se le due curve sono due linee + if ( pCrv1->GetType() == CRV_LINE && pCrv2->GetType() == CRV_LINE) { + // calcolo angolo formato dalle due linee + Vector3d vt1, vt2 ; + vOffsTmp[idx]->GetPointTang( dParCrit, ICurve::FROM_MINUS, Point3d(), vt1) ; + vOffsTmp[idx]->GetPointTang( dParCrit, ICurve::FROM_PLUS, Point3d(), vt2) ; + vt2.Invert() ; + double dCosAng = vt1 * vt2 ; + + // calcolo lunghezza basandomi sull'angolo e sull'overlap + double dAngSin = sqrt( (1 - dCosAng) / 2) ; + double dOverlap = 1 - GetSideStep() / m_TParams.m_dDiam ; + double dLen = dAngSin > EPS_ANG_SMALL ? (( m_TParams.m_dDiam / 2 - m_TParams.m_dDiam * dOverlap) / dAngSin - m_TParams.m_dDiam / 2) : - 1.0 ; + + Point3d ptCen ; + pResidualCrv->GetCentroid( ptCen) ; + Vector3d vtDir = ptCen - ptCrit ; + vtDir.Normalize() ; + ptEnd = ptCrit + dLen * vtDir ; + bUsePtEnd = dLen > 0 ; + + // se devo usare ptEnd verifico sia interno alla svuotatura + if ( bUsePtEnd) { + const ISurfTriMesh* pSrfTmBound = pSrfBound->GetAuxSurf() ; + DistPointSurfTm DistPtSTm( ptEnd, *pSrfTmBound) ; + Point3d ptMinDist ; + if ( DistPtSTm.GetMinDistPoint( ptMinDist) && ! AreSamePointApprox( ptEnd, ptMinDist)) + bUsePtEnd = false ; + } + } + } + + // calcolo il percorso aggiuntivo + ICurveComposite * pAddPath = CreateCurveComposite() ; + if ( ! ComputeAdditionalPath( ptCrit, ptEnd, bUsePtEnd, pAddPath, pResidualCrv, pSrfBound, pNewCutRegion)) + return false ; + + // se non ho aggiunto alcun percorso passo alla prossima regione residua + if ( pAddPath->GetCurveCount() == 0) + continue ; + + // nuova curva di offset con tratti aggiuntivi + bAddedPaths = true ; + PtrOwner pNewOffs( CreateCurveComposite()) ; + double dPar, dParS, dParE ; + vOffs[idx]->GetDomain( dParS, dParE) ; + vOffs[idx]->GetParamAtPoint( ptCrit, dPar) ; + pNewOffs->AddCurve( vOffs[idx]->CopyParamRange( dParS, dPar)) ; // fino al punto critico è il vecchio offset + pNewOffs->AddCurve( pAddPath) ; // al punto critico aggiungo il nuovo percorso + if ( abs( dPar - dParS) > EPS_SMALL && abs( dPar - dParE) > EPS_SMALL) + pNewOffs->AddCurve( vOffs[idx]->CopyParamRange( dPar, dParE)) ; // aggiungo la parte rimanente del vecchio offset + + vOffs[idx] = Release( pNewOffs) ; + } + + // Se ho aggiunto nuovi percorsi, verifico se sono rimaste aree non lavorate e le rimuovo + if ( bAddedPaths && pNewCutRegion->GetLoopCount( 0) > pSrfBound->GetLoopCount( 0)) { + if ( ! RemoveUncutRegions( pNewCutRegion, vOffs, pSrfBound)) + return false ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +Pocketing::FindCurveForPathAdd( const ICurve* pResidualCrv, const ICRVCOMPOPOVECTOR& vOffs, size_t& nIdxMin, Point3d& ptMinDist, + double& dMinDistPar, const ISurfFlatRegion * pSrfBound) +{ + nIdxMin = -1 ; + double dMinDist = INFINITO ; + + Vector3d vtExtr ; + vOffs[0]->GetExtrusion( vtExtr) ; + Frame3d frLoc ; + frLoc.Set( ORIG, vtExtr) ; + // porto le curve in questo riferimento + CurveLocal pCrvLoc( pResidualCrv, GLOB_FRM, frLoc) ; + + Point3d ptCen ; + pResidualCrv->GetCentroid( ptCen) ; + double dist ; + + for ( size_t i = 0 ; i < vOffs.size() ; i ++) { + // verifico se la regione da rimuovere ( pCrv) è esterna alla regione racchiusa da vOffs + ISurfFlatRegion * pSrf = CreateSurfFlatRegion() ; + pSrf->AddExtLoop( vOffs[i]->Clone()) ; + CRVCVECTOR ccClass ; + pSrf->GetCurveClassification( *pResidualCrv, ccClass) ; + + if ( ccClass.size() != 1) + continue ; + + // se è esterna calcolo la sua distanza dal centro della regione da rimuovere + if ( ccClass[0].nClass == CRVC_OUT) { + DistPointCurve distPtCrv( ptCen, *(vOffs[i]->Clone())) ; + if ( distPtCrv.GetDist( dist) && dist < dMinDist) { + dMinDist = dist ; + nIdxMin = i ; + int nFlag ; + distPtCrv.GetMinDistPoint( 0, ptMinDist, nFlag) ; + vOffs[i]->GetParamAtPoint( ptMinDist, dMinDistPar) ; + } + } + } + + // for ( size_t i = 1 ; i < vOffs.size() ; i ++) { + // + // // verifico se la parte da rimuovere ( pResidualCrv) è esterna alla regione racchiusa da vOffs[i] + // CurveLocal pOffsLoc( vOffs[i]->Clone(), GLOB_FRM, frLoc) ; + // IntersCurveCurve intersCC( *pCrvLoc, *pOffsLoc) ; + // + // if ( intersCC.GetRegionCurveClassification() != CCREGC_NULL && intersCC.GetRegionCurveClassification() != CCREGC_IN1) { + // + // double dParS, dParE ; + // vOffs[i]->GetDomain( dParS, dParE) ; + // // considero i punti di congiunzione fra le curve di vOffs[i] + // for ( int j = int( dParS + 0.5) ; j < int( dParE + 0.5) ; j ++) { + // + // // calcolo il punto più vicino su pResidualCrv + // Point3d ptCrv ; + // vOffs[i]->GetPointD1D2( j, ICurve::FROM_MINUS, ptCrv) ; + // DistPointCurve distPtCrv( ptCrv, *pResidualCrv) ; + // int nFlag ; + // Point3d ptResCrv ; + // distPtCrv.GetMinDistPoint( 0, ptResCrv, nFlag) ; + // + // // calcolo la distanza come lunghezza del percorso interno alla svuotatura che li congiunge + // ICurveComposite * pLinkPath = CreateCurveComposite() ; + // if ( ! CalcBoundedLink( ptCrv, ptResCrv, pSrfBound, pLinkPath)) + // continue ; + // double dLen ; + // if ( pLinkPath->GetLength( dLen) && dLen < dMinDist) { + // dMinDist = dLen ; + // nIdxMin = i ; + // ptMinDist = ptCrv ; + // dMinDistPar = j ; + // } + // } + // } + // } + + if ( nIdxMin == -1 ) + return false ; + + return true ; +} + + +//---------------------------------------------------------------------------- +bool +Pocketing::ComputeAdditionalPath( const Point3d ptStart, Point3d ptEnd, bool bUsePtEnd, ICurveComposite * pAddPath, + const ICurve * pResidualCrv, const ISurfFlatRegion * pSrfBound, ISurfFlatRegion * pNewCutRegion) +{ + ICurveComposite * pResidualCrvClosed = GetCurveComposite( pResidualCrv->Clone()) ; + if ( ! pResidualCrv->IsClosed()) + pResidualCrvClosed->Close() ; + + // Se chiudendo la curva creo autointersezione, conservo la sottoparte di curva più lunga che non si autointerseca + SelfIntersCurve SelfIntersC( *pResidualCrvClosed) ; + if ( SelfIntersC.GetIntersCount() == 1) { + IntCrvCrvInfo aInfo ; + SelfIntersC.GetIntCrvCrvInfo( 0, aInfo) ; + double dParS, dParE ; + pResidualCrvClosed->GetDomain( dParS, dParE) ; + PtrOwner pCrvTmp1( GetCurveComposite( pResidualCrvClosed->CopyParamRange( dParS, aInfo.IciA[0].dU))) ; + pCrvTmp1->AddCurve( pResidualCrvClosed->CopyParamRange( aInfo.IciB[0].dU, dParE)) ; + PtrOwner pCrvTmp2( GetCurveComposite( pResidualCrvClosed->CopyParamRange( aInfo.IciA[0].dU, aInfo.IciB[0].dU))) ; + double dLen1 = 0.0, dLen2 = 0.0 ; + pCrvTmp1->GetLength( dLen1) ; + pCrvTmp2->GetLength( dLen2) ; + + pResidualCrvClosed = dLen1 > dLen2 ? Release( pCrvTmp1) : Release( pCrvTmp2) ; + } + + // verifico che area non sia troppo piccola + double dArea = 0 ; + Plane3d plPlane ; + if ( pResidualCrvClosed->GetArea( plPlane, dArea) && dArea < 10 * EPS_SMALL) + return true ; + + // inverto direzione della curve per essere coerente con pAddSrf quando credo la superficie + if ( AreOppositeVectorApprox( plPlane.GetVersN(), pNewCutRegion->GetNormVersor())) + pResidualCrvClosed->Invert() ; + + // scelta del punto finale + if ( ! bUsePtEnd) { + + pResidualCrv->GetCentroid( ptEnd) ; + + ISurfTriMesh* pResidualSrfTm = GetSurfTriMeshByFlatContour( pResidualCrvClosed) ; + dArea = 0 ; + if ( pResidualSrfTm != nullptr && pResidualSrfTm->GetArea( dArea) && dArea < 10 * EPS_SMALL) + return true ; + + // se regione è abbastanza grande e il centroide non è interno alla regione chiamo la funzione specifica + if ( dArea > 5) { + DistPointSurfTm DistPtSTm( ptEnd, *pResidualSrfTm) ; + Point3d ptMinDist ; + if ( DistPtSTm.GetMinDistPoint( ptMinDist) && ! AreSamePointApprox( ptEnd, ptMinDist)) + return AdditionalPathExternalCentroid( ptStart, pAddPath, pResidualCrvClosed, pSrfBound, pNewCutRegion) ; + } + } + + // se il punto iniziale e finale coincidono, scelgo un nuovo ptEnd + if ( AreSamePointEpsilon( ptStart, ptEnd, 1e-2)) { + + Point3d ptMid ; + pResidualCrv->GetMidPoint( ptMid) ; + + Vector3d vtDir = ptMid - ptStart ; + vtDir.Normalize() ; + double len = Dist( ptStart, ptMid) + 10 * EPS_SMALL - m_TParams.m_dDiam / 2 ; + if ( Dist( ptStart, ptMid) < EPS_SMALL ) + return true ; + ptEnd = ptStart + len * vtDir ; + } + + // creo il percorso fra ptStart e ptEnd senza uscire dalla svuotatura + if ( ! CalcBoundedLink( ptStart, ptEnd, pSrfBound, pAddPath)) + return false ; + + ICurveComposite * pReturnPath = pAddPath->Clone() ; // percorso di ritorno + pReturnPath->Invert() ; + + // regione svuotata da pAddPath + PtrOwner pAddPathTmp( CreateCurveComposite()) ; + pAddPathTmp->AddCurve( pAddPath->Clone()) ; + pAddPathTmp->AddCurve( pReturnPath->Clone()) ; + Vector3d vtExtr = pNewCutRegion->GetNormVersor() ; + pAddPathTmp->SetExtrusion( vtExtr) ; + + OffsetCurve OffsCrv ; + OffsCrv.Make( pAddPathTmp, m_TParams.m_dDiam / 2 + 10 * EPS_SMALL, ICurve::OFF_FILLET) ; + ICurve * pCrvOffs = OffsCrv.GetLongerCurve() ; + PtrOwner pToolSrf( CreateSurfFlatRegion()) ; + + pToolSrf->AddExtLoop( pCrvOffs->Clone()) ; + while ( OffsCrv.GetCurveCount() != 0) { + ICurve * pCrvOffs2 = OffsCrv.GetCurve() ; + pToolSrf->AddIntLoop( pCrvOffs2->Clone()) ; + } + + // aggiorno la superficie lavorata + if ( ! pNewCutRegion->Add( *Release( pToolSrf))) { + + // se fallisce provo con una ToolSurf più piccola + pToolSrf.Set( CreateSurfFlatRegion()) ; + OffsCrv.Make( pAddPathTmp, m_TParams.m_dDiam / 2 - 10 * EPS_SMALL, ICurve::OFF_FILLET) ; + ICurve * pCrvOffs = OffsCrv.GetLongerCurve() ; + pToolSrf->AddExtLoop( pCrvOffs->Clone()) ; + + while ( OffsCrv.GetCurveCount() != 0) { + ICurve * pCrvOffs2 = OffsCrv.GetCurve() ; + pToolSrf->AddIntLoop( pCrvOffs2->Clone()) ; + } + + if ( ! pNewCutRegion->Add( *Release( pToolSrf))) + return false ; + } + + + // porto le curva in locale per farne intersezione + Frame3d frLoc ; + frLoc.Set( ORIG, vtExtr) ; + CurveLocal pResidualCrvLoc( pResidualCrv, GLOB_FRM, frLoc) ; + CurveLocal pOffsCrvLoc( pCrvOffs, GLOB_FRM, frLoc) ; + + IntersCurveCurve intersCC( *pResidualCrvLoc, *pOffsCrvLoc) ; + CRVCVECTOR ccClass ; + intersCC.GetCurveClassification( 0, ccClass) ; + + // ricorsione su eventuali aree non lavorate rimaste + size_t nFirst = 0 ; + size_t nLast = ccClass.size() ; + + // verifico se posso trattare in una volta sola la parte inziale e finale della curva + if ( pResidualCrv->IsClosed() && ccClass.front().nClass == CRVC_OUT && ccClass.back().nClass == CRVC_OUT) { + ICurveComposite* pNewResidualCrv = CreateCurveComposite() ; + pNewResidualCrv->AddCurve( pResidualCrv->CopyParamRange( ccClass.back().dParS, ccClass.back().dParE)) ; + pNewResidualCrv->AddCurve( pResidualCrv->CopyParamRange( ccClass.front().dParS, ccClass.front().dParE)) ; + ICurveComposite * pNewAddPath = CreateCurveComposite() ; + if ( ! ComputeAdditionalPath( ptEnd, Point3d(), false, pNewAddPath, pNewResidualCrv, pSrfBound, pNewCutRegion)) + return false ; + pAddPath->AddCurve( pNewAddPath->Clone()) ; + + nFirst = 1 ; + nLast = ccClass.size() - 1 ; + } + + for ( size_t i = nFirst ; i < nLast ; i++) { + if ( ccClass[i].nClass != CRVC_IN ) { + ICurve * pNewResidualCrv = pResidualCrv->CopyParamRange( ccClass[i].dParS, ccClass[i].dParE) ; + ICurveComposite * pNewAddPath = CreateCurveComposite() ; + if ( ! ComputeAdditionalPath( ptEnd, Point3d(), false, pNewAddPath, pNewResidualCrv, pSrfBound, pNewCutRegion)) + return false ; + pAddPath->AddCurve( pNewAddPath) ; + } + } + + pAddPath->AddCurve( pReturnPath) ; // percorso di ritorno + + return true ; +} + + +//---------------------------------------------------------------------------- +bool +Pocketing::AdditionalPathExternalCentroid( const Point3d ptStart, ICurveComposite * pAddPath, ICurveComposite * pResidualCrv, + const ISurfFlatRegion * pSrfBound, ISurfFlatRegion * pNewCutRegion) +{ + DistPointCurve distPtCrv( ptStart, *pResidualCrv) ; + double dParam ; + int nFlag ; + Point3d ptEnd ; + distPtCrv.GetParamAtMinDistPoint( 0, dParam, nFlag) ; + distPtCrv.GetMinDistPoint( 0, ptEnd, nFlag) ; + pResidualCrv->ChangeStartPoint( dParam) ; + + if ( ! CalcBoundedLink( ptStart, ptEnd, pSrfBound, pAddPath)) + return false ; + + PtrOwner pReturnPath( pAddPath->Clone()) ; // percorso di ritorno + pReturnPath->Invert() ; + + pAddPath->AddCurve( pResidualCrv->Clone()) ; + pAddPath->AddCurve( Release( pReturnPath)) ; + + // area coperta da pAddPath + PtrOwner pToolSrf( CreateSurfFlatRegion()) ; + OffsetCurve OffsCrvPlus ; + if ( ! OffsCrvPlus.Make( pAddPath, m_TParams.m_dDiam / 2 + 5 * EPS_SMALL, ICurve::OFF_FILLET)) + return false ; + ICurve * pCrvOffPlus = OffsCrvPlus.GetLongerCurve() ; + if ( pCrvOffPlus == nullptr) + pToolSrf->AddExtLoop( pResidualCrv->Clone()) ; + else + pToolSrf->AddExtLoop( pCrvOffPlus) ; + + OffsetCurve OffsCrvMinus ; + OffsCrvMinus.Make( pAddPath, - m_TParams.m_dDiam / 2 - 5 * EPS_SMALL, ICurve::OFF_FILLET) ; + ICurve * pCrvOffMinus = OffsCrvMinus.GetLongerCurve() ; + while ( pCrvOffMinus != nullptr) { + if ( GetCurveRadius( pCrvOffMinus) > EPS_ZERO) + pToolSrf->AddIntLoop( pCrvOffMinus) ; + pCrvOffMinus = OffsCrvMinus.GetCurve() ; + } + + // aggiorno la superficie lavorata + if ( ! pNewCutRegion->Add( *Release( pToolSrf))) { + + // se fallisce provo con una ToolSurf più piccola + pToolSrf.Set( CreateSurfFlatRegion()) ; + if ( ! OffsCrvPlus.Make( pAddPath, m_TParams.m_dDiam / 2 - 5 * EPS_SMALL, ICurve::OFF_FILLET)) + return false ; + pCrvOffPlus = OffsCrvPlus.GetLongerCurve() ; + + if ( pCrvOffPlus == nullptr) + pToolSrf->AddExtLoop( pResidualCrv->Clone()) ; + else + pToolSrf->AddExtLoop( pCrvOffPlus->Clone()) ; + + OffsCrvMinus.Make( pAddPath, - m_TParams.m_dDiam / 2 + 5 * EPS_SMALL, ICurve::OFF_FILLET) ; + pCrvOffMinus = OffsCrvMinus.GetLongerCurve() ; + while ( pCrvOffMinus != nullptr) { + if ( GetCurveRadius( pCrvOffMinus) > EPS_ZERO) + pToolSrf->AddIntLoop( pCrvOffMinus) ; + pCrvOffMinus = OffsCrvMinus.GetCurve() ; + } + + if ( ! pNewCutRegion->Add( *Release( pToolSrf))) + return false ; + } + + return true ; +} + diff --git a/Pocketing.h b/Pocketing.h index b50ea06..902e2ab 100644 --- a/Pocketing.h +++ b/Pocketing.h @@ -88,6 +88,13 @@ class Pocketing : public Machining double dDepth, double dElev, double dOkStep, bool bSplitArcs) ; bool CalcSpiral( const ISurfFlatRegion* pSrf, int nReg, bool bSplitArcs, ICurveComposite* pMCrv, ICurveComposite* pRCrv) ; + bool RemoveUncutRegions( const ISurfFlatRegion * pCutRegion, ICRVCOMPOPVECTOR& vOffs, const ISurfFlatRegion * pSrfBound) ; + bool FindCurveForPathAdd( const ICurve* pResidualCrv, const ICRVCOMPOPOVECTOR& vOffs, size_t& nIdxMin, Point3d& ptMinDist, + double& dMinDistPar, const ISurfFlatRegion * pSrfBound) ; + bool ComputeAdditionalPath( const Point3d ptStart, Point3d ptEnd, bool bUsePtEnd, ICurveComposite * pAddPath, + const ICurve * pResidualCrv, const ISurfFlatRegion * pSrfBound, ISurfFlatRegion * pNewCutRegion) ; + bool AdditionalPathExternalCentroid( const Point3d ptStart, ICurveComposite * pAddPath, ICurveComposite * pResidualCrv, + const ISurfFlatRegion * pSrfBound, ISurfFlatRegion * pNewCutRegion) ; bool CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, const ISurfFlatRegion * pSrf, ICurveComposite* pCrvLink) ; bool CircleSpiral( ISurfFlatRegion* pSrf, bool bSplitArcs, ICRVCOMPOPVECTOR& vOffs, ICurveComposite* pRCrv) ;