From ac45a259b69bc4439d4b55c99dac9b9c6f2a50ac Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Mon, 4 May 2026 17:13:00 +0200 Subject: [PATCH] EgtMachKernel 3.1e1 : - In PocketingNT aggiunta gestione lavorazioni in Doppio in Parallelo. --- Drilling.cpp | 2 - EgtMachKernel.rc | Bin 11774 -> 11774 bytes PocketingNT.cpp | 437 +++++++++++++++++++++++++++++++++++++++++------ PocketingNT.h | 9 +- 4 files changed, 390 insertions(+), 58 deletions(-) diff --git a/Drilling.cpp b/Drilling.cpp index 9b8b05c..2bee841 100644 --- a/Drilling.cpp +++ b/Drilling.cpp @@ -3348,8 +3348,6 @@ Drilling::VerifyParallelDrilling( int nDouble, const Hole& hole) Machine* pMch = m_pMchMgr->GetCurrMachine() ; if ( pMch == nullptr) return false ; - - // verifico se la macchina presenta nel file .ini l'abilitazione per le forature in doppio in parallelo string sMachIni = pMch->GetMachineDir() + "\\" + pMch->GetMachineName() + ".ini" ; int nDrillingDouble = GetPrivateProfileInt( MACHININGS_SEC.c_str(), DRILLING_PARALLEL_KEY.c_str(), 0, sMachIni.c_str()) ; if ( nDrillingDouble != 1) diff --git a/EgtMachKernel.rc b/EgtMachKernel.rc index 39dadd4ac7fb824a6765f29404f06a8b04d2dc8f..9436fcaba6bc23cb05176c85f35ba5f6a0c78c0b 100644 GIT binary patch delta 129 zcmewt{V#gMCpK171|0^&&F|$dGEF|gnZ=koxlu-Pasap3<~S)2#?7m^U6|oY?3t0J Tl|a(MNYYqL=wZR7c>y;7%?~Iz delta 105 zcmewt{V#gMCpK0S1|0_T&F|$dGEF|gnZ=v}( ceil( dElev / dOkStep))) ; - double dStep = dElev / nStep ; + // verifico se svuotatura in doppio con parte di essa da eseguire in parallelo + // determino dunque numero e affondamento degli step + int nStep = 0 ; + double dStep = - EPS_SMALL, dLastStep = - EPS_SMALL ; + DBLVECTOR vdSteps ; + int nDouble = GetDoubleType( m_Params.m_sUserNotes) ; + bool bDouble = ( nDouble != 0) ; + bool bUniformStep = true ; + if ( bDouble) { + // solo se lavorazione in doppio, recupero il LastStep se presente + dLastStep = GetDoubleLastStep() ; + if ( dLastStep > EPS_SMALL && abs( dLastStep - m_Params.m_dStep) > 10. * EPS_SMALL) { + double dStepPart = dElev - dLastStep ; + bUniformStep = ( dStepPart < EPS_SMALL) ; // se LastStep maggiore dell'elevazione, allora non lo considero + if ( bUniformStep) { + string sInfo = "Warning in PocketingNT : LastStep (" + ToString( dLastStep, 3) + ") bigger than" + "Elevation (" + ToString( dElev, 3) + ")" ; + m_pMchMgr->SetWarning( 2458, sInfo) ; + } + else { + nStep = max( 1, static_cast( ceil( dStepPart / dOkStep))) ; + dStep = dStepPart / nStep ; + for ( int i = 1 ; i <= nStep ; ++ i) + vdSteps.push_back( i * dStep) ; + vdSteps.push_back( vdSteps.back() + dLastStep) ; + } + } + } + if ( bUniformStep) { + nStep = max( 1, static_cast( ceil( dElev / dOkStep))) ; + dStep = dElev / nStep ; + for ( int i = 1 ; i <= nStep ; ++ i) + vdSteps.push_back( i * dStep) ; + } // step per progressBar int nProgressBarStep = 0 ; - // vettore per gli step - STEPINFOPOVECTOR vStepInfo ; - + STEPINFOPOVECTOR vStepInfo ; vStepInfo.reserve( vdSteps.size()) ; // regione esterna per Geometria di Selezione ISURFFRPOVECTOR vSfrGeoExt ; - CalcGeoExtSurfFr( pSfr, vtTool, dDepth - dElev + nStep * dStep, ( pStmTrim == nullptr ? pStmRaw : pStmTrim), vGeoSel, vSfrGeoExt) ; + CalcGeoExtSurfFr( pSfr, vtTool, dDepth - dElev + vdSteps.back(), ( pStmTrim == nullptr ? pStmRaw : pStmTrim), vGeoSel, vSfrGeoExt) ; - for ( int j = 1 ; j <= nStep ; ++ j) { + for ( int j = 0 ; j < ssize( vdSteps) ; ++ j) { // per i contatori non controllo se effettivamente svuoto una superficie o meno ++ nProgressBarStep ; // aggiorno step per progressBar // porto la superficie allo step corrente PtrOwner pSfrPock( CloneSurfFlatRegion( pSfr)) ; if ( IsNull( pSfrPock) || ! pSfrPock->IsValid() || - ! pSfrPock->Translate( - vtTool * ( dDepth - dElev + j * dStep))) + ! pSfrPock->Translate( - vtTool * ( dDepth - dElev + vdSteps[j]))) return false ; // adatto la regione piana alla geometria del grezzo @@ -4021,8 +4052,8 @@ PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId) #endif // inserisco le informazioni dello step nel vettore vStepInfo.resize( vStepInfo.size() + 1) ; - vStepInfo.back().dDepth = j * dStep ; - vStepInfo.back().dRelativeDepth = dStep ; + vStepInfo.back().dDepth = vdSteps[j] ; + vStepInfo.back().dRelativeDepth = ( j + 1 == ssize( vdSteps) && ! bUniformStep ? dLastStep : dStep) ; vStepInfo.back().pSfrPock.Set( Release( pSfrPock)) ; vStepInfo.back().pSfrLimit.Set( CreateSurfFlatRegion()) ; if ( pSfrLimit->IsValid()) @@ -4530,7 +4561,7 @@ PocketingNT::CalcPaths( STEPINFOPOVECTOR& vStepInfo) // punto finale di riferimento per il percorso attuale ( serve per trovare il punto iniziale // del percorso successivo). Parto analizzando la testa ( da sopra/da sotto) Point3d ptStartRef = GetStartPointsByHead( vStepInfo) ; - // --- se punto invalido e raggio utensile grande se raggio utensile grande + // --- se punto invalido e raggio utensile grande if ( ! ptStartRef.IsValid() && m_TParams.m_dDiam / 2. > TOOL_RAD_PTSTART - EPS_ZERO) { // cerco l'ingresso in base alla geometria iniziale della tasca ptStartRef = GetStartPointsFromSteps( vStepInfo, TEMP_PROP_OPEN_EDGE) ; @@ -4589,11 +4620,11 @@ PocketingNT::CalcPaths( STEPINFOPOVECTOR& vStepInfo) if ( vCrvPaths.empty()) return false ; // sistemo gli archi per massimo angolo al centro - for ( int j = 0 ; j < int( vCrvPaths.size()) ; ++ j) + for ( int j = 0 ; j < ssize( vCrvPaths) ; ++ j) VerifyArcs( vCrvPaths[j]) ; // inserisco i percorsi nel vettore dei Paths - vStepInfo[i].vPaths.resize( int( vCrvPaths.size())) ; - for ( int j = 0 ; j < int( vCrvPaths.size()) ; ++ j) { + vStepInfo[i].vPaths.resize( vCrvPaths.size()) ; + for ( int j = 0 ; j < ssize( vCrvPaths) ; ++ j) { // controllo se il percorso ha un ingresso presso un lato aperto vStepInfo[i].vPaths[j].bOutStart = ( vCrvPaths[j]->GetCurveCount() > 0 && vCrvPaths[j]->GetFirstCurve()->GetTempProp( 0) == TEMP_PROP_OUT_START) ; @@ -4642,7 +4673,7 @@ PocketingNT::CalcPaths( STEPINFOPOVECTOR& vStepInfo) } // definisco il nuovo punto di riferimento per il percorso successivo // Se caso ottimizzato a spirale - if ( int( vStepInfo[i].vPaths.size()) == 1 && vStepInfo[i].vPaths[0].bOptCirle) { + if ( ssize( vStepInfo[i].vPaths) == 1 && vStepInfo[i].vPaths[0].bOptCirle) { // Se entrata da fuori, ricomincio dall'esterno if ( vStepInfo[i].vPaths[0].bOutStart) vStepInfo[i].vPaths[0].pCrvPath->GetStartPoint( ptStartRef) ; @@ -4658,16 +4689,14 @@ PocketingNT::CalcPaths( STEPINFOPOVECTOR& vStepInfo) else vStepInfo[i].vPaths.front().pCrvPath->GetStartPoint( ptStartRef) ; // aggiorno la progressBar - ExeProcessEvents( 50 + i * 50 / int( vStepInfo.size()), 0) ; + ExeProcessEvents( 50 + i * 50 / ssize( vStepInfo), 0) ; } // controllo se la svuotatura è riferita ad un foro chiuso bool bHolePocketing = true ; - for ( int i = 0 ; i < int( vStepInfo.size()) && bHolePocketing ; ++ i) { - bHolePocketing = ( int( vStepInfo[i].vPaths.size()) == 1 && - vStepInfo[i].vPaths[0].bOptCirle && - ! vStepInfo[i].vPaths[0].bOutStart && - ! vStepInfo[i].vPaths[0].bOutEnd) ; + for ( int i = 0 ; i < ssize( vStepInfo) && bHolePocketing ; ++ i) { + bHolePocketing = ( ssize( vStepInfo[i].vPaths) == 1 && vStepInfo[i].vPaths[0].bOptCirle && + ! vStepInfo[i].vPaths[0].bOutStart && ! vStepInfo[i].vPaths[0].bOutEnd) ; } // se foro chiuso ed entrata ad elica, aggiusto il raggio massimo if ( bHolePocketing && m_Params.m_nSubType == POCKET_SUB_SPIRALOUT && GetLeadInType() == POCKET_LI_HELIX) { @@ -4682,8 +4711,8 @@ PocketingNT::CalcPaths( STEPINFOPOVECTOR& vStepInfo) } // calcolo la curva di ritorno ( se necessaria) - for ( int i = 0 ; i < int( vStepInfo.size()) ; ++ i) { - for ( int j = 0 ; j < int( vStepInfo[i].vPaths.size()) ; ++ j) { + for ( int i = 0 ; i < ssize( vStepInfo) ; ++ i) { + for ( int j = 0 ; j < ssize( vStepInfo[i].vPaths) ; ++ j) { if ( GetLeadInType() == POCKET_LI_GLIDE || bHolePocketing) { PtrOwner pCrvGlideIn( CreateCurveComposite()) ; if ( IsNull( pCrvGlideIn) || @@ -4725,10 +4754,12 @@ PocketingNT::CalcPaths( STEPINFOPOVECTOR& vStepInfo) bool bOk = true ; for ( int nC = 0 ; bOk && nC < vStepInfo[i].vPaths[j].pCrvPath->GetCurveCount() ; ++ nC) { const ICurve* pCrv = vStepInfo[i].vPaths[j].pCrvPath->GetCurve( nC) ; - bOk = ( pCrv != nullptr && pCrv->IsValid() && pCompoZigZag->AddCurve( *pCrv)) ; - Point3d ptEnd ; pCrv->GetEndPoint( ptEnd) ; - if ( AreSamePointEpsilon( ptStart, ptEnd, 25. * EPS_SMALL)) - break ; + bOk = ( pCrv != nullptr && pCrv->IsValid() && pCompoZigZag->AddCurve( *pCrv)) ; + if ( bOk) { + Point3d ptEnd ; pCrv->GetEndPoint( ptEnd) ; + if ( AreSamePointEpsilon( ptStart, ptEnd, 25. * EPS_SMALL)) + break ; + } } if ( bOk) vStepInfo[i].vPaths[j].pCrvZigZagIn.Set( Release( pCompoZigZag)) ; @@ -4782,6 +4813,276 @@ PocketingNT::ManageSmoothLink( const PathInfoPO& currPath, const PathInfoPO& nex return true ; } +//---------------------------------------------------------------------------- +bool +PocketingNT::VerifyParallelPocketing( int nDouble, const STEPINFOPOVECTOR& vStepInfo) const +{ + // verifico se lavorazione in doppio valida + if ( nDouble != 1 && nDouble != 2 && nDouble != 3) + return false ; + + // se non ho piano di pocketing allora non devo fare nulla + if ( vStepInfo.empty()) + return false ; + + // se la macchina non presenta nel file .ini la possibilità di lavorazione in doppio parallela, esco + Machine* pMch = m_pMchMgr->GetCurrMachine() ; + if ( pMch == nullptr) + return false ; + string sMachIni = pMch->GetMachineDir() + "\\" + pMch->GetMachineName() + ".ini" ; + int nPocketingDouble = GetPrivateProfileInt( MACHININGS_SEC.c_str(), POCKETING_PARALLEL_KEY.c_str(), 0, sMachIni.c_str()) ; + if ( nPocketingDouble != 1) + return false ; + + // recupero il piano di Mirror + Point3d ptOn ; Vector3d vtNorm ; + if ( ! CalcMirrorPlaneByDouble( nDouble, m_Params.m_sUserNotes, ptOn, vtNorm)) + return false ; + Plane3d plMirror ; + if ( ! plMirror.Set( ptOn, vtNorm)) + return false ; + + // recupero il piano dell'ultima svuotatura + bool bOk = false ; + Plane3d plLastStep ; + for ( auto Iter = vStepInfo.rbegin() ; ! bOk && Iter != vStepInfo.rend() ; ++ Iter) { + if ( Iter->pSfrPock != nullptr && Iter->pSfrPock->IsValid()) { + for ( int nPath = 0 ; ! bOk && nPath < ssize( ( *Iter).vPaths) ; ++ nPath) { + if ( ( *Iter).vPaths[nPath].pCrvPath != nullptr && ( *Iter).vPaths[nPath].pCrvPath->IsValid()) { + Point3d ptLastStep ; ( *Iter).pSfrPock->GetCentroid( ptLastStep) ; + bOk = ( plLastStep.Set( ptLastStep, ( *Iter).pSfrPock->GetNormVersor())) ; + } + } + } + } + if ( ! bOk) + return false ; + + // verifico subito che la normale del piano si trovi entro un grado rispetto alla direzione di svuotatura ( tolleranza da .BTL) + if ( abs( plLastStep.GetVersN() * vtNorm) < cos( ( 1. - EPS_ANG_SMALL) * DEGTORAD)) + return false ; + + // se l'ultimo piano di pocketing si trova nel semipiano positivo di Mirroring e sufficientemente distante da esso non eseguo la lavorazione + // in parallelo ( SAFE_DIST_TOL è la distanza tra l'utensile e il piano di Mirror, quindi la distanza tra le due "punte" è il doppio) + const double SAFE_DIST_TOL = 5. ; // -->! distanza tra le punte è il doppio + double dDist = ( plLastStep.GetPoint() - ptOn) * plLastStep.GetVersN() ; + if ( dDist < EPS_SMALL) + return true ; + double dSafeTipDist = m_TParams.m_dTLen - m_TParams.m_dLen ; // nelle svuotature mi aspetto 0. + if ( dDist < dSafeTipDist + SAFE_DIST_TOL) + return true ; + + return false ; +} + +//---------------------------------------------------------------------------- +double +PocketingNT::GetDoubleLastStep( void) +{ + // se non è pocketing in doppio, restituisco valore negativo + const double FALSE_LASTSTEP = - EPS_SMALL ; + if ( GetDoubleType( m_Params.m_sUserNotes) == 0) + return FALSE_LASTSTEP ; + // recupero valore + const double MIN_LASTSTEP = 15 ; + double dDoubleLastStep = m_Params.m_dStep ; + if ( GetValInNotes( m_Params.m_sUserNotes, UN_LASTSTEP, dDoubleLastStep)) + dDoubleLastStep = max( dDoubleLastStep, MIN_LASTSTEP) ; + return dDoubleLastStep ; +} + +//---------------------------------------------------------------------------- +bool +PocketingNT::CalcDoubleParallelPenultimateStep( int nDouble, int nIdDblS, double dStep, double dLastStep, const Point3d& ptNeatEnd, const Vector3d& vtEnd, + const INTVECTOR& vLeadOutId, const ISurfFlatRegion* pSfrLimit, const Vector3d& vtTool, + bool bSplitArcs, double dMinFeed) +{ + // recupero l'ultima entità del percorso + int nIdDblEnd = m_pGeomDB->GetLastInGroup( m_nPathId) ; + if ( nIdDblS > nIdDblEnd) + return false ; + + // determino il piano corrente di svuotatura + Plane3d plLastStep ; + if ( ! plLastStep.Set( ptNeatEnd, vtTool)) + return false ; + INTVECTOR vIndCrvNotInLastStepPlane ; + + // recupero il percorso dell'ultimo piano di pocketing + PtrOwner pCompo( CreateCurveComposite()) ; + if ( IsNull( pCompo)) + return false ; + for ( int nEntId = nIdDblS + 1 ; nEntId <= nIdDblEnd ; ++ nEntId) { + // l'ultimo piano deve essere eseguito in parallelo, quindi modifico il Name delle entità + m_pGeomDB->SetName( nEntId, MCH_CL_PARALLEL_DBL) ; + const ICurve* pCrv = GetCurve( m_pGeomDB->GetGeoObj( nEntId)) ; + if ( pCrv == nullptr || ! pCrv->IsValid()) + return false ; + // recupero l'entità camData corrispondente + CamData* pCamData = GetCamData( m_pGeomDB->GetUserObj( nEntId)) ; + if ( pCamData != nullptr) { + double dFeed = pCamData->GetFeed() ; + // verifico se la curva corrente appartiene al piano del LastStep + bool bOnPlane = false ; + Plane3d plCrv ; + if ( pCrv->GetType() == CRV_LINE) { + Point3d ptS ; pCrv->GetStartPoint( ptS) ; + Point3d ptE ; pCrv->GetEndPoint( ptE) ; + if ( DistPointPlane( ptS, plLastStep) < 10. * EPS_SMALL && DistPointPlane( ptE, plLastStep) < 10. * EPS_SMALL) + bOnPlane = true ; + } + else if ( pCrv->IsFlat( plCrv, false, 10. * EPS_SMALL) && + abs( DistPointPlane( plCrv.GetPoint(), plLastStep)) < 10. * EPS_SMALL && + AreSameOrOppositeVectorApprox( plCrv.GetVersN(), plLastStep.GetVersN())) + bOnPlane = true ; + if ( ! bOnPlane) + vIndCrvNotInLastStepPlane.push_back( pCompo->GetCurveCount()) ; + else { + // NB : dLastStep non assume valore < 15 per definizione ( GetDoubleLastStep()) + if ( dLastStep > dStep + 10. * EPS_SMALL) { + double dNewFeed = Clamp( dFeed * ( dStep / dLastStep), dMinFeed, GetFeed()) ; + pCamData->SetFeed( dNewFeed) ; + } + } + PtrOwner pCurve( pCrv->Clone()) ; + if ( IsNull( pCurve)) + return false ; + pCurve->SetTempParam( dFeed, 0) ; + if ( ! pCompo->AddCurve( Release( pCurve))) + return false ; + } + } + #if DEBUG_DOUBLE_PARALLEL + int nCompoBC = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCompo->Clone()) ; + m_pGeomDB->SetMaterial( nCompoBC, RED) ; + for ( int i = 0 ; i < ssize( vIndCrvNotInLastStepPlane) ; ++ i) { + const ICurve* pCrv = pCompo->GetCurve( vIndCrvNotInLastStepPlane[i]) ; + int nEntId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCrv->Clone()) ; + m_pGeomDB->SetMaterial( nEntId, YELLOW) ; + } + #endif + + // calcolo il piano di Mirror + Point3d ptOn ; Vector3d vtNorm ; + CalcMirrorPlaneByDouble( nDouble, m_Params.m_sUserNotes, ptOn, vtNorm) ; + + // dato che l'ultimo piano di svuotatura arriva alla Depth stabilita, bisogna aggiungere un alteriore piano che il secondo + // utensile deve svuotare. Essendo che i percorsi sono calcolati sempre sull'utensile principale, bisogna effettuare un'opportuna + // operazione di traslazione e di Mirror in modo da posizionare il primo utensile in modo tale che il secondo finisca in un piano + // di Pocketing specchiato e alla quota corretta rispetto al piano di Mirror calcolato. + double dDblTrasl = ( ( ptOn - ptNeatEnd) * vtTool) ; // ptNeat in quanto privo di possibile LeadOut + pCompo->Mirror( ptOn, vtNorm) ; + pCompo->Translate( 2. * ( dLastStep - dDblTrasl) * vtTool) ; + #if DEBUG_DOUBLE_PARALLEL + int nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCompo->Clone()) ; + m_pGeomDB->SetMaterial( nId, LIME) ; + #endif + + // dopo aver percorso l'ultimo Step devo raccordarmi per raggiungere quest'ultimo + Point3d ptStart ; pCompo->GetStartPoint( ptStart) ; + Vector3d vtStart ; pCompo->GetStartDir( vtStart) ; + // proietto il punto iniziale del percorso di Mirror sul piano di Mirror + Plane3d plMirror ; plMirror.Set( ptOn, vtNorm) ; + Point3d ptStartProj = ProjectPointOnPlane( ptStart, plMirror) ; + Point3d ptCurr ; GetCurrPos( ptCurr) ; + Point3d ptCurrProj = ProjectPointOnPlane( ptCurr, plMirror) ; + + // se il punto corrente e la proiezione della destinazione non coincidono, definisco il collegamento + // -->! l'obiettivo è raggiungere ptStart, il punto iniziale del percorso dello Step aggiuntivo + SetFeed( GetStartFeed()) ; // per lo Step in doppio + if ( ! AreSamePointEpsilon( ptStartProj, ptCurrProj, 25. * EPS_SMALL)) { + // --- controllo se un collegamento lineare è valido + PtrOwner pCrvSafeLink( CreateCurveComposite()) ; + if ( IsNull( pCrvSafeLink)) + return false ; + pCrvSafeLink->AddPoint( ptCurrProj) ; + pCrvSafeLink->AddLine( ptStartProj) ; + if ( ! pCrvSafeLink->IsValid()) + return false ; + bool bSafeLimit = true ; + if ( pSfrLimit != nullptr && pSfrLimit->IsValid()) { + for ( int nC = 0 ; nC < pSfrLimit->GetChunkCount() && bSafeLimit ; ++ nC) { + CRVCVECTOR ccClass ; + bSafeLimit = ( pSfrLimit->GetCurveClassification( *pCrvSafeLink, EPS_SMALL, ccClass) && + ssize( ccClass) == 1 && ccClass[0].nClass == CRVC_OUT) ; + } + } + // --- altrimenti cerco un percorso di raccordo smussato ed in tangenza + if ( ! bSafeLimit) { + Vector3d vtEndDir = vtEnd ; + int nLastId = m_pGeomDB->GetLastInGroup( m_nPathId) ; + bool bOk = false ; + do { + const ICurve* pCrv = GetCurve( m_pGeomDB->GetGeoObj( nLastId)) ; + bOk = ( pCrv != nullptr && pCrv->IsValid()) ; + if ( bOk) { + pCrv->GetEndDir( vtEndDir) ; + bOk = CheckSafetyLink( ptCurr, vtEndDir, ptStart, vtStart, pSfrLimit, vtTool, false, bSafeLimit, pCrvSafeLink) ; + } + } while ( ! bOk) ; + if ( ! bOk) + return false ; + } + // aggiusto la pendenza della curva di raccordo calcolata + if ( ! IsNull( pCrvSafeLink) && pCrvSafeLink->IsValid()) { + SetFeed( GetEndFeed()) ; + pCrvSafeLink->SetExtrusion( vtTool) ; + double dNini = ( ptCurr - ORIG) * vtTool ; + double dNfin = ( ptStart - ORIG) * vtTool ; + AdjustCurveSlope( pCrvSafeLink, dNini, dNfin) ; + AddCurveMove( pCrvSafeLink, bSplitArcs, MCH_CL_PARALLEL_DBL) ; + } + } + else { + // aggiungo risalita nel vuoto + AddLinearMove( ptStart, bSplitArcs, MCH_CL_PARALLEL_DBL) ; + } + + // aggiungo il percorso dello Step Extra ( con le opportune Feed) + for ( int nU = 0 ; nU < pCompo->GetCurveCount() ; ++ nU) { + // curva corrente + const ICurve* pCrvC = pCompo->GetCurve( nU) ; + PtrOwner pCurve( pCrvC->Clone()) ; + if ( IsNull( pCurve)) + return false ; + // coefficiente feed ( riduzione di feed per sezione di taglio superiore al previsto ) + double dFeed ; pCompo->GetCurveTempParam( nU, dFeed) ; // feed originaria + if ( vIndCrvNotInLastStepPlane.empty() || + find( vIndCrvNotInLastStepPlane.begin(), vIndCrvNotInLastStepPlane.end(), nU) == vIndCrvNotInLastStepPlane.end()) { + if ( dLastStep - 2. * dDblTrasl > dStep) + dFeed = Clamp( dFeed * ( dStep / ( dLastStep - 2. * dDblTrasl)), dMinFeed, GetFeed()) ; + } + else { + #if DEBUG_DOUBLE_PARALLEL + nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCurve->Clone()) ; + m_pGeomDB->SetMaterial( nId, AQUA) ; + #endif + } + SetFeed( dFeed) ; + // elaborazioni sulla curva corrente + if ( pCurve->GetType() == CRV_LINE) { + ICurveLine* pLine = GetCurveLine( pCurve) ; + Point3d ptP3 = pLine->GetEnd() ; + if ( AddLinearMove( ptP3, bSplitArcs, MCH_CL_PARALLEL_DBL) == GDB_ID_NULL) + return false ; + } + else { + if ( AddCurveMove( pCurve, bSplitArcs, MCH_CL_PARALLEL_DBL) == GDB_ID_NULL) + return false ; + } + } + + // aggiungo discesa per movimento di sincronizzazione + GetCurrPos( ptCurr) ; + double dDepth = ( - ( ptNeatEnd - ptCurr) * vtTool) / 2. ; + if ( dDepth > 25. * EPS_SMALL) { // sempre... + SetFeed( GetEndFeed()) ; // ho rimosso tutto il materiale + AddLinearMove( ptCurr - dDepth * vtTool, bSplitArcs, MCH_CL_PARALLEL_DBL) ; + } + + return true ; +} + //---------------------------------------------------------------------------- bool PocketingNT::AddPocket( STEPINFOPOVECTOR& vStepInfo, const Vector3d& vtTool, double dStep, bool bSplitArcs, @@ -4820,12 +5121,21 @@ PocketingNT::AddPocket( STEPINFOPOVECTOR& vStepInfo, const Vector3d& vtTool, dou if ( GetValInNotes( m_Params.m_sUserNotes, UN_MINFEED, dMinFeed)) dMinFeed = Clamp( dMinFeed, GetFeed() / FEED_MAX_REDUCE, GetFeed()) ; + // verifico se devo eseguire una lavorazione in doppio in parallelo + int nDouble = GetDoubleType( m_Params.m_sUserNotes) ; + bool bDouble = ( nDouble != 0) ; + bool bDoubleParallel = false ; + int nIdDblS = GDB_ID_NULL ; + INTVECTOR vLeadOutIds ; + if ( bDouble) + bDoubleParallel = VerifyParallelPocketing( nDouble, vStepInfo) ; + // scorro il vettore dei piani di pocketing - for ( int i = 0 ; i < int( vStepInfo.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vStepInfo) ; ++ i) { // riferimento alle informazioni relative allo step i-esimo StepInfoPO& currStep = vStepInfo[i] ; // scorro i percorsi calcolati per il piano di pocketing i-esimo - for ( int j = 0 ; j < int( currStep.vPaths.size()) ; ++ j) { + for ( int j = 0 ; j < ssize( currStep.vPaths) ; ++ j) { // riferimento alle informazioni relative al percorso j-esimo del piano di pocketing i-esimo PathInfoPO& currPath = currStep.vPaths[j] ; // ciclo sulle curve elementari del percorso attuale @@ -4864,7 +5174,7 @@ PocketingNT::AddPocket( STEPINFOPOVECTOR& vStepInfo, const Vector3d& vtTool, dou double dEscapeElev = 0. ; Vector3d vtEscape ; if ( bAbsFirst) - CalcFirstElevation( ptStart, ptP1, vtTool, currStep, dSafeZ, dStep, dCurrElev, dEscapeElev, vtEscape) ; + CalcFirstElevation( ptP1, vtTool, currStep, dSafeZ, dStep, dCurrElev, dEscapeElev, vtEscape) ; bool bEscapeElev = ( dEscapeElev > 10. * EPS_SMALL && vtEscape.Len() > 10. * EPS_SMALL) ; // sposto il focus su PtP1 per approccio, quindi riduco l'elevazione corrente se esso non coicide con ptStart dCurrElev -= ( ptP1 - ptStart) * vtTool ; @@ -4876,7 +5186,7 @@ PocketingNT::AddPocket( STEPINFOPOVECTOR& vStepInfo, const Vector3d& vtTool, dou // se lucidatura forzo il valore al parametro di elevazione in ingresso if ( m_TParams.m_nType == TT_MILL_POLISHING) { ptP1 += vtTool * max( m_Params.m_dLiElev, dCurrElev + LIO_ELEV_TOL) ; - dCurrElev = 0 ; + dCurrElev = 0. ; } // altrimenti, muovo ptP1 alla quota dell'elevazione corrente else { @@ -4902,7 +5212,7 @@ PocketingNT::AddPocket( STEPINFOPOVECTOR& vStepInfo, const Vector3d& vtTool, dou double dMyAppr = ( bAbsFirst ? dAppr : 0.) ; if ( bAbsFirst || ! OrthoCompo( ptMyPos - ptP1, vtTool).IsSmall()) { if ( bAbsFirst && bEscapeElev) { - if ( ! AddApproach( ptP1 + vtEscape * dEscapeElev, vtEscape, dMySafeZ, dSafeAggrBottZ, 0, dMyAppr, bSplitArcs, currPath.bOutStart)) { + if ( ! AddApproach( ptP1 + vtEscape * dEscapeElev, vtEscape, dMySafeZ, dSafeAggrBottZ, 0., dMyAppr, bSplitArcs, currPath.bOutStart)) { m_pMchMgr->SetLastError( 3011, "Error in PocketingNT : Approach not computable") ; return false ; } @@ -4929,7 +5239,7 @@ PocketingNT::AddPocket( STEPINFOPOVECTOR& vStepInfo, const Vector3d& vtTool, dou PtrOwner pLine( CreateCurveLine()) ; pLine->Set( ptCurr, ptP1) ; DebugDrawFeed( pLine->Clone(), bInMaterial ? GetRightFeed( vtMove, vtTool) : GetStartFeed(), nLayDebugFeed) ; #endif - AddLinearMove( ptP1) ; + AddLinearMove( ptP1, bSplitArcs) ; } bool bNoneForced = ( currPath.bOutStart || currPath.bSingleCrv || ( m_Params.m_nSubType == POCKET_SUB_ZIGZAG && ! currPath.bIsZigZagOneWayBorder) || @@ -4972,20 +5282,35 @@ PocketingNT::AddPocket( STEPINFOPOVECTOR& vStepInfo, const Vector3d& vtTool, dou // memorizzo il punto finale della lavorazione ptPockEnd = ptEnd ; // aggiungo LeadOut + int nLastId = GDB_ID_NULL ; + if ( bDoubleParallel) + nLastId = m_pGeomDB->GetLastInGroup( m_nPathId) ; Point3d ptP1 ; SetFeed( GetEndFeed()) ; if ( ! AddLeadOut( ptEnd, vtEnd, vtTool, currStep.pSfrPock, currPath.pCrvGlideOut, bSplitArcs, false, ptP1)) { m_pMchMgr->SetLastError( 3014, "Error in PocketingNT : LeadOut not computable") ; return false ; } + /* ---- se lavorazione in Doppio in Parallelo ---- */ + if ( bDoubleParallel) { + int nCurrId = m_pGeomDB->GetLastInGroup( m_nPathId) ; + if ( nLastId != nCurrId) { + for ( int nId = nLastId + 1 ; nId <= nCurrId ; ++ nId) + vLeadOutIds.push_back( nId) ; + } + if ( ! CalcDoubleParallelPenultimateStep( nDouble, nIdDblS, dStep, currStep.dRelativeDepth, ptEnd, vtEnd, vLeadOutIds, + currStep.pSfrLimit, vtTool, bSplitArcs, dMinFeed)) + return false ; + GetCurrPos( ptEnd) ; + } // calcolo l'elevazione al di sopra del punto corrente. Esattamente come per la prima elevazione in assoluto potrei // avere una direzione di 'Escape' double dLastElev = 0., dEscapeElev = 0. ; Vector3d vtEscape ; - if ( ! CalcLastElevation( ptEnd, ptP1, vtTool, currStep, dSafeZ, dStep, dLastElev, dEscapeElev, vtEscape)) + if ( ! CalcLastElevation( ptP1, vtTool, currStep, dSafeZ, dStep, dLastElev, dEscapeElev, vtEscape)) return false ; if ( dEscapeElev > 10. * EPS_SMALL && vtEscape.Len() > 10. * EPS_SMALL) { - AddLinearMove( ptP1 + vtTool * dLastElev) ; + AddLinearMove( ptP1 + vtTool * dLastElev, bSplitArcs) ; if ( ! AddRetract( ptP1 + vtTool * dLastElev, vtEscape, dSafeZ, dSafeAggrBottZ, dEscapeElev, dAppr, bSplitArcs)) { m_pMchMgr->SetLastError( 3015, "Error in PocketingNT : Retract not computable") ; return false ; @@ -5016,6 +5341,11 @@ PocketingNT::AddPocket( STEPINFOPOVECTOR& vStepInfo, const Vector3d& vtTool, dou PathToGo.pCrvPath->GetStartPoint( ptDest) ; PathToGo.pCrvPath->GetStartDir( vtDest) ; } + /* ---- // ---- se lavorazione in doppio e in parallelo ---- // ---- */ + if ( bDoubleParallel && ! bSamePlane) { + if ( ( i + 2) == ssize( vStepInfo) && nIdDblS == GDB_ID_NULL) + nIdDblS = m_pGeomDB->GetLastInGroup( m_nPathId) ; + } // determino se possibile aggiungere un collegamento smussato bool bSafeLimit = false, bSmoothEnd = true, bForceLinear = false ; ManageSmoothLink( currPath, PathToGo, bSamePlane, bSmoothEnd, bForceLinear) ; // verifico solo se fattibile @@ -5065,7 +5395,7 @@ PocketingNT::AddPocket( STEPINFOPOVECTOR& vStepInfo, const Vector3d& vtTool, dou SetFeed( GetEndFeed()) ; dCurrElev += ( bSafeLimit ? 0. : EXTRA_ELEV) ; dNextElev += ( bSafeLimit ? 0. : EXTRA_ELEV) ; - // se devo salire lungo vtTool da vtEnd, mi alzo + // se devo salire lungo vtTool da ptEnd, mi alzo if ( dCurrElev > EPS_SMALL) AddLinearMove( ptEnd + dCurrElev * vtTool, bSplitArcs) ; // mi dirigo sopra a ptDest @@ -5093,25 +5423,25 @@ PocketingNT::AddPocket( STEPINFOPOVECTOR& vStepInfo, const Vector3d& vtTool, dou //---------------------------------------------------------------------------- bool -PocketingNT::CalcFirstElevation( const Point3d& ptStart, const Point3d& ptP1, const Vector3d& vtTool, +PocketingNT::CalcFirstElevation( const Point3d& ptP1, const Vector3d& vtTool, const StepInfoPO& currStep, double dSafeZ, double dStep, double& dCurrElev, double& dEscapeElev, Vector3d& vtEscape) const { // elevazione per ingresso - if ( ! GetElevation( m_nPhase, ptP1 - 10 * EPS_SMALL * vtTool, vtTool, GetRadiusForStartEndElevation(), vtTool, dCurrElev)) - dCurrElev = currStep.dDepth + 10 * EPS_SMALL ; + if ( ! GetElevation( m_nPhase, ptP1 - 10. * EPS_SMALL * vtTool, vtTool, GetRadiusForStartEndElevation(), vtTool, dCurrElev)) + dCurrElev = currStep.dDepth + 10. * EPS_SMALL ; else - dCurrElev = max( dCurrElev, currStep.dDepth + 10 * EPS_SMALL) ; - dEscapeElev = 0 ; + dCurrElev = max( dCurrElev, currStep.dDepth + 10. * EPS_SMALL) ; + dEscapeElev = 0. ; vtEscape = V_NULL ; - double dMyEscapeElev = 0 ; + double dMyEscapeElev = 0. ; Vector3d vtMyEscape = vtTool ; vtMyEscape.z = ( m_bAboveHead ? max( vtTool.z, 0.) : min( vtTool.z, 0.)) ; bool bAhUnderRaw = m_bAboveHead && ! m_bAggrBottom && ! m_bTiltingTab && - GetAhPointUnderRaw( ptP1 + dCurrElev * vtTool, vtTool, 0, GetRadiusForStartEndElevation(), + GetAhPointUnderRaw( ptP1 + dCurrElev * vtTool, vtTool, 0., GetRadiusForStartEndElevation(), m_TParams.m_dLen, false, dSafeZ, vtMyEscape, dMyEscapeElev) ; bool bUhAboveRaw = ! m_bAboveHead && - GetUhPointAboveRaw( ptP1 + dCurrElev * vtTool, vtTool, 0, GetRadiusForStartEndElevation(), + GetUhPointAboveRaw( ptP1 + dCurrElev * vtTool, vtTool, 0., GetRadiusForStartEndElevation(), m_TParams.m_dLen, false, dSafeZ, vtMyEscape, dMyEscapeElev) ; if ( bAhUnderRaw || bUhAboveRaw || m_bTiltingTab) { dEscapeElev = dMyEscapeElev ; @@ -5123,22 +5453,22 @@ PocketingNT::CalcFirstElevation( const Point3d& ptStart, const Point3d& ptP1, co //---------------------------------------------------------------------------- bool -PocketingNT::CalcLastElevation( const Point3d& ptEnd, const Point3d& ptP1, const Vector3d& vtTool, const StepInfoPO& currStep, +PocketingNT::CalcLastElevation( const Point3d& ptP1, const Vector3d& vtTool, const StepInfoPO& currStep, double dSafeZ, double dStep, double& dCurrElev, double& dEscapeElev, Vector3d& vtEscape) const { // elevazione per uscita if ( ! GetElevation( m_nPhase, ptP1, vtTool, GetRadiusForStartEndElevation(), m_TParams.m_dLen, vtTool, dCurrElev)) dCurrElev = currStep.dDepth ; - dEscapeElev = 0 ; + dEscapeElev = 0. ; vtEscape = V_NULL ; - double dMyEscapeElev = 0 ; + double dMyEscapeElev = 0. ; Vector3d vtMyEscape = vtTool ; vtMyEscape.z = ( m_bAboveHead ? max( vtTool.z, 0.) : min( vtTool.z, 0.)) ; bool bAhUnderRaw = m_bAboveHead && ! m_bAggrBottom && ! m_bTiltingTab && - GetAhPointUnderRaw( ptP1 + vtTool * dCurrElev, vtTool, 0, GetRadiusForStartEndElevation(), + GetAhPointUnderRaw( ptP1 + vtTool * dCurrElev, vtTool, 0., GetRadiusForStartEndElevation(), m_TParams.m_dLen, false, dSafeZ, vtMyEscape, dMyEscapeElev) ; bool bUhAboveRaw = ! m_bAboveHead && - GetUhPointAboveRaw( ptP1 + vtTool * dCurrElev, vtTool, 0, GetRadiusForStartEndElevation(), + GetUhPointAboveRaw( ptP1 + vtTool * dCurrElev, vtTool, 0., GetRadiusForStartEndElevation(), m_TParams.m_dLen, false, dSafeZ, vtMyEscape, dMyEscapeElev) ; if ( bAhUnderRaw || bUhAboveRaw || m_bTiltingTab) { dEscapeElev = dMyEscapeElev ; @@ -5876,7 +6206,7 @@ PocketingNT::AddLeadOut( const Point3d& ptEnd, const Vector3d& vtEnd, const Vect double dNfin = ( ptFin - ORIG) * vtN ; AdjustCurveSlope( pCrv, dNini, dNfin) ; // emetto (con eventuale spezzatura) - if ( AddCurveMove( pCrv, bSplitArcs, MCH_CL_LEADIN) == GDB_ID_NULL) + if ( AddCurveMove( pCrv, bSplitArcs, MCH_CL_LEADOUT) == GDB_ID_NULL) return false ; ptP1 = ptFin ; } @@ -6170,7 +6500,6 @@ PocketingNT::AddSpecialLeadInZigZag( const ICurveComposite* pCompoPath, const Po if ( ! pCompoPath->IsPointOn( ptCurr, TOL)) return false ; - Point3d ptStartZigZag = ptCurr ; // punto di inizio dello ZigZag ( potrebbe essere diverso da ptCurr) bool bAtStart = false ; // indica se lo ZigZag è vincolato prima della partenza bool bAtEnd = false ; // indica se lo ZigZag è vincolato dopo l'arrivo @@ -6330,7 +6659,7 @@ PocketingNT::CalcDistanceFromRawSurface( int nPhase, const Point3d& ptP, const V if ( ! GetElevation( nPhase, ptP, vtDir, dDist, vtNorm)) return false ; - // se punto esterno al grezzo + // se punto esterno al grezzo if ( abs( dDist) < EPS_SMALL) { double dDist1, dDist2 ; if ( ! GetElevation( nPhase, ptP, -vtDir, dDist1)) diff --git a/PocketingNT.h b/PocketingNT.h index 70c532a..e67528e 100644 --- a/PocketingNT.h +++ b/PocketingNT.h @@ -152,10 +152,10 @@ class PocketingNT : public Machining double dElev, double dAppr, bool bSplitArcs) ; bool AddRetract( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dSafeAggrBottZ, double dElev, double dAppr, bool bSplitArcs) ; - bool CalcFirstElevation( const Point3d& ptStart, const Point3d& ptP1, const Vector3d& vtTool, + bool CalcFirstElevation( const Point3d& ptP1, const Vector3d& vtTool, const StepInfoPO& currStep, double dSafeZ, double dStep, double& dCurrElev, double& dEscapeElev, Vector3d& vtEscape) const ; - bool CalcLastElevation( const Point3d& ptStart, const Point3d& ptP1, const Vector3d& vtTool, + bool CalcLastElevation( const Point3d& ptP1, const Vector3d& vtTool, const StepInfoPO& currStep, double dSafeZ, double dStep, double& dCurrElev, double& dEscapeElev, Vector3d& vtEscape) const ; bool CalcLeadInStart( Point3d& ptStart, const Vector3d& vtTool, const ICurveComposite* pCrvPath, Point3d& ptP1) ; @@ -177,6 +177,11 @@ class PocketingNT : public Machining bool VerifyLeadInOutGlide( const ISurfFlatRegion* pSfr, ICurveComposite* pCrvGlide) ; bool AddSpecialLeadInZigZag( const ICurveComposite* pCompoPath, const Point3d& ptStart, const Vector3d& vtTool, int nStep, double dStep) ; bool CalcDistanceFromRawSurface( int nPhase, const Point3d& ptP, const Vector3d& vtDir, double& dDist, Vector3d& vtNorm) ; + bool VerifyParallelPocketing( int nDouble, const STEPINFOPOVECTOR& vStepInfo) const ; + bool CalcDoubleParallelPenultimateStep( int nDouble, int nIdDblS, double dStep, double dLastStep, const Point3d& ptNeatEnd, const Vector3d& vtEnd, + const INTVECTOR& vLeadOutId, const ISurfFlatRegion* pSfrLimit, const Vector3d& vtTool, + bool bSplitArcs, double dMinFeed) ; + double GetDoubleLastStep( void) ; // debug void DebugDrawSfr( const ISurfFlatRegion* pSfr, bool bUniform, int nlayer = GDB_ID_ROOT) ; void DebugDrawLoop( const ICurveComposite* pCrvCompo, int nLayer, bool bUniform) ;