Files
EgtMachKernel/Sawing.cpp
T
Dario Sassi cc2a72d5af EgtMachKernel 1.6l3 :
- aggiunta prima gestione preview tagli con lama.
2015-12-15 14:48:11 +00:00

1414 lines
48 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/EXeConst.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_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_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 ;
}
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_STEPTYPE :
if ( ! m_Params.VerifyStepType( nVal))
return false ;
m_Params.m_nStepType = 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_STARTPOS :
m_Params.m_dStartPos = dVal ;
return true ;
case MPA_STEP :
m_Params.m_dStep = 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::Preview( bool bRecalc)
{
// 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) ;
bool bChain = false ;
// se non c'è, lo aggiungo
if ( nAuxId == GDB_ID_NULL) {
nAuxId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ;
if ( nAuxId == GDB_ID_NULL)
return false ;
m_pGeomDB->SetName( nAuxId, MCH_AUX) ;
bChain = true ;
}
// altrimenti, se chiesto ricalcolo, lo svuoto
else if ( bRecalc) {
m_pGeomDB->EmptyGroup( nAuxId) ;
bChain = true ;
}
// se necessario, eseguo concatenamento ed inserisco i percorsi sotto la geometria ausiliaria
if ( bChain && ! Chain( nAuxId))
return false ;
// verifiche per angolo di sbandamento
if ( ! VerifySideAngle())
return false ;
// recupero gruppo per anteprima di lavorazione (PreView)
int nPvId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_PV) ;
// se non c'è, lo aggiungo
if ( nPvId == GDB_ID_NULL) {
nPvId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ;
if ( nPvId == GDB_ID_NULL)
return false ;
m_pGeomDB->SetName( nPvId, MCH_PV) ;
}
// altrimenti lo svuoto
else
m_pGeomDB->EmptyGroup( nPvId) ;
// calcolo anteprima di ogni singola catena
int nPathId = m_pGeomDB->GetFirstGroupInGroup( nAuxId) ;
while ( nPathId != GDB_ID_NULL) {
if ( ! ProcessPath( nPathId, nPvId, GDB_ID_NULL))
return false ;
nPathId = m_pGeomDB->GetNextGroup( nPathId) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
Sawing::Apply( bool bRecalc)
{
// 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) ;
bool bChain = false ;
// se non c'è, lo aggiungo
if ( nAuxId == GDB_ID_NULL) {
nAuxId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ;
if ( nAuxId == GDB_ID_NULL)
return false ;
m_pGeomDB->SetName( nAuxId, MCH_AUX) ;
bChain = true ;
}
// altrimenti, se chiesto ricalcolo, lo svuoto
else if ( bRecalc) {
m_pGeomDB->EmptyGroup( nAuxId) ;
bChain = true ;
}
// se necessario, eseguo concatenamento ed inserisco i percorsi sotto la geometria ausiliaria
if ( bChain && ! Chain( nAuxId))
return false ;
// verifiche per angolo di sbandamento
if ( ! VerifySideAngle())
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) {
if ( ! ProcessPath( nPathId, GDB_ID_NULL, nClId))
return false ;
nPathId = m_pGeomDB->GetNextGroup( nPathId) ;
}
// calcolo gli assi macchina
if ( ! CalculateAxesValues())
return false ;
// gestione movimenti all'inizio di ogni singolo percorso di lavorazione
if ( ! AdjustStartMovements())
return false ;
return true ;
}
//----------------------------------------------------------------------------
bool
Sawing::GetParam( int nType, bool& bVal) const
{
switch ( nType) {
case MPA_INVERT :
bVal = m_Params.m_bInvert ;
return true ;
}
return false ;
}
//----------------------------------------------------------------------------
bool
Sawing::GetParam( int nType, int& nVal) const
{
switch ( nType) {
case MPA_TYPE :
nVal = MT_SAWING ;
return true ;
case MPA_WORKSIDE :
nVal = m_Params.m_nWorkSide ;
return true ;
case MPA_HEADSIDE :
nVal = m_Params.m_nHeadSide ;
return true ;
case MPA_STEPTYPE :
nVal = m_Params.m_nStepType ;
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_STARTPOS :
dVal = m_Params.m_dStartPos ;
return true ;
case MPA_STEP :
dVal = m_Params.m_dStep ;
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::AdjustPositionForAxesCalc( const CamData* pCamData, Point3d& ptP)
{
// compenso il raggio dell'utensile
ptP += pCamData->GetCorrDir() * ( m_TParams.m_dDiam / 2) ;
return true ;
}
//----------------------------------------------------------------------------
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::ProcessPath( int nPathId, int nPvId, int nClId)
{
// recupero gruppo per geometria temporanea
const string GRP_TEMP = "Temp" ;
int nTempId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, GRP_TEMP) ;
// se non c'è, lo aggiungo
if ( nTempId == GDB_ID_NULL) {
nTempId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ;
if ( nTempId == GDB_ID_NULL)
return false ;
m_pGeomDB->SetName( nTempId, GRP_TEMP) ;
}
// altrimenti lo svuoto
else
m_pGeomDB->EmptyGroup( nTempId) ;
// in ogni caso lo dichiaro temporaneo e non visibile
m_pGeomDB->SetLevel( nTempId, GDB_LV_TEMP) ;
m_pGeomDB->SetStatus( nTempId, GDB_ST_OFF) ;
// 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) ;
// recupero distanza da fondo dei grezzi interessati dal percorso
double dRbDist ;
if ( ! GetDistanceFromRawBottom( nCopyId, 2 * m_TParams.m_dThick, dRbDist))
return false ;
// valuto l'espressione dell'affondamento
ExeLuaSetGlobNumVar( "TH", (( dThick * vtExtr.z < 0) ? fabs( dThick) : 0)) ;
ExeLuaSetGlobNumVar( "RB", dRbDist) ;
double dDepth ;
if ( ! ExeLuaEvalNumExpr( m_Params.m_sDepth, &dDepth)) {
LOG_INFO( GetEMkLogger(), "Error in Sawing : Depth not computable") ;
return false ;
}
// determino l'eccesso di taglio
double dExtraCut = max( 0., dDepth - dRbDist) ;
// correzione per angolo di fianco
if ( fabs( m_Params.m_dSideAngle) > EPS_ANG_SMALL) {
// generale
double dCoeff = 1 / cos( m_Params.m_dSideAngle * DEGTORAD) ;
dDepth *= dCoeff ;
dExtraCut *= dCoeff ;
// 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 = "Error in Sawing : 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 ( ! ProcessEntity( pCrvP, pCrvC, pCrvN, dDepth, dExtraCut, i == 0, i == nMaxInd, sName, nPvId, nClId))
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
Sawing::ProcessEntity( const ICurve* pCrvP, const ICurve* pCrvC, const ICurve* pCrvN,
double dDepth, double dExtraCut, bool bIsFirst, bool bIsLast,
const string& sName, int nPvId, int nClId)
{
// se non è una linea, la salto
if ( pCrvC->GetType() != CRV_LINE)
return true ;
// copio la curva
PtrOwner<ICurveLine> pLine( GetCurveLine( pCrvC->Clone())) ;
// calcolo i versori fresa e correzione
Vector3d vtTool, vtCorr ;
if ( ! CalculateToolAndCorrVersors( Get( pLine), vtTool, vtCorr)) {
LOG_INFO( GetEMkLogger(), "Error in Sawing : Entity CalculateToolAndCorrVersors") ;
return false ;
}
// correzioni per lato lama, lato mandrino
if ( ! AdjustForSide( Get( pLine))) {
LOG_INFO( GetEMkLogger(), "Error in Sawing : Entity AdjustForSide") ;
return false ;
}
// aggiungo affondamento
pLine->Translate( - vtCorr * dDepth) ;
// calcolo elevazione (sui due bordi della striscia
double dElev, dElev2 ;
Vector3d vtThick = vtTool * m_TParams.m_dThick ;
if ( ! GetElevation( pLine->GetStart(), pLine->GetEnd(), vtCorr, dElev) ||
! GetElevation( pLine->GetStart() + vtThick, pLine->GetEnd() + vtThick, vtCorr, dElev2) ) {
LOG_INFO( GetEMkLogger(), "Error in Sawing : Entity GetElevation") ;
return false ;
}
dElev = max( dElev, dElev2) ;
// 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
bool bToSkip = false ;
if ( ! AdjustForEdges( Get( pLine), dElev, vtThick, bIsFirst, bIsLast, bExtAngPC, bExtAngCN, bToSkip)) {
LOG_INFO( GetEMkLogger(), "Error in Sawing : Entity AdjustForEdges") ;
return false ;
}
if ( bToSkip) {
LOG_INFO( GetEMkLogger(), "Warning in Sawing : skipped Entity too small") ;
return true ;
}
// Se richiesto Preview
if ( nPvId != GDB_ID_NULL) {
if ( ! GenerateEntityPv( Get( pLine), vtTool, vtCorr, dElev, dExtraCut, sName, nPvId))
return false ;
}
// Se richiesta geometria di lavorazione
if ( nClId != GDB_ID_NULL) {
if ( ! GenerateEntityCl( Get( pLine), vtTool, vtCorr, dElev, dExtraCut, sName, nClId))
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
Sawing::GenerateEntityPv( const ICurveLine* pLine, const Vector3d& vtTool, const Vector3d& vtCorr,
double dElev, double dExtraCut, const string& sName, int nPvId)
{
// creo gruppo per anteprima di lavorazione della linea
int nPxId = m_pGeomDB->AddGroup( GDB_ID_NULL, nPvId, Frame3d()) ;
if ( nPxId == GDB_ID_NULL)
return false ;
m_pGeomDB->SetName( nPxId, sName) ;
m_pGeomDB->SetMaterial( nPxId, BLUE) ;
// rettangolo per parte di taglio completo
Point3d ptIni = pLine->GetStart() + dElev * vtCorr ;
Point3d ptEnd = pLine->GetEnd() + dElev * vtCorr ;
Vector3d vtToolH( vtTool.x, vtTool.y, 0) ;
vtToolH *= m_TParams.m_dThick / vtToolH.SqLen() ;
Point3d ptCross = ptEnd + vtToolH ;
Vector3d vtDZ( 0, 0, 0.1) ;
int nId = ExeCreateRectangle3P( nPxId, ptIni + vtDZ, ptCross + vtDZ, ptEnd + vtDZ, RTY_LOC) ;
// assegno colore
m_pGeomDB->SetMaterial( nId, LIME) ;
// 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) ;
// direzione del taglio
Vector3d vtDir ;
pLine->GetStartDir( vtDir) ;
// rettangolo per parte parziale iniziale
int nId2 = ExeCreateRectangle3P( nPxId, ptIni - vtDir * dDeltaT, ptIni + vtToolH, ptIni, RTY_LOC) ;
// assegno colore
m_pGeomDB->SetMaterial( nId2, FUCHSIA) ;
// rettangolo per parte parziale finale
int nId3 = ExeCreateRectangle3P( nPxId, ptEnd, ptCross + vtDir * dDeltaT, ptEnd + vtDir * dDeltaT, RTY_LOC) ;
// assegno colore
m_pGeomDB->SetMaterial( nId3, FUCHSIA) ;
return true ;
}
//----------------------------------------------------------------------------
bool
Sawing::GenerateEntityCl( const ICurveLine* pLine, const Vector3d& vtTool, const Vector3d& vtCorr,
double dElev, double dExtraCut, const string& sName, int nClId)
{
// 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) ;
// Imposto dati comuni
SetPathId( nPxId) ;
SetToolDir( vtTool) ;
SetCorrDir( vtCorr) ;
// recupero distanza di sicurezza
double dSafeZ = m_pMchMgr->GetCurrMachiningsMgr()->GetSafeZ() ;
// lunghezza di approccio/retrazione
double dAppr = m_Params.m_dStartPos ;
if ( fabs( m_Params.m_dSideAngle) > EPS_ANG_SMALL)
dAppr /= cos( m_Params.m_dSideAngle * DEGTORAD) ;
// Se una sola passata
if ( m_Params.m_dStep < EPS_SMALL) {
// 1 -> approccio
if ( ! AddApproach( pLine->GetStart(), vtCorr, dSafeZ, dElev, dAppr))
return false ;
// 2 -> movimento in affondo al punto iniziale
SetFlag( 0) ;
SetFeed( m_TParams.m_dTipFeed) ;
Point3d ptP2 = pLine->GetStart() ;
if ( AddLinearMove( ptP2) == GDB_ID_NULL)
return false ;
// 3 -> movimento di lato al punto finale
SetFeed( m_TParams.m_dFeed) ;
Point3d ptP3 = pLine->GetEnd() ;
if ( AddLinearMove( ptP3) == GDB_ID_NULL)
return false ;
// 4 -> retrazione
if ( ! AddRetract( pLine->GetEnd(), vtCorr, dSafeZ, dElev, dAppr))
return false ;
}
// Se step a Zig-Zag o ToAndFrom
else if ( m_Params.m_nStepType == SAW_ST_ZIGZAG || m_Params.m_nStepType == SAW_ST_TOANDFROM) {
// 1 -> approccio
if ( ! AddApproach( pLine->GetStart(), vtCorr, dSafeZ, dElev, dAppr))
return false ;
// 2-3 -> lavorazione (sempre numero pari di passate)
// calcolo numero e valore degli step
double dCutH = dElev - dExtraCut ;
int nStep = 2 ;
if ( m_Params.m_nStepType == SAW_ST_ZIGZAG) {
nStep = static_cast<int>( ceil( dCutH / m_Params.m_dStep)) ;
if ( ( nStep % 2) == 1)
nStep += 1 ;
}
double dStep = dCutH / nStep ;
// esecuzione degli step
for ( int i = nStep - 1 ; i >= 0 ; -- i) {
// distanza dal fondo
double dDelta = ( ( i != 0) ? dExtraCut + i * dStep : 0) ;
// estremi del movimento (dispari vanno, pari tornano)
Point3d ptP2 = pLine->GetStart() + vtCorr * dDelta ;
Point3d ptP3 = pLine->GetEnd() + vtCorr * dDelta ;
if ( ( i % 2) == 0)
swap( ptP2, ptP3) ;
// movimento in affondo
SetFlag( 0) ;
SetFeed( m_TParams.m_dTipFeed) ;
if ( AddLinearMove( ptP2) == GDB_ID_NULL)
return false ;
// movimento di lato
SetFeed( m_TParams.m_dFeed) ;
if ( AddLinearMove( ptP3) == GDB_ID_NULL)
return false ;
}
// 4 -> retrazione
if ( ! AddRetract( pLine->GetStart(), vtCorr, dSafeZ, dElev, dAppr))
return false ;
}
// Altrimenti step a una via
else {
// 1 -> approccio
if ( ! AddApproach( pLine->GetStart(), vtCorr, dSafeZ, dElev, dAppr))
return false ;
// 2-3 -> lavorazione
// calcolo numero e valore degli step
double dCutH = dElev - dExtraCut ;
int nStep = static_cast<int>( ceil( dCutH / m_Params.m_dStep)) ;
double dStep = dCutH / nStep ;
// esecuzione degli step
for ( int i = nStep - 1 ; i >= 0 ; -- i) {
// distanza dal fondo
double dDelta = ( ( i != 0) ? dExtraCut + i * dStep : 0) ;
// movimento in affondo al punto iniziale
SetFlag( 0) ;
SetFeed( m_TParams.m_dTipFeed) ;
Point3d ptP2 = pLine->GetStart() + vtCorr * dDelta ;
if ( AddLinearMove( ptP2) == GDB_ID_NULL)
return false ;
// movimento di lato al punto finale
SetFeed( m_TParams.m_dFeed) ;
Point3d ptP3 = pLine->GetEnd() + vtCorr * dDelta ;
if ( AddLinearMove( ptP3) == GDB_ID_NULL)
return false ;
// se non è ultimo passo
if ( i != 0) {
// movimento di risalita sopra il punto finale
SetFeed( m_TParams.m_dEndFeed) ;
Point3d ptP4 = pLine->GetEnd() + vtCorr * ( dElev + dAppr) ;
if ( AddLinearMove( ptP4) == GDB_ID_NULL)
return false ;
// movimento di ritorno spora il punto iniziale
SetFeed( m_TParams.m_dEndFeed) ;
Point3d ptP5 = pLine->GetStart() + vtCorr * ( dElev + dAppr) ;
if ( AddLinearMove( ptP5) == GDB_ID_NULL)
return false ;
}
}
// 4 -> retrazione
if ( ! AddRetract( pLine->GetEnd(), vtCorr, dSafeZ, dElev, dAppr))
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
Sawing::AddApproach( const Point3d& ptP, const Vector3d& vtCorr, double dSafeZ, double dElev, double dAppr)
{
// se distanza di sicurezza minore di distanza di inizio
if ( dSafeZ < m_Params.m_dStartPos + 10 * EPS_SMALL) {
// 1 -> punto sopra inizio
SetFlag( 1) ;
Point3d ptP1 = ptP + vtCorr * ( dElev + dAppr) ;
if ( AddRapidStart( ptP1) == GDB_ID_NULL)
return false ;
}
else {
// 1a -> punto sopra inizio
SetFlag( 1) ;
Point3d ptP1b = ptP + vtCorr * ( dElev + dAppr) ;
Point3d ptP1a = ptP1b + Z_AX * ( dSafeZ - m_Params.m_dStartPos) ;
if ( AddRapidStart( ptP1a) == GDB_ID_NULL)
return false ;
// 1b -> punto appena sopra inizio
SetFlag( 0) ;
if ( AddRapidMove( ptP1b) == GDB_ID_NULL)
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
Sawing::AddRetract( const Point3d& ptP, const Vector3d& vtCorr, double dSafeZ, double dElev, double dAppr)
{
if ( dSafeZ < m_Params.m_dStartPos + 10 * EPS_SMALL) {
// 4 -> movimento di risalita sopra il punto finale
SetFeed( m_TParams.m_dEndFeed) ;
Point3d ptP4 = ptP + vtCorr * ( dElev + dAppr) ;
if ( AddLinearMove( ptP4) == GDB_ID_NULL)
return false ;
}
else {
// 4a -> movimento di risalita appena sopra il punto finale
SetFeed( m_TParams.m_dEndFeed) ;
Point3d ptP4a = ptP + vtCorr * ( dElev + dAppr) ;
if ( AddLinearMove( ptP4a) == GDB_ID_NULL)
return false ;
// 4b -> movimento di risalita sopra il punto finale
Point3d ptP4b = ptP4a + Z_AX * ( dSafeZ - m_Params.m_dStartPos) ;
if ( AddRapidMove( ptP4b) == 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, const Vector3d& vtThick,
bool bIsFirst, bool bIsLast, bool bExtAngPC, bool bExtAngCN, bool& bToSkip)
{
// 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)
// all'interno
dDeltaI = - dDeltaT ;
else if ( m_Params.m_nLeadInType == SAW_LI_OUT)
// all'esterno
dDeltaI = dDeltaT ;
else if ( m_Params.m_nLeadInType == SAW_LI_EXT_CENT) {
// porto il centro lama sul bordo del grezzo
// calcolo punto di inizio e direzione (sono in globale)
Point3d ptP ;
pLine->GetStartPoint( ptP) ;
Vector3d vtDir ;
pLine->GetStartDir( vtDir) ;
// determino la distanza dal bordo del grezzo
double dDist = 0, dDist2 = 0 ;
if ( ! GetDistanceFromRawSide( ptP, - vtDir, dDist) &&
! GetDistanceFromRawSide( ptP + vtThick, - vtDir, dDist2))
return false ;
dDeltaI = max( dDist, dDist2) ;
}
else if ( m_Params.m_nLeadInType == SAW_LI_EXT_OUT) {
// estendo all'esterno del bordo del grezzo
// calcolo punto di inizio e direzione (sono in globale)
Point3d ptP ;
pLine->GetStartPoint( ptP) ;
Vector3d vtDir ;
pLine->GetStartDir( vtDir) ;
// determino la distanza dal bordo del grezzo
double dDist = 0, dDist2 = 0 ;
if ( ! GetDistanceFromRawSide( ptP, - vtDir, dDist) ||
! GetDistanceFromRawSide( ptP + vtThick, - vtDir, dDist2))
return false ;
dDeltaI = max( dDist, dDist2) + dDeltaT ;
}
}
else {
if ( m_Params.m_nExtLinkType == SAW_EL_EXT_NEXT ||
m_Params.m_nExtLinkType == SAW_EL_EXT_BOTH) {
// estendere al bordo del grezzo
// calcolo punto di inizio e direzione (sono in globale)
Point3d ptP ;
pLine->GetStartPoint( ptP) ;
Vector3d vtDir ;
pLine->GetStartDir( vtDir) ;
// determino la distanza dal bordo del grezzo
double dDist = 0, dDist2 = 0 ;
if ( ! GetDistanceFromRawSide( ptP, - vtDir, dDist) ||
! GetDistanceFromRawSide( ptP + vtThick, - vtDir, dDist2))
return false ;
dDeltaI = max( dDist, dDist2) ;
// se LeadIn EXT_OUT vado all'esterno
if ( m_Params.m_nLeadInType == SAW_LI_EXT_OUT)
dDeltaI += dDeltaT ;
}
}
// verifiche e aggiustamenti sulla fine
double dDeltaF = 0 ;
if ( ! bExtAngCN)
dDeltaF = - dDeltaT ;
else if ( bIsLast) {
if ( m_Params.m_nLeadOutType == SAW_LO_STRICT)
dDeltaF = - dDeltaT ;
else if ( m_Params.m_nLeadInType == SAW_LO_EXT) {
// estendo al bordo del grezzo
// calcolo punto di fine e direzione (sono in globale)
Point3d ptP ;
pLine->GetEndPoint( ptP) ;
Vector3d vtDir ;
pLine->GetEndDir( vtDir) ;
// determino la distanza dal bordo del grezzo
double dDist = 0, dDist2 = 0 ;
if ( ! GetDistanceFromRawSide( ptP, vtDir, dDist) ||
! GetDistanceFromRawSide( ptP + vtThick, vtDir, dDist2))
return false ;
dDeltaF = max( dDist, dDist2) ;
}
}
else {
if ( m_Params.m_nExtLinkType == SAW_EL_EXT_PREV ||
m_Params.m_nExtLinkType == SAW_EL_EXT_BOTH) {
// estendo al bordo del grezzo
// calcolo punto di fine e direzione (sono in globale)
Point3d ptP ;
pLine->GetEndPoint( ptP) ;
Vector3d vtDir ;
pLine->GetEndDir( vtDir) ;
// determino la distanza dal bordo del grezzo
double dDist = 0, dDist2 = 0 ;
if ( ! GetDistanceFromRawSide( ptP, vtDir, dDist) ||
! GetDistanceFromRawSide( ptP + vtThick, vtDir, dDist2))
return false ;
dDeltaF = max( dDist, dDist2) ;
}
}
// controllo se lunghezza entità accettabile
const double MIN_LEN = 10 ;
double dLenXY = DistXY( pLine->GetStart(), pLine->GetEnd()) ;
if ( dDeltaI + dLenXY + dDeltaF < MIN_LEN) {
bToSkip = true ;
return true ;
}
bToSkip = 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 ;
}