From 947164bfcc707cfa7b9433d3c9fbe124bbac1e96 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Mon, 17 Aug 2026 11:38:08 +0200 Subject: [PATCH] EgtMachKernel : - in Finitura di lama Section e Agross aggiunta gestione dei percorsi mediante curve composite, rimuovendo quella mediante PolyLines. - in Finitura di lama Section migliorato il controllo del trim della sezione - in Finitura di lama Section migliorati i contrilli sui link di tipo Standard ed Extended - in Finiture di lama semplificazione del codice. --- SawFinishing.cpp | 543 ++++++++++++++++++++++++++++++++++------------- SawFinishing.h | 15 +- 2 files changed, 399 insertions(+), 159 deletions(-) diff --git a/SawFinishing.cpp b/SawFinishing.cpp index bb35366..86de92c 100644 --- a/SawFinishing.cpp +++ b/SawFinishing.cpp @@ -19,6 +19,7 @@ #include "OperationConst.h" #include "OperUserNotesConst.h" #include "GeoConst.h" +#include "EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EXeCmdLogOff.h" #include "/EgtDev/Include/EXeConst.h" #include "/EgtDev/Include/EGkCurveLine.h" @@ -915,6 +916,15 @@ SawFinishing::AdjustEndPointForAxesCalc( const CamData* pCamData, Point3d& ptP) return true ; } +//---------------------------------------------------------------------------- +bool +SawFinishing::AdjustArcCenterForAxesCalc( const CamData* pCamData, Point3d& ptCen) const +{ + // compenso il raggio dell'utensile + ptCen += pCamData->GetCorrDir() * ( m_TParams.m_dDiam / 2) ; + return true ; +} + //---------------------------------------------------------------------------- bool SawFinishing::VerifyGeometry( SelData Id, int& nSubs) @@ -1390,44 +1400,52 @@ SawFinishing::CalculateStraightAcrossToolPath( int nAuxId, int nClId) return false ; } + // Verifico se richiesta approssimazione + bool bSplit = GetSplitArcs( vtTool) ; + // per ogni sezione for ( int nSect = 0 ; nSect < ssize( vpSections) ; ++ nSect) { - // recupero la sezione corrente - ICurve* pCrv = vpSections[nSect] ; - if ( pCrv == nullptr || ! pCrv->IsValid()) - continue ; - - // Approssimo la curva con una spezzata - PolyLine PL ; - if ( ! pCrv->ApproxWithLines( LIN_TOL_MID, ANG_TOL_STD_DEG, ICurve::APL_RIGHT, PL)) { - m_pMchMgr->SetLastError( 2706, "Error in SawFinishing : ApproxWithLines") ; + // Recupero la Curva Composita associata alla sezione locale + PtrOwner pCompo( ConvertCurveToComposite( ::Release( vpSections[nSect]))) ; + if ( IsNull( pCompo) || ! pCompo->IsValid()) return false ; + + // Se richiesta approssimazione + if ( bSplit) { + PolyLine PL ; + if ( ! pCompo->ApproxWithLines( LIN_TOL_MID, ANG_TOL_STD_DEG, ICurve::APL_RIGHT, PL) || + ! pCompo->Clear() || ! pCompo->FromPolyLine( PL)) { + m_pMchMgr->SetLastError( 2706, "Error in SawFinishing : ApproxWithLines") ; + return false ; + } } + else { + // Aggiungo dei Join presso gli archi nei loro punti estremi in Z e limito l'angolo massimo dell'arco + const double MAX_ANG_DEG = 45. ; + if ( ! SplitLeftRightArcSection( pCompo, MAX_ANG_DEG)) + return false ; + } + + // Se standard, allungo inizio e fine della sezione dello spessore lama if ( m_Params.m_nLeadLinkType == SAWFIN_LL_STD) { - // inizio - PL.Invert() ; - double dU ; - Point3d ptP ; - PL.GetLastUPoint( &dU, &ptP) ; - PL.AddUPoint( dU, ptP + Vector3d( m_TParams.m_dThick, 0, 0)) ; - PL.Invert() ; - // fine - PL.GetLastUPoint( &dU, &ptP) ; - PL.AddUPoint( dU, ptP - Vector3d( m_TParams.m_dThick, 0, 0)) ; + Point3d ptStart ; pCompo->GetStartPoint( ptStart) ; + pCompo->AddLine( ptStart + m_TParams.m_dThick * X_AX, false) ; + Point3d ptEnd ; pCompo->GetEndPoint( ptEnd) ; + pCompo->AddLine( ptEnd - m_TParams.m_dThick * X_AX, true) ; } // La porto in globale - PL.ToGlob( frSect) ; - PL.Translate( vtDeltaSect) ; + pCompo->ToGlob( frSect) ; + pCompo->Translate( vtDeltaSect) ; if ( m_Params.m_bInvert) - PL.Translate( ptGdStart - ptGdEnd) ; + pCompo->Translate( ptGdStart - ptGdEnd) ; // Calcolo eventuale anticipo dell'inizio double dAddStart = 0 ; if ( m_Params.m_nLeadLinkType == SAWFIN_LL_OUT) { BBox3d b3PL ; - PL.GetLocalBBox( b3PL) ; + pCompo->GetLocalBBox( b3PL) ; double dMaxElev = min( dDepth, b3Raw.GetMax().z - b3PL.GetMin().z) ; if ( dMaxElev > 0.0 && dMaxElev < 0.5 * m_TParams.m_dDiam) dAddStart = sqrt( dMaxElev * m_TParams.m_dDiam - dMaxElev * dMaxElev) ; @@ -1457,12 +1475,12 @@ SawFinishing::CalculateStraightAcrossToolPath( int nAuxId, int nClId) Vector3d vtMove = vtGdDir * ( - dAddStart + i * dStep) ; // lavoro la sezione if ( m_Params.m_nStepType != SAWFIN_ST_ZIGZAG) { - if ( ! CalcAcrossOneWayCut( PL, vtMove, vtTool, vtCorr, b3Raw.GetMax().z, dDepth)) + if ( ! CalcAcrossOneWayCut( pCompo, vtMove, vtTool, vtCorr, b3Raw.GetMax().z, dDepth)) return false ; } else { bool bFirst = ( i == 0) ; - if ( ! CalcAcrossZigZagCut( PL, vtMove, vtTool, vtCorr, b3Raw.GetMax().z, dDepth, bFirst)) + if ( ! CalcAcrossZigZagCut( pCompo, vtMove, vtTool, vtCorr, b3Raw.GetMax().z, dDepth, bFirst)) return false ; } } @@ -1866,11 +1884,16 @@ SawFinishing::CalculateStraightSectionToolPath( int nAuxId, int nClId) BBox3d b3Sect ; m_pGeomDB->GetGlobalBBox( nSectGrpId, b3Sect) ; // Recupero ed elaboro le sezioni per portarle ad essere la curva del centro in basso della lama - ICurve* pSect ; - if ( ! CalculateOffsetSection( nSectGrpId, frSect, pSect)) + ICurve* pSect, + * pOrigSect ; + ISurfFlatRegion* pSfrLimit ; + if ( ! CalculateOffsetSection( nSectGrpId, frSect, pSect, pOrigSect, pSfrLimit)) return false ; - PtrOwner pCrv( pSect) ; - if ( IsNull( pCrv) || ! pCrv->IsValid()) + PtrOwner pCrv( pSect), + pCrvOrig( pOrigSect) ; + PtrOwner pSfrTabLimit( pSfrLimit) ; + if ( IsNull( pCrv) || ! pCrv->IsValid() || IsNull( pCrvOrig) || ! pCrvOrig->IsValid() || + IsNull( pSfrTabLimit) || ! pSfrTabLimit->IsValid()) return false ; // Recupero da UserNotes il flag di estensione al bordo del grezzo @@ -1932,29 +1955,94 @@ SawFinishing::CalculateStraightSectionToolPath( int nAuxId, int nClId) return false ; } - // Approssimo la curva di sezione ad una spezzata - PolyLine PL ; - if ( ! pCrv->ApproxWithLines( LIN_TOL_MID, ANG_TOL_STD_DEG, ICurve::APL_RIGHT, PL)) { - m_pMchMgr->SetLastError( 2706, "Error in SawFinishing : ApproxWithLines") ; + // Recupero la Curva Composita associata alla sezione locale + PtrOwner pCompo( ConvertCurveToComposite( ::Release( pCrv))) ; + if ( IsNull( pCompo) || ! pCompo->IsValid()) return false ; + + // Verifico se richiesta approssimazione + bool bSplit = GetSplitArcs( vtTool) ; + if ( bSplit) { + // Approssimo la curva di sezione ad una spezzata + PolyLine PL ; + if ( ! pCrv->ApproxWithLines( LIN_TOL_MID, ANG_TOL_STD_DEG, ICurve::APL_RIGHT, PL) || + ! pCompo->Clear() || ! pCompo->FromPolyLine( PL)) { + m_pMchMgr->SetLastError( 2706, "Error in SawFinishing : ApproxWithLines") ; + return false ; + } } - // Se link standard, allungo inizio e fine della sezione dello spessore lama + else { + // Aggiungo dei Join presso gli archi nei loro punti estremi in Z e limito l'angolo massimo dell'arco + const double MAX_ANG_DEG = 45. ; + if ( ! SplitLeftRightArcSection( pCompo, MAX_ANG_DEG)) + return false ; + } + + // Se link standard, allungo inizio e fine della sezione dello spessore lama (senza scendere sotto la quota Z di sicurezza) if ( m_Params.m_nLeadLinkType == SAWFIN_LL_STD) { - // inizio - PL.Invert() ; - double dU ; - Point3d ptP ; - PL.GetLastUPoint( &dU, &ptP) ; - PL.AddUPoint( dU, ptP + Vector3d( m_TParams.m_dThick, 0., 0.)) ; - PL.Invert() ; - // fine - PL.GetLastUPoint( &dU, &ptP) ; - PL.AddUPoint( dU, ptP - Vector3d( m_TParams.m_dThick, 0., 0.)) ; + Point3d ptS, ptE ; + pCompo->GetStartPoint( ptS) ; pCompo->GetEndPoint( ptE) ; + Vector3d vtS, vtE ; + pCompo->GetStartDir( vtS) ; vtS.Invert() ; pCompo->GetEndDir( vtE) ; + PtrOwner pLineS( CreateCurveLine()), + pLineE( CreateCurveLine()) ; + if ( IsNull( pLineS) || ! pLineS->Set( ptS, ptS + vtS * m_TParams.m_dThick) || + IsNull( pLineE) || ! pLineE->Set( ptE, ptE + vtE * m_TParams.m_dThick)) + return false ; + PtrOwner pCrvLimit( pSfrTabLimit->GetLoop( 0, 0)) ; + if ( IsNull( pCrvLimit) || ! pCrvLimit->IsValid()) + return false ; + // --- aggiunta estensione iniziale (verifica con sezione e tavola) + pLineS->SetExtrusion( GetToLoc( vtTool, frSect)) ; + PtrOwner pSfrSawShape( GetSurfFlatRegionFromFatCurve( pLineS->Clone(), m_TParams.m_dDiam / 2. + GetOffsR() - 10. * EPS_SMALL, false, false)) ; + if ( IsNull( pSfrSawShape) || ! pSfrSawShape->IsValid() || + ! pSfrSawShape->Translate( GetToLoc( vtCorr, frSect) * m_TParams.m_dDiam / 2.)) + return false ; + CRVCVECTOR ccClass ; + if ( ! pSfrSawShape->GetCurveClassification( *pCrvOrig, EPS_SMALL, ccClass)) + return false ; + bool bInters = false ; + for ( int j = 0 ; ! bInters && j < ssize( ccClass) ; ++ j) + bInters = ( ccClass[j].nClass == CRVC_IN) ; + if ( ! bInters) { + IntersCurveCurve ICCS( *pLineS, *pCrvLimit) ; + if ( ICCS.GetIntersCount() == 0) + pCompo->AddLine( ptS + vtS * m_TParams.m_dThick, false) ; + else { + IntCrvCrvInfo aInfo ; + if ( ! ICCS.GetIntCrvCrvInfo( 0, aInfo)) + return false ; + pCompo->AddLine( aInfo.IciA->ptI, false) ; + } + } + // --- aggiunta estensione finale (verifica con sezione e tavola) + pLineE->SetExtrusion( GetToLoc( vtTool, frSect)) ; + pSfrSawShape.Set( GetSurfFlatRegionFromFatCurve( pLineE->Clone(), m_TParams.m_dDiam / 2. + GetOffsR() - 10. * EPS_SMALL, false, false)) ; + if ( IsNull( pSfrSawShape) || ! pSfrSawShape->IsValid() || + ! pSfrSawShape->Translate( GetToLoc( vtCorr, frSect) * m_TParams.m_dDiam / 2.)) + return false ; + ccClass.clear() ; + if ( ! pSfrSawShape->GetCurveClassification( *pCrvOrig, EPS_SMALL, ccClass)) + return false ; + bInters = false ; + for ( int j = 0 ; ! bInters && j < ssize( ccClass) ; ++ j) + bInters = ( ccClass[j].nClass == CRVC_IN) ; + if ( ! bInters) { + IntersCurveCurve ICCE( *pLineE, *pCrvLimit) ; + if ( ICCE.GetIntersCount() == 0) + pCompo->AddLine( ptE + vtE * m_TParams.m_dThick, true) ; + else { + IntCrvCrvInfo aInfo ; + if ( ! ICCE.GetIntCrvCrvInfo( 0, aInfo)) + return false ; + pCompo->AddLine( aInfo.IciA->ptI, true) ; + } + } } // La porto in globale - PL.ToGlob( frSect) ; + pCompo->ToGlob( frSect) ; // traslo la sezione lungo la direzione della guida per farla coicidere con il suo punto iniziale - PL.Translate( ( ( ptGdStart - GetToGlob( ptSecStart, frSect)) * vtGdDir) * vtGdDir) ; + pCompo->Translate( ( ( ptGdStart - GetToGlob( ptSecStart, frSect)) * vtGdDir) * vtGdDir) ; // Imposto dati comuni SetPathId( nPxId) ; @@ -2001,24 +2089,38 @@ SawFinishing::CalculateStraightSectionToolPath( int nAuxId, int nClId) int nStep = static_cast( ceil( dL/dStep)) ; dStep = dL / nStep ; Point3d ptP ; + + if ( m_Params.m_nLeadLinkType == SAWFIN_LL_OUT) { + pCrvOrig->ToGlob( frSect) ; + pSfrTabLimit->ToGlob( frSect) ; + } + for ( int i = 0 ; i <= nStep ; ++ i) { // vettore di spostamento Vector3d vtMove = vtGdDir * ( i * dStep) ; + // Curva di percorso corrente + ICurveComposite* pCompoPath = pCompo ; + // se link Extended, allora estendo il percorso fino alla dimensione del grezzo + PtrOwner pCompoTmp( nullptr) ; if ( m_Params.m_nLeadLinkType == SAWFIN_LL_OUT) { - PL.Translate( vtMove) ; - if ( ! ExtendPathToRaw( PL, pStmRaw, m_TParams.m_dThick)) + pCompoTmp.Set( CloneCurveComposite( pCompoPath)) ; + if ( IsNull( pCompoTmp)) return false ; - PL.Translate( - vtMove) ; + pCompoTmp->Translate( vtMove) ; + if ( ! ExtendPathToRaw( pCompoTmp, pStmRaw, m_TParams.m_dThick, pCrvOrig)) + return false ; + pCompoTmp->Translate( - vtMove) ; + pCompoPath = pCompoTmp ; } // lavoro la sezione if ( m_Params.m_nStepType != SAWFIN_ST_ZIGZAG) { - if ( ! CalcAcrossOneWayCut( PL, vtMove, vtTool, vtCorr, b3Raw.GetMax().z, dDepth)) + if ( ! CalcAcrossOneWayCut( pCompoPath, vtMove, vtTool, vtCorr, b3Raw.GetMax().z, dDepth)) return false ; } else { bool bFirst = ( i == 0) ; - if ( ! CalcAcrossZigZagCut( PL, vtMove, vtTool, vtCorr, b3Raw.GetMax().z, dDepth, bFirst)) + if ( ! CalcAcrossZigZagCut( pCompoPath, vtMove, vtTool, vtCorr, b3Raw.GetMax().z, dDepth, bFirst)) return false ; } } @@ -2153,15 +2255,18 @@ SawFinishing::CalculateStraightAlong5AToolPath( int nAuxId, int nClId) //---------------------------------------------------------------------------- bool -SawFinishing::ExtendPathToRaw( PolyLine& PL, const ISurfTriMesh* pStmRaw, double dExtraOut) const +SawFinishing::ExtendPathToRaw( ICurveComposite* pCompo, const ISurfTriMesh* pStmRaw, double dExtraOut, const ICurve* pSection) const { // se grezzo non valido, non estendo nulla if ( pStmRaw == nullptr || ! pStmRaw->IsValid() || pStmRaw->GetTriangleCount() == 0) return true ; + // se curve non valide, errore + if ( pCompo == nullptr || ! pCompo->IsValid()) + return false ; // recupero gli estremi della PolyLine e il versore di estensione - Point3d ptS ; PL.GetFirstPoint( ptS) ; - Point3d ptE ; PL.GetLastPoint( ptE) ; + Point3d ptS ; pCompo->GetStartPoint( ptS) ; + Point3d ptE ; pCompo->GetEndPoint( ptE) ; Vector3d vtExt = ( ptE - ptS) ; vtExt.z = 0. ; if ( ! vtExt.Normalize()) @@ -2178,11 +2283,32 @@ SawFinishing::ExtendPathToRaw( PolyLine& PL, const ISurfTriMesh* pStmRaw, double for ( int i = 0 ; i < ssize( vInfo) ; ++ i) { // se c'è intersezione ed esco dalla superficie if ( vInfo[i].nILTT != ILTT_NO && vInfo[i].dCosDN > COS_SMALL) { - // aggiungo il punto di intersezione con il grezzo - PL.AddUPoint( 0., vInfo[i].ptI, false) ; + // verifico se la lama rovina la sezione corrente + if ( pSection != nullptr && pSection->IsValid()) { + PtrOwner pLine( CreateCurveLine()) ; + if ( IsNull( pLine)) + return false ; + if ( ! pLine->Set( ptS, vInfo[i].ptI) || ! pLine->SetExtrusion( m_vtTool)) + break ; // punti troppo vicini + // Offset della linea per recuperare il centro della lama + PtrOwner pSfrSawShape( GetSurfFlatRegionFromFatCurve( pLine->Clone(), m_TParams.m_dDiam / 2. + GetOffsR() - 10. * EPS_SMALL, false, false)) ; + if ( IsNull( pSfrSawShape) || ! pSfrSawShape->IsValid() || + ! pSfrSawShape->Translate( m_vtCorr * m_TParams.m_dDiam / 2.)) + break ; + CRVCVECTOR ccClass ; + if ( ! pSfrSawShape->GetCurveClassification( *pSection, EPS_SMALL, ccClass)) + break ; + bool bBreak = false ; + for ( int j = 0 ; ! bBreak && j < ssize( ccClass) ; ++ j) + bBreak = ( ccClass[j].nClass == CRVC_IN) ; + if ( bBreak) + break ; + } + // aggiungo il punto di intersezione con i grezzo + pCompo->AddLine( vInfo[i].ptI, false) ; // aggiungo un punto per estensione aggiuntiva if ( dExtraOut > EPS_SMALL) - PL.AddUPoint( 0., vInfo[i].ptI - vtExt * dExtraOut, false) ; + pCompo->AddLine( vInfo[i].ptI - vtExt * dExtraOut, false) ; break ; } } @@ -2196,11 +2322,32 @@ SawFinishing::ExtendPathToRaw( PolyLine& PL, const ISurfTriMesh* pStmRaw, double for ( int i = 0 ; i < ssize( vInfo) ; ++ i) { // se c'è intersezione ed esco dalla superficie if ( vInfo[i].nILTT != ILTT_NO && vInfo[i].dCosDN > COS_SMALL) { + // verifico se la lama rovina la sezione corrente + if ( pSection != nullptr && pSection->IsValid()) { + PtrOwner pLine( CreateCurveLine()) ; + if ( IsNull( pLine)) + return false ; + if ( ! pLine->Set( ptE, vInfo[i].ptI) || ! pLine->SetExtrusion( m_vtTool)) + break ; // punti troppo vicini + // Offset della linea per recuperare il centro della lama + PtrOwner pSfrSawShape( GetSurfFlatRegionFromFatCurve( pLine->Clone(), m_TParams.m_dDiam / 2. + GetOffsR() - 10. * EPS_SMALL, false, false)) ; + if ( IsNull( pSfrSawShape) || ! pSfrSawShape->IsValid() || + ! pSfrSawShape->Translate( m_vtCorr * m_TParams.m_dDiam / 2.)) + break ; + CRVCVECTOR ccClass ; + if ( ! pSfrSawShape->GetCurveClassification( *pSection, EPS_SMALL, ccClass)) + break ; + bool bBreak = false ; + for ( int j = 0 ; ! bBreak && j < ssize( ccClass) ; ++ j) + bBreak = ( ccClass[j].nClass == CRVC_IN) ; + if ( bBreak) + break ; + } // aggiungo il punto di intersezione con il grezzo - PL.AddUPoint( 0., vInfo[i].ptI, true) ; + pCompo->AddLine( vInfo[i].ptI, true) ; // aggiungo un punto per estensione aggiuntiva if ( dExtraOut > EPS_SMALL) - PL.AddUPoint( 0., vInfo[i].ptI + vtExt * dExtraOut, true) ; + pCompo->AddLine( vInfo[i].ptI + vtExt * dExtraOut, true) ; break ; } } @@ -2211,7 +2358,8 @@ SawFinishing::ExtendPathToRaw( PolyLine& PL, const ISurfTriMesh* pStmRaw, double //---------------------------------------------------------------------------- bool -SawFinishing::CalculateOffsetSection( int nSectGrpId, const Frame3d& frSec, ICurve*& pSect) const +SawFinishing::CalculateOffsetSection( int nSectGrpId, const Frame3d& frSec, ICurve*& pSect, ICurve*& pOrigSec, + ISurfFlatRegion*& pSfrLimit) const { // recupero le sezioni ICURVEPVECTOR vpSects ; @@ -2239,8 +2387,7 @@ SawFinishing::CalculateOffsetSection( int nSectGrpId, const Frame3d& frSec, ICur // calcolo ordinamento delle curve secondo la X decrescente typedef pair INDASC ; // coppia indice, ascissa typedef vector INDASCVECTOR ; // vettore di coppie indice, ascissa - INDASCVECTOR vIAsc ; - vIAsc.reserve( vpNucCrvs.size()) ; + INDASCVECTOR vIAsc ; vIAsc.reserve( vpNucCrvs.size()) ; for ( int i = 0 ; i < ssize( vpNucCrvs) ; ++ i) { Point3d ptStart ; if ( ! vpNucCrvs[i]->GetStartPoint( ptStart)) @@ -2250,21 +2397,23 @@ SawFinishing::CalculateOffsetSection( int nSectGrpId, const Frame3d& frSec, ICur sort( vIAsc.begin(), vIAsc.end(), []( const INDASC& a, const INDASC& b) { return a.second > b.second ; }) ; // definisco la regione non oltrepassabile dal fondo della lama - BBox3d b3Raw ; - if ( ! GetCurrRawsGlobBox( b3Raw) || b3Raw.IsEmpty()) { - m_pMchMgr->SetLastError( 2703, "Error in SawFinishing : Empty RawBox") ; + Machine* pMch = m_pMchMgr->GetCurrMachine() ; + if ( pMch == nullptr) return false ; - } - b3Raw.ToLoc( frSec) ; - Point3d ptMin = b3Raw.GetMin(), - ptMax = b3Raw.GetMax() ; - double dMinY = 5. ; - double dTabDist = 0. ; + BBox3d BBoxLimit ; + pMch->GetCurrTableArea1( BBoxLimit) ; + if ( BBoxLimit.IsEmpty()) + return false ; + BBoxLimit.ToLoc( frSec) ; + Point3d ptMin = BBoxLimit.GetMin(), + ptMax = BBoxLimit.GetMax() ; + double dMinY = 5., + dTabDist = 0. ; if ( GetValInNotes( m_Params.m_sUserNotes, UN_RB_DIST, dTabDist) && dTabDist > dMinY) dMinY = dTabDist ; const double LINE_EXT = 1e5 ; - Point3d ptLineMinYStart = Point3d( ptMin.x - LINE_EXT, ptMin.y + dMinY, 0.) ; - Point3d ptLineMinYEnd = Point3d( ptMax.x + LINE_EXT, ptMin.y + dMinY, 0.) ; + Point3d ptLineMinYStart = Point3d( ptMin.x - LINE_EXT, ptMax.y + dMinY, 0.), + ptLineMinYEnd = Point3d( ptMax.x + LINE_EXT, ptMax.y + dMinY, 0.) ; PtrOwner pCompoRegLimit( CreateCurveComposite()) ; if ( IsNull( pCompoRegLimit)) return false ; @@ -2273,10 +2422,12 @@ SawFinishing::CalculateOffsetSection( int nSectGrpId, const Frame3d& frSec, ICur pCompoRegLimit->AddLine( ptLineMinYEnd - Y_AX * LINE_EXT) ; pCompoRegLimit->AddLine( ptLineMinYEnd) ; pCompoRegLimit->Close() ; - PtrOwner pSfrLimit( CreateSurfFlatRegion()) ; - if ( IsNull( pSfrLimit) || ! pSfrLimit->AddExtLoop( ::Release( pCompoRegLimit))) + PtrOwner pMySfrLimit( CreateSurfFlatRegion()) ; + if ( IsNull( pMySfrLimit) || ! pMySfrLimit->AddExtLoop( ::Release( pCompoRegLimit))) return false ; + pSfrLimit = Release( pMySfrLimit) ; + // unisco le diverse curve (ora aperte) in un unico profilo PtrOwner pCurve( CreateCurveComposite()) ; if ( IsNull( pCurve)) @@ -2294,11 +2445,22 @@ SawFinishing::CalculateOffsetSection( int nSectGrpId, const Frame3d& frSec, ICur bFirst = false ; } + // memorizzo la sezione corrente + if ( IsNull( pCurve) || ! pCurve->IsValid()) + return false ; + pOrigSec = pCurve->Clone() ; + + // effettuo trim per parti iniziali e finali + if ( ! TrimSection( pCurve)) + return false ; + // offset radiale delle sezioni per il sovramateriale e il raggio utensile OffsetCurve OffsCrv ; pCurve->Translate( - Y_AX * m_TParams.m_dDiam / 2.) ; OffsCrv.Make( pCurve, m_TParams.m_dDiam / 2. + GetOffsR(), ICurve::OFF_FILLET) ; PtrOwner pOvrCrv( OffsCrv.GetLongerCurve()) ; + if ( IsNull( pOvrCrv)) + return false ; // la curva ricavata deve essere sufficientemente distante dal fondo del grezzo CRVCVECTOR ccClass ; @@ -2326,7 +2488,7 @@ SawFinishing::CalculateOffsetSection( int nSectGrpId, const Frame3d& frSec, ICur } // eseguo trim (se richiesto) - if ( IsNull( pCurve) || ! TrimSection( pCurve)) + if ( IsNull( pCurve)) return false ; pSect = Release( pCurve) ; @@ -2731,6 +2893,57 @@ SawFinishing::Split5ASection( int nSectGrpId, SECTIONVECTOR& vSections) const return true ; } +//---------------------------------------------------------------------------- +bool +SawFinishing::SplitLeftRightArcSection( ICurveComposite* pCompo, double dMaxAngDeg) const +{ + // verifico che la curva composita sia valida + if ( pCompo == nullptr || ! pCompo->IsValid()) + return false ; + // verifico valore dell'angolo + double dMyMaxAngDeg = Clamp( dMaxAngDeg, 15., 90.) ; + + int i = 0 ; + const ICurve* pCrv = pCompo->GetCurve( i) ; + while ( pCrv != nullptr) { + if ( pCrv->GetType() == CRV_ARC) { + const ICurveArc* pArc = GetCurveArc( pCrv) ; + // determino la rotazione angolare dall'inizio alle direzioni su e giù + double dAng1, dAng2 ; + bool bDet ; + pArc->GetStartVersor().GetRotation( Y_AX, Z_AX, dAng1, bDet) ; + pArc->GetStartVersor().GetRotation( - Y_AX, Z_AX, dAng2, bDet) ; + // oriento queste rotazioni come l'angolo al centro dell'arco + if ( pArc->GetAngCenter() > 0.) { + if ( dAng1 < 0.) + dAng1 += ANG_FULL ; + if ( dAng2 < 0.) + dAng2 += ANG_FULL ; + } + else { + if ( dAng1 > 0.) + dAng1 -= ANG_FULL ; + if ( dAng2 > 0.) + dAng2 -= ANG_FULL ; + } + // le ordino in senso crescente di ampiezza assoluta + if ( abs( dAng1) > abs( dAng2)) + swap( dAng1, dAng2) ; + // verifico se la prima di queste rotazioni è compresa nell'arco + if ( abs( dAng1) > EPS_ANG_SMALL && abs( dAng1) < abs( pArc->GetAngCenter()) - EPS_ANG_SMALL) + pCompo->AddJoint( i + dAng1 / pArc->GetAngCenter()) ; + // verifico la seconda + else if ( abs( dAng2) > EPS_ANG_SMALL && abs( dAng2) < abs( pArc->GetAngCenter()) - EPS_ANG_SMALL) + pCompo->AddJoint( i + dAng2 / pArc->GetAngCenter()) ; + } + // passo alla successiva + pCrv = pCompo->GetCurve( ++ i) ; + } + + // verifiche sull'ampiezza dell'angolo al centro degli eventuali archi + return VerifyArcs( pCompo, dMyMaxAngDeg) ; +} + //---------------------------------------------------------------------------- bool SawFinishing::AdaptGuideLineToRaw( Point3d& ptGdStart, Point3d& ptGdEnd, const Vector3d& vtGdDir, bool bExtend, const ISurfTriMesh* pStmRaw) const @@ -3678,55 +3891,67 @@ SawFinishing::CalcAlongZigZagCut( const Point3d& ptStart, const Point3d& ptEnd, //---------------------------------------------------------------------------- bool -SawFinishing::CalcAcrossOneWayCut( const PolyLine& PL, const Vector3d& vtMove, - const Vector3d& vtTool, const Vector3d& vtCorr, double dRawZ, double dDepth) +SawFinishing::CalcAcrossOneWayCut( const ICurveComposite* pCompo, const Vector3d& vtMove, + const Vector3d& vtTool, const Vector3d& vtCorr, double dRawZ, double dDepth) { + // verifico che la curva sia valida + if ( pCompo == nullptr || ! pCompo->IsValid()) + return false ; + // recupero distanza di sicurezza double dSafeZ = GetSafeZ() ; // lunghezza di approccio/retrazione double dAppr = m_Params.m_dStartPos ; - Point3d ptP ; - // 1 -> approccio - bool bFound = PL.GetFirstPoint( ptP) ; - if ( bFound) { - ptP += vtMove - 0.5 * m_TParams.m_dThick * vtTool ; - ptP.z = max( ptP.z, dRawZ - dDepth) ; - double dElev = dRawZ - ptP.z ; - if ( ! AddApproach( ptP, vtCorr, dSafeZ, dElev, dAppr)) + Point3d ptPrev ; GetCurrPos( ptPrev) ; + + // ciclo sulle curve della sezione + int nCrvCnt = pCompo->GetCurveCount() ; + for ( int i = 0 ; i < nCrvCnt ; ++ i) { + // recupero la curva corrente + const ICurve* pCrv = pCompo->GetCurve( i) ; + if ( pCrv == nullptr || ! pCrv->IsValid()) return false ; - } - // 2 -> movimento lungo la sezione - Point3d ptPrev ; - GetCurrPos( ptPrev) ; - while ( bFound) { - // se diverso da precedente, movimento al punto - if ( ! AreSamePointEpsilon( ptP, ptPrev, 10 * EPS_SMALL)) { - Vector3d vtDelta = ptP - ptPrev ; - if ( vtDelta.z > - EPS_SMALL) - SetFeed( GetFeed()) ; - else { - double dC = sqrt( 1 + ( vtDelta.x * vtDelta.x + vtDelta.y * vtDelta.y) / ( vtDelta.z * vtDelta.z)) ; - double dF = min( GetFeed(), dC * GetTipFeed()) ; - SetFeed( dF) ; - } - if ( AddLinearMove( ptP) == GDB_ID_NULL) - return false ; - ptPrev = ptP ; - } - // recupero punto successivo - bFound = PL.GetNextPoint( ptP) ; - if ( bFound) { - ptP += vtMove - 0.5 * m_TParams.m_dThick * vtTool ; + // sposto la curva corrente + PtrOwner pMyCrv( pCrv->Clone()) ; + if ( IsNull( pMyCrv) || ! pMyCrv->Translate( vtMove - 0.5 * m_TParams.m_dThick * vtTool)) + return false ; + + // approccio + if ( i == 0) { + Point3d ptP ; pMyCrv->GetStartPoint( ptP) ; ptP.z = max( ptP.z, dRawZ - dDepth) ; + double dElev = dRawZ - ptP.z ; + if ( ! AddApproach( ptP, vtCorr, dSafeZ, dElev, dAppr)) + return false ; + } + + // aggiungo la curva corrente + Point3d ptP ; pMyCrv->GetStartPoint( ptP) ; + Vector3d vtDelta = ptP - ptPrev ; + if ( vtDelta.z > - EPS_SMALL) + SetFeed( GetFeed()) ; + else { + double dC = sqrt( 1 + ( vtDelta.x * vtDelta.x + vtDelta.y * vtDelta.y) / ( vtDelta.z * vtDelta.z)) ; + double dF = min( GetFeed(), dC * GetTipFeed()) ; + SetFeed( dF) ; + } + // -- se derivo da approccio, collegamento lineare all'inizio della curva + if ( i == 0) + AddLinearMove( ptP) ; + if ( AddCurveMove( pMyCrv) == GDB_ID_NULL) + return false ; + ptPrev = ptP ; + + // retroazione + if ( i == nCrvCnt - 1) { + Point3d ptP ; pMyCrv->GetEndPoint( ptP) ; + double dElev = dRawZ - ptP.z ; + if ( ! AddRetract( ptP, vtCorr, dSafeZ, dElev, dAppr)) + return false ; } } - // 3-> retrazione - { - double dElev = dRawZ - ptP.z ; - if ( ! AddRetract( ptP, vtCorr, dSafeZ, dElev, dAppr)) - return false ; - } + // incremento contatore passate ++ m_nCuts ; @@ -3735,54 +3960,66 @@ SawFinishing::CalcAcrossOneWayCut( const PolyLine& PL, const Vector3d& vtMove, //---------------------------------------------------------------------------- bool -SawFinishing::CalcAcrossZigZagCut( const PolyLine& PL, const Vector3d& vtMove, - const Vector3d& vtTool, const Vector3d& vtCorr, double dRawZ, double dDepth, bool bFirst) +SawFinishing::CalcAcrossZigZagCut( const ICurveComposite* pCompo, const Vector3d& vtMove, + const Vector3d& vtTool, const Vector3d& vtCorr, double dRawZ, double dDepth, bool bFirst) { + // verifico che la curva sia valida + if ( pCompo == nullptr || ! pCompo->IsValid()) + return false ; + // recupero distanza di sicurezza double dSafeZ = GetSafeZ() ; // lunghezza di approccio/retrazione double dAppr = m_Params.m_dStartPos ; - // sezione da invertire - bool bInvert = (( m_nCuts % 2) != 0) ; + Point3d ptPrev ; GetCurrPos( ptPrev) ; - Point3d ptP ; - bool bFound = ( bInvert ? PL.GetLastPoint( ptP) : PL.GetFirstPoint( ptP)) ; - // 1 -> approccio - if ( bFound) { - ptP += vtMove - 0.5 * m_TParams.m_dThick * vtTool ; - ptP.z = max( ptP.z, dRawZ - dDepth) ; - if ( bFirst) { - double dElev = dRawZ - ptP.z ; - if ( ! AddApproach( ptP, vtCorr, dSafeZ, dElev, dAppr)) - return false ; - } - } - // 2 -> movimento lungo la sezione - Point3d ptPrev ; - GetCurrPos( ptPrev) ; - while ( bFound) { - // se diverso da precedente, movimento al punto - if ( ! AreSamePointEpsilon( ptP, ptPrev, 10 * EPS_SMALL)) { - Vector3d vtDelta = ptP - ptPrev ; - if ( vtDelta.z > - EPS_SMALL) - SetFeed( GetFeed()) ; - else { - double dC = sqrt( 1 + ( vtDelta.x * vtDelta.x + vtDelta.y * vtDelta.y) / ( vtDelta.z * vtDelta.z)) ; - double dF = min( GetFeed(), dC * GetTipFeed()) ; - SetFeed( dF) ; - } - if ( AddLinearMove( ptP) == GDB_ID_NULL) - return false ; - ptPrev = ptP ; - } - // recupero punto successivo - bFound = ( bInvert ? PL.GetPrevPoint( ptP) : PL.GetNextPoint( ptP)) ; - if ( bFound) { - ptP += vtMove - 0.5 * m_TParams.m_dThick * vtTool ; + // ciclo sulle curve della sezione + bool bInvert = ( ! IsEven( m_nCuts)) ; + int nCrvCnt = pCompo->GetCurveCount() ; + for ( int i = ( ! bInvert ? 0 : nCrvCnt - 1) ; ( ! bInvert ? i < nCrvCnt : i >= 0) ; ( ! bInvert ? ++ i : -- i)) { + // recupero la curva corrente + const ICurve* pCrv = pCompo->GetCurve( i) ; + if ( pCrv == nullptr || ! pCrv->IsValid()) + return false ; + // sposto la curva corrente + PtrOwner pMyCrv( pCrv->Clone()) ; + if ( IsNull( pMyCrv) || ! pMyCrv->Translate( vtMove - 0.5 * m_TParams.m_dThick * vtTool)) + return false ; + if ( bInvert) + pMyCrv->Invert() ; + + // approccio + bool bIsFirstIter = ( ! bInvert ? ( i == 0) : ( i == nCrvCnt - 1)) ; + if ( bIsFirstIter) { + Point3d ptP ; pMyCrv->GetStartPoint( ptP) ; ptP.z = max( ptP.z, dRawZ - dDepth) ; + if ( bFirst) { + double dElev = dRawZ - ptP.z ; + if ( ! AddApproach( ptP, vtCorr, dSafeZ, dElev, dAppr)) + return false ; + } } + + // aggiungo la curva corrente + Point3d ptP ; pMyCrv->GetStartPoint( ptP) ; + Vector3d vtDelta = ptP - ptPrev ; + if ( vtDelta.z > - EPS_SMALL) + SetFeed( GetFeed()) ; + else { + double dC = sqrt( 1 + ( vtDelta.x * vtDelta.x + vtDelta.y * vtDelta.y) / ( vtDelta.z * vtDelta.z)) ; + double dF = min( GetFeed(), dC * GetTipFeed()) ; + SetFeed( dF) ; + } + + // -- se derivo da approccio, collegamento lineare all'inizio della curva + if ( bIsFirstIter) + AddLinearMove( ptP) ; + if ( AddCurveMove( pMyCrv) == GDB_ID_NULL) + return false ; + ptPrev = ptP ; } + // incremento contatore passate ++ m_nCuts ; diff --git a/SawFinishing.h b/SawFinishing.h index acdbfb4..81c7376 100644 --- a/SawFinishing.h +++ b/SawFinishing.h @@ -22,6 +22,7 @@ class ICurve ; class ICurveLine ; class ICurveArc ; class ICurveComposite ; +class ISurfFlatRegion ; class ISurfTriMesh ; class Polygon3d ; @@ -71,6 +72,7 @@ class SawFinishing : public Machining int GetSolCh( void) const override { return m_Params.m_nSolCh ; } bool AdjustEndPointForAxesCalc( const CamData* pCamData, Point3d& ptP) const override ; + bool AdjustArcCenterForAxesCalc( const CamData* pCamData, Point3d& ptCen) const override ; public : // Machining bool Prepare( const std::string& sSawName) override ; @@ -103,12 +105,13 @@ class SawFinishing : public Machining bool CalculateCurvedAcrossToolPath( int nAuxId, int nClId) ; bool CalculateStraightSectionToolPath( int nAuxId, int nClId) ; bool CalculateStraightAlong5AToolPath( int nAuxId, int nClId) ; - bool CalculateOffsetSection( int nSectGrpId, const Frame3d& frSec, ICurve*& pSect) const ; + bool CalculateOffsetSection( int nSectGrpId, const Frame3d& frSec, ICurve*& pSect, ICurve*& pOrigSec, ISurfFlatRegion*& pSfrLimit) const ; bool CalculateSection( int nSectGrpId, std::vector>& vpSections) const ; bool TrimSection( ICurve* pCrv) const ; bool Split5ASection( int nSectGrpId, SECTIONVECTOR& vSubSections) const ; + bool SplitLeftRightArcSection( ICurveComposite* pCompo, double dMaxAngDeg) const ; bool AdaptGuideLineToRaw( Point3d& ptGdStart, Point3d& ptGdEnd, const Vector3d& vtGdDir, bool bExtend, const ISurfTriMesh* pStmRaw) const ; - bool ExtendPathToRaw( PolyLine& PL, const ISurfTriMesh* pStmRaw, double dExtraOut) const ; + bool ExtendPathToRaw( ICurveComposite* pCompo, const ISurfTriMesh* pStmRaw, double dExtraOutconst, const ICurve* pSection = nullptr) const ; bool CalculateSectElevation( const Polygon3d& pgFacet, double& dElev) const ; bool CalculateGuideLine( int nGuideId, Point3d& ptGdStart, Point3d& ptGdEnd, Vector3d& vtGdDir, int nSectGrpId, bool bExtendToRawBox) const ; @@ -128,10 +131,10 @@ class SawFinishing : public Machining const Vector3d& vtTool, const Vector3d& vtCorr, double dElev, bool bExtend, bool bVert) ; bool CalcAlongZigZagCut( const Point3d& ptStart, const Point3d& ptEnd, const Vector3d& vtDir, const Vector3d& vtTool, const Vector3d& vtCorr, double dElev, bool bExtend, bool bVert, bool bFirst, bool bAppr = false) ; - bool CalcAcrossOneWayCut( const PolyLine& PL, const Vector3d& vtMove, - const Vector3d& vtTool, const Vector3d& vtCorr, double dRawZ, double dDepth) ; - bool CalcAcrossZigZagCut( const PolyLine& PL, const Vector3d& vtMove, - const Vector3d& vtTool, const Vector3d& vtCorr, double dRawZ, double dDepth, bool bFirst) ; + bool CalcAcrossOneWayCut( const ICurveComposite* pCompo, const Vector3d& vtMove, + const Vector3d& vtTool, const Vector3d& vtCorr, double dRawZ, double dDepth) ; + bool CalcAcrossZigZagCut( const ICurveComposite* pCompo, const Vector3d& vtMove, + const Vector3d& vtTool, const Vector3d& vtCorr, double dRawZ, double dDepth, bool bFirst) ; bool CalcCurvedAlongVerticalCuts( ICurve* pSect, int nUmin, int nUmax, const Frame3d& frSect, ICurve* pGuide, double dDepth, double dRaxMaxZ, const Vector3d& vtTool) ; bool CalcCurvedAlongStdCuts( ICurve* pSect, double dUmin, double dUmax,