diff --git a/EgtMachKernel.vcxproj b/EgtMachKernel.vcxproj
index a330e7c..a512e30 100644
--- a/EgtMachKernel.vcxproj
+++ b/EgtMachKernel.vcxproj
@@ -282,6 +282,7 @@ copy $(TargetPath) \EgtProg\Dll64
Create
+
@@ -423,6 +424,7 @@ copy $(TargetPath) \EgtProg\Dll64
+
diff --git a/EgtMachKernel.vcxproj.filters b/EgtMachKernel.vcxproj.filters
index cffc386..69e13c7 100644
--- a/EgtMachKernel.vcxproj.filters
+++ b/EgtMachKernel.vcxproj.filters
@@ -219,6 +219,9 @@
Source Files\Machinings
+
+ Source Files\Operations
+
@@ -638,6 +641,9 @@
Header Files
+
+ Header Files
+
diff --git a/OperationConst.h b/OperationConst.h
index 58f012c..3632e3f 100644
--- a/OperationConst.h
+++ b/OperationConst.h
@@ -1,13 +1,13 @@
//----------------------------------------------------------------------------
-// EgalTech 2017-2017
+// EgalTech 2017-2019
//----------------------------------------------------------------------------
-// File : OperationConst.h Data : 17.08.17 Versione : 1.8h1
+// File : OperationConst.h Data : 28.05.19 Versione : 2.1e5
// Contenuto : Costanti per le operazioni.
//
//
//
// Modifiche : 17.08.17 DS Creazione modulo.
-//
+// 25.05.19 DS Aggiunte SurfRoughing e SurfFinishing.
//
//----------------------------------------------------------------------------
@@ -28,7 +28,9 @@ static const std::string s_OpeClass[] = {"",
"EMkSawRoughing",
"EMkSawFinishing",
"EMkGenMachining",
- "EMkChiseling"} ;
+ "EMkChiseling",
+ "EMkSurfRoughing",
+ "EMkSurfFinishing"} ;
//----------------------------------------------------------------------------
// Dal tipo numerico restituisce la classe della operazione
@@ -46,6 +48,8 @@ GetOperationClass( int nOpeType)
case OPER_SAWFINISHING : return s_OpeClass[8] ;
case OPER_GENMACHINING : return s_OpeClass[9] ;
case OPER_CHISELING : return s_OpeClass[10] ;
+ case OPER_SURFROUGHING : return s_OpeClass[11] ;
+ case OPER_SURFFINISHING : return s_OpeClass[12] ;
}
return s_OpeClass[0] ;
}
@@ -75,6 +79,10 @@ GetOperationType( const std::string& sOpeClass)
return OPER_GENMACHINING ;
else if ( sOpeClass == s_OpeClass[10])
return OPER_CHISELING ;
+ else if ( sOpeClass == s_OpeClass[11])
+ return OPER_SURFROUGHING ;
+ else if ( sOpeClass == s_OpeClass[12])
+ return OPER_SURFFINISHING ;
else
return OPER_NULL ;
}
\ No newline at end of file
diff --git a/SurfFinishing.cpp b/SurfFinishing.cpp
new file mode 100644
index 0000000..2ba6a18
--- /dev/null
+++ b/SurfFinishing.cpp
@@ -0,0 +1,1669 @@
+//----------------------------------------------------------------------------
+// EgalTech 2019-2019
+//----------------------------------------------------------------------------
+// File : SurfFinishing.cpp Data : 28.05.19 Versione : 2.1e5
+// Contenuto : Implementazione gestione finitura superfici.
+//
+// Note : Questa lavorazione è sempre espressa nel riferimento globale.
+//
+// Modifiche : 28.05.19 DS Creazione modulo.
+//
+//
+//----------------------------------------------------------------------------
+
+//--------------------------- Include ----------------------------------------
+#include "stdafx.h"
+#include "MachMgr.h"
+#include "DllMain.h"
+#include "SurfFinishing.h"
+#include "OperationConst.h"
+#include "GeoConst.h"
+#include "/EgtDev/Include/EXeCmdLogOff.h"
+#include "/EgtDev/Include/EXeConst.h"
+#include "/EgtDev/Include/EGkCurveLine.h"
+#include "/EgtDev/Include/EGkCurveArc.h"
+#include "/EgtDev/Include/EGkCurveComposite.h"
+#include "/EgtDev/Include/EGkChainCurves.h"
+#include "/EgtDev/Include/EgkOffsetCurve.h"
+#include "/EgtDev/Include/EgkOffsetCurveOnX.h"
+#include "/EgtDev/Include/EGkSfrCreate.h"
+#include "/EgtDev/Include/EGkCAvToolSurfTm.h"
+#include "/EgtDev/Include/EGkIntervals.h"
+#include "/EgtDev/Include/EGkUserObjFactory.h"
+#include "/EgtDev/Include/EGnStringKeyVal.h"
+#include "/EgtDev/Include/EgtPointerOwner.h"
+// per far dimenticare macro di WinUser.h
+#undef GetClassName
+
+using namespace std ;
+
+//------------------------------ Errors --------------------------------------
+// 2701 = "Error in SurfFinishing : UpdateToolData failed"
+// 2702 = "Error in SurfFinishing : AdjustGeometry failed"
+// 2703 = "Error in SurfFinishing : Empty RawBox"
+// 2704 = "Error in SurfFinishing : Depth not computable"
+// 2705 = "Error in SurfFinishing : CalculateToolAndCorrVersors"
+// 2706 = "Error in SurfFinishing : ApproxWithLines"
+// 2707 = "Error in SurfFinishing : Guide Line not along X or Y"
+// 2708 = "Error in SurfFinishing : GetElevation"
+// 2709 = "Error in SurfFinishing : CalculateAlongToolPath failed"
+// 2710 = "Error in SurfFinishing : CalculateAcrossToolPath failed"
+// 2711 = "Error in SurfFinishing : axes values not calculable"
+// 2712 = "Error in SurfFinishing : outstroke xx"
+// 2713 = "Error in SurfFinishing : link movements not calculable"
+// 2714 = "Error in SurfFinishing : link outstroke xx"
+// 2715 = "Error in SurfFinishing : post apply not calculable"
+
+//----------------------------------------------------------------------------
+USEROBJ_REGISTER( GetOperationClass( OPER_SURFFINISHING), SurfFinishing) ;
+
+//----------------------------------------------------------------------------
+const string&
+SurfFinishing::GetClassName( void) const
+{
+ return USEROBJ_GETNAME( SurfFinishing) ;
+}
+
+//----------------------------------------------------------------------------
+SurfFinishing*
+SurfFinishing::Clone( void) const
+{
+ // alloco oggetto
+ SurfFinishing* pSrF = new(nothrow) SurfFinishing ;
+ // eseguo copia dei dati
+ if ( pSrF != nullptr) {
+ try {
+ pSrF->m_vId = m_vId ;
+ pSrF->m_pMchMgr = m_pMchMgr ;
+ pSrF->m_nPhase = m_nPhase ;
+ pSrF->m_Params = m_Params ;
+ pSrF->m_TParams = m_TParams ;
+ pSrF->m_nStatus = m_nStatus ;
+ pSrF->m_nPaths = m_nPaths ;
+ }
+ catch( ...) {
+ delete pSrF ;
+ return nullptr ;
+ }
+ }
+ // ritorno l'oggetto
+ return pSrF ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::Dump( string& sOut, bool bMM, const char* szNewLine) const
+{
+ sOut += GetClassName() + "[mm]" + szNewLine ;
+ sOut += KEY_PHASE + EQUAL + ToString( m_nPhase) + szNewLine ;
+ sOut += KEY_IDS + EQUAL + ToString( m_vId) + szNewLine ;
+ for ( int i = 0 ; i < m_Params.GetSize() ; ++ i)
+ sOut += m_Params.ToString( i) + szNewLine ;
+ for ( int i = 0 ; i < m_TParams.GetSize() ; ++ i)
+ sOut += m_TParams.ToString( i) + szNewLine ;
+ sOut += KEY_NUM + EQUAL + ToString( m_nPaths) + szNewLine ;
+ sOut += KEY_STAT + EQUAL + ToString( m_nStatus) + szNewLine ;
+
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::Save( int nBaseId, STRVECTOR& vString) const
+{
+ try {
+ int nSize = 1 + m_Params.GetSize() + m_TParams.GetSize() + 3 ;
+ vString.insert( vString.begin(), nSize, "") ;
+ int k = - 1 ;
+ if ( ! SetVal( KEY_IDS, m_vId, vString[++k]))
+ return false ;
+ for ( int i = 0 ; i < m_Params.GetSize() ; ++ i)
+ vString[++k] = m_Params.ToString( i) ;
+ for ( int i = 0 ; i < m_TParams.GetSize() ; ++ i)
+ vString[++k] = m_TParams.ToString( i) ;
+ if ( ! SetVal( KEY_PHASE, m_nPhase, vString[++k]))
+ return false ;
+ if ( ! SetVal( KEY_NUM, m_nPaths, vString[++k]))
+ return false ;
+ if ( ! SetVal( KEY_STAT, m_nStatus, vString[++k]))
+ return false ;
+ }
+ catch( ...) {
+ return false ;
+ }
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::Load( const STRVECTOR& vString, int nBaseGdbId)
+{
+ int nSize = int( vString.size()) ;
+ // lista identificativi geometrie da lavorare
+ int k = - 1 ;
+ if ( k >= nSize - 1 || ! GetVal( vString[++k], KEY_IDS, m_vId))
+ return false ;
+ for ( auto& Sel : m_vId)
+ Sel.nId += nBaseGdbId ;
+ // parametri lavorazione
+ for ( int i = 0 ; i < m_Params.GetSize() ; ++ i) {
+ int nKey ;
+ if ( k >= nSize - 1 || ! m_Params.FromString( vString[++k], nKey) || nKey != i) {
+ if ( m_Params.IsOptional( i))
+ -- k ;
+ else
+ return false ;
+ }
+ }
+ // parametri utensile
+ for ( int i = 0 ; i < m_TParams.GetSize() ; ++ i) {
+ int nKey ;
+ if ( k >= nSize - 1 || ! m_TParams.FromString( vString[++k], nKey) || nKey != i)
+ return false ;
+ }
+ // parametri di stato
+ while ( k < nSize - 1) {
+ // separo chiave da valore
+ string sKey, sVal ;
+ SplitFirst( vString[++k], "=", sKey, sVal) ;
+ // leggo
+ if ( sKey == KEY_PHASE) {
+ if ( ! FromString( sVal, m_nPhase))
+ return false ;
+ }
+ else if ( sKey == KEY_NUM) {
+ if ( ! FromString( sVal, m_nPaths))
+ return false ;
+ }
+ else if ( sKey == KEY_STAT) {
+ if ( ! FromString( sVal, m_nStatus))
+ return false ;
+ }
+ }
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+SurfFinishing::SurfFinishing( void)
+{
+ m_Params.m_sName = "*" ;
+ m_Params.m_sToolName = "*" ;
+ m_TParams.m_sName = "*" ;
+ m_TParams.m_sHead = "*" ;
+ m_dTHoldLen = 0 ;
+ m_dTHoldDiam = 0 ;
+ m_nStatus = MCH_ST_TO_VERIFY ;
+ m_nPaths = 0 ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::Prepare( const string& sSawName)
+{
+ // verifico il gestore lavorazioni
+ if ( m_pMchMgr == nullptr)
+ return false ;
+ // recupero il gestore DB utensili della macchina corrente
+ ToolsMgr* pTMgr = m_pMchMgr->GetCurrToolsMgr() ;
+ if ( pTMgr == nullptr)
+ return false ;
+ // recupero il gestore DB lavorazioni della macchina corrente
+ MachiningsMgr* pMMgr = m_pMchMgr->GetCurrMachiningsMgr() ;
+ if ( pMMgr == nullptr)
+ return false ;
+ // ricerca della lavorazione di libreria con il nome indicato
+ const SurfFinishingData* pDdata = GetSurfFinishingData( pMMgr->GetMachining( sSawName)) ;
+ if ( pDdata == nullptr)
+ return false ;
+ m_Params = *pDdata ;
+ // ricerca dell'utensile usato dalla lavorazione
+ const ToolData* pTdata = pTMgr->GetTool( m_Params.m_ToolUuid) ;
+ if ( pTdata == nullptr)
+ return false ;
+ m_TParams = *pTdata ;
+ m_Params.m_sToolName = m_TParams.m_sName ;
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::SetParam( int nType, bool bVal)
+{
+ switch ( nType) {
+ case MPA_INVERT :
+ if ( bVal != m_Params.m_bInvert)
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_bInvert = bVal ;
+ return true ;
+ }
+ return false ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::SetParam( int nType, int nVal)
+{
+ switch ( nType) {
+ case MPA_SUBTYPE :
+ if ( ! m_Params.VerifySubType( nVal))
+ return false ;
+ if ( nVal != m_Params.m_nSubType)
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_nSubType = nVal ;
+ return true ;
+ case MPA_LEADINTYPE :
+ if ( ! m_Params.VerifyLeadInType( nVal))
+ return false ;
+ if ( nVal != m_Params.m_nLeadInType)
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_nLeadInType = nVal ;
+ return true ;
+ case MPA_LEADLINKTYPE :
+ if ( ! m_Params.VerifyLeadLinkType( nVal))
+ return false ;
+ if ( nVal != m_Params.m_nLeadLinkType)
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_nLeadLinkType = nVal ;
+ return true ;
+ case MPA_LEADOUTTYPE :
+ if ( ! m_Params.VerifyLeadOutType( nVal))
+ return false ;
+ if ( nVal != m_Params.m_nLeadOutType)
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_nLeadOutType = nVal ;
+ return true ;
+ case MPA_SCC :
+ if ( ! m_Params.VerifySolCh( nVal))
+ return false ;
+ if ( nVal != m_Params.m_nSolCh)
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_nSolCh = nVal ;
+ return true ;
+ }
+ return false ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::SetParam( int nType, double dVal)
+{
+ switch ( nType) {
+ case MPA_SPEED :
+ if ( ! m_TParams.VerifySpeed( dVal))
+ return false ;
+ if ( AreSameAngValue( dVal, m_TParams.m_dSpeed))
+ dVal = 0 ;
+ m_Params.m_dSpeed = dVal ;
+ return true ;
+ case MPA_FEED :
+ if ( AreSameLenValue( dVal, m_TParams.m_dFeed))
+ dVal = 0 ;
+ if ( ! AreSameLenValue( dVal, m_Params.m_dFeed))
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_dFeed = dVal ;
+ return true ;
+ case MPA_STARTFEED :
+ if ( AreSameLenValue( dVal, m_TParams.m_dStartFeed))
+ dVal = 0 ;
+ if ( ! AreSameLenValue( dVal, m_Params.m_dStartFeed))
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_dStartFeed = dVal ;
+ return true ;
+ case MPA_ENDFEED :
+ if ( AreSameLenValue( dVal, m_TParams.m_dEndFeed))
+ dVal = 0 ;
+ if ( ! AreSameLenValue( dVal, m_Params.m_dEndFeed))
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_dEndFeed = dVal ;
+ return true ;
+ case MPA_TIPFEED :
+ if ( AreSameLenValue( dVal, m_TParams.m_dTipFeed))
+ dVal = 0 ;
+ if ( ! AreSameLenValue( dVal, m_Params.m_dTipFeed))
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_dTipFeed = dVal ;
+ return true ;
+ case MPA_OFFSR :
+ if ( AreSameLenValue( dVal, m_TParams.m_dOffsR))
+ dVal = UNKNOWN_PAR ;
+ if ( ! AreSameLenValue( dVal, m_Params.m_dOffsR))
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_dOffsR = dVal ;
+ return true ;
+ case MPA_DEPTH: {
+ string sVal = ToString( dVal) ;
+ if ( sVal != m_Params.m_sDepth)
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_sDepth = sVal ;
+ } return true ;
+ case MPA_STARTPOS :
+ if ( ! AreSameLenValue( dVal, m_Params.m_dStartPos))
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_dStartPos = dVal ;
+ return true ;
+ case MPA_SIDESTEP :
+ if ( ! AreSameLenValue( dVal, m_Params.m_dSideStep))
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_dSideStep = dVal ;
+ return true ;
+ case MPA_SIDEANGLE :
+ if ( abs( dVal - m_Params.m_dSideAngle) > EPS_MACH_LEN_PAR)
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_dSideAngle = dVal ;
+ return true ;
+ case MPA_LITANG :
+ if ( abs( dVal - m_Params.m_dLiTang) > EPS_MACH_LEN_PAR)
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_dLiTang = dVal ;
+ return true ;
+ case MPA_LIPERP :
+ if ( abs( dVal - m_Params.m_dLiPerp) > EPS_MACH_LEN_PAR)
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_dLiPerp = dVal ;
+ return true ;
+ case MPA_LOTANG :
+ if ( abs( dVal - m_Params.m_dLoTang) > EPS_MACH_LEN_PAR)
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_dLoTang = dVal ;
+ return true ;
+ case MPA_LOPERP :
+ if ( abs( dVal - m_Params.m_dLoPerp) > EPS_MACH_LEN_PAR)
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_dLoPerp = dVal ;
+ return true ;
+ case MPA_APPROX :
+ if ( ! AreSameLenValue( dVal, m_Params.m_dApprox))
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_dApprox = dVal ;
+ return true ;
+ }
+ return false ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::SetParam( int nType, const string& sVal)
+{
+ switch ( nType) {
+ case MPA_TOOL : {
+ const ToolData* pTdata ;
+ if ( ! m_Params.VerifyTool( m_pMchMgr->GetCurrToolsMgr(), sVal, pTdata))
+ return false ;
+ if ( ! SameTool( m_TParams, *pTdata))
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_sToolName = sVal ;
+ m_Params.m_ToolUuid = pTdata->m_Uuid ;
+ m_TParams = *pTdata ;
+ } return true ;
+ case MPA_DEPTH_STR :
+ if ( sVal != m_Params.m_sDepth)
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_sDepth = sVal ;
+ return true ;
+ case MPA_SYSNOTES :
+ if ( sVal != m_Params.m_sSysNotes)
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_sSysNotes = sVal ;
+ return true ;
+ case MPA_USERNOTES :
+ if ( sVal != m_Params.m_sUserNotes)
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_sUserNotes = sVal ;
+ return true ;
+ case MPA_INITANGS :
+ if ( sVal != m_Params.m_sInitAngs)
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_sInitAngs = sVal ;
+ return true ;
+ case MPA_BLOCKEDAXIS :
+ if ( sVal != m_Params.m_sBlockedAxis)
+ m_nStatus |= MCH_ST_PARAM_MODIF ;
+ m_Params.m_sBlockedAxis = sVal ;
+ return true ;
+ }
+ return false ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::SetGeometry( const SELVECTOR& vIds)
+{
+ // verifico validità gestore DB geometrico
+ if ( m_pGeomDB == nullptr)
+ return false ;
+ // reset della geometria corrente
+ m_vId.clear() ;
+ // verifico che gli identificativi rappresentino delle entità ammissibili
+ for ( const auto& Id : vIds) {
+ // test sull'entità
+ int nSubs ;
+ if ( ! VerifyGeometry( Id, nSubs)) {
+ string sOut = "Entity " + ToString( Id) + " skipped by SurfFinishing" ;
+ LOG_INFO( GetEMkLogger(), sOut.c_str()) ;
+ continue ;
+ }
+ // posso aggiungere alla lista
+ m_vId.emplace_back( Id) ;
+ }
+ // aggiorno lo stato
+ m_nStatus |= MCH_ST_GEO_MODIF ;
+ // restituisco presenza geometria da lavorare
+ return ( ! m_vId.empty()) ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::Preview( bool bRecalc)
+{
+ // non esiste preview, si fa apply
+ return Apply( bRecalc, false) ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::Apply( bool bRecalc, bool bPostApply)
+{
+ // reset numero tagli nella lavorazione
+ int nCurrPaths = m_nPaths ;
+ m_nPaths = 0 ;
+
+ // verifico validità gestore DB geometrico e Id del gruppo
+ if ( m_pGeomDB == nullptr || ! m_pGeomDB->ExistsObj( m_nOwnerId))
+ return false ;
+
+ // aggiorno dati geometrici dell'utensile
+ bool bToolChanged = true ;
+ if ( ! UpdateToolData( &bToolChanged)) {
+ m_pMchMgr->SetLastError( 2701, "Error in SurfFinishing : UpdateToolData failed") ;
+ return false ;
+ }
+
+ // verifico se necessario continuare nell'aggiornamento
+ if ( ! bRecalc && ! bToolChanged &&
+ ( m_nStatus == MCH_ST_OK || ( ! bPostApply && m_nStatus == MCH_ST_NO_POSTAPPL))) {
+ m_nPaths = nCurrPaths ;
+ LOG_DBG_INFO( GetEMkLogger(), "SurfFinishing apply skipped : status already ok") ;
+ return true ;
+ }
+ m_nStatus = MCH_ST_TO_VERIFY ;
+
+ // recupero gruppo per geometria ausiliaria
+ int nAuxId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_AUX) ;
+ bool bChain = false ;
+ // se non c'è, lo aggiungo
+ if ( nAuxId == GDB_ID_NULL) {
+ nAuxId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ;
+ if ( nAuxId == GDB_ID_NULL)
+ return false ;
+ m_pGeomDB->SetName( nAuxId, MCH_AUX) ;
+ m_pGeomDB->SetStatus( nAuxId, GDB_ST_OFF) ;
+ bChain = true ;
+ }
+ // altrimenti, se chiesto ricalcolo, lo svuoto
+ else if ( bRecalc) {
+ m_pGeomDB->EmptyGroup( nAuxId) ;
+ bChain = true ;
+ }
+
+ // rendo corrente l'utensile usato nella lavorazione
+ if ( ! m_pMchMgr->SetCalcTool( m_TParams.m_sName, m_TParams.m_sHead, m_TParams.m_nExit)) {
+ m_pMchMgr->SetLastError( 2702, "Error in SurfFinishing : Tool loading failed") ;
+ return false ;
+ }
+ // recupero i dati del portautensile
+ int nToolId = m_pMchMgr->GetCalcTool() ;
+ m_dTHoldLen = 0 ;
+ m_pGeomDB->GetInfo( nToolId, TTH_LEN, m_dTHoldLen) ;
+ m_dTHoldDiam = 0 ;
+ m_pGeomDB->GetInfo( nToolId, TTH_DIAM, m_dTHoldDiam) ;
+
+ // se necessario, eseguo concatenamento ed inserisco i percorsi sotto la geometria ausiliaria
+ if ( bChain && ! Chain( nAuxId)) {
+ m_pMchMgr->SetLastError( 2421, "Error in Pocketing : Chaining failed") ;
+ return false ;
+ }
+
+ // recupero gruppo per geometria di lavorazione (Cutter Location)
+ int nClId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_CL) ;
+ // se non c'è, lo aggiungo
+ if ( nClId == GDB_ID_NULL) {
+ nClId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ;
+ if ( nClId == GDB_ID_NULL)
+ return false ;
+ m_pGeomDB->SetName( nClId, MCH_CL) ;
+ }
+ // altrimenti lo svuoto
+ else
+ m_pGeomDB->EmptyGroup( nClId) ;
+
+ // lavoro ogni singola catena
+ bool bOk = true ;
+ int nPathId = m_pGeomDB->GetFirstGroupInGroup( nAuxId) ;
+ while ( nPathId != GDB_ID_NULL) {
+ if ( ! ProcessPath( nPathId, GDB_ID_NULL, nClId))
+ bOk = false ;
+ nPathId = m_pGeomDB->GetNextGroup( nPathId) ;
+ }
+ if ( ! bOk)
+ return false ;
+
+ // assegno ingombri dei vari percorsi di lavorazione e della lavorazione nel suo complesso
+ CalcAndSetBBox( nClId) ;
+
+ // eseguo aggiornamento assi macchina e collegamento con operazione precedente
+ if ( ! Update( bPostApply))
+ return false ;
+
+ // aggiorno stato della lavorazione
+ m_nStatus = ( bPostApply ? MCH_ST_OK : MCH_ST_NO_POSTAPPL) ;
+ // dichiaro successiva da aggiornare
+ UpdateFollowingOperationsStatus( MCH_ST_OTH_MODIF) ;
+
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::Update( bool bPostApply)
+{
+ // verifico validità gestore DB geometrico e Id del gruppo
+ if ( m_pGeomDB == nullptr || ! m_pGeomDB->ExistsObj( m_nOwnerId))
+ return false ;
+
+ // se lavorazione vuota, esco
+ if ( m_nPaths == 0) {
+ LOG_WARN( GetEMkLogger(), "Warning in SurfFinishing : No machinable path")
+ return true ;
+ }
+
+ // imposto eventuale asse bloccato da lavorazione
+ if ( ! m_Params.m_sBlockedAxis.empty()) {
+ string sAxis, sVal ;
+ Split( m_Params.m_sBlockedAxis, "=", true, sAxis, sVal) ;
+ double dVal = 0 ;
+ FromString( sVal, dVal) ;
+ m_pMchMgr->ClearRotAxisBlock() ;
+ m_pMchMgr->SetRotAxisBlock( sAxis, dVal) ;
+ }
+
+ // calcolo gli assi macchina
+ string sHint = ExtractHint( m_Params.m_sUserNotes) ;
+ if ( ! m_Params.m_sInitAngs.empty())
+ sHint = m_Params.m_sInitAngs ;
+ if ( ! CalculateAxesValues( sHint)) {
+ string sInfo = m_pMchMgr->GetOutstrokeInfo() ;
+ if ( sInfo.empty())
+ m_pMchMgr->SetLastError( 2711, "Error in SurfFinishing : axes values not calculable") ;
+ else
+ m_pMchMgr->SetLastError( 2712, "Error in SurfFinishing : outstroke ") ;
+ return false ;
+ }
+
+ // gestione movimenti all'inizio di ogni singolo percorso di lavorazione e alla fine della lavorazione
+ if ( ! AdjustStartEndMovements()) {
+ string sInfo = m_pMchMgr->GetOutstrokeInfo() ;
+ if ( sInfo.empty())
+ m_pMchMgr->SetLastError( 2713, "Error in SurfFinishing : link movements not calculable") ;
+ else
+ m_pMchMgr->SetLastError( 2714, "Error in SurfFinishing : link outstroke ") ;
+ return false ;
+ }
+
+ // esecuzione eventuali personalizzazioni
+ if ( bPostApply && ! PostApply()) {
+ m_pMchMgr->SetLastError( 2715, "Error in SurfFinishing : post apply not calculable") ;
+ return false ;
+ }
+
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::GetParam( int nType, bool& bVal) const
+{
+ switch ( nType) {
+ case MPA_INVERT :
+ bVal = m_Params.m_bInvert ;
+ return true ;
+ }
+ bVal = false ;
+ return false ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::GetParam( int nType, int& nVal) const
+{
+ switch ( nType) {
+ case MPA_TYPE :
+ nVal = MT_SURFFINISHING ;
+ return true ;
+ case MPA_SUBTYPE :
+ nVal = m_Params.m_nSubType ;
+ return true ;
+ case MPA_LEADINTYPE :
+ nVal = m_Params.m_nLeadInType ;
+ return true ;
+ case MPA_LEADLINKTYPE :
+ nVal = m_Params.m_nLeadLinkType ;
+ return true ;
+ case MPA_LEADOUTTYPE :
+ nVal = m_Params.m_nLeadOutType ;
+ return true ;
+ case MPA_SCC :
+ nVal = m_Params.m_nSolCh ;
+ return true ;
+ }
+ nVal = 0 ;
+ return false ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::GetParam( int nType, double& dVal) const
+{
+ switch ( nType) {
+ case MPA_SPEED :
+ dVal = GetSpeed() ;
+ return true ;
+ case MPA_FEED :
+ dVal = GetFeed() ;
+ return true ;
+ case MPA_STARTFEED :
+ dVal = GetStartFeed() ;
+ return true ;
+ case MPA_ENDFEED :
+ dVal = GetEndFeed() ;
+ return true ;
+ case MPA_TIPFEED :
+ dVal = GetTipFeed() ;
+ return true ;
+ case MPA_OFFSR :
+ dVal =GetOffsR() ;
+ return true ;
+ case MPA_STARTPOS :
+ dVal = m_Params.m_dStartPos ;
+ return true ;
+ case MPA_SIDESTEP :
+ dVal = m_Params.m_dSideStep ;
+ return true ;
+ case MPA_SIDEANGLE :
+ dVal = m_Params.m_dSideAngle ;
+ return true ;
+ case MPA_LITANG :
+ dVal = m_Params.m_dLiTang ;
+ return true ;
+ case MPA_LIPERP :
+ dVal = m_Params.m_dLiPerp ;
+ return true ;
+ case MPA_LOTANG :
+ dVal = m_Params.m_dLoTang ;
+ return true ;
+ case MPA_LOPERP :
+ dVal = m_Params.m_dLoPerp ;
+ return true ;
+ case MPA_APPROX :
+ dVal = m_Params.m_dApprox ;
+ return true ;
+ }
+ dVal = 0 ;
+ return false ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::GetParam( int nType, string& sVal) const
+{
+ switch ( nType) {
+ case MPA_NAME :
+ sVal = m_Params.m_sName ;
+ return true ;
+ case MPA_TOOL :
+ sVal = m_Params.m_sToolName ;
+ return true ;
+ case MPA_DEPTH_STR :
+ sVal = m_Params.m_sDepth ;
+ return true ;
+ case MPA_TUUID :
+ sVal = ToString( m_Params.m_ToolUuid) ;
+ return true ;
+ case MPA_UUID :
+ sVal = ToString( m_Params.m_Uuid) ;
+ return true ;
+ case MPA_SYSNOTES :
+ sVal = m_Params.m_sSysNotes ;
+ return true ;
+ case MPA_USERNOTES :
+ sVal = m_Params.m_sUserNotes ;
+ return true ;
+ case MPA_INITANGS :
+ sVal = m_Params.m_sInitAngs ;
+ return true ;
+ case MPA_BLOCKEDAXIS :
+ sVal = m_Params.m_sBlockedAxis ;
+ return true ;
+ }
+ sVal = "" ;
+ return false ;
+}
+
+//----------------------------------------------------------------------------
+const ToolData&
+SurfFinishing::GetToolData( void) const
+{
+ return m_TParams ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::UpdateToolData( bool* pbChanged)
+{
+ // recupero il gestore DB utensili della macchina corrente
+ ToolsMgr* pTMgr = m_pMchMgr->GetCurrToolsMgr() ;
+ if ( pTMgr == nullptr)
+ return false ;
+ // recupero l'utensile nel DB utensili
+ const ToolData* pTdata = pTMgr->GetTool( m_Params.m_ToolUuid) ;
+ if ( pTdata == nullptr)
+ return false ;
+ // verifico se sono diversi (ad esclusione del nome)
+ m_TParams.m_sName = pTdata->m_sName ;
+ bool bChanged = ! SameTool( m_TParams, *pTdata) ;
+ // aggiorno comunque i parametri
+ m_TParams = *pTdata ;
+ // eventuali segnalazioni
+ if ( ! EqualNoCase( m_Params.m_sToolName, m_TParams.m_sName)) {
+ string sLog = "Warning in SurfFinishing : tool name changed (" +
+ m_Params.m_sToolName + "->" + m_TParams.m_sName + ")" ;
+ LOG_INFO( GetEMkLogger(), sLog.c_str()) ;
+ m_Params.m_sToolName = m_TParams.m_sName ;
+ }
+ if ( bChanged) {
+ string sLog = "Warning in SurfFinishing : tool data changed (" +
+ m_Params.m_sToolName + ")" ;
+ LOG_INFO( GetEMkLogger(), sLog.c_str()) ;
+ }
+ // se definito parametro di ritorno, lo assegno
+ if ( pbChanged != nullptr)
+ *pbChanged = bChanged ;
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::GetGeometry( SELVECTOR& vIds) const
+{
+ // restituisco l'elenco delle entità
+ vIds = m_vId ;
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::AdjustEndPointForAxesCalc( const CamData* pCamData, Point3d& ptP) const
+{
+ // compenso il raggio dell'utensile
+ ptP += pCamData->GetCorrDir() * ( m_TParams.m_dDiam / 2) ;
+
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::VerifyGeometry( SelData Id, int& nSubs)
+{
+ // ammessi : curve o superfici
+
+ // per ora accetto solo curve
+ const ICurve* pCurve = nullptr ;
+ const IGeoObj* pGObj = m_pGeomDB->GetGeoObj( Id.nId) ;
+ // se direttamente la curva
+ if ( Id.nSub == SEL_SUB_ALL) {
+ pCurve = ::GetCurve( m_pGeomDB->GetGeoObj( Id.nId)) ;
+ if ( pCurve != nullptr) {
+ if ( pCurve->GetType() == CRV_COMPO)
+ nSubs = ::GetCurveComposite( pCurve)->GetCurveCount() ;
+ else
+ nSubs = 0 ;
+ }
+ }
+ // altrimenti sottocurva di composita
+ else {
+ const ICurveComposite* pCompo = GetCurveComposite( m_pGeomDB->GetGeoObj( Id.nId)) ;
+ if ( pCompo != nullptr)
+ pCurve = pCompo->GetCurve( Id.nSub) ;
+ nSubs = 0 ;
+ }
+ return ( pCurve != nullptr) ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::GetCurves( SelData Id, ICURVEPLIST& lstPC)
+{
+ // ammessi : curve
+ const IGeoObj* pGObj = m_pGeomDB->GetGeoObj( Id.nId) ;
+ if ( pGObj == nullptr)
+ return false ;
+ // ne recupero il riferimento globale
+ Frame3d frGlob ;
+ if ( ! m_pGeomDB->GetGlobFrame( Id.nId, frGlob))
+ return false ;
+ // se curva
+ if ( ( pGObj->GetType() & GEO_CURVE) != 0) {
+ PtrOwner pCurve ;
+ // se direttamente curva
+ if ( Id.nSub == SEL_SUB_ALL) {
+ // recupero la curva
+ const ICurve* pOriCurve = ::GetCurve( pGObj) ;
+ if ( pOriCurve == nullptr)
+ return false ;
+ // la duplico
+ pCurve.Set( pOriCurve->Clone()) ;
+ // se estrusione mancante, imposto default
+ Vector3d vtExtr ;
+ if ( ! pCurve->GetExtrusion( vtExtr) || vtExtr.IsSmall())
+ pCurve->SetExtrusion( Z_AX) ;
+ }
+ // altrimenti sottocurva di composita
+ else {
+ // recupero la composita
+ const ICurveComposite* pCompo = GetCurveComposite( pGObj) ;
+ if ( pCompo == nullptr)
+ return false ;
+ // recupero la curva semplice
+ const ICurve* pOriCurve = ::GetCurve( pCompo->GetCurve( Id.nSub)) ;
+ if ( pOriCurve == nullptr)
+ return false ;
+ // la duplico
+ pCurve.Set( pOriCurve->Clone()) ;
+ // recupero estrusione e spessore
+ Vector3d vtExtr ;
+ if ( ! pCompo->GetExtrusion( vtExtr) || vtExtr.IsSmall())
+ vtExtr = Z_AX ;
+ pCurve->SetExtrusion( vtExtr) ;
+ double dThick ;
+ if ( pCompo->GetThickness( dThick))
+ pCurve->SetThickness( dThick) ;
+ }
+ if ( IsNull( pCurve))
+ return false ;
+ // la porto in globale
+ pCurve->ToGlob( frGlob) ;
+ // la restituisco
+ lstPC.emplace_back( Release( pCurve)) ;
+ return true ;
+ }
+ else
+ return false ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::Chain( int nGrpDestId)
+{
+ // vettore puntatori alle curve
+ ICURVEPOVECTOR vpCrvs ;
+ vpCrvs.reserve( m_vId.size()) ;
+ // vettore selettori delle curve originali
+ SELVECTOR vInds ;
+ // recupero tutte le curve e le porto in globale
+ for ( const auto& Id : m_vId) {
+ // prendo le curve
+ ICURVEPLIST lstPC ;
+ if ( ! GetCurves( Id, lstPC)) {
+ string sOut = "Entity " + ToString( Id) + " skipped by Pocketing" ;
+ LOG_INFO( GetEMkLogger(), sOut.c_str()) ;
+ }
+ for ( auto pCrv : lstPC) {
+ vpCrvs.emplace_back( pCrv) ;
+ vInds.emplace_back( Id) ;
+ }
+ }
+ // preparo i dati per il concatenamento
+ bool bFirst = true ;
+ Point3d ptNear = ORIG ;
+ double dToler = 10 * EPS_SMALL ;
+ ChainCurves chainC ;
+ chainC.Init( true, dToler, int( vpCrvs.size())) ;
+ for ( size_t i = 0 ; i < vpCrvs.size() ; ++ i) {
+ // recupero la curva e il suo riferimento
+ ICurve* pCrv = vpCrvs[i] ;
+ if ( pCrv == nullptr)
+ continue ;
+ // recupero i dati della curva necessari al concatenamento e li assegno
+ Point3d ptStart, ptEnd ;
+ Vector3d vtStart, vtEnd ;
+ if ( ! pCrv->GetStartPoint( ptStart) || ! pCrv->GetStartDir( vtStart) ||
+ ! pCrv->GetEndPoint( ptEnd) || ! pCrv->GetEndDir( vtEnd))
+ return false ;
+ if ( ! chainC.AddCurve( int( i + 1), ptStart, vtStart, ptEnd, vtEnd))
+ return false ;
+ // se prima curva, assegno inizio della ricerca
+ if ( bFirst) {
+ ptNear = ptStart + 10 * EPS_SMALL * vtStart ;
+ bFirst = false ;
+ }
+ }
+ // recupero i percorsi concatenati
+ int nCount = 0 ;
+ INTVECTOR vnId2 ;
+ while ( chainC.GetChainFromNear( ptNear, false, vnId2)) {
+ // creo una curva composita
+ PtrOwner pCrvCompo( CreateCurveComposite()) ;
+ if ( IsNull( pCrvCompo))
+ return false ;
+ // estrusione e spessore
+ Vector3d vtExtr = Z_AX ;
+ double dThick = 0 ;
+ // vettore Id originali
+ SELVECTOR vId2 ;
+ vId2.reserve( vnId2.size()) ;
+ // recupero le curve semplici e le inserisco nella curva composita
+ for ( size_t i = 0 ; i < vnId2.size() ; ++ i) {
+ int nId = abs( vnId2[i]) - 1 ;
+ bool bInvert = ( vnId2[i] < 0) ;
+ vId2.emplace_back( vInds[nId]) ;
+ // recupero la curva
+ ICurve* pCrv = vpCrvs[nId] ;
+ // se necessario, la inverto
+ if ( bInvert)
+ pCrv->Invert() ;
+ // recupero eventuali estrusione e spessore
+ Vector3d vtTemp ;
+ if ( pCrv->GetExtrusion( vtTemp)) {
+ vtExtr = vtTemp ;
+ double dTemp ;
+ if ( pCrv->GetThickness( dTemp) && abs( dTemp) > abs( dThick))
+ dThick = dTemp ;
+ }
+ // la aggiungo alla curva composta
+ if ( ! pCrvCompo->AddCurve( ::Release( vpCrvs[nId]), true, dToler))
+ return false ;
+ }
+ // se non sono state inserite curve, vado oltre
+ if ( pCrvCompo->GetCurveCount() == 0)
+ continue ;
+ // imposto estrusione e spessore
+ pCrvCompo->SetExtrusion( vtExtr) ;
+ pCrvCompo->SetThickness( dThick) ;
+ // aggiorno il nuovo punto vicino
+ pCrvCompo->GetEndPoint( ptNear) ;
+ // se utile, approssimo con archi
+ if ( ! ApproxWithArcsIfUseful( pCrvCompo))
+ return false ;
+ // creo nuovo gruppo
+ int nPathId = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrpDestId, Frame3d()) ;
+ if ( nPathId == GDB_ID_NULL)
+ return false ;
+ m_pGeomDB->SetName( nPathId, MCH_PATH + ToString( ++ nCount)) ;
+ m_pGeomDB->SetInfo( nPathId, KEY_IDS, ToString( vId2)) ;
+ // inserisco la curva composita nel gruppo destinazione
+ int nNewId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPathId, ::Release( pCrvCompo)) ;
+ if ( nNewId == GDB_ID_NULL)
+ return false ;
+ }
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::ProcessPath( int nPathId, int nPvId, int nClId)
+{
+ // recupero gruppo per geometria temporanea
+ const string GRP_TEMP = "Temp" ;
+ int nTempId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, GRP_TEMP) ;
+ // se non c'è, lo aggiungo
+ if ( nTempId == GDB_ID_NULL) {
+ nTempId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ;
+ if ( nTempId == GDB_ID_NULL)
+ return false ;
+ m_pGeomDB->SetName( nTempId, GRP_TEMP) ;
+ }
+ // altrimenti lo svuoto
+ else
+ m_pGeomDB->EmptyGroup( nTempId) ;
+ // in ogni caso lo dichiaro temporaneo e non visibile
+ m_pGeomDB->SetLevel( nTempId, GDB_LV_TEMP) ;
+ m_pGeomDB->SetStatus( nTempId, GDB_ST_OFF) ;
+
+ // verifico sia una curva chiusa (deve delimitare l'area da svuotare)
+ int nCrvId = m_pGeomDB->GetFirstInGroup( nPathId) ;
+ if ( m_pGeomDB->GetGeoType( nCrvId) != CRV_COMPO)
+ return false ;
+ ICurve* pCrv = ::GetCurve( m_pGeomDB->GetGeoObj( nCrvId)) ;
+ if ( pCrv == nullptr || ! pCrv->IsClosed()) {
+ m_pMchMgr->SetLastError( 2402, "Error in Pocketing : Open Contour") ;
+ return false ;
+ }
+
+ // copio la curva composita da elaborare
+ int nCopyId = m_pGeomDB->CopyGlob( nCrvId, GDB_ID_NULL, nTempId) ;
+ if ( nCopyId == GDB_ID_NULL)
+ return false ;
+ ICurveComposite* pCompo = GetCurveComposite( m_pGeomDB->GetGeoObj( nCopyId)) ;
+
+ // recupero estrusione e spessore
+ Vector3d vtExtr = Z_AX ;
+ pCompo->GetExtrusion( vtExtr) ;
+ double dThick ;
+ pCompo->GetThickness( dThick) ;
+
+ // verifico sia piana e sistemo senso antiorario visto dalla direzione di estrusione
+ Plane3d plPlane ; double dArea ;
+ if ( ! pCompo->GetArea( plPlane, dArea)) {
+ m_pMchMgr->SetLastError( 2403, "Error in Pocketing : Contour Not Flat") ;
+ return false ;
+ }
+ if ( abs( plPlane.GetVersN() * vtExtr) < cos( 10 * EPS_ANG_SMALL)) {
+ m_pMchMgr->SetLastError( 2404, "Error in Pocketing : Tool Dir not perpendicular to Flat Area") ;
+ return false ;
+ }
+ if ( plPlane.GetVersN() * vtExtr * dArea < 0)
+ pCompo->Invert() ;
+
+ // unisco le parti allineate
+ if ( ! pCompo->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, true))
+ return false ;
+
+ // recupero il box del grezzo in globale
+ BBox3d b3Raw ;
+ if ( ! GetRawGlobBox( m_nPhase, nPathId, 0.5 * m_TParams.m_dTDiam, b3Raw) || b3Raw.IsEmpty()) {
+ m_pMchMgr->SetLastError( 2405, "Error in Pocketing : Empty RawBox") ;
+ return false ;
+ }
+
+ // valuto l'espressione dell'affondamento
+ ExeLuaSetGlobNumVar( "TH", abs( dThick)) ;
+ double dDepth ;
+ string sMyDepth = m_Params.m_sDepth ;
+ if ( ! ExeLuaEvalNumExpr( ToUpper( sMyDepth), &dDepth)) {
+ m_pMchMgr->SetLastError( 2406, "Error in Pocketing : Depth not computable") ;
+ return false ;
+ }
+
+ // recupero nome del path
+ string sPathName ;
+ m_pGeomDB->GetName( nPathId, sPathName) ;
+
+ // assegno il versore fresa
+ Vector3d vtTool = vtExtr ;
+
+ // se richiesta lavorazione
+ if ( nClId != GDB_ID_NULL) {
+ // creo gruppo per geometria di lavorazione del percorso
+ int nPxId = m_pGeomDB->AddGroup( GDB_ID_NULL, nClId, Frame3d()) ;
+ if ( nPxId == GDB_ID_NULL)
+ return false ;
+ m_pGeomDB->SetName( nPxId, sPathName) ;
+ m_pGeomDB->SetMaterial( nPxId, BLUE) ;
+
+ // verifico se archi vanno approssimati con segmenti di retta
+ int nSplitArcs = m_pMchMgr->GetCurrMachiningsMgr()->GetSplitArcs() ;
+ bool bSplitArcs = ( nSplitArcs == SPLAR_ALWAYS ||
+ ( nSplitArcs == SPLAR_NO_XY_PLANE && ! vtExtr.IsZplus()) ||
+ ( nSplitArcs == SPLAR_GEN_PLANE && vtExtr.IsGeneric())) ;
+
+ // assegno il vettore estrazione al gruppo del percorso
+ m_pGeomDB->SetInfo( nPxId, KEY_EXTR, vtTool) ;
+
+ // Imposto dati comuni
+ SetPathId( nPxId) ;
+ SetToolDir( vtTool) ;
+
+ // Eseguo la lavorazione a seconda del tipo
+ double dElev = dDepth ;
+ if ( ! AddZigZag( pCompo, vtTool, vtExtr, dDepth, dElev, bSplitArcs))
+ return false ;
+ }
+
+ // incremento numero di percorsi
+ ++ m_nPaths ;
+
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::AddZigZag( const ICurveComposite* pCompo, const Vector3d& vtTool, const Vector3d& vtExtr,
+ double dDepth, double dElev, bool bSplitArcs)
+{
+ // recupero distanze di sicurezza
+ double dSafeZ = m_pMchMgr->GetCurrMachiningsMgr()->GetSafeZ() ;
+ double dSafeAggrBottZ = m_pMchMgr->GetCurrMachiningsMgr()->GetSafeAggrBottZ() ;
+ // lunghezza di approccio/retrazione
+ double dAppr = m_Params.m_dStartPos ;
+
+ // calcolo curva offsettata del raggio utensile + sovramateriale + extra
+ double dTRad = 0.5 * m_TParams.m_dDiam ;
+ double dOffs = dTRad ;
+ double dExtra = min( 0.1 * m_TParams.m_dDiam, 2.0) ;
+ OffsetCurve OffsCrv ;
+ if ( ! OffsCrv.Make( pCompo, - ( dOffs + dExtra), ICurve::OFF_FILLET)) {
+ m_pMchMgr->SetLastError( 2412, "Error in Pocketing : Offset not computable") ;
+ return false ;
+ }
+
+ // ciclo sulle curve risultanti
+ bool bStart = true ;
+ while ( OffsCrv.GetCurveCount() > 0) {
+
+ // recupero la prima curva di offset
+ PtrOwner pOffs( CreateCurveComposite()) ;
+ if ( IsNull( pOffs) || ! pOffs->AddCurve( OffsCrv.GetLongerCurve())) {
+ m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ;
+ return false ;
+ }
+
+ // determino il riferimento di base e il box della svuotatura
+ Frame3d frPocket ;
+ Point3d ptCen ; pCompo->GetCentroid( ptCen) ;
+ frPocket.Set( ptCen, vtExtr) ;
+ frPocket.Rotate( ptCen, vtExtr, m_Params.m_dSideAngle) ;
+ pOffs->ToLoc( frPocket) ;
+
+ // calcolo i percorsi di svuotatura
+ ICRVCOMPOPOVECTOR vpCrvs ;
+ if ( ! CalcZigZag( pOffs, vpCrvs))
+ return false ;
+
+ // li correggo per non interferire con le superfici
+ PtrOwner pCAvTlStm( CreateCAvToolSurfTm()) ;
+ if ( IsNull( pCAvTlStm))
+ return false ;
+ pCAvTlStm->SetStdTool( m_TParams.m_dLen + GetOffsR(),
+ m_TParams.m_dDiam / 2 + GetOffsR(),
+ m_TParams.m_dCornRad + GetOffsR()) ;
+ // recupero le superfici TriMesh dei pezzi in lavorazione
+ int nRawId = m_pMchMgr->GetFirstRawPart() ;
+ int nPartId = m_pMchMgr->GetFirstPartInRawPart( nRawId) ;
+ int nLayId = m_pGeomDB->GetFirstGroupInGroup( nPartId) ;
+ int nEntId = m_pGeomDB->GetFirstInGroup( nLayId) ;
+ while ( nEntId != GDB_ID_NULL) {
+ if ( m_pGeomDB->GetGeoType( nEntId) == SRF_TRIMESH)
+ break ;
+ nEntId = m_pGeomDB->GetNext( nEntId) ;
+ }
+ if ( nEntId != GDB_ID_NULL) {
+ const ISurfTriMesh* pStm = GetSurfTriMesh( m_pGeomDB->GetGeoObj( nEntId)) ;
+ if ( pStm == nullptr)
+ return false ;
+ // recupero il riferimento della superficie
+ Frame3d frSurf ;
+ if ( ! m_pGeomDB->GetGlobFrame( nEntId, frSurf))
+ return false ;
+ // approssimo la curva con una polilinea
+ PolyLine PL ;
+ if ( ! vpCrvs[0]->ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
+ return false ;
+ // eventuale aggiunta di punti per garantire max distanza
+ const double MIN_DIST = 1. ;
+ const double MAX_DIST = 50. ;
+ double dDist = Clamp( m_TParams.m_dDiam / 2, MIN_DIST, MAX_DIST) ;
+ if ( ! PL.AdjustForMaxSegmentLen( dDist))
+ return false ;
+ // porto nel riferimento della superficie
+ PL.LocToLoc( frPocket, frSurf) ;
+ // porto i dati geometrici in locale alla superficie
+ Vector3d vtAxL = vtTool ;
+ vtAxL.ToLoc( frSurf) ;
+ Vector3d vtMoveL = vtAxL ;
+ // traslo della lunghezza utensile diminuita dell'affondamento
+ PL.Translate( vtAxL * ( m_TParams.m_dLen - dDepth)) ;
+ // imposto dati
+ pCAvTlStm->SetSurfTm( *pStm) ;
+ // eseguo CAv
+ if ( ! pCAvTlStm->TestPath( PL.GetUPointList(), vtAxL, vtMoveL, m_Params.m_dApprox))
+ return false ;
+ // contro-traslo della lunghezza utensile
+ PL.Translate( - vtAxL * m_TParams.m_dLen) ;
+ // riporto la polilinea nel riferimento della curva
+ PL.LocToLoc( frSurf, frPocket) ;
+ // elimino i punti allineati
+ PL.RemoveAlignedPoints( 0.8 * m_Params.m_dApprox) ;
+ // creo una curva composita a partire dalla polilinea
+ PtrOwner< ICurveComposite> pCompo( CreateCurveComposite()) ;
+ if ( IsNull( pCompo) || ! pCompo->FromPolyLine( PL))
+ return false ;
+ // sostituisco la vecchia curva con la nuova
+ vpCrvs[0].Set( Release( pCompo )) ;
+ }
+ // ciclo sui percorsi
+ for ( int k = 0 ; k < int( vpCrvs.size()) ; ++ k) {
+ // ciclo sulle curve elementari
+ int nMaxInd = vpCrvs[k]->GetCurveCount() - 1 ;
+ for ( int i = 0 ; i <= nMaxInd ; ++ i) {
+ // curva corrente
+ const ICurve* pCrvC = vpCrvs[k]->GetCurve( i) ;
+ // copio la curva
+ PtrOwner pCurve( pCrvC->Clone()) ;
+ if ( IsNull( pCurve))
+ return false ;
+ pCurve->ToGlob( frPocket) ;
+ // se prima entità
+ if ( i == 0 ) {
+ // dati inizio entità
+ Point3d ptStart ;
+ pCurve->GetStartPoint( ptStart) ;
+ Vector3d vtStart ;
+ pCurve->GetStartDir( vtStart) ;
+ // determino inizio attacco
+ Point3d ptP1 ;
+ if ( ! CalcLeadInStart( ptStart, vtStart, vtExtr, ptP1))
+ return false ;
+ // determino elevazione su inizio attacco
+ double dStElev = dElev ;
+ dStElev -= ( ptP1 - ptStart) * vtExtr ;
+ // se inizio, approccio globale al punto iniziale
+ if ( bStart) {
+ if ( ! AddApproach( ptP1, vtTool, dSafeZ, dStElev, dAppr)) {
+ m_pMchMgr->SetLastError( 2414, "Error in Pocketing : Approach not computable") ;
+ return false ;
+ }
+ bStart = false ;
+ }
+ // altrimenti, approccio di collegamento
+ else {
+ if ( ! AddLinkApproach( ptP1, vtTool, dSafeZ, dStElev, dAppr)) {
+ m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Link not computable") ;
+ return false ;
+ }
+ }
+ // aggiungo attacco
+ SetFeed( GetStartFeed()) ;
+ if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtExtr)) {
+ m_pMchMgr->SetLastError( 2415, "Error in Pocketing : LeadIn not computable") ;
+ return false ;
+ }
+ }
+ // elaborazioni sulla curva corrente
+ if ( pCurve->GetType() == CRV_LINE) {
+ ICurveLine* pLine = GetCurveLine( pCurve) ;
+ Point3d ptP3 = pLine->GetEnd() ;
+ SetFeed( GetFeed()) ;
+ if ( AddLinearMove( ptP3) == GDB_ID_NULL)
+ return false ;
+ }
+ else if ( pCurve->GetType() == CRV_ARC) {
+ ICurveArc* pArc = GetCurveArc( pCurve) ;
+ Point3d ptCen = pArc->GetCenter() ;
+ double dAngCen = pArc->GetAngCenter() ;
+ Vector3d vtN = pArc->GetNormVersor() ;
+ Point3d ptP3 ;
+ pArc->GetEndPoint( ptP3) ;
+ SetFeed( GetFeed()) ;
+ if ( AddArcMove( ptP3, ptCen, dAngCen, vtN) == GDB_ID_NULL)
+ return false ;
+ }
+ // se ultima entità
+ if ( i == nMaxInd) {
+ // dati fine entità
+ Point3d ptEnd ;
+ pCurve->GetEndPoint( ptEnd) ;
+ Vector3d vtEnd ;
+ pCurve->GetEndDir( vtEnd) ;
+ // aggiungo uscita
+ double dEndElev = dElev ;
+ Point3d ptP1 ;
+ SetFeed( GetEndFeed()) ;
+ if ( ! AddLeadOut( ptEnd, vtEnd, vtExtr, ptP1)) {
+ m_pMchMgr->SetLastError( 2416, "Error in Pocketing : LeadOut not computable") ;
+ return false ;
+ }
+ // se non è ultimo tratto, aggiungo retrazione di collegamento
+ if ( k < int( vpCrvs.size()) - 1) {
+ if ( ! AddLinkRetract( ptP1, vtTool, dSafeZ, dEndElev, dAppr)) {
+ m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Link not computable") ;
+ return false ;
+ }
+ }
+ // altrimenti aggiungo retrazione finale
+ else {
+ if ( ! AddRetract( ptP1, vtTool, dSafeZ, dEndElev, dAppr)) {
+ m_pMchMgr->SetLastError( 2418, "Error in Pocketing : Retract not computable") ;
+ return false ;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::CalcZigZag( const ICurveComposite* pOffs,
+ ICRVCOMPOPOVECTOR& vpCrvs)
+{
+ // ingombro del contorno offsettato
+ BBox3d b3Pocket ;
+ pOffs->GetLocalBBox( b3Pocket) ;
+ Point3d ptMin ; double dDimX, dDimY, dDimZ ;
+ b3Pocket.GetMinDim( ptMin, dDimX, dDimY, dDimZ) ;
+
+ // lunghezza del contorno offsettato
+ double dLen ; pOffs->GetLength( dLen) ;
+
+ // passi in Y
+ int nYStep = static_cast( ceil( ( dDimY - 20 * EPS_SMALL) / GetSideStep())) ;
+ double dYStep = ( nYStep > 0 ? ( dDimY - 20 * EPS_SMALL) / nYStep : 0) ;
+
+ // tratto valido
+ struct Section {
+ bool bActive ;
+ Point3d ptS ;
+ Point3d ptE ;
+ double dOs ;
+ double dOe ;
+ } ;
+ // raccolta di tratti
+ typedef std::vector> VECVECSECT ;
+
+ VECVECSECT vvSec ;
+ vvSec.resize( nYStep + 1) ;
+
+ // calcolo le linee di svuotatura
+ int nCount = 0 ;
+ for ( int i = 0 ; i <= nYStep ; ++ i) {
+ // determino senso
+ bool bPlus = (( i % 2) == 0) ;
+ // definisco la linea
+ PtrOwner pLine( CreateCurveLine()) ;
+ const double EXP_LEN = 1.0 ;
+ Point3d ptStart( ptMin.x - EXP_LEN, ptMin.y + 10 * EPS_SMALL + i * dYStep, ptMin.z + dDimZ) ;
+ if ( IsNull( pLine) || ! pLine->SetPVL( ptStart, X_AX, dDimX + 2 * EXP_LEN)) {
+ m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ;
+ return false ;
+ }
+ // calcolo la classificazione della curva rispetto al contorno esterno offsettato
+ IntersCurveCurve intCC( *pLine, *pOffs) ;
+ CRVCVECTOR ccClass ;
+ if ( ! intCC.GetCurveClassification( 0, ccClass)) {
+ m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ;
+ return false ;
+ }
+ // determino gli intervalli di curva da conservare
+ Intervals inOk ;
+ for ( auto& ccOne : ccClass) {
+ if ( ccOne.nClass == CRVC_IN || ccOne.nClass == CRVC_ON_P || ccOne.nClass == CRVC_ON_M)
+ inOk.Add( ccOne.dParS, ccOne.dParE) ;
+ }
+ // inserisco i tratti validi (secondo X+ i pari, secondo X- i dispari)
+ double dParS, dParE ;
+ bool bFound = ( bPlus ? inOk.GetFirst( dParS, dParE) : inOk.GetLast( dParE, dParS)) ;
+ while ( bFound) {
+ // determino i dati della sezione
+ Section Sect ;
+ Sect.bActive = true ;
+ pLine->GetPointD1D2( dParS, ICurve::FROM_PLUS, Sect.ptS) ;
+ pLine->GetPointD1D2( dParE, ICurve::FROM_MINUS, Sect.ptE) ;
+ pOffs->GetParamAtPoint( Sect.ptS, Sect.dOs, 10 * EPS_SMALL) ;
+ pOffs->GetParamAtPoint( Sect.ptE, Sect.dOe, 10 * EPS_SMALL) ;
+ // inserisco nel contenitore
+ vvSec[i].emplace_back( Sect) ;
+ ++ nCount ;
+ // recupero successivo intervallo
+ bFound = ( bPlus ? inOk.GetNext( dParS, dParE) : inOk.GetPrev( dParE, dParS)) ;
+ }
+ }
+
+ // dominio del contorno
+ double dUmin, dUmax ;
+ pOffs->GetDomain( dUmin, dUmax) ;
+ double dUspan = dUmax - dUmin ;
+
+ // creo i percorsi di svuotatura
+ vpCrvs.reserve( nCount) ;
+ int nI = -1, nJ = -1 ;
+ while ( true) {
+ // se sezione non valida
+ if ( nI < 0 || nJ < 0) {
+ // ricerco la prima valida
+ for ( int k = 0 ; k < int( vvSec.size()) && nI < 0 ; ++ k) {
+ for ( int l = 0 ; l < int( vvSec[k].size()) && nJ < 0 ; ++ l) {
+ if ( vvSec[k][l].bActive) {
+ nI = k ;
+ nJ = l ;
+ }
+ }
+ }
+ // se trovata, creo nuova curva composita
+ if ( nI >= 0 && nJ >= 0) {
+ // creo la curva
+ vpCrvs.emplace_back( CreateCurveComposite()) ;
+ // aggiungo punto iniziale
+ vpCrvs.back()->AddPoint( vvSec[nI][nJ].ptS) ;
+ }
+ // altrimenti, esco
+ else
+ break ;
+ }
+ // determino senso
+ bool bPlus = (( nI % 2) == 0) ;
+ // aggiungo la sezione alla curva
+ Section& Sec = vvSec[nI][nJ] ;
+ Sec.bActive = false ;
+ vpCrvs.back()->AddLine( vvSec[nI][nJ].ptE) ;
+ // cerco nella stessa fila o in quella successiva sezione successiva raccordabile tramite il contorno
+ double dUstart = Sec.dOe ;
+ double dUref = ( bPlus ? INFINITO : - INFINITO) ;
+ int nNextI = -1 ;
+ int nNextJ = -1 ;
+ int li = nJ + 1 ;
+ for ( int k = nI ; k <= nI + 1 && k < int( vvSec.size()) ; ++ k) {
+ for ( int l = li ; l < int( vvSec[k].size()) ; ++ l) {
+ if ( ! vvSec[k][l].bActive)
+ continue ;
+ double dU = vvSec[k][l].dOs ;
+ if ( bPlus) {
+ if ( dU < dUstart)
+ dU += dUspan ;
+ if ( dU < dUref) {
+ dUref = dU ;
+ nNextI = k ;
+ nNextJ = l ;
+ }
+ }
+ else {
+ if ( dU > dUstart)
+ dU -= dUspan ;
+ if ( dU > dUref) {
+ dUref = dU ;
+ nNextI = k ;
+ nNextJ = l ;
+ }
+ }
+ }
+ li = 0 ;
+ }
+ // se trovato, aggiungo il tratto di contorno e continuo
+ if ( nNextI != -1) {
+ PtrOwner pCopy ;
+ if ( bPlus) {
+ if ( dUref > dUmax)
+ dUref -= dUspan ;
+ pCopy.Set( pOffs->CopyParamRange( dUstart, dUref)) ;
+ if ( ! IsNull( pCopy)) {
+ double dCLen ; pCopy->GetLength( dCLen) ;
+ if ( dCLen > 0.5 * dLen) {
+ pCopy.Set( pOffs->CopyParamRange( dUref, dUstart)) ;
+ if ( ! IsNull( pCopy))
+ pCopy->Invert() ;
+ }
+ }
+ }
+ else {
+ if ( dUref < dUmin)
+ dUref += dUspan ;
+ pCopy.Set( pOffs->CopyParamRange( dUref, dUstart)) ;
+ if ( ! IsNull( pCopy)) {
+ pCopy->Invert() ;
+ double dCLen ; pCopy->GetLength( dCLen) ;
+ if ( dCLen > 0.5 * dLen)
+ pCopy.Set( pOffs->CopyParamRange( dUstart, dUref)) ;
+ }
+ }
+ BBox3d b3Copy ;
+ if ( ! IsNull( pCopy))
+ pCopy->GetLocalBBox( b3Copy) ;
+ if ( ! b3Copy.IsEmpty() && ( b3Copy.GetMax().y - b3Copy.GetMin().y) < dYStep + 10 * EPS_SMALL) {
+ vpCrvs.back()->AddCurve( Release( pCopy)) ;
+ nI = nNextI ;
+ nJ = nNextJ ;
+ }
+ else {
+ nI = -1 ;
+ nJ = -1 ;
+ }
+ }
+ else {
+ nI = -1 ;
+ nJ = -1 ;
+ }
+ }
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::AddApproach( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dElev, double dAppr)
+{
+ SetFlag( 1) ;
+ // se sopra attacco c'è spazio per sicurezza o approccio
+ double dSafeDist = dSafeZ ;
+ if ( dElev + max( dSafeDist, dAppr) > 10 * EPS_SMALL) {
+ // se distanza di sicurezza minore di distanza di inizio
+ if ( dSafeDist < dAppr + 10 * EPS_SMALL) {
+ // 1 -> punto sopra inizio
+ Point3d ptP1 = ptP + vtTool * ( dElev + dAppr) ;
+ if ( AddRapidStart( ptP1) == GDB_ID_NULL)
+ return false ;
+ }
+ else {
+ // 1a -> punto sopra inizio
+ Point3d ptP1b = ptP + vtTool * ( dElev + dAppr) ;
+ Point3d ptP1a = ptP1b + vtTool * ( dSafeDist - dAppr) ;
+ if ( ( AddRapidStart( ptP1a) == GDB_ID_NULL))
+ return false ;
+ // 1b -> punto appena sopra inizio
+ if ( ( dElev + dAppr) > EPS_SMALL) {
+ SetFlag( 0) ;
+ if ( AddRapidMove( ptP1b) == GDB_ID_NULL)
+ return false ;
+ }
+ }
+ // affondo al punto iniziale
+ SetFlag( 0) ;
+ SetFeed( GetTipFeed()) ;
+ if ( AddLinearMove( ptP) == GDB_ID_NULL)
+ return false ;
+ }
+ else {
+ // affondo diretto al punto iniziale
+ SetFlag( 0) ;
+ if ( AddRapidStart( ptP) == GDB_ID_NULL)
+ return false ;
+ }
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::AddLinkApproach( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dElev, double dAppr)
+{
+ // se sopra attacco c'è spazio per approccio
+ if ( ( dElev + dAppr) > 10 * EPS_SMALL) {
+ // 1b -> punto appena sopra inizio
+ Point3d ptP1b = ptP + vtTool * ( dElev + dAppr) ;
+ if ( ( dElev + dAppr) > EPS_SMALL) {
+ SetFlag( 0) ;
+ if ( AddRapidMove( ptP1b) == GDB_ID_NULL)
+ return false ;
+ }
+ // affondo al punto iniziale
+ SetFlag( 0) ;
+ SetFeed( GetTipFeed()) ;
+ if ( AddLinearMove( ptP) == GDB_ID_NULL)
+ return false ;
+ }
+ else {
+ // affondo diretto al punto iniziale
+ SetFlag( 0) ;
+ if ( AddRapidMove( ptP) == GDB_ID_NULL)
+ return false ;
+ }
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::AddLinkRetract( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dElev, double dAppr)
+{
+ // se sopra uscita c'è spazio per approccio
+ if ( ( dElev + dAppr) > 10 * EPS_SMALL) {
+ // 4 -> movimento di risalita sopra il punto finale
+ SetFeed( GetEndFeed()) ;
+ Point3d ptP4 = ptP + vtTool * ( dElev + dAppr) ;
+ if ( AddLinearMove( ptP4) == GDB_ID_NULL)
+ return false ;
+ }
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::AddRetract( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dElev, double dAppr)
+{
+ // se sopra uscita c'è spazio per sicurezza o approccio
+ double dSafeDist = dSafeZ ;
+ if ( dElev + max( dSafeDist, dAppr) > 10 * EPS_SMALL) {
+ if ( dSafeDist < dAppr + 10 * EPS_SMALL) {
+ // 4 -> movimento di risalita sopra il punto finale
+ SetFeed( GetEndFeed()) ;
+ Point3d ptP4 = ptP + vtTool * ( dElev + dAppr) ;
+ if ( AddLinearMove( ptP4) == GDB_ID_NULL)
+ return false ;
+ }
+ else {
+ // 4a -> movimento di risalita appena sopra il punto finale
+ Point3d ptP4a = ptP + vtTool * ( dElev + dAppr) ;
+ if ( dElev + dAppr > EPS_SMALL) {
+ SetFeed( GetEndFeed()) ;
+ if ( AddLinearMove( ptP4a) == GDB_ID_NULL)
+ return false ;
+ }
+ // 4b -> movimento di risalita sopra il punto finale
+ Point3d ptP4b = ptP4a + vtTool * ( dSafeDist - dAppr) ;
+ if ( AddRapidMove( ptP4b) == GDB_ID_NULL)
+ return false ;
+ }
+ }
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::CalcLeadInStart( const Point3d& ptStart, const Vector3d& vtStart, const Vector3d& vtN, Point3d& ptP1)
+{
+ ptP1 = ptStart ;
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::AddLeadIn( const Point3d& ptP1, const Point3d& ptStart, const Vector3d& vtStart, const Vector3d& vtN)
+{
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfFinishing::AddLeadOut( const Point3d& ptEnd, const Vector3d& vtEnd, const Vector3d& vtN, Point3d& ptP1)
+{
+ ptP1 = ptEnd ;
+ return true ;
+}
diff --git a/SurfFinishing.h b/SurfFinishing.h
new file mode 100644
index 0000000..a95468d
--- /dev/null
+++ b/SurfFinishing.h
@@ -0,0 +1,109 @@
+//----------------------------------------------------------------------------
+// EgalTech 2019-2019
+//----------------------------------------------------------------------------
+// File : SurfFinishing.h Data : 28.05.19 Versione : 2.1e5
+// Contenuto : Dichiarazione della classe SurfFinishing.
+//
+//
+//
+// Modifiche : 28.05.19 DS Creazione modulo.
+//
+//
+//----------------------------------------------------------------------------
+
+#pragma once
+
+#include "Machining.h"
+#include "SurfFinishingData.h"
+#include "ToolData.h"
+#include "MachiningConst.h"
+#include "/EgtDev/Include/EGkCurveComposite.h"
+#include "/EgtDev/Include/EgtNumUtils.h"
+
+//----------------------------------------------------------------------------
+class SurfFinishing : public Machining
+{
+ public : // IUserObj
+ SurfFinishing* Clone( void) const override ;
+ const std::string& GetClassName( void) const override ;
+ bool Dump( std::string& sOut, bool bMM = true, const char* szNewLine = "\n") const override ;
+ bool ToSave( void) const override
+ { return true ; }
+ bool Save( int nBaseId, STRVECTOR& vString) const override ;
+ bool Load( const STRVECTOR& vString, int nBaseGdbId) override ;
+
+ public : // Operation
+ int GetType( void) const override
+ { return OPER_SAWFINISHING ; }
+ bool IsEmpty( void) const override
+ { return ( m_nPaths == 0) ; }
+ bool UpdateStatus( int nModif) override
+ { m_nStatus |= nModif ; return true ; }
+
+ protected : // Operation
+ int GetSolCh( void) const override
+ { return m_Params.m_nSolCh ; }
+ bool AdjustEndPointForAxesCalc( const CamData* pCamData, Point3d& ptP) const override ;
+
+ public : // Machining
+ bool Prepare( const std::string& sSawName) override ;
+ bool SetParam( int nType, bool bVal) override ;
+ bool SetParam( int nType, int nVal) override ;
+ bool SetParam( int nType, double dVal) override ;
+ bool SetParam( int nType, const std::string& sVal) override ;
+ bool SetGeometry( const SELVECTOR& vIds) override ;
+ bool Preview( bool bRecalc) override ;
+ bool Apply( bool bRecalc, bool bPostApply) override ;
+ bool Update( bool bPostApply) override ;
+ bool GetParam( int nType, bool& bVal) const override ;
+ bool GetParam( int nType, int& nVal) const override ;
+ bool GetParam( int nType, double& dVal) const override ;
+ bool GetParam( int nType, std::string& sVal) const override ;
+ bool UpdateToolData( bool* pbChanged = nullptr) override ;
+ const ToolData& GetToolData( void) const override ;
+ bool GetGeometry( SELVECTOR& vIds) const override ;
+
+ public :
+ SurfFinishing( void) ;
+
+ private :
+ bool VerifyGeometry( SelData Id, int& nSubs) ;
+ bool GetCurves( SelData Id, ICURVEPLIST& lstPC) ;
+ bool Chain( int nGrpDestId) ;
+ bool ProcessPath( int nPathId, int nPvId, int nClId) ;
+ bool AddZigZag( const ICurveComposite* pCompo, const Vector3d& vtTool, const Vector3d& vtExtr,
+ double dDepth, double dElev, bool bSplitArcs) ;
+ bool CalcZigZag( const ICurveComposite* pOffs, ICRVCOMPOPOVECTOR& vpCrvs) ;
+ bool AddApproach( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dElev, double dAppr) ;
+ bool AddLinkApproach( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dElev, double dAppr) ;
+ bool AddLinkRetract( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dElev, double dAppr) ;
+ bool AddRetract( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dElev, double dAppr) ;
+ bool CalcLeadInStart( const Point3d& ptStart, const Vector3d& vtStart, const Vector3d& vtN, Point3d& ptP1) ;
+ bool AddLeadIn( const Point3d& ptP1, const Point3d& ptStart, const Vector3d& vtStart, const Vector3d& vtN) ;
+ bool AddLeadOut( const Point3d& ptEnd, const Vector3d& vtEnd, const Vector3d& vtN, Point3d& ptP1) ;
+
+ private :
+ double GetSpeed() const
+ { return ( IsNullAngValue( m_Params.m_dSpeed) ? m_TParams.m_dSpeed : m_Params.m_dSpeed) ; }
+ double GetFeed() const
+ { return ( IsNullLenValue( m_Params.m_dFeed) ? m_TParams.m_dFeed : m_Params.m_dFeed) ; }
+ double GetStartFeed() const
+ { return ( IsNullLenValue( m_Params.m_dStartFeed) ? m_TParams.m_dStartFeed : m_Params.m_dStartFeed) ; }
+ double GetEndFeed() const
+ { return ( IsNullLenValue( m_Params.m_dEndFeed) ? m_TParams.m_dEndFeed : m_Params.m_dEndFeed) ; }
+ double GetTipFeed() const
+ { return ( IsNullLenValue( m_Params.m_dTipFeed) ? m_TParams.m_dTipFeed : m_Params.m_dTipFeed) ; }
+ double GetOffsR() const
+ { return ( IsUnknownValue( m_Params.m_dOffsR) ? m_TParams.m_dOffsR : m_Params.m_dOffsR) ; }
+ double GetSideStep( void) const
+ { return Clamp( m_Params.m_dSideStep, std::min( 0.1 * m_TParams.m_dDiam, 1.0), m_TParams.m_dDiam) ; }
+
+ private :
+ SELVECTOR m_vId ; // identificativi entità geometriche da lavorare
+ SurfFinishingData m_Params ; // parametri lavorazione
+ ToolData m_TParams ; // parametri utensile
+ double m_dTHoldLen ; // lunghezza del porta-utensile
+ double m_dTHoldDiam ; // diametro del porta-utensile
+ int m_nStatus ; // stato di aggiornamento della lavorazione
+ int m_nPaths ; // numero di percorsi di lavoro generati
+} ;