diff --git a/Operation.h b/Operation.h index b9cb5d7..f17a9de 100644 --- a/Operation.h +++ b/Operation.h @@ -306,6 +306,8 @@ class Operation : public IUserObj { if ( ! m_bCurr) return false ; return AreSamePointEpsilon( ptP, m_ptCurr, 10 * EPS_SMALL) ; } bool GetCurrCorr( Vector3d& vtCCurr) const { if ( ! m_bCurr) return false ; vtCCurr = m_vtCorr ; return true ; } + bool GetCurrTool( Vector3d& vtCTool) const + { if ( ! m_bCurr) return false ; vtCTool = m_vtTool ; return true ; } bool GetCurrAux( Vector3d& vtACurr) const { if ( ! m_bCurr) return false ; vtACurr = m_vtAux ; return true ; } int AddRapidStart( const Point3d& ptP) ; diff --git a/SawFinishing.cpp b/SawFinishing.cpp index aa3c6ad..86b8f26 100644 --- a/SawFinishing.cpp +++ b/SawFinishing.cpp @@ -2168,12 +2168,6 @@ SawFinishing::CalculateStraightAlong5AToolPath( int nAuxId, int nClId) m_pMchMgr->SetWarning( 2655, "Warning in SawRoughing : Link not compatible with extension") ; m_Params.m_nLeadLinkType = SAWFIN_LL_CENT ; } - // se link di tipo Standard, questa viene convertita in Center, per la lavorazione corrente si effettuano le rotazioni della lama - // sempre al di fuori del grezzo - if ( m_Params.m_nLeadLinkType == SAWFIN_LL_STD) { - m_pMchMgr->SetWarning( 2655, "Warning in SawRoughing : Link not compatible with extension") ; - m_Params.m_nLeadLinkType = SAWFIN_LL_CENT ; - } // Recupero ed elaboro la linea guida Point3d ptGdStart, ptGdEnd ; @@ -2529,6 +2523,59 @@ SawFinishing::CalculateSection( int nSectGrpId, ICRVCOMPOPOVECTOR& vpSections) c vpNucCrvs.back()->Invert() ; } + // le curve ricavate vengo ordinate per X descrescente + // NB. prima le curve sono orientate per X decrescente, quindi ogni curva si muove verso sinistra; ora, se si hanno più sezioni, queste + // vengono lavorate oridinatamente da destra a sinistra + typedef pair INDASC ; // coppia indice, ascissa + typedef vector INDASCVECTOR ; // vettore di coppie indice, ascissa + INDASCVECTOR vIAsc ; vIAsc.reserve( vpNucCrvs.size()) ; + for ( int i = 0 ; i < ssize( vpNucCrvs) ; ++ i) { + Point3d ptStart ; + if ( ! vpNucCrvs[i]->GetStartPoint( ptStart)) + return false ; + vIAsc.emplace_back( i, ptStart.x) ; + } + sort( vIAsc.begin(), vIAsc.end(), []( const INDASC& a, const INDASC& b) { return a.second > b.second ; }) ; + ICURVEPOVECTOR vpSortedSections ; vpSortedSections.reserve( vpNucCrvs.size()) ; + for ( int i = 0 ; i < ssize( vIAsc) ; ++ i) { + int nOldPos = vIAsc[i].first ; + vpSortedSections.emplace_back( ::Release( vpNucCrvs[nOldPos])) ; + } + swap( vpSortedSections, vpNucCrvs) ; + + // calcolo il Box delle sezioni e controllo quali posso unire tra di loro + if ( ssize( vpNucCrvs) > 1) { + const double TOL_STICK_SECTION = m_TParams.m_dThick + 10. * EPS_SMALL ; + BOXVECTOR vBBoxSection( ssize( vpNucCrvs), BBox3d()) ; + for ( int i = 0 ; i < ssize( vpNucCrvs) ; ++ i) { + vpNucCrvs[i]->GetLocalBBox( vBBoxSection[i]) ; + vBBoxSection[i].Expand( TOL_STICK_SECTION / 2.) ; // espando per includere la tolleranza + } + // verifico quali sezioni posso unire tra di loro + ICRVCOMPOPOVECTOR vLinkedSection ; vLinkedSection.reserve( vpNucCrvs.size()) ; + vLinkedSection.resize( 1) ; + if ( ! vLinkedSection.back().Set( ConvertCurveToComposite( Release( vpNucCrvs[0])))) + return false ; + for ( int i = 1 ; i < ssize( vpNucCrvs) ; ++ i) { + // controllo se il Box corrente interseca il precedente + if ( vBBoxSection[i-1].OverlapsXY( vBBoxSection[i])) { + Point3d pt ; vpNucCrvs[i]->GetStartPoint( pt) ; + if ( IsNull( vLinkedSection.back())) + return false ; + vLinkedSection.back()->AddLine( pt) ; + vLinkedSection.back()->AddCurve( Release( vpNucCrvs[i])) ; + } + else { + vLinkedSection.resize( vLinkedSection.size() + 1) ; + if ( ! vLinkedSection.back().Set( ConvertCurveToComposite( Release( vpNucCrvs[i])))) + return false ; + } + } + vpNucCrvs.clear() ; vpNucCrvs.resize( vLinkedSection.size()) ; + for ( int i = 0 ; i < ssize( vLinkedSection) ; ++ i) + vpNucCrvs[i].Set( Release( vLinkedSection[i])) ; + } + // dalle sezioni recuperate eseguo l'Offset Radiale complessivo (evito così interferenze con sezioni differenti) ICURVEPVECTOR vpMySections ; vpMySections.resize( vpNucCrvs.size()) ; for ( int i = 0 ; i < ssize( vpNucCrvs) ; ++ i) @@ -2543,7 +2590,7 @@ SawFinishing::CalculateSection( int nSectGrpId, ICRVCOMPOPOVECTOR& vpSections) c if ( ! vpSections.back().Set( CreateCurveComposite()) || ! vpSections.back()->AddCurve( vMySections[i]->Clone())) return false ; - // eseguo anche Offset lungo X + // eseguo Offset lungo X OffsetCurveOnX OffsCrvX ; if ( ! OffsCrvX.Make( vpSections.back(), 0.5 * m_TParams.m_dThick)) return false ; @@ -2560,26 +2607,6 @@ SawFinishing::CalculateSection( int nSectGrpId, ICRVCOMPOPOVECTOR& vpSections) c } } - // le curve ricavate vengo ordinate per X descrescente - // NB. prima le curve sono orientate per X decrescente, quindi ogni curva si muove verso sinistra; ora, se si hanno più sezioni, queste - // vengono lavorate oridinatamente da destra a sinistra - typedef pair INDASC ; // coppia indice, ascissa - typedef vector INDASCVECTOR ; // vettore di coppie indice, ascissa - INDASCVECTOR vIAsc ; vIAsc.reserve( vpSections.size()) ; - for ( int i = 0 ; i < ssize( vpSections) ; ++ i) { - Point3d ptStart ; - if ( ! vpSections[i]->GetStartPoint( ptStart)) - return false ; - vIAsc.emplace_back( i, ptStart.x) ; - } - sort( vIAsc.begin(), vIAsc.end(), []( const INDASC& a, const INDASC& b) { return a.second > b.second ; }) ; - ICRVCOMPOPOVECTOR vpSortedSections ; vpSortedSections.reserve( vpSections.size()) ; - for ( int i = 0 ; i < ssize( vIAsc) ; ++ i) { - int nOldPos = vIAsc[i].first ; - vpSortedSections.emplace_back( ::Release( vpSections[nOldPos])) ; - } - swap( vpSortedSections, vpSections) ; - erase_if( vpSections, []( const ICurveComposite* pSection) { return ( pSection == nullptr || ! pSection->IsValid()) ; }) ; return ( ! vpSections.empty()) ; } @@ -2646,28 +2673,72 @@ SawFinishing::Split5ASection( int nSectGrpId, SECTIONVECTOR& vSections) const nSectId = m_pGeomDB->GetNext( nSectId) ; } - // elimino eventuali sottosquadra (splittando anche gli archi in sopra/sotto) + // elimino eventuali sottosquadra e oriento ogni curva secondo X descrescente ICRVCOMPOPOVECTOR vpNucCrvs ; vpNucCrvs.reserve( vpSects.size()) ; for ( const auto& pSect : vpSects) { PtrOwner pCrvCompo( CreateCurveComposite()) ; if ( IsNull( pCrvCompo) || ! pCrvCompo->AddCurve( *pSect) || - ! pCrvCompo->RemoveUndercutOnY( LIN_TOL_STD, ANG_TOL_STD_DEG)) + ! pCrvCompo->RemoveUndercutOnY( LIN_TOL_STD, ANG_TOL_STD_DEG) || + ! vpNucCrvs.emplace_back( Release( pCrvCompo))) return false ; - vpNucCrvs.emplace_back( Release( pCrvCompo)) ; + Point3d ptS ; vpNucCrvs.back()->GetStartPoint( ptS) ; + Point3d ptE ; vpNucCrvs.back()->GetEndPoint( ptE) ; + if ( ptS.x < ptE.x) + vpNucCrvs.back()->Invert() ; } - // oriento le sezioni + // le curve ricavate vengo ordinate per X descrescente + // NB. prima le curve sono orientate per X decrescente, quindi ogni curva si muove verso sinistra; ora, se si hanno più sezioni, queste + // vengono lavorate oridinatamente da destra a sinistra + typedef pair INDASC ; // coppia indice, ascissa + typedef vector INDASCVECTOR ; // vettore di coppie indice, ascissa + INDASCVECTOR vIAsc ; vIAsc.reserve( vpNucCrvs.size()) ; for ( int i = 0 ; i < ssize( vpNucCrvs) ; ++ i) { - // se tratto non valido, errore - if ( IsNull( vpNucCrvs[i]) || ! vpNucCrvs[i]->IsValid()) + Point3d ptStart ; + if ( ! vpNucCrvs[i]->GetStartPoint( ptStart)) return false ; + vIAsc.emplace_back( i, ptStart.x) ; + } + sort( vIAsc.begin(), vIAsc.end(), []( const INDASC& a, const INDASC& b) { return a.second > b.second ; }) ; + ICRVCOMPOPOVECTOR vpSortedSections ; vpSortedSections.reserve( vpNucCrvs.size()) ; + for ( int i = 0 ; i < ssize( vIAsc) ; ++ i) { + int nOldPos = vIAsc[i].first ; + vpSortedSections.emplace_back( ::Release( vpNucCrvs[nOldPos])) ; + } + swap( vpSortedSections, vpNucCrvs) ; - // oriento la curva corrente per X decrescenti - Point3d ptStart ; vpNucCrvs[i]->GetStartPoint( ptStart) ; - Point3d ptEnd ; vpNucCrvs[i]->GetEndPoint( ptEnd) ; - if ( ptEnd.x > ptStart.x) - vpNucCrvs[i]->Invert() ; + // calcolo il Box delle sezioni e controllo quali posso unire tra di loro + if ( ssize( vpNucCrvs) > 1) { + const double TOL_STICK_SECTION = m_TParams.m_dThick + 10. * EPS_SMALL ; + BOXVECTOR vBBoxSection( ssize( vpNucCrvs), BBox3d()) ; + for ( int i = 0 ; i < ssize( vpNucCrvs) ; ++ i) { + vpNucCrvs[i]->GetLocalBBox( vBBoxSection[i]) ; + vBBoxSection[i].Expand( TOL_STICK_SECTION / 2.) ; // espando per includere la tolleranza + } + // verifico quali sezioni posso unire tra di loro + ICRVCOMPOPOVECTOR vLinkedSection ; vLinkedSection.reserve( vpNucCrvs.size()) ; + vLinkedSection.resize( 1) ; + if ( ! vLinkedSection.back().Set( ConvertCurveToComposite( Release( vpNucCrvs[0])))) + return false ; + for ( int i = 1 ; i < ssize( vpNucCrvs) ; ++ i) { + // controllo se il Box corrente interseca il precedente + if ( vBBoxSection[i-1].OverlapsXY( vBBoxSection[i])) { + Point3d pt ; vpNucCrvs[i]->GetStartPoint( pt) ; + if ( IsNull( vLinkedSection.back())) + return false ; + vLinkedSection.back()->AddLine( pt) ; + vLinkedSection.back()->AddCurve( Release( vpNucCrvs[i])) ; + } + else { + vLinkedSection.resize( vLinkedSection.size() + 1) ; + if ( ! vLinkedSection.back().Set( ConvertCurveToComposite( Release( vpNucCrvs[i])))) + return false ; + } + } + vpNucCrvs.clear() ; vpNucCrvs.resize( vLinkedSection.size()) ; + for ( int i = 0 ; i < ssize( vLinkedSection) ; ++ i) + vpNucCrvs[i].Set( Release( vLinkedSection[i])) ; } // dalle sezioni semplici recuperate eseguo l'Offset Radiale complessivo ( evito così interferenze con sezioni differenti) @@ -2685,26 +2756,6 @@ SawFinishing::Split5ASection( int nSectGrpId, SECTIONVECTOR& vSections) const } } - // 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( vSections.size()) ; - for ( int i = 0 ; i < ssize( vSections) ; ++ i) { - Point3d ptStart ; - if ( ! vSections[i].pSection->GetStartPoint( ptStart)) - return false ; - vIAsc.emplace_back( i, ptStart.x) ; - } - sort( vIAsc.begin(), vIAsc.end(), []( const INDASC& a, const INDASC& b) { return a.second > b.second ; }) ; - for ( int nNewPos = 0 ; nNewPos < ssize( vIAsc) ; ++ nNewPos) { - int nOldPos = vIAsc[nNewPos].first ; - if ( nOldPos == nNewPos) - continue ; - swap( vSections[nNewPos], vSections[nOldPos]) ; - swap( vIAsc[nNewPos].first, vIAsc[nOldPos].first) ; - } - // !<-- NB: // - Una Section semplice non presente tratti verticali e non presenta tratti in sottosquadra // - Una Section semplice è orientata per X decrescente @@ -3540,6 +3591,7 @@ SawFinishing::CalcAlong5ACuts( const SECTIONVECTOR& vSections, const Frame3d& fr } // scorro le sezioni + double dLastElev = 0. ; for ( int nSect = 0 ; nSect < ssize( vSections) ; ++ nSect) { // recupero la sezione @@ -3549,6 +3601,10 @@ SawFinishing::CalcAlong5ACuts( const SECTIONVECTOR& vSections, const Frame3d& fr // scorro le SubSection ottenute bool bLastToolInv = false ; + bool bFirst = true ; + Point3d ptStartPrev ; + Vector3d vtCorrPrev = V_NULL, + vtToolPrev = V_NULL ; for ( int nSubSect = 0 ; nSubSect < ssize( Section.vSubSections) ; ++ nSubSect) { // recupero la SubSection corrente, se non valida, passo alla successiva @@ -3556,10 +3612,6 @@ SawFinishing::CalcAlong5ACuts( const SECTIONVECTOR& vSections, const Frame3d& fr PtrOwner pSubSect( CloneCurveComposite( SubSection.pSubSection)) ; if ( pSubSect == nullptr || ! pSubSect->IsValid()) continue ; - // essendo l'utensile inclinato e la testa con orientamento forzato è meglio estendere la sezione per evitare lavorazioni - // a filo dei suoi bordi - pSubSect->ExtendStartByLen( 50. * EPS_SMALL) ; - pSubSect->ExtendEndByLen( 50. * EPS_SMALL) ; // calcolo della lunghezza dello step e del numero di step complessivi double dStep = max( m_Params.m_dSideStep, 10. * EPS_SMALL) ; @@ -3572,10 +3624,6 @@ SawFinishing::CalcAlong5ACuts( const SECTIONVECTOR& vSections, const Frame3d& fr dStep = dLen / nStep ; // Ciclo sulle passate - double dLastElev ; - Point3d ptStartPrev ; - Vector3d vtCorrPrev = V_NULL, - vtToolPrev = V_NULL ; for ( int i = 0 ; i <= nStep ; ++ i) { // coordinate nel punto, del versore correzione e del versore utensile double dLcurr = i * dStep ; @@ -3586,31 +3634,24 @@ SawFinishing::CalcAlong5ACuts( const SECTIONVECTOR& vSections, const Frame3d& fr return false ; Vector3d vtCorr = GetToGlob( vtTan, frSect) ; vtCorr.Rotate( vtGdDir, m_Params.m_bInvert ? - ANG_RIGHT : ANG_RIGHT) ; - // se tangente circa orizzontale - if ( abs( vtTan.y) < 2. * EPS_SMALL) { - if ( ( SubSection.nHeadSide == SAWFIN_HS_LEFT && vtTan.y < 0.) || - ( SubSection.nHeadSide == SAWFIN_HS_RIGHT && vtTan.y > 0.)) - vtTan.y = - vtTan.y ; + // se tangente circa orizzontale, correggo la direzione per evitare inversioni di vtTool + if ( abs( vtTan.y) < 5 * EPS_SMALL) { + if ( ( SubSection.nHeadSide == SAWFIN_HS_LEFT)) { + vtTan.y = abs( vtTan.y) ; // y > 0. + vtTan.x = - abs( vtTan.x) ; // x < 0. + } + else if ( SubSection.nHeadSide == SAWFIN_HS_RIGHT) { + vtTan.y = - abs( vtTan.y) ; // y < 0. + vtTan.x = abs( vtTan.x) ; // x > 0. + } } Vector3d vtTool = GetToGlob( vtTan, frSect) ; // determino l'orientamento della testa - bool bCurrToolInv = false ; - if ( vtTool.z < - EPS_ZERO) { - vtTool.Invert() ; // NB. vtTool deve sempre avere la componente Z come positiva (quindi vtCorr.y >= 0) - bCurrToolInv = true ; - } - - // verifico se inversione della testa - bool bFirst = ( i == 0) ; - bool bSpecialAppr = ( m_Params.m_nLeadLinkType != SAWFIN_LL_CENT && ! bFirst && ( bCurrToolInv != bLastToolInv)) ; - if ( bSpecialAppr) { - SetFeed( GetEndFeed()) ; - Point3d ptCurr ; GetCurrPos( ptCurr) ; - if ( ! AddRetract( ptCurr, vtCorrPrev, GetSafeZ(), dLastElev, m_Params.m_dStartPos)) - return false ; - } - bLastToolInv = bCurrToolInv ; + // NB. vtTool deve sempre avere la componente Z come positiva (quindi vtCorr.y >= 0) + bool bCurrToolInv = ( SubSection.nHeadSide == SAWFIN_HS_RIGHT) ; + if ( vtTool.z < - 5. * EPS_SMALL) + vtTool.Invert() ; // punto di passata è sulla metà della sezione lama ptP += - 0.5 * m_TParams.m_dThick * GetToLoc( vtTool, frSect) ; @@ -3627,6 +3668,9 @@ SawFinishing::CalcAlong5ACuts( const SECTIONVECTOR& vSections, const Frame3d& fr if ( bOtherColl || bAwayFromPoint) continue ; + // verifico se inversione della testa + bool bSpecialAppr = ( m_Params.m_nLeadLinkType != SAWFIN_LL_CENT && ! bFirst && ( bCurrToolInv != bLastToolInv)) ; + // definisco gli estremi del tratto rettilineo in globale Point3d ptPCAvSect = GetToGlob( ptP, frSect) + vtCorr * dSectElev ; if ( m_Params.m_bInvert) @@ -3696,11 +3740,11 @@ SawFinishing::CalcAlong5ACuts( const SECTIONVECTOR& vSections, const Frame3d& fr if ( bFirst || ! AreSamePointEpsilon( ptStart, ptStartPrev, 10. * EPS_SMALL)) { if ( m_Params.m_nStepType != SAWFIN_ST_ZIGZAG) { if ( ! CalcAlong5AOneWayCut( ptStart, ptEnd, vtGdDir, vtTool, vtToolPrev, vtCorr, vtCorrPrev, dElev, bExtend, false, - bFirst)) + bFirst, bSpecialAppr)) return false ; } else { - if ( ! CalcAlong5AZigZagCut( ptStart, ptEnd, vtGdDir, vtTool, vtToolPrev, vtCorr, vtCorrPrev, dElev, bExtend, false, + if ( ! CalcAlong5AZigZagCut( ptStart, ptEnd, vtGdDir, vtTool, vtToolPrev, vtCorr, vtCorrPrev, dElev, dLastElev, bExtend, false, bFirst, bSpecialAppr)) return false ; } @@ -3708,20 +3752,24 @@ SawFinishing::CalcAlong5ACuts( const SECTIONVECTOR& vSections, const Frame3d& fr dLastElev = dElev ; ptStartPrev = ptStart ; } + bFirst = false ; vtCorrPrev = vtCorr ; vtToolPrev = vtTool ; + bLastToolInv = bCurrToolInv ; } - // se ZigZag e non centrato aggiungo risalita - if ( m_Params.m_nStepType == SAWFIN_ST_ZIGZAG && m_Params.m_nLeadLinkType != SAWFIN_LL_CENT) { - // recupero distanza di sicurezza - double dSafeZ = GetSafeZ() ; - // lunghezza di approccio/retrazione - double dAppr = m_Params.m_dStartPos ; - // aggiungo retrazione - Point3d ptNewEnd ; - if ( ! GetCurrPos( ptNewEnd) || ! AddRetract( ptNewEnd, Z_AX, dSafeZ, dLastElev, dAppr)) - return false ; - } + } + // se ZigZag e non centrato aggiungo risalita + if ( m_Params.m_nStepType == SAWFIN_ST_ZIGZAG && m_Params.m_nLeadLinkType != SAWFIN_LL_CENT) { + // recupero distanza di sicurezza + double dSafeZ = GetSafeZ() ; + // lunghezza di approccio/retrazione + double dAppr = m_Params.m_dStartPos ; + // recupero direzione utensile corrente + Vector3d vtCorr ; GetCurrCorr( vtCorr) ; + // aggiungo retrazione + Point3d ptNewEnd ; + if ( ! GetCurrPos( ptNewEnd) || ! AddRetract( ptNewEnd, vtCorr, dSafeZ, dLastElev, dAppr)) + return false ; } } @@ -3732,7 +3780,7 @@ SawFinishing::CalcAlong5ACuts( const SECTIONVECTOR& vSections, const Frame3d& fr bool SawFinishing::CalcAlong5AOneWayCut( const Point3d& ptStart, const Point3d& ptEnd, const Vector3d& vtDir, const Vector3d& vtTool, const Vector3d& vtToolPrev, const Vector3d& vtCorr, const Vector3d& vtCorrPrev, - double dElev, bool bExtend, bool bVert, bool bFirst) + double dElev, bool bExtend, bool bVert, bool bFirst, bool bAppr) { // recupero distanza di sicurezza double dSafeZ = GetSafeZ() ; @@ -3742,9 +3790,8 @@ SawFinishing::CalcAlong5AOneWayCut( const Point3d& ptStart, const Point3d& ptEnd // se attacco/uscita/collegamento esterno allungo inizio Point3d ptNewStart = ptStart ; - if ( m_Params.m_nLeadLinkType == SAWFIN_LL_STD) { + if ( m_Params.m_nLeadLinkType == SAWFIN_LL_STD) ptNewStart = ptStart - vtDir * dAlongAppr ; - } else if ( m_Params.m_nLeadLinkType == SAWFIN_LL_OUT) { // distanza XY tra centro e bordo taglio double dDeltaT = 0 ; @@ -3755,34 +3802,46 @@ SawFinishing::CalcAlong5AOneWayCut( const Point3d& ptStart, const Point3d& ptEnd } // 1 -> approccio - // verifico se la deviazione angolare tra la passata corrente ela precedente superla la tolleranza + // effettuo una retroazione se : + // - ho un approccio forzato dovuto all'inversione dell'utensile + // - la deviazione angolare tra la passata corrente e la precedente supera la tolleranza const double ANG_DEG_MAX = 10. ; - if ( ! bFirst && vtToolPrev.IsValid() && vtTool.IsValid() && vtTool * vtToolPrev < cos( ANG_DEG_MAX * DEGTORAD)) { - // Tengo l'utensile orientato come la passata precedente - SetToolDir( vtToolPrev) ; - SetCorrDir( vtCorrPrev) ; - // Recupero il punto corrente e il nuovo punto di destinazione al du fuori del grezzo - Point3d ptCurr ; GetCurrPos( ptCurr) ; - // Se link di tipo out, aggiungo la retroazione al percorso precedente - if ( m_Params.m_nLeadLinkType == SAWFIN_LL_OUT) { - if ( ! AddRetract( ptCurr, vtCorr, dSafeZ, dElev, dAppr)) - return false ; + if ( ! bFirst && vtToolPrev.IsValid() && vtTool.IsValid()) { + // se approccio forzato per inversione utensile + if ( bAppr || vtTool * vtToolPrev < cos( ANG_DEG_MAX * DEGTORAD)) { + // Recupero il punto corrente + Point3d ptCurr ; GetCurrPos( ptCurr) ; + // Recupero il punto di approccio per il nuovo collegamento + double dMyAppr = max( dAppr, 1.0) ; + Point3d ptAppr ; + if ( dSafeZ < dMyAppr + 10 * EPS_SMALL) + ptAppr = ptNewStart + vtCorr * dElev ; + else + ptAppr = ptNewStart + vtCorr * ( dElev + dSafeZ) ; + // aggiungo il movimento in rapido per il collegamento speciale al di fuori del grezzo + double dDeltaZ = ptAppr.z - ptCurr.z ; + // se discesa + if ( dDeltaZ < 0.) { + Point3d ptA = ptAppr + Z_AX * ( - dDeltaZ) ; + if ( ! SameAsCurrPos( ptA)) { + if ( AddRapidMove( ptA) == GDB_ID_NULL) + return false ; + } + } + // se salita + else { + Point3d ptA = ptCurr + Z_AX * dDeltaZ ; + if ( ! SameAsCurrPos( ptA)) { + if ( AddRapidMove( ptA) == GDB_ID_NULL) + return false ; + } + } + // Approccio al nuovo punto + if ( ! SameAsCurrPos( ptAppr)) { + if ( AddRapidMove( ptAppr) == GDB_ID_NULL) + return false ; + } } - // Recupero la Z del punto di destinazione - double dMyAppr = max( dAppr, 1.0) ; - Point3d ptAppr ; - if ( dSafeZ < dMyAppr + 10 * EPS_SMALL) - ptAppr = ptNewStart + vtCorr * dElev ; - else - ptAppr = ptNewStart + vtCorr * ( dElev + dSafeZ) ; - // aggiungo il movimento in rapido per il collegamento speciale al di fuori del grezzo - double dDeltaZ = ptAppr.z - ptCurr.z ; // se scendo < 0, se salgo > 0 - if ( dDeltaZ < 0) - AddRapidMove( ptAppr + Z_AX * ( - dDeltaZ)) ; - else - AddRapidMove( ptCurr + Z_AX * dDeltaZ) ; - SetToolDir( vtTool) ; - SetCorrDir( vtCorr) ; } if ( ! AddApproach( ptNewStart, vtCorr, dSafeZ, dElev, dAppr)) return false ; @@ -3811,7 +3870,7 @@ SawFinishing::CalcAlong5AOneWayCut( const Point3d& ptStart, const Point3d& ptEnd bool SawFinishing::CalcAlong5AZigZagCut( const Point3d& ptStart, const Point3d& ptEnd, const Vector3d& vtDir, const Vector3d& vtTool, const Vector3d& vtToolPrev, const Vector3d& vtCorr, const Vector3d& vtCorrPrev, double dElev, - bool bExtend, bool bVert, bool bFirst, bool bAppr) + double dLastElev, bool bExtend, bool bVert, bool bFirst, bool bAppr) { // recupero distanza di sicurezza double dSafeZ = GetSafeZ() ; @@ -3825,14 +3884,14 @@ SawFinishing::CalcAlong5AZigZagCut( const Point3d& ptStart, const Point3d& ptEnd Point3d ptNewStart = ptStart ; Point3d ptNewEnd = ptEnd ; Vector3d vtNewDir = vtDir ; - // se attacco/uscita/collegamento standard allungo inizio e fine dell'approccio + // se attacco/uscita/collegamento standard allungo inizio e fine dell'approccio if ( m_Params.m_nLeadLinkType == SAWFIN_LL_STD) { // modifico inizio ptNewStart = ptStart - vtDir * dAlongAppr ; // modifico fine ptNewEnd = ptEnd + vtDir * dAlongAppr ; } - // se attacco/uscita/collegamento esterno allungo inizio e fine a fuori grezzo + // se attacco/uscita/collegamento esterno allungo inizio e fine a fuori grezzo else if ( m_Params.m_nLeadLinkType == SAWFIN_LL_OUT) { // distanza XY tra centro e bordo taglio double dDeltaT = 0 ; @@ -3851,39 +3910,111 @@ SawFinishing::CalcAlong5AZigZagCut( const Point3d& ptStart, const Point3d& ptEnd } // 1 -> approccio - // Verifico se la deviazione angolare tra la passata corrente e la precedente supera la tolleranza + // effettuo una retroazione se : + // - ho un approccio forzato dovuto all'inversione dell'utensile + // - la deviazione angolare tra la passata corrente e la precedente supera la tolleranza const double ANG_DEG_MAX = 10. ; - bool bOutRaw = false ; - if ( ! bFirst && vtToolPrev.IsValid() && vtTool.IsValid() && vtTool * vtToolPrev < cos( ANG_DEG_MAX * DEGTORAD)) { - // Tengo l'utensile orientato come la passata precedente - SetToolDir( vtToolPrev) ; - SetCorrDir( vtCorrPrev) ; - // Recupero il punto corrente e il nuovo punto di destinazione al du fuori del grezzo - Point3d ptCurr ; GetCurrPos( ptCurr) ; - // Se link di tipo out, aggiungo la retroazione al percorso precedente - if ( m_Params.m_nLeadLinkType == SAWFIN_LL_OUT) { - if ( ! AddRetract( ptCurr, vtCorr, dSafeZ, dElev, dAppr)) - return false ; + bool bPrevRetract = false ; + if ( ! bFirst && vtToolPrev.IsValid() && vtTool.IsValid()) { + // se approccio forzato per inversione utensile + if ( bAppr) { + // recupero il punto corrente + Point3d ptCurr ; GetCurrPos( ptCurr) ; + // tengo l'utensile orientato come la passata precedente + SetToolDir( vtToolPrev) ; + SetCorrDir( vtCorrPrev) ; + // Aggiungo la retroazione (se link centrati è già aggiunta) + if ( m_Params.m_nLeadLinkType != SAWFIN_LL_CENT) { + if ( ! AddRetract( ptCurr, vtCorrPrev, dSafeZ, dLastElev, dAppr)) + return false ; + GetCurrPos( ptCurr) ; + } + // Recupero il punto di approccio per il nuovo collegamento + double dMyAppr = max( dAppr, 1.0) ; + Point3d ptAppr ; + if ( dSafeZ < dMyAppr + 10 * EPS_SMALL) + ptAppr = ptNewStart + vtCorr * dElev ; + else + ptAppr = ptNewStart + vtCorr * ( dElev + dSafeZ) ; + // imposto i dati utensili nuovi + SetToolDir( vtTool) ; + SetCorrDir( vtCorr) ; + // aggiungo il movimento in rapido per il collegamento speciale al di fuori del grezzo + double dDeltaZ = ptAppr.z - ptCurr.z ; + // se discesa + if ( dDeltaZ < 0.) { + Point3d ptA = ptAppr + Z_AX * ( - dDeltaZ) ; + if ( ! SameAsCurrPos( ptA)) { + if ( AddRapidMove( ptA) == GDB_ID_NULL) + return false ; + } + } + // se salita + else { + Point3d ptA = ptCurr + Z_AX * dDeltaZ ; + if ( ! SameAsCurrPos( ptA)) { + if ( AddRapidMove( ptA) == GDB_ID_NULL) + return false ; + } + } + // Approccio al nuovo punto + if ( ! SameAsCurrPos( ptAppr)) { + if ( AddRapidMove( ptAppr) == GDB_ID_NULL) + return false ; + } + bPrevRetract = true ; + } + // se la deviazione angolare supera la tolleranza + else if ( vtTool * vtToolPrev < cos( ANG_DEG_MAX * DEGTORAD)) { + // Recupero il punto corrente + Point3d ptCurr ; GetCurrPos( ptCurr) ; + // Tengo l'utensile orientato come la passata precedente + SetToolDir( vtToolPrev) ; + SetCorrDir( vtCorrPrev) ; + // Aggiungo la retroazione (se link centrati è già aggiunta) + if ( m_Params.m_nLeadLinkType != SAWFIN_LL_CENT) { + if ( ! AddRetract( ptCurr, vtCorrPrev, dSafeZ, dLastElev, dAppr)) + return false ; + GetCurrPos( ptCurr) ; + } + // Recupero il punto di approccio per il nuovo collegamento + double dMyAppr = max( dAppr, 1.0) ; + Point3d ptAppr ; + if ( dSafeZ < dMyAppr + 10 * EPS_SMALL) + ptAppr = ptNewStart + vtCorr * dElev ; + else + ptAppr = ptNewStart + vtCorr * ( dElev + dSafeZ) ; + // aggiungo il movimento in rapido per il collegamento speciale al di fuori del grezzo + double dDeltaZ = ptAppr.z - ptCurr.z ; + // se discesa + if ( dDeltaZ < 0.) { + Point3d ptA = ptAppr + Z_AX * ( - dDeltaZ) ; + if ( ! SameAsCurrPos( ptA)) { + if ( AddRapidMove( ptA) == GDB_ID_NULL) + return false ; + } + } + // se salita + else { + Point3d ptA = ptCurr + Z_AX * dDeltaZ ; + if ( ! SameAsCurrPos( ptA)) { + if ( AddRapidMove( ptA) == GDB_ID_NULL) + return false ; + } + } + // imposto i dati utensili nuovi + SetToolDir( vtTool) ; + SetCorrDir( vtCorr) ; + // Approccio al nuovo punto + if ( ! SameAsCurrPos( ptAppr)) { + if ( AddRapidMove( ptAppr) == GDB_ID_NULL) + return false ; + } + bPrevRetract = true ; } - // Recupero la Z del punto di destinazione - double dMyAppr = max( dAppr, 1.0) ; - Point3d ptAppr ; - if ( dSafeZ < dMyAppr + 10 * EPS_SMALL) - ptAppr = ptNewStart + vtCorr * dElev ; - else - ptAppr = ptNewStart + vtCorr * ( dElev + dSafeZ) ; - // aggiungo il movimento in rapido per il collegamento speciale al di fuori del grezzo - double dDeltaZ = ptAppr.z - ptCurr.z ; // se scendo < 0, se salgo > 0 - if ( dDeltaZ < 0) - AddRapidMove( ptAppr + Z_AX * ( - dDeltaZ)) ; - else - AddRapidMove( ptCurr + Z_AX * dDeltaZ) ; - bOutRaw = true ; - SetToolDir( vtTool) ; - SetCorrDir( vtCorr) ; } - if ( bFirst || m_Params.m_nLeadLinkType == SAWFIN_LL_CENT || bAppr || bOutRaw) { + if ( bFirst || m_Params.m_nLeadLinkType == SAWFIN_LL_CENT || bPrevRetract) { if ( ! AddApproach( ptNewStart, vtCorr, dSafeZ, dElev, dAppr)) return false ; } diff --git a/SawFinishing.h b/SawFinishing.h index ca93964..d11ec58 100644 --- a/SawFinishing.h +++ b/SawFinishing.h @@ -130,10 +130,10 @@ class SawFinishing : public Machining const BBox3d& b3Raw, const ISurfTriMesh* pStmRaw) ; bool CalcAlong5AOneWayCut( const Point3d& ptStart, const Point3d& ptEnd, const Vector3d& vtDir, const Vector3d& vtTool, const Vector3d& vtToolPrev, const Vector3d& vtCorr, const Vector3d& vtCorrPrev, double dElev, - bool bExtend, bool bVert, bool bFirst) ; + bool bExtend, bool bVert, bool bFirst, bool bAppr) ; bool CalcAlong5AZigZagCut( const Point3d& ptStart, const Point3d& ptEnd, const Vector3d& vtDir, const Vector3d& vtTool, const Vector3d& vtToolPrev, const Vector3d& vtCorr, const Vector3d& vtCorrPrev, double dElev, - bool bExtend, bool bVert, bool bFirst, bool bAppr) ; + double dLastElev, bool bExtend, bool bVert, bool bFirst, bool bAppr) ; bool CalcAlongOneWayCut( const Point3d& ptStart, const Point3d& ptEnd, const Vector3d& vtDir, 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, diff --git a/SawRoughing.cpp b/SawRoughing.cpp index d384a16..cbe904d 100644 --- a/SawRoughing.cpp +++ b/SawRoughing.cpp @@ -1532,6 +1532,8 @@ SawRoughing::CalculateCurvedToolPath( int nAuxId, int nClId) bool SawRoughing::CalculateSection( int nSectGrpId, ICRVCOMPOPOVECTOR& vpSections) const { + vpSections.clear() ; + // recupero le sezioni ICURVEPVECTOR vpSects ; int nSectId = m_pGeomDB->GetFirstInGroup( nSectGrpId) ; @@ -1560,6 +1562,59 @@ SawRoughing::CalculateSection( int nSectGrpId, ICRVCOMPOPOVECTOR& vpSections) co vpNucCrvs.back()->Invert() ; } + // le curve ricavate vengo ordinate per X descrescente + // NB. prima le curve sono orientate per X decrescente, quindi ogni curva si muove verso sinistra; ora, se si hanno più sezioni, queste + // vengono lavorate oridinatamente da destra a sinistra + typedef pair INDASC ; // coppia indice, ascissa + typedef vector INDASCVECTOR ; // vettore di coppie indice, ascissa + INDASCVECTOR vIAsc ; vIAsc.reserve( vpNucCrvs.size()) ; + for ( int i = 0 ; i < ssize( vpNucCrvs) ; ++ i) { + Point3d ptStart ; + if ( ! vpNucCrvs[i]->GetStartPoint( ptStart)) + return false ; + vIAsc.emplace_back( i, ptStart.x) ; + } + sort( vIAsc.begin(), vIAsc.end(), []( const INDASC& a, const INDASC& b) { return a.second > b.second ; }) ; + ICURVEPOVECTOR vpSortedSections ; vpSortedSections.reserve( vpNucCrvs.size()) ; + for ( int i = 0 ; i < ssize( vIAsc) ; ++ i) { + int nOldPos = vIAsc[i].first ; + vpSortedSections.emplace_back( ::Release( vpNucCrvs[nOldPos])) ; + } + swap( vpSortedSections, vpNucCrvs) ; + + // calcolo il Box delle sezioni e controllo quali posso unire tra di loro + if ( ssize( vpNucCrvs) > 1) { + const double TOL_STICK_SECTION = m_TParams.m_dThick + 10. * EPS_SMALL ; + BOXVECTOR vBBoxSection( ssize( vpNucCrvs), BBox3d()) ; + for ( int i = 0 ; i < ssize( vpNucCrvs) ; ++ i) { + vpNucCrvs[i]->GetLocalBBox( vBBoxSection[i]) ; + vBBoxSection[i].Expand( TOL_STICK_SECTION / 2.) ; // espando per includere la tolleranza + } + // verifico quali sezioni posso unire tra di loro + ICRVCOMPOPOVECTOR vLinkedSection ; vLinkedSection.reserve( vpNucCrvs.size()) ; + vLinkedSection.resize( 1) ; + if ( ! vLinkedSection.back().Set( ConvertCurveToComposite( ::Release( vpNucCrvs[0])))) + return false ; + for ( int i = 1 ; i < ssize( vpNucCrvs) ; ++ i) { + // controllo se il Box corrente interseca il precedente + if ( vBBoxSection[i-1].OverlapsXY( vBBoxSection[i])) { + Point3d pt ; vpNucCrvs[i]->GetStartPoint( pt) ; + if ( IsNull( vLinkedSection.back())) + return false ; + vLinkedSection.back()->AddLine( pt) ; + vLinkedSection.back()->AddCurve( ::Release( vpNucCrvs[i])) ; + } + else { + vLinkedSection.resize( vLinkedSection.size() + 1) ; + if ( ! vLinkedSection.back().Set( ConvertCurveToComposite( ::Release( vpNucCrvs[i])))) + return false ; + } + } + vpNucCrvs.clear() ; vpNucCrvs.resize( vLinkedSection.size()) ; + for ( int i = 0 ; i < ssize( vLinkedSection) ; ++ i) + vpNucCrvs[i].Set( ::Release( vLinkedSection[i])) ; + } + // dalle sezioni recuperate eseguo l'Offset Radiale complessivo (evito così interferenze con sezioni differenti) ICURVEPVECTOR vpMySections ; vpMySections.resize( vpNucCrvs.size()) ; for ( int i = 0 ; i < ssize( vpNucCrvs) ; ++ i) @@ -1574,7 +1629,7 @@ SawRoughing::CalculateSection( int nSectGrpId, ICRVCOMPOPOVECTOR& vpSections) co if ( ! vpSections.back().Set( CreateCurveComposite()) || ! vpSections.back()->AddCurve( vMySections[i]->Clone())) return false ; - // eseguo anche Offset lungo X + // eseguo Offset lungo X OffsetCurveOnX OffsCrvX ; if ( ! OffsCrvX.Make( vpSections.back(), 0.5 * m_TParams.m_dThick + GetOffsL() - GetOffsR())) return false ; @@ -1591,26 +1646,6 @@ SawRoughing::CalculateSection( int nSectGrpId, ICRVCOMPOPOVECTOR& vpSections) co } } - // le curve ricavate vengo ordinate per X descrescente - // NB. prima le curve sono orientate per X decrescente, quindi ogni curva si muove verso sinistra; ora, se si hanno più sezioni, queste - // vengono lavorate oridinatamente da destra a sinistra - typedef pair INDASC ; // coppia indice, ascissa - typedef vector INDASCVECTOR ; // vettore di coppie indice, ascissa - INDASCVECTOR vIAsc ; vIAsc.reserve( vpSections.size()) ; - for ( int i = 0 ; i < ssize( vpSections) ; ++ i) { - Point3d ptStart ; - if ( ! vpSections[i]->GetStartPoint( ptStart)) - return false ; - vIAsc.emplace_back( i, ptStart.x) ; - } - sort( vIAsc.begin(), vIAsc.end(), []( const INDASC& a, const INDASC& b) { return a.second > b.second ; }) ; - ICRVCOMPOPOVECTOR vpSortedSections ; vpSortedSections.reserve( vpSections.size()) ; - for ( int i = 0 ; i < ssize( vIAsc) ; ++ i) { - int nOldPos = vIAsc[i].first ; - vpSortedSections.emplace_back( ::Release( vpSections[nOldPos])) ; - } - swap( vpSortedSections, vpSections) ; - erase_if( vpSections, []( const ICurveComposite* pSection) { return ( pSection == nullptr || ! pSection->IsValid()) ; }) ; return ( ! vpSections.empty()) ; }