7c4470b1d6
- prima versione del bloccaggio assi rotanti.
1329 lines
49 KiB
C++
1329 lines
49 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2016-2016
|
|
//----------------------------------------------------------------------------
|
|
// File : Operation.cpp Data : 29.04.16 Versione : 1.6p4
|
|
// Contenuto : Implementazione gestione base operazioni.
|
|
//
|
|
//
|
|
//
|
|
// Modifiche : 29.04.16 DS Creazione modulo.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "DllMain.h"
|
|
#include "Operation.h"
|
|
#include "MachMgr.h"
|
|
#include "/EgtDev/Include/EGkAngle.h"
|
|
#include "/EgtDev/Include/EGkGeoPoint3d.h"
|
|
#include "/EgtDev/Include/EGkCurveLine.h"
|
|
#include "/EgtDev/Include/EGkCurveArc.h"
|
|
#include "/EgtDev/Include/EgkDistPointCurve.h"
|
|
#include "/EgtDev/Include/EgkIntersCurves.h"
|
|
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
|
#include "/EgtDev/Include/EGkGeomDB.h"
|
|
#include "/EgtDev/Include/EgtPointerOwner.h"
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::SetOwner( int nId, IGeomDB* pGDB)
|
|
{
|
|
m_nOwnerId = nId ;
|
|
m_pGeomDB = pGDB ;
|
|
return ( m_nOwnerId != GDB_ID_NULL && m_pGeomDB != nullptr) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
Operation::GetOwner( void) const
|
|
{
|
|
return m_nOwnerId ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
IGeomDB*
|
|
Operation::GetGeomDB( void) const
|
|
{
|
|
return m_pGeomDB ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::Init( MachMgr* pMchMgr)
|
|
{
|
|
m_pMchMgr = pMchMgr ;
|
|
if ( m_pMchMgr == nullptr)
|
|
return false ;
|
|
if ( m_pMchMgr->GetGeomDB() != m_pGeomDB)
|
|
return false ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
Operation::Operation( void)
|
|
: m_nOwnerId( GDB_ID_NULL), m_pGeomDB( nullptr), m_pMchMgr( nullptr), m_nPhase( 1),
|
|
m_nPathId( GDB_ID_NULL), m_bCurr( false), m_ptCurr(),
|
|
m_vtTool(), m_vtCorr(), m_vtAux(), m_dFeed( 0), m_nFlag( 0)
|
|
{
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::GetElevation( int nPhase, const Point3d& ptP,
|
|
const Vector3d& vtDir, double& dElev)
|
|
{
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return false ;
|
|
// inizializzo elevazione
|
|
dElev = INFINITO ;
|
|
// ciclo sui grezzi
|
|
bool bFound = false ;
|
|
int nRawId = m_pMchMgr->GetFirstRawPart() ;
|
|
while ( nRawId != GDB_ID_NULL) {
|
|
// verifico che il grezzo compaia nella fase
|
|
if ( m_pMchMgr->VerifyRawPartPhase( nRawId, nPhase)) {
|
|
// intersezione del raggio dal punto alla trimesh del grezzo
|
|
const double RAY_LEN = 10000 ;
|
|
int nStmId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ;
|
|
ISurfTriMesh* pStm = GetSurfTriMesh( m_pGeomDB->GetGeoObj( nStmId)) ;
|
|
if ( pStm != nullptr) {
|
|
bFound = true ;
|
|
// recupero il riferimento della trimesh
|
|
Frame3d frStm ;
|
|
m_pGeomDB->GetGlobFrame( nStmId, frStm) ;
|
|
// porto il raggio in questo riferimento
|
|
Point3d ptPL = ptP ;
|
|
ptPL.ToLoc( frStm) ;
|
|
Vector3d vtDirL = vtDir ;
|
|
vtDirL.ToLoc( frStm) ;
|
|
ILSIVECTOR vInfo ;
|
|
if ( IntersLineSurfTm( ptPL, vtDirL, RAY_LEN, *pStm, vInfo)) {
|
|
for ( const auto& Info : vInfo) {
|
|
// se tratto di intersezione coincidente, considero la posizione più lontana, ovvero 2
|
|
if ( Info.nILTT == ILTT_SEGM || Info.nILTT == ILTT_SEGM_ON_EDGE) {
|
|
// se prosegue un tratto precedente, non devo controllare sia minimo
|
|
if ( fabs( dElev - Info.dU) < EPS_SMALL)
|
|
dElev = Info.dU2 ;
|
|
else
|
|
dElev = min( dElev, Info.dU2) ;
|
|
}
|
|
// altrimenti intersezione puntuale, verifico che esca (coseno >= 0)
|
|
else if ( Info.dCosDN > - COS_ORTO_ANG_ZERO) {
|
|
dElev = min( dElev, Info.dU) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// passo al grezzo successivo
|
|
nRawId = m_pMchMgr->GetNextRawPart( nRawId) ;
|
|
}
|
|
// se non trovate intersezioni, elevazione nulla
|
|
if ( dElev > INFINITO - 1)
|
|
dElev = 0 ;
|
|
return bFound ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::GetElevation( int nPhase, const Point3d& ptP1, const Point3d& ptP2,
|
|
const Vector3d& vtDir, double& dElev)
|
|
{
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return false ;
|
|
// inizializzo elevazione
|
|
dElev = INFINITO ;
|
|
// ciclo sui grezzi
|
|
bool bFound = false ;
|
|
int nRawId = m_pMchMgr->GetFirstRawPart() ;
|
|
while ( nRawId != GDB_ID_NULL) {
|
|
// verifico che il grezzo compaia nella fase
|
|
if ( m_pMchMgr->VerifyRawPartPhase( nRawId, nPhase)) {
|
|
// intersezione del raggio dal punto alla trimesh del grezzo
|
|
const double RAY_LEN = 10000 ;
|
|
int nStmId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ;
|
|
ISurfTriMesh* pStm = GetSurfTriMesh( m_pGeomDB->GetGeoObj( nStmId)) ;
|
|
if ( pStm != nullptr) {
|
|
bFound = true ;
|
|
// recupero il riferimento della trimesh
|
|
Frame3d frStm ;
|
|
m_pGeomDB->GetGlobFrame( nStmId, frStm) ;
|
|
// porto il segmento e la direzione in questo riferimento
|
|
Point3d ptP1L = ptP1 ;
|
|
ptP1L.ToLoc( frStm) ;
|
|
Point3d ptP2L = ptP2 ;
|
|
ptP2L.ToLoc( frStm) ;
|
|
Vector3d vtDirL = vtDir ;
|
|
vtDirL.ToLoc( frStm) ;
|
|
ILSIVECTOR vInfo ;
|
|
// inizializzo elevazione della superficie
|
|
double dElevS = 0 ;
|
|
// faccio test con un insieme di punti ( !!! sostituire con intersezione tra rettangolo e trimesh !!!)
|
|
const double STEP = 50 ;
|
|
int nStep = max( (int) ceil( ApproxDist( ptP1L, ptP2L) / STEP), 3) ;
|
|
for ( int i = 0 ; i <= nStep ; ++ i) {
|
|
// calcolo punto di test
|
|
double dFraz = i / (double) nStep ;
|
|
Point3d ptPL = Media( ptP1L, ptP2L, dFraz) ;
|
|
// inizializzo elevazione del punto
|
|
double dElevP = INFINITO ;
|
|
// calcolo elevazione sul punto
|
|
if ( IntersLineSurfTm( ptPL, vtDirL, RAY_LEN, *pStm, vInfo)) {
|
|
for ( const auto& Info : vInfo) {
|
|
// se tratto di intersezione coincidente, considero la posizione più lontana, ovvero 2
|
|
if ( Info.nILTT == ILTT_SEGM || Info.nILTT == ILTT_SEGM_ON_EDGE) {
|
|
// se prosegue un tratto precedente, non devo controllare sia minimo
|
|
if ( fabs( dElevP - Info.dU) < EPS_SMALL)
|
|
dElevP = Info.dU2 ;
|
|
else
|
|
dElevP = min( dElevP, Info.dU2) ;
|
|
}
|
|
// altrimenti intersezione puntuale, verifico che esca (coseno >= 0)
|
|
else if ( Info.dCosDN > - COS_ORTO_ANG_ZERO) {
|
|
dElevP = min( dElevP, Info.dU) ;
|
|
}
|
|
}
|
|
}
|
|
// se elevazione calcolata, aggiorno quella della superficie
|
|
if ( dElevP < INFINITO - 1)
|
|
dElevS = max( dElevS, dElevP) ;
|
|
}
|
|
// aggiorno elevazione complessiva
|
|
if ( dElevS > 0)
|
|
dElev = min( dElev, dElevS) ;
|
|
}
|
|
}
|
|
// passo al grezzo successivo
|
|
nRawId = m_pMchMgr->GetNextRawPart( nRawId) ;
|
|
}
|
|
// se non trovate intersezioni, elevazione nulla
|
|
if ( dElev > INFINITO - 1)
|
|
dElev = 0 ;
|
|
return bFound ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::GetElevation( int nPhase, const Point3d& ptP1, const Point3d& ptP2, const Point3d& ptP3,
|
|
const Vector3d& vtDir, double& dElev)
|
|
{
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return false ;
|
|
// approssimo l'arco con due linee
|
|
double dElev1, dElev2 ;
|
|
if ( ! GetElevation( nPhase, ptP1, ptP2, vtDir, dElev1))
|
|
return false ;
|
|
if ( ! GetElevation( nPhase, ptP2, ptP3, vtDir, dElev2))
|
|
return false ;
|
|
dElev = max( dElev1, dElev2) ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::GetDistanceFromRawSide( int nPhase, const Point3d& ptP, const Vector3d& vtDir, double& dDist)
|
|
{
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return false ;
|
|
// recupero il grezzo in cui è incluso il punto
|
|
BBox3d b3Pnt( ptP) ;
|
|
b3Pnt.Expand( 10, 10, 0) ;
|
|
int nRawId = m_pMchMgr->GetFirstRawPart() ;
|
|
while ( nRawId != GDB_ID_NULL) {
|
|
// verifico che il grezzo compaia nella fase
|
|
if ( m_pMchMgr->VerifyRawPartPhase( nRawId, nPhase)) {
|
|
// pre-filtro con il box
|
|
BBox3d b3Raw ;
|
|
int nRawSolidId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ;
|
|
if ( m_pGeomDB->GetGlobalBBox( nRawSolidId, b3Raw) && b3Pnt.OverlapsXY( b3Raw)) {
|
|
// porto il punto nel riferimento del grezzo
|
|
Frame3d frRaw ;
|
|
m_pGeomDB->GetGroupGlobFrame( nRawId, frRaw) ;
|
|
Point3d ptPL = ptP ;
|
|
ptPL.ToLoc( frRaw) ;
|
|
// verifica con il contorno
|
|
int nOutCrvId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_OUTLINE) ;
|
|
ICurve* pCurve = GetCurve( m_pGeomDB->GetGeoObj( nOutCrvId)) ;
|
|
if ( pCurve != nullptr) {
|
|
int nSide ;
|
|
double dDist ;
|
|
DistPointCurve distPC( ptPL, *pCurve) ;
|
|
if ( distPC.GetDist( dDist) && dDist < 100 * EPS_SMALL ||
|
|
(distPC.GetSideAtMinDistPoint( 0, Z_AX, nSide) && nSide != MDS_RIGHT))
|
|
break ;
|
|
}
|
|
}
|
|
}
|
|
// passo al grezzo successivo
|
|
nRawId = m_pMchMgr->GetNextRawPart( nRawId) ;
|
|
}
|
|
// se il punto non è interno ad alcun grezzo, distanza nulla
|
|
if ( nRawId == GDB_ID_NULL) {
|
|
dDist = 0 ;
|
|
return true ;
|
|
}
|
|
// recupero il contorno del grezzo
|
|
int nOutId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_OUTLINE) ;
|
|
ICurve* pOut = ::GetCurve( m_pGeomDB->GetGeoObj( nOutId)) ;
|
|
if ( pOut == nullptr)
|
|
return false ;
|
|
// recupero il riferimento del contorno e verifico che abbia Z verticale
|
|
Frame3d frStm ;
|
|
if ( ! m_pGeomDB->GetGlobFrame( nOutId, frStm) ||
|
|
( frStm.GetZType() != Frame3d::TOP && frStm.GetZType() != Frame3d::BOTTOM))
|
|
return false ;
|
|
// interseco il raggio di test (portato nel riferimento del contorno) con il contorno del grezzo
|
|
const double RAY_LEN = 10000 ;
|
|
PtrOwner<ICurveLine> pRay( CreateCurveLine()) ;
|
|
if ( IsNull( pRay) || ! pRay->SetPVL( ptP, vtDir, RAY_LEN))
|
|
return false ;
|
|
pRay->ToLoc( frStm) ;
|
|
IntersCurveCurve intCC( *pRay, *pOut) ;
|
|
IntCrvCrvInfo aInfo ;
|
|
if ( intCC.GetIntCrvCrvInfo( 0, aInfo))
|
|
dDist = aInfo.IciA[0].dU * RAY_LEN ;
|
|
else
|
|
dDist = 0 ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::GetDistanceFromRawBottom( int nPhase, int nPathId, double dToler, double& dRbDist)
|
|
{
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return false ;
|
|
// recupero distanza da fondo dei grezzi interessati dal percorso
|
|
dRbDist = 0 ;
|
|
BBox3d b3Compo ;
|
|
if ( ! m_pGeomDB->GetGlobalBBox( nPathId, b3Compo))
|
|
return false ;
|
|
b3Compo.Expand( dToler, dToler, 0) ;
|
|
int nRawId = m_pMchMgr->GetFirstRawPart() ;
|
|
while ( nRawId != GDB_ID_NULL) {
|
|
// verifico che il grezzo compaia nella fase
|
|
if ( m_pMchMgr->VerifyRawPartPhase( nRawId, nPhase)) {
|
|
BBox3d b3Raw ;
|
|
int nRawSolidId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ;
|
|
if ( m_pGeomDB->GetGlobalBBox( nRawSolidId, b3Raw) && b3Compo.OverlapsXY( b3Raw)) {
|
|
double dDist = b3Compo.GetMax().z - b3Raw.GetMin().z ;
|
|
if ( dDist > dRbDist)
|
|
dRbDist = dDist ;
|
|
}
|
|
}
|
|
// passo al grezzo successivo
|
|
nRawId = m_pMchMgr->GetNextRawPart( nRawId) ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::GetRawGlobBox( int nPhase, int nPathId, BBox3d& b3Raw)
|
|
{
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return false ;
|
|
// inizializzo box
|
|
b3Raw.Reset() ;
|
|
// ricerco grezzi interessati dal percorso
|
|
BBox3d b3Compo ;
|
|
if ( ! m_pGeomDB->GetGlobalBBox( nPathId, b3Compo))
|
|
return false ;
|
|
b3Compo.Expand( 10 * EPS_SMALL, 10 * EPS_SMALL, 0) ;
|
|
int nRawId = m_pMchMgr->GetFirstRawPart() ;
|
|
while ( nRawId != GDB_ID_NULL) {
|
|
// verifico che il grezzo compaia nella fase
|
|
if ( m_pMchMgr->VerifyRawPartPhase( nRawId, nPhase)) {
|
|
BBox3d b3OneRaw ;
|
|
int nRawSolidId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ;
|
|
if ( m_pGeomDB->GetGlobalBBox( nRawSolidId, b3OneRaw) && b3Compo.OverlapsXY( b3OneRaw)) {
|
|
b3Raw.Add( b3OneRaw) ;
|
|
}
|
|
}
|
|
// passo al grezzo successivo
|
|
nRawId = m_pMchMgr->GetNextRawPart( nRawId) ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::GetInitialAxesValues( DBLVECTOR& vAxVal)
|
|
{
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return false ;
|
|
// recupero gruppo per geometria di lavorazione (Cutter Location)
|
|
int nClId = m_pGeomDB->GetFirstNameInGroup( GetOwner(), MCH_CL) ;
|
|
if ( nClId == GDB_ID_NULL)
|
|
return false ;
|
|
// recupero il primo percorso CL
|
|
int nClPathId = m_pGeomDB->GetFirstGroupInGroup( nClId) ;
|
|
// restituisco i valori iniziali degli assi di questo percorso di lavorazione
|
|
return GetClPathInitialAxesValues( nClPathId, vAxVal) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::GetClPathInitialAxesValues( int nClPathId, DBLVECTOR& vAxVal)
|
|
{
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return false ;
|
|
// recupero la prima entità di questo percorso
|
|
int nEntId = m_pGeomDB->GetFirstInGroup( nClPathId) ;
|
|
// recupero i dati Cam dell'entità
|
|
CamData* pCamData = GetCamData( m_pGeomDB->GetUserObj( nEntId)) ;
|
|
if ( pCamData == nullptr)
|
|
return false ;
|
|
// assegno i valori degli assi
|
|
vAxVal = pCamData->GetAxesVal() ;
|
|
return ( vAxVal.size() > 0) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::GetFinalAxesValues( DBLVECTOR& vAxVal)
|
|
{
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return false ;
|
|
// recupero gruppo per geometria di lavorazione (Cutter Location)
|
|
int nClId = m_pGeomDB->GetFirstNameInGroup( GetOwner(), MCH_CL) ;
|
|
if ( nClId == GDB_ID_NULL)
|
|
return false ;
|
|
// recupero l'ultimo percorso CL
|
|
int nClPathId = m_pGeomDB->GetLastGroupInGroup( nClId) ;
|
|
// restituisco i valori finali degli assi di questo percorso di lavorazione
|
|
return GetClPathFinalAxesValues( nClPathId, vAxVal) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::GetClPathFinalAxesValues( int nClPathId, DBLVECTOR& vAxVal)
|
|
{
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return false ;
|
|
// recupero l'ultima entità di questo percorso
|
|
int nEntId = m_pGeomDB->GetLastInGroup( nClPathId) ;
|
|
// recupero i dati Cam dell'entità
|
|
CamData* pCamData = GetCamData( m_pGeomDB->GetUserObj( nEntId)) ;
|
|
if ( pCamData == nullptr)
|
|
return false ;
|
|
// assegno i valori degli assi
|
|
vAxVal = pCamData->GetAxesVal() ;
|
|
return ( vAxVal.size() > 0) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::CalculateAxesValues( void)
|
|
{
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return false ;
|
|
// recupero l'operazione precedente non vuota
|
|
int nPrevOpId = m_pMchMgr->GetPrevActiveOperation( m_nOwnerId) ;
|
|
Operation* pPrevOp = GetOperation( m_pGeomDB->GetUserObj( nPrevOpId)) ;
|
|
while ( pPrevOp != nullptr) {
|
|
if ( ! pPrevOp->IsEmpty())
|
|
break ;
|
|
else {
|
|
nPrevOpId = m_pMchMgr->GetPrevActiveOperation( nPrevOpId) ;
|
|
pPrevOp = GetOperation( m_pGeomDB->GetUserObj( nPrevOpId)) ;
|
|
}
|
|
}
|
|
// recupero l'utensile precedente
|
|
string sPrevTool ;
|
|
if ( pPrevOp != nullptr)
|
|
sPrevTool = pPrevOp->GetToolName() ;
|
|
|
|
// imposto l'utensile per i calcoli macchina
|
|
if ( ! m_pMchMgr->SetCalcTool( GetToolName(), GetHeadName(), GetExitNbr()))
|
|
return false ;
|
|
|
|
// rimuovo posizionamento home da lavorazione precedente (non può più essere l'ultima)
|
|
if ( pPrevOp != nullptr)
|
|
pPrevOp->RemoveHome() ;
|
|
|
|
// recupero il numero di assi lineari e rotanti attivi
|
|
int nLinAxes = m_pMchMgr->GetCurrLinAxes() ;
|
|
int nRotAxes = m_pMchMgr->GetCurrRotAxes() ;
|
|
|
|
// assegno gli angoli iniziali
|
|
DBLVECTOR vAxRotPrec( nRotAxes, 0.) ;
|
|
DBLVECTOR vAxVal ;
|
|
// se utensile non cambiato, uso gli angoli finali della lavorazione precedente
|
|
if ( ! sPrevTool.empty() && GetToolName() == sPrevTool &&
|
|
pPrevOp->GetFinalAxesValues( vAxVal)) {
|
|
for ( int i = 0 ; i < nRotAxes ; ++ i)
|
|
vAxRotPrec[i] = vAxVal[nLinAxes + i] ;
|
|
}
|
|
// altrimenti uso gli angoli home
|
|
else {
|
|
m_pMchMgr->GetAllCalcAxesHomePos( vAxVal) ;
|
|
for ( int i = 0 ; i < nRotAxes ; ++ i)
|
|
vAxRotPrec[i] = vAxVal[nLinAxes + i] ;
|
|
}
|
|
|
|
// recupero peso primo asse rotante di testa
|
|
double dRot1W = m_pMchMgr->GetCalcRot1W() ;
|
|
|
|
// applico eventuali blocchi di assi rotanti
|
|
m_pMchMgr->ApplyRotAxisBlock() ;
|
|
|
|
// recupero gruppo della geometria di lavorazione (Cutter Location)
|
|
int nClId = m_pGeomDB->GetFirstNameInGroup( GetOwner(), MCH_CL) ;
|
|
if ( nClId == GDB_ID_NULL)
|
|
return false ;
|
|
|
|
// calcolo il valore degli assi macchina di tutti i movimenti
|
|
bool bOk = true ;
|
|
int nClPathId = m_pGeomDB->GetFirstGroupInGroup( nClId) ;
|
|
while ( nClPathId != GDB_ID_NULL) {
|
|
DBLVECTOR vAxRotPrecOri = vAxRotPrec ;
|
|
int nOutStrC = 0 ;
|
|
if ( ! CalculateClPathAxesValues( nClPathId, nLinAxes, nRotAxes, dRot1W, vAxRotPrec, nOutStrC)) {
|
|
// se extracorsa dell'asse C, provo a precaricarlo al contrario
|
|
if ( nOutStrC != 0) {
|
|
vAxRotPrec[0] = vAxRotPrecOri[0] + ( nOutStrC > 0 ? - ANG_FULL : ANG_FULL) ;
|
|
vAxRotPrec[1] = vAxRotPrecOri[1] ;
|
|
if ( ! CalculateClPathAxesValues( nClPathId, nLinAxes, nRotAxes, dRot1W, vAxRotPrec, nOutStrC))
|
|
bOk = false ;
|
|
}
|
|
else
|
|
bOk = false ;
|
|
}
|
|
nClPathId = m_pGeomDB->GetNextGroup( nClPathId) ;
|
|
}
|
|
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::CalculateClPathAxesValues( int nClPathId, int nLinAxes, int nRotAxes, double dRot1W,
|
|
DBLVECTOR& vAxRotPrec, int& nOutStrC)
|
|
{
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return false ;
|
|
// recupero il numero degli assi lineari e rotanti
|
|
// predispongo variabile per valori assi
|
|
DBLVECTOR vAxVal ;
|
|
vAxVal.reserve( 8) ;
|
|
// variabili per coordinate lineari precedenti
|
|
double dXprec, dYprec, dZprec ;
|
|
// ciclo su tutte le entità del percorso CL
|
|
nOutStrC = 0 ;
|
|
bool bOk = true ;
|
|
bool bFirst = true ;
|
|
for ( int nEntId = m_pGeomDB->GetFirstInGroup( nClPathId) ;
|
|
nEntId != GDB_ID_NULL ;
|
|
nEntId = m_pGeomDB->GetNext( nEntId)) {
|
|
// recupero i dati Cam dell'entità
|
|
CamData* pCamData = GetCamData( m_pGeomDB->GetUserObj( nEntId)) ;
|
|
if ( pCamData == nullptr)
|
|
continue ;
|
|
// verifico che il primo movimento non sia un arco
|
|
if ( bFirst && pCamData->IsArc()) {
|
|
pCamData->ResetAxes() ;
|
|
LOG_INFO( GetEMkLogger(), "Error : first move in ClPath is an arc")
|
|
return false ;
|
|
}
|
|
// calcolo degli assi rotanti della macchina
|
|
int nRStat ;
|
|
DBLVECTOR vAng1, vAng2 ;
|
|
bool bROk = m_pMchMgr->GetCalcAngles( pCamData->GetToolDir(), pCamData->GetAuxDir(), nRStat, vAng1, vAng2) ;
|
|
if ( ! bROk || nRStat == 0) {
|
|
bOk = false ;
|
|
pCamData->SetAxes( CamData::AS_DIR_ERR, vAxVal) ;
|
|
continue ;
|
|
}
|
|
if ( nRStat == 1) {
|
|
// se primo movimento
|
|
if ( bFirst) {
|
|
// porto gli angoli ai valori più vicini ai precedenti con offset di uno o più giri
|
|
for ( size_t i = 0 ; i < vAng1.size() ; ++ i)
|
|
m_pMchMgr->GetNearestAngleInStroke( int( i), vAxRotPrec[i], vAng1[i]) ;
|
|
}
|
|
// per movimenti successivi
|
|
else {
|
|
// scelgo gli angoli più vicini, per continuità non applico offset per stare nelle corse
|
|
for ( size_t i = 0 ; i < vAng1.size() ; ++ i)
|
|
vAng1[i] = AngleNearAngle( vAng1[i], vAxRotPrec[i]) ;
|
|
}
|
|
}
|
|
if ( nRStat == 2) {
|
|
// se primo movimento
|
|
if ( bFirst) {
|
|
// porto gli angoli ai valori più vicini ai precedenti con offset di uno o più giri
|
|
for ( size_t i = 0 ; i < vAng1.size() ; ++ i) {
|
|
m_pMchMgr->GetNearestAngleInStroke( int( i), vAxRotPrec[i], vAng1[i]) ;
|
|
m_pMchMgr->GetNearestAngleInStroke( int( i), vAxRotPrec[i], vAng2[i]) ;
|
|
}
|
|
}
|
|
else {
|
|
// scelgo gli angoli più vicini, per continuità non applico offset per stare nelle corse
|
|
for ( size_t i = 0 ; i < vAng1.size() ; ++ i) {
|
|
vAng1[i] = AngleNearAngle( vAng1[i], vAxRotPrec[i]) ;
|
|
vAng2[i] = AngleNearAngle( vAng2[i], vAxRotPrec[i]) ;
|
|
}
|
|
}
|
|
// scelgo la soluzione più vicina ai precedenti
|
|
double dDelta1 = 0 ;
|
|
double dDelta2 = 0 ;
|
|
bool bFirst = true ;
|
|
for ( size_t i = 0 ; i < vAng1.size() ; ++ i) {
|
|
// ignoro gli assi bloccati
|
|
if ( ! m_pMchMgr->IsKinematicRotAxisBlocked( int( i)))
|
|
continue ;
|
|
// calcolo i delta asse con eventuale peso
|
|
dDelta1 += fabs( vAng1[i] - vAxRotPrec[i]) * ( bFirst ? dRot1W : 1) ;
|
|
dDelta2 += fabs( vAng2[i] - vAxRotPrec[i]) * ( bFirst ? dRot1W : 1) ;
|
|
}
|
|
if ( dDelta2 < dDelta1 - 1.)
|
|
vAng1 = vAng2 ;
|
|
}
|
|
// ricavo posizione con eventuali modifiche dipendenti dalla lavorazione
|
|
Point3d ptP = pCamData->GetEndPoint() ;
|
|
AdjustEndPointForAxesCalc( pCamData, ptP) ;
|
|
// calcolo gli assi lineari della macchina
|
|
int nLStat ;
|
|
double dX, dY, dZ ;
|
|
bool bLOk = m_pMchMgr->GetCalcPositions( ptP, vAng1, nLStat, dX, dY, dZ) ;
|
|
if ( ! bLOk || nLStat != 0) {
|
|
bOk = false ;
|
|
pCamData->SetAxes( CamData::AS_ERR, vAxVal) ;
|
|
continue ;
|
|
}
|
|
// assegno valori assi
|
|
vAxVal.clear() ;
|
|
vAxVal.emplace_back( dX) ;
|
|
vAxVal.emplace_back( dY) ;
|
|
vAxVal.emplace_back( dZ) ;
|
|
for ( auto dAng : vAng1)
|
|
vAxVal.emplace_back( dAng) ;
|
|
// verifico i limiti di corsa degli assi
|
|
int nStat ;
|
|
double dAngA = ( vAng1.size() >= 1 ? vAng1[0] : 0) ;
|
|
double dAngB = ( vAng1.size() >= 2 ? vAng1[1] : 0) ;
|
|
bool bOsOk = m_pMchMgr->VerifyOutstroke( dX, dY, dZ, dAngA, dAngB, nStat) ;
|
|
if ( ! bOsOk || nStat != 0) {
|
|
bOk = false ;
|
|
pCamData->SetAxes( CamData::AS_OUTSTROKE, vAxVal) ;
|
|
if ( nOutStrC == 0) {
|
|
if ( (nStat & 64) != 0)
|
|
nOutStrC = - 1 ;
|
|
else if ( (nStat & 128) != 0)
|
|
nOutStrC = 1 ;
|
|
}
|
|
string sInfo = "Outstroke : " + m_pMchMgr->GetOutstrokeInfo() ;
|
|
LOG_INFO( GetEMkLogger(), sInfo.c_str())
|
|
continue ;
|
|
}
|
|
// salvo i valori degli assi
|
|
pCamData->SetAxes( CamData::AS_OK, vAxVal) ;
|
|
// se arco (per ora solo nel piano XY) devo calcolarne il centro in assi macchina
|
|
if ( pCamData->IsArc()) {
|
|
// ricavo punto medio
|
|
Point3d ptCen = pCamData->GetCenter() ;
|
|
double dAngCen = pCamData->GetAngCen() ;
|
|
Point3d ptMid = ptP ;
|
|
ptMid.Rotate( ptCen, Z_AX, - dAngCen / 2) ;
|
|
// determino i valori degli assi al punto medio
|
|
DBLVECTOR vAngMid( vAng1.size()) ;
|
|
for ( size_t i = 0 ; i < vAng1.size() ; ++ i)
|
|
vAngMid[i] = ( vAxRotPrec[i] + vAng1[i]) / 2 ;
|
|
int nLmidStat ;
|
|
double dXmid, dYmid, dZmid ;
|
|
bool bLmidOk = m_pMchMgr->GetCalcPositions( ptMid, vAngMid, nLmidStat, dXmid, dYmid, dZmid) ;
|
|
if ( ! bLmidOk || nLmidStat != 0) {
|
|
bOk = false ;
|
|
pCamData->SetAxes( CamData::AS_ERR, vAxVal) ;
|
|
continue ;
|
|
}
|
|
// punti espressi in assi macchina
|
|
Point3d ptP1M( dXprec, dYprec, dZprec) ;
|
|
Point3d ptP2M( dXmid, dYmid, dZmid) ;
|
|
Point3d ptP3M( dX, dY, dZ) ;
|
|
// se coincidono
|
|
if ( AreSamePointApprox( ptP1M, ptP2M) && AreSamePointApprox( ptP1M, ptP3M)) {
|
|
// lo considero un arco di raggio nullo
|
|
pCamData->SetAxesCen( ptP2M) ;
|
|
pCamData->SetAxesRad( 0) ;
|
|
pCamData->SetAxesAngCen( 0) ;
|
|
// il movimento diventa lineare
|
|
pCamData->SetMoveType( 1) ;
|
|
// non è necessario verificare i limiti di corsa degli assi
|
|
}
|
|
// altrimenti calcolo l'arco cui appartengono
|
|
else {
|
|
// calcolo arco per i tre punti espressi in assi macchina
|
|
PtrOwner<ICurveArc> pArc( CreateCurveArc()) ;
|
|
if ( IsNull( pArc) || ! pArc->Set3P( ptP1M, ptP2M, ptP3M, false)) {
|
|
bOk = false ;
|
|
continue ;
|
|
}
|
|
// verifico il piano
|
|
if ( pArc->GetNormVersor().z < 0)
|
|
pArc->InvertN() ;
|
|
// assegno il centro e il raggio di questo arco ai dati cam
|
|
pCamData->SetAxesCen( pArc->GetCenter()) ;
|
|
pCamData->SetAxesRad( pArc->GetRadius()) ;
|
|
pCamData->SetAxesAngCen( pArc->GetAngCenter()) ;
|
|
// aggiorno il tipo di arco
|
|
pCamData->SetMoveType( pArc->GetAngCenter() > 0 ? 3 : 2) ;
|
|
// verifico i limiti di corsa dei punti lungo l'arco
|
|
const int NUM_VERIF_STEP = 16 ;
|
|
Point3d ptCen = pCamData->GetAxesCen() ;
|
|
double dAngCenStep = pCamData->GetAxesAngCen() / NUM_VERIF_STEP ;
|
|
Vector3d vtCurr = Point3d( dXprec, dYprec, dZprec) - ptCen ;
|
|
for ( int i = 1 ; i < NUM_VERIF_STEP ; ++ i) {
|
|
vtCurr.Rotate( Z_AX, dAngCenStep) ;
|
|
Point3d ptCurr = ptCen + vtCurr ;
|
|
double dCoeff = i / NUM_VERIF_STEP ;
|
|
DBLVECTOR vAng( vAng1.size()) ;
|
|
for ( size_t i = 0 ; i < vAng1.size() ; ++ i)
|
|
vAng[i] = vAxRotPrec[i] * ( 1 - dCoeff) + vAng1[i] * dCoeff ;
|
|
int nStat ;
|
|
bool bOsOk = m_pMchMgr->VerifyOutstroke( ptCurr.x, ptCurr.y, ptCurr.z, vAng[0], vAng[1], nStat) ;
|
|
if ( ! bOsOk || nStat != 0) {
|
|
bOk = false ;
|
|
pCamData->SetAxes( CamData::AS_OUTSTROKE, vAxVal) ;
|
|
string sInfo = "Outstroke : " + m_pMchMgr->GetOutstrokeInfo() ;
|
|
LOG_INFO( GetEMkLogger(), sInfo.c_str())
|
|
continue ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
bFirst = false ;
|
|
// memorizzo i valori degli assi lineari come nuovi precedenti
|
|
dXprec = dX ;
|
|
dYprec = dY ;
|
|
dZprec = dZ ;
|
|
// memorizzo i valori degli angoli come nuovi precedenti
|
|
vAxRotPrec = vAng1 ;
|
|
}
|
|
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::AdjustStartEndMovements(void)
|
|
{
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return false ;
|
|
// recupero gruppo della geometria di lavorazione (Cutter Location)
|
|
int nClId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_CL) ;
|
|
if ( nClId == GDB_ID_NULL)
|
|
return false ;
|
|
|
|
// recupero la lavorazione precedente non vuota
|
|
int nPrevOpId = m_pMchMgr->GetPrevActiveOperation( m_nOwnerId) ;
|
|
Operation* pPrevOp = GetOperation( m_pGeomDB->GetUserObj( nPrevOpId)) ;
|
|
while ( pPrevOp != nullptr) {
|
|
if ( ! pPrevOp->IsEmpty())
|
|
break ;
|
|
else {
|
|
nPrevOpId = m_pMchMgr->GetPrevActiveOperation( nPrevOpId) ;
|
|
pPrevOp = GetOperation( m_pGeomDB->GetUserObj( nPrevOpId)) ;
|
|
}
|
|
}
|
|
// recupero l'utensile precedente e i dati della sua testa
|
|
string sPrevTool ;
|
|
if ( pPrevOp != nullptr)
|
|
sPrevTool = pPrevOp->GetToolName() ;
|
|
|
|
// imposto l'utensile per i calcoli macchina
|
|
if ( ! m_pMchMgr->SetCalcTool( GetToolName(), GetHeadName(), GetExitNbr()))
|
|
return false ;
|
|
|
|
// determino posizione precedente assi
|
|
DBLVECTOR vAxVal ;
|
|
// se primo utensile, uso la posizione home
|
|
if ( sPrevTool.empty()) {
|
|
if ( ! m_pMchMgr->GetAllCalcAxesHomePos( vAxVal))
|
|
return false ;
|
|
}
|
|
// se utensile non cambiato o su diversa uscita della stessa testa, uso posizione finale della lavorazione precedente
|
|
else if ( ! ToolChangeNeeded( *pPrevOp, *this)) {
|
|
pPrevOp->RemoveRise() ;
|
|
DBLVECTOR vAxIni ;
|
|
if ( ! pPrevOp->GetFinalAxesValues( vAxVal) || ! GetInitialAxesValues( vAxIni))
|
|
return false ;
|
|
// determino delta Z rispetto a posizione finale
|
|
if ( vAxVal.size() >= 4 && vAxIni.size() >= 4) {
|
|
double dDelta = 0 ;
|
|
if ( ! CalcDeltaZForHeadRotation( vAxVal, vAxIni, dDelta))
|
|
return false ;
|
|
if ( dDelta > EPS_SMALL) {
|
|
if ( ! pPrevOp->AddRise( vAxVal, dDelta))
|
|
return false ;
|
|
}
|
|
}
|
|
}
|
|
// altrimenti aggiungo uscita per cambio utensile alla lavorazione precedente e parto da questa
|
|
else {
|
|
pPrevOp->RemoveRise() ;
|
|
if ( ! pPrevOp->AddRise( vAxVal))
|
|
return false ;
|
|
}
|
|
|
|
// aggiusto l'inizio di ogni percorso di lavoro
|
|
bool bOk = true ;
|
|
int nClPathId = m_pGeomDB->GetFirstGroupInGroup( nClId) ;
|
|
while ( bOk && nClPathId != GDB_ID_NULL) {
|
|
// sistemo inizio
|
|
if ( ! AdjustOneStartMovement( nClPathId, vAxVal))
|
|
bOk = false ;
|
|
// recupero nuovi finali
|
|
if ( ! GetClPathFinalAxesValues( nClPathId, vAxVal))
|
|
bOk = false ;
|
|
// passo al successivo
|
|
nClPathId = m_pGeomDB->GetNextGroup( nClPathId) ;
|
|
}
|
|
|
|
// aggiungo risalita finale
|
|
bOk = bOk && AddRise( vAxVal) ;
|
|
bOk = bOk && AddHome() ;
|
|
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::AdjustOneStartMovement( int nClPathId, const DBLVECTOR& vAxPrev)
|
|
{
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return false ;
|
|
// recupero la prima entità di questo percorso
|
|
int nEntId = m_pGeomDB->GetFirstInGroup( nClPathId) ;
|
|
// recupero i dati Cam dell'entità
|
|
CamData* pCamData = GetCamData( m_pGeomDB->GetUserObj( nEntId)) ;
|
|
if ( pCamData == nullptr)
|
|
return false ;
|
|
// recupero i valori degli assi
|
|
DBLVECTOR vAxCurr ;
|
|
vAxCurr = pCamData->GetAxesVal() ;
|
|
// se Z pressochè uguali non devo fare alcunché
|
|
if ( fabs( vAxCurr[2] - vAxPrev[2]) < 10 * EPS_SMALL)
|
|
return true ;
|
|
// se Z corrente maggiore della precedente
|
|
else if ( vAxCurr[2] > vAxPrev[2]) {
|
|
// copio l'entità
|
|
if ( m_pGeomDB->Copy( nEntId, GDB_ID_NULL, nEntId, GDB_AFTER) == GDB_ID_NULL)
|
|
return false ;
|
|
// modifico quella originale (è la prima del percorso)
|
|
DBLVECTOR vAxNew = vAxPrev ;
|
|
vAxNew[2] = vAxCurr[2] ;
|
|
pCamData->SetAxes( CamData::AS_OK, vAxNew) ;
|
|
pCamData->ChangeAxesMask( CamData::MSK_L3) ;
|
|
pCamData->SetFlag( 0) ;
|
|
}
|
|
// altrimenti Z corrente minore della precedente
|
|
else {
|
|
// copio l'entità
|
|
if ( m_pGeomDB->Copy( nEntId, GDB_ID_NULL, nEntId, GDB_AFTER) == GDB_ID_NULL)
|
|
return false ;
|
|
// modifico quella originale (è la prima del percorso)
|
|
DBLVECTOR vAxNew = vAxCurr ;
|
|
vAxNew[2] = vAxPrev[2] ;
|
|
pCamData->SetAxes( CamData::AS_OK, vAxNew) ;
|
|
pCamData->ChangeAxesMask( CamData::MSK_L1 | CamData::MSK_L2 | CamData::MSK_R1 | CamData::MSK_R2) ;
|
|
pCamData->SetFlag( 2) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::ToolChangeNeeded( const Operation& Op1, const Operation& Op2)
|
|
{
|
|
// se non cambia l'utensile, non cambia la testa fisica
|
|
if ( EqualNoCase( Op1.GetToolName(), Op2.GetToolName()))
|
|
return false ;
|
|
// se non hanno TcPos e stanno sulla stessa testa con uscita diversa, non cambia la testa fisica
|
|
if ( Op1.GetToolTcPos().empty() && Op2.GetToolTcPos().empty() &&
|
|
EqualNoCase( Op1.GetHeadName(), Op2.GetHeadName()) && Op1.GetExitNbr() != Op2.GetExitNbr())
|
|
return false ;
|
|
// se hanno lo stesso TcPos e stanno sulla stessa testa con uscita diversa, non cambia la testa fisica
|
|
if ( EqualNoCase( Op1.GetToolTcPos(), Op2.GetToolTcPos()) &&
|
|
EqualNoCase( Op1.GetHeadName(), Op2.GetHeadName()) && Op1.GetExitNbr() != Op2.GetExitNbr())
|
|
return false ;
|
|
// altrimenti necessario un cambio
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::AddRise( DBLVECTOR& vAxVal, double dDelta)
|
|
{
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return false ;
|
|
// recupero gruppo per geometria di lavorazione (Cutter Location)
|
|
int nClId = m_pGeomDB->GetFirstNameInGroup( GetOwner(), MCH_CL) ;
|
|
if ( nClId == GDB_ID_NULL)
|
|
return false ;
|
|
// recupero l'ultimo percorso
|
|
int nLastPxClId = m_pGeomDB->GetLastGroupInGroup( nClId) ;
|
|
// recupero l'ultima entità del percorso
|
|
int nEntId = m_pGeomDB->GetLastInGroup( nLastPxClId) ;
|
|
if ( nEntId == GDB_ID_NULL)
|
|
return false ;
|
|
// ne recupero i dati Cam
|
|
CamData* pCamData = GetCamData( m_pGeomDB->GetUserObj( nEntId)) ;
|
|
if ( pCamData == nullptr)
|
|
return false ;
|
|
// creo oggetto punto per DB geometrico
|
|
PtrOwner<IGeoPoint3d> pGP( CreateGeoPoint3d()) ;
|
|
if ( IsNull( pGP))
|
|
return false ;
|
|
// assegno le coordinate del punto
|
|
pGP->Set( pCamData->GetEndPoint()) ;
|
|
// inserisco l'oggetto nel DB geometrico
|
|
int nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLastPxClId, Release( pGP)) ;
|
|
if ( nId == GDB_ID_NULL)
|
|
return false ;
|
|
m_pGeomDB->SetName( nId, MCH_RISE) ;
|
|
// creo oggetto dati Cam
|
|
PtrOwner<CamData> pCam( pCamData->Clone()) ;
|
|
if ( IsNull( pCam))
|
|
return false ;
|
|
// recupero i valori degli assi
|
|
vAxVal = pCam->GetAxesVal() ;
|
|
if ( vAxVal.size() < 3)
|
|
return false ;
|
|
// flag per tipo di movimento in rapido
|
|
int nFlag = 0 ;
|
|
// se delta positivo lo uso come incremento di Z
|
|
if ( dDelta > 0) {
|
|
vAxVal[2] += dDelta ;
|
|
nFlag = 0 ; // movimento standard
|
|
}
|
|
// altrimenti uso la Z home
|
|
else {
|
|
DBLVECTOR vAxHome ;
|
|
m_pMchMgr->GetAllCalcAxesHomePos( vAxHome) ;
|
|
vAxVal[2] = vAxHome[2] ;
|
|
nFlag = 3 ; // movimento a Zmax
|
|
}
|
|
// verifico extra-corsa dell'asse Z
|
|
double dL1 = vAxVal[0] ;
|
|
double dL2 = vAxVal[1] ;
|
|
double dL3 = vAxVal[2] ;
|
|
double dR1 = ( vAxVal.size() >= 4 ? vAxVal[3] : 0) ;
|
|
double dR2 = ( vAxVal.size() >= 5 ? vAxVal[4] : 0) ;
|
|
int nStat ;
|
|
bool bOk = ( m_pMchMgr->VerifyOutstroke( dL1, dL2, dL3, dR1, dR2, nStat) && nStat == 0) ;
|
|
// assegno i dati
|
|
pCam->SetAxes( (bOk ? CamData::AS_OK : CamData::AS_OUTSTROKE), vAxVal) ;
|
|
pCam->SetMoveType( 0) ;
|
|
pCam->SetFeed( 0) ;
|
|
pCam->SetFlag( nFlag) ;
|
|
// associo questo oggetto a quello geometrico
|
|
m_pGeomDB->SetUserObj( nId, Release( pCam)) ;
|
|
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::RemoveRise( void)
|
|
{
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return false ;
|
|
// recupero gruppo per geometria di lavorazione (Cutter Location)
|
|
int nClId = m_pGeomDB->GetFirstNameInGroup( GetOwner(), MCH_CL) ;
|
|
if ( nClId == GDB_ID_NULL)
|
|
return false ;
|
|
// recupero l'ultimo percorso CL
|
|
int nClPathId = m_pGeomDB->GetLastGroupInGroup( nClId) ;
|
|
// elimino tutte le entità RISE alla fine del percorso
|
|
int nId = m_pGeomDB->GetFirstNameInGroup( nClPathId, MCH_RISE) ;
|
|
while ( nId != GDB_ID_NULL) {
|
|
m_pGeomDB->Erase( nId) ;
|
|
nId = m_pGeomDB->GetFirstNameInGroup( nClPathId, MCH_RISE) ;
|
|
}
|
|
// elimino a maggior ragione le entità HOME
|
|
nId = m_pGeomDB->GetFirstNameInGroup( nClPathId, MCH_HOME) ;
|
|
while ( nId != GDB_ID_NULL) {
|
|
m_pGeomDB->Erase( nId) ;
|
|
nId = m_pGeomDB->GetFirstNameInGroup( nClPathId, MCH_HOME) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::AddHome( void)
|
|
{
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return false ;
|
|
// recupero gruppo per geometria di lavorazione (Cutter Location)
|
|
int nClId = m_pGeomDB->GetFirstNameInGroup( GetOwner(), MCH_CL) ;
|
|
if ( nClId == GDB_ID_NULL)
|
|
return false ;
|
|
// recupero l'ultimo percorso
|
|
int nLastPxClId = m_pGeomDB->GetLastGroupInGroup( nClId) ;
|
|
// recupero l'ultima entità del percorso di nome RISE
|
|
int nEntId = m_pGeomDB->GetLastNameInGroup( nLastPxClId, MCH_RISE) ;
|
|
if ( nEntId == GDB_ID_NULL)
|
|
return false ;
|
|
// ne recupero i dati Cam
|
|
CamData* pCamData = GetCamData( m_pGeomDB->GetUserObj( nEntId)) ;
|
|
if ( pCamData == nullptr)
|
|
return false ;
|
|
// creo oggetto punto per DB geometrico
|
|
PtrOwner<IGeoPoint3d> pGP( CreateGeoPoint3d()) ;
|
|
if ( IsNull( pGP))
|
|
return false ;
|
|
// assegno le coordinate del punto
|
|
pGP->Set( pCamData->GetEndPoint()) ;
|
|
// inserisco l'oggetto nel DB geometrico
|
|
int nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLastPxClId, Release( pGP)) ;
|
|
if ( nId == GDB_ID_NULL)
|
|
return false ;
|
|
m_pGeomDB->SetName( nId, MCH_HOME) ;
|
|
// creo oggetto dati Cam
|
|
PtrOwner<CamData> pCam( pCamData->Clone()) ;
|
|
if ( IsNull( pCam))
|
|
return false ;
|
|
// flag per tipo di movimento in rapido (rapido a Home)
|
|
int nFlag = 4 ;
|
|
// recupero coordinate home
|
|
DBLVECTOR vAxHome ;
|
|
m_pMchMgr->GetAllCalcAxesHomePos( vAxHome) ;
|
|
// assegno i dati
|
|
pCam->SetAxes( CamData::AS_OK, vAxHome) ;
|
|
pCam->SetMoveType( 0) ;
|
|
pCam->SetFeed( 0) ;
|
|
pCam->SetFlag( nFlag) ;
|
|
// associo questo oggetto a quello geometrico
|
|
m_pGeomDB->SetUserObj( nId, Release( pCam)) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::RemoveHome( void)
|
|
{
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return false ;
|
|
// recupero gruppo per geometria di lavorazione (Cutter Location)
|
|
int nClId = m_pGeomDB->GetFirstNameInGroup( GetOwner(), MCH_CL) ;
|
|
if ( nClId == GDB_ID_NULL)
|
|
return false ;
|
|
// recupero l'ultimo percorso CL
|
|
int nClPathId = m_pGeomDB->GetLastGroupInGroup( nClId) ;
|
|
// elimino tutte le entità HOME alla fine del percorso
|
|
int nId = m_pGeomDB->GetFirstNameInGroup( nClPathId, MCH_HOME) ;
|
|
while ( nId != GDB_ID_NULL) {
|
|
m_pGeomDB->Erase( nId) ;
|
|
nId = m_pGeomDB->GetFirstNameInGroup( nClPathId, MCH_HOME) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::CalcDeltaZForHeadRotation( const DBLVECTOR& vAxStart, const DBLVECTOR& vAxEnd, double& dDeltaZ)
|
|
{
|
|
// il numero di assi deve essere costante
|
|
if ( vAxStart.size() != vAxEnd.size())
|
|
return false ;
|
|
// se ci sono solo assi lineari, non delta Z nullo
|
|
if ( vAxStart.size() <= 3) {
|
|
dDeltaZ = 0 ;
|
|
return true ;
|
|
}
|
|
// determino gli estremi del movimento rotatorio
|
|
double dR1Start = ( vAxStart.size() >= 4 ? vAxStart[3] : 0) ;
|
|
double dR2Start = ( vAxStart.size() >= 5 ? vAxStart[4] : 0) ;
|
|
double dR1End = ( vAxEnd.size() >= 4 ? vAxEnd[3] : 0) ;
|
|
double dR2End = ( vAxEnd.size() >= 5 ? vAxEnd[4] : 0) ;
|
|
// determino le variazioni di ciascun asse
|
|
double dR1Delta = dR1End - dR1Start ;
|
|
double dR2Delta = dR2End - dR2Start ;
|
|
// divido il movimento in step di massimo 15 gradi
|
|
int nStep = int( max( abs( dR1Delta), abs( dR2Delta)) / 15.0) + 1 ;
|
|
double dR1Step = dR1Delta / nStep ;
|
|
double dR2Step = dR2Delta / nStep ;
|
|
// calcolo
|
|
double dL1 = vAxStart[0] ;
|
|
double dL2 = vAxStart[1] ;
|
|
double dL3 = vAxStart[2] ;
|
|
double dZStart, dZmin ;
|
|
for ( int i = 0 ; i <= nStep ; ++ i) {
|
|
double dR1 = dR1Start + i * dR1Step ;
|
|
double dR2 = dR2Start + i * dR2Step ;
|
|
Point3d ptTip ;
|
|
if ( ! m_pMchMgr->GetCalcTipFromPositions( dL1, dL2, dL3, dR1, dR2, true, ptTip))
|
|
return false ;
|
|
if ( i == 0) {
|
|
dZStart = ptTip.z ;
|
|
dZmin = dZStart ;
|
|
}
|
|
else if ( ptTip.z < dZmin)
|
|
dZmin = ptTip.z ;
|
|
}
|
|
dDeltaZ = dZStart - dZmin ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::SetPathId( int nPathId)
|
|
{
|
|
m_nPathId = nPathId ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::SetToolDir( const Vector3d& vtDir)
|
|
{
|
|
m_vtTool = vtDir ;
|
|
return ( m_vtTool.Normalize()) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::SetCorrDir( const Vector3d& vtDir)
|
|
{
|
|
m_vtCorr = vtDir ;
|
|
return ( ! m_vtCorr.IsSmall()) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::SetAuxDir( const Vector3d& vtDir)
|
|
{
|
|
m_vtAux = vtDir ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::SetCorrAuxDir( const Vector3d& vtDir)
|
|
{
|
|
m_vtCorr = vtDir ;
|
|
m_vtAux = vtDir ;
|
|
return ( ! m_vtCorr.IsSmall()) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::SetFeed( double dFeed)
|
|
{
|
|
m_dFeed = dFeed ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::SetFlag( int nFlag)
|
|
{
|
|
m_nFlag = nFlag ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
Operation::AddRapidStart( const Point3d& ptP)
|
|
{
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return GDB_ID_NULL ;
|
|
// verifico di essere in uno stato valido per inizio
|
|
if ( m_vtTool.IsSmall())
|
|
return GDB_ID_NULL ;
|
|
// creo oggetto punto per DB geometrico
|
|
PtrOwner<IGeoPoint3d> pGP( CreateGeoPoint3d()) ;
|
|
if ( IsNull( pGP))
|
|
return GDB_ID_NULL ;
|
|
// assegno le coordinate del punto
|
|
pGP->Set( ptP) ;
|
|
// inserisco l'oggetto nel DB geometrico
|
|
int nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, m_nPathId, Release( pGP)) ;
|
|
if ( nId == GDB_ID_NULL)
|
|
return GDB_ID_NULL ;
|
|
// creo oggetto dati Cam
|
|
PtrOwner<CamData> pCam( new( nothrow) CamData) ;
|
|
if ( IsNull( pCam))
|
|
return GDB_ID_NULL ;
|
|
// assegno valori
|
|
pCam->SetMoveType( 0) ;
|
|
pCam->SetToolDir( m_vtTool) ;
|
|
pCam->SetCorrDir( m_vtCorr) ;
|
|
pCam->SetAuxDir( m_vtAux) ;
|
|
pCam->SetEndPoint( ptP) ;
|
|
pCam->SetFeed( 0) ;
|
|
pCam->SetFlag( m_nFlag) ;
|
|
// associo questo oggetto a quello geometrico
|
|
m_pGeomDB->SetUserObj( nId, Release( pCam)) ;
|
|
// salvo la posizione corrente
|
|
m_bCurr = true ;
|
|
m_ptCurr = ptP ;
|
|
return nId ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
Operation::AddRapidMove( const Point3d& ptP)
|
|
{
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return GDB_ID_NULL ;
|
|
// verifico di essere in uno stato valido per un movimento in rapido
|
|
if ( ! m_bCurr || m_vtTool.IsSmall())
|
|
return GDB_ID_NULL ;
|
|
// creo oggetto linea per DB geometrico
|
|
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ;
|
|
if ( IsNull( pLine))
|
|
return GDB_ID_NULL ;
|
|
// assegno le coordinate degli estremi
|
|
if ( ! pLine->Set( m_ptCurr, ptP))
|
|
return GDB_ID_NULL ;
|
|
// inserisco l'oggetto nel DB geometrico
|
|
int nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, m_nPathId, Release( pLine)) ;
|
|
if ( nId == GDB_ID_NULL)
|
|
return GDB_ID_NULL ;
|
|
// creo oggetto dati Cam
|
|
PtrOwner<CamData> pCam( new( nothrow) CamData) ;
|
|
if ( IsNull( pCam))
|
|
return GDB_ID_NULL ;
|
|
// assegno valori
|
|
pCam->SetMoveType( 0) ;
|
|
pCam->SetToolDir( m_vtTool) ;
|
|
pCam->SetCorrDir( m_vtCorr) ;
|
|
pCam->SetAuxDir( m_vtAux) ;
|
|
pCam->SetEndPoint( ptP) ;
|
|
pCam->SetFeed( 0) ;
|
|
pCam->SetFlag( m_nFlag) ;
|
|
// associo questo oggetto a quello geometrico
|
|
m_pGeomDB->SetUserObj( nId, Release( pCam)) ;
|
|
// salvo la posizione corrente
|
|
m_ptCurr = ptP ;
|
|
return nId ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
Operation::AddLinearMove( const Point3d& ptP)
|
|
{
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return GDB_ID_NULL ;
|
|
// verifico di essere in uno stato valido per un movimento lineare
|
|
if ( ! m_bCurr || m_vtTool.IsSmall()) {
|
|
LOG_INFO( GetEMkLogger(), "Error on LinearMove : Curr or ToolDir")
|
|
return GDB_ID_NULL ;
|
|
}
|
|
// se feed nulla, assegno il minimo e lo segnalo
|
|
if ( m_dFeed < FEED_MIN) {
|
|
m_dFeed = FEED_MIN ;
|
|
LOG_INFO( GetEMkLogger(), "Error on LinearMove : Min Feed")
|
|
}
|
|
// creo oggetto linea per DB geometrico
|
|
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ;
|
|
if ( IsNull( pLine))
|
|
return GDB_ID_NULL ;
|
|
// assegno le coordinate degli estremi
|
|
if ( ! pLine->Set( m_ptCurr, ptP))
|
|
return GDB_ID_NULL ;
|
|
// inserisco l'oggetto nel DB geometrico
|
|
int nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, m_nPathId, Release( pLine)) ;
|
|
if ( nId == GDB_ID_NULL)
|
|
return GDB_ID_NULL ;
|
|
// creo oggetto dati Cam
|
|
PtrOwner<CamData> pCam( new( nothrow) CamData) ;
|
|
if ( IsNull( pCam))
|
|
return GDB_ID_NULL ;
|
|
// assegno valori
|
|
pCam->SetMoveType( 1) ;
|
|
pCam->SetToolDir( m_vtTool) ;
|
|
pCam->SetCorrDir( m_vtCorr) ;
|
|
pCam->SetAuxDir( m_vtAux) ;
|
|
pCam->SetEndPoint( ptP) ;
|
|
pCam->SetFeed( m_dFeed) ;
|
|
pCam->SetFlag( m_nFlag) ;
|
|
// associo questo oggetto a quello geometrico
|
|
m_pGeomDB->SetUserObj( nId, Release( pCam)) ;
|
|
// salvo la posizione corrente
|
|
m_ptCurr = ptP ;
|
|
return nId ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
Operation::AddArcMove( const Point3d& ptP, const Point3d& ptCen, double dAngCen, double dDeltaZ)
|
|
{
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return GDB_ID_NULL ;
|
|
// verifico di essere in uno stato valido per un movimento arco
|
|
if ( ! m_bCurr || m_vtTool.IsSmall()) {
|
|
LOG_INFO( GetEMkLogger(), "Error on ArcMove : Curr or ToolDir")
|
|
return GDB_ID_NULL ;
|
|
}
|
|
// se feed nulla, assegno il minimo e lo segnalo
|
|
if ( m_dFeed < FEED_MIN) {
|
|
m_dFeed = FEED_MIN ;
|
|
LOG_INFO( GetEMkLogger(), "Error on ArcMove : Min Feed")
|
|
}
|
|
// creo oggetto arco per DB geometrico
|
|
PtrOwner<ICurveArc> pArc( CreateCurveArc()) ;
|
|
if ( IsNull( pArc))
|
|
return GDB_ID_NULL ;
|
|
// assegno i dati dell'arco
|
|
if ( ! pArc->SetCPA( ptCen, m_ptCurr, dAngCen, dDeltaZ))
|
|
return GDB_ID_NULL ;
|
|
Point3d ptFin ;
|
|
if ( ! pArc->GetEndPoint( ptFin) || ! AreSamePointApprox( ptFin, ptP))
|
|
return GDB_ID_NULL ;
|
|
int nMove = ( dAngCen > 0 ? 3 : 2) ;
|
|
// inserisco l'oggetto nel DB geometrico
|
|
int nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, m_nPathId, Release( pArc)) ;
|
|
if ( nId == GDB_ID_NULL)
|
|
return GDB_ID_NULL ;
|
|
// creo oggetto dati Cam
|
|
PtrOwner<CamData> pCam( new( nothrow) CamData) ;
|
|
if ( IsNull( pCam))
|
|
return GDB_ID_NULL ;
|
|
// assegno valori
|
|
pCam->SetMoveType( nMove) ;
|
|
pCam->SetToolDir( m_vtTool) ;
|
|
pCam->SetCorrDir( m_vtCorr) ;
|
|
pCam->SetAuxDir( m_vtAux) ;
|
|
pCam->SetEndPoint( ptP) ;
|
|
pCam->SetCenter( ptCen) ;
|
|
pCam->SetAngCen( dAngCen) ;
|
|
pCam->SetFeed( m_dFeed) ;
|
|
pCam->SetFlag( m_nFlag) ;
|
|
// associo questo oggetto a quello geometrico
|
|
m_pGeomDB->SetUserObj( nId, Release( pCam)) ;
|
|
// salvo la posizione corrente
|
|
m_ptCurr = ptP ;
|
|
return nId ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
Operation::ResetMoveData( void)
|
|
{
|
|
m_bCurr = false ;
|
|
m_ptCurr = ORIG ;
|
|
m_vtTool = V_NULL ;
|
|
m_vtCorr = V_NULL ;
|
|
m_vtAux = V_NULL ;
|
|
m_dFeed = 0 ;
|
|
m_nFlag = 0 ;
|
|
return true ;
|
|
}
|