Files
EgtMachKernel/Sawing.cpp
T
Dario Sassi 8dd67afcb7 EgtMachKernel 1.6k8 :
- modifiche per tagli di lama inclinati.
2015-11-20 13:41:10 +00:00

1044 lines
34 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2015-2015
//----------------------------------------------------------------------------
// File : Sawing.cpp Data : 24.10.15 Versione : 1.6j3
// Contenuto : Implementazione gestione tagli con lama.
//
// Note : Questa lavorazione è sempre espressa nel riferimento globale.
//
// Modifiche : 07.06.15 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "MachMgr.h"
#include "DllMain.h"
#include "Sawing.h"
#include "MachiningConst.h"
#include "CamData.h"
#include "/EgtDev/Include/EXeExecutor.h"
#include "/EgtDev/Include/EGkCurveLine.h"
#include "/EgtDev/Include/EGkCurveComposite.h"
#include "/EgtDev/Include/EgkChainCurves.h"
#include "/EgtDev/Include/EGkUserObjFactory.h"
#include "/EgtDev/Include/EGnStringKeyVal.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
// per far dimenticare macro di WinUser.h
#undef GetClassName
using namespace std ;
//----------------------------------------------------------------------------
USEROBJ_REGISTER( "EMkSawing", Sawing) ;
//----------------------------------------------------------------------------
const string&
Sawing::GetClassName( void) const
{
return USEROBJ_GETNAME( Sawing) ;
}
//----------------------------------------------------------------------------
Sawing*
Sawing::Clone( void) const
{
// alloco oggetto
Sawing* pSaw = new(nothrow) Sawing ;
// eseguo copia dei dati
if ( pSaw != nullptr) {
try {
pSaw->m_nOwnerId = GDB_ID_NULL ;
pSaw->m_pGeomDB = nullptr ;
pSaw->m_Params = m_Params ;
pSaw->m_TParams = m_TParams ;
}
catch( ...) {
delete pSaw ;
return nullptr ;
}
}
// ritorno l'oggetto
return pSaw ;
}
//----------------------------------------------------------------------------
bool
Sawing::Dump( string& sOut, bool bMM, const char* szNewLine) const
{
sOut += GetClassName() + "[mm]" + szNewLine ;
sOut += KEY_IDS + EQUAL + ToString( m_vId) + szNewLine ;
for ( int i = 0 ; i < m_Params.GetSize() ; ++ i)
sOut += m_Params.ToString( i) + szNewLine ;
for ( int i = 0 ; i < m_TParams.GetSize() ; ++ i)
sOut += m_TParams.ToString( i) + szNewLine ;
return true ;
}
//----------------------------------------------------------------------------
bool
Sawing::Save( STRVECTOR& vString) const
{
try {
int nSize = 1 + m_Params.GetSize() + m_TParams.GetSize() ;
vString.insert( vString.begin(), nSize, "") ;
int k = - 1 ;
if ( ! SetVal( KEY_IDS, m_vId, vString[++k]))
return false ;
for ( int i = 0 ; i < m_Params.GetSize() ; ++ i)
vString[++k] = m_Params.ToString( i) ;
for ( int i = 0 ; i < m_TParams.GetSize() ; ++ i)
vString[++k] = m_TParams.ToString( i) ;
}
catch( ...) {
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
Sawing::Load( const STRVECTOR& vString)
{
int nSize = 1 + m_Params.GetSize() + m_TParams.GetSize() ;
if ( int( vString.size()) < nSize)
return false ;
int k = - 1 ;
if ( ! GetVal( vString[++k], KEY_IDS, m_vId))
return false ;
for ( int i = 0 ; i < m_Params.GetSize() ; ++ i) {
int nKey ;
if ( ! m_Params.FromString( vString[++k], nKey) || nKey != i)
return false ;
}
for ( int i = 0 ; i < m_TParams.GetSize() ; ++ i) {
int nKey ;
if ( ! m_TParams.FromString( vString[++k], nKey) || nKey != i)
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
Sawing::Sawing( void)
{
m_nOwnerId = GDB_ID_NULL ;
m_pGeomDB = nullptr ;
m_Params.m_sName = "*" ;
m_Params.m_sToolName = "*" ;
m_TParams.m_sName = "*" ;
m_TParams.m_sHead = "*" ;
}
//----------------------------------------------------------------------------
bool
Sawing::Prepare( const string& sSawName)
{
// verifico il gestore lavorazioni
if ( m_pMchMgr == nullptr)
return false ;
// recupero il gestore DB utensili della macchina corrente
ToolsMgr* pTMgr = m_pMchMgr->GetCurrToolsMgr() ;
if ( pTMgr == nullptr)
return false ;
// recupero il gestore DB lavorazioni della macchina corrente
MachiningsMgr* pMMgr = m_pMchMgr->GetCurrMachiningsMgr() ;
if ( pMMgr == nullptr)
return false ;
// ricerca della lavorazione di libreria con il nome indicato
const SawingData* pDdata = GetSawingData( pMMgr->GetMachining( sSawName)) ;
if ( pDdata == nullptr)
return false ;
m_Params = *pDdata ;
// ricerca dell'utensile usato dalla lavorazione
const ToolData* pTdata = pTMgr->GetTool( m_Params.m_ToolUuid) ;
if ( pTdata == nullptr)
return false ;
m_TParams = *pTdata ;
m_Params.m_sToolName = m_TParams.m_sName ;
return true ;
}
//----------------------------------------------------------------------------
bool
Sawing::SetParam( int nType, bool bVal)
{
switch ( nType) {
case MPA_INVERT :
m_Params.m_bInvert = bVal ;
return true ;
case MPA_TOANDFROM :
m_Params.m_bToAndFrom = bVal ;
return true ;
}
return false ;
}
//----------------------------------------------------------------------------
bool
Sawing::SetParam( int nType, int nVal)
{
switch ( nType) {
case MPA_WORKSIDE :
if ( ! m_Params.VerifyWorkSide( nVal))
return false ;
m_Params.m_nWorkSide = nVal ;
return true ;
case MPA_HEADSIDE :
if ( ! m_Params.VerifyHeadSide( nVal))
return false ;
m_Params.m_nHeadSide = nVal ;
return true ;
case MPA_LEADINTYPE :
if ( ! m_Params.VerifyLeadInType( nVal))
return false ;
m_Params.m_nLeadInType = nVal ;
return true ;
case MPA_EXTLINKTYPE :
if ( ! m_Params.VerifyExtLinkType( nVal))
return false ;
m_Params.m_nExtLinkType = nVal ;
return true ;
case MPA_LEADOUTTYPE :
if ( ! m_Params.VerifyLeadOutType( nVal))
return false ;
m_Params.m_nLeadOutType = nVal ;
return true ;
case MPA_CURVEUSE :
if ( ! m_Params.VerifyCurveUse( nVal))
return false ;
m_Params.m_nCurveUse = nVal ;
return true ;
}
return false ;
}
//----------------------------------------------------------------------------
bool
Sawing::SetParam( int nType, double dVal)
{
switch ( nType) {
case MPA_TOOLSPEED :
if ( ! m_TParams.VerifySpeed( dVal))
return false ;
m_TParams.m_dSpeed = dVal ;
return true ;
case MPA_TOOLFEED :
m_TParams.m_dFeed = dVal ;
return true ;
case MPA_TOOLSTARTFEED :
m_TParams.m_dStartFeed = dVal ;
return true ;
case MPA_TOOLENDFEED :
m_TParams.m_dEndFeed = dVal ;
return true ;
case MPA_TOOLTIPFEED :
m_TParams.m_dTipFeed = dVal ;
return true ;
case MPA_TOOLOFFSR :
m_TParams.m_dOffsR = dVal ;
return true ;
case MPA_TOOLOFFSL :
m_TParams.m_dOffsL = dVal ;
return true ;
case MPA_DEPTH :
m_Params.m_sDepth = ToString( dVal) ;
return true ;
case MPA_SIDEANGLE :
if ( ! m_Params.VerifySideAngle( dVal))
return false ;
m_Params.m_dSideAngle = dVal ;
return true ;
case MPA_APPROX :
m_Params.m_dApprox = dVal ;
return true ;
}
return false ;
}
//----------------------------------------------------------------------------
bool
Sawing::SetParam( int nType, const string& sVal)
{
switch ( nType) {
case MPA_TOOL : {
const ToolData* pTdata ;
if ( ! m_Params.VerifyTool( m_pMchMgr->GetCurrToolsMgr(), sVal, pTdata))
return false ;
m_Params.m_sToolName = sVal ;
m_Params.m_ToolUuid = pTdata->m_Uuid ;
m_TParams = *pTdata ;
} return true ;
case MPA_DEPTH_STR :
m_Params.m_sDepth = sVal ;
return true ;
}
return false ;
}
//----------------------------------------------------------------------------
bool
Sawing::SetGeometry( const SELVECTOR& vIds)
{
// verifico validità gestore DB geometrico
if ( m_pGeomDB == nullptr)
return false ;
// reset della geometria corrente
m_vId.clear() ;
// verifico che gli identificativi rappresentino delle entità ammissibili
for ( const auto& Id : vIds) {
// test sull'entità
int nSubs ;
if ( ! VerifyGeometry( Id, nSubs)) {
string sOut = "Entity " + ToString( Id) + " skipped by Sawing" ;
LOG_INFO( GetEMkLogger(), sOut.c_str()) ;
continue ;
}
// posso aggiungere alla lista
if ( nSubs == 0)
m_vId.emplace_back( Id) ;
else {
for ( int i = 0 ; i < nSubs ; ++ i)
m_vId.emplace_back( Id.nId, i) ;
}
}
return ( ! m_vId.empty()) ;
}
//----------------------------------------------------------------------------
bool
Sawing::Apply( void)
{
// verifico validità gestore DB geometrico e Id del gruppo
if ( m_pGeomDB == nullptr || ! m_pGeomDB->ExistsObj( m_nOwnerId))
return false ;
// recupero gruppo per geometria ausiliaria
int nAuxId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_AUX) ;
// se non c'è, lo aggiungo
if ( nAuxId == GDB_ID_NULL) {
nAuxId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ;
if ( nAuxId == GDB_ID_NULL)
return false ;
m_pGeomDB->SetName( nAuxId, MCH_AUX) ;
}
// altrimenti lo svuoto
else
m_pGeomDB->EmptyGroup( nAuxId) ;
// verifiche per angolo di sbandamento
if ( ! VerifySideAngle())
return false ;
// eseguo concatenamento, inserisco i percorsi sotto la geometria ausiliaria
if ( ! Chain( nAuxId))
return false ;
// recupero gruppo per geometria di lavorazione (Cutter Location)
int nClId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_CL) ;
// se non c'è, lo aggiungo
if ( nClId == GDB_ID_NULL) {
nClId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ;
if ( nClId == GDB_ID_NULL)
return false ;
m_pGeomDB->SetName( nClId, MCH_CL) ;
}
// altrimenti lo svuoto
else
m_pGeomDB->EmptyGroup( nClId) ;
// lavoro ogni singola catena
int nPathId = m_pGeomDB->GetFirstGroupInGroup( nAuxId) ;
while ( nPathId != GDB_ID_NULL) {
PathApply( nPathId, nClId) ;
nPathId = m_pGeomDB->GetNextGroup( nPathId) ;
}
// calcolo gli assi macchina
return CalculateAxesValues() ;
}
//----------------------------------------------------------------------------
bool
Sawing::GetParam( int nType, bool& bVal) const
{
switch ( nType) {
case MPA_INVERT :
bVal = m_Params.m_bInvert ;
return true ;
case MPA_TOANDFROM :
bVal = m_Params.m_bToAndFrom ;
return true ;
}
return false ;
}
//----------------------------------------------------------------------------
bool
Sawing::GetParam( int nType, int& nVal) const
{
switch ( nType) {
case MPA_WORKSIDE :
nVal = m_Params.m_nWorkSide ;
return true ;
case MPA_HEADSIDE :
nVal = m_Params.m_nHeadSide ;
return true ;
case MPA_LEADINTYPE :
nVal = m_Params.m_nLeadInType ;
return true ;
case MPA_EXTLINKTYPE :
nVal = m_Params.m_nExtLinkType ;
return true ;
case MPA_LEADOUTTYPE :
nVal = m_Params.m_nLeadOutType ;
return true ;
case MPA_CURVEUSE :
nVal = m_Params.m_nCurveUse ;
return true ;
}
return false ;
}
//----------------------------------------------------------------------------
bool
Sawing::GetParam( int nType, double& dVal) const
{
switch ( nType) {
case MPA_TOOLSPEED :
dVal = m_TParams.m_dSpeed ;
return true ;
case MPA_TOOLFEED :
dVal = m_TParams.m_dFeed ;
return true ;
case MPA_TOOLSTARTFEED :
dVal = m_TParams.m_dStartFeed ;
return true ;
case MPA_TOOLENDFEED :
dVal = m_TParams.m_dEndFeed ;
return true ;
case MPA_TOOLTIPFEED :
dVal = m_TParams.m_dTipFeed ;
return true ;
case MPA_TOOLOFFSR :
dVal = m_TParams.m_dOffsR ;
return true ;
case MPA_TOOLOFFSL :
dVal = m_TParams.m_dOffsL ;
return true ;
case MPA_SIDEANGLE :
dVal = m_Params.m_dSideAngle ;
return true ;
case MPA_APPROX :
dVal = m_Params.m_dApprox ;
return true ;
}
return false ;
}
//----------------------------------------------------------------------------
bool
Sawing::GetParam( int nType, string& sVal) const
{
switch ( nType) {
case MPA_NAME :
sVal = m_Params.m_sName ;
return true ;
case MPA_TOOL :
sVal = m_Params.m_sToolName ;
return true ;
case MPA_DEPTH_STR :
sVal = m_Params.m_sDepth ;
return true ;
case MPA_TUUID :
sVal = ToString( m_Params.m_ToolUuid) ;
return true ;
case MPA_UUID :
sVal = ToString( m_Params.m_Uuid) ;
return true ;
}
return false ;
}
//----------------------------------------------------------------------------
const ToolData&
Sawing::GetToolData( void) const
{
return m_TParams ;
}
//----------------------------------------------------------------------------
bool
Sawing::VerifyGeometry( SelData Id, int& nSubs)
{
// ammessi : curve o facce di polymesh
// per ora accetto solo curve
const ICurve* pCurve = nullptr ;
const IGeoObj* pGObj = m_pGeomDB->GetGeoObj( Id.nId) ;
// se direttamente la curva
if ( Id.nSub == SEL_SUB_ALL) {
pCurve = ::GetCurve( m_pGeomDB->GetGeoObj( Id.nId)) ;
if ( pCurve != nullptr) {
if ( pCurve->GetType() == CRV_COMPO)
nSubs = ::GetCurveComposite( pCurve)->GetCurveCount() ;
else
nSubs = 0 ;
}
}
// altrimenti sottocurva di composita
else {
const ICurveComposite* pCompo = GetCurveComposite( m_pGeomDB->GetGeoObj( Id.nId)) ;
if ( pCompo != nullptr)
pCurve = pCompo->GetCurve( Id.nSub) ;
nSubs = 0 ;
}
return ( pCurve != nullptr) ;
}
//----------------------------------------------------------------------------
ICurve*
Sawing::GetCurve( SelData Id)
{
// ammessi : curve o facce di polymesh
// nel caso di facce si deve recuperare la linea di base
// per ora accetto solo curve
PtrOwner<ICurve> pCurve ;
// se direttamente curva
if ( Id.nSub == SEL_SUB_ALL) {
// recupero e duplico la curva
const ICurve* pOriCurve = ::GetCurve( m_pGeomDB->GetGeoObj( Id.nId)) ;
if ( pOriCurve != nullptr)
pCurve.Set( pOriCurve->Clone()) ;
}
// altrimenti sottocurva di composita
else {
// recupero la composita
const ICurveComposite* pCompo = GetCurveComposite( m_pGeomDB->GetGeoObj( Id.nId)) ;
if ( pCompo != nullptr) {
// duplico la curva semplice
const ICurve* pOriCurve = ::GetCurve( pCompo->GetCurve( Id.nSub)) ;
if ( pOriCurve != nullptr) {
pCurve.Set( pOriCurve->Clone()) ;
// recupero estrusione e spessore
Vector3d vtExtr ;
if ( pCompo->GetExtrusion( vtExtr))
pCurve->SetExtrusion( vtExtr) ;
double dThick ;
if ( pCompo->GetThickness( dThick))
pCurve->SetThickness( dThick) ;
}
}
}
if ( IsNull( pCurve))
return nullptr ;
// ne recupero il riferimento globale
Frame3d frGlob ;
if ( ! m_pGeomDB->GetGlobFrame( Id.nId, frGlob))
return nullptr ;
// la porto in globale
pCurve->ToGlob( frGlob) ;
// la restituisco
return Release( pCurve) ;
}
//----------------------------------------------------------------------------
bool
Sawing::VerifySideAngle( void)
{
// verifiche per angolo di sbandamento
if ( fabs( m_Params.m_dSideAngle) > EPS_ANG_SMALL) {
// non ammesso lato di lavoro in centro
if ( m_Params.m_nWorkSide == SAW_WS_CENTER) {
LOG_INFO( GetEMkLogger(), "Center work not allowed with side angle") ;
return false ;
}
// se angolo esterno lato mandrino deve uguagliare lato di lavoro
if ( m_Params.m_dSideAngle > 0) {
if ( m_Params.m_nWorkSide == SAW_WS_RIGHT) {
if ( m_Params.m_nHeadSide == SAW_HS_LEFT) {
LOG_INFO( GetEMkLogger(), "External side angle HeadSide must equal WorkSide") ;
m_Params.m_nHeadSide = SAW_HS_RIGHT ;
}
}
if ( m_Params.m_nWorkSide == SAW_WS_LEFT) {
if ( m_Params.m_nHeadSide == SAW_HS_RIGHT) {
LOG_INFO( GetEMkLogger(), "External side angle HeadSide must equal WorkSide") ;
m_Params.m_nHeadSide = SAW_HS_LEFT ;
}
}
}
// altrimenti angolo interno, lato mandrino deve essere opposto a lato di lavoro
else {
if ( m_Params.m_nWorkSide == SAW_WS_RIGHT) {
if ( m_Params.m_nHeadSide == SAW_HS_RIGHT) {
LOG_INFO( GetEMkLogger(), "Internal side angle HeadSide must opposite WorkSide") ;
m_Params.m_nHeadSide = SAW_HS_LEFT ;
}
}
if ( m_Params.m_nWorkSide == SAW_WS_LEFT) {
if ( m_Params.m_nHeadSide == SAW_HS_LEFT) {
LOG_INFO( GetEMkLogger(), "Internal side angle HeadSide must opposite WorkSide") ;
m_Params.m_nHeadSide = SAW_HS_RIGHT ;
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
Sawing::Chain( int nGrpDestId)
{
// vettore puntatori alle curve
typedef PtrOwner<ICurve> POWNCURVE ;
typedef std::vector<POWNCURVE> POCRVVECTOR ;
POCRVVECTOR vpCrvs ;
vpCrvs.reserve( m_vId.size()) ;
// recupero tutte le curve e le porto in globale
for ( const auto& Id : m_vId) {
// prendo curva
vpCrvs.emplace_back( GetCurve( Id)) ;
// ne verifico la validità
if ( IsNull( vpCrvs.back())) {
string sOut = "Entity " + ToString( Id) + " skipped by Sawing" ;
LOG_INFO( GetEMkLogger(), sOut.c_str()) ;
vpCrvs.back().Reset() ;
}
}
// preparo i dati per il concatenamento
double dToler = 10 * EPS_SMALL ;
ChainCurves chainC ;
chainC.Init( true, dToler, int( vpCrvs.size())) ;
for ( size_t i = 0 ; i < vpCrvs.size() ; ++ i) {
// recupero la curva e il suo riferimento
ICurve* pCrv = Get( vpCrvs[i]) ;
if ( pCrv == nullptr)
continue ;
// recupero i dati della curva necessari al concatenamento e li assegno
Point3d ptStart, ptEnd ;
Vector3d vtStart, vtEnd ;
if ( ! pCrv->GetStartPoint( ptStart) || ! pCrv->GetStartDir( vtStart) ||
! pCrv->GetEndPoint( ptEnd) || ! pCrv->GetEndDir( vtEnd))
return false ;
if ( ! chainC.AddCurve( int( i + 1), ptStart, vtStart, ptEnd, vtEnd))
return false ;
}
// recupero i percorsi concatenati
int nCount = 0 ;
Point3d ptNear = ORIG ;
INTVECTOR vnId2 ;
while ( chainC.GetChainFromNear( ptNear, false, vnId2)) {
// creo una curva composita
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
if ( IsNull( pCrvCompo))
return false ;
// estrusione e spessore
Vector3d vtExtr = Z_AX ;
double dThick = 0 ;
// vettore Id originali
SELVECTOR vId2 ;
vId2.reserve( vnId2.size()) ;
// recupero le curve semplici e le inserisco nella curva composita
for ( size_t i = 0 ; i < vnId2.size() ; ++ i) {
int nId = abs( vnId2[i]) - 1 ;
bool bInvert = ( vnId2[i] < 0) ;
vId2.emplace_back( m_vId[nId]) ;
// recupero la curva
ICurve* pCrv = Get( vpCrvs[nId]) ;
// se necessario, la inverto
if ( bInvert)
pCrv->Invert() ;
// recupero eventuali estrusione e spessore
Vector3d vtTemp ;
if ( pCrv->GetExtrusion( vtTemp)) {
vtExtr = vtTemp ;
double dTemp ;
if ( pCrv->GetThickness( dTemp) && fabs( dTemp) > fabs( dThick))
dThick = dTemp ;
}
// la aggiungo alla curva composta
if ( ! pCrvCompo->AddCurve( ::Release( vpCrvs[nId]), true, dToler))
return false ;
}
// se non sono state inserite curve, vado oltre
if ( pCrvCompo->GetCurveCount() == 0)
continue ;
// imposto estrusione e spessore
pCrvCompo->SetExtrusion( vtExtr) ;
pCrvCompo->SetThickness( dThick) ;
// aggiorno il nuovo punto vicino
pCrvCompo->GetEndPoint( ptNear) ;
// creo nuovo gruppo
int nPathId = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrpDestId, Frame3d()) ;
if ( nPathId == GDB_ID_NULL)
return false ;
m_pGeomDB->SetName( nPathId, MCH_PATH + ToString( ++ nCount)) ;
m_pGeomDB->SetInfo( nPathId, KEY_IDS, ToString( vId2)) ;
// inserisco la curva composita nel gruppo destinazione
int nNewId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPathId, ::Release( pCrvCompo)) ;
if ( nNewId == GDB_ID_NULL)
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
Sawing::PathApply( int nPathId, int nClId)
{
// recupero gruppo per geometria temporanea
const string GRP_TEMP = "Temp" ;
int nTempId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, GRP_TEMP) ;
// se non c'è, lo aggiungo
if ( nTempId == GDB_ID_NULL) {
nTempId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ;
if ( nTempId == GDB_ID_NULL)
return false ;
m_pGeomDB->SetName( nTempId, GRP_TEMP) ;
}
// altrimenti lo svuoto
else
m_pGeomDB->EmptyGroup( nTempId) ;
// in ogni caso lo dichiaro temporaneo e non visibile
m_pGeomDB->SetLevel( nTempId, GDB_LV_TEMP) ;
m_pGeomDB->SetStatus( nTempId, GDB_ST_OFF) ;
// copio la curva composita da elaborare
int nCrvId = m_pGeomDB->GetFirstInGroup( nPathId) ;
if ( m_pGeomDB->GetGeoType( nCrvId) != CRV_COMPO)
return false ;
int nCopyId = m_pGeomDB->CopyGlob( nCrvId, GDB_ID_NULL, nTempId) ;
if ( nCopyId == GDB_ID_NULL)
return false ;
ICurveComposite* pCompo = GetCurveComposite( m_pGeomDB->GetGeoObj( nCopyId)) ;
// elaboro la curva composita e la esplodo nelle curve componenti
if ( m_Params.m_nCurveUse == SAW_CRV_APPROX ||
m_Params.m_nCurveUse == SAW_CRV_CONVEX) {
// calcolo l'approssimazione lineare con eventuale convessità
PolyLine PL ;
int nType = ICurve::APL_STD ;
if ( m_Params.m_nWorkSide == SAW_WS_LEFT)
nType = (( m_Params.m_nCurveUse == SAW_CRV_APPROX) ? ICurve::APL_LEFT : ICurve::APL_LEFT_CONVEX) ;
else if ( m_Params.m_nWorkSide == SAW_WS_RIGHT)
nType = (( m_Params.m_nCurveUse == SAW_CRV_APPROX) ? ICurve::APL_RIGHT : ICurve::APL_RIGHT_CONVEX) ;
if ( ! pCompo->ApproxWithLines( m_Params.m_dApprox, ANG_RIGHT, nType, PL))
return false ;
// salvo estrusione e spessore
Vector3d vtExtr ;
pCompo->GetExtrusion( vtExtr) ;
double dThick ;
pCompo->GetThickness( dThick) ;
// sostituisco la curva composita con la sua approssimazione
if ( ! pCompo->Clear() || ! pCompo->FromPolyLine( PL))
return false ;
// assegno estrusione e spessore originali
pCompo->SetExtrusion( vtExtr) ;
pCompo->SetThickness( dThick) ;
}
// se lama non centrata e richiesto, eseguo offset
if ( m_Params.m_nWorkSide != SAW_WS_CENTER && fabs( m_TParams.m_dOffsL) > EPS_SMALL) {
double dOffs = ( m_Params.m_nWorkSide == SAW_WS_RIGHT) ? m_TParams.m_dOffsL : - m_TParams.m_dOffsL ;
if ( ! pCompo->SimpleOffset( dOffs, ICurve::OFF_EXTEND))
return false ;
}
// unisco le parti allineate
if ( ! pCompo->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL))
return false ;
// eventuale inversione percorso
if ( m_Params.m_bInvert)
pCompo->Invert() ;
// recupero estrusione e spessore
Vector3d vtExtr ;
pCompo->GetExtrusion( vtExtr) ;
double dThick ;
pCompo->GetThickness( dThick) ;
// valuto l'espressione dell'affondamento
string sExec = "TH=" + (( dThick * vtExtr.z < 0) ? ToString( fabs( dThick)) : ToString( 0)) ;
ExeLuaExecLine( sExec) ;
double dDepth ;
if ( ! ExeLuaEvalNumExpr( m_Params.m_sDepth, &dDepth)) {
string sOut = "Depth not computable by Sawing" ;
LOG_INFO( GetEMkLogger(), sOut.c_str()) ;
return false ;
}
// correzione per angolo di fianco
if ( fabs( m_Params.m_dSideAngle) > EPS_ANG_SMALL) {
// generale
dDepth /= cos( m_Params.m_dSideAngle * DEGTORAD) ;
// se sottosquadra (controllo il lato opposto della lama, quindi ...)
if ( m_Params.m_dSideAngle < 0)
dDepth += m_TParams.m_dThick * tan( abs( m_Params.m_dSideAngle) * DEGTORAD) ;
}
// verifico di non superare il massimo materiale
if ( dDepth > m_TParams.m_dMaxMat) {
string sOut = "Depth bigger than MaxMaterial" ;
LOG_INFO( GetEMkLogger(), sOut.c_str()) ;
return false ;
}
// recupero nome del path
string sPathName ;
m_pGeomDB->GetName( nPathId, sPathName) ;
// ciclo sulle curve elementari
bool bClosed = pCompo->IsClosed() ;
int nMaxInd = pCompo->GetCurveCount() - 1 ;
for ( int i = 0 ; i <= nMaxInd ; ++ i) {
// curva precedente
int j = (( i == 0 && bClosed) ? nMaxInd : i - 1) ;
const ICurve* pCrvP = pCompo->GetCurve( j) ; ;
// curva corrente
const ICurve* pCrvC = pCompo->GetCurve( i) ;
// curva successiva
int k = (( i == nMaxInd && bClosed) ? 0 : i + 1) ;
const ICurve* pCrvN = pCompo->GetCurve( k) ;
// elaborazioni sulla curva corrente
string sName = sPathName + "_" + ToString( i) ;
if ( ! EntityApply( pCrvP, pCrvC, pCrvN, dDepth, i == 0, i == nMaxInd, sName, nClId))
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
Sawing::EntityApply( const ICurve* pCrvP, const ICurve* pCrvC, const ICurve* pCrvN,
double dDepth, bool bIsFirst, bool bIsLast, const string& sName, int nClId)
{
// se non è una linea, la salto
if ( pCrvC->GetType() != CRV_LINE)
return true ;
// creo gruppo per geometria di lavorazione della linea
int nPxId = m_pGeomDB->AddGroup( GDB_ID_NULL, nClId, Frame3d()) ;
if ( nPxId == GDB_ID_NULL)
return false ;
m_pGeomDB->SetName( nPxId, sName) ;
m_pGeomDB->SetMaterial( nPxId, BLUE) ;
// copio la curva
PtrOwner<ICurveLine> pLine( GetCurveLine( pCrvC->Clone())) ;
// calcolo i versori fresa e correzione
Vector3d vtTool, vtCorr ;
if ( ! CalculateToolAndCorrVersors( Get( pLine), vtTool, vtCorr)) {
string sOut = "Entity not versorable by Sawing" ;
LOG_INFO( GetEMkLogger(), sOut.c_str()) ;
return false ;
}
// correzioni per lato lama, lato mandrino
if ( ! AdjustForSide( Get( pLine))) {
string sOut = "Entity not offsetable by Sawing" ;
LOG_INFO( GetEMkLogger(), sOut.c_str()) ;
return false ;
}
// aggiungo affondamento
pLine->Translate( - vtCorr * dDepth) ;
// calcolo elevazione
double dElev ;
if ( ! GetElevation( pLine->GetStart(), pLine->GetEnd(), vtCorr, dElev)) {
string sOut = "Entity not elevation-enabled by Sawing" ;
LOG_INFO( GetEMkLogger(), sOut.c_str()) ;
return false ;
}
// direzione linea corrente
Vector3d vtDirC ;
pLine->GetStartDir( vtDirC) ;
// calcolo tipo angolo con precedente
bool bExtAngPC = true ;
if ( pCrvP != nullptr) {
Vector3d vtDirP ;
pCrvP->GetEndDir( vtDirP) ;
double dAngPC ;
vtDirP.GetAngleXY( vtDirC, dAngPC) ;
if ( ( m_Params.m_nWorkSide == SAW_WS_LEFT && dAngPC > EPS_ANG_SMALL) ||
( m_Params.m_nWorkSide == SAW_WS_RIGHT && dAngPC < - EPS_ANG_SMALL))
bExtAngPC = false ;
}
// calcolo tipo angolo con successivo
bool bExtAngCN = true ;
if ( pCrvN != nullptr) {
Vector3d vtDirN ;
pCrvN->GetStartDir( vtDirN) ;
double dAngCN ;
vtDirC.GetAngleXY( vtDirN, dAngCN) ;
if ( ( m_Params.m_nWorkSide == SAW_WS_LEFT && dAngCN > EPS_ANG_SMALL) ||
( m_Params.m_nWorkSide == SAW_WS_RIGHT && dAngCN < - EPS_ANG_SMALL))
bExtAngCN = false ;
}
// aggiusto per tipo estremi
AdjustForEdges( Get( pLine), dElev, bIsFirst, bIsLast, bExtAngPC, bExtAngCN) ;
// recupero distanza di approccio
double dAppr = GetApproachDist() ;
// correzione per angolo di fianco
if ( fabs( m_Params.m_dSideAngle) > EPS_ANG_SMALL)
dAppr /= cos( m_Params.m_dSideAngle * DEGTORAD) ;
// imposto dati comuni
SetPathId( nPxId) ;
SetToolDir( vtTool) ;
SetCorrDir( vtCorr) ;
// 1 -> punto sopra inizio
Point3d ptP1 = pLine->GetStart() + vtCorr * ( dElev + dAppr) ;
if ( AddStart( ptP1) == GDB_ID_NULL)
return false ;
// 2 -> movimento al punto iniziale
SetFeed( m_TParams.m_dTipFeed) ;
Point3d ptP2 = pLine->GetStart() ;
if ( AddLinearMove( ptP2) == GDB_ID_NULL)
return false ;
// 3 -> movimento al punto finale
SetFeed( m_TParams.m_dFeed) ;
Point3d ptP3 = pLine->GetEnd() ;
if ( AddLinearMove( ptP3) == GDB_ID_NULL)
return false ;
// 4 -> movimento di risalita sopra il punto finale
SetFeed( m_TParams.m_dFeed) ;
Point3d ptP4 = pLine->GetEnd() + vtCorr * ( dElev + dAppr) ;
if ( AddLinearMove( ptP4) == GDB_ID_NULL)
return false ;
return true ;
}
//----------------------------------------------------------------------------
bool
Sawing::CalculateToolAndCorrVersors( const ICurve* pCurve, Vector3d& vtTool, Vector3d& vtCorr)
{
// Recupero la direzione della linea e la proietto nel piano XY
Vector3d vtTang ;
pCurve->GetStartDir( vtTang) ;
vtTang.z = 0 ;
if ( ! vtTang.Normalize())
return false ;
// Versore fresa : annullo la componente in Z e normalizzo
vtTool = vtTang ;
// ruoto attorno a Zglob+ a seconda del lato mandrino
if ( m_Params.m_nHeadSide == SAW_HS_LEFT)
vtTool.Rotate( Z_AX, 90) ;
else
vtTool.Rotate( Z_AX, -90) ;
// Versore correzione
vtCorr = Z_AX ;
// Se lama sbandata
if ( fabs( m_Params.m_dSideAngle) > EPS_ANG_SMALL) {
if ( m_Params.m_nWorkSide == SAW_WS_RIGHT) {
vtTool.Rotate( vtTang, - m_Params.m_dSideAngle) ;
vtCorr.Rotate( vtTang, - m_Params.m_dSideAngle) ;
}
else {
vtTool.Rotate( vtTang, m_Params.m_dSideAngle) ;
vtCorr.Rotate( vtTang, m_Params.m_dSideAngle) ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
Sawing::AdjustForSide( ICurve* pCurve)
{
// se lato lavoro e lato mandrino coincidono, non devo fare alcunché
if ( ( m_Params.m_nWorkSide == SAW_WS_LEFT && m_Params.m_nHeadSide == SAW_HS_LEFT) ||
( m_Params.m_nWorkSide == SAW_WS_RIGHT && m_Params.m_nHeadSide == SAW_HS_RIGHT))
return true ;
// calcolo offset curva
double dOffs = 0 ;
if ( m_Params.m_nWorkSide == SAW_WS_LEFT)
dOffs = - m_TParams.m_dThick ;
else if ( m_Params.m_nWorkSide == SAW_WS_RIGHT)
dOffs = m_TParams.m_dThick ;
else if ( m_Params.m_nHeadSide == SAW_HS_LEFT) // lama in centro
dOffs = 0.5 * m_TParams.m_dThick ;
else // testa a destra e lama in centro
dOffs = - 0.5 * m_TParams.m_dThick ;
// correzione per angolo di fianco
if ( fabs( m_Params.m_dSideAngle) > EPS_ANG_SMALL)
dOffs /= cos( m_Params.m_dSideAngle * DEGTORAD) ;
// eseguo offset curva ( nel piano XY globale)
return pCurve->SimpleOffset( dOffs) ;
}
//----------------------------------------------------------------------------
bool
Sawing::AdjustForEdges( ICurveLine* pLine, double dElev, bool bIsFirst, bool bIsLast, bool bExtAngPC, bool bExtAngCN)
{
// distanza XY tra centro e bordo taglio
double dDeltaT = (( dElev < 0.5 * m_TParams.m_dDiam) ? sqrt( dElev * m_TParams.m_dDiam - dElev * dElev) : 0) ;
// verifiche e aggiustamenti sull'inizio
double dDeltaI = 0 ;
if ( ! bExtAngPC)
dDeltaI = - dDeltaT ;
else if ( bIsFirst) {
if ( m_Params.m_nLeadInType == SAW_LI_STRICT)
dDeltaI = - dDeltaT ;
else if ( m_Params.m_nLeadInType == SAW_LI_OUT)
dDeltaI = dDeltaT ;
else if ( m_Params.m_nLeadInType == SAW_LI_EXT_CENT)
; // estendere al bordo del grezzo
else if ( m_Params.m_nLeadInType == SAW_LI_EXT_OUT)
; // estendere al bordo del grezzo e aggiungere dDeltaT
}
else {
if ( m_Params.m_nExtLinkType == SAW_EL_EXT_NEXT ||
m_Params.m_nExtLinkType == SAW_EL_EXT_BOTH) {
; // estendere al bordo del grezzo se LeadIn EXT_OUT aggiungere dDeltaT
}
}
// verifiche e aggiustamenti sulla fine
double dDeltaF = 0 ;
if ( ! bExtAngCN)
dDeltaF = - dDeltaT ;
else if ( bIsLast) {
if ( m_Params.m_nLeadOutType == SAW_LI_STRICT)
dDeltaF = - dDeltaT ;
else if ( m_Params.m_nLeadInType == SAW_LO_EXT)
; // estendere al bordo del grezzo
}
else {
if ( m_Params.m_nExtLinkType == SAW_EL_EXT_PREV ||
m_Params.m_nExtLinkType == SAW_EL_EXT_BOTH) {
; // estendere al bordo del grezzo
}
}
// controllo se lunghezza entità accettabile
const double MIN_LEN = 10 ;
double dLenXY = DistXY( pLine->GetStart(), pLine->GetEnd()) ;
if ( dDeltaI + dLenXY + dDeltaF < MIN_LEN)
return false ;
// modifico gli estremi
if ( dDeltaF > EPS_SMALL)
pLine->ExtendEndByLen( dDeltaF) ;
else if ( dDeltaF < - EPS_SMALL)
pLine->TrimEndAtLen( dLenXY + dDeltaF) ;
if ( dDeltaI > EPS_SMALL)
pLine->ExtendStartByLen( dDeltaI) ;
else if ( dDeltaI < - EPS_SMALL)
pLine->TrimStartAtLen( fabs( dDeltaI)) ;
return true ;
}
//----------------------------------------------------------------------------
bool
Sawing::AdjustPositionForAxesCalc( const CamData* pCamData, Point3d& ptP)
{
// compenso il raggio dell'utensile
ptP += pCamData->GetCorrDir() * ( m_TParams.m_dDiam / 2) ;
return true ;
}