f8d2f26692
- se robot sempre spezzatura - spezzatura movimenti per robot - in tagli con lama, tolto da Apply preview.
2422 lines
91 KiB
C++
2422 lines
91 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2015-2023
|
|
//----------------------------------------------------------------------------
|
|
// File : Drilling.cpp Data : 20.12.23 Versione : 2.5l47
|
|
// Contenuto : Implementazione gestione forature.
|
|
//
|
|
// Note : Questa lavorazione è sempre espressa nel riferimento globale.
|
|
//
|
|
// Modifiche : 21.05.15 DS Creazione modulo.
|
|
// 20.12.23 RE Forature multiple con aggregati.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "MachMgr.h"
|
|
#include "DllMain.h"
|
|
#include "Drilling.h"
|
|
#include "OperationConst.h"
|
|
#include "/EgtDev/Include/EXeCmdLogOff.h"
|
|
#include "/EgtDev/Include/EGkGeoPoint3d.h"
|
|
#include "/EgtDev/Include/EGkGeoVector3d.h"
|
|
#include "/EgtDev/Include/EGkCurveLine.h"
|
|
#include "/EgtDev/Include/EGkCurveArc.h"
|
|
#include "/EgtDev/Include/EGkCurveComposite.h"
|
|
#include "/EgtDev/Include/EGkChainCurves.h"
|
|
#include "/EgtDev/Include/EGkSfrCreate.h"
|
|
#include "/EgtDev/Include/EGkUserObjFactory.h"
|
|
#include "/EgtDev/Include/EGnStringKeyVal.h"
|
|
#include "/EgtDev/Include/EgtPointerOwner.h"
|
|
#include "/EgtDev/Include/EGkGeoFrame3d.h"
|
|
|
|
using namespace std ;
|
|
|
|
//------------------------------ Errors --------------------------------------
|
|
// 2101 = "Error in Drilling : UpdateToolData failed"
|
|
// 2102 = "Error in Drilling : Offset not computable"
|
|
// 2103 = "Error in Drilling : Overlap not computable"
|
|
// 2104 = "Error in Drilling : Depth not computable"
|
|
// 2105 = "Error in Drilling : Drill with zero depth"
|
|
// 2106 = "Error in Drilling : Entity xx skipped because missing aggregate from bottom"
|
|
// 2107 = "Error in Drilling : Entity xx skipped because too far from part sides"
|
|
// 2108 = "Error in Drilling : Chaining failed"
|
|
// 2109 = "Error in Drilling : axes values not calculable"
|
|
// 2110 = "Error in Drilling : outstroke xx"
|
|
// 2111 = "Error in Drilling : link movements not calculable"
|
|
// 2112 = "Error in Drilling : link outstroke xx"
|
|
// 2113 = "Error in Drilling : post apply not calculable"
|
|
// 2114 = "Error in Drilling : blind hole not reversible"
|
|
// 2115 = "Error in Drilling : Mirror for Double calculation failed"
|
|
// 2116 = "Error in Drilling : multi drilling head without valid tools"
|
|
// 2117 = "Error in Drilling : incorrect multi drilling head"
|
|
// 2151 = "Warning in Drilling : Skipped entity (xx)"
|
|
// 2152 = "Warning in Drilling : No machinable path"
|
|
// 2153 = "Warning in Drilling : Tool name changed (xx)"
|
|
// 2154 = "Warning in Drilling : Tool data changed (xx)"
|
|
// 2155 = "Warning in Drilling : Drill bit too short for Hole "
|
|
// 2156 = "Warning in Drilling : Skipped by Standard Drilling "
|
|
// 2157 = "Warning in Drilling : Skipped by Peck Drilling "
|
|
|
|
//----------------------------------------------------------------------------
|
|
struct Hole
|
|
{
|
|
int nOriId ; // identificativo della geometria di origine
|
|
Point3d ptIni ; // punto iniziale
|
|
Vector3d vtDir ; // direzione di riferimento (dal fondo verso l'inizio)
|
|
double dDiam ; // diametro
|
|
double dThick ; // lunghezza della geometria originale
|
|
double dLen ; // lunghezza dell'asse
|
|
bool bBlind ; // flag per cieco/passante
|
|
// eventuale tipo ( standard, ribassato, svasato) ?
|
|
Hole( void)
|
|
: nOriId( GDB_ID_NULL), ptIni(), vtDir(), dDiam( 0), dThick( 0), dLen( 0), bBlind( true) {}
|
|
} ;
|
|
|
|
struct MHDrill {
|
|
int nInd_id_hole ; // indice foro
|
|
Vector3d vtAux ; // vettore ausiliario per tale foratura
|
|
} ;
|
|
|
|
struct HoleInfo {
|
|
Hole hole ; // foro
|
|
bool bDrill = false ; // se alla fine verrà lavorato
|
|
bool bTempDrill = false ; // per test maschera (se durante un test viene lavorato o no)
|
|
int nTempTool = -1 ; // per test maschera ( indice utensile che lo lavora durante un test)
|
|
bool bSkipToAngle = false ; // nel caso di più assi rotanti, se foro già lavorato con testa orientata
|
|
bool bForToolM = false ; // se tool main lavorerà questo foro
|
|
int nIndHoleToolM = -1 ; // indice del foro che lo svuoterà inserendo il primo tool in esso
|
|
INTVECTOR vToolHole ; // vettore di indici dei fori ai quali inserire l'ultim punta per lavorare il foro corrente
|
|
INTVECTOR vIndTools ; // vettore dei tool associati ad ogni lavorazione in vToolHole (ordinati)
|
|
VCT3DVECTOR vVtAux ; // vettore dei vtAux ausiliari del tool principale per lavorare questo foro (ordinati)
|
|
int nIndTool = -1 ; // indice del tool che alla fine lavorerà il foro
|
|
Vector3d vtAux ; // vettore ausiliario del tool principale che permette al tool principale di lavorare questo foro
|
|
Point3d ptBtn ; // punto interno alla base del foro
|
|
int nIndInSelVector = 0 ; // indice nel vettore m_vId (id fori selezionati)
|
|
} ;
|
|
|
|
struct ToolInfo
|
|
{
|
|
const ToolData* pTool ; // puntatore per utensile (nullo se utensile non presente)
|
|
Point3d ptToolTip ; // punto finale del tool (per ptBtn del foro)
|
|
ToolInfo( void)
|
|
: pTool( nullptr) {}
|
|
ToolInfo( const ToolData* pT)
|
|
: pTool( pT) {}
|
|
} ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
USEROBJ_REGISTER( GetOperationClass( OPER_DRILLING), Drilling) ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
const string&
|
|
Drilling::GetClassName( void) const
|
|
{
|
|
return USEROBJ_GETNAME( Drilling) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
Drilling*
|
|
Drilling::Clone( void) const
|
|
{
|
|
// alloco oggetto
|
|
Drilling* pDri = new(nothrow) Drilling ;
|
|
// eseguo copia dei dati
|
|
if ( pDri != nullptr) {
|
|
try {
|
|
pDri->m_vId = m_vId ;
|
|
pDri->m_pMchMgr = m_pMchMgr ;
|
|
pDri->m_nPhase = m_nPhase ;
|
|
pDri->m_Params = m_Params ;
|
|
pDri->m_TParams = m_TParams ;
|
|
pDri->m_nStatus = m_nStatus ;
|
|
pDri->m_nDrillings = m_nDrillings ;
|
|
pDri->m_bTiltingTab = m_bTiltingTab ;
|
|
pDri->m_vtTiltingAx = m_vtTiltingAx ;
|
|
pDri->m_bAboveHead = m_bAboveHead ;
|
|
pDri->m_bAggrBottom = m_bAggrBottom ;
|
|
}
|
|
catch( ...) {
|
|
delete pDri ;
|
|
return nullptr ;
|
|
}
|
|
}
|
|
// ritorno l'oggetto
|
|
return pDri ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::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_nDrillings) + szNewLine ;
|
|
sOut += KEY_STAT + EQUAL + ToString( m_nStatus) + szNewLine ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::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_nDrillings, vString[++k]))
|
|
return false ;
|
|
if ( ! SetVal( KEY_STAT, m_nStatus, vString[++k]))
|
|
return false ;
|
|
}
|
|
catch( ...) {
|
|
return false ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::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_nDrillings))
|
|
return false ;
|
|
}
|
|
else if ( sKey == KEY_STAT) {
|
|
if ( ! FromString( sVal, m_nStatus))
|
|
return false ;
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
Drilling::Drilling( void)
|
|
{
|
|
m_Params.m_sName = "*" ;
|
|
m_Params.m_sToolName = "*" ;
|
|
m_TParams.m_sName = "*" ;
|
|
m_TParams.m_sHead = "*" ;
|
|
m_nStatus = MCH_ST_TO_VERIFY ;
|
|
m_nDrillings = 0 ;
|
|
m_bTiltingTab = false ;
|
|
m_bAboveHead = true ;
|
|
m_bAggrBottom = false ;
|
|
m_dDistBottom = 0 ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::Prepare( const string& sDriName)
|
|
{
|
|
// 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 DrillingData* pDdata = GetDrillingData( pMMgr->GetMachining( sDriName)) ;
|
|
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
|
|
Drilling::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
|
|
Drilling::SetParam( int nType, int nVal)
|
|
{
|
|
switch ( nType) {
|
|
case MPA_SUBTYPE :
|
|
if ( nVal != m_Params.m_nSubType)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_nSubType = 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
|
|
Drilling::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)
|
|
dVal = 0 ;
|
|
if ( abs( dVal - m_Params.m_dSpeed) > EPS_MACH_ANG_PAR)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dSpeed = dVal ;
|
|
return true ;
|
|
case MPA_FEED :
|
|
if ( abs( m_TParams.m_dFeed - dVal) < EPS_MACH_LEN_PAR)
|
|
dVal = 0 ;
|
|
if ( abs( dVal - m_Params.m_dFeed) > EPS_MACH_LEN_PAR)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dFeed = dVal ;
|
|
return true ;
|
|
case MPA_STARTFEED :
|
|
if ( abs( m_TParams.m_dStartFeed - dVal) < EPS_MACH_LEN_PAR)
|
|
dVal = 0 ;
|
|
if ( abs( dVal - m_Params.m_dStartFeed) > EPS_MACH_LEN_PAR)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dStartFeed = dVal ;
|
|
return true ;
|
|
case MPA_ENDFEED :
|
|
if ( abs( m_TParams.m_dEndFeed - dVal) < EPS_MACH_LEN_PAR)
|
|
dVal = 0 ;
|
|
if ( abs( dVal - m_Params.m_dEndFeed) > EPS_MACH_LEN_PAR)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dEndFeed = dVal ;
|
|
return true ;
|
|
case MPA_TIPFEED :
|
|
if ( abs( m_TParams.m_dTipFeed - dVal) < EPS_MACH_LEN_PAR)
|
|
dVal = 0 ;
|
|
if ( abs( dVal - m_Params.m_dTipFeed) > EPS_MACH_LEN_PAR)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dTipFeed = 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 ( abs( dVal - m_Params.m_dStartPos) > EPS_MACH_LEN_PAR)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dStartPos = dVal ;
|
|
return true ;
|
|
case MPA_STARTSLOWLEN :
|
|
if ( abs( dVal - m_Params.m_dStartSlowLen) > EPS_MACH_LEN_PAR)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dStartSlowLen = dVal ;
|
|
return true ;
|
|
case MPA_ENDSLOWLEN :
|
|
if ( abs( dVal - m_Params.m_dEndSlowLen) > EPS_MACH_LEN_PAR)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dEndSlowLen = dVal ;
|
|
return true ;
|
|
case MPA_THROUADDLEN :
|
|
if ( abs( dVal - m_Params.m_dThroughAddLen) > EPS_MACH_LEN_PAR)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dThroughAddLen = dVal ;
|
|
return true ;
|
|
case MPA_STEP :
|
|
if ( abs( dVal - m_Params.m_dStep) > EPS_MACH_LEN_PAR)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dStep = dVal ;
|
|
return true ;
|
|
case MPA_RETURNPOS :
|
|
if ( abs( dVal - m_Params.m_dReturnPos) > EPS_MACH_LEN_PAR)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dReturnPos = dVal ;
|
|
return true ;
|
|
case MPA_OVERLAP : {
|
|
string sVal = ToString( dVal) ;
|
|
if ( sVal != m_Params.m_sOverlap)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_sOverlap = sVal ;
|
|
} return true ;
|
|
case MPA_STARTADDLEN :
|
|
if ( abs( dVal - m_Params.m_dStartAddLen) > EPS_MACH_LEN_PAR)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dStartAddLen = dVal ;
|
|
return true ;
|
|
case MPA_ENDADDLEN :
|
|
if ( abs( dVal - m_Params.m_dEndAddLen) > EPS_MACH_LEN_PAR)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dEndAddLen = dVal ;
|
|
return true ;
|
|
case MPA_OFFSET : {
|
|
string sVal = ToString( dVal) ;
|
|
if ( sVal != m_Params.m_sOverlap)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_sOffset = sVal ;
|
|
} return true ;
|
|
}
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::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_OVERLAP_STR :
|
|
if ( sVal != m_Params.m_sOverlap)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_sOverlap = sVal ;
|
|
return true ;
|
|
case MPA_OFFSET_STR :
|
|
if ( sVal != m_Params.m_sOffset)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_sOffset = 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
|
|
Drilling::SetGeometry( const SELVECTOR& vIds)
|
|
{
|
|
// verifico validità gestore generale e gestore DB geometrico
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return false ;
|
|
// reset della geometria corrente
|
|
m_vId.clear() ;
|
|
// se lavorazione standard
|
|
if ( m_Params.m_nSubType == DRI_SUB_STD) {
|
|
// recupero il valore di tolleranza sul diametro
|
|
//double dDiamTol = m_pMchMgr->GetCurrMachiningsMgr()->GetHoleDiamToler() ;
|
|
// verifico che gli identificativi rappresentino dei fori con il corretto diametro
|
|
for ( int i = 0 ; i < int( vIds.size()) ; ++ i) {
|
|
// recupero i dati del foro
|
|
//Hole hole ;
|
|
//if ( ! GetHoleData( vIds[i], hole) || !VerifyDiameter(hole.dDiam, m_TParams.m_dDiam, dDiamTol)) {
|
|
// string sInfo = "Warning in Drilling : Skipped entity " + ToString( vIds[i].nId) ;
|
|
// m_pMchMgr->SetWarning( 2151, sInfo) ;
|
|
// continue ;
|
|
//}
|
|
// posso aggiungere alla lista
|
|
m_vId.push_back( vIds[i]) ;
|
|
}
|
|
}
|
|
// altrimenti se lavorazione lungo curve
|
|
else if ( m_Params.m_nSubType == DRI_SUB_ALONG_CURVE) {
|
|
// verifico che gli identificativi rappresentino delle curve
|
|
for ( int i = 0 ; i < int( vIds.size()) ; ++ i) {
|
|
if ( ( m_pGeomDB->GetGeoType( vIds[i].nId) & GEO_CURVE) == 0) {
|
|
string sInfo = "Warning in Drilling : Skipped entity " + ToString( vIds[i].nId) ;
|
|
m_pMchMgr->SetWarning( 2151, sInfo) ;
|
|
continue ;
|
|
}
|
|
// posso aggiungere alla lista
|
|
m_vId.push_back( vIds[i]) ;
|
|
}
|
|
}
|
|
// aggiorno lo stato
|
|
m_nStatus |= MCH_ST_GEO_MODIF ;
|
|
// restituisco presenza geometria da lavorare
|
|
return ( ! m_vId.empty()) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::Preview( bool bRecalc)
|
|
{
|
|
// reset numero forature nella lavorazione
|
|
m_nDrillings = 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 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) ;
|
|
|
|
// aggiorno dati geometrici dell'utensile
|
|
if ( ! UpdateToolData()) {
|
|
m_pMchMgr->SetLastError( 2101, "Error in Drilling : UpdateToolData failed") ;
|
|
return false ;
|
|
}
|
|
|
|
// se lavorazione standard
|
|
if ( m_Params.m_nSubType == DRI_SUB_STD)
|
|
return StandardProcess( bRecalc, nPvId, GDB_ID_NULL) ;
|
|
// se altrimenti lavorazione lungo curve
|
|
else if ( m_Params.m_nSubType == DRI_SUB_ALONG_CURVE)
|
|
return AlongCurveProcess( bRecalc, nPvId, GDB_ID_NULL) ;
|
|
// altrimenti errore
|
|
else
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::Apply( bool bRecalc, bool bPostApply)
|
|
{
|
|
// reset numero forature nella lavorazione
|
|
int nCurrDrillings = m_nDrillings ;
|
|
m_nDrillings = 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( 2101, "Error in Drilling : 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))) {
|
|
// confermo i percorsi di lavorazione
|
|
m_nDrillings = nCurrDrillings ;
|
|
LOG_DBG_INFO( GetEMkLogger(), "Drilling apply skipped : status already ok") ;
|
|
// eseguo aggiornamento assi macchina e collegamento con operazione precedente
|
|
if ( ! Update( bPostApply))
|
|
return false ;
|
|
LOG_DBG_INFO( GetEMkLogger(), "Update done") ;
|
|
// esco con successo
|
|
return true ;
|
|
}
|
|
m_nStatus = MCH_ST_TO_VERIFY ;
|
|
|
|
// 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) ;
|
|
|
|
// elimino eventuale gruppo geometria simmetrica per lavorazione in doppio
|
|
int nDblId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_DBL) ;
|
|
if ( nDblId != GDB_ID_NULL) {
|
|
m_pGeomDB->Erase( nDblId) ;
|
|
nDblId = GDB_ID_NULL ;
|
|
}
|
|
|
|
// 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( 2322, "Error in Milling : Tool loading failed") ;
|
|
return false ;
|
|
}
|
|
|
|
// se lavorazione standard
|
|
if ( m_Params.m_nSubType == DRI_SUB_STD) {
|
|
if ( ! StandardProcess( bRecalc, GDB_ID_NULL, nClId))
|
|
return false ;
|
|
}
|
|
// se altrimenti lavorazione lungo curve
|
|
else if ( m_Params.m_nSubType == DRI_SUB_ALONG_CURVE) {
|
|
if ( ! AlongCurveProcess( bRecalc, GDB_ID_NULL, nClId))
|
|
return false ;
|
|
}
|
|
// altrimenti errore
|
|
else
|
|
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 ;
|
|
|
|
// se lavorazione in doppio, aggiungo geometria della parte simmetrica
|
|
if ( ! CalcMirrorByDouble( nClId, m_Params.m_sUserNotes)) {
|
|
m_pMchMgr->SetLastError( 2115, "Error in Drilling : Mirror for Double calculation failed") ;
|
|
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) ;
|
|
|
|
LOG_DBG_INFO( GetEMkLogger(), "Drilling apply done") ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::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_nDrillings == 0) {
|
|
m_pMchMgr->SetWarning( 2152, "Warning in Drilling : No machinable hole") ;
|
|
return true ;
|
|
}
|
|
|
|
// elimino le entità CLIMB, RISE e HOME della lavorazione, potrebbero falsare i calcoli degli assi (in ogni casi vengono riaggiunte dopo)
|
|
RemoveClimbRiseHome() ;
|
|
|
|
// imposto eventuale asse bloccato da lavorazione
|
|
SetBlockedRotAxis( m_Params.m_sBlockedAxis) ;
|
|
|
|
// 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( 2109, "Error in Drilling : axes values not calculable") ;
|
|
else
|
|
m_pMchMgr->SetLastError( 2110, "Error in Drilling : 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( 2111, "Error in Drilling : link movements not calculable") ;
|
|
else
|
|
m_pMchMgr->SetLastError( 2112, "Error in Drilling : link outstroke ") ;
|
|
return false ;
|
|
}
|
|
|
|
// assegno estremi degli assi dei vari percorsi di lavorazione e della lavorazione nel suo complesso
|
|
CalcAndSetAxesBBox() ;
|
|
|
|
// esecuzione eventuali personalizzazioni
|
|
string sErr ;
|
|
if ( bPostApply && ! PostApply( sErr)) {
|
|
if ( ! IsEmptyOrSpaces( sErr))
|
|
m_pMchMgr->SetLastError( 2113, sErr) ;
|
|
else
|
|
m_pMchMgr->SetLastError( 2113, "Error in Drilling : post apply not calculable") ;
|
|
return false ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::VerifyMultiParallelFixedDrills( void)
|
|
{
|
|
// se aggregato da sotto, sicuramente con una sola punta
|
|
bool bAggrBottom = IsAggrBottom( m_TParams.m_sHead) ;
|
|
if ( bAggrBottom)
|
|
return false ;
|
|
// se una sola uscita, inutile continuare
|
|
int nExitCnt = m_pMchMgr->GetCurrMachine()->GetHeadExitCount( m_TParams.m_sHead) ;
|
|
if ( nExitCnt == 1)
|
|
return false ;
|
|
// verifico che le uscite siano fisse
|
|
int nSelectType = m_pMchMgr->GetCurrMachine()->GetHeadSelectType( m_TParams.m_sHead) ;
|
|
if ( nSelectType != MCH_SLT_FIXEDEXITS)
|
|
return false ;
|
|
// recupero la direzione dell'utensile principale
|
|
Point3d ptMainExit ; Vector3d vtMainTool, vtMainAux ;
|
|
m_pMchMgr->GetCurrMachine()->GetHeadExitPosDirAux( m_TParams.m_sHead, m_TParams.m_nExit, ptMainExit, vtMainTool, vtMainAux) ;
|
|
// verifico ci sia almeno un'altra uscita attrezzata parallela a quella principale
|
|
for ( int nT = 0 ; nT < nExitCnt ; ++ nT) {
|
|
if ( nT + 1 == m_TParams.m_nExit)
|
|
continue ;
|
|
string sToolName ;
|
|
if ( m_pMchMgr->GetLoadedTool( m_TParams.m_sHead, nT + 1, sToolName) && ! sToolName.empty()) {
|
|
Point3d ptExit ; Vector3d vtTool, vtAux ;
|
|
if ( m_pMchMgr->GetCurrMachine()->GetHeadExitPosDirAux(m_TParams.m_sHead, nT + 1, ptExit, vtTool, vtAux) &&
|
|
AreSameVectorApprox( vtTool, vtMainTool))
|
|
return true ;
|
|
}
|
|
}
|
|
// non è stato trovato niente
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::StandardProcess( bool bRecalc, int nPvId, int nClId)
|
|
{
|
|
// se ho almeno un'altra punta fissa parallela alla principale ...
|
|
if ( VerifyMultiParallelFixedDrills()) {
|
|
TABMHDRILL tabDrills ;
|
|
double dMHOff = 0 ;
|
|
if ( ! MultiHeadDrilling( m_vId, nClId, tabDrills, dMHOff))
|
|
return false ;
|
|
if ( tabDrills.empty())
|
|
return true ;
|
|
for ( int i = 0 ; i < ( int)tabDrills.size() ; ++i) {
|
|
// se richiesto preview
|
|
if ( nPvId != GDB_ID_NULL) {
|
|
if ( ! GenerateHolePv( i, m_vId[tabDrills[i][0].nInd_id_hole], MCH_PATH, nClId))
|
|
return false ;
|
|
// creo la regione di ingombro del foro
|
|
int nDriId = m_pGeomDB->GetFirstInGroup( m_pGeomDB->GetLastGroupInGroup( nPvId)) ;
|
|
GenerateHoleRegionPv( nDriId, 1, nPvId) ;
|
|
}
|
|
// se richiesta lavorazione
|
|
if ( nClId != GDB_ID_NULL) {
|
|
if ( ! GenerateHoleCl( i, m_vId[tabDrills[i][0].nInd_id_hole], MCH_PATH, nClId, dMHOff, tabDrills[i][0].vtAux))
|
|
return false ;
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
// ... altrimenti elaboro i singoli fori
|
|
for ( int i = 0 ; i < int( m_vId.size()) ; ++ i) {
|
|
const auto& vId = m_vId[i] ;
|
|
// se richiesto preview
|
|
if ( nPvId != GDB_ID_NULL) {
|
|
if ( ! GenerateHolePv( i, vId, MCH_PATH, nPvId))
|
|
return false ;
|
|
// creo la regione di ingombro del foro
|
|
int nDriId = m_pGeomDB->GetFirstInGroup( m_pGeomDB->GetLastGroupInGroup( nPvId)) ;
|
|
GenerateHoleRegionPv( nDriId, 1, nPvId) ;
|
|
}
|
|
// se richiesta lavorazione
|
|
if ( nClId != GDB_ID_NULL) {
|
|
if ( ! GenerateHoleCl( i, vId, MCH_PATH, nClId))
|
|
return false ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::MultiHeadDrilling( const SELVECTOR& vId, int nClId, TABMHDRILL& tabDrills, double& dMHOff, bool bOrd)
|
|
{
|
|
// controllo parametri
|
|
tabDrills.clear() ;
|
|
if ( vId.empty())
|
|
return true ;
|
|
|
|
// gestore degli utensili
|
|
ToolsMgr* pTMgr = m_pMchMgr->GetCurrToolsMgr() ;
|
|
if ( pTMgr == nullptr)
|
|
return false ;
|
|
|
|
// recupero il nome della testa e il numero di uscite
|
|
string sHead ;
|
|
m_pMchMgr->GetCurrMachine()->GetCurrHead( sHead) ;
|
|
int nExitCnt = m_pMchMgr->GetCurrMachine()->GetHeadExitCount( sHead) ;
|
|
|
|
// Recupero i dati degli utensili montati sulla testa
|
|
int nMainToolInd = -1 ;
|
|
VECTORTOOL vTools ; vTools.reserve( nExitCnt) ;
|
|
// ricavo gli utensili presenti sulle uscite
|
|
for ( int nT = 0 ; nT < nExitCnt ; ++ nT) {
|
|
string sToolName ;
|
|
if ( ! m_pMchMgr->GetLoadedTool( sHead, nT + 1, sToolName) || sToolName.empty()) {
|
|
// non c'è utensile
|
|
vTools.emplace_back( nullptr) ;
|
|
continue ;
|
|
}
|
|
// se presente e valido
|
|
const ToolData* pTdata = pTMgr->GetTool( sToolName) ;
|
|
vTools.emplace_back( pTdata) ;
|
|
|
|
// imposto il tool di riferimento come il tool m_TParams
|
|
if ( pTdata->m_Uuid == m_TParams.m_Uuid)
|
|
nMainToolInd = nT ;
|
|
}
|
|
// se non ho utensili attivi o validi, errore
|
|
if ( nMainToolInd == -1 || vTools.empty()) {
|
|
m_pMchMgr->SetLastError( 2116, "Error in Drilling : multi drilling head without valid tools") ;
|
|
return false ;
|
|
}
|
|
|
|
// recupero i dati dell'uscita dell'utensile principale
|
|
Vector3d vtTool, vtAux ;
|
|
Point3d ptExit ;
|
|
m_pMchMgr->GetCurrMachine()->GetHeadExitPosDirAux( sHead, nMainToolInd + 1, ptExit, vtTool, vtAux) ;
|
|
vTools[nMainToolInd].ptToolTip = ptExit - vtTool * vTools[nMainToolInd].pTool->m_dLen ;
|
|
if ( vtAux.IsSmall() && m_pMchMgr->GetCurrMachine()->GetCurrRotAxes() == 0)
|
|
vtAux = FromUprightOrtho( vtTool) ;
|
|
if ( vtTool.IsSmall() || vtAux.IsSmall()) {
|
|
m_pMchMgr->SetLastError( 2117, "Error in Drilling : incorrect multi drilling head") ;
|
|
return false ;
|
|
}
|
|
|
|
// carico gli altri dati della testa con le sue uscite
|
|
for ( int nT = 0 ; nT < nExitCnt ; ++ nT) {
|
|
// se utensile principale, salto al successivo
|
|
if ( nT == nMainToolInd)
|
|
continue ;
|
|
// se non attrezzato, salto al successivo
|
|
if ( vTools[nT].pTool == nullptr)
|
|
continue ;
|
|
// recupero i dati dell'uscita
|
|
Point3d ptExit ;
|
|
Vector3d vtCurrDir, vtCurrAux ;
|
|
m_pMchMgr->GetCurrMachine()->GetHeadExitPosDirAux( sHead, nT + 1, ptExit, vtCurrDir, vtCurrAux) ;
|
|
// controllo abbia la stessa direzione del principale, altrimenti disattrezzo
|
|
if ( ! AreSameVectorApprox( vtCurrDir, vtTool)) {
|
|
vTools[nT].pTool = nullptr ;
|
|
continue ;
|
|
}
|
|
// assegno tip utensile
|
|
vTools[nT].ptToolTip = ptExit - vtCurrDir * vTools[nT].pTool->m_dLen ;
|
|
}
|
|
|
|
// Recupero le geometrie dei fori
|
|
bool bSomeHoleOk = false ;
|
|
VECTORHOLE vHoles( vId.size()) ;
|
|
for ( int h = 0 ; h < ( int)vId.size() ; ++ h) {
|
|
Hole hole ;
|
|
if ( ! GetHoleData( m_vId[h], hole)) {
|
|
string sInfo = "Warning in Drilling : Skipped entity " + ToString( m_vId[h]) ;
|
|
m_pMchMgr->SetWarning( 2151, sInfo) ;
|
|
continue ;
|
|
}
|
|
// se richiesta inversione e foro passante, provvedo
|
|
if ( m_Params.m_bInvert) {
|
|
if ( hole.bBlind) {
|
|
m_pMchMgr->SetLastError( 2114, "Error in Drilling : blind hole not reversible") ;
|
|
return false ;
|
|
}
|
|
else {
|
|
hole.ptIni -= hole.vtDir * hole.dThick ;
|
|
hole.vtDir.Invert() ;
|
|
}
|
|
}
|
|
// se lavorazione del foro non arriva al suo fondo, lo considero cieco
|
|
if ( hole.dLen < hole.dThick - 10 * EPS_SMALL)
|
|
hole.bBlind = true ;
|
|
|
|
vHoles[h].hole = hole ;
|
|
vHoles[h].nIndInSelVector = h ;
|
|
bSomeHoleOk = true ;
|
|
}
|
|
if ( ! bSomeHoleOk)
|
|
return true ;
|
|
|
|
// calcolo la corrispondenza tra utensili e fori
|
|
if ( ! CalcMask( vHoles, vTools, nMainToolInd, vtTool, vtAux))
|
|
return false ;
|
|
|
|
// i fori con dimensione 0 del vettore vToolHole non possono essere lavorati
|
|
int nNoDrillHoles = 0 ;
|
|
for ( int i = 0 ; i < ( int)vHoles.size() ; ++ i) {
|
|
if ( vHoles[i].vToolHole.empty())
|
|
++ nNoDrillHoles ;
|
|
}
|
|
|
|
// resetto le variabili di controllo di lavorazione temporanea per tutti i fori
|
|
for ( int k = 0 ; k < ( int)vHoles.size() ; ++k)
|
|
vHoles[k].bTempDrill = false ;
|
|
|
|
// numero di fori lavorati
|
|
int nOkHole = 0 ;
|
|
|
|
// se c'è un solo foro va sicuramente bene
|
|
if ( vHoles.size() == 1 && ! vHoles[0].vVtAux.empty()) {
|
|
vHoles[0].bForToolM = true ;
|
|
vHoles[0].nIndTool = nMainToolInd ;
|
|
vHoles[0].nIndHoleToolM = 0 ;
|
|
vHoles[0].vtAux = vHoles[0].vVtAux[0] ;
|
|
}
|
|
|
|
// decido in quali fori inserire il tool principale
|
|
for ( int nCheck = 1 ; nCheck < ( int)vHoles.size() && nOkHole < ( int)vHoles.size() - nNoDrillHoles ; ++ nCheck) {
|
|
for ( int i = 0 ; i < ( int)vHoles.size() ; ++i) {
|
|
// prendo tutti i fori con vToolHope di lunghezza nCheck non già lavorati
|
|
if ( vHoles[i].vToolHole.size() == nCheck && ! vHoles[i].bDrill) {
|
|
vHoles[vHoles[i].vToolHole[0]].bForToolM = true ;
|
|
vHoles[vHoles[i].vToolHole[0]].nIndTool = nMainToolInd ;
|
|
vHoles[vHoles[i].vToolHole[0]].nIndHoleToolM = vHoles[i].vToolHole[0] ;
|
|
vHoles[vHoles[i].vToolHole[0]].vtAux = vHoles[i].vVtAux[0] ;
|
|
for ( int k = 0 ; k < ( int)vHoles.size() ; ++k) {
|
|
for ( int l = 0 ; l < ( int)vHoles[k].vToolHole.size() ; ++l) {
|
|
if ( vHoles[k].vToolHole[l] == vHoles[i].vToolHole[0] && ! vHoles[k].bDrill) {
|
|
vHoles[k].bDrill = true ;
|
|
vHoles[k].nIndTool = vHoles[k].vIndTools[0] ;
|
|
vHoles[k].nIndHoleToolM = vHoles[vHoles[i].vToolHole[0]].nIndHoleToolM ;
|
|
vHoles[k].vtAux = vHoles[k].vVtAux[l] ;
|
|
++ nOkHole ;
|
|
break ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// calcolo la massima differenza di lunghezza tra il primo tool e gli altri ( così l'elevazione finale rimane compatibile)
|
|
double dRefLen = vTools[nMainToolInd].pTool->m_dTLen ;
|
|
double dOffMax = 0 ;
|
|
for ( int nT = 0 ; nT < ( int)vTools.size() && nNoDrillHoles != (int)vHoles.size() ; ++ nT) {
|
|
if ( vTools[nT].pTool == nullptr || nT == nMainToolInd)
|
|
continue ;
|
|
if ( vTools[nT].pTool->m_dTLen > dRefLen + dOffMax) {
|
|
dOffMax = vTools[nT].pTool->m_dTLen - dRefLen ;
|
|
}
|
|
}
|
|
dMHOff = dOffMax ;
|
|
|
|
// riempio la maschera
|
|
VCT3DVECTOR vVtA ;
|
|
for ( int i = 0 ; i < ( int)vHoles.size() && nNoDrillHoles != ( int)vHoles.size() ; ++ i) {
|
|
if ( ! vHoles[i].bForToolM)
|
|
continue ;
|
|
// per tutti i fori che vengono svuotati da un tool t-esimo conto quanti versori A diversi tra loro trovo
|
|
for ( int j = 0 ; j < ( int)vHoles.size() ; ++j) {
|
|
if ( vHoles[j].nIndHoleToolM != i)
|
|
continue ;
|
|
if ( vVtA.empty())
|
|
vVtA.push_back( vHoles[j].vtAux) ;
|
|
else {
|
|
bool bPush = true ;
|
|
for ( int v = 0 ; v < ( int)vVtA.size() ; ++ v) {
|
|
if ( AreSameVectorApprox( vHoles[j].vtAux, vVtA[v])) {
|
|
bPush = false ;
|
|
break ;
|
|
}
|
|
}
|
|
if ( bPush)
|
|
vVtA.push_back( vHoles[j].vtAux) ;
|
|
}
|
|
}
|
|
|
|
for ( int v = 0 ; v < ( int)vVtA.size() ; ++ v) {
|
|
vector<MHDrill> vRowDrill ;
|
|
MHDrill FirstMHDrill ;
|
|
FirstMHDrill.nInd_id_hole = i ;
|
|
FirstMHDrill.vtAux = vVtA[v] ;
|
|
vRowDrill.push_back( FirstMHDrill) ;
|
|
tabDrills.push_back( vRowDrill) ;
|
|
}
|
|
vVtA.clear() ;
|
|
}
|
|
// se non trovo corrispondenze ...
|
|
if ( tabDrills.empty())
|
|
return true ;
|
|
|
|
// se devo riordinare
|
|
if ( bOrd) {
|
|
struct Order {
|
|
int nInd_id_hole ;
|
|
Point3d ptIni ;
|
|
} ;
|
|
vector<Order> vOrder ;
|
|
for ( int i = 0 ; i < ( int)tabDrills.size() ; ++ i) {
|
|
Order newOrder ;
|
|
newOrder.nInd_id_hole = tabDrills[i][0].nInd_id_hole ;
|
|
newOrder.ptIni = vHoles[tabDrills[i][0].nInd_id_hole].hole.ptIni ;
|
|
vOrder.push_back( newOrder) ;
|
|
}
|
|
|
|
// prendo come riferimento il punto del primo foro selezionato dall'utente
|
|
Point3d ptRef = vOrder[0].ptIni ;
|
|
double dMinDist = INFINITO ;
|
|
int nIndexSwitch = -1 ;
|
|
for ( int i = 0 ; i < ( int)vOrder.size() - 1 ; ++ i) {
|
|
for ( int j = i + 1 ; j < ( int)vOrder.size() ; ++ j) {
|
|
Point3d ptS = vOrder[j].ptIni ;
|
|
if ( Dist( ptS, ptRef) < dMinDist) {
|
|
dMinDist = Dist( ptS, ptRef) ;
|
|
nIndexSwitch = j ;
|
|
}
|
|
}
|
|
if ( nIndexSwitch != i + 1) {
|
|
vector<MHDrill> VHelp = tabDrills[nIndexSwitch] ;
|
|
tabDrills[nIndexSwitch] = tabDrills[i + 1] ;
|
|
tabDrills[i + 1] = VHelp ;
|
|
}
|
|
ptRef = vOrder[i + 1].ptIni ;
|
|
dMinDist = INFINITO ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::CalcMask( VECTORHOLE& vHoles, const VECTORTOOL& vTools, int nIndMT, const Vector3d& vtTool, const Vector3d& vtAux)
|
|
{
|
|
// controllo dei parametri
|
|
if ( vHoles.empty() || vTools.empty())
|
|
return false ;
|
|
|
|
// recupero il valore di tolleranza sul diametro
|
|
double dDiamToler = m_pMchMgr->GetCurrMachiningsMgr()->GetHoleDiamToler() ;
|
|
|
|
int nExitCnt = ( int)vTools.size() ;
|
|
int nNullTools = 0 ;
|
|
for ( int i = 0 ; i < ( int)vTools.size() ; ++ i) {
|
|
if ( vTools[i].pTool == nullptr)
|
|
++ nNullTools ;
|
|
}
|
|
|
|
// in ogni foro i-esimo inserisco il Tool principale
|
|
for ( int i = 0 ; i < ( int)vHoles.size() ; ++ i) {
|
|
|
|
// resetto le veriabili di controllo di svuotatura temporanea per tutti i fori
|
|
for ( int k = 0 ; k < ( int)vHoles.size() ; ++ k) {
|
|
vHoles[k].bTempDrill = false ;
|
|
vHoles[k].nTempTool = -1 ;
|
|
}
|
|
|
|
// verifica validità del foro i-esimo per il Tool principale
|
|
Hole Hole_i = vHoles[i].hole ;
|
|
if ( ! MultiHeadVerifyHole( Hole_i, vTools[nIndMT].pTool, dDiamToler, m_vId[vHoles[i].nIndInSelVector]))
|
|
continue ;
|
|
|
|
int nStat ;
|
|
DBLVECTOR vAng1, vAng2 ;
|
|
// angoli per allineare T del tool principale con vtDir del foro i-esimo
|
|
if ( ! m_pMchMgr->GetCalcAngles( Hole_i.vtDir, V_NULL, nStat, vAng1, vAng2))
|
|
continue ;
|
|
Vector3d vtTnew ;
|
|
// check che T sia allineato con vtDir
|
|
if ( ! m_pMchMgr->GetCalcToolDirFromAngles( vAng1, vtTnew) || ! AreSameVectorApprox( vtTnew, Hole_i.vtDir))
|
|
continue ;
|
|
Vector3d vtAnew ;
|
|
// nuova configurazione del versore A ottenuta
|
|
if ( ! m_pMchMgr->GetCalcAuxDirFromAngles( vAng1, vtAnew))
|
|
continue ;
|
|
if ( vtAnew.IsSmall() && m_pMchMgr->GetCurrMachine()->GetCurrRotAxes() == 0)
|
|
vtAnew = vtAux ;
|
|
|
|
// creo un nuovo sistema di riferimento centrato nel Tool principale
|
|
Frame3d frMT ;
|
|
frMT.Set( vTools[nIndMT].ptToolTip, vtTool, vtAux) ;
|
|
if ( ! frMT.IsValid())
|
|
return false ;
|
|
|
|
// creo un frame nel foro i-esimo orientato come il frame sul tool principale ( origine nella base interna del foro)
|
|
Frame3d frHMT ;
|
|
frHMT.Set( Hole_i.ptIni - Hole_i.vtDir * Hole_i.dLen, vtTnew, vtAnew) ;
|
|
if ( ! frHMT.IsValid())
|
|
return false ;
|
|
|
|
// numero di svuotature inserendo il Tool principale nel foro i-esimo
|
|
int nDrills = 1 ;
|
|
// setto le variabili temporanee per il foro i-esimo
|
|
vHoles[i].bTempDrill = true ;
|
|
vHoles[i].nTempTool = nIndMT ;
|
|
|
|
// controllo la compatibilità tra le geometrie dei Tool e dei fori
|
|
CheckOtherHolesWithTools( vHoles, vTools, nIndMT, i, Hole_i, frMT, frHMT, dDiamToler, nDrills) ;
|
|
|
|
// controllo quanti fori sono riuscito a svuotare e setto i loro parametri di foratura
|
|
if ( nDrills == nExitCnt - nNullTools) { // se ho svuotato il numero corretto di fori ...
|
|
for ( int d = 0 ; d < ( int)vHoles.size() ; ++ d) {
|
|
if ( vHoles[d].bTempDrill) {
|
|
vHoles[d].vToolHole.push_back( i) ; // indice del foro per il tool principale
|
|
vHoles[d].vIndTools.push_back( vHoles[d].nTempTool) ; // indice del tool che svuota questo foro
|
|
vHoles[d].vVtAux.push_back( frHMT.VersX()) ; // versore ausiliario A del tool principale
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for ( int d = 0 ; d < ( int)vHoles.size() ; ++ d)
|
|
if ( vHoles[d].bTempDrill)
|
|
vHoles[d].bTempDrill = false ;
|
|
}
|
|
|
|
// se la testa può ruotare
|
|
if ( nStat < 0) {
|
|
|
|
// inizio a scorrere tutti i tools
|
|
for ( int t = 0 ; t < ( int)vTools.size() ; ++ t) {
|
|
if ( vTools[t].pTool == nullptr || t == nIndMT)
|
|
continue ;
|
|
|
|
// cerco se ho un foro j-esimo adatto per quella punta
|
|
for ( int j = 0 ; j < ( int)vHoles.size() ; ++ j) {
|
|
|
|
Hole Hole_j = vHoles[j].hole ;
|
|
if ( i == j ||
|
|
vHoles[j].bSkipToAngle ||
|
|
! AreSameVectorApprox( Hole_j.vtDir, Hole_i.vtDir) ||
|
|
! MultiHeadVerifyHole( Hole_j, vTools[t].pTool, dDiamToler, m_vId[vHoles[j].nIndInSelVector]))
|
|
continue ;
|
|
|
|
// resetto le veriabili di controllo di svuotatura temporanea per tutti i fori
|
|
for ( int k = 0 ; k < ( int)vHoles.size() ; ++ k) {
|
|
vHoles[k].bTempDrill = false ;
|
|
vHoles[k].nTempTool = -1 ;
|
|
}
|
|
|
|
Vector3d vtRefT = vTools[t].ptToolTip - vTools[nIndMT].ptToolTip ;
|
|
Vector3d vtRefH = Hole_j.ptIni - Hole_j.vtDir * Hole_j.dLen -
|
|
( Hole_i.ptIni - Hole_i.vtDir * Hole_i.dLen) ;
|
|
|
|
// se le distanze sono compatibili
|
|
if ( abs( vtRefH.Len() - vtRefT.Len()) < EPS_SMALL) {
|
|
// rioriento il frame sul foro i-esimo
|
|
Point3d ptHj = Hole_j.ptIni - Hole_j.vtDir * Hole_j.dLen ;
|
|
ptHj.ToLoc( frHMT) ;
|
|
Vector3d vtProjB( ptHj.x, ptHj.y, 0) ;
|
|
|
|
Point3d ptTt = vTools[t].ptToolTip ;
|
|
ptTt.ToLoc( frMT) ;
|
|
Vector3d vtProjA( ptTt.x, ptTt.y, 0) ;
|
|
|
|
double dAngle ; vtProjA.GetAngle( vtProjB, dAngle) ;
|
|
frHMT.Rotate( frHMT.Orig(), frHMT.VersZ(), dAngle) ;
|
|
|
|
nDrills = 1 ; // foratura nel foro i-esimo e j-esimo
|
|
CheckOtherHolesWithTools( vHoles, vTools, nIndMT, i, Hole_i, frMT, frHMT, dDiamToler, nDrills) ;
|
|
|
|
// setto le variabili temporanee per il foro i-esimo
|
|
vHoles[i].bTempDrill = true ;
|
|
vHoles[i].nTempTool = nIndMT ;
|
|
|
|
// controllo quanti fori sono riuscito a svuotare in questo nuovo sistema di riferimento
|
|
if ( nDrills == nExitCnt - nNullTools) {
|
|
for ( int d = 0 ; d < ( int)vHoles.size() ; ++ d) {
|
|
if ( vHoles[d].bTempDrill) {
|
|
vHoles[d].vToolHole.push_back( i) ; // indice del foro per il tool principale
|
|
vHoles[d].vIndTools.push_back( vHoles[d].nTempTool) ; // indice del tool che svuota questo foro
|
|
vHoles[d].vVtAux.push_back( frHMT.VersX()) ; // versore ausiliario del tool principale
|
|
vHoles[d].bSkipToAngle = true ;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for ( int d = 0 ; d < ( int)vHoles.size() ; ++ d)
|
|
if ( vHoles[d].bTempDrill)
|
|
vHoles[d].bTempDrill = false ;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::CheckOtherHolesWithTools( VECTORHOLE& vHoles, const VECTORTOOL& vTools, int nIndTM, int nIndHTM, Hole holeICP,
|
|
const Frame3d& frMT, const Frame3d& frHMT, double dDiamToler, int& nDrills)
|
|
{
|
|
// controllo parametri
|
|
if ( vHoles.empty() || vTools.empty())
|
|
return true ;
|
|
if ( nIndTM < 0 || nIndTM >= ( int)vTools.size() ||
|
|
nIndHTM < 0 || nIndHTM >= ( int)vHoles.size() ||
|
|
! frMT.IsValid() || ! frHMT.IsValid() ||
|
|
nDrills < 0 || nDrills > max( ( int)vHoles.size(), ( int)vTools.size()))
|
|
return false ;
|
|
|
|
// definisco il punto dove cade il tool principale
|
|
Hole holeTM = holeICP ; // copia del foro i-esimo
|
|
|
|
// ciclo su tutti i tools
|
|
for ( int t = 0 ; t < ( int)vTools.size() ; ++ t) {
|
|
if ( vTools[t].pTool == nullptr || t == nIndTM)
|
|
continue ;
|
|
// esprimo il punto finale del tool t-esimo nel sistema di riferimento del Tool principale
|
|
Point3d ptETt = vTools[t].ptToolTip ;
|
|
ptETt.ToLoc( frMT) ;
|
|
|
|
// cerco se ho un foro j-esimo adatto per quella punta
|
|
for ( int j = 0 ; j < ( int)vHoles.size() ; ++ j) {
|
|
Hole Hole_j = vHoles[j].hole ; // copia del foro j-esimo
|
|
// controllo che il foro j-esimo non sia l'i-esimo, che non sia stato già precedentemente svuotato da un altro tool t'-esimo ...
|
|
// ... che vtDir del foro i-esimo coincida con vtDir del foro j-esimo e che il tool t-esimo sia compatibile con il foro j-esimo
|
|
if ( nIndHTM == j ||
|
|
vHoles[j].bTempDrill ||
|
|
! AreSameVectorApprox( Hole_j.vtDir, holeTM.vtDir) ||
|
|
! MultiHeadVerifyHole( Hole_j, vTools[t].pTool, dDiamToler, m_vId[vHoles[j].nIndInSelVector]))
|
|
continue ;
|
|
|
|
// esprimo il foro j-esimo nel sistema di riferimento del Tool principale centrato nel foro i-esimo
|
|
Point3d ptHj = Hole_j.ptIni - Hole_j.vtDir * Hole_j.dLen ;
|
|
ptHj.ToLoc( frHMT) ;
|
|
|
|
// controllo la compatibilità
|
|
if ( AreSamePointApprox( ptHj, ptETt)) {
|
|
// un foro in più lavorato
|
|
++ nDrills ;
|
|
// aggiorno le variabili temporanee
|
|
vHoles[j].bTempDrill = true ;
|
|
vHoles[j].nTempTool = t ;
|
|
// non controllo gli altri vertici per la punta t-esima
|
|
break ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::MultiHeadVerifyHole( Hole& hole, const ToolData* Tool, double dDiamToler, SelData Id)
|
|
{
|
|
// verifico che il diamtro del tool sia compatibile con quello del foro
|
|
if ( ! VerifyDiameter( hole.dDiam, Tool->m_dDiam, dDiamToler))
|
|
return false ;
|
|
// imposto elevazione da lunghezza foro con possibilità di sovrascrittura da info
|
|
double dElev = hole.dLen ;
|
|
double dMaxElev ;
|
|
if ( FromString( ExtractInfo( m_Params.m_sUserNotes, "MaxElev="), dMaxElev) && dElev > dMaxElev) {
|
|
dElev = dMaxElev ;
|
|
hole.ptIni += hole.vtDir * ( dElev - hole.dLen) ;
|
|
hole.dLen = dElev ;
|
|
}
|
|
// limito lunghezza foro a massima lavorazione della punta
|
|
double dAddLen = ( hole.bBlind ? 0 : m_Params.m_dThroughAddLen) ;
|
|
if ( ( dElev + dAddLen) > Tool->m_dMaxMat + EPS_SMALL) {
|
|
hole.dLen = Tool->m_dMaxMat + max( hole.dLen - dElev, 0.) ;
|
|
hole.bBlind = true ;
|
|
}
|
|
if ( ! VerifyHoleFromBottom( hole, Id))
|
|
return false ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::AlongCurveProcess( bool bRecalc, int nPvId, int nClId)
|
|
{
|
|
// 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 ;
|
|
}
|
|
|
|
// se necessario, eseguo concatenamento ed inserisco i percorsi sotto la geometria ausiliaria
|
|
if ( bChain && ! Chain( nAuxId)) {
|
|
m_pMchMgr->SetLastError( 2108, "Error in Drilling : Chaining failed") ;
|
|
return false ;
|
|
}
|
|
|
|
// calcolo ogni singola catena
|
|
int nPathId = m_pGeomDB->GetFirstGroupInGroup( nAuxId) ;
|
|
while ( nPathId != GDB_ID_NULL) {
|
|
if ( ! ProcessPath( nPathId, nPvId, nClId))
|
|
return false ;
|
|
nPathId = m_pGeomDB->GetNextGroup( nPathId) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::Chain( int nGrpDestId)
|
|
{
|
|
// vettore puntatori alle curve
|
|
ICURVEPOVECTOR 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 sInfo = "Warning in Drilling : Skipped entity " + ToString( Id) ;
|
|
m_pMchMgr->SetWarning( 2151, sInfo) ;
|
|
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<ICurveComposite> 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) && 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) ;
|
|
// 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 ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
ICurve*
|
|
Drilling::GetCurve( SelData Id)
|
|
{
|
|
// accetto solo curve
|
|
PtrOwner<ICurve> pCurve ;
|
|
// se direttamente curva
|
|
if ( Id.nSub == SEL_SUB_ALL) {
|
|
// recupero e duplico la curva
|
|
const ICurve* pOriCurve = ::GetCurve( m_pGeomDB->GetGeoObj( Id.nId)) ;
|
|
if ( pOriCurve != nullptr)
|
|
pCurve.Set( pOriCurve->Clone()) ;
|
|
}
|
|
// altrimenti sottocurva di composita
|
|
else {
|
|
// recupero la composita
|
|
const ICurveComposite* pCompo = GetCurveComposite( m_pGeomDB->GetGeoObj( Id.nId)) ;
|
|
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))
|
|
pCurve->SetExtrusion( vtExtr) ;
|
|
double dThick ;
|
|
if ( pCompo->GetThickness( dThick))
|
|
pCurve->SetThickness( dThick) ;
|
|
}
|
|
}
|
|
}
|
|
if ( IsNull( pCurve))
|
|
return nullptr ;
|
|
// ne recupero il riferimento globale
|
|
Frame3d frGlob ;
|
|
if ( ! m_pGeomDB->GetGlobFrame( Id.nId, frGlob))
|
|
return nullptr ;
|
|
// la porto in globale
|
|
pCurve->ToGlob( frGlob) ;
|
|
// la restituisco
|
|
return Release( pCurve) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::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) ;
|
|
|
|
// recupero la curva composita
|
|
int nCrvId = m_pGeomDB->GetFirstInGroup( nPathId) ;
|
|
// recupero nome del path
|
|
string sPName ;
|
|
m_pGeomDB->GetName( nPathId, sPName) ;
|
|
|
|
// valuto l'espressione dell'offset e della sovrapposizione
|
|
ExeLuaSetGlobNumVar( "D", m_TParams.m_dDiam) ;
|
|
double dOffset ;
|
|
if ( ! ExeLuaEvalNumExpr( m_Params.m_sOffset, &dOffset)) {
|
|
m_pMchMgr->SetLastError( 2102, "Error in Drilling : Offset not computable") ;
|
|
return false ;
|
|
}
|
|
double dOverlap ;
|
|
if ( ! ExeLuaEvalNumExpr( m_Params.m_sOverlap, &dOverlap)) {
|
|
m_pMchMgr->SetLastError( 2103, "Error in Drilling : Overlap not computable") ;
|
|
return false ;
|
|
}
|
|
|
|
// disabilito eventuale registrazione comandi EXE (riabilitazione automatica)
|
|
CmdLogOff cmdLogOff ;
|
|
|
|
// genero le circonferenze
|
|
int nCount = 0 ;
|
|
int nFirstId = ExeCreateCirclesAlongCurve( nTempId, nCrvId, dOffset, dOverlap, m_Params.m_dStartAddLen,
|
|
m_Params.m_dEndAddLen, m_TParams.m_dDiam, &nCount) ;
|
|
|
|
// se richiesta anteprima
|
|
if ( nPvId != GDB_ID_NULL) {
|
|
// creo l'anteprima dei fori
|
|
for ( int i = 0 ; i < nCount ; ++ i) {
|
|
// identificativo circonferenza
|
|
int nId = nFirstId + i ;
|
|
// calcolo il preview del foro
|
|
if ( ! GenerateHolePv( i, nId, sPName + "_", nPvId))
|
|
return false ;
|
|
}
|
|
// creo la regione di ingombro dei fori
|
|
GenerateHoleRegionPv( nFirstId, nCount, nPvId) ;
|
|
}
|
|
|
|
// se richiesta lavorazione
|
|
if ( nClId != GDB_ID_NULL) {
|
|
// creo lavorazione dei fori
|
|
for ( int i = 0 ; i < nCount ; ++ i) {
|
|
// identificativo circonferenza
|
|
int nId = nFirstId + i ;
|
|
// calcolo la lavorazione del foro
|
|
if ( ! GenerateHoleCl( i, nId, sPName + "_", nClId))
|
|
return false ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::GenerateHolePv( int nInd, const SelData& nCircId, const string& sPName, int nPvId)
|
|
{
|
|
// creo gruppo per geometria di lavorazione del foro
|
|
int nPathId = m_pGeomDB->AddGroup( GDB_ID_NULL, nPvId, Frame3d()) ;
|
|
if ( nPathId == GDB_ID_NULL)
|
|
return false ;
|
|
m_pGeomDB->SetName( nPathId, sPName + ToString( nInd + 1)) ;
|
|
m_pGeomDB->SetInfo( nPathId, KEY_IDS, ToString( nCircId)) ;
|
|
m_pGeomDB->SetMaterial( nPathId, GREEN) ;
|
|
// recupero il valore di tolleranza sul diametro
|
|
double dDiamTol = m_pMchMgr->GetCurrMachiningsMgr()->GetHoleDiamToler() ;
|
|
// recupero i dati del foro
|
|
Hole hole ;
|
|
if ( ! GetHoleData( nCircId, hole) || ! VerifyDiameter( hole.dDiam, m_TParams.m_dDiam, dDiamTol)) {
|
|
m_pGeomDB->Erase( nPathId) ;
|
|
string sInfo = "Warning in Drilling : Skipped entity " + ToString( nCircId) ;
|
|
m_pMchMgr->SetWarning( 2151, sInfo) ;
|
|
return true ;
|
|
}
|
|
// limito lunghezza foro a massima lavorazione della punta
|
|
if ( hole.dLen > m_TParams.m_dMaxMat + EPS_SMALL) {
|
|
hole.dLen = m_TParams.m_dMaxMat ;
|
|
string sInfo = "Warning in Drilling : Drill bit too short for Hole " + ToString( nCircId) ;
|
|
m_pMchMgr->SetWarning( 2155, sInfo) ;
|
|
}
|
|
// inserisco circonferenza che rappresenta il foro
|
|
PtrOwner<ICurveArc> pCrvArc( CreateCurveArc()) ;
|
|
if ( IsNull( pCrvArc) || ! pCrvArc->Set( hole.ptIni, hole.vtDir, 0.5 * m_TParams.m_dDiam))
|
|
return false ;
|
|
// assegno il versore estrusione e lo spessore
|
|
pCrvArc->SetExtrusion( hole.vtDir) ;
|
|
pCrvArc->SetThickness( - hole.dLen) ;
|
|
// inserisco nel DB
|
|
int nDriId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPathId, Release( pCrvArc)) ;
|
|
// assegno nome e colore
|
|
m_pGeomDB->SetName( nDriId, MCH_PV_CUT) ;
|
|
m_pGeomDB->SetMaterial( nDriId, LIME) ;
|
|
// aggiorno numero forature
|
|
++ m_nDrillings ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::GenerateHoleCl( int nInd, const SelData& nCircId, const string& sPName, int nClId, double dMHOff, Vector3d vtA)
|
|
{
|
|
// creo gruppo per geometria di lavorazione del foro
|
|
int nPathId = m_pGeomDB->AddGroup( GDB_ID_NULL, nClId, Frame3d()) ;
|
|
if ( nPathId == GDB_ID_NULL)
|
|
return false ;
|
|
m_pGeomDB->SetName( nPathId, sPName + ToString( nInd + 1)) ;
|
|
m_pGeomDB->SetInfo( nPathId, KEY_IDS, ToString( nCircId)) ;
|
|
m_pGeomDB->SetMaterial( nPathId, GREEN) ;
|
|
// recupero il valore di tolleranza sul diametro
|
|
double dDiamTol = m_pMchMgr->GetCurrMachiningsMgr()->GetHoleDiamToler() ;
|
|
// recupero i dati del foro
|
|
Hole hole ;
|
|
if ( ! GetHoleData( nCircId, hole) || ! VerifyDiameter( hole.dDiam, m_TParams.m_dDiam, dDiamTol)) {
|
|
m_pGeomDB->Erase( nPathId) ;
|
|
string sInfo = "Warning in Drilling : Skipped entity " + ToString( nCircId) ;
|
|
m_pMchMgr->SetWarning( 2151, sInfo) ;
|
|
return true ;
|
|
}
|
|
// se richiesta inversione e foro passante, provvedo
|
|
if ( m_Params.m_bInvert) {
|
|
if ( hole.bBlind) {
|
|
m_pMchMgr->SetLastError( 2114, "Error in Drilling : blind hole not reversible") ;
|
|
return false ;
|
|
}
|
|
else {
|
|
hole.ptIni -= hole.vtDir * hole.dThick ;
|
|
hole.vtDir.Invert() ;
|
|
}
|
|
}
|
|
// se lavorazione del foro non arriva al suo fondo, lo considero cieco
|
|
if ( hole.dLen < hole.dThick - 10 * EPS_SMALL)
|
|
hole.bBlind = true ;
|
|
// imposto elevazione da lunghezza foro con possibilità di sovrascrittura da info
|
|
double dElev = hole.dLen ;
|
|
double dMaxElev ;
|
|
if ( FromString( ExtractInfo( m_Params.m_sUserNotes, "MaxElev="), dMaxElev) && dElev > dMaxElev) {
|
|
dElev = dMaxElev ;
|
|
hole.ptIni += hole.vtDir * ( dElev - hole.dLen) ;
|
|
hole.dLen = dElev ;
|
|
}
|
|
// limito lunghezza foro a massima lavorazione della punta
|
|
double dAddLen = ( hole.bBlind ? 0 : m_Params.m_dThroughAddLen) ;
|
|
if ( ( dElev + dAddLen) > m_TParams.m_dMaxMat + EPS_SMALL) {
|
|
hole.dLen = m_TParams.m_dMaxMat + max( hole.dLen - dElev, 0.) ;
|
|
hole.bBlind = true ;
|
|
string sInfo = "Warning in Drilling : Drill bit too short for Hole " + ToString( nCircId) ;
|
|
m_pMchMgr->SetWarning( 2155, sInfo) ;
|
|
}
|
|
// verifico se tavola basculante
|
|
bool bTiltTab = false ;
|
|
m_bTiltingTab = ( m_pMchMgr->GetCurrMachine()->GetCurrTableIsTilting( bTiltTab, m_vtTiltingAx) && bTiltTab) ;
|
|
// verifico se testa da sopra (Z+)
|
|
m_bAboveHead = m_pMchMgr->GetHeadAbove( m_TParams.m_sHead) ;
|
|
// verifiche per foro verso il basso
|
|
m_bAggrBottom = false ;
|
|
if ( ! VerifyHoleFromBottom( hole, nCircId))
|
|
return false ;
|
|
// assegno il vettore estrazione al gruppo del percorso
|
|
m_pGeomDB->SetInfo( nPathId, KEY_EXTR, hole.vtDir) ;
|
|
// assegno i punti di inizio e fine al gruppo del percorso
|
|
m_pGeomDB->SetInfo( nPathId, KEY_START, hole.ptIni) ;
|
|
m_pGeomDB->SetInfo( nPathId, KEY_END, hole.ptIni) ;
|
|
// assegno l'elevazione massima
|
|
m_pGeomDB->SetInfo( nPathId, KEY_ELEV, hole.dLen) ;
|
|
// foro normale
|
|
if ( m_Params.m_dStep < EPS_SMALL ||
|
|
m_Params.m_dStep > hole.dLen - EPS_SMALL) {
|
|
if ( DoStandardDrilling( hole, nCircId, nPathId, dMHOff, vtA)) {
|
|
// aggiorno numero forature
|
|
++ m_nDrillings ;
|
|
}
|
|
else {
|
|
m_pGeomDB->Erase( nPathId) ;
|
|
string sInfo = "Warning in Drilling : Skipped by Standard Drilling " + ToString( nCircId) ;
|
|
m_pMchMgr->SetWarning( 2156, sInfo) ;
|
|
}
|
|
}
|
|
else {
|
|
if ( DoPeckDrilling( hole, nCircId, nPathId)) {
|
|
// aggiorno numero forature
|
|
++ m_nDrillings ;
|
|
}
|
|
else {
|
|
m_pGeomDB->Erase( nPathId) ;
|
|
string sInfo = "Warning in Drilling : Skipped by Peck Drilling " + ToString( nCircId) ;
|
|
m_pMchMgr->SetWarning( 2157, sInfo) ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::GenerateHoleRegionPv( int nFirstId, int nCount, int nPvId)
|
|
{
|
|
// raggio dei fori
|
|
double dRad = m_TParams.m_dDiam / 2 ;
|
|
// extra raggio
|
|
double dExtraR = m_pMchMgr->GetCurrMachiningsMgr()->GetExtraROnDrillRegion() ;
|
|
|
|
// gruppo di inserimento
|
|
int nGroupId = m_pGeomDB->GetLastGroupInGroup( nPvId) ;
|
|
|
|
// creo polyline che unisce i centri
|
|
PolyLine PL ;
|
|
for ( int i = 0 ; i < nCount ; ++ i) {
|
|
int nId = nFirstId + i ;
|
|
const ICurveArc* pArc = GetCurveArc( m_pGeomDB->GetGeoObj( nId)) ;
|
|
if ( pArc == nullptr)
|
|
return false ;
|
|
PL.AddUPoint( i, pArc->GetCenter()) ;
|
|
}
|
|
|
|
// calcolo la regione
|
|
ISurfFlatRegion* pSfr = nullptr ;
|
|
|
|
// se polilinea con almeno due punti
|
|
if ( PL.GetPointNbr() > 1) {
|
|
// ne derivo una curva composita
|
|
PtrOwner<ICurveComposite> pCompo1( CreateCurveComposite()) ;
|
|
if ( IsNull( pCompo1) || ! pCompo1->FromPolyLine( PL))
|
|
return false ;
|
|
// calcolo la regione
|
|
pSfr = GetSurfFlatRegionFromFatCurve( Release( pCompo1), dRad + dExtraR, false, true) ;
|
|
if ( pSfr == nullptr)
|
|
return false ;
|
|
}
|
|
// altrimenti
|
|
else {
|
|
// approssimo l'unico foro
|
|
pSfr = GetSurfFlatRegionDisk( dRad + dExtraR) ;
|
|
if ( pSfr == nullptr)
|
|
return false ;
|
|
Point3d ptCen ;
|
|
PL.GetFirstPoint( ptCen) ;
|
|
pSfr->Translate( ptCen - ORIG) ;
|
|
}
|
|
|
|
// inserisco la regione nel DB
|
|
int nRId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nGroupId, pSfr) ;
|
|
if ( nRId == GDB_ID_NULL)
|
|
return false ;
|
|
m_pGeomDB->SetName( nRId, MCH_PV_RCUT) ;
|
|
m_pGeomDB->SetMaterial( nRId, INVISIBLE) ;
|
|
// la copio anche come regione ridotta
|
|
int nRrId = m_pGeomDB->Copy( nRId, GDB_ID_NULL, nGroupId) ;
|
|
if ( nRrId == GDB_ID_NULL)
|
|
return false ;
|
|
m_pGeomDB->SetName( nRrId, MCH_PV_RRCUT) ;
|
|
m_pGeomDB->SetMaterial( nRrId, INVISIBLE) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::VerifyDiameter( double dHdiam, double dTdiam, double dDiamTol)
|
|
{
|
|
// imposto minima tolleranza
|
|
if ( abs( dDiamTol) < 10 * EPS_SMALL)
|
|
dDiamTol = 10 * EPS_SMALL ;
|
|
// se tolleranza in più o in meno
|
|
if ( dDiamTol > 0)
|
|
return ( abs( dHdiam - dTdiam) < dDiamTol) ;
|
|
// altrimenti tolleranza solo in meno
|
|
return ( dTdiam < dHdiam + 10 * EPS_SMALL && dTdiam > dHdiam + dDiamTol - 10 * EPS_SMALL) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::GetParam( int nType, bool& bVal) const
|
|
{
|
|
switch ( nType) {
|
|
case MPA_INVERT :
|
|
bVal = m_Params.m_bInvert ;
|
|
return true ;
|
|
}
|
|
bVal = false ;
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::GetParam( int nType, int& nVal) const
|
|
{
|
|
switch ( nType) {
|
|
case MPA_TYPE :
|
|
nVal = MT_DRILLING ;
|
|
return true ;
|
|
case MPA_SUBTYPE :
|
|
nVal = m_Params.m_nSubType ;
|
|
return true ;
|
|
case MPA_SCC :
|
|
nVal = m_Params.m_nSolCh ;
|
|
return true ;
|
|
}
|
|
nVal = 0 ;
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::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_STARTPOS :
|
|
dVal = m_Params.m_dStartPos ;
|
|
return true ;
|
|
case MPA_STARTSLOWLEN :
|
|
dVal = m_Params.m_dStartSlowLen ;
|
|
return true ;
|
|
case MPA_ENDSLOWLEN :
|
|
dVal = m_Params.m_dEndSlowLen ;
|
|
return true ;
|
|
case MPA_THROUADDLEN :
|
|
dVal = m_Params.m_dThroughAddLen ;
|
|
return true ;
|
|
case MPA_STEP :
|
|
dVal = m_Params.m_dStep ;
|
|
return true ;
|
|
case MPA_RETURNPOS :
|
|
dVal = m_Params.m_dReturnPos ;
|
|
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
|
|
Drilling::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_OVERLAP_STR :
|
|
sVal = m_Params.m_sOverlap ;
|
|
return true ;
|
|
case MPA_OFFSET_STR :
|
|
sVal = m_Params.m_sOffset ;
|
|
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&
|
|
Drilling::GetToolData( void) const
|
|
{
|
|
return m_TParams ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::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 ;
|
|
// salvo posizione TC, testa e uscita originali
|
|
string sOrigTcPos = m_TParams.m_sTcPos ;
|
|
string sOrigHead = m_TParams.m_sHead ;
|
|
int nOrigExit = m_TParams.m_nExit ;
|
|
// verifico se sono diversi (ad esclusione di nome, posizione TC, testa e uscita)
|
|
bool bChanged = ( ! SameTool( m_TParams, *pTdata, false)) ;
|
|
// aggiorno comunque i parametri
|
|
m_TParams = *pTdata ;
|
|
// se definito attrezzaggio, aggiorno i parametri che ne possono derivare
|
|
string sTcPos ; string sHead ; int nExit ;
|
|
if ( m_pMchMgr->GetCurrSetupMgr().GetToolData( m_TParams.m_sName, sTcPos, sHead, nExit)) {
|
|
if ( sOrigTcPos != sTcPos ||
|
|
sOrigHead != sHead ||
|
|
nOrigExit != nExit)
|
|
bChanged = true ;
|
|
m_TParams.m_sTcPos = sTcPos ;
|
|
m_TParams.m_sHead = sHead ;
|
|
m_TParams.m_nExit = nExit ;
|
|
}
|
|
else {
|
|
if ( sOrigTcPos != pTdata->m_sTcPos ||
|
|
sOrigHead != pTdata->m_sHead ||
|
|
nOrigExit != pTdata->m_nExit)
|
|
bChanged = true ;
|
|
}
|
|
// eventuali segnalazioni
|
|
if ( ! EqualNoCase( m_Params.m_sToolName, m_TParams.m_sName)) {
|
|
string sInfo = "Warning in Drilling : tool name changed (" +
|
|
m_Params.m_sToolName + "->" + m_TParams.m_sName + ")" ;
|
|
m_pMchMgr->SetWarning( 2153, sInfo) ;
|
|
m_Params.m_sToolName = m_TParams.m_sName ;
|
|
}
|
|
if ( bChanged) {
|
|
string sInfo = "Warning in Drilling : tool data changed (" +
|
|
m_Params.m_sToolName + ")" ;
|
|
m_pMchMgr->SetWarning( 2154, sInfo) ;
|
|
}
|
|
// se definito parametro di ritorno, lo assegno
|
|
if ( pbChanged != nullptr)
|
|
*pbChanged = bChanged ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::GetGeometry( SELVECTOR& vIds) const
|
|
{
|
|
// restituisco l'elenco delle entità
|
|
vIds = m_vId ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::GetHoleData( SelData Id, Hole& hole)
|
|
{
|
|
PtrOwner<ICurveArc> pMyArc ;
|
|
// deve essere un arco o una composita formata da un arco
|
|
const ICurveArc* pArc = GetCurveArc( m_pGeomDB->GetGeoObj( Id.nId)) ;
|
|
if ( pArc == nullptr) {
|
|
const ICurveComposite* pCompo = GetCurveComposite( m_pGeomDB->GetGeoObj( Id.nId)) ;
|
|
Point3d ptCen ;
|
|
Vector3d vtN ;
|
|
double dRad ;
|
|
bool bCCW ;
|
|
if ( pCompo == nullptr || ! pCompo->IsACircle( 100 * EPS_SMALL, ptCen, vtN, dRad, bCCW))
|
|
return false ;
|
|
pMyArc.Set( CreateCurveArc()) ;
|
|
if ( IsNull( pMyArc) || ! pMyArc->Set( ptCen, vtN, dRad))
|
|
return false ;
|
|
Vector3d vtExtr ; pCompo->GetExtrusion( vtExtr) ;
|
|
pMyArc->SetExtrusion( vtExtr) ;
|
|
double dThick = 0 ; pCompo->GetThickness( dThick) ;
|
|
pMyArc->SetThickness( dThick) ;
|
|
pArc = pMyArc ;
|
|
}
|
|
// ne recupero il riferimento globale
|
|
Frame3d frGlob ;
|
|
if ( ! m_pGeomDB->GetGlobFrame( Id.nId, frGlob))
|
|
return false ;
|
|
// deve avere estrusione
|
|
Vector3d vtExtr ;
|
|
if ( ! pArc->GetExtrusion( vtExtr))
|
|
return false ;
|
|
if ( vtExtr.IsSmall())
|
|
vtExtr = pArc->GetNormVersor() ;
|
|
// recupero spessore
|
|
double dThick = 0 ;
|
|
pArc->GetThickness( dThick) ;
|
|
// se diretto come asse Z, recupero distanza da fondo dei grezzi interessati dal foro
|
|
double dRbDist = 0 ;
|
|
Vector3d vtExtrG = vtExtr ;
|
|
vtExtrG.ToGlob( frGlob) ;
|
|
if ( vtExtrG.IsZplus())
|
|
GetDistanceFromRawBottom( m_nPhase, Id.nId, EPS_SMALL, dRbDist) ;
|
|
// 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( 2104, "Error in Drilling : Depth not computable") ;
|
|
return false ;
|
|
}
|
|
if ( abs( dDepth) < EPS_SMALL) {
|
|
m_pMchMgr->SetLastError( 2105, "Error in Drilling : Drill with zero depth") ;
|
|
return false ;
|
|
}
|
|
// assegno Id
|
|
hole.nOriId = Id.nId ;
|
|
// ne recupero il diametro
|
|
hole.dDiam = 2 * pArc->GetRadius() ;
|
|
// ne recupero il centro
|
|
hole.ptIni = pArc->GetCenter() + ( dThick > 0 ? vtExtr * dThick : V_NULL) ;
|
|
hole.ptIni.ToGlob( frGlob) ;
|
|
// ne recupero versore direzione e lunghezze
|
|
hole.vtDir = vtExtr ;
|
|
hole.vtDir.ToGlob( frGlob) ;
|
|
hole.vtDir.Normalize() ;
|
|
hole.dThick = abs( dThick) ;
|
|
hole.dLen = abs( dDepth) ;
|
|
// per default è cieco
|
|
hole.bBlind = true ;
|
|
// se dichiarato passante o no (1/0)
|
|
int nOpen ;
|
|
if ( FromString( ExtractInfo( m_Params.m_sUserNotes, "Open="), nOpen))
|
|
hole.bBlind = ( nOpen == 0) ;
|
|
// se verticale ed arriva fino al fondo grezzo, allora passante
|
|
else if ( hole.vtDir.IsZplus() && hole.dThick > dRbDist - EPS_SMALL)
|
|
hole.bBlind = false ;
|
|
// altrimenti determino la distanza del fondo del foro dal bordo opposto del grezzo
|
|
else {
|
|
const double BLIND_TOL = 10 ;
|
|
double dBackElev ;
|
|
if ( GetElevation( m_nPhase, hole.ptIni, - hole.vtDir, dBackElev) && ( dBackElev - hole.dThick) <= BLIND_TOL)
|
|
hole.bBlind = false ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::VerifyHoleFromBottom( const Hole& hole, SelData Id)
|
|
{
|
|
// se non è foro dal basso in alto, esco
|
|
if ( hole.vtDir.z > MIN_ZDIR_TOP_TOOL)
|
|
return true ;
|
|
// se c'è testa non dall'alto o tavola basculante, esco
|
|
if ( ! m_bAboveHead || m_bTiltingTab)
|
|
return true ;
|
|
// recupero dati di eventuale rinvio da sotto
|
|
if ( ! GetAggrBottomData( m_TParams.m_sHead, m_AggrBottom) || m_AggrBottom.nType == 0) {
|
|
string sOut = "Error in Drilling : Entity " + ToString( Id) + " skipped because missing aggregate from bottom" ;
|
|
m_pMchMgr->SetLastError( 2106, sOut) ;
|
|
return false ;
|
|
}
|
|
// calcolo la distanza minima del punto dal contorno del grezzo
|
|
double dDist ;
|
|
Vector3d vtDir ;
|
|
if ( ! GetMinDistanceFromRawSide( m_nPhase, hole.ptIni, 0, m_AggrBottom.vtMDir, MCH_AGB_DELTAMAX_MDIR, dDist, vtDir) || dDist > m_AggrBottom.dDMax) {
|
|
string sOut = "Error in Drilling : Entity " + ToString( Id) + " skipped because too far from part sides" ;
|
|
m_pMchMgr->SetLastError( 2107, sOut) ;
|
|
return false ;
|
|
}
|
|
// assegno direzione di accesso e segnalazione di utilizzo aggregato da sotto
|
|
m_vtAggrBottom = vtDir ;
|
|
m_bAggrBottom = true ;
|
|
m_dDistBottom = dDist ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::DoStandardDrilling( const Hole& hole, SelData Id, int nPathId, double dMHOff, Vector3d vtA)
|
|
{
|
|
// aggiusto alcuni parametri del ciclo di foratura
|
|
double dStartSlowLen = abs( m_Params.m_dStartSlowLen) ;
|
|
if ( abs( m_TParams.m_dStartFeed - m_TParams.m_dFeed) < EPS_SMALL)
|
|
dStartSlowLen = 0 ;
|
|
double dEndSlowLen = ( hole.bBlind ? 0 : abs( m_Params.m_dEndSlowLen)) ;
|
|
if ( abs( m_TParams.m_dTipFeed - m_TParams.m_dFeed) < EPS_SMALL)
|
|
dEndSlowLen = 0 ;
|
|
if ( ( dStartSlowLen + dEndSlowLen) > hole.dLen) {
|
|
dStartSlowLen = dStartSlowLen / ( dStartSlowLen + dEndSlowLen) * hole.dLen ;
|
|
dEndSlowLen = hole.dLen - dStartSlowLen ;
|
|
}
|
|
double dAddLen = ( hole.bBlind ? 0 : m_Params.m_dThroughAddLen) ;
|
|
bool bStartSlow = ( dStartSlowLen > EPS_SMALL) ;
|
|
bool bStd = ( ( hole.dLen - dStartSlowLen - dEndSlowLen) > EPS_SMALL) ;
|
|
bool bEndSlow = ( dEndSlowLen > EPS_SMALL) ;
|
|
// determino l'elevazione
|
|
double dElev = 0 ;
|
|
GetElevation( m_nPhase, hole.ptIni, hole.vtDir, m_TParams.m_dDiam / 2, hole.vtDir, dElev) ;
|
|
// determino alcune caratteristiche dell'utensile
|
|
double dTExtrLen = max( 0.0, m_TParams.m_dTLen - m_TParams.m_dLen) ;
|
|
// necessità di spezzatura per robot
|
|
bool bSplitArcs = GetSplitArcs( V_NULL) ;
|
|
// imposto dati comuni
|
|
SetPathId( nPathId) ;
|
|
SetToolDir( hole.vtDir) ;
|
|
// 1 -> punto approccio (se con aggregato da sotto è una sequenza di approccio)
|
|
SetFlag( 1) ;
|
|
double dSafeZ = m_pMchMgr->GetCurrMachiningsMgr()->GetSafeZ() ;
|
|
double dSafeAggrBottZ = m_pMchMgr->GetCurrMachiningsMgr()->GetSafeAggrBottZ() ;
|
|
double dAppr = ( m_bAggrBottom ? dSafeAggrBottZ : dSafeZ) ;
|
|
Point3d ptP1 = hole.ptIni + hole.vtDir * ( dAppr + dElev + dTExtrLen + dMHOff) ;
|
|
if ( m_bAggrBottom) {
|
|
Point3d ptP0 = ptP1 + m_vtAggrBottom * ( m_dDistBottom + m_AggrBottom.dEncH + dSafeZ) ;
|
|
Point3d ptP00 = ptP0 + Z_AX * ( m_AggrBottom.dEncV + m_TParams.m_dLen + dAppr + dTExtrLen) ;
|
|
// se rinvio da sotto che richiede speciale rotazione
|
|
if ( m_AggrBottom.nType == 1) {
|
|
Vector3d vtAux = m_vtAggrBottom ;
|
|
vtAux.Rotate( Z_AX, 0, 1) ;
|
|
SetAuxDir( vtAux) ;
|
|
if ( AddRapidStart( ptP00, MCH_CL_AGB_DWN) == GDB_ID_NULL)
|
|
return false ;
|
|
SetAuxDir( m_vtAggrBottom) ;
|
|
SetFlag( 0) ;
|
|
if ( AddRapidMove( ptP0, bSplitArcs, MCH_CL_AGB_IN) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// altrimenti rinvio normale
|
|
else {
|
|
SetAuxDir( m_vtAggrBottom) ;
|
|
if ( AddRapidStart( ptP0, MCH_CL_AGB_IN) == GDB_ID_NULL)
|
|
return false ;
|
|
SetFlag( 0) ;
|
|
}
|
|
if ( AddRapidMove( ptP1, bSplitArcs) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
else {
|
|
if( ! vtA.IsSmall())
|
|
SetAuxDir( vtA) ;
|
|
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 = hole.ptIni + hole.vtDir * ( m_Params.m_dStartPos + dTExtrLen) ;
|
|
if ( AddRapidMove( ptP2, bSplitArcs) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// 3 -> punto termine velocità ridotta iniziale (se previsto)
|
|
if ( bStartSlow) {
|
|
SetFeed( GetStartFeed()) ;
|
|
if ( ! bStd && ! bEndSlow)
|
|
SetFlag( 101) ; // fondo del foro
|
|
Point3d ptP3 = hole.ptIni - hole.vtDir * dStartSlowLen ;
|
|
if ( ! bStd && ! bEndSlow)
|
|
ptP3 -= hole.vtDir * dAddLen ;
|
|
if ( AddLinearMove( ptP3, bSplitArcs) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// 4 -> punto termine velocità standard (se risulta)
|
|
if ( bStd) {
|
|
SetFeed( GetFeed()) ;
|
|
if ( ! bEndSlow)
|
|
SetFlag( 101) ; // fondo del foro
|
|
Point3d ptP4 = hole.ptIni - hole.vtDir * ( hole.dLen - dEndSlowLen) ;
|
|
if ( ! bEndSlow)
|
|
ptP4 -= hole.vtDir * dAddLen ;
|
|
if ( AddLinearMove( ptP4, bSplitArcs) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// 5 -> punto termine velocità finale ridotta (se previsto)
|
|
if ( bEndSlow) {
|
|
SetFeed( GetTipFeed()) ;
|
|
SetFlag( 101) ; // fondo del foro
|
|
Point3d ptP5 = hole.ptIni - hole.vtDir * ( hole.dLen + dAddLen) ;
|
|
if ( AddLinearMove( ptP5, bSplitArcs) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// 6 -> ritorno all'approccio del foro
|
|
SetFeed( GetEndFeed()) ;
|
|
SetFlag( 104) ; // risalita sopra il foro
|
|
if ( AddLinearMove( ptP1, bSplitArcs) == GDB_ID_NULL)
|
|
return false ;
|
|
// 7 -> punto fuori (se uso aggregato da sotto)
|
|
if ( m_bAggrBottom) {
|
|
SetFlag( 0) ;
|
|
Point3d ptP0 = ptP1 + m_vtAggrBottom * ( m_dDistBottom + m_AggrBottom.dEncH + dSafeZ) ;
|
|
Point3d ptP00 = ptP0 + Z_AX * ( m_AggrBottom.dEncV + m_TParams.m_dLen + dAppr + dTExtrLen) ;
|
|
if ( AddRapidMove( ptP0, bSplitArcs, MCH_CL_AGB_OUT) == GDB_ID_NULL)
|
|
return false ;
|
|
// se rinvio da sotto che richiede speciale rotazione
|
|
if ( m_AggrBottom.nType == 1) {
|
|
Vector3d vtAux = m_vtAggrBottom ;
|
|
vtAux.Rotate( Z_AX, 0, 1) ;
|
|
SetAuxDir( vtAux) ;
|
|
if ( AddRapidMove( ptP00, bSplitArcs, MCH_CL_AGB_UP) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
}
|
|
|
|
// reset dati di movimento
|
|
ResetMoveData() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Drilling::DoPeckDrilling( const Hole& hole, SelData Id, int nPathId)
|
|
{
|
|
// aggiusto alcuni parametri del ciclo di foratura
|
|
double dStartSlowLen = abs( m_Params.m_dStartSlowLen) ;
|
|
if ( abs( m_TParams.m_dStartFeed - m_TParams.m_dFeed) < EPS_SMALL)
|
|
dStartSlowLen = 0 ;
|
|
double dEndSlowLen = ( hole.bBlind ? 0 : abs( m_Params.m_dEndSlowLen)) ;
|
|
if ( abs( m_TParams.m_dTipFeed - m_TParams.m_dFeed) < EPS_SMALL)
|
|
dEndSlowLen = 0 ;
|
|
if ( ( dStartSlowLen + dEndSlowLen) > hole.dLen) {
|
|
dStartSlowLen = dStartSlowLen / ( dStartSlowLen + dEndSlowLen) * hole.dLen ;
|
|
dEndSlowLen = hole.dLen - dStartSlowLen ;
|
|
}
|
|
double dStdLen = hole.dLen - dStartSlowLen - dEndSlowLen ;
|
|
double dAddLen = ( hole.bBlind ? 0 : m_Params.m_dThroughAddLen) ;
|
|
double dReturnPos = m_Params.m_dReturnPos ;
|
|
bool bStartSlow = ( dStartSlowLen > EPS_SMALL) ;
|
|
bool bStd = ( dStdLen > EPS_SMALL) ;
|
|
bool bEndSlow = ( dEndSlowLen > EPS_SMALL) ;
|
|
// determino l'elevazione
|
|
double dElev = 0 ;
|
|
GetElevation( m_nPhase, hole.ptIni, hole.vtDir, m_TParams.m_dDiam / 2, hole.vtDir, dElev) ;
|
|
// determino alcune caratteristiche dell'utensile
|
|
double dTExtrLen = max( 0.0, m_TParams.m_dTLen - m_TParams.m_dLen) ;
|
|
// necessità di spezzatura per robot
|
|
bool bSplitArcs = GetSplitArcs( V_NULL) ;
|
|
// imposto dati comuni
|
|
SetPathId( nPathId) ;
|
|
SetToolDir( hole.vtDir) ;
|
|
// 1 -> punto approccio
|
|
SetFlag( 1) ;
|
|
double dSafeZ = m_pMchMgr->GetCurrMachiningsMgr()->GetSafeZ() ;
|
|
double dSafeAggrBottZ = m_pMchMgr->GetCurrMachiningsMgr()->GetSafeAggrBottZ() ;
|
|
double dAppr = ( m_bAggrBottom ? dSafeAggrBottZ : dSafeZ) ;
|
|
Point3d ptP1 = hole.ptIni + hole.vtDir * ( dAppr + dElev + dTExtrLen) ;
|
|
if ( m_bAggrBottom) {
|
|
Point3d ptP0 = ptP1 + m_vtAggrBottom * ( m_dDistBottom + m_AggrBottom.dEncH + dSafeZ) ;
|
|
Point3d ptP00 = ptP0 + Z_AX * ( m_AggrBottom.dEncV + m_TParams.m_dLen + dAppr + dTExtrLen) ;
|
|
// se rinvio da sotto che richiede speciale rotazione
|
|
if ( m_AggrBottom.nType == 1) {
|
|
Vector3d vtAux = m_vtAggrBottom ;
|
|
vtAux.Rotate( Z_AX, 0, 1) ;
|
|
SetAuxDir( vtAux) ;
|
|
if ( AddRapidStart( ptP00, MCH_CL_AGB_DWN) == GDB_ID_NULL)
|
|
return false ;
|
|
SetFlag( 0) ;
|
|
SetAuxDir( m_vtAggrBottom) ;
|
|
if ( AddRapidMove( ptP0, bSplitArcs, MCH_CL_AGB_IN) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// altrimenti rinvio normale
|
|
else {
|
|
SetAuxDir( m_vtAggrBottom) ;
|
|
if ( AddRapidStart( ptP0, MCH_CL_AGB_IN) == GDB_ID_NULL)
|
|
return false ;
|
|
SetFlag( 0) ;
|
|
}
|
|
if ( AddRapidMove( ptP1, bSplitArcs) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
else {
|
|
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 = hole.ptIni + hole.vtDir * ( m_Params.m_dStartPos + dTExtrLen) ;
|
|
if ( AddRapidMove( ptP2, bSplitArcs) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// ciclo di affondamento a step
|
|
const double MIN_STEP = 5 ;
|
|
const double APPR_STEP = 1 ;
|
|
const double MIN_MOVE = 1 ;
|
|
double dStep = max( m_Params.m_dStep, MIN_STEP) ;
|
|
int nStep = int( ceil( hole.dLen / dStep)) ;
|
|
dStep = hole.dLen / nStep ;
|
|
if ( dReturnPos < - dStep + APPR_STEP + MIN_MOVE)
|
|
dReturnPos = - dStep + APPR_STEP + MIN_MOVE ;
|
|
double dCurrLen = 0 ;
|
|
for ( int i = 1 ; i <= nStep ; ++ i) {
|
|
// se non è primo step faccio retrazione e riaffondo
|
|
if ( i != 1) {
|
|
// retrazione
|
|
SetFeed( GetEndFeed()) ;
|
|
SetFlag( 103) ; // punto di scarico truciolo
|
|
Point3d ptPr = hole.ptIni + hole.vtDir * dReturnPos ;
|
|
if ( AddLinearMove( ptPr, bSplitArcs) == GDB_ID_NULL)
|
|
return false ;
|
|
// riaffondo
|
|
SetFeed( GetEndFeed()) ;
|
|
SetFlag( 0) ;
|
|
Point3d ptPa = hole.ptIni - hole.vtDir * ( dCurrLen - APPR_STEP) ;
|
|
if ( AddLinearMove( ptPa, bSplitArcs) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// lunghezza di fine step
|
|
double dEndLen = dCurrLen + dStep ;
|
|
// 3 -> punto termine velocità ridotta iniziale (se previsto)
|
|
if ( bStartSlow && ( i == 1 || dCurrLen < dStartSlowLen + EPS_SMALL)) {
|
|
// lunghezza di esecuzione
|
|
double dLen = min( dStartSlowLen, dEndLen) ;
|
|
// determino se arrivo in fondo al foro
|
|
bool bHoleEnd = ( ! bStd && ! bEndSlow && dLen > hole.dLen - EPS_SMALL) ;
|
|
// determino se arrivo in fondo allo step
|
|
bool bStepEnd = ( dLen > dEndLen - EPS_SMALL) ;
|
|
// assegno parametri
|
|
SetFeed( GetStartFeed()) ;
|
|
if ( bHoleEnd)
|
|
SetFlag( 101) ; // fondo del foro
|
|
else if ( bStepEnd)
|
|
SetFlag( 102) ; // fondo dello step
|
|
// movimento
|
|
Point3d ptP3 = hole.ptIni - hole.vtDir * dLen ;
|
|
if ( bHoleEnd)
|
|
ptP3 -= hole.vtDir * dAddLen ;
|
|
if ( AddLinearMove( ptP3, bSplitArcs) == GDB_ID_NULL)
|
|
return false ;
|
|
// aggiorno posizione e verifico se step completato
|
|
dCurrLen = dLen ;
|
|
if ( bHoleEnd || bStepEnd)
|
|
continue ;
|
|
}
|
|
// 4 -> punto termine velocità standard (se risulta)
|
|
if ( bStd && dCurrLen < dStartSlowLen + dStdLen + EPS_SMALL) {
|
|
// lunghezza di esecuzione
|
|
double dLen = min( hole.dLen - dEndSlowLen, dEndLen) ;
|
|
// determino se arrivo in fondo al foro
|
|
bool bHoleEnd = ( ! bEndSlow && dLen > hole.dLen - EPS_SMALL) ;
|
|
// determino se arrivo in fondo allo step
|
|
bool bStepEnd = ( dLen > dEndLen - EPS_SMALL) ;
|
|
// assegno parametri
|
|
SetFeed( GetFeed()) ;
|
|
if ( bHoleEnd)
|
|
SetFlag( 101) ; // fondo del foro
|
|
else if ( bStepEnd)
|
|
SetFlag( 102) ; // fondo dello step
|
|
// movimento
|
|
Point3d ptP4 = hole.ptIni - hole.vtDir * dLen ;
|
|
if ( bHoleEnd)
|
|
ptP4 -= hole.vtDir * dAddLen ;
|
|
if ( AddLinearMove( ptP4, bSplitArcs) == GDB_ID_NULL)
|
|
return false ;
|
|
// aggiorno posizione e verifico se step completato
|
|
dCurrLen = dLen ;
|
|
if ( bHoleEnd || bStepEnd)
|
|
continue ;
|
|
}
|
|
// 5 -> punto termine velocità finale ridotta (se previsto)
|
|
if ( bEndSlow) {
|
|
// lunghezza di esecuzione
|
|
double dLen = dEndLen ;
|
|
// determino se arrivo in fondo al foro
|
|
bool bHoleEnd = ( dLen > hole.dLen - EPS_SMALL) ;
|
|
// sono sempre in fondo allo step
|
|
// assegno parametri
|
|
SetFeed( GetTipFeed()) ;
|
|
if ( bHoleEnd)
|
|
SetFlag( 101) ; // fondo del foro
|
|
else
|
|
SetFlag( 102) ; // fondo dello step
|
|
// movimento
|
|
Point3d ptP5 = hole.ptIni - hole.vtDir * dLen ;
|
|
if ( bHoleEnd)
|
|
ptP5 -= hole.vtDir * dAddLen ;
|
|
if ( AddLinearMove( ptP5, bSplitArcs) == GDB_ID_NULL)
|
|
return false ;
|
|
// aggiorno posizione
|
|
dCurrLen = dLen ;
|
|
}
|
|
}
|
|
|
|
// 6 -> ritorno all'approccio del foro
|
|
SetFeed( GetEndFeed()) ;
|
|
SetFlag( 104) ; // risalita sopra il foro
|
|
if ( AddLinearMove( ptP1, bSplitArcs) == GDB_ID_NULL)
|
|
return false ;
|
|
|
|
// 7 -> punto fuori (se uso aggregato da sotto)
|
|
if ( m_bAggrBottom) {
|
|
SetFlag( 0) ;
|
|
Point3d ptP0 = ptP1 + m_vtAggrBottom * ( m_dDistBottom + m_AggrBottom.dEncH + dSafeZ) ;
|
|
Point3d ptP00 = ptP0 + Z_AX * ( m_AggrBottom.dEncV + m_TParams.m_dLen + dAppr + dTExtrLen) ;
|
|
if ( AddRapidMove( ptP0, bSplitArcs, MCH_CL_AGB_OUT) == GDB_ID_NULL)
|
|
return false ;
|
|
// se rinvio da sotto che richiede speciale rotazione
|
|
if ( m_AggrBottom.nType == 1) {
|
|
Vector3d vtAux = m_vtAggrBottom ;
|
|
vtAux.Rotate( Z_AX, 0, 1) ;
|
|
SetAuxDir( vtAux) ;
|
|
if ( AddRapidMove( ptP00, bSplitArcs, MCH_CL_AGB_UP) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
}
|
|
|
|
// reset dati di movimento
|
|
ResetMoveData() ;
|
|
|
|
return true ;
|
|
}
|