Files
EgtMachKernel/Machining.cpp
T
Dario Sassi d20bc015d6 EgtMachKernel 1.6l11 :
- migliorie alla risalita in Z tra una lavorazione e l'altra.
2016-02-03 07:24:37 +00:00

969 lines
35 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2015-2015
//----------------------------------------------------------------------------
// File : Machining.cpp Data : 10.06.15 Versione : 1.6f2
// Contenuto : Implementazione gestione base lavorazioni.
//
//
//
// Modifiche : 10.06.15 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "DllMain.h"
#include "MachMgr.h"
#include "Machining.h"
#include "MachiningConst.h"
#include "CamData.h"
#include "/EgtDev/Include/EGkGeoPoint3d.h"
#include "/EgtDev/Include/EGkCurveLine.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
Machining::SetOwner( int nId, IGeomDB* pGDB)
{
m_nOwnerId = nId ;
m_pGeomDB = pGDB ;
return ( m_nOwnerId != GDB_ID_NULL && m_pGeomDB != nullptr) ;
}
//----------------------------------------------------------------------------
int
Machining::GetOwner( void) const
{
return m_nOwnerId ;
}
//----------------------------------------------------------------------------
IGeomDB*
Machining::GetGeomDB( void) const
{
return m_pGeomDB ;
}
//----------------------------------------------------------------------------
bool
Machining::Init( MachMgr* pMchMgr)
{
m_pMchMgr = pMchMgr ;
if ( m_pMchMgr == nullptr)
return false ;
if ( m_pMchMgr->GetGeomDB() != m_pGeomDB)
return false ;
return true ;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
Machining::Machining( void)
: m_nOwnerId( GDB_ID_NULL), m_pGeomDB( nullptr), m_pMchMgr( nullptr),
m_nPathId( GDB_ID_NULL), m_bCurr( false), m_ptCurr(),
m_vtTool(), m_vtCorr(), m_vtAux(), m_dFeed( 0), m_nFlag( 0)
{
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
bool
Machining::GetElevation( 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) {
// 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
Machining::GetElevation( 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) {
// 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
Machining::GetDistanceFromRawSide( 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) {
BBox3d b3Raw ;
int nRawSolidId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ;
if ( m_pGeomDB->GetGlobalBBox( nRawSolidId, b3Raw) && b3Pnt.OverlapsXY( b3Raw)) {
break ;
}
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( *Get( pRay), *pOut) ;
IntCrvCrvInfo aInfo ;
if ( intCC.GetIntCrvCrvInfo( 0, aInfo))
dDist = aInfo.IciA[0].dU * RAY_LEN ;
else
dDist = 0 ;
return true ;
}
//----------------------------------------------------------------------------
bool
Machining::GetDistanceFromRawBottom( 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) {
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 ;
}
nRawId = m_pMchMgr->GetNextRawPart( nRawId) ;
}
return true ;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
bool
Machining::SetPathId( int nPathId)
{
m_nPathId = nPathId ;
return true ;
}
//----------------------------------------------------------------------------
bool
Machining::SetToolDir( const Vector3d& vtDir)
{
m_vtTool = vtDir ;
return ( m_vtTool.Normalize()) ;
}
//----------------------------------------------------------------------------
bool
Machining::SetCorrDir( const Vector3d& vtDir)
{
m_vtCorr = vtDir ;
return ( ! m_vtCorr.IsSmall()) ;
}
//----------------------------------------------------------------------------
bool
Machining::SetAuxDir( const Vector3d& vtDir)
{
m_vtAux = vtDir ;
return true ;
}
//----------------------------------------------------------------------------
bool
Machining::SetFeed( double dFeed)
{
m_dFeed = dFeed ;
return true ;
}
//----------------------------------------------------------------------------
bool
Machining::SetFlag( int nFlag)
{
m_nFlag = nFlag ;
return true ;
}
//----------------------------------------------------------------------------
int
Machining::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->SetToolDir( m_vtTool) ;
pCam->SetCorrDir( m_vtCorr) ;
pCam->SetAuxDir( m_vtAux) ;
pCam->SetBasePoint( 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
Machining::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->SetToolDir( m_vtTool) ;
pCam->SetCorrDir( m_vtCorr) ;
pCam->SetAuxDir( m_vtAux) ;
pCam->SetBasePoint( 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
Machining::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->SetToolDir( m_vtTool) ;
pCam->SetCorrDir( m_vtCorr) ;
pCam->SetAuxDir( m_vtAux) ;
pCam->SetBasePoint( 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 ;
}
//----------------------------------------------------------------------------
bool
Machining::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 ;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
bool
Machining::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
Machining::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 = dynamic_cast<CamData*>( m_pGeomDB->GetUserObj( nEntId)) ;
if ( pCamData == nullptr)
return false ;
// assegno i valori degli assi
vAxVal = pCamData->GetAxisVal() ;
return ( vAxVal.size() > 0) ;
}
//----------------------------------------------------------------------------
bool
Machining::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
Machining::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 = dynamic_cast<CamData*>( m_pGeomDB->GetUserObj( nEntId)) ;
if ( pCamData == nullptr)
return false ;
// assegno i valori degli assi
vAxVal = pCamData->GetAxisVal() ;
return ( vAxVal.size() > 0) ;
}
//----------------------------------------------------------------------------
bool
Machining::CalculateAxesValues( void)
{
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
return false ;
// recupero la lavorazione precedente non vuota
int nPrevOpId = m_pMchMgr->GetPrevActiveOperation( m_nOwnerId) ;
Machining* pPrevMch = dynamic_cast<Machining*>( m_pGeomDB->GetUserObj( nPrevOpId)) ;
while ( pPrevMch != nullptr) {
if ( pPrevMch->IsNotEmpty())
break ;
else {
nPrevOpId = m_pMchMgr->GetPrevActiveOperation( nPrevOpId) ;
pPrevMch = dynamic_cast<Machining*>( m_pGeomDB->GetUserObj( nPrevOpId)) ;
}
}
// recupero l'utensile precedente
string sPrevTool ;
if ( pPrevMch != nullptr)
pPrevMch->GetParam( MPA_TOOL, sPrevTool) ;
// imposto l'utensile per i calcoli macchina
if ( ! m_pMchMgr->SetCalcTool( GetToolData().m_sName, GetToolData().m_sHead, GetToolData().m_nExit))
return false ;
// recupero il numero di assi lineari e rotanti attivi
int nLinAxes = m_pMchMgr->GetCurrLinAxes() ;
int nRotAxes = m_pMchMgr->GetCurrRotAxes() ;
// assegno gli angoli iniziali
double dAngAprec = 0 ;
double dAngBprec = 0 ;
DBLVECTOR vAxVal ;
// se utensile non cambiato, uso gli angoli finali della lavorazione precedente
if ( ! sPrevTool.empty() && GetToolData().m_sName == sPrevTool &&
pPrevMch->GetFinalAxesValues( vAxVal)) {
if ( nRotAxes >= 1)
dAngAprec = vAxVal[nLinAxes - 1 + 1] ;
if ( nRotAxes >= 2)
dAngBprec = vAxVal[nLinAxes - 1 + 2] ;
}
// altrimenti uso gli angoli home
else {
m_pMchMgr->GetAllCalcAxesHomePos( vAxVal) ;
if ( nRotAxes >= 1)
dAngAprec = vAxVal[nLinAxes - 1 + 1] ;
if ( nRotAxes >= 2)
dAngBprec = vAxVal[nLinAxes - 1 + 2] ;
}
// recupero peso primo asse rotante di testa
double dRot1W = m_pMchMgr->GetCalcRot1W() ;
// 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) {
if ( ! CalculateClPathAxesValues( nClPathId, nLinAxes, nRotAxes, dRot1W, dAngAprec, dAngBprec))
bOk = false ;
nClPathId = m_pGeomDB->GetNextGroup( nClPathId) ;
}
return bOk ;
}
//----------------------------------------------------------------------------
bool
Machining::CalculateClPathAxesValues( int nClPathId, int nLinAxes, int nRotAxes, double dRot1W,
double& dAngAprec, double& dAngBprec)
{
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) ;
// ciclo su tutte le entità del percorso CL
bool bOk = 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 = dynamic_cast<CamData*>( m_pGeomDB->GetUserObj( nEntId)) ;
if ( pCamData == nullptr)
continue ;
// calcolo degli assi rotanti della macchina
int nRStat ;
double dAngA1, dAngB1, dAngA2, dAngB2 ;
bool bROk = m_pMchMgr->GetCalcAngles( pCamData->GetToolDir(), pCamData->GetCorrDir(), nRStat, dAngA1, dAngB1, dAngA2, dAngB2) ;
if ( ! bROk || nRStat == 0) {
bOk = false ;
pCamData->SetAxes( CamData::AS_DIR_ERR, vAxVal) ;
continue ;
}
if ( nRStat == 1) {
// porto gli angoli ai valori più vicini ai precedenti con offset di uno o più giri
m_pMchMgr->GetNearestAngleInStroke( 1, dAngAprec, dAngA1) ;
m_pMchMgr->GetNearestAngleInStroke( 2, dAngBprec, dAngB1) ;
}
if ( nRStat == 2) {
// porto gli angoli ai valori più vicini ai precedenti con offset di uno o più giri
m_pMchMgr->GetNearestAngleInStroke( 1, dAngAprec, dAngA1) ;
m_pMchMgr->GetNearestAngleInStroke( 2, dAngBprec, dAngB1) ;
m_pMchMgr->GetNearestAngleInStroke( 1, dAngAprec, dAngA2) ;
m_pMchMgr->GetNearestAngleInStroke( 2, dAngBprec, dAngB2) ;
// scelgo la soluzione più vicina ai precedenti
double dDeltaA1 = dRot1W * fabs( dAngA1 - dAngAprec) ;
double dDeltaB1 = fabs( dAngB1 - dAngBprec) ;
double dDeltaA2 = dRot1W * fabs( dAngA2 - dAngAprec) ;
double dDeltaB2 = fabs( dAngB2 - dAngBprec) ;
if ( dDeltaA2 + dDeltaB2 < dDeltaA1 + dDeltaB1 - 1.) {
dAngA1 = dAngA2 ;
dAngB1 = dAngB2 ;
}
}
// ricavo posizione con eventuali modifiche dipendenti dalla lavorazione
Point3d ptP = pCamData->GetBasePoint() ;
AdjustPositionForAxesCalc( pCamData, ptP) ;
// calcolo gli assi lineari della macchina
int nLStat ;
double dX, dY, dZ ;
bool bLOk = m_pMchMgr->GetCalcPositions( ptP, dAngA1, dAngB1, 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) ;
vAxVal.emplace_back( dAngA1) ;
vAxVal.emplace_back( dAngB1) ;
// verifico i limiti di corsa degli assi
int nStat ;
bool bOsOk = m_pMchMgr->VerifyOutstroke( dX, dY, dZ, dAngA1, dAngB1, 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 ;
}
// salvo i valori degli assi
pCamData->SetAxes( CamData::AS_OK, vAxVal) ;
// memorizzo i valori degli angoli come nuovi precedenti
dAngAprec = dAngA1 ;
dAngBprec = dAngB1 ;
}
return bOk ;
}
//----------------------------------------------------------------------------
bool
Machining::AdjustStartMovements(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) ;
Machining* pPrevMch = dynamic_cast<Machining*>( m_pGeomDB->GetUserObj( nPrevOpId)) ;
while ( pPrevMch != nullptr) {
if ( pPrevMch->IsNotEmpty())
break ;
else {
nPrevOpId = m_pMchMgr->GetPrevActiveOperation( nPrevOpId) ;
pPrevMch = dynamic_cast<Machining*>( m_pGeomDB->GetUserObj( nPrevOpId)) ;
}
}
// recupero l'utensile precedente e i dati della sua testa
string sPrevTool ;
if ( pPrevMch != nullptr)
pPrevMch->GetParam( MPA_TOOL, sPrevTool) ;
// imposto l'utensile per i calcoli macchina
if ( ! m_pMchMgr->SetCalcTool( GetToolData().m_sName, GetToolData().m_sHead, GetToolData().m_nExit))
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( pPrevMch->GetToolData(), GetToolData())) {
pPrevMch->RemoveRise() ;
DBLVECTOR vAxIni ;
if ( ! pPrevMch->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 ( ! pPrevMch->AddRise( vAxVal, dDelta))
return false ;
}
}
}
// altrimenti aggiungo uscita per cambio utensile alla lavorazione precedente e parto da questa
else {
pPrevMch->RemoveRise() ;
if ( ! pPrevMch->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
AddRise( vAxVal) ;
return bOk ;
}
//----------------------------------------------------------------------------
bool
Machining::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 = dynamic_cast<CamData*>( m_pGeomDB->GetUserObj( nEntId)) ;
if ( pCamData == nullptr)
return false ;
// recupero i valori degli assi
DBLVECTOR vAxCurr ;
vAxCurr = pCamData->GetAxisVal() ;
// 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
Machining::ToolChangeNeeded( const ToolData& T1, const ToolData& T2)
{
// se non cambia l'utensile, non cambia la testa fisica
if ( EqualNoCase( T1.m_sName, T2.m_sName))
return false ;
// se non hanno TcPos e stanno sulla stessa testa con uscita diversa, non cambia la testa fisica
if ( T1.m_sTcPos.empty() && T2.m_sTcPos.empty() &&
EqualNoCase( T1.m_sHead, T2.m_sHead) && T1.m_nExit != T2.m_nExit)
return false ;
// se hanno lo stesso TcPos e stanno sulla stessa testa con uscita diversa, non cambia la testa fisica
if ( EqualNoCase( T1.m_sTcPos, T2.m_sTcPos) &&
EqualNoCase( T1.m_sHead, T2.m_sHead) && T1.m_nExit != T2.m_nExit)
return false ;
// altrimenti necessario un cambio
return true ;
}
//----------------------------------------------------------------------------
bool
Machining::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 = dynamic_cast<CamData*>( 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->GetBasePoint()) ;
// 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->GetAxisVal() ;
// flag 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->SetFeed( 0) ;
pCam->SetFlag( nFlag) ;
// associo questo oggetto a quello geometrico
m_pGeomDB->SetUserObj( nId, Release( pCam)) ;
return bOk ;
}
//----------------------------------------------------------------------------
bool
Machining::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) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
Machining::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 ;
}