EgtMachKernel 2.1c1 :

- corretta risalita in Z tra lavorazioni (senza più CalcDeltaZForHeadRotation)
- corretta svuotatura per reset flag lato aperto prima di analisi
- modificata simulazione per gestire più grezzi simultaneamente.
This commit is contained in:
Dario Sassi
2019-03-04 08:04:32 +00:00
parent 2f1b3ba378
commit c0906ef63c
8 changed files with 121 additions and 69 deletions
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -3504,7 +3504,7 @@ bool
Milling::CalcOffset( ICurveComposite* pCompo, double dSignOffs)
{
// eseguo offset semplice
int nFlag = ICurve::OFF_FILLET ;
int nFlag = ICurve::OFF_FILLET | ICurve::OFF_FORCE_OPEN ;
if ( pCompo->SimpleOffset( dSignOffs, nFlag))
return true ;
// se curva piatta, provo con offset avanzato
+57 -34
View File
@@ -1394,31 +1394,38 @@ Operation::AdjustStartEndMovements( bool bVerifyPreviousLink)
DBLVECTOR vAxIni ;
if ( ! GetInitialAxesValues( vAxIni))
return false ;
// aggiungo eventuale delta Z
double dDeltaZ = 0 ;
// determino delta Z rispetto a posizione finale
if ( vAxVal.size() >= 4 && vAxIni.size() >= 4) {
// verifico se movimento assi rotanti richiede una risalita parziale
if ( ! CalcDeltaZForHeadRotation( vAxVal, vAxIni, dDeltaZ))
return false ;
}
// confronto con eventuale risalita di inizio lavorazione
dDeltaZ = max( dDeltaZ, ( vAxIni[2] - vAxVal[2])) ;
// se necessaria, aggiungo risalita parziale
double dDeltaZ = ( vAxIni[2] - vAxVal[2]) ;
if ( dDeltaZ > 100 * EPS_SMALL) {
if ( ! pPrevOp->AddRise( vAxVal, dDeltaZ))
return false ;
// aggiorno quota in Z della posizione iniziale ( anche se verrà aggiornata solo in seguito)
vAxIni[2] = vAxVal[2] ;
}
// verifico se la testa interferisce con i pezzi o i bloccaggi sulla tavola
if ( ! TestCollisionAvoid( vAxVal, vAxIni)) {
// riprovo con risalita parziale
double dHomeZ ;
if ( ! m_pMchMgr->GetCurrAxisHomePos( 2, dHomeZ))
// Verifico non ci sia collisione a Zmax
double dSafeZ ;
if ( m_pMchMgr->GetCurrAxisHomePos( 2, dSafeZ)) {
DBLVECTOR vAxVal2 = vAxVal ; vAxVal2[2] = dSafeZ ;
DBLVECTOR vAxIni2 = vAxIni ; vAxIni2[2] = dSafeZ ;
if ( ! TestCollisionAvoid( vAxVal2, vAxIni2))
return false ;
}
else
return false ;
// Se richiesta risalita a Zmax
if ( ForcedZmax( vAxVal, vAxIni)) {
// cancello eventuale risalita parziale della lavorazione precedente
pPrevOp->RemoveRise() ;
// aggiungo risalita a Zmax
if ( ! pPrevOp->AddRise( vAxVal))
return false ;
// si parte da Z massima
bMaxZ = true ;
}
// altrimenti, verifico se la testa interferisce con i pezzi o i bloccaggi sulla tavola
else if ( ! TestCollisionAvoid( vAxVal, vAxIni)) {
// riprovo con risalita parziale
bool bPartRise = false ;
double dSafeZ = dHomeZ ;
double dUnsafeZ = max( vAxVal[2], vAxIni[2]) ;
DBLVECTOR vAxVal2 = vAxVal ;
DBLVECTOR vAxIni2 = vAxIni ;
@@ -1558,8 +1565,10 @@ Operation::AdjustOneStartMovement( int nClPathId, int nPrevClPathId, const DBLVE
// per il test uso posizioni temporanee con questa Z
DBLVECTOR vAxPrevTmp = vAxPrev ; vAxPrevTmp[2] = dTopZ ;
DBLVECTOR vAxCurrTmp = vAxCurr ; vAxCurrTmp[2] = dTopZ ;
// verifico se forzata risalita a Zmax
bool bForcedZMax = ForcedZmax( vAxPrevTmp, vAxCurrTmp) ;
// se interferisce
if ( ! TestCollisionAvoid( vAxPrevTmp, vAxCurrTmp)) {
if ( bForcedZMax || ! TestCollisionAvoid( vAxPrevTmp, vAxCurrTmp)) {
// recupero HomeZ
double dHomeZ ;
if ( ! m_pMchMgr->GetCurrAxisHomePos( 2, dHomeZ))
@@ -1571,7 +1580,7 @@ Operation::AdjustOneStartMovement( int nClPathId, int nPrevClPathId, const DBLVE
double dTestSafeZ = ( dUnsafeZ + dSafeZ) / 2 ;
vAxPrevTmp[2] = dTestSafeZ ;
vAxCurrTmp[2] = dTestSafeZ ;
if ( TestCollisionAvoid( vAxPrevTmp, vAxCurrTmp))
if ( ! bForcedZMax && TestCollisionAvoid( vAxPrevTmp, vAxCurrTmp))
dSafeZ = dTestSafeZ ;
else
dUnsafeZ = dTestSafeZ ;
@@ -1939,6 +1948,35 @@ Operation::CalcDeltaZForHeadRotation( const DBLVECTOR& vAxStart, const DBLVECTOR
return true ;
}
//----------------------------------------------------------------------------
bool
Operation::ForcedZmax( const DBLVECTOR& vAxStart, const DBLVECTOR& vAxEnd)
{
// Recupero macchina corrente
Machine* pMch = ( m_pMchMgr != nullptr ? m_pMchMgr->GetCurrMachine() : nullptr) ;
if ( pMch == nullptr)
return true ;
// Recupero numero assi e ne verifico la costanza
int nLinAxes = m_pMchMgr->GetCurrLinAxes() ;
int nRotAxes = m_pMchMgr->GetCurrRotAxes() ;
if ( nLinAxes + nRotAxes != vAxStart.size() || nLinAxes + nRotAxes != vAxEnd.size())
return true ;
// Se testa con Info ZMAXONROT != 0 e movimento assi rotanti -> risalita a Zmax
int nHeadId = pMch->GetCurrHead() ;
DBLVECTOR vdVal ;
if ( m_pGeomDB->GetInfo( nHeadId, MCH_ZMAXONROT, vdVal) && vdVal.size() >= 1 && lround(vdVal[0]) > 0) {
double dAngTol = 100 * EPS_ANG_SMALL ;
if ( vdVal.size() >= 2)
dAngTol = max( vdVal[1], dAngTol) ;
for ( int i = nLinAxes ; i < nLinAxes + nRotAxes ; ++ i) {
if ( abs( vAxEnd[i] - vAxStart[i]) > dAngTol)
return true ;
}
}
// Non forzata risalita a Zmax
return false ;
}
//----------------------------------------------------------------------------
bool
Operation::TestCollisionAvoid( const DBLVECTOR& vAxStart, const DBLVECTOR& vAxEnd)
@@ -1951,26 +1989,11 @@ Operation::TestCollisionAvoid( const DBLVECTOR& vAxStart, const DBLVECTOR& vAxEn
string sTable ;
if ( ! pMch->GetCurrTable( sTable))
return false ;
// Recupero assi correnti
// Recupero assi correnti e ne verifico la costanza
STRVECTOR vAxName ;
pMch->GetAllCurrAxesName( vAxName) ;
// il numero di assi deve essere costante
if ( vAxName.size() != vAxStart.size() || vAxName.size() != vAxEnd.size())
return false ;
// Se testa con Info ZMAXONROT != 0 e movimento assi rotanti -> collisione
int nHeadId = pMch->GetCurrHead() ;
DBLVECTOR vdVal ;
if ( m_pGeomDB->GetInfo( nHeadId, MCH_ZMAXONROT, vdVal) && vdVal.size() >= 1 && lround(vdVal[0]) > 0) {
double dAngTol = 100 * EPS_ANG_SMALL ;
if ( vdVal.size() >= 2)
dAngTol = max( vdVal[1], dAngTol) ;
int nLinAxes = m_pMchMgr->GetCurrLinAxes() ;
int nRotAxes = m_pMchMgr->GetCurrRotAxes() ;
for ( int i = nLinAxes ; i < nLinAxes + nRotAxes ; ++ i) {
if ( int( vAxName.size()) > i && abs( vAxEnd[i] - vAxStart[i]) > dAngTol)
return false ;
}
}
// Porto la macchina in home
pMch->ResetAllAxesPos() ;
// Elenco grezzi attivi
+1
View File
@@ -103,6 +103,7 @@ class Operation : public IUserObj
bool RemoveRise( int nClPathId = GDB_ID_NULL) ;
bool AddHome( void) ;
bool CalcDeltaZForHeadRotation( const DBLVECTOR& vAxStart, const DBLVECTOR& vAxEnd, double& dDeltaZ) ;
bool ForcedZmax( const DBLVECTOR& vAxStart, const DBLVECTOR& vAxEnd) ;
bool TestCollisionAvoid( const DBLVECTOR& vAxStart, const DBLVECTOR& vAxEnd) ;
bool SpecialMoveZup( Vector3d& vtTool, DBLVECTOR& vAx, bool& bModif) ;
+28 -2
View File
@@ -932,6 +932,8 @@ Pocketing::GetCurves( SelData Id, ICURVEPLIST& lstPC)
return false ;
// la duplico
pCurve.Set( pOriCurve->Clone()) ;
// reset proprietà temporanee
ResetCurveAllTempProp( pCurve) ;
// se estrusione mancante, imposto default
Vector3d vtExtr ;
if ( ! pCurve->GetExtrusion( vtExtr) || vtExtr.IsSmall())
@@ -949,6 +951,8 @@ Pocketing::GetCurves( SelData Id, ICURVEPLIST& lstPC)
return false ;
// la duplico
pCurve.Set( pOriCurve->Clone()) ;
// reset proprietà temporanee
ResetCurveAllTempProp( pCurve) ;
// recupero estrusione e spessore
Vector3d vtExtr ;
if ( ! pCompo->GetExtrusion( vtExtr) || vtExtr.IsSmall())
@@ -975,6 +979,9 @@ Pocketing::GetCurves( SelData Id, ICURVEPLIST& lstPC)
// recupero l'outline del testo
if ( ! pText->GetOutline( lstPC))
return false ;
// reset proprietà temporanee
for ( auto pCrv : lstPC)
ResetCurveAllTempProp( pCrv) ;
// porto le curve in globale
for ( auto pCrv : lstPC)
pCrv->ToGlob( frGlob) ;
@@ -999,6 +1006,8 @@ Pocketing::GetCurves( SelData Id, ICURVEPLIST& lstPC)
pCrvCompo->FromPolyLine( vPL[0]) ;
if ( ! pCrvCompo->IsValid())
return false ;
// reset proprietà temporanee
ResetCurveAllTempProp( pCrvCompo) ;
// determino eventuali lati aperti e aggiorno proprietà del contorno
int nInd = 0 ;
double dPar ;
@@ -1063,6 +1072,8 @@ Pocketing::GetCurves( SelData Id, ICURVEPLIST& lstPC)
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
if ( IsNull( pCrvCompo) || ! pCrvCompo->AddCurve( pReg->GetLoop( nC, nL)))
return false ;
// reset proprietà temporanee
ResetCurveAllTempProp( pCrvCompo) ;
// assegno l'estrusione dalla normale alla regione
pCrvCompo->SetExtrusion( vtN) ;
// unisco le eventuali parti allineate
@@ -1082,6 +1093,21 @@ Pocketing::GetCurves( SelData Id, ICURVEPLIST& lstPC)
return false ;
}
//----------------------------------------------------------------------------
bool
Pocketing::ResetCurveAllTempProp( ICurve* pCurve)
{
if ( pCurve == nullptr)
return false ;
pCurve->SetTempProp( 0) ;
ICurveComposite* pCC = GetCurveComposite( pCurve) ;
if ( pCC != nullptr) {
for ( int i = 0 ; i < pCC->GetCurveCount() ; ++ i)
pCC->SetCurveTempProp( i, 0) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
Pocketing::Chain( int nGrpDestId)
@@ -1429,7 +1455,7 @@ Pocketing::ProcessPath( int nPathId, int nPvId, int nClId)
m_pGeomDB->SetName( nPxId, sPathName) ;
m_pGeomDB->SetMaterial( nPxId, GREEN) ;
// creo l'anteprima del percorso
if ( ! GenerateMillingPv( nPxId, pCompo))
if ( ! GeneratePocketingPv( nPxId, pCompo))
return false ;
}
@@ -1611,7 +1637,7 @@ Pocketing::VerifyPathFromBottom( const ICurveComposite* pCompo, const Vector3d&
//----------------------------------------------------------------------------
bool
Pocketing::GenerateMillingPv( int nPathId, const ICurveComposite* pCompo)
Pocketing::GeneratePocketingPv( int nPathId, const ICurveComposite* pCompo)
{
// creo copia della curva composita
PtrOwner< ICurve> pCrv( pCompo->Clone()) ;
+2 -1
View File
@@ -65,11 +65,12 @@ class Pocketing : public Machining
private :
bool VerifyGeometry( SelData Id, int& nSubs, int& nType) ;
bool GetCurves( SelData Id, ICURVEPLIST& lstPC) ;
bool ResetCurveAllTempProp( ICurve* pCurve) ;
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 VerifyPathFromBottom( const ICurveComposite* pCompo, const Vector3d& vtTool) ;
bool GenerateMillingPv( int nPathId, const ICurveComposite* pCompo) ;
bool GeneratePocketingPv( int nPathId, const ICurveComposite* pCompo) ;
bool AddZigZag( const ICurveComposite* pCompo, const Vector3d& vtTool, const Vector3d& vtExtr,
double dDepth, double dElev, double dOkStep, bool bSplitArcs) ;
bool CalcZigZag( const ICurveComposite* pOffs, ICRVCOMPOPOVECTOR& vpCrvs) ;
+29 -28
View File
@@ -57,7 +57,6 @@ Simulator::Simulator( void)
m_nAuxSInd = 0 ;
m_nAuxETot = 0 ;
m_nAuxEInd = 0 ;
m_nVmId = GDB_ID_NULL ;
m_dVmTdOffs = 0 ;
m_dVmAdOffs = 0 ;
m_bEnabAxes = true ;
@@ -176,7 +175,7 @@ Simulator::ResetInterpolation( void)
m_nAuxSInd = 0 ;
m_nAuxETot = 0 ;
m_nAuxEInd = 0 ;
m_nVmId = GDB_ID_NULL ;
m_VmId.clear() ;
m_dVmTdOffs = 0 ;
m_dVmAdOffs = 0 ;
m_bEnabAxes = true ;
@@ -913,21 +912,24 @@ Simulator::ManageSingleMove( int& nStatus, double& dMove)
dMove = ( m_dCoeff - dPrevCoeff) * dDist ;
// Posizione e direzione attuali dell'utensile e riferimento attuale del pezzo (per Vmill)
Point3d ptNoseI ; Vector3d vtDirI ; Vector3d vtAuxI ; Frame3d frVzmI ;
bool bOkI = GetHeadCurrPosDirAux( ptNoseI, vtDirI, vtAuxI) && m_pGeomDB->GetGlobFrame( m_nVmId, frVzmI) ;
Point3d ptNoseI ; Vector3d vtDirI ; Vector3d vtAuxI ;
bool bOkI = GetHeadCurrPosDirAux( ptNoseI, vtDirI, vtAuxI) ;
vector<Frame3d> vFrVzmI( m_VmId.size()) ;
for ( int i = 0 ; i < int( m_VmId.size()) ; ++ i)
bOkI = m_pGeomDB->GetGlobFrame( m_VmId[i], vFrVzmI[i]) && bOkI ;
// Eseguo movimento rapido o lineare
if ( nMoveType != 2 && nMoveType != 3) {
// assegno posizioni finali
for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) {
for ( int i = 0 ; i < int( m_AxesName.size()) ; ++ i) {
double dVal = m_AxesVal[i] * ( 1 - m_dCoeff) + AxesEnd[i] * m_dCoeff ;
m_pMachine->SetAxisPos( m_AxesName[i], dVal) ;
}
// eseguo eventuale Vmill
if ( m_nVmId != GDB_ID_NULL) {
for ( int j = 0 ; j < int( m_VmId.size()) ; ++ j) {
Point3d ptNoseF ; Vector3d vtDirF ; Vector3d vtAuxF ; Frame3d frVzmF ;
bool bOkF = GetHeadCurrPosDirAux( ptNoseF, vtDirF, vtAuxF) && m_pGeomDB->GetGlobFrame( m_nVmId, frVzmF) ; ;
ExecLineVmill( ptNoseI, vtDirI, vtAuxI, frVzmI, ptNoseF, vtDirF, vtAuxF, frVzmF) ;
bool bOkF = GetHeadCurrPosDirAux( ptNoseF, vtDirF, vtAuxF) && m_pGeomDB->GetGlobFrame( m_VmId[j], frVzmF) ; ;
ExecLineVmill( m_VmId[j], ptNoseI, vtDirI, vtAuxI, vFrVzmI[j], ptNoseF, vtDirF, vtAuxF, frVzmF) ;
}
}
// Eseguo movimento su arco
@@ -943,10 +945,10 @@ Simulator::ManageSingleMove( int& nStatus, double& dMove)
vtRot.Rotate( vtN, dPrevCoeff * dAngCen) ;
// approssimo movimento con 1 o più step a seconda ci sia Vmill
int nStep = 1 ;
if ( m_nVmId != GDB_ID_NULL) {
if ( ! m_VmId.empty()) {
const double LEN_STEP = 2. ;
nStep = max( int( abs( dDiffAng * DEGTORAD * dRad) / LEN_STEP), 1) ;
const double ANG_STEP = 10. ;
const double ANG_STEP = 5. ;
if ( abs( dDiffAng) / nStep > ANG_STEP)
nStep = int( abs( dDiffAng) / ANG_STEP) ;
}
@@ -958,20 +960,23 @@ Simulator::ManageSingleMove( int& nStatus, double& dMove)
m_pMachine->SetAxisPos( m_AxesName[1], ptCen.y + vtRot.y + dCurrCoeff * dDeltaN * vtN.y) ;
m_pMachine->SetAxisPos( m_AxesName[2], ptCen.z + vtRot.z + dCurrCoeff * dDeltaN * vtN.z) ;
// assi rotanti
for ( size_t j = 3 ; j < m_AxesName.size() ; ++ j) {
for ( int j = 3 ; j < int( m_AxesName.size()) ; ++ j) {
double dVal = m_AxesVal[j] * ( 1 - dCurrCoeff) + AxesEnd[j] * dCurrCoeff ;
m_pMachine->SetAxisPos( m_AxesName[j], dVal) ;
}
// eseguo eventuale Vmill
if ( m_nVmId != GDB_ID_NULL) {
Point3d ptNoseF ; Vector3d vtDirF ; Vector3d vtAuxF ; Frame3d frVzmF ;
bool bOkF = GetHeadCurrPosDirAux( ptNoseF, vtDirF, vtAuxF) && m_pGeomDB->GetGlobFrame( m_nVmId, frVzmF) ;
ExecLineVmill( ptNoseI, vtDirI, vtAuxI, frVzmI, ptNoseF, vtDirF, vtAuxF, frVzmF) ;
// aggiorno prossimo inizio
ptNoseI = ptNoseF ;
vtDirI = vtDirF ;
frVzmI = frVzmF ;
Point3d ptNoseF ; Vector3d vtDirF ; Vector3d vtAuxF ;
bool bOkF = GetHeadCurrPosDirAux( ptNoseF, vtDirF, vtAuxF) ;
for ( int k = 0 ; k < int( m_VmId.size()) ; ++ k) {
Frame3d frVzmF ;
bOkF = m_pGeomDB->GetGlobFrame( m_VmId[k], frVzmF) && bOkF ;
ExecLineVmill( m_VmId[k], ptNoseI, vtDirI, vtAuxI, vFrVzmI[k], ptNoseF, vtDirF, vtAuxF, frVzmF) ;
// salvo riferimento per prossimo inizio
vFrVzmI[k] = frVzmF ;
}
// aggiorno prossimo inizio
ptNoseI = ptNoseF ;
vtDirI = vtDirF ;
}
}
}
@@ -1046,11 +1051,11 @@ Simulator::GetHeadCurrPosDirAux( Point3d& ptH, Vector3d& vtH, Vector3d& vtA)
//----------------------------------------------------------------------------
bool
Simulator::ExecLineVmill( const Point3d& ptHi, const Vector3d& vtHi, const Vector3d& vtAi, const Frame3d& frVzmI,
const Point3d& ptHf, const Vector3d& vtHf, const Vector3d& vtAf, const Frame3d& frVzmF)
Simulator::ExecLineVmill( int nVmId, 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)) ;
IVolZmap* pVZM = GetVolZmap( m_pGeomDB->GetGeoObj( nVmId)) ;
if ( pVZM == nullptr)
return false ;
// Porto gli estremi nel riferimento opportuno dello Zmap
@@ -1145,9 +1150,7 @@ Simulator::OnDispositionStart( int nOpId, int nOpInd, int nPhase,
// chiamo la funzione di inizio disposizione
bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_DISPOSITION_START) ;
// recupero i dati di ritorno
int nVmId = GDB_ID_NULL ;
m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_VMILL, nVmId) ;
m_nVmId = nVmId ;
m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_VMILL, m_VmId) ;
// forzo aggiornamento posizione assi (possono essere stati mossi nello script)
UpdateAxesPos() ;
return bOk ;
@@ -1163,9 +1166,7 @@ Simulator::OnDispositionEnd( void)
// chiamo la funzione di fine disposizione
bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_DISPOSITION_END) ;
// recupero i dati di ritorno
int nVmId = GDB_ID_NULL ;
m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_VMILL, nVmId) ;
m_nVmId = nVmId ;
m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_VMILL, m_VmId) ;
// forzo aggiornamento posizione assi (possono essere stati mossi nello script)
UpdateAxesPos() ;
return bOk ;
+3 -3
View File
@@ -56,8 +56,8 @@ class Simulator
bool ManageMove( int& nStatus) ;
bool ManageSingleMove( int& nStatus, double& dMove) ;
bool GetHeadCurrPosDirAux( Point3d& ptH, Vector3d& vtH, Vector3d& vtA) ;
bool ExecLineVmill( 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 ExecLineVmill( int nVmId, 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 Stopped( void)
{ return ( m_nUiStatus == MCH_UISIM_STOP) ; }
bool OnStart( bool bFirst) ;
@@ -98,7 +98,7 @@ class Simulator
int m_nAuxETot ; // numero totale movimenti ausiliari di fine percorso
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
INTVECTOR m_VmId ; // vettore identificativi 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