diff --git a/Chiseling.cpp b/Chiseling.cpp index 757dd99..03ad9da 100644 --- a/Chiseling.cpp +++ b/Chiseling.cpp @@ -847,23 +847,20 @@ Chiseling::GetCurve( SelData Id) bool Chiseling::AdjustCurveFromSurf( ICurveComposite* pCrvCompo) { - // prendo il contorno - if ( ( m_TParams.m_nType & TF_SAWBLADE) == 0) { - // cerco l'estremo più alto e lo imposto come inizio - double dU = 0 ; - double dUmax = 0 ; - double dZmax = - INFINITO ; - Point3d ptP ; - while ( pCrvCompo->GetPointD1D2( dU, ICurve::FROM_MINUS, ptP)) { - if ( ptP.z > dZmax + EPS_SMALL) { - dZmax = ptP.z ; - dUmax = dU ; - } - dU += 1 ; + // cerco l'estremo più alto del contorno e lo imposto come inizio + double dU = 0 ; + double dUmax = 0 ; + double dZmax = - INFINITO ; + Point3d ptP ; + while ( pCrvCompo->GetPointD1D2( dU, ICurve::FROM_MINUS, ptP)) { + if ( ptP.z > dZmax + EPS_SMALL) { + dZmax = ptP.z ; + dUmax = dU ; } - if ( dU != 0) - pCrvCompo->ChangeStartPoint( dUmax) ; + dU += 1 ; } + if ( dU != 0) + pCrvCompo->ChangeStartPoint( dUmax) ; return true ; } diff --git a/EgtMachKernel.vcxproj b/EgtMachKernel.vcxproj index 7edbdd3..3d24985 100644 --- a/EgtMachKernel.vcxproj +++ b/EgtMachKernel.vcxproj @@ -251,6 +251,8 @@ copy $(TargetPath) \EgtProg\Dll64 + + @@ -305,6 +307,8 @@ copy $(TargetPath) \EgtProg\Dll64 + + diff --git a/EgtMachKernel.vcxproj.filters b/EgtMachKernel.vcxproj.filters index 4ada46f..efe444a 100644 --- a/EgtMachKernel.vcxproj.filters +++ b/EgtMachKernel.vcxproj.filters @@ -204,6 +204,12 @@ Source Files\Machine + + Source Files\Machinings + + + Source Files\Operations + @@ -359,6 +365,12 @@ Header Files + + Header Files + + + Header Files + diff --git a/MachMgr.h b/MachMgr.h index 1d5c64a..0ecb3ba 100644 --- a/MachMgr.h +++ b/MachMgr.h @@ -380,7 +380,7 @@ class MachMgr : public IMachMgr { m_vAxisBlock.clear() ; } bool IsKinematicRotAxisBlocked( int nInd) const ; double GetCalcRot1W( void) const ; - bool SetCalcSolCh( int nScc) ; + bool SetCalcSolCh( int nScc, bool bExact) ; bool VerifyAngleOutstroke( int nInd, double dAng) const ; bool VerifyOutstroke( double dX, double dY, double dZ, const DBLVECTOR& vAng, bool bClear, int& nStat) const ; // Operations diff --git a/MachMgrMachines.cpp b/MachMgrMachines.cpp index a88a5eb..a990f39 100644 --- a/MachMgrMachines.cpp +++ b/MachMgrMachines.cpp @@ -428,13 +428,13 @@ MachMgr::IsKinematicRotAxisBlocked( int nInd) const //---------------------------------------------------------------------------- bool -MachMgr::SetCalcSolCh( int nScc) +MachMgr::SetCalcSolCh( int nScc, bool bExact) { Machine* pMch = GetCurrMachine() ; if ( pMch == nullptr) return false ; // imposto il criterio di scelta della soluzione - return pMch->SetSolCh( nScc) ; + return pMch->SetSolCh( nScc, bExact) ; } //---------------------------------------------------------------------------- diff --git a/Machine.h b/Machine.h index 626a197..eb90497 100644 --- a/Machine.h +++ b/Machine.h @@ -95,7 +95,7 @@ class Machine bool FreeKinematicRotAxis( int nId) ; bool IsKinematicRotAxisBlocked( int nInd) const ; bool GetKinematicRotAxisBlocked( int nInd, std::string& sName, double& dVal) const ; - bool SetSolCh( int nScc) ; + bool SetSolCh( int nScc, bool bExact) ; int GetCurrLinAxes( void) const ; int GetCurrRotAxes( void) const ; bool GetCurrAxisName( int nInd, std::string& sAxName) const ; @@ -215,7 +215,7 @@ class Machine bool GetDirection( const Vector3d& vtDir, const DBLVECTOR& vAng, Vector3d& vtNew) const ; bool GetBackDirection( const Vector3d& vtDir, const DBLVECTOR& vAng, Vector3d& vtNew) const ; bool GetSccDir( int nSolCh, const Vector3d& vtDirA, Vector3d& vtDirScc) const ; - bool VerifyScc( const Vector3d& vtDirI, const Vector3d& vtDirA, int nSolCh) const ; + bool VerifyScc( const Vector3d& vtDirI, const Vector3d& vtDirA, int nSolCh, bool bExact) const ; bool AdjustAngleInStroke( const STROKE& Stroke, double& dAng) const ; bool LuaInit( const std::string& sMachineName) ; bool LuaExit( void) ; @@ -249,6 +249,7 @@ class Machine int m_nCalcToolId ; // utensile corrente per calcoli double m_dCalcRot1W ; // peso del primo asse rotante per i confronti int m_nCalcSolCh ; // criterio di scelta della soluzione + bool m_bSolChExact ; // flag per scelta soluzione da soddisfare esattamente Point3d m_ptCalcPos ; // posizione utensile a riposo per calcoli Vector3d m_vtCalcDir ; // direzione utensile a riposo per calcoli Vector3d m_vtCalcADir ; // direzione ausiliaria a riposo per calcoli diff --git a/MachineCalc.cpp b/MachineCalc.cpp index 0476073..570f263 100644 --- a/MachineCalc.cpp +++ b/MachineCalc.cpp @@ -577,8 +577,10 @@ Machine::GetKinematicRotAxisBlocked( int nInd, string& sName, double& dVal) cons //---------------------------------------------------------------------------- bool -Machine::SetSolCh( int nScc) +Machine::SetSolCh( int nScc, bool bExact) { + // imposto se richiesta verifica esatta + m_bSolChExact = bExact ; // se standard o nullo o suo opposto if ( nScc == MCH_SCC_STD || nScc == MCH_SCC_NONE || nScc == MCH_SCC_OPPOSITE) { // recupero i dati della testa @@ -781,6 +783,16 @@ Machine::GetMyAngles( const Vector3d& vtDirT, const Vector3d& vtDirA, vtAx2.Invert() ; // calcolo secondo angolo di rotazione nStat = GetRotationComponent( vtDirHn, dCompTSuAxR1, vtAx1, vtAx2, dAngB1, dAngB2, bDet) ; + // se indeterminato con richiesta direzione ausiliaria esatta, ricalcolo con direzione aux + if ( nStat >= 1 && ! bDet && m_bSolChExact) { + // componente versore ausiliario desiderato su direzione primo asse rotante + Vector3d vtSccDir ; + if ( GetSccDir( m_nCalcSolCh, vtDirAn, vtSccDir)) { + double dCompASuAxR1 = vtSccDir * vtAx1 ; + // ricalcolo secondo angolo di rotazione + nStat = GetRotationComponent( vtDirIn, dCompASuAxR1, vtAx1, vtAx2, dAngB1, dAngB2, bDet) ; + } + } // aggiornamento direzioni fresa e ausiliaria su testa if ( nStat >= 1) { // se indeterminato lo azzero @@ -867,11 +879,11 @@ Machine::GetMyAngles( const Vector3d& vtDirT, const Vector3d& vtDirA, // verifiche per criterio scelta soluzione if ( nStat >= 2) { - if ( ! VerifyScc( vtDirI2, vtDirAn, m_nCalcSolCh)) + if ( ! VerifyScc( vtDirI2, vtDirAn, m_nCalcSolCh, m_bSolChExact)) -- nStat ; } if ( nStat >= 1) { - if ( ! VerifyScc( vtDirI1, vtDirAn, m_nCalcSolCh)) { + if ( ! VerifyScc( vtDirI1, vtDirAn, m_nCalcSolCh, m_bSolChExact)) { -- nStat ; // riloco eventuale soluzione rimasta if ( nStat >= 1) { @@ -1165,27 +1177,51 @@ Machine::GetSccDir( int nSolCh, const Vector3d& vtDirA, Vector3d& vtDirScc) cons //---------------------------------------------------------------------------- bool -Machine::VerifyScc( const Vector3d& vtDirI, const Vector3d& vtDirA, int nSolCh) const +Machine::VerifyScc( const Vector3d& vtDirI, const Vector3d& vtDirA, int nSolCh, bool bExact) const { switch ( nSolCh) { default : return true ; case MCH_SCC_ADIR_XP : - return ( vtDirI.x > - EPS_ZERO) ; + if ( bExact) + return vtDirI.IsXplus() ; + else + return ( vtDirI.x > - EPS_ZERO) ; case MCH_SCC_ADIR_XM : - return ( vtDirI.x < EPS_ZERO) ; + if ( bExact) + return vtDirI.IsXminus() ; + else + return ( vtDirI.x < EPS_ZERO) ; case MCH_SCC_ADIR_YP : - return ( vtDirI.y > - EPS_ZERO) ; + if ( bExact) + return vtDirI.IsYplus() ; + else + return ( vtDirI.y > - EPS_ZERO) ; case MCH_SCC_ADIR_YM : - return ( vtDirI.y < EPS_ZERO) ; + if ( bExact) + return vtDirI.IsYminus() ; + else + return ( vtDirI.y < EPS_ZERO) ; case MCH_SCC_ADIR_ZP : - return ( vtDirI.z > - EPS_ZERO) ; + if ( bExact) + return vtDirI.IsZplus() ; + else + return ( vtDirI.z > - EPS_ZERO) ; case MCH_SCC_ADIR_ZM : - return ( vtDirI.z < EPS_ZERO) ; + if ( bExact) + return vtDirI.IsZminus() ; + else + return ( vtDirI.z < EPS_ZERO) ; case MCH_SCC_ADIR_NEAR : - return ( vtDirA.IsSmall() || ( vtDirI * vtDirA) > cos( 60 * DEGTORAD)) ; + if ( bExact) + return ( ! vtDirA.IsSmall() && ( vtDirI * vtDirA) > cos( 0.1 * DEGTORAD)) ; + else + return ( vtDirA.IsSmall() || ( vtDirI * vtDirA) > cos( 60 * DEGTORAD)) ; case MCH_SCC_ADIR_FAR : - return ( vtDirA.IsSmall() || ( vtDirI * vtDirA) < cos( 120 * DEGTORAD)) ; + if ( bExact) + return ( ! vtDirA.IsSmall() && ( vtDirI * vtDirA) < cos( 179.1 * DEGTORAD)) ; + else + return ( vtDirA.IsSmall() || ( vtDirI * vtDirA) < cos( 120 * DEGTORAD)) ; } } diff --git a/MachineHeads.cpp b/MachineHeads.cpp index bdab308..8a9f45c 100644 --- a/MachineHeads.cpp +++ b/MachineHeads.cpp @@ -136,6 +136,10 @@ Machine::LoadTool( Exit* pExit, const string& sTool) if ( nT == GDB_ID_NULL) return false ; m_pGeomDB->Rotate( nT, ORIG, X_AX, 90) ; + // se mortasa, lo ruoto 90 deg attorno a Z + int nType ; + if ( m_pMchMgr->TdbGetCurrToolParam( TPA_TYPE, nType) && nType == TT_MORTISE_STD) + m_pGeomDB->Rotate( nT, ORIG, Z_AX, 90) ; pExit->SetTool( sTool) ; return true ; } diff --git a/Milling.cpp b/Milling.cpp index 500991f..9bb4d56 100644 --- a/Milling.cpp +++ b/Milling.cpp @@ -1377,7 +1377,7 @@ Milling::ProcessPath( int nPathId, int nPvId, int nClId) if ( ! pCompo->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, false)) return false ; - // recupero i punti di inizio e fine (per poi salvarlo nelle info di CL path) + // recupero i punti di inizio e fine (per poi salvarli nelle info di CL path) Point3d ptStart ; pCompo->GetStartPoint( ptStart) ; Point3d ptEnd ; pCompo->GetEndPoint( ptEnd) ; @@ -1497,7 +1497,7 @@ Milling::ProcessPath( int nPathId, int nPvId, int nClId) // se richiesta anteprima if ( nPvId != GDB_ID_NULL) { - // creo gruppo per geometria di lavorazione del percorso + // creo gruppo per geometria di anteprima del percorso int nPxId = m_pGeomDB->AddGroup( GDB_ID_NULL, nPvId, Frame3d()) ; if ( nPxId == GDB_ID_NULL) return false ; diff --git a/Mortising.cpp b/Mortising.cpp new file mode 100644 index 0000000..d9755ce --- /dev/null +++ b/Mortising.cpp @@ -0,0 +1,1549 @@ +//---------------------------------------------------------------------------- +// EgalTech 2018-2018 +//---------------------------------------------------------------------------- +// File : Mortising.cpp Data : 25.02.18 Versione : 1.9c1 +// Contenuto : Implementazione gestione mortasature. +// +// +// +// Modifiche : 25.02.18 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "MachMgr.h" +#include "DllMain.h" +#include "Mortising.h" +#include "OperationConst.h" +#include "/EgtDev/Include/EGkCurveLine.h" +#include "/EgtDev/Include/EGkCurveArc.h" +#include "/EgtDev/Include/EGkCurveComposite.h" +#include "/EgtDev/Include/EGkArcSpecial.h" +#include "/EgtDev/Include/EGkChainCurves.h" +#include "/EgtDev/Include/EGkOffsetCurve.h" +#include "/EgtDev/Include/EGkSfrCreate.h" +#include "/EgtDev/Include/EGkSurfTriMesh.h" +#include "/EgtDev/Include/EGkUserObjFactory.h" +#include "/EgtDev/Include/EGnStringKeyVal.h" +#include "/EgtDev/Include/EgtPointerOwner.h" + +using namespace std ; + +//------------------------------ Errors -------------------------------------- +// 2501 = "Error in Mortising : UpdateToolData failed" +// 2502 = "Error in Mortising : Offset not computable" +// 2503 = "Error in Mortising : Empty RawBox" +// 2504 = "Error in Mortising : Depth not computable" +// 2505 = "Error in Mortising : machining depth (xxx) bigger than MaxMaterial (yyy)" +// 2506 = "Error in Mortising : Entity GetElevation" +// 2507 = "Error in Mortising : Chaining failed" +// 2508 = "Error in Mortising : axes values not calculable" +// 2509 = "Error in Mortising : outstroke xx" +// 2510 = "Error in Mortising : link movements not calculable" +// 2511 = "Error in Mortising : link outstroke xx" +// 2512 = "Error in Mortising : post apply not calculable" +// 2513 = "Error in Mortising : Tool MaxMaterial too small (xx)" +// 2514 = "Error in Mortising : Closed path not allowed" + +//---------------------------------------------------------------------------- +USEROBJ_REGISTER( GetOperationClass( OPER_MORTISING), Mortising) ; + +//---------------------------------------------------------------------------- +const string& +Mortising::GetClassName( void) const +{ + return USEROBJ_GETNAME( Mortising) ; +} + +//---------------------------------------------------------------------------- +Mortising* +Mortising::Clone( void) const +{ + // alloco oggetto + Mortising* pMort = new(nothrow) Mortising ; + // eseguo copia dei dati + if ( pMort != nullptr) { + try { + pMort->m_Params = m_Params ; + pMort->m_TParams = m_TParams ; + } + catch( ...) { + delete pMort ; + return nullptr ; + } + } + // ritorno l'oggetto + return pMort ; +} + +//---------------------------------------------------------------------------- +bool +Mortising::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_nMortises) + szNewLine ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +Mortising::Save( int nBaseId, STRVECTOR& vString) const +{ + try { + int nSize = 1 + m_Params.GetSize() + m_TParams.GetSize() + 2 ; + 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_nMortises, vString[++k])) + return false ; + } + catch( ...) { + return false ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +Mortising::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_nMortises)) + return false ; + } + } + return true ; +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +Mortising::Mortising( void) +{ + m_Params.m_sName = "*" ; + m_Params.m_sToolName = "*" ; + m_TParams.m_sName = "*" ; + m_TParams.m_sHead = "*" ; + m_nMortises = 0 ; +} + +//---------------------------------------------------------------------------- +bool +Mortising::Prepare( const string& sMillName) +{ + // 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 MortisingData* pDdata = GetMortisingData( pMMgr->GetMachining( sMillName)) ; + 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 +Mortising::SetParam( int nType, bool bVal) +{ + switch ( nType) { + case MPA_INVERT : + m_Params.m_bInvert = bVal ; + return true ; + case MPA_TOOLINVERT : + m_Params.m_bToolInvert = bVal ; + return true ; + } + return false ; +} + +//---------------------------------------------------------------------------- +bool +Mortising::SetParam( int nType, int nVal) +{ + switch ( nType) { + case MPA_WORKSIDE : + if ( ! m_Params.VerifyWorkSide( nVal)) + return false ; + m_Params.m_nWorkSide = nVal ; + return true ; + case MPA_SCC : + if ( ! m_Params.VerifySolCh( nVal)) + return false ; + m_Params.m_nSolCh = nVal ; + return true ; + case MPA_FACEUSE : + if ( ! m_Params.VerifyFaceUse( nVal)) + return false ; + m_Params.m_nFaceUse = nVal ; + return true ; + } + return false ; +} + +//---------------------------------------------------------------------------- +bool +Mortising::SetParam( int nType, double dVal) +{ + switch ( nType) { + case MPA_SPEED : + if ( ! m_TParams.VerifySpeed( dVal)) + return false ; + if ( abs( m_TParams.m_dSpeed - dVal) < EPS_MACH_ANG_PAR) + m_Params.m_dSpeed = 0 ; + else + m_Params.m_dSpeed = dVal ; + return true ; + case MPA_FEED : + if ( abs( m_TParams.m_dFeed - dVal) < EPS_MACH_LEN_PAR) + m_Params.m_dFeed = 0 ; + else + m_Params.m_dFeed = dVal ; + return true ; + case MPA_STARTFEED : + if ( abs( m_TParams.m_dStartFeed - dVal) < EPS_MACH_LEN_PAR) + m_Params.m_dStartFeed = 0 ; + else + m_Params.m_dStartFeed = dVal ; + return true ; + case MPA_ENDFEED : + if ( abs( m_TParams.m_dEndFeed - dVal) < EPS_MACH_LEN_PAR) + m_Params.m_dEndFeed = 0 ; + else + m_Params.m_dEndFeed = dVal ; + return true ; + case MPA_TIPFEED : + if ( abs( m_TParams.m_dTipFeed - dVal) < EPS_MACH_LEN_PAR) + m_Params.m_dTipFeed = 0 ; + else + m_Params.m_dTipFeed = dVal ; + return true ; + case MPA_OFFSR : + if ( abs( m_TParams.m_dOffsR - dVal) < EPS_MACH_LEN_PAR) + m_Params.m_dOffsR = UNKNOWN_PAR ; + else + m_Params.m_dOffsR = dVal ; + return true ; + case MPA_OFFSL : + if ( abs( m_TParams.m_dOffsL - dVal) < EPS_MACH_LEN_PAR) + m_Params.m_dOffsL = UNKNOWN_PAR ; + else + m_Params.m_dOffsL = dVal ; + return true ; + case MPA_DEPTH : + m_Params.m_sDepth = ToString( dVal) ; + return true ; + case MPA_STARTPOS : + m_Params.m_dStartPos = dVal ; + return true ; + case MPA_STEP : + m_Params.m_dStep = dVal ; + return true ; + case MPA_STARTADDLEN : + m_Params.m_dStartAddLen = dVal ; + return true ; + case MPA_ENDADDLEN : + m_Params.m_dEndAddLen = dVal ; + return true ; + } + return false ; +} + +//---------------------------------------------------------------------------- +bool +Mortising::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 ; + m_Params.m_sToolName = sVal ; + m_Params.m_ToolUuid = pTdata->m_Uuid ; + m_TParams = *pTdata ; + } break ; + case MPA_DEPTH_STR : + m_Params.m_sDepth = sVal ; + return true ; + case MPA_SYSNOTES : + m_Params.m_sSysNotes = sVal ; + break ; + case MPA_USERNOTES : + m_Params.m_sUserNotes = sVal ; + break ; + case MPA_INITANGS : + m_Params.m_sInitAngs = sVal ; + break ; + case MPA_BLOCKEDAXIS : + m_Params.m_sBlockedAxis = sVal ; + break ; + default : + return false ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +Mortising::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 (tutte curve o tutte facce) + int nType = GEO_NONE ; + for ( const auto& Id : vIds) { + // test sull'entità + int nSubs ; + if ( ! VerifyGeometry( Id, nSubs, nType)) { + string sOut = "Entity " + ToString( Id) + " skipped by Mortising" ; + LOG_INFO( GetEMkLogger(), sOut.c_str()) ; + continue ; + } + // posso aggiungere alla lista + m_vId.emplace_back( Id) ; + } + return ( ! m_vId.empty() || vIds.empty()) ; +} + +//---------------------------------------------------------------------------- +bool +Mortising::Preview( bool bRecalc) +{ + // reset numero percorsi di lavoro generati + m_nMortises = 0 ; + + // verifico validità gestore DB geometrico e Id del gruppo + if ( m_pGeomDB == nullptr || ! m_pGeomDB->ExistsObj( m_nOwnerId)) + return false ; + + // recupero gruppo per geometria ausiliaria + int nAuxId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_AUX) ; + bool bChain = false ; + // se non c'è, lo aggiungo + 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 ; + } + + // aggiorno dati geometrici dell'utensile + if ( ! UpdateToolData()) { + m_pMchMgr->SetLastError( 2501, "Error in Mortising : UpdateToolData failed") ; + return false ; + } + + // se necessario, eseguo concatenamento ed inserisco i percorsi sotto la geometria ausiliaria + if ( bChain && ! Chain( nAuxId)) { + m_pMchMgr->SetLastError( 2507, "Error in Mortising : Chaining failed") ; + return false ; + } + // recupero gruppo per geometria di Preview + int nPvId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_PV) ; + // se non c'è, lo aggiungo + if ( nPvId == GDB_ID_NULL) { + nPvId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ; + if ( nPvId == GDB_ID_NULL) + return false ; + m_pGeomDB->SetName( nPvId, MCH_PV) ; + } + // altrimenti lo svuoto + else + m_pGeomDB->EmptyGroup( nPvId) ; + + // lavoro ogni singola catena + int nPathId = m_pGeomDB->GetFirstGroupInGroup( nAuxId) ; + while ( nPathId != GDB_ID_NULL) { + if ( ! ProcessPath( nPathId, nPvId, GDB_ID_NULL)) + return false ; + nPathId = m_pGeomDB->GetNextGroup( nPathId) ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +Mortising::Apply( bool bRecalc, bool bPostApply) +{ + // reset numero mortasature generate + m_nMortises = 0 ; + + // verifico validità gestore DB geometrico e Id del gruppo + if ( m_pGeomDB == nullptr || ! m_pGeomDB->ExistsObj( m_nOwnerId)) + return false ; + + // recupero gruppo per geometria ausiliaria + int nAuxId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_AUX) ; + bool bChain = false ; + // se non c'è, lo aggiungo + 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 ; + } + + // aggiorno dati geometrici dell'utensile + if ( ! UpdateToolData()) { + m_pMchMgr->SetLastError( 2501, "Error in Mortising : UpdateToolData failed") ; + return false ; + } + + // se necessario, eseguo concatenamento ed inserisco i percorsi sotto la geometria ausiliaria + if ( bChain && ! Chain( nAuxId)) { + m_pMchMgr->SetLastError( 2507, "Error in Mortising : 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 + int nPathId = m_pGeomDB->GetFirstGroupInGroup( nAuxId) ; + while ( nPathId != GDB_ID_NULL) { + if ( ! ProcessPath( nPathId, GDB_ID_NULL, nClId)) + return false ; + nPathId = m_pGeomDB->GetNextGroup( nPathId) ; + } + + // eseguo aggiornamento assi macchina e collegamento con operazione precedente + return Update( bPostApply) ; +} + +//---------------------------------------------------------------------------- +bool +Mortising::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_nMortises == 0) { + LOG_INFO( GetEMkLogger(), "Warning in Mortising : Plunges not found") + 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, true)) { + string sInfo = m_pMchMgr->GetOutstrokeInfo() ; + if ( sInfo.empty()) + m_pMchMgr->SetLastError( 2508, "Error in Mortising : axes values not calculable") ; + else + m_pMchMgr->SetLastError( 2509, "Error in Mortising : 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( 2510, "Error in Mortising : link movements not calculable") ; + else + m_pMchMgr->SetLastError( 2511, "Error in Mortising : link outstroke ") ; + return false ; + } + + // esecuzione eventuali personalizzazioni + if ( bPostApply && ! PostApply()) { + m_pMchMgr->SetLastError( 2512, "Error in Mortising : post apply not calculable") ; + return false ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +Mortising::GetParam( int nType, bool& bVal) const +{ + switch ( nType) { + case MPA_INVERT : + bVal = m_Params.m_bInvert ; + return true ; + case MPA_TOOLINVERT : + bVal = m_Params.m_bToolInvert ; + return true ; + } + bVal = false ; + return false ; +} + +//---------------------------------------------------------------------------- +bool +Mortising::GetParam( int nType, int& nVal) const +{ + switch ( nType) { + case MPA_TYPE : + nVal = MT_MORTISING ; + return true ; + case MPA_WORKSIDE : + nVal = m_Params.m_nWorkSide ; + return true ; + case MPA_SCC : + nVal = m_Params.m_nSolCh ; + return true ; + case MPA_FACEUSE : + nVal = m_Params.m_nFaceUse ; + return true ; + } + nVal = 0 ; + return false ; +} + +//---------------------------------------------------------------------------- +bool +Mortising::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_OFFSL : + dVal = GetOffsL() ; + return true ; + case MPA_STARTPOS : + dVal = m_Params.m_dStartPos ; + return true ; + case MPA_STEP : + dVal = m_Params.m_dStep ; + return true ; + case MPA_STARTADDLEN : + dVal = m_Params.m_dStartAddLen ; + return true ; + case MPA_ENDADDLEN : + dVal = m_Params.m_dEndAddLen ; + return true ; + } + dVal = 0 ; + return false ; +} + +//---------------------------------------------------------------------------- +bool +Mortising::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& +Mortising::GetToolData( void) const +{ + return m_TParams ; +} + +//---------------------------------------------------------------------------- +bool +Mortising::UpdateToolData( void) +{ + // 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 ; + // aggiorno i parametri + m_TParams = *pTdata ; + if ( ! EqualNoCase( m_Params.m_sToolName, m_TParams.m_sName)) { + string sLog = "Warning in Mortising : tool name changed (" + + m_Params.m_sToolName + "->" + m_TParams.m_sName +")" ; + LOG_INFO( GetEMkLogger(), sLog.c_str()) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +Mortising::GetGeometry( SELVECTOR& vIds) const +{ + // restituisco l'elenco delle entità + vIds = m_vId ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +Mortising::VerifyGeometry( SelData Id, int& nSubs, int& nType) +{ + // ammessi : tutte curve o tutte facce di trimesh + const IGeoObj* pGObj = m_pGeomDB->GetGeoObj( Id.nId) ; + if ( pGObj == nullptr) + return false ; + // se ammesse curve ed è tale + if ( nType != GEO_SURF && ( pGObj->GetType() & GEO_CURVE) != 0) { + const ICurve* pCurve = nullptr ; + // se direttamente la curva + if ( Id.nSub == SEL_SUB_ALL) { + pCurve = ::GetCurve( pGObj) ; + if ( pCurve != nullptr) { + if ( pCurve->GetType() == CRV_COMPO) + nSubs = ::GetCurveComposite( pCurve)->GetCurveCount() ; + else + nSubs = 0 ; + } + } + // altrimenti sottocurva di composita + else { + const ICurveComposite* pCompo = GetCurveComposite( pGObj) ; + if ( pCompo != nullptr) + pCurve = pCompo->GetCurve( Id.nSub) ; + nSubs = 0 ; + } + return ( pCurve != nullptr) ; + } + // se altrimenti ammesse superfici trimesh ed è tale + else if ( nType != GEO_CURVE && ( pGObj->GetType() & GEO_SURF) != 0) { + const ISurfTriMesh* pSurf = ::GetSurfTriMesh( pGObj) ; + if ( pSurf == nullptr) + return false ; + // se direttamente la superficie + if ( Id.nSub == SEL_SUB_ALL) { + nSubs = pSurf->GetFacetCount() ; + return true ; + } + // altrimenti faccia di superficie trimesh + else { + // se faccia non esistente + if ( Id.nSub > pSurf->GetFacetCount()) + return false ; + // tutto bene + nSubs = 0 ; + return true ; + } + } + // altrimenti errore + else + return false ; +} + +//---------------------------------------------------------------------------- +ICurve* +Mortising::GetCurve( SelData Id) +{ + // ammessi : curve o facce di polymesh + const IGeoObj* pGObj = m_pGeomDB->GetGeoObj( Id.nId) ; + if ( pGObj == nullptr) + return nullptr ; + // ne recupero il riferimento globale + Frame3d frGlob ; + if ( ! m_pGeomDB->GetGlobFrame( Id.nId, frGlob)) + return nullptr ; + // se curva + if ( ( pGObj->GetType() & GEO_CURVE) != 0) { + PtrOwner pCurve ; + // se direttamente curva + if ( Id.nSub == SEL_SUB_ALL) { + // recupero e duplico la curva + const ICurve* pOriCurve = ::GetCurve( pGObj) ; + if ( pOriCurve != nullptr) + 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) { + // duplico la curva semplice + const ICurve* pOriCurve = ::GetCurve( pCompo->GetCurve( Id.nSub)) ; + if ( pOriCurve != nullptr) { + 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 nullptr ; + // la porto in globale + pCurve->ToGlob( frGlob) ; + // la restituisco + return Release( pCurve) ; + } + // se altrimenti superficie + else if ( ( pGObj->GetType() & GEO_SURF) != 0) { + // recupero la trimesh + const ISurfTriMesh* pSurf = ::GetSurfTriMesh( pGObj) ; + if ( pSurf == nullptr) + return nullptr ; + // recupero l'indice della faccia + int nFacet = ( ( Id.nSub == SEL_SUB_ALL) ? 0 : Id.nSub) ; + // recupero i contorni della faccia + POLYLINEVECTOR vPL ; + pSurf->GetFacetLoops( nFacet, vPL) ; + if ( vPL.empty()) + return nullptr ; + // recupero la normale esterna della faccia + Vector3d vtN ; + if ( ! pSurf->GetFacetNormal( nFacet, vtN)) + return nullptr ; + // creo la curva a partire da quello esterno + PtrOwner pCrvCompo( CreateCurveComposite()) ; + pCrvCompo->FromPolyLine( vPL[0]) ; + if ( ! pCrvCompo->IsValid()) + return nullptr ; + // assegno l'estrusione dalla normale alla faccia + pCrvCompo->SetExtrusion( vtN) ; + // la porto in globale + pCrvCompo->ToGlob( frGlob) ; + // sistemazioni varie + AdjustCurveFromSurf( pCrvCompo) ; + // la restituisco + return Release( pCrvCompo) ; + } + // altrimenti errore + else + return nullptr ; +} + +//---------------------------------------------------------------------------- +bool +Mortising::AdjustCurveFromSurf( ICurveComposite* pCrvCompo) +{ + // tipo posizione utensile + enum { TOOL_PARAL = 1, TOOL_ORTHO = 2, TOOL_ORTUP = 3} ; + int nToolDir ; + if ( ( m_Params.m_nFaceUse & 64) != 0) + nToolDir = TOOL_ORTUP ; + else if ( ( m_Params.m_nFaceUse & 32) != 0) + nToolDir = TOOL_ORTHO ; + else + nToolDir = TOOL_PARAL ; + // tipo di utilizzo contorno faccia + enum { FACE_DOWN = 1, FACE_TOP = 2, FACE_FRONT = 3, FACE_BACK = 4, FACE_LEFT = 5, FACE_RIGHT = 6, FACE_CONT = 7} ; + int nFace = ( m_Params.m_nFaceUse & 31) ; + + // copia della curva originale + PtrOwner pCopy( pCrvCompo->Clone()) ; + + // se richiesto contorno + if ( nFace == FACE_CONT) { + // cerco l'estremo più alto e lo imposto come inizio + double dU = 0 ; + double dUmax = 0 ; + double dZmax = - INFINITO ; + Point3d ptP ; + while ( pCrvCompo->GetPointD1D2( dU, ICurve::FROM_MINUS, ptP)) { + if ( ptP.z > dZmax + EPS_SMALL) { + dZmax = ptP.z ; + dUmax = dU ; + } + dU += 1 ; + } + if ( dU != 0) + pCrvCompo->ChangeStartPoint( dUmax) ; + } + // altrimenti + else { + // ingombro + BBox3d b3Box ; + pCrvCompo->GetLocalBBox( b3Box) ; + double dMin = b3Box.GetMin().z ; + double dMax = b3Box.GetMax().z ; + if ( nFace == FACE_FRONT || nFace == FACE_BACK) { + dMin = b3Box.GetMin().y ; + dMax = b3Box.GetMax().y ; + } + else if ( nFace == FACE_RIGHT || nFace == FACE_LEFT) { + dMin = b3Box.GetMin().x ; + dMax = b3Box.GetMax().x ; + } + double dTol = min( ( dMax - dMin) / 4., 20.) ; + // cerco il punto medio delle curve più vicino all'estremo desiderato + double dRef = dMin ; + if ( nFace == FACE_DOWN || nFace == FACE_FRONT || nFace == FACE_LEFT) + dRef = dMax ; + const ICurve* pCrv = pCrvCompo->GetFirstCurve() ; + while ( pCrv != nullptr) { + Point3d ptMid ; pCrv->GetMidPoint( ptMid) ; + switch ( nFace) { + case FACE_DOWN : dRef = min( dRef, ptMid.z) ; break ; + case FACE_TOP : dRef = max( dRef, ptMid.z) ; break ; + case FACE_FRONT : dRef = min( dRef, ptMid.y) ; break ; + case FACE_BACK : dRef = max( dRef, ptMid.y) ; break ; + case FACE_LEFT : dRef = min( dRef, ptMid.x) ; break ; + case FACE_RIGHT : dRef = max( dRef, ptMid.x) ; break ; + } + pCrv = pCrvCompo->GetNextCurve() ; + } + // elimino le linee troppo discoste dal riferimento dall'inizio e poi dalla fine + pCrv = pCrvCompo->GetFirstCurve() ; + while ( pCrv != nullptr) { + Point3d ptMid ; pCrv->GetMidPoint( ptMid) ; + if ( ( nFace == FACE_DOWN && ptMid.z > dRef + dTol) || + ( nFace == FACE_TOP && ptMid.z < dRef - dTol) || + ( nFace == FACE_FRONT && ptMid.y > dRef + dTol) || + ( nFace == FACE_BACK && ptMid.y < dRef - dTol) || + ( nFace == FACE_LEFT && ptMid.x > dRef + dTol) || + ( nFace == FACE_RIGHT && ptMid.x < dRef - dTol)) { + ICurve* pErase = pCrvCompo->RemoveFirstOrLastCurve( false) ; + delete( pErase) ; + pCrv = pCrvCompo->GetFirstCurve() ; + } + else + break ; + } + pCrv = pCrvCompo->GetLastCurve() ; + while ( pCrv != nullptr) { + Point3d ptMid ; pCrv->GetMidPoint( ptMid) ; + if ( ( nFace == FACE_DOWN && ptMid.z > dRef + dTol) || + ( nFace == FACE_TOP && ptMid.z < dRef - dTol) || + ( nFace == FACE_FRONT && ptMid.y > dRef + dTol) || + ( nFace == FACE_BACK && ptMid.y < dRef - dTol) || + ( nFace == FACE_LEFT && ptMid.x > dRef + dTol) || + ( nFace == FACE_RIGHT && ptMid.x < dRef - dTol)) { + ICurve* pErase = pCrvCompo->RemoveFirstOrLastCurve( true) ; + delete( pErase) ; + pCrv = pCrvCompo->GetLastCurve() ; + } + else + break ; + } + } + // determino il versore estrusione (utensile) + if ( nToolDir == TOOL_ORTHO) + pCrvCompo->SetThickness( 0) ; + else if ( nToolDir == TOOL_ORTUP) { + Vector3d vtN ; + pCrvCompo->GetExtrusion( vtN) ; + if ( vtN.z < - sin( 2 * DEGTORAD)) { + // pCrvCompo->Invert() ; + pCrvCompo->Translate( vtN * m_TParams.m_dThick) ; + pCrvCompo->SetExtrusion( - vtN) ; + } + pCrvCompo->SetThickness( 0) ; + } + else { // nToolDir == TOOL_PARAL + // sistemo versore + Vector3d vtN ; + pCrvCompo->GetExtrusion( vtN) ; + Point3d ptStart, ptEnd ; + pCrvCompo->GetStartPoint( ptStart) ; + pCrvCompo->GetEndPoint( ptEnd) ; + Vector3d vtT = ptEnd - ptStart ; + Vector3d vtExtr = vtN ^ vtT ; + if ( ! vtExtr.Normalize()) + return false ; + pCrvCompo->SetExtrusion( vtExtr) ; + // elimino eventuali parti iniziali e/o finali dirette circa come il versore + const double MAX_ALL_COS = cos( 25 * DEGTORAD) ; + const ICurve* pCrv = pCrvCompo->GetFirstCurve() ; + while ( pCrv != nullptr) { + Vector3d vtDir ; pCrv->GetStartDir( vtDir) ; + if ( abs( vtDir * vtExtr) > MAX_ALL_COS) { + ICurve* pErase = pCrvCompo->RemoveFirstOrLastCurve( false) ; + delete( pErase) ; + pCrv = pCrvCompo->GetFirstCurve() ; + } + else if ( pCrvCompo->IsClosed()) { + pCrvCompo->ChangeStartPoint( 1) ; + pCrv = pCrvCompo->GetFirstCurve() ; + } + else + break ; + } + pCrv = pCrvCompo->GetLastCurve() ; + while ( pCrv != nullptr) { + Vector3d vtDir ; pCrv->GetStartDir( vtDir) ; + if ( abs( vtDir * vtExtr) > MAX_ALL_COS) { + ICurve* pErase = pCrvCompo->RemoveFirstOrLastCurve( true) ; + delete( pErase) ; + pCrv = pCrvCompo->GetLastCurve() ; + } + else + break ; + } + // determino lo spessore misurato lungo la direzione + if ( ! IsNull( pCopy)) { + Frame3d frOcs ; frOcs.Set( ORIG, vtExtr) ; + Frame3d frExtr ; frExtr.ToLoc( frOcs) ; + BBox3d b3Extr ; pCopy->GetBBox( frExtr, b3Extr) ; + if ( ! b3Extr.IsEmpty()) + pCrvCompo->SetThickness( b3Extr.GetMax().z - b3Extr.GetMin().z) ; + } + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +Mortising::Chain( int nGrpDestId) +{ + // vettore puntatori alle curve + POCRVVECTOR vpCrvs ; + vpCrvs.reserve( m_vId.size()) ; + // recupero tutte le curve e le porto in globale + for ( const auto& Id : m_vId) { + // prendo curva + vpCrvs.emplace_back( GetCurve( Id)) ; + // ne verifico la validità + if ( IsNull( vpCrvs.back())) { + string sOut = "Entity " + ToString( Id) + " skipped by Mortising" ; + LOG_INFO( GetEMkLogger(), sOut.c_str()) ; + vpCrvs.back().Reset() ; + } + } + // 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( m_vId[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) && fabs( dTemp) > fabs( 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) ; + // 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 +Mortising::AdjustEndPointForAxesCalc( const CamData* pCamData, Point3d& ptP) const +{ + // non devo fare alcunché + return true ; +} + +//---------------------------------------------------------------------------- +bool +Mortising::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) ; + + // copio la curva composita da elaborare + int nCrvId = m_pGeomDB->GetFirstInGroup( nPathId) ; + if ( m_pGeomDB->GetGeoType( nCrvId) != CRV_COMPO) + return false ; + int nCopyId = m_pGeomDB->CopyGlob( nCrvId, GDB_ID_NULL, nTempId) ; + if ( nCopyId == GDB_ID_NULL) + return false ; + ICurveComposite* pCompo = GetCurveComposite( m_pGeomDB->GetGeoObj( nCopyId)) ; + + // eventuale inversione percorso + if ( m_Params.m_bInvert) + pCompo->Invert() ; + + // recupero estrusione e spessore + Vector3d vtExtr = Z_AX ; + pCompo->GetExtrusion( vtExtr) ; + double dThick ; + pCompo->GetThickness( dThick) ; + + // eventuale inversione direzione utensile + if ( m_Params.m_bToolInvert) { + vtExtr.Invert() ; + pCompo->SetExtrusion( vtExtr) ; + dThick = - dThick ; + pCompo->SetThickness( dThick) ; + } + + // verifico non sia un percorso chiuso + if ( pCompo->IsClosed()) { + m_pMchMgr->SetLastError( 2514, "Error in Mortising : Closed path not allowed") ; + return false ; + } + + // eventuali allungamenti/accorciamenti + { + // verifico che il percorso sia abbastanza lungo + double dLen ; pCompo->GetLength( dLen) ; + if ( dLen + m_Params.m_dStartAddLen + m_Params.m_dEndAddLen < 10 * EPS_SMALL) { + LOG_INFO( GetEMkLogger(), "Warning in Mortising : skipped Path too small") ; + return true ; + } + // se una sola entità circonferenza completa, la divido in due per poterla allungare + if ( pCompo->GetCurveCount() == 1 && pCompo->IsClosed()) + pCompo->AddJoint( 0.5) ; + // eventuali allungamenti + if ( m_Params.m_dStartAddLen > EPS_SMALL) { + if ( ! pCompo->ExtendStartByLen( m_Params.m_dStartAddLen)) + return false ; + dLen += m_Params.m_dStartAddLen ; + } + if ( m_Params.m_dEndAddLen > EPS_SMALL) { + if ( ! pCompo->ExtendEndByLen( m_Params.m_dEndAddLen)) + return false ; + dLen += m_Params.m_dEndAddLen ; + } + // eventuale accorciamenti (da fare dopo tutti gli allungamenti) + if ( m_Params.m_dStartAddLen < - EPS_SMALL) { + if ( ! pCompo->TrimStartAtLen( - m_Params.m_dStartAddLen)) + return false ; + dLen += m_Params.m_dStartAddLen ; + } + if ( m_Params.m_dEndAddLen < - EPS_SMALL) { + if ( ! pCompo->TrimEndAtLen( dLen + m_Params.m_dEndAddLen)) + return false ; + dLen += m_Params.m_dEndAddLen ; + } + } + + // unisco le parti allineate + if ( ! pCompo->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL)) + return false ; + + // recupero i punti di inizio e fine (per poi salvarli nelle info di CL path) + Point3d ptStart ; pCompo->GetStartPoint( ptStart) ; + Point3d ptEnd ; pCompo->GetEndPoint( ptEnd) ; + + // determino il versore ausiliario + Vector3d vtAux = ( ptEnd - ptStart) ^ vtExtr ; + vtAux.Normalize() ; + if ( vtAux.z < 0) + vtAux.Invert() ; + + // sistemo per lato di lavoro e offset radiale + Vector3d vtSide = ( ptEnd - ptStart) ^ vtExtr ; + vtSide.Normalize() ; + if ( m_Params.m_nWorkSide == MORTISE_WS_LEFT) + vtSide.Invert() ; + if ( AreOppositeVectorApprox( vtAux, vtSide)) + pCompo->Translate( vtSide * m_TParams.m_dThick) ; + if ( abs( GetOffsR()) > EPS_SMALL) + pCompo->Translate( vtSide * GetOffsR()) ; + + // recupero il box del grezzo in globale + BBox3d b3Raw ; + if ( ! GetRawGlobBox( m_nPhase, nPathId, 0.5 * m_TParams.m_dDiam, b3Raw) || b3Raw.IsEmpty()) { + m_pMchMgr->SetLastError( 2503, "Error in Mortising : Empty RawBox") ; + return false ; + } + + // recupero distanza da fondo dei grezzi interessati dal percorso + double dRbDist = 0 ; + if ( AreSameVectorApprox( vtExtr, Z_AX)) { + if ( ! GetDistanceFromRawBottom( m_nPhase, nCopyId, m_TParams.m_dDiam, dRbDist)) + return false ; + } + + // valuto l'espressione dell'affondamento + ExeLuaSetGlobNumVar( "TH", abs( dThick)) ; + ExeLuaSetGlobNumVar( "RB", dRbDist) ; + double dDepth ; + string sMyDepth = m_Params.m_sDepth ; + if ( ! ExeLuaEvalNumExpr( ToUpper( sMyDepth), &dDepth)) { + m_pMchMgr->SetLastError( 2504, "Error in Mortising : Depth not computable") ; + return false ; + } + // se spessore positivo, lo sottraggo dal risultato + if ( dThick > 0) + dDepth -= dThick ; + // sottraggo eventuale offset longitudinale + dDepth -= GetOffsL() ; + + // recupero nome del path + string sPathName ; + m_pGeomDB->GetName( nPathId, sPathName) ; + + // assegno il versore fresa + Vector3d vtTool = vtExtr ; + + // calcolo l'elevazione massima + double dElev ; + if ( CalcPathElevation( pCompo, vtTool, dDepth, 0.5 * m_TParams.m_dDiam, dElev)) { + if ( dElev < EPS_SMALL && AreSameVectorApprox( vtExtr, Z_AX)) { + BBox3d b3Crv ; + pCompo->GetLocalBBox( b3Crv) ; + dElev = max( 0., b3Raw.GetMax().z - b3Crv.GetMin().z + min( 0., dThick) + dDepth) ; + } + } + else + return false ; + + // verifico che lo step dell'utensile sia sensato + double dOkStep = m_Params.m_dStep ; + const double MIN_ZSTEP = 1.0 ; + if ( dOkStep >= EPS_SMALL && dOkStep < MIN_ZSTEP) { + dOkStep = MIN_ZSTEP ; + string sInfo = "Warning in Mortising : machining step too small (" + + ToString( m_Params.m_dStep, 2) + ")" ; + LOG_INFO( GetEMkLogger(), sInfo.c_str()) ; + } + + // verifico di non superare il massimo materiale + const double MAXMAT_TOL = EPS_SMALL ; + if ( dElev > m_TParams.m_dMaxMat + MAXMAT_TOL) { + // verifico che il massimo materiale dell'utensile sia sensato + const double MIN_MAXMAT = 1.0 ; + if ( m_TParams.m_dMaxMat < dElev && m_TParams.m_dMaxMat < MIN_MAXMAT) { + string sInfo = "Error in Mortising : Tool MaxMaterial too small (" + + ToString( m_TParams.m_dMaxMat, 2) + ")" ; + m_pMchMgr->SetLastError( 2513, sInfo) ; + return false ; + } + // se lo step supera la capacità dell'utensile + if ( m_Params.m_dStep > m_TParams.m_dMaxMat + EPS_SMALL) { + dOkStep = m_TParams.m_dMaxMat ; + string sInfo = "Warning in Mortising : machining step (" + ToString( m_Params.m_dStep, 1) + + ") bigger than MaxMaterial (" + ToString( m_TParams.m_dMaxMat, 1) + ")" ; + LOG_INFO( GetEMkLogger(), sInfo.c_str()) ; + } + // se lavorazione singola e l'elevazione supera la capacità dell'utensile + if ( ( dOkStep < EPS_SMALL || dOkStep > dElev) && dElev > m_TParams.m_dMaxMat + EPS_SMALL) { + // se affondamento riducibile : segnalo, riduco e continuo + if ( dDepth + max( dThick, 0.0) > m_TParams.m_dMaxMat) { + dDepth = m_TParams.m_dMaxMat - max( dThick, 0.0) ; + string sInfo = "Warning in Mortising : machining depth (" + ToString( dElev, 1) + + ") bigger than MaxMaterial (" + ToString( m_TParams.m_dMaxMat, 1) + ")" ; + LOG_INFO( GetEMkLogger(), sInfo.c_str()) ; + } + // altrimenti errore + else { + string sInfo = "Error in Mortising : machining depth (" + ToString( dElev, 1) + + ") bigger than MaxMaterial (" + ToString( m_TParams.m_dMaxMat, 1) + ")" ; + m_pMchMgr->SetLastError( 2505, sInfo.c_str()) ; + return false ; + } + } + } + + // se richiesta anteprima + if ( nPvId != GDB_ID_NULL) { + // creo gruppo per geometria di anteprima del percorso + int nPxId = m_pGeomDB->AddGroup( GDB_ID_NULL, nPvId, Frame3d()) ; + if ( nPxId == GDB_ID_NULL) + return false ; + m_pGeomDB->SetName( nPxId, sPathName) ; + m_pGeomDB->SetMaterial( nPxId, GREEN) ; + // creo l'anteprima del percorso + if ( ! GenerateMortisingPv( nPxId, pCompo)) + return false ; + } + + // 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) ; + + // assegno il vettore estrazione al gruppo del percorso + m_pGeomDB->SetInfo( nPxId, KEY_EXTR, vtTool) ; + // assegno i punti di inizio e fine al gruppo del percorso + m_pGeomDB->SetInfo( nPxId, KEY_START, ptStart) ; + m_pGeomDB->SetInfo( nPxId, KEY_END, ptEnd) ; + // assegno l'elevazione massima + m_pGeomDB->SetInfo( nPxId, KEY_ELEV, dElev) ; + + // Imposto dati comuni + SetPathId( nPxId) ; + SetToolDir( vtTool) ; + SetAuxDir( vtAux) ; + + // Calcolo la mortasatura + if ( ! GenerateMortisingCl( pCompo, vtTool, dDepth, dElev, dOkStep)) + return false ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +Mortising::CalcPathElevation( const ICurveComposite* pCompo, const Vector3d& vtTool, double dDepth, double dRad, + double& dElev) +{ + dElev = 0 ; + int nMaxInd = pCompo->GetCurveCount() - 1 ; + for ( int i = 0 ; i <= nMaxInd ; ++ i) { + // curva corrente + const ICurve* pCrvC = pCompo->GetCurve( i) ; + // calcolo elevazione + double dCurrElev ; + Point3d ptStart, ptMid, ptEnd ; + pCrvC->GetStartPoint( ptStart) ; + pCrvC->GetMidPoint( ptMid) ; + pCrvC->GetEndPoint( ptEnd) ; + Vector3d vtStartPerp, vtMidPerp, vtEndPerp, vtTg ; + pCrvC->GetStartDir( vtTg) ; + vtStartPerp = vtTg ^ vtTool ; + vtStartPerp.Normalize() ; + vtStartPerp *= dRad ; + pCrvC->GetMidDir( vtTg) ; + vtMidPerp = vtTg ^ vtTool ; + vtMidPerp.Normalize() ; + vtMidPerp *= dRad ; + pCrvC->GetEndDir( vtTg) ; + vtEndPerp = vtTg ^ vtTool ; + vtEndPerp.Normalize() ; + vtEndPerp *= dRad ; + Vector3d vtDepth = vtTool * dDepth ; + // linea centro utensile + if ( GetElevation( m_nPhase, ptStart - vtDepth, ptMid - vtDepth, ptEnd - vtDepth, vtTool, dCurrElev)) { + if ( dCurrElev > dElev) + dElev = dCurrElev ; + } + else { + m_pMchMgr->SetLastError( 2506, "Error in Mortising : Entity GetElevation") ; + return false ; + } + // da una parte + if ( GetElevation( m_nPhase, ptStart + vtStartPerp - vtDepth, ptMid + vtMidPerp - vtDepth, + ptEnd + vtEndPerp - vtDepth, vtTool, dCurrElev)) { + if ( dCurrElev > dElev) + dElev = dCurrElev ; + } + else { + m_pMchMgr->SetLastError( 2506, "Error in Mortising : Entity GetElevation") ; + return false ; + } + // dall'altra parte + if ( GetElevation( m_nPhase, ptStart - vtStartPerp - vtDepth, ptMid - vtMidPerp - vtDepth, + ptEnd - vtEndPerp - vtDepth, vtTool, dCurrElev)) { + if ( dCurrElev > dElev) + dElev = dCurrElev ; + } + else { + m_pMchMgr->SetLastError( 2506, "Error in Mortising : Entity GetElevation") ; + return false ; + } + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +Mortising::GenerateMortisingPv( int nPathId, const ICurveComposite* pCompo) +{ + // incremento numero di mortasature + ++ m_nMortises ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +Mortising::GenerateMortisingCl( const ICurveComposite* pCompo, const Vector3d& vtTool, double dDepth, double dElev, double dOkStep) +{ + // estremi della curva composita + Point3d ptStart ; pCompo->GetStartPoint( ptStart) ; + Point3d ptEnd ; pCompo->GetEndPoint( ptEnd) ; + + // compensazione elevazione/affondamento + double dDelta = dElev - dDepth ; + + // 1 -> punto approccio + SetFlag( 1) ; + double dAppr = m_pMchMgr->GetCurrMachiningsMgr()->GetSafeZ() ; + Point3d ptP1 = ptStart + vtTool * ( dDelta + dAppr) ; + if ( AddRapidStart( ptP1) == GDB_ID_NULL) + return false ; + SetFlag( 0) ; + + // 2 -> punto fuori (se diverso dal precedente) + if ( m_Params.m_dStartPos < dAppr) { + Point3d ptP2 = ptStart + vtTool * ( dDelta + m_Params.m_dStartPos) ; + if ( AddRapidMove( ptP2) == GDB_ID_NULL) + return false ; + } + + // determino numero e affondamento degli step + if ( dOkStep < EPS_SMALL) + dOkStep = dElev ; + int nStep = max( 1, static_cast( ceil( dElev / dOkStep))) ; + double dStep = dElev / nStep ; + const double RETURN_DIST = 10 ; + + // ciclo sugli step + for ( int i = 1 ; i <= nStep ; ++ i) { + + // 3 -> punto in affondamento + SetFeed( GetStartFeed()) ; + SetFlag( 0) ; + Point3d ptP3 = ptStart + ( dDelta - i * dStep) * vtTool ; + if ( AddLinearMove( ptP3) == GDB_ID_NULL) + return false ; + + // 4 -> punto termine + SetFeed( GetFeed()) ; + SetFlag( 0) ; + Point3d ptP4 = ptEnd + ( dDelta - i * dStep) * vtTool ; + if ( AddLinearMove( ptP4) == GDB_ID_NULL) + return false ; + + // 5 -> ritorno sull'inizio, se non ultimo punto + if ( i < nStep) { + // retrocedo + SetFeed( GetFeed()) ; + SetFlag( 0) ; + Point3d ptP5a = ptP4 + RETURN_DIST * vtTool ; + if ( AddLinearMove( ptP5a) == GDB_ID_NULL) + return false ; + // ritorno sopra inizio + SetFeed( GetFeed()) ; + SetFlag( 0) ; + Point3d ptP5b = ptP3 + RETURN_DIST * vtTool ; + if ( AddLinearMove( ptP5b) == GDB_ID_NULL) + return false ; + } + } + + // 6 -> ritorno all'approccio + SetFeed( GetEndFeed()) ; + SetFlag( 104) ; // risalita sopra il foro + Point3d ptP6 = ptEnd + vtTool * ( dDelta + dAppr) ; + if ( AddLinearMove( ptP6) == GDB_ID_NULL) + return false ; + + // reset dati di movimento + ResetMoveData() ; + + // incremento numero di mortasature + ++ m_nMortises ; + + return true ; +} + +//---------------------------------------------------------------------------- +double +Mortising::GetRadiusForStartEndElevation( void) +{ + const double DELTA_ELEV_RAD = 20.0 ; + return ( 0.5 * m_TParams.m_dTDiam + DELTA_ELEV_RAD) ; +} diff --git a/Mortising.h b/Mortising.h new file mode 100644 index 0000000..512d25e --- /dev/null +++ b/Mortising.h @@ -0,0 +1,100 @@ +//---------------------------------------------------------------------------- +// EgalTech 2018-2018 +//---------------------------------------------------------------------------- +// File : Mortising.h Data : 25.02.18 Versione : 1.9c1 +// Contenuto : Dichiarazione della classe Mortising. +// +// +// +// Modifiche : 25.02.18 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +#pragma once + +#include "Machining.h" +#include "MortisingData.h" +#include "ToolData.h" + +struct SqHole ; +class ICurve ; +class ICurveComposite ; + +//---------------------------------------------------------------------------- +class Mortising : public Machining +{ + public : // IUserObj + Mortising* 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_MORTISING ; } + bool IsEmpty( void) const override + { return ( m_nMortises == 0) ; } + + 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& sMillName) 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 ; + const ToolData& GetToolData( void) const ; + bool GetGeometry( SELVECTOR& vIds) const override ; + + public : + Mortising( void) ; + + private : + bool UpdateToolData( void) ; + bool VerifyGeometry( SelData Id, int& nSubs, int& nType) ; + ICurve* GetCurve( SelData Id) ; + bool AdjustCurveFromSurf( ICurveComposite* pCrvCompo) ; + bool Chain( int nGrpDestId) ; + bool ProcessPath( int nPathId, int nPvId, int nClId) ; + bool CalcPathElevation( const ICurveComposite* pCompo, const Vector3d& vtTool, double dDepth, double dRad, double& dElev) ; + bool GenerateMortisingPv( int nPathId, const ICurveComposite* pCompo) ; + bool GenerateMortisingCl( const ICurveComposite* pCompo, const Vector3d& vtTool, double dDepth, double dElev, double dOkStep) ; + double GetRadiusForStartEndElevation( void) ; + + private : + double GetSpeed() const + { return ( abs( m_Params.m_dSpeed) < EPS_MACH_ANG_PAR ? m_TParams.m_dSpeed : m_Params.m_dSpeed) ; } + double GetFeed() const + { return ( abs( m_Params.m_dFeed) < EPS_MACH_LEN_PAR ? m_TParams.m_dFeed : m_Params.m_dFeed) ; } + double GetStartFeed() const + { return ( abs( m_Params.m_dStartFeed) < EPS_MACH_LEN_PAR ? m_TParams.m_dStartFeed : m_Params.m_dStartFeed) ; } + double GetEndFeed() const + { return ( abs( m_Params.m_dEndFeed) < EPS_MACH_LEN_PAR ? m_TParams.m_dEndFeed : m_Params.m_dEndFeed) ; } + double GetTipFeed() const + { return ( abs( m_Params.m_dTipFeed) < EPS_MACH_LEN_PAR ? m_TParams.m_dTipFeed : m_Params.m_dTipFeed) ; } + double GetOffsL() const + { return ( abs( m_Params.m_dOffsL - UNKNOWN_PAR) < EPS_MACH_LEN_PAR ? m_TParams.m_dOffsL : m_Params.m_dOffsL) ; } + double GetOffsR() const + { return ( abs( m_Params.m_dOffsR - UNKNOWN_PAR) < EPS_MACH_LEN_PAR ? m_TParams.m_dOffsR : m_Params.m_dOffsR) ; } + + private : + SELVECTOR m_vId ; // identificativi entità geometriche da lavorare + MortisingData m_Params ; // parametri lavorazione + ToolData m_TParams ; // parametri utensile + int m_nMortises ; // numero di mortasature generate +} ; \ No newline at end of file diff --git a/MortisingData.cpp b/MortisingData.cpp new file mode 100644 index 0000000..0b29b04 --- /dev/null +++ b/MortisingData.cpp @@ -0,0 +1,632 @@ +//---------------------------------------------------------------------------- +// EgalTech 2018-2018 +//---------------------------------------------------------------------------- +// File : MortisingData.cpp Data : 25.02.18 Versione : 1.9cb1 +// Contenuto : Implementazione struttura dati lavorazione di mortasatura. +// +// +// +// Modifiche : 25.02.18 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "MortisingData.h" +#include "MachiningDataFactory.h" +#include "MachiningConst.h" +#include "/EgtDev/Include/EmkToolConst.h" +#include "/EgtDev/Include/EmkSimuGenConst.h" +#include "/EgtDev/Include/EGnStringUtils.h" +#include +#include + +using namespace std ; + +//---------------------------------------------------------------------------- +enum nMortisingKey { + KEY_AB = 0, + KEY_AI, + KEY_DH, + KEY_EAL, + KEY_F, + KEY_FE, + KEY_FS, + KEY_FT, + KEY_FU, + KEY_INV, + KEY_NAME, + KEY_NNS, + KEY_NNU, + KEY_OL, + KEY_OR, + KEY_PS, + KEY_S, + KEY_SAL, + KEY_SCC, + KEY_ST, + KEY_TI, + KEY_TNAME, + KEY_TUUID, + KEY_UUID, + KEY_WS, + KEY_ZZZ} ; // rappresenta il numero di elementi + +static const std::array sMortisingKey = { + "AB", + "AI", + "DH", + "EAL", + "F", + "FE", + "FS", + "FT", + "FU", + "INV", + "NAME", + "NNS", + "NNU", + "OL", + "OR", + "PS", + "S", + "SAL", + "SCC", + "ST", + "TI", + "TN", + "TU", + "UUID", + "WS"} ; + +//---------------------------------------------------------------------------- +MCHDATA_REGISTER( MT_MORTISING, "MORTISING", MortisingData) ; + +//---------------------------------------------------------------------------- +MortisingData* +MortisingData::Clone( void) const +{ + // alloco oggetto + MortisingData* pDdata = new(nothrow) MortisingData ; + // copio i dati + if ( pDdata != nullptr) { + if ( ! pDdata->CopyFrom( this)) { + delete pDdata ; + return nullptr ; + } + } + return pDdata ; +} + +//---------------------------------------------------------------------------- +bool +MortisingData::CopyFrom( const MachiningData* pMdata) +{ + // è inutile copiare se sorgente coincide con destinazione + if ( pMdata == this) + return true ; + // la sorgente deve essere dello stesso tipo + const MortisingData* pDdata = GetMortisingData( pMdata) ; + if ( pDdata == nullptr) + return false ; + // eseguo copia + m_Uuid = pDdata->m_Uuid ; + m_sName = pDdata->m_sName ; + m_ToolUuid = pDdata->m_ToolUuid ; + m_sToolName = pDdata->m_sToolName ; + m_sBlockedAxis = pDdata->m_sBlockedAxis ; + m_sInitAngs = pDdata->m_sInitAngs ; + m_nSolCh = pDdata->m_nSolCh ; + m_dSpeed = pDdata->m_dSpeed ; + m_dFeed = pDdata->m_dFeed ; + m_dStartFeed = pDdata->m_dStartFeed ; + m_dEndFeed = pDdata->m_dEndFeed ; + m_dTipFeed = pDdata->m_dTipFeed ; + m_dOffsL = pDdata->m_dOffsL ; + m_dOffsR = pDdata->m_dOffsR ; + m_nWorkSide = pDdata->m_nWorkSide ; + m_bToolInvert = pDdata->m_bToolInvert ; + m_nFaceUse = pDdata->m_nFaceUse ; + m_bInvert = pDdata->m_bInvert ; + m_sDepth = pDdata->m_sDepth ; + m_dStartPos = pDdata->m_dStartPos ; + m_dStep = pDdata->m_dStep ; + m_dStartAddLen = pDdata->m_dStartAddLen ; + m_dEndAddLen = pDdata->m_dEndAddLen ; + m_sSysNotes = pDdata->m_sSysNotes ; + m_sUserNotes = pDdata->m_sUserNotes ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +MortisingData::SameAs(const MachiningData* pMdata) const +{ + // se coincide con altro -> uguali + if ( pMdata == this) + return true ; + // se sono di tipo diverso -> diversi + const MortisingData* pDdata = GetMortisingData( pMdata) ; + if ( pDdata == nullptr) + return false ; + // confronto termine a termine + return ( m_Uuid == pDdata->m_Uuid && + m_sName == pDdata->m_sName && + m_ToolUuid == pDdata->m_ToolUuid && + m_sToolName == pDdata->m_sToolName && + m_sBlockedAxis == pDdata->m_sBlockedAxis && + m_sInitAngs == pDdata->m_sInitAngs && + m_nSolCh == pDdata->m_nSolCh && + abs( m_dSpeed - pDdata->m_dSpeed) < EPS_MACH_ANG_PAR && + abs( m_dFeed - pDdata->m_dFeed) < EPS_MACH_LEN_PAR && + abs( m_dStartFeed - pDdata->m_dStartFeed) < EPS_MACH_LEN_PAR && + abs( m_dEndFeed - pDdata->m_dEndFeed) < EPS_MACH_LEN_PAR && + abs( m_dTipFeed - pDdata->m_dTipFeed) < EPS_MACH_LEN_PAR && + abs( m_dOffsL - pDdata->m_dOffsL) < EPS_MACH_LEN_PAR && + abs( m_dOffsR - pDdata->m_dOffsR) < EPS_MACH_LEN_PAR && + m_nWorkSide == pDdata->m_nWorkSide && + m_bToolInvert == pDdata->m_bToolInvert && + m_nFaceUse == pDdata->m_nFaceUse && + m_bInvert == pDdata->m_bInvert && + m_sDepth == pDdata->m_sDepth && + abs( m_dStartPos - pDdata->m_dStartPos) < EPS_MACH_LEN_PAR && + abs( m_dStep - pDdata->m_dStep) < EPS_MACH_LEN_PAR && + abs( m_dStartAddLen - pDdata->m_dStartAddLen) < EPS_MACH_LEN_PAR && + abs( m_dEndAddLen - pDdata->m_dEndAddLen) < EPS_MACH_LEN_PAR && + m_sSysNotes == pDdata->m_sSysNotes && + m_sUserNotes == pDdata->m_sUserNotes) ; +} + +//---------------------------------------------------------------------------- +int +MortisingData::GetSize( void) const +{ + // in debug verifico validità ultimo campo + assert( sMortisingKey[KEY_UUID] == "UUID") ; + return KEY_ZZZ ; +} +//---------------------------------------------------------------------------- +string +MortisingData::GetTitle( void) const +{ + return MCHDATA_GETNAME( MortisingData) ; +} + +//---------------------------------------------------------------------------- +int +FindMortisingKey( const string& sKey) +{ + auto TheRange = equal_range( sMortisingKey.cbegin(), sMortisingKey.cend(), sKey) ; + if ( TheRange.first == TheRange.second) + return - 1 ; + return int( TheRange.first - sMortisingKey.cbegin()) ; +} + +//---------------------------------------------------------------------------- +bool +MortisingData::FromString( const string& sString, int& nKey) +{ + // separo chiave da valore + string sKey, sVal ; + SplitFirst( sString, "=", sKey, sVal) ; + // riconosco la chiave + nKey = FindMortisingKey( ToUpper( sKey)) ; + bool bOk = ( nKey >= 0) ; + switch ( nKey) { + case KEY_AB : + m_sBlockedAxis = sVal ; + break ; + case KEY_AI : + m_sInitAngs = sVal ; + break ; + case KEY_DH : + m_sDepth = sVal ; + if ( m_sDepth.empty()) + m_sDepth = "TH" ; + break ; + case KEY_EAL : + bOk = ::FromString( sVal, m_dEndAddLen) ; + break ; + case KEY_F : + bOk = ::FromString( sVal, m_dFeed) ; + break ; + case KEY_FE : + bOk = ::FromString( sVal, m_dEndFeed) ; + break ; + case KEY_FS : + bOk = ::FromString( sVal, m_dStartFeed) ; + break ; + case KEY_FT : + bOk = ::FromString( sVal, m_dTipFeed) ; + break ; + case KEY_FU : + bOk = ::FromString( sVal, m_nFaceUse) ; + break ; + case KEY_INV : + bOk = ::FromString( sVal, m_bInvert) ; + break ; + case KEY_NAME : + m_sName = sVal ; + bOk = ! m_sName.empty() ; + break ; + case KEY_NNS : + m_sSysNotes = sVal ; + break ; + case KEY_NNU : + m_sUserNotes = sVal ; + break ; + case KEY_OL : + bOk = ::FromString( sVal, m_dOffsL) ; + break ; + case KEY_OR : + bOk = ::FromString( sVal, m_dOffsR) ; + break ; + case KEY_PS : + bOk = ::FromString( sVal, m_dStartPos) ; + break ; + case KEY_S : + bOk = ::FromString( sVal, m_dSpeed) ; + break ; + case KEY_SAL : + bOk = ::FromString( sVal, m_dStartAddLen) ; + break ; + case KEY_SCC : + bOk = ::FromString( sVal, m_nSolCh) ; + break ; + case KEY_ST : + bOk = ::FromString( sVal, m_dStep) ; + break ; + case KEY_TI : + bOk = ::FromString( sVal, m_bToolInvert) ; + break ; + case KEY_TNAME : + m_sToolName = sVal ; + break ; + case KEY_TUUID : + bOk = ::FromString( sVal, m_ToolUuid) ; + break ; + case KEY_UUID : + bOk = ::FromString( sVal, m_Uuid) ; + break ; + case KEY_WS : + bOk = ::FromString( sVal, m_nWorkSide) ; + break ; + default : + bOk = false ; + break ; + } + return bOk ; +} + +//---------------------------------------------------------------------------- +string +MortisingData::ToString( int nKey) const +{ + switch ( nKey) { + case KEY_AB : return ( sMortisingKey[KEY_AB] + "=" + m_sBlockedAxis) ; + case KEY_AI : return ( sMortisingKey[KEY_AI] + "=" + m_sInitAngs) ; + case KEY_DH : return ( sMortisingKey[KEY_DH] + "=" + m_sDepth) ; + case KEY_EAL : return ( sMortisingKey[KEY_EAL] + "=" + ::ToString( m_dEndAddLen)) ; + case KEY_F : return ( sMortisingKey[KEY_F] + "=" + ::ToString( m_dFeed)) ; + case KEY_FE : return ( sMortisingKey[KEY_FE] + "=" + ::ToString( m_dEndFeed)) ; + case KEY_FS : return ( sMortisingKey[KEY_FS] + "=" + ::ToString( m_dStartFeed)) ; + case KEY_FT : return ( sMortisingKey[KEY_FT] + "=" + ::ToString( m_dTipFeed)) ; + case KEY_FU : return ( sMortisingKey[KEY_FU] + "=" + ::ToString( m_nFaceUse)) ; + case KEY_INV : return ( sMortisingKey[KEY_INV] + "=" + ::ToString( m_bInvert)) ; + case KEY_NAME : return ( sMortisingKey[KEY_NAME] + "=" + m_sName) ; + case KEY_NNS : return ( sMortisingKey[KEY_NNS] + "=" + m_sSysNotes) ; + case KEY_NNU : return ( sMortisingKey[KEY_NNU] + "=" + m_sUserNotes) ; + case KEY_OL : return ( sMortisingKey[KEY_OL] + "=" + ::ToString( m_dOffsL)) ; + case KEY_OR : return ( sMortisingKey[KEY_OR] + "=" + ::ToString( m_dOffsR)) ; + case KEY_PS : return ( sMortisingKey[KEY_PS] + "=" + ::ToString( m_dStartPos)) ; + case KEY_S : return ( sMortisingKey[KEY_S] + "=" + ::ToString( m_dSpeed)) ; + case KEY_SAL : return ( sMortisingKey[KEY_SAL] + "=" + ::ToString( m_dStartAddLen)) ; + case KEY_SCC : return ( sMortisingKey[KEY_SCC] + "=" + ::ToString( m_nSolCh)) ; + case KEY_ST : return ( sMortisingKey[KEY_ST] + "=" + ::ToString( m_dStep)) ; + case KEY_TI : return ( sMortisingKey[KEY_TI] + "=" + ::ToString( m_bToolInvert)) ; + case KEY_TNAME : return ( sMortisingKey[KEY_TNAME] + "=" + m_sToolName) ; + case KEY_TUUID : return ( sMortisingKey[KEY_TUUID] + "=" + ::ToString( m_ToolUuid)) ; + case KEY_UUID : return ( sMortisingKey[KEY_UUID] + "=" + ::ToString( m_Uuid)) ; + case KEY_WS : return ( sMortisingKey[KEY_WS] + "=" + ::ToString( m_nWorkSide)) ; + default : return "" ; + } +} + +//---------------------------------------------------------------------------- +bool +MortisingData::IsOptional( int nKey) const +{ + return ( nKey == KEY_ST) ; +} + +//---------------------------------------------------------------------------- +bool +MortisingData::VerifySolCh( int nVal) const +{ + return IsValidOperationScc( nVal) ; +} + +//---------------------------------------------------------------------------- +bool +MortisingData::VerifyFaceUse( int nVal) const +{ + return ( nVal == MILL_FU_NONE || + ( nVal >= MORTISE_FU_PARAL_DOWN && nVal <= MORTISE_FU_PARAL_RIGHT)) ; +} + +//---------------------------------------------------------------------------- +bool +MortisingData::VerifyWorkSide( int nVal) const +{ + return ( nVal == MORTISE_WS_LEFT || nVal == MORTISE_WS_RIGHT) ; +} + +//---------------------------------------------------------------------------- +bool +MortisingData::VerifyTool( const ToolsMgr* pToolsMgr, const std::string& sVal, const ToolData*& pTdata) const +{ + if ( pToolsMgr == nullptr) + return false ; + pTdata = pToolsMgr->GetTool( sVal) ; + if ( pTdata == nullptr) + return false ; + if ( pTdata->m_nType != TT_MORTISE_STD) + return false ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +MortisingData::GetTool( const ToolsMgr* pToolsMgr, const ToolData*& pTdata) const +{ + if ( pToolsMgr == nullptr) + return false ; + pTdata = pToolsMgr->GetTool( m_ToolUuid) ; + return ( pTdata != nullptr) ; +} + +//---------------------------------------------------------------------------- +bool +MortisingData::SetParam( int nType, bool bVal) +{ + switch ( nType) { + case MPA_INVERT : + m_bInvert = bVal ; + return true ; + case MPA_TOOLINVERT : + m_bToolInvert = bVal ; + return true ; + } + return false ; +} + +//---------------------------------------------------------------------------- +bool +MortisingData::SetParam( int nType, int nVal) +{ + switch ( nType) { + case MPA_WORKSIDE : + if ( ! VerifyWorkSide( nVal)) + return false ; + m_nWorkSide = nVal ; + return true ; + case MPA_SCC : + if ( ! VerifySolCh( nVal)) + return false ; + m_nSolCh = nVal ; + return true ; + case MPA_FACEUSE : + if ( ! VerifyFaceUse( nVal)) + return false ; + m_nFaceUse = nVal ; + return true ; + } + return false ; +} + +//---------------------------------------------------------------------------- +bool +MortisingData::SetParam( int nType, double dVal) +{ + switch ( nType) { + case MPA_SPEED : + m_dSpeed = dVal ; + return true ; + case MPA_FEED : + m_dFeed = dVal ; + return true ; + case MPA_STARTFEED : + m_dStartFeed = dVal ; + return true ; + case MPA_ENDFEED : + m_dEndFeed = dVal ; + return true ; + case MPA_TIPFEED : + m_dTipFeed = dVal ; + return true ; + case MPA_OFFSL : + m_dOffsL = dVal ; + return true ; + case MPA_OFFSR : + m_dOffsR = dVal ; + return true ; + case MPA_DEPTH : + m_sDepth = ::ToString( dVal) ; + return true ; + case MPA_STARTPOS : + m_dStartPos = dVal ; + return true ; + case MPA_STEP : + m_dStep = dVal ; + return true ; + case MPA_STARTADDLEN : + m_dStartAddLen = dVal ; + return true ; + case MPA_ENDADDLEN : + m_dEndAddLen = dVal ; + return true ; + } + return false ; +} + +//---------------------------------------------------------------------------- +bool +MortisingData::SetParam( int nType, const string& sVal) +{ + switch ( nType) { + case MPA_NAME : + m_sName = sVal ; + return true ; + case MPA_TOOL : + m_sToolName = sVal ; + return true ; + case MPA_DEPTH_STR : + m_sDepth = sVal ; + return true ; + case MPA_TUUID : + return ::FromString( sVal, m_ToolUuid) ; + case MPA_UUID : + return ::FromString( sVal, m_Uuid) ; + case MPA_SYSNOTES : + m_sSysNotes = sVal ; + return true ; + case MPA_USERNOTES : + m_sUserNotes = sVal ; + return true ; + case MPA_INITANGS : + m_sInitAngs = sVal ; + return true ; + case MPA_BLOCKEDAXIS : + m_sBlockedAxis = sVal ; + return true ; + } + return false ; +} + +//---------------------------------------------------------------------------- +bool +MortisingData::ResetTool( void) +{ + m_sToolName.clear() ; + m_ToolUuid.Clear() ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +MortisingData::GetParam( int nType, bool& bVal) const +{ + switch ( nType) { + case MPA_INVERT : + bVal = m_bInvert ; + return true ; + case MPA_TOOLINVERT : + bVal = m_bToolInvert ; + return true ; + } + bVal = false ; + return false ; +} + +//---------------------------------------------------------------------------- +bool +MortisingData::GetParam( int nType, int& nVal) const +{ + switch ( nType) { + case MPA_TYPE : + nVal = MT_MORTISING ; + return true ; + case MPA_WORKSIDE : + nVal = m_nWorkSide ; + return true ; + case MPA_SCC : + nVal = m_nSolCh ; + return true ; + case MPA_FACEUSE : + nVal = m_nFaceUse ; + return true ; + } + nVal = 0 ; + return false ; +} + +//---------------------------------------------------------------------------- +bool +MortisingData::GetParam( int nType, double& dVal) const +{ + switch ( nType) { + case MPA_SPEED : + dVal = m_dSpeed ; + return true ; + case MPA_FEED : + dVal = m_dFeed ; + return true ; + case MPA_STARTFEED : + dVal = m_dStartFeed ; + return true ; + case MPA_ENDFEED : + dVal = m_dEndFeed ; + return true ; + case MPA_TIPFEED : + dVal = m_dTipFeed ; + return true ; + case MPA_OFFSL : + dVal = m_dOffsL ; + return true ; + case MPA_OFFSR : + dVal = m_dOffsR ; + return true ; + case MPA_STARTPOS : + dVal = m_dStartPos ; + return true ; + case MPA_STEP : + dVal = m_dStep ; + return true ; + case MPA_STARTADDLEN : + dVal = m_dStartAddLen ; + return true ; + case MPA_ENDADDLEN : + dVal = m_dEndAddLen ; + return true ; + } + dVal = 0 ; + return false ; +} + +//---------------------------------------------------------------------------- +bool +MortisingData::GetParam( int nType, string& sVal) const +{ + switch ( nType) { + case MPA_NAME : + sVal = m_sName ; + return true ; + case MPA_TOOL : + sVal = m_sToolName ; + return true ; + case MPA_DEPTH_STR : + sVal = m_sDepth ; + return true ; + case MPA_TUUID : + sVal = ::ToString( m_ToolUuid) ; + return true ; + case MPA_UUID : + sVal = ::ToString( m_Uuid) ; + return true ; + case MPA_SYSNOTES : + sVal = m_sSysNotes ; + return true ; + case MPA_USERNOTES : + sVal = m_sUserNotes ; + return true ; + case MPA_INITANGS : + sVal = m_sInitAngs ; + return true ; + case MPA_BLOCKEDAXIS : + sVal = m_sBlockedAxis ; + return true ; + } + sVal = "" ; + return false ; +} diff --git a/MortisingData.h b/MortisingData.h new file mode 100644 index 0000000..bdfc54b --- /dev/null +++ b/MortisingData.h @@ -0,0 +1,80 @@ +//---------------------------------------------------------------------------- +// EgalTech 2018-2018 +//---------------------------------------------------------------------------- +// File : MortisingData.h Data : 25.02.18 Versione : 1.9c1 +// Contenuto : Dichiarazione della struct MortisingData e costanti associate. +// +// +// +// Modifiche : 25.02.18 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +#pragma once + +#include "MachiningData.h" + +//---------------------------------------------------------------------------- +struct MortisingData : public MachiningData +{ + EgtUUID m_ToolUuid ; // identificativo universale dell'utensile + std::string m_sToolName ; // nome dell'utensile + std::string m_sInitAngs ; // angoli iniziali suggeriti (Nome1=val1,Nome2=val2) + std::string m_sBlockedAxis ; // eventuale asse rotante bloccato (Nome=val) + int m_nSolCh ; // criterio scelta soluzione (quando possibili molteplici) + double m_dSpeed ; // velocità di rotazione (+ se CCW, - se CW) ( se 0 da utensile) + double m_dFeed ; // velocità di lavorazione normale ( se 0 da utensile) + double m_dStartFeed ; // velocità di lavorazione iniziale ( se 0 da utensile) + double m_dEndFeed ; // velocità di lavorazione finale ( se 0 da utensile) + double m_dTipFeed ; // velocità di lavorazione di sfondamento ( se 0 da utensile) + double m_dOffsR ; // offset radiale ( se UNKNOWN_PAR da utensile) + double m_dOffsL ; // offset longitudinale ( se UNKNOWN_PAR da utensile) + bool m_bToolInvert ; // flag per inversione direzione utensile da geometria + int m_nFaceUse ; // metodo di utilizzo della faccia per lavorare + bool m_bInvert ; // flag di inversione direzione lavorazione + int m_nWorkSide ; // lato di lavoro (destra, sinistra) + std::string m_sDepth ; // affondamento (espressione numerica) + double m_dStartPos ; // quota di inizio lavorazione (sempre >= 0) + double m_dStep ; // passo di affondamento (0=nessun passo) + double m_dStartAddLen ; // lunghezza da aggiungere/togliere all'inizio + double m_dEndAddLen ; // lunghezza da aggiungere/togliere alla fine + std::string m_sSysNotes ; // note interne + std::string m_sUserNotes ; // note dell'utente + + MortisingData( void) + : m_ToolUuid(), m_nSolCh( 0), m_dSpeed( 0), m_dFeed( 0), m_dStartFeed( 0), m_dEndFeed( 0), m_dTipFeed( 0), + m_dOffsR( UNKNOWN_PAR), m_dOffsL( UNKNOWN_PAR), + m_bToolInvert( false), m_nFaceUse( 0), m_bInvert( false), m_nWorkSide( 0), m_dStartPos( 0), + m_dStep( 0), m_dStartAddLen( 0), m_dEndAddLen( 0) {} + MortisingData* Clone( void) const override ; + bool CopyFrom( const MachiningData* pMdata) override ; + bool SameAs(const MachiningData* pMdata) const override ; + int GetType( void) const override + { return MT_MORTISING ; } + int GetSize( void) const override ; + std::string GetTitle( void) const override ; + bool FromString( const std::string& sString, int& nKey) override ; + std::string ToString( int nKey) const override ; + bool IsOptional( int nKey) const 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 ResetTool( void) 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 GetTool( const ToolsMgr* pToolsMgr, const ToolData*& pTdata) const override ; + bool VerifyTool( const ToolsMgr* pToolsMgr, const std::string& sVal, const ToolData*& pTdata) const override ; + bool VerifySolCh( int nVal) const ; + bool VerifyFaceUse( int nVal) const ; + bool VerifyWorkSide( int nVal) const ; +} ; + +//---------------------------------------------------------------------------- +inline const MortisingData* GetMortisingData( const MachiningData* pMdata) + { return (dynamic_cast( pMdata)) ; } +inline MortisingData* GetMortisingData( MachiningData* pMdata) + { return (dynamic_cast( pMdata)) ; } diff --git a/Operation.cpp b/Operation.cpp index ec99ba2..94d6462 100644 --- a/Operation.cpp +++ b/Operation.cpp @@ -640,7 +640,7 @@ Operation::ExtractHint( const string& sNotes) //---------------------------------------------------------------------------- bool -Operation::CalculateAxesValues( const string& sHint) +Operation::CalculateAxesValues( const string& sHint, bool bSolChExact) { if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr) return false ; @@ -722,7 +722,7 @@ Operation::CalculateAxesValues( const string& sHint) m_pMchMgr->ApplyRotAxisBlock() ; // applico il criterio di scelta della soluzione quando molteplici - m_pMchMgr->SetCalcSolCh( GetSolCh()) ; + m_pMchMgr->SetCalcSolCh( GetSolCh(), bSolChExact) ; // recupero gruppo della geometria di lavorazione (Cutter Location) int nClId = m_pGeomDB->GetFirstNameInGroup( GetOwner(), MCH_CL) ; diff --git a/Operation.h b/Operation.h index d4da772..80fc20c 100644 --- a/Operation.h +++ b/Operation.h @@ -83,7 +83,7 @@ class Operation : public IUserObj bool GetClPathFinalAxesValues( int nClPathId, DBLVECTOR& vAxVal) ; std::string Operation::ExtractInfo( const std::string& sNotes, const std::string& sKey) ; std::string ExtractHint( const std::string& sNotes) ; - bool CalculateAxesValues( const std::string& sHint) ; + bool CalculateAxesValues( const std::string& sHint, bool bSolChExact = false) ; bool CalculateClPathAxesValues( int nClPathId, int nLinAxes, int nRotAxes, double dRot1W, double dAngDeltaMinForHome, const DBLVECTOR& vAxRotHome, DBLVECTOR& vAxRotPrec, int& nOutStrC) ; bool AdjustStartEndMovements( bool bVerifyPreviousLink = true) ; diff --git a/Simulator.cpp b/Simulator.cpp index 7092829..a5630e1 100644 --- a/Simulator.cpp +++ b/Simulator.cpp @@ -51,6 +51,8 @@ Simulator::Simulator( void) m_nAuxETot = 0 ; m_nAuxEInd = 0 ; m_nVmId = GDB_ID_NULL ; + m_dVmTdOffs = 0 ; + m_dVmAdOffs = 0 ; m_bEnabAxes = true ; m_AxesName.reserve( 8) ; m_AxesToken.reserve( 8) ; @@ -401,6 +403,23 @@ Simulator::UpdateTool( bool bFirst) // aggiorno gli assi macchina if ( ! UpdateAxes()) return false ; + // eventuali offset per Vmill (per adattare lo ZeroT macchina con quello di Zmap) + int nToolType ; m_pMchMgr->TdbGetCurrToolParam( TPA_TYPE, nToolType) ; + if ( nToolType == TT_MORTISE_STD) { + double dThick ; m_pMchMgr->TdbGetCurrToolParam( TPA_THICK, dThick) ; + m_dVmTdOffs = 0 ; + m_dVmAdOffs = 0.5 * dThick ; + } + else if ( nToolType == TT_SAW_STD || nToolType == TT_SAW_FLAT) { + double dLen ; m_pMchMgr->TdbGetCurrToolParam( TPA_LEN, dLen) ; + double dThick ; m_pMchMgr->TdbGetCurrToolParam( TPA_THICK, dThick) ; + m_dVmTdOffs = - dLen + dThick ; + m_dVmAdOffs = 0 ; + } + else { + m_dVmTdOffs = 0 ; + m_dVmAdOffs = 0 ; + } // eventuale lancio script if ( ! OnToolSelect( m_sTool, sHead, nExit, sTcPos, bFirst)) return false ; @@ -598,9 +617,11 @@ Simulator::FindAndManageOperationStart( bool bStart, bool bFirst, int& nStatus) nStatus = MCH_SIM_ERR ; return false ; } - // aggiorno visualizzazione e breve pausa (200 ms) - ExeDraw() ; - Sleep( 200) ; + // se non è inizio, aggiorno visualizzazione e breve pausa (200 ms) + if ( nPhase != 1) { + ExeDraw() ; + Sleep( 200) ; + } } } // passo alla operazione successiva @@ -830,8 +851,8 @@ Simulator::ManageMove( int& nStatus) m_dCoeff = 1 ; // Posizione e direzione attuali dell'utensile e riferimento attuale del pezzo (per Vmill) - Point3d ptNoseI ; Vector3d vtDirI ; Frame3d frVzmI ; - bool bOkI = GetHeadCurrPosDir( ptNoseI, vtDirI) && m_pGeomDB->GetGlobFrame( m_nVmId, frVzmI) ; + Point3d ptNoseI ; Vector3d vtDirI ; Vector3d vtAuxI ; Frame3d frVzmI ; + bool bOkI = GetHeadCurrPosDirAux( ptNoseI, vtDirI, vtAuxI) && m_pGeomDB->GetGlobFrame( m_nVmId, frVzmI) ; // Eseguo movimento rapido o lineare if ( nMoveType != 2 && nMoveType != 3) { @@ -842,9 +863,9 @@ Simulator::ManageMove( int& nStatus) } // eseguo eventuale Vmill if ( m_nVmId != GDB_ID_NULL) { - Point3d ptNoseF ; Vector3d vtDirF ; Frame3d frVzmF ; - bool bOkF = GetHeadCurrPosDir( ptNoseF, vtDirF) && m_pGeomDB->GetGlobFrame( m_nVmId, frVzmF) ; ; - ExecVmillOnLine( ptNoseI, vtDirI, frVzmI, ptNoseF, vtDirF, frVzmF) ; + Point3d ptNoseF ; Vector3d vtDirF ; Vector3d vtAuxF ; Frame3d frVzmF ; + bool bOkF = GetHeadCurrPosDirAux( ptNoseF, vtDirF, vtAuxF) && m_pGeomDB->GetGlobFrame( m_nVmId, frVzmF) ; ; + ExecVmillOnLine( ptNoseI, vtDirI, vtAuxI, frVzmI, ptNoseF, vtDirF, vtAuxF, frVzmF) ; } } // Eseguo movimento su arco @@ -876,9 +897,9 @@ Simulator::ManageMove( int& nStatus) } // eseguo eventuale Vmill if ( m_nVmId != GDB_ID_NULL) { - Point3d ptNoseF ; Vector3d vtDirF ; Frame3d frVzmF ; - bool bOkF = GetHeadCurrPosDir( ptNoseF, vtDirF) && m_pGeomDB->GetGlobFrame( m_nVmId, frVzmF) ; - ExecVmillOnLine( ptNoseI, vtDirI, frVzmI, ptNoseF, vtDirF, frVzmF) ; + Point3d ptNoseF ; Vector3d vtDirF ; Vector3d vtAuxF ; Frame3d frVzmF ; + bool bOkF = GetHeadCurrPosDirAux( ptNoseF, vtDirF, vtAuxF) && m_pGeomDB->GetGlobFrame( m_nVmId, frVzmF) ; + ExecVmillOnLine( ptNoseI, vtDirI, vtAuxI, frVzmI, ptNoseF, vtDirF, vtAuxF, frVzmF) ; // aggiorno prossimo inizio ptNoseI = ptNoseF ; vtDirI = vtDirF ; @@ -934,7 +955,7 @@ Simulator::ManageMove( int& nStatus) //---------------------------------------------------------------------------- bool -Simulator::GetHeadCurrPosDir( Point3d& ptH, Vector3d& vtH) +Simulator::GetHeadCurrPosDirAux( Point3d& ptH, Vector3d& vtH, Vector3d& vtA) { // ci devono essere almeno i tre assi lineari if ( m_AxesName.size() < 3) @@ -950,13 +971,14 @@ Simulator::GetHeadCurrPosDir( Point3d& ptH, Vector3d& vtH) // determino posizione e orientamento della testa m_pMachine->GetNoseFromPositions( vLinAx[0], vLinAx[1], vLinAx[2], vRotAx, ptH) ; m_pMachine->GetToolDirFromAngles( vRotAx, vtH) ; + m_pMachine->GetAuxDirFromAngles( vRotAx, vtA) ; return true ; } //---------------------------------------------------------------------------- bool -Simulator::ExecVmillOnLine( const Point3d& ptHi, const Vector3d& vtHi, const Frame3d& frVzmI, - const Point3d& ptHf, const Vector3d& vtHf, const Frame3d& frVzmF) +Simulator::ExecVmillOnLine( const Point3d& ptHi, const Vector3d& vtHi, const Vector3d& vtAi, const Frame3d& frVzmI, + const Point3d& ptHf, const Vector3d& vtHf, const Vector3d& vtAf, const Frame3d& frVzmF) { // Recupero Zmap IVolZmap* pVZM = GetVolZmap( m_pGeomDB->GetGeoObj( m_nVmId)) ; @@ -965,13 +987,19 @@ Simulator::ExecVmillOnLine( const Point3d& ptHi, const Vector3d& vtHi, const Fra // Porto gli estremi nel riferimento opportuno dello Zmap Point3d ptHiL = ptHi ; ptHiL.ToLoc( frVzmI) ; Vector3d vtHiL = vtHi ; vtHiL.ToLoc( frVzmI) ; + Vector3d vtAiL = vtAi ; vtAiL.ToLoc( frVzmI) ; Point3d ptHfL = ptHf ; ptHfL.ToLoc( frVzmF) ; Vector3d vtHfL = vtHf ; vtHfL.ToLoc( frVzmF) ; + Vector3d vtAfL = vtAf ; vtAfL.ToLoc( frVzmI) ; + // Eventuali offset + ptHiL += m_dVmTdOffs * vtHiL + m_dVmAdOffs * vtAiL ; + ptHfL += m_dVmTdOffs * vtHfL + m_dVmAdOffs * vtAfL ; // Log per debug - //string sOut = "Pi=(" + ToString( ptHiL) + ") Vi=(" + ToString( vtHiL) + ") Pf=(" + ToString( ptHfL) + ") Vf=(" + ToString( vtHfL) + ")" ; + //string sOut = "Pi=(" + ToString( ptHiL) + ") Vi=(" + ToString( vtHiL) + ") Ai=(" + ToString( vtAiL) + + // ") Pf=(" + ToString( ptHfL) + ") Vf=(" + ToString( vtHfL) + ") Af=(" + ToString( vtAfL) + ")" ; //LOG_INFO( GetEMkLogger(), sOut.c_str()) // Eseguo - return pVZM->MillingStep( ptHiL, vtHiL, ptHfL, vtHfL) ; + return pVZM->MillingStep( ptHiL, vtHiL, vtAiL, ptHfL, vtHfL, vtAfL) ; } //---------------------------------------------------------------------------- @@ -1085,10 +1113,8 @@ Simulator::OnToolSelect( const string& sTool, const string& sHead, int nExit, co bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_TOOL_SELECT) ; // forzo aggiornamento posizione assi (possono essere stati mossi nello script) UpdateAxesPos() ; - - // reset assi ausiliari + // recupero i dati di ritorno per assi ausiliari ResetAuxAxes() ; - // recupero i dati di ritorno int nNumAuxAxes = 0 ; if ( ! m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_AUXAXES, nNumAuxAxes) || nNumAuxAxes == 0) return true ; diff --git a/Simulator.h b/Simulator.h index 5b3f2c7..c8bd330 100644 --- a/Simulator.h +++ b/Simulator.h @@ -53,9 +53,9 @@ class Simulator bool ManagePathStartAux( int& nStatus) ; bool ManagePathEndAux( int& nStatus) ; bool ManageMove( int& nStatus) ; - bool GetHeadCurrPosDir( Point3d& ptH, Vector3d& vtH) ; - bool ExecVmillOnLine( const Point3d& ptHi, const Vector3d& vtHi, const Frame3d& frVzmI, - const Point3d& ptHf, const Vector3d& vtHf, const Frame3d& frVzmF) ; + bool GetHeadCurrPosDirAux( Point3d& ptH, Vector3d& vtH, Vector3d& vtA) ; + bool ExecVmillOnLine( const Point3d& ptHi, const Vector3d& vtHi, const Vector3d& vtAi, const Frame3d& frVzmI, + const Point3d& ptHf, const Vector3d& vtHf, const Vector3d& vtAf, const Frame3d& frVzmF) ; bool OnDispositionStarting( int nOpId, int nOpInd, int nPhase, const std::string& sTable, const Point3d& ptOri1, bool bEmpty, bool bSomeByHand) ; bool OnDispositionStart( int nOpId, int nOpInd, int nPhase, @@ -92,6 +92,8 @@ class Simulator int m_nAuxEInd ; // indice del movimento ausiliario di fine percorso corrente std::string m_sTool ; // nome dell'utensile corrente int m_nVmId ; // identificativo dell'oggetto Zmap per Virtual Milling + double m_dVmTdOffs ; // offset utensile in direzione principale per VM + double m_dVmAdOffs ; // offset utensile in direzione ausiliaria per VM bool m_bEnabAxes ; // flag abilitazione movimento assi attivi STRVECTOR m_AxesName ; // nomi degli assi macchina attivi STRVECTOR m_AxesToken ; // token degli assi macchina attivi