8fed51ca79
- aggiunta scrittura nota "EXTR" in Px di CL per SawRoughing e SawFinishing.
2985 lines
113 KiB
C++
2985 lines
113 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2015-2019
|
|
//----------------------------------------------------------------------------
|
|
// File : SawRoughing.cpp Data : 23.04.19 Versione : 2.1d3
|
|
// Contenuto : Implementazione gestione sgrossatura superficie con lama.
|
|
//
|
|
// Note : Questa lavorazione è sempre espressa nel riferimento globale.
|
|
//
|
|
// Modifiche : 30.03.16 DS Creazione modulo.
|
|
// 23.04.19 DS Aggiunte cornici curve.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "MachMgr.h"
|
|
#include "DllMain.h"
|
|
#include "SawRoughing.h"
|
|
#include "OperationConst.h"
|
|
#include "GeoConst.h"
|
|
#include "/EgtDev/Include/EXeCmdLogOff.h"
|
|
#include "/EgtDev/Include/EXeConst.h"
|
|
#include "/EgtDev/Include/EGkCurveLine.h"
|
|
#include "/EgtDev/Include/EGkCurveArc.h"
|
|
#include "/EgtDev/Include/EGkCurveComposite.h"
|
|
#include "/EgtDev/Include/EGkOffsetCurve.h"
|
|
#include "/EgtDev/Include/EGkOffsetCurveOnX.h"
|
|
#include "/EgtDev/Include/EGkSfrCreate.h"
|
|
#include "/EgtDev/Include/EGkIntervals.h"
|
|
#include "/EgtDev/Include/EGkUserObjFactory.h"
|
|
#include "/EgtDev/Include/EGkIntersLineBox.h"
|
|
#include "/EgtDev/Include/EGnStringKeyVal.h"
|
|
#include "/EgtDev/Include/EgtPointerOwner.h"
|
|
// per far dimenticare macro di WinUser.h
|
|
#undef GetClassName
|
|
|
|
using namespace std ;
|
|
|
|
//------------------------------ Errors --------------------------------------
|
|
// 2601 = "Error in SawRoughing : UpdateToolData failed"
|
|
// 2602 = "Error in SawRoughing : AdjustGeometry failed"
|
|
// 2603 = "Error in SawRoughing : Guide Line not along X or Y"
|
|
// 2604 = "Error in SawRoughing : Empty RawBox"
|
|
// 2605 = "Error in SawRoughing : OffsetCurve"
|
|
// 2606 = "Error in SawRoughing : OffsetCurveOnX"
|
|
// 2607 = "Error in SawRoughing : Depth not computable"
|
|
// 2608 = "Error in SawRoughing : CalculateToolAndCorrVersors"
|
|
// 2609 = "Error in SawRoughing : GetElevation"
|
|
// 2610 = "Error in SawRoughing : TrimSection failed"
|
|
// 2611 = "Error in SawRoughing : axes values not calculable"
|
|
// 2612 = "Error in SawRoughing : outstroke xxx"
|
|
// 2613 = "Error in SawRoughing : link movements not calculable"
|
|
// 2614 = "Error in SawRoughing : link outstroke xxx"
|
|
// 2615 = "Error in SawRoughing : post apply not calculable"
|
|
// 2616 = "Error in SawRoughing : special apply not calculable"
|
|
// 2651 = "Warning in SawRoughing : Skipped entity (xx)"
|
|
// 2652 = "Warning in SawRoughing : No machinable path"
|
|
// 2653 = "Warning in SawRoughing : Tool name changed (xx)"
|
|
// 2654 = "Warning in SawRoughing : Tool data changed (xx)"
|
|
|
|
//----------------------------------------------------------------------------
|
|
const string MCH_SECTION = "Sect" ;
|
|
const string MCH_GUIDE = "Guide" ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
USEROBJ_REGISTER( GetOperationClass( OPER_SAWROUGHING), SawRoughing) ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
const string&
|
|
SawRoughing::GetClassName( void) const
|
|
{
|
|
return USEROBJ_GETNAME( SawRoughing) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
SawRoughing*
|
|
SawRoughing::Clone( void) const
|
|
{
|
|
// alloco oggetto
|
|
SawRoughing* pSaw = new(nothrow) SawRoughing ;
|
|
// eseguo copia dei dati
|
|
if ( pSaw != nullptr) {
|
|
try {
|
|
pSaw->m_vId = m_vId ;
|
|
pSaw->m_bStraight = m_bStraight ;
|
|
pSaw->m_pMchMgr = m_pMchMgr ;
|
|
pSaw->m_nPhase = m_nPhase ;
|
|
pSaw->m_Params = m_Params ;
|
|
pSaw->m_TParams = m_TParams ;
|
|
pSaw->m_nStatus = m_nStatus ;
|
|
pSaw->m_nCuts = m_nCuts ;
|
|
}
|
|
catch( ...) {
|
|
delete pSaw ;
|
|
return nullptr ;
|
|
}
|
|
}
|
|
// ritorno l'oggetto
|
|
return pSaw ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::Dump( string& sOut, bool bMM, const char* szNewLine) const
|
|
{
|
|
sOut += GetClassName() + "[mm]" + szNewLine ;
|
|
sOut += KEY_PHASE + EQUAL + ToString( m_nPhase) + szNewLine ;
|
|
sOut += KEY_IDS + EQUAL + ToString( m_vId) + szNewLine ;
|
|
sOut += KEY_STRAIGHT + EQUAL + ToString( m_bStraight) + 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 ;
|
|
sOut += KEY_NUM + EQUAL + ToString( m_nCuts) + szNewLine ;
|
|
sOut += KEY_STAT + EQUAL + ToString( m_nStatus) + szNewLine ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::Save( int nBaseId, STRVECTOR& vString) const
|
|
{
|
|
try {
|
|
int nSize = 1 + m_Params.GetSize() + m_TParams.GetSize() + 4 ;
|
|
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) ;
|
|
if ( ! SetVal( KEY_PHASE, m_nPhase, vString[++k]))
|
|
return false ;
|
|
if ( ! SetVal( KEY_NUM, m_nCuts, vString[++k]))
|
|
return false ;
|
|
if ( ! SetVal( KEY_STAT, m_nStatus, vString[++k]))
|
|
return false ;
|
|
if ( ! SetVal( KEY_STRAIGHT, m_bStraight, vString[++k]))
|
|
return false ;
|
|
}
|
|
catch( ...) {
|
|
return false ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::Load( const STRVECTOR& vString, int nBaseGdbId)
|
|
{
|
|
int nSize = int( vString.size()) ;
|
|
// lista identificativi geometrie da lavorare
|
|
int k = - 1 ;
|
|
if ( k >= nSize - 1 || ! GetVal( vString[++k], KEY_IDS, m_vId))
|
|
return false ;
|
|
for ( auto& Sel : m_vId)
|
|
Sel.nId += nBaseGdbId ;
|
|
// parametri lavorazione
|
|
for ( int i = 0 ; i < m_Params.GetSize() ; ++ i) {
|
|
int nKey ;
|
|
if ( k >= nSize - 1 || ! m_Params.FromString( vString[++k], nKey) || nKey != i) {
|
|
if ( m_Params.IsOptional( i))
|
|
-- k ;
|
|
else
|
|
return false ;
|
|
}
|
|
}
|
|
// parametri utensile
|
|
for ( int i = 0 ; i < m_TParams.GetSize() ; ++ i) {
|
|
int nKey ;
|
|
if ( k >= nSize - 1 || ! m_TParams.FromString( vString[++k], nKey) || nKey != i)
|
|
return false ;
|
|
}
|
|
// parametri di stato
|
|
while ( k < nSize - 1) {
|
|
// separo chiave da valore
|
|
string sKey, sVal ;
|
|
SplitFirst( vString[++k], "=", sKey, sVal) ;
|
|
// leggo
|
|
if ( sKey == KEY_PHASE) {
|
|
if ( ! FromString( sVal, m_nPhase))
|
|
return false ;
|
|
}
|
|
else if ( sKey == KEY_NUM) {
|
|
if ( ! FromString( sVal, m_nCuts))
|
|
return false ;
|
|
}
|
|
else if ( sKey == KEY_STAT) {
|
|
if ( ! FromString( sVal, m_nStatus))
|
|
return false ;
|
|
}
|
|
else if ( sKey == KEY_STRAIGHT) {
|
|
if ( ! FromString( sVal, m_bStraight))
|
|
return false ;
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//----------------------------------------------------------------------------
|
|
SawRoughing::SawRoughing( void)
|
|
{
|
|
m_Params.m_sName = "*" ;
|
|
m_Params.m_sToolName = "*" ;
|
|
m_TParams.m_sName = "*" ;
|
|
m_TParams.m_sHead = "*" ;
|
|
m_nStatus = MCH_ST_TO_VERIFY ;
|
|
m_nCuts = 0 ;
|
|
m_bStraight = true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::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 SawRoughingData* pDdata = GetSawRoughingData( 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
|
|
SawRoughing::SetParam( int nType, bool bVal)
|
|
{
|
|
//switch ( nType) {
|
|
//}
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::SetParam( int nType, int nVal)
|
|
{
|
|
switch ( nType) {
|
|
case MPA_HEADSIDE :
|
|
if ( ! m_Params.VerifyHeadSide( nVal))
|
|
return false ;
|
|
if ( nVal != m_Params.m_nHeadSide)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_nHeadSide = nVal ;
|
|
return true ;
|
|
case MPA_STEPTYPE :
|
|
if ( ! m_Params.VerifyStepType( nVal))
|
|
return false ;
|
|
if ( nVal != m_Params.m_nStepType)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_nStepType = nVal ;
|
|
return true ;
|
|
case MPA_LEADLINKTYPE :
|
|
if ( ! m_Params.VerifyLeadLinkType( nVal))
|
|
return false ;
|
|
if ( nVal != m_Params.m_nLeadLinkType)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_nLeadLinkType = nVal ;
|
|
return true ;
|
|
case MPA_SCC :
|
|
if ( ! m_Params.VerifySolCh( nVal))
|
|
return false ;
|
|
if ( nVal != m_Params.m_nSolCh)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_nSolCh = nVal ;
|
|
return true ;
|
|
}
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::SetParam( int nType, double dVal)
|
|
{
|
|
switch ( nType) {
|
|
case MPA_SPEED :
|
|
if ( ! m_TParams.VerifySpeed( dVal))
|
|
return false ;
|
|
if ( AreSameAngValue( dVal, m_TParams.m_dSpeed))
|
|
dVal = 0 ;
|
|
if ( ! AreSameAngValue( dVal, m_Params.m_dSpeed))
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dSpeed = dVal ;
|
|
return true ;
|
|
case MPA_FEED :
|
|
if ( AreSameLenValue( dVal, m_TParams.m_dFeed))
|
|
dVal = 0 ;
|
|
if ( ! AreSameLenValue( dVal, m_Params.m_dFeed))
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dFeed = dVal ;
|
|
return true ;
|
|
case MPA_STARTFEED :
|
|
if ( AreSameLenValue( dVal, m_TParams.m_dStartFeed))
|
|
dVal = 0 ;
|
|
if ( ! AreSameLenValue( dVal, m_Params.m_dStartFeed))
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dStartFeed = dVal ;
|
|
return true ;
|
|
case MPA_ENDFEED :
|
|
if ( AreSameLenValue( dVal, m_TParams.m_dEndFeed))
|
|
dVal = 0 ;
|
|
if ( ! AreSameLenValue( dVal, m_Params.m_dEndFeed))
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dEndFeed = dVal ;
|
|
return true ;
|
|
case MPA_TIPFEED :
|
|
if ( AreSameLenValue( dVal, m_TParams.m_dTipFeed))
|
|
dVal = 0 ;
|
|
if ( ! AreSameLenValue( dVal, m_Params.m_dTipFeed))
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dTipFeed = dVal ;
|
|
return true ;
|
|
case MPA_OFFSR :
|
|
if ( AreSameLenValue( dVal, m_TParams.m_dOffsR))
|
|
dVal = UNKNOWN_PAR ;
|
|
if ( ! AreSameLenValue( dVal, m_Params.m_dOffsR))
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dOffsR = dVal ;
|
|
return true ;
|
|
case MPA_OFFSL :
|
|
if ( AreSameLenValue( dVal, m_TParams.m_dOffsL))
|
|
dVal = UNKNOWN_PAR ;
|
|
if ( ! AreSameLenValue( dVal, m_Params.m_dOffsL))
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dOffsL = dVal ;
|
|
return true ;
|
|
case MPA_DEPTH: {
|
|
string sVal = ToString( dVal) ;
|
|
if ( sVal != m_Params.m_sDepth)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_sDepth = sVal ;
|
|
} return true ;
|
|
case MPA_STARTPOS :
|
|
if ( ! AreSameLenValue( dVal, m_Params.m_dStartPos))
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dStartPos = dVal ;
|
|
return true ;
|
|
case MPA_SIDESTEP :
|
|
if ( ! AreSameLenValue( dVal, m_Params.m_dSideStep))
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dSideStep = dVal ;
|
|
return true ;
|
|
case MPA_STEP :
|
|
if ( ! AreSameLenValue( dVal, m_Params.m_dStep))
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dStep = dVal ;
|
|
return true ;
|
|
case MPA_APPROX :
|
|
if ( ! AreSameLenValue( dVal, m_Params.m_dApprox))
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dApprox = dVal ;
|
|
return true ;
|
|
case MPA_STARTADDLEN :
|
|
if ( ! AreSameLenValue( dVal, m_Params.m_dStartAddLen))
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dStartAddLen = dVal ;
|
|
return true ;
|
|
case MPA_ENDADDLEN :
|
|
if ( ! AreSameLenValue( dVal, m_Params.m_dEndAddLen))
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_dEndAddLen = dVal ;
|
|
return true ;
|
|
}
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::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 ;
|
|
if ( ! SameTool( m_TParams, *pTdata))
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_sToolName = sVal ;
|
|
m_Params.m_ToolUuid = pTdata->m_Uuid ;
|
|
m_TParams = *pTdata ;
|
|
} return true ;
|
|
case MPA_DEPTH_STR :
|
|
if ( sVal != m_Params.m_sDepth)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_sDepth = sVal ;
|
|
return true ;
|
|
case MPA_SYSNOTES :
|
|
if ( sVal != m_Params.m_sSysNotes)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_sSysNotes = sVal ;
|
|
return true ;
|
|
case MPA_USERNOTES :
|
|
if ( sVal != m_Params.m_sUserNotes)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_sUserNotes = sVal ;
|
|
return true ;
|
|
case MPA_INITANGS :
|
|
if ( sVal != m_Params.m_sInitAngs)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_sInitAngs = sVal ;
|
|
return true ;
|
|
case MPA_BLOCKEDAXIS :
|
|
if ( sVal != m_Params.m_sBlockedAxis)
|
|
m_nStatus |= MCH_ST_PARAM_MODIF ;
|
|
m_Params.m_sBlockedAxis = sVal ;
|
|
return true ;
|
|
}
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::SetGeometry( const SELVECTOR& vIds)
|
|
{
|
|
// verifico validità gestore DB geometrico
|
|
if ( m_pGeomDB == nullptr)
|
|
return false ;
|
|
// copia temporanea e reset della geometria corrente
|
|
SELVECTOR vOldId = m_vId ;
|
|
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 sInfo = "Warning in SawRoughing : Skipped entity " + ToString( Id) ;
|
|
m_pMchMgr->SetWarning( 2651, sInfo) ;
|
|
continue ;
|
|
}
|
|
// posso aggiungere alla lista
|
|
m_vId.emplace_back( Id) ;
|
|
}
|
|
// aggiorno lo stato
|
|
if ( m_vId != vOldId)
|
|
m_nStatus |= MCH_ST_GEO_MODIF ;
|
|
// restituisco presenza geometria da lavorare
|
|
return ( ! m_vId.empty()) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::Preview( bool bRecalc)
|
|
{
|
|
// reset numero tagli nella lavorazione
|
|
m_nCuts = 0 ;
|
|
|
|
// verifico validità gestore DB geometrico e Id del gruppo
|
|
if ( m_pGeomDB == nullptr || ! m_pGeomDB->ExistsObj( m_nOwnerId))
|
|
return false ;
|
|
|
|
// aggiorno dati geometrici dell'utensile
|
|
if ( ! UpdateToolData()) {
|
|
m_pMchMgr->SetLastError( 2601, "Error in SawRoughing : UpdateToolData failed") ;
|
|
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) ;
|
|
m_pGeomDB->SetStatus( nAuxId, GDB_ST_OFF) ;
|
|
}
|
|
// altrimenti, se chiesto ricalcolo, lo svuoto
|
|
else if ( bRecalc)
|
|
m_pGeomDB->EmptyGroup( nAuxId) ;
|
|
|
|
// se necessario, preparo geometria e la inserisco sotto la geometria ausiliaria
|
|
if ( ! AdjustGeometry( nAuxId)) {
|
|
m_pMchMgr->SetLastError( 2602, "Error in SawRoughing : AdjustGeometry failed") ;
|
|
return false ;
|
|
}
|
|
|
|
// recupero gruppo per anteprima di lavorazione
|
|
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 le passate
|
|
if ( m_bStraight) {
|
|
if ( ! CalculateToolPath( nAuxId, nPvId, GDB_ID_NULL))
|
|
return false ;
|
|
m_nCuts = 1 ;
|
|
}
|
|
else {
|
|
// TODO
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::Apply( bool bRecalc, bool bPostApply)
|
|
{
|
|
// reset numero tagli nella lavorazione
|
|
int nCurrCuts = m_nCuts ;
|
|
m_nCuts = 0 ;
|
|
|
|
// verifico validità gestore DB geometrico e Id del gruppo
|
|
if ( m_pGeomDB == nullptr || ! m_pGeomDB->ExistsObj( m_nOwnerId))
|
|
return false ;
|
|
|
|
// aggiorno dati geometrici dell'utensile
|
|
if ( ! UpdateToolData()) {
|
|
m_pMchMgr->SetLastError( 2601, "Error in SawRoughing : UpdateToolData failed") ;
|
|
return false ;
|
|
}
|
|
|
|
// se modificata geometria, necessario ricalcolo
|
|
if ( ( m_nStatus & MCH_ST_GEO_MODIF) != 0)
|
|
bRecalc = true ;
|
|
|
|
// verifico se necessario continuare nell'aggiornamento
|
|
if ( ! bRecalc && ( m_nStatus == MCH_ST_OK || m_nStatus == MCH_ST_NO_POSTAPPL)) {
|
|
// confermo i percorsi di lavorazione
|
|
m_nCuts = nCurrCuts ;
|
|
string sLog = string( "SawRoughing apply skipped : status ") + ( m_nStatus == MCH_ST_OK ? "already ok" : "no postapply") ;
|
|
LOG_DBG_INFO( GetEMkLogger(), sLog.c_str()) ;
|
|
// eseguo aggiornamento assi macchina e collegamento con operazione precedente
|
|
if ( ! Update( bPostApply))
|
|
return false ;
|
|
m_nStatus = ( bPostApply ? MCH_ST_OK : MCH_ST_NO_POSTAPPL) ;
|
|
LOG_DBG_INFO( GetEMkLogger(), "Update done") ;
|
|
// esco con successo
|
|
return true ;
|
|
}
|
|
m_nStatus = MCH_ST_TO_VERIFY ;
|
|
|
|
// 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) ;
|
|
m_pGeomDB->SetStatus( nAuxId, GDB_ST_OFF) ;
|
|
bRecalc = true ;
|
|
}
|
|
// altrimenti, se chiesto ricalcolo, lo svuoto
|
|
else if ( bRecalc) {
|
|
m_pGeomDB->EmptyGroup( nAuxId) ;
|
|
}
|
|
|
|
// se necessario, preparo geometria e la inserisco sotto la geometria ausiliaria
|
|
if ( bRecalc && ! AdjustGeometry( nAuxId)) {
|
|
m_pMchMgr->SetLastError( 2602, "Error in SawRoughing : AdjustGeometry failed") ;
|
|
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) ;
|
|
|
|
// calcolo le passate
|
|
if ( m_bStraight) {
|
|
if ( ! CalculateToolPath( nAuxId, GDB_ID_NULL, nClId))
|
|
return false ;
|
|
}
|
|
else {
|
|
if ( ! CalculateCurvedToolPath( nAuxId, nClId))
|
|
return false ;
|
|
}
|
|
m_nCuts = 1 ;
|
|
|
|
// assegno ingombri dei vari percorsi di lavorazione e della lavorazione nel suo complesso
|
|
CalcAndSetBBox( nClId) ;
|
|
|
|
// eseguo aggiornamento assi macchina e collegamento con operazione precedente
|
|
if ( ! Update( bPostApply))
|
|
return false ;
|
|
|
|
// aggiorno stato della lavorazione
|
|
m_nStatus = ( bPostApply ? MCH_ST_OK : MCH_ST_NO_POSTAPPL) ;
|
|
// dichiaro successiva da aggiornare
|
|
UpdateFollowingOperationsStatus( MCH_ST_OTH_MODIF) ;
|
|
|
|
LOG_DBG_INFO( GetEMkLogger(), "SawRoughing apply done") ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::Update( bool bPostApply)
|
|
{
|
|
// verifico validità gestore DB geometrico e Id del gruppo
|
|
if ( m_pGeomDB == nullptr || ! m_pGeomDB->ExistsObj( m_nOwnerId))
|
|
return false ;
|
|
|
|
// se lavorazione vuota, esco
|
|
if ( m_nCuts == 0) {
|
|
m_pMchMgr->SetWarning( 2652, "Warning in SawRoughing : No machinable path") ;
|
|
return true ;
|
|
}
|
|
|
|
// elimino le entità CLIMB, RISE e HOME della lavorazione, potrebbero falsare i calcoli degli assi (in ogni casi vengono riaggiunte dopo)
|
|
RemoveClimbRiseHome() ;
|
|
|
|
// imposto eventuale asse bloccato da lavorazione
|
|
SetBlockedRotAxis( m_Params.m_sBlockedAxis) ;
|
|
|
|
// calcolo gli assi macchina
|
|
string sHint = ExtractHint( m_Params.m_sUserNotes) ;
|
|
if ( ! m_Params.m_sInitAngs.empty())
|
|
sHint = m_Params.m_sInitAngs ;
|
|
if ( ! CalculateAxesValues( sHint)) {
|
|
string sInfo = m_pMchMgr->GetOutstrokeInfo() ;
|
|
if ( sInfo.empty())
|
|
m_pMchMgr->SetLastError( 2611, "Error in SawRoughing : axes values not calculable") ;
|
|
else
|
|
m_pMchMgr->SetLastError( 2612, "Error in SawRoughing : outstroke ") ;
|
|
return false ;
|
|
}
|
|
|
|
// assegno estremi degli assi dei vari percorsi di lavorazione e della lavorazione nel suo complesso
|
|
CalcAndSetAxesBBox() ;
|
|
|
|
// esecuzione eventuali personalizzazioni speciali
|
|
string sSpecErr ;
|
|
if ( bPostApply && ! SpecialApply( sSpecErr)) {
|
|
if ( ! IsEmptyOrSpaces( sSpecErr))
|
|
m_pMchMgr->SetLastError( 2616, sSpecErr) ;
|
|
else
|
|
m_pMchMgr->SetLastError( 2616, "Error in SawRoughing : special apply not calculable") ;
|
|
return false ;
|
|
}
|
|
|
|
// gestione movimenti all'inizio di ogni singolo percorso di lavorazione e alla fine della lavorazione
|
|
if ( ! AdjustStartEndMovements()) {
|
|
string sInfo = m_pMchMgr->GetOutstrokeInfo() ;
|
|
if ( sInfo.empty())
|
|
m_pMchMgr->SetLastError( 2613, "Error in SawRoughing : link movements not calculable") ;
|
|
else
|
|
m_pMchMgr->SetLastError( 2614, "Error in SawRoughing : link outstroke ") ;
|
|
return false ;
|
|
}
|
|
|
|
// esecuzione eventuali personalizzazioni
|
|
string sPostErr ;
|
|
if ( bPostApply && ! PostApply( sPostErr)) {
|
|
if ( ! IsEmptyOrSpaces( sPostErr))
|
|
m_pMchMgr->SetLastError( 2615, sPostErr) ;
|
|
else
|
|
m_pMchMgr->SetLastError( 2615, "Error in SawRoughing : post apply not calculable") ;
|
|
return false ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::GetParam( int nType, bool& bVal) const
|
|
{
|
|
//switch ( nType) {
|
|
//}
|
|
bVal = false ;
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::GetParam( int nType, int& nVal) const
|
|
{
|
|
switch ( nType) {
|
|
case MPA_TYPE :
|
|
nVal = MT_SAWROUGHING ;
|
|
return true ;
|
|
case MPA_HEADSIDE :
|
|
nVal = m_Params.m_nHeadSide ;
|
|
return true ;
|
|
case MPA_STEPTYPE :
|
|
nVal = m_Params.m_nStepType ;
|
|
return true ;
|
|
case MPA_LEADLINKTYPE :
|
|
nVal = m_Params.m_nLeadLinkType ;
|
|
return true ;
|
|
case MPA_SCC :
|
|
nVal = m_Params.m_nSolCh ;
|
|
return true ;
|
|
}
|
|
nVal = 0 ;
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::GetParam( int nType, double& dVal) const
|
|
{
|
|
switch ( nType) {
|
|
case MPA_SPEED :
|
|
dVal = GetSpeed() ;
|
|
return true ;
|
|
case MPA_FEED :
|
|
dVal = GetFeed() ;
|
|
return true ;
|
|
case MPA_STARTFEED :
|
|
dVal = GetStartFeed() ;
|
|
return true ;
|
|
case MPA_ENDFEED :
|
|
dVal = GetEndFeed() ;
|
|
return true ;
|
|
case MPA_TIPFEED :
|
|
dVal = GetTipFeed() ;
|
|
return true ;
|
|
case MPA_OFFSR :
|
|
dVal =GetOffsR() ;
|
|
return true ;
|
|
case MPA_OFFSL :
|
|
dVal = GetOffsL() ;
|
|
return true ;
|
|
case MPA_STARTPOS :
|
|
dVal = m_Params.m_dStartPos ;
|
|
return true ;
|
|
case MPA_SIDESTEP :
|
|
dVal = m_Params.m_dSideStep ;
|
|
return true ;
|
|
case MPA_STEP :
|
|
dVal = m_Params.m_dStep ;
|
|
return true ;
|
|
case MPA_APPROX :
|
|
dVal = m_Params.m_dApprox ;
|
|
return true ;
|
|
case MPA_STARTADDLEN :
|
|
dVal = m_Params.m_dStartAddLen ;
|
|
return true ;
|
|
case MPA_ENDADDLEN :
|
|
dVal = m_Params.m_dEndAddLen ;
|
|
return true ;
|
|
}
|
|
dVal = 0 ;
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::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 ;
|
|
case MPA_SYSNOTES :
|
|
sVal = m_Params.m_sSysNotes ;
|
|
return true ;
|
|
case MPA_USERNOTES :
|
|
sVal = m_Params.m_sUserNotes ;
|
|
return true ;
|
|
case MPA_INITANGS :
|
|
sVal = m_Params.m_sInitAngs ;
|
|
return true ;
|
|
case MPA_BLOCKEDAXIS :
|
|
sVal = m_Params.m_sBlockedAxis ;
|
|
return true ;
|
|
}
|
|
sVal = "" ;
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
const ToolData&
|
|
SawRoughing::GetToolData( void) const
|
|
{
|
|
return m_TParams ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::UpdateToolData( void)
|
|
{
|
|
// recupero il gestore DB utensili della macchina corrente
|
|
ToolsMgr* pTMgr = m_pMchMgr->GetCurrToolsMgr() ;
|
|
if ( pTMgr == nullptr)
|
|
return false ;
|
|
// recupero l'utensile nel DB utensili (se fallisce con UUID provo con il nome)
|
|
const ToolData* pTdata = pTMgr->GetTool( m_Params.m_ToolUuid) ;
|
|
if ( pTdata == nullptr) {
|
|
pTdata = pTMgr->GetTool( m_Params.m_sToolName) ;
|
|
if ( pTdata == nullptr)
|
|
return false ;
|
|
m_Params.m_ToolUuid = m_TParams.m_Uuid ;
|
|
}
|
|
// salvo posizione TC, testa e uscita originali
|
|
string sOrigTcPos = m_TParams.m_sTcPos ;
|
|
string sOrigHead = m_TParams.m_sHead ;
|
|
int nOrigExit = m_TParams.m_nExit ;
|
|
// verifico se sono diversi (ad esclusione di nome, posizione TC, testa e uscita)
|
|
bool bChanged = ( ! SameTool( m_TParams, *pTdata, false)) ;
|
|
// aggiorno comunque i parametri
|
|
m_TParams = *pTdata ;
|
|
// se definito attrezzaggio, aggiorno i parametri che ne possono derivare
|
|
string sTcPos ; string sHead ; int nExit ;
|
|
if ( m_pMchMgr->GetCurrSetupMgr().GetToolData( m_TParams.m_sName, sTcPos, sHead, nExit)) {
|
|
if ( sOrigTcPos != sTcPos ||
|
|
sOrigHead != sHead ||
|
|
nOrigExit != nExit)
|
|
bChanged = true ;
|
|
m_TParams.m_sTcPos = sTcPos ;
|
|
m_TParams.m_sHead = sHead ;
|
|
m_TParams.m_nExit = nExit ;
|
|
}
|
|
else {
|
|
if ( sOrigTcPos != pTdata->m_sTcPos ||
|
|
sOrigHead != pTdata->m_sHead ||
|
|
nOrigExit != pTdata->m_nExit)
|
|
bChanged = true ;
|
|
}
|
|
// eventuali segnalazioni
|
|
if ( ! EqualNoCase( m_Params.m_sToolName, m_TParams.m_sName)) {
|
|
string sInfo = "Warning in SawRoughing : tool name changed (" +
|
|
m_Params.m_sToolName + "->" + m_TParams.m_sName + ")" ;
|
|
m_pMchMgr->SetWarning( 2653, sInfo) ;
|
|
m_Params.m_sToolName = m_TParams.m_sName ;
|
|
}
|
|
if ( bChanged) {
|
|
string sInfo = "Warning in SawRoughing : tool data changed (" +
|
|
m_Params.m_sToolName + ")" ;
|
|
m_pMchMgr->SetWarning( 2654, sInfo) ;
|
|
}
|
|
// se modificato, aggiusto lo stato
|
|
if ( bChanged)
|
|
m_nStatus = MCH_ST_TO_VERIFY ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::GetGeometry( SELVECTOR& vIds) const
|
|
{
|
|
// restituisco l'elenco delle entità
|
|
vIds = m_vId ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::AdjustEndPointForAxesCalc( const CamData* pCamData, Point3d& ptP) const
|
|
{
|
|
// compenso il raggio dell'utensile
|
|
ptP += pCamData->GetCorrDir() * ( m_TParams.m_dDiam / 2) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::VerifyGeometry( SelData Id, int& nSubs)
|
|
{
|
|
// ammessi : curve o superfici
|
|
|
|
// 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( pGObj) ;
|
|
if ( pCurve != nullptr) {
|
|
if ( pCurve->GetType() == CRV_COMPO)
|
|
nSubs = ::GetCurveComposite( pCurve)->GetCurveCount() ;
|
|
else
|
|
nSubs = 0 ;
|
|
}
|
|
}
|
|
// altrimenti sottocurva di composita
|
|
else {
|
|
const ICurveComposite* pCompo = GetCurveComposite( pGObj) ;
|
|
if ( pCompo != nullptr)
|
|
pCurve = pCompo->GetCurve( Id.nSub) ;
|
|
nSubs = 0 ;
|
|
}
|
|
return ( pCurve != nullptr) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
ICurve*
|
|
SawRoughing::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
|
|
SawRoughing::AdjustGeometry( int nAuxId)
|
|
{
|
|
// sgrossatura di cornici diritte : due o più curve (sezioni e guida rettilinea)
|
|
// sgrossatura di cornici curve : due curve (sezione e guida curva)
|
|
size_t nCrvCount = m_vId.size() ;
|
|
if ( nCrvCount >= 2) {
|
|
// le sezioni devono essere chiuse, piane e giacere in uno stesso piano verticale
|
|
ICURVEPOVECTOR vpSects ;
|
|
vpSects.reserve( nCrvCount - 1) ;
|
|
Vector3d vtN ;
|
|
for ( size_t i = 0 ; i < nCrvCount - 1 ; ++ i) {
|
|
vpSects.emplace_back( GetCurve( m_vId[i])) ;
|
|
if ( IsNull( vpSects.back()))
|
|
return false ;
|
|
if ( ! vpSects.back()->IsClosed())
|
|
return false ;
|
|
Plane3d plPlane ;
|
|
if ( ! vpSects.back()->IsFlat( plPlane, false, 10 * EPS_SMALL) || abs( plPlane.GetVersN().z) > EPS_SMALL)
|
|
return false ;
|
|
if ( i == 0)
|
|
vtN = plPlane.GetVersN() ;
|
|
else {
|
|
if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtN))
|
|
return false ;
|
|
}
|
|
}
|
|
// l'ultima curva è la guida
|
|
PtrOwner<ICurve> pGuide( GetCurve( m_vId[nCrvCount-1])) ;
|
|
if ( IsNull( pGuide))
|
|
return false ;
|
|
// se linea -> cornici diritte (lama verticale)
|
|
if ( pGuide->GetType() == CRV_LINE)
|
|
m_bStraight = true ;
|
|
// altrimenti curva -> cornici curve (lama orizzontale)
|
|
else {
|
|
m_bStraight = false ;
|
|
// ammessa una sola sezione
|
|
if ( nCrvCount > 2)
|
|
return false ;
|
|
// la guida deve giacere nel piano XY
|
|
Plane3d plPlane ;
|
|
if ( ! pGuide->IsFlat( plPlane, false, 10 * EPS_SMALL) || ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), Z_AX))
|
|
return false ;
|
|
// verifiche sulla curva (che trasformo in composita)
|
|
PtrOwner<ICurveComposite> pCompo ;
|
|
if ( ! pCompo.Set( ConvertCurveToComposite( Release( pGuide))))
|
|
return false ;
|
|
// converto in archi e rette
|
|
pCompo->ArcsBezierCurvesToArcsPerpExtr( LIN_TOL_MID, ANG_TOL_STD_DEG) ;
|
|
// verifiche sull'ampiezza dell'angolo al centro degli eventuali archi
|
|
VerifyArcs( pCompo) ;
|
|
// reinserisco nella curva originale
|
|
pGuide.Set( pCompo) ;
|
|
}
|
|
// deve iniziare in comune con la prima sezione ed essere ivi perpendicolare
|
|
Vector3d vtGdDir ;
|
|
if ( ! pGuide->GetStartDir( vtGdDir) || ! AreSameOrOppositeVectorApprox( vtN, vtGdDir))
|
|
return false ;
|
|
Point3d ptStStart, ptGdStart ;
|
|
if ( ! vpSects[0]->GetStartPoint( ptStStart) ||
|
|
! pGuide->GetStartPoint( ptGdStart) ||
|
|
( ptGdStart - ptStStart) * vtGdDir > 10 * EPS_SMALL)
|
|
return false ;
|
|
// creo sottogruppo per le sezioni con riferimento avente
|
|
// l'origine nel punto di inizio della guida e la Z opposta alla direzione della guida
|
|
Frame3d frSect ;
|
|
if ( ! frSect.Set( ptGdStart, - vtGdDir))
|
|
return false ;
|
|
int nGrpSectId = m_pGeomDB->AddGroup( GDB_ID_NULL, nAuxId, frSect) ;
|
|
if ( nGrpSectId == GDB_ID_NULL)
|
|
return false ;
|
|
m_pGeomDB->SetName( nGrpSectId, MCH_SECTION) ;
|
|
// inserisco le sezioni e ne sistemo il senso di rotazione come CCW
|
|
for ( auto& pSect : vpSects) {
|
|
pSect->ToLoc( frSect) ;
|
|
double dArea ;
|
|
pSect->GetAreaXY( dArea) ;
|
|
if ( dArea < 0)
|
|
pSect->Invert() ;
|
|
if ( m_pGeomDB->AddGeoObj( GDB_ID_NULL, nGrpSectId, ::Release( pSect)) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// creo sottogruppo per la guida
|
|
// inserisco la guida nel gruppo ausiliario
|
|
int nGrpGuideId = m_pGeomDB->AddGroup( GDB_ID_NULL, nAuxId, Frame3d()) ;
|
|
if ( nGrpGuideId == GDB_ID_NULL)
|
|
return false ;
|
|
m_pGeomDB->SetName( nGrpGuideId, MCH_GUIDE) ;
|
|
if ( m_pGeomDB->AddGeoObj( GDB_ID_NULL, nGrpGuideId, ::Release( pGuide)) == GDB_ID_NULL)
|
|
return false ;
|
|
return true ;
|
|
}
|
|
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::CalculateToolPath( int nAuxId, int nPvId, int nClId)
|
|
{
|
|
// Recupero ed elaboro le sezioni
|
|
ICurve* pSect ;
|
|
int nSectGrpId = m_pGeomDB->GetFirstNameInGroup( nAuxId, MCH_SECTION) ;
|
|
if ( ! CalculateSection( nSectGrpId, pSect))
|
|
return false ;
|
|
PtrOwner<ICurve> pCrv( pSect) ;
|
|
// recupero il riferimento globale delle sezioni
|
|
Frame3d frSect ;
|
|
m_pGeomDB->GetGroupGlobFrame( nSectGrpId, frSect) ;
|
|
// recupero il box globale delle sezioni
|
|
BBox3d b3Sect ;
|
|
m_pGeomDB->GetGlobalBBox( nSectGrpId, b3Sect) ;
|
|
|
|
// Recupero ed elaboro la linea guida
|
|
Point3d ptGdStart, ptGdEnd ;
|
|
Vector3d vtGdDir ;
|
|
int nGuideId = m_pGeomDB->GetFirstInGroup( m_pGeomDB->GetFirstNameInGroup( nAuxId, MCH_GUIDE)) ;
|
|
if ( ! CalculateGuideLine( nGuideId, b3Sect, ptGdStart, ptGdEnd, vtGdDir))
|
|
return false ;
|
|
// recupero il box globale della linea guida
|
|
BBox3d b3Guide ;
|
|
m_pGeomDB->GetGlobalBBox( nGuideId, b3Guide) ;
|
|
|
|
// determino l'ingombro della curva risultante in locale
|
|
BBox3d b3Crv ;
|
|
pCrv->GetLocalBBox( b3Crv) ;
|
|
|
|
// recupero il box del grezzo in globale e lo porto in locale alla sezione
|
|
BBox3d b3Test ;
|
|
b3Test.Add( b3Sect) ;
|
|
b3Test.Add( b3Guide) ;
|
|
BBox3d b3Raw ;
|
|
if ( ! GetRawGlobBox( m_nPhase, b3Test, 10 * EPS_SMALL, b3Raw) || b3Raw.IsEmpty()) {
|
|
m_pMchMgr->SetLastError( 2703, "Error in SawFinishing : Empty RawBox") ;
|
|
return false ;
|
|
}
|
|
BBox3d b3RawLoc = b3Raw ;
|
|
b3RawLoc.ToLoc( frSect) ;
|
|
|
|
// valuto l'espressione dell'affondamento
|
|
ExeLuaSetGlobNumVar( "TH", 0) ;
|
|
ExeLuaSetGlobNumVar( "RB", b3Raw.GetMax().z - b3Raw.GetMin().z) ;
|
|
double dDepth ;
|
|
if ( ! ExeLuaEvalNumExpr( m_Params.m_sDepth, &dDepth)) {
|
|
m_pMchMgr->SetLastError( 2607, "Error in SawRoughing : Depth not computable") ;
|
|
return false ;
|
|
}
|
|
// confronto con la massima lavorazione della lama
|
|
double dMaxDepth = min( dDepth, m_TParams.m_dMaxMat) ;
|
|
|
|
// Determino versori fresa e correzione
|
|
Vector3d vtTool, vtCorr ;
|
|
if ( ! CalculateToolAndCorrVersors( vtGdDir, m_Params.m_nHeadSide, vtTool, vtCorr)) {
|
|
m_pMchMgr->SetLastError( 2608, "Error in SawRoughing : CalculateToolAndCorrVersors") ;
|
|
return false ;
|
|
}
|
|
|
|
// Imposto dati comuni
|
|
SetToolDir( vtTool) ;
|
|
SetCorrAuxDir( vtCorr) ;
|
|
|
|
// se richiesta anteprima
|
|
if ( nPvId != GDB_ID_NULL) {
|
|
// creo gruppo per geometria di anteprima del percorso
|
|
int nPxId = m_pGeomDB->AddGroup( GDB_ID_NULL, nPvId, Frame3d()) ;
|
|
if ( nPxId == GDB_ID_NULL)
|
|
return false ;
|
|
m_pGeomDB->SetName( nPxId, MCH_PATH + "1_1") ;
|
|
m_pGeomDB->SetMaterial( nPxId, GREEN) ;
|
|
// creo l'anteprima del percorso
|
|
if ( ! GeneratePreView( nPxId, pSect, frSect, Dist( ptGdStart, ptGdEnd), vtGdDir, b3Raw))
|
|
return false ;
|
|
}
|
|
|
|
// se richiesta lavorazione
|
|
if ( nClId != GDB_ID_NULL) {
|
|
// creo gruppo per geometria di lavorazione
|
|
int nPxId = m_pGeomDB->AddGroup( GDB_ID_NULL, nClId, Frame3d()) ;
|
|
if ( nPxId == GDB_ID_NULL)
|
|
return false ;
|
|
m_pGeomDB->SetName( nPxId, MCH_PATH + "1_1") ;
|
|
m_pGeomDB->SetMaterial( nPxId, BLUE) ;
|
|
|
|
SetPathId( nPxId) ;
|
|
|
|
// assegno il vettore estrazione al gruppo del percorso
|
|
m_pGeomDB->SetInfo( nPxId, KEY_EXTR, vtTool) ;
|
|
|
|
// Determino eventuali pareti verticali ( sono in senso decrescente di X)
|
|
DBLVECTOR vdVr ;
|
|
DBLVECTOR vdVrDelta ;
|
|
double dPrevX = INFINITO ;
|
|
const ICurveComposite* pCompo = GetCurveComposite( pCrv) ;
|
|
if ( pCompo != nullptr) {
|
|
const ICurve* pSimpCrv = pCompo->GetFirstCurve() ;
|
|
while ( pSimpCrv != nullptr) {
|
|
Point3d ptStart, ptEnd ;
|
|
pSimpCrv->GetStartPoint( ptStart) ;
|
|
pSimpCrv->GetEndPoint( ptEnd) ;
|
|
if ( abs( ptEnd.x - ptStart.x) < EPS_SMALL) {
|
|
double dX = ( ptEnd.x + ptStart.x) / 2 ;
|
|
if ( dX < dPrevX - EPS_SMALL) {
|
|
vdVr.push_back( dX) ;
|
|
vdVrDelta.push_back( ptEnd.y - ptStart.y) ;
|
|
dPrevX = dX ;
|
|
}
|
|
}
|
|
pSimpCrv = pCompo->GetNextCurve() ;
|
|
}
|
|
}
|
|
else {
|
|
Point3d ptStart, ptEnd ;
|
|
pCrv->GetStartPoint( ptStart) ;
|
|
pCrv->GetEndPoint( ptEnd) ;
|
|
if ( abs( ptEnd.x - ptStart.x) < EPS_SMALL) {
|
|
vdVr.push_back( ( ptEnd.x + ptStart.x) / 2) ;
|
|
vdVrDelta.push_back( ptEnd.y - ptStart.y) ;
|
|
}
|
|
}
|
|
|
|
// Determino le posizioni particolari
|
|
DBLVECTOR vdPp ;
|
|
DBLVECTOR vdPDelta ;
|
|
size_t nVr = vdVr.size() ;
|
|
double dSawOffs = 0.5 * m_TParams.m_dThick ;
|
|
double dFinOffs = m_Params.m_dSideStep - dSawOffs ;
|
|
// calcolo dell'inizio ( Xmin)
|
|
double dRawMin = b3RawLoc.GetMin().x ; // inizio grezzo
|
|
double dStart = max( dRawMin + dFinOffs, b3Crv.GetMin().x) ; // inizio con aletta prima
|
|
double dStartDelta = 0 ;
|
|
if ( nVr > 0 &&
|
|
vdVr[nVr-1] < dStart + EPS_SMALL &&
|
|
vdVr[nVr-1] + dSawOffs > dRawMin + EPS_SMALL) {
|
|
dStart = vdVr[nVr-1] ; // correzione per parete verticale
|
|
dStartDelta = vdVrDelta[nVr-1] ;
|
|
}
|
|
// calcolo della fine ( Xmax)
|
|
double dRawMax = b3RawLoc.GetMax().x ; // fine grezzo
|
|
double dEnd = min( dRawMax - dFinOffs, b3Crv.GetMax().x) ; // fine con aletta dopo
|
|
double dEndDelta = 0 ;
|
|
if ( nVr > 0 &&
|
|
vdVr[0] > dEnd - EPS_SMALL &&
|
|
vdVr[0] - dSawOffs < dRawMax - EPS_SMALL) {
|
|
dEnd = vdVr[0] ; // correzione per parete verticale
|
|
dEndDelta = vdVrDelta[0] ;
|
|
}
|
|
// assegno le posizioni particolari ( ordinate in senso decrescente)
|
|
vdPp.push_back( dEnd) ;
|
|
vdPDelta.push_back( dEndDelta) ;
|
|
for ( size_t i = 0 ; i < nVr ; ++ i) {
|
|
if ( vdVr[i] > dStart + EPS_SMALL && vdVr[i] < dEnd - EPS_SMALL) {
|
|
vdPp.push_back( vdVr[i]) ;
|
|
vdPDelta.push_back( vdVrDelta[i]) ;
|
|
}
|
|
}
|
|
vdPp.push_back( dStart) ;
|
|
vdPDelta.push_back( dStartDelta) ;
|
|
|
|
// Ciclo sugli intervalli tra le posizioni particolari per generare le passate
|
|
int nCount = 0 ;
|
|
for ( int j = 1 ; j < int( vdPp.size()) ; ++ j) {
|
|
double dXmax = vdPp[j-1] ;
|
|
double dXmin = vdPp[j] ;
|
|
|
|
if ( m_Params.m_nStepType == SAWROU_ST_ZCONST) {
|
|
// le pareti verticali vanno trattate nell'intervallo della quota più bassa
|
|
bool bIncludeMax = ( vdPDelta[j-1] < EPS_SMALL) ;
|
|
bool bIncludeMin = ( vdPDelta[j] > - EPS_SMALL) ;
|
|
// verifico se devo trattare l'estremo a dXmax singolarmente
|
|
if ( j == 1 && ! bIncludeMax) {
|
|
if ( ! CalculateZConstCut( pCrv, dXmax, dXmax, true, false, ptGdStart, ptGdEnd, vtGdDir, frSect, b3Raw, dMaxDepth,
|
|
true, false, nCount))
|
|
return false ;
|
|
}
|
|
// tratto l'intervallo
|
|
bool bFirstInterval = ( j == 1) && bIncludeMax ;
|
|
bool bLastInterval = ( j == vdPp.size() - 1) && bIncludeMin ;
|
|
if ( ! CalculateZConstCut( pCrv, dXmin, dXmax, bIncludeMax, bIncludeMin, ptGdStart, ptGdEnd, vtGdDir, frSect, b3Raw, dMaxDepth,
|
|
bFirstInterval, bLastInterval, nCount))
|
|
return false ;
|
|
// verifico se devo trattare l'estremo a dXmin singolarmente
|
|
if ( j == vdPp.size() - 1 && ! bIncludeMin) {
|
|
if ( ! CalculateZConstCut( pCrv, dXmin, dXmin, false, true, ptGdStart, ptGdEnd, vtGdDir, frSect, b3Raw, dMaxDepth,
|
|
false, true, nCount))
|
|
return false ;
|
|
}
|
|
}
|
|
else {
|
|
double dLargh = dXmax - dXmin ;
|
|
double dStep = max( m_Params.m_dSideStep, 10 * EPS_SMALL) ;
|
|
int nStep = max( 1, static_cast<int>( ceil( dLargh / dStep))) ;
|
|
dStep = dLargh / nStep ;
|
|
double dSectYMin = b3Crv.GetMin().y ;
|
|
double dSectYMax = b3Crv.GetMax().y ;
|
|
|
|
int nStart = ( j == 1 ? 0 : 1) ;
|
|
for ( int i = nStart ; i <= nStep ; ++ i) {
|
|
// flag per primo e ultimo taglio
|
|
bool bFirst = ( j == 1 && i == 0) ;
|
|
bool bLast = ( j == vdPp.size() - 1 && i == nStep) ;
|
|
// determino l'ascissa della prima intersezione
|
|
double dX = dXmax - i * dStep ;
|
|
// determino l'ordinata della prima intersezione
|
|
double dY ;
|
|
if ( ! GetHeightOnSection( pCrv, dX, dSectYMin, dSectYMax, dY))
|
|
return false ;
|
|
// estremi del taglio
|
|
Vector3d vtMove = dX * frSect.VersX() + dY * frSect.VersY() - 0.5 * m_TParams.m_dThick * vtTool ;
|
|
Point3d ptStart = ptGdStart + vtMove ;
|
|
Point3d ptEnd = ptGdEnd + vtMove ;
|
|
// adatto la guida corrente al grezzo
|
|
AdaptGuideLineToRaw( ptStart, ptEnd, vtGdDir, b3Raw) ;
|
|
// determino l'elevazione del taglio
|
|
Vector3d vtThick = vtTool * m_TParams.m_dThick ;
|
|
double dElev, dElev2 ;
|
|
if ( ! GetElevation( m_nPhase, ptStart, ptEnd, vtCorr, dElev) ||
|
|
! GetElevation( m_nPhase, ptStart + vtThick, ptEnd + vtThick, vtCorr, dElev2) ) {
|
|
m_pMchMgr->SetLastError( 2609, "Error in SawRoughing : GetElevation") ;
|
|
return false ;
|
|
}
|
|
dElev = max( dElev, dElev2) ;
|
|
// se elevazione nulla, verifico col massimo del grezzo
|
|
if ( dElev < EPS_SMALL)
|
|
dElev = max( 0., b3Raw.GetMax().z - ptStart.z) ;
|
|
// la confronto con il massimo affondamento e con la massima lavorazione della lama
|
|
if ( dElev > dMaxDepth) {
|
|
ptStart += Vector3d( 0, 0, dElev - dMaxDepth) ;
|
|
ptEnd += Vector3d( 0, 0, dElev - dMaxDepth) ;
|
|
dElev = dMaxDepth ;
|
|
}
|
|
// esecuzione del taglio
|
|
if ( m_Params.m_nStepType != SAWROU_ST_ZIGZAG) {
|
|
if ( ! CalculateOneWayCut( ptStart, ptEnd, vtGdDir, vtTool, vtCorr, dElev, bFirst, bLast, b3Raw))
|
|
return false ;
|
|
}
|
|
else {
|
|
if ( ! CalculateZigZagCut( ptStart, ptEnd, vtGdDir, vtTool, vtCorr, dElev, bFirst, bLast, nCount, b3Raw))
|
|
return false ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::CalculateCurvedToolPath( int nAuxId, int nClId)
|
|
{
|
|
// Ruoto di 90 deg la curva sezione nel suo piano
|
|
int nSectGrpId = m_pGeomDB->GetFirstNameInGroup( nAuxId, MCH_SECTION) ;
|
|
int nCrvId = ExeGetFirstInGroup( nSectGrpId) ;
|
|
m_pGeomDB->Rotate( nCrvId, ORIG, Z_AX, 90.0) ;
|
|
// Recupero ed elaboro la sezione
|
|
ICurve* pSect ;
|
|
if ( ! CalculateSection( nSectGrpId, pSect))
|
|
return false ;
|
|
// Contro rotazione della curva
|
|
m_pGeomDB->Rotate( nCrvId, ORIG, Z_AX, -90.0) ;
|
|
PtrOwner<ICurve> pCrv( pSect) ;
|
|
// recupero il riferimento globale della sezione
|
|
Frame3d frSect ;
|
|
m_pGeomDB->GetGroupGlobFrame( nSectGrpId, frSect) ;
|
|
// recupero il box globale della sezione
|
|
BBox3d b3Sect ;
|
|
m_pGeomDB->GetGlobalBBox( nSectGrpId, b3Sect) ;
|
|
|
|
// Recupero ed elaboro la linea guida
|
|
int nGuideId = m_pGeomDB->GetFirstInGroup( m_pGeomDB->GetFirstNameInGroup( nAuxId, MCH_GUIDE)) ;
|
|
// recupero la linea guida
|
|
ICurve* pGuide = ::GetCurve( m_pGeomDB->GetGeoObj( nGuideId)) ;
|
|
if ( pGuide == nullptr)
|
|
return false ;
|
|
// recupero il box globale della linea guida
|
|
BBox3d b3Guide ;
|
|
m_pGeomDB->GetGlobalBBox( nGuideId, b3Guide) ;
|
|
|
|
// recupero il box del grezzo in globale e lo porto in locale alla sezione
|
|
BBox3d b3Test ;
|
|
b3Test.Add( b3Sect) ;
|
|
b3Test.Add( b3Guide) ;
|
|
BBox3d b3Raw ;
|
|
if ( ! GetRawGlobBox( m_nPhase, b3Test, 10 * EPS_SMALL, b3Raw) || b3Raw.IsEmpty()) {
|
|
m_pMchMgr->SetLastError( 2703, "Error in SawFinishing : Empty RawBox") ;
|
|
return false ;
|
|
}
|
|
BBox3d b3RawLoc = b3Raw ;
|
|
b3RawLoc.ToLoc( frSect) ;
|
|
|
|
// valuto l'espressione dell'affondamento
|
|
ExeLuaSetGlobNumVar( "TH", 0) ;
|
|
ExeLuaSetGlobNumVar( "RB", b3Raw.GetMax().z - b3Raw.GetMin().z) ;
|
|
double dDepth ;
|
|
if ( ! ExeLuaEvalNumExpr( m_Params.m_sDepth, &dDepth)) {
|
|
m_pMchMgr->SetLastError( 2607, "Error in SawRoughing : Depth not computable") ;
|
|
return false ;
|
|
}
|
|
|
|
// creo gruppo per geometria di lavorazione
|
|
int nPxId = m_pGeomDB->AddGroup( GDB_ID_NULL, nClId, Frame3d()) ;
|
|
if ( nPxId == GDB_ID_NULL)
|
|
return false ;
|
|
m_pGeomDB->SetName( nPxId, MCH_PATH + "1_1") ;
|
|
m_pGeomDB->SetMaterial( nPxId, BLUE) ;
|
|
|
|
// Ripristino orientamento sezione con controrotazione
|
|
pCrv->Rotate( ORIG, Z_AX, -90.0) ;
|
|
|
|
// determino l'ingombro della curva risultante in locale
|
|
BBox3d b3Crv ;
|
|
pCrv->GetLocalBBox( b3Crv) ;
|
|
|
|
// Determino eventuali pareti orizzontali (in senso decrescente di Y)
|
|
DBLVECTOR vdVr ;
|
|
double dPrevY = INFINITO ;
|
|
const ICurveComposite* pCompo = GetCurveComposite( pCrv) ;
|
|
if ( pCompo != nullptr) {
|
|
const ICurve* pSimpCrv = pCompo->GetLastCurve() ;
|
|
while ( pSimpCrv != nullptr) {
|
|
Point3d ptStart, ptEnd ;
|
|
pSimpCrv->GetStartPoint( ptStart) ;
|
|
pSimpCrv->GetEndPoint( ptEnd) ;
|
|
if ( abs( ptEnd.y - ptStart.y) < EPS_SMALL) {
|
|
double dY = ( ptEnd.y + ptStart.y) / 2 ;
|
|
if ( dY < dPrevY - EPS_SMALL) {
|
|
vdVr.push_back( dY) ;
|
|
dPrevY = dY ;
|
|
}
|
|
}
|
|
pSimpCrv = pCompo->GetPrevCurve() ;
|
|
}
|
|
}
|
|
else {
|
|
Point3d ptStart, ptEnd ;
|
|
pCrv->GetStartPoint( ptStart) ;
|
|
pCrv->GetEndPoint( ptEnd) ;
|
|
if ( abs( ptEnd.y - ptStart.y) < EPS_SMALL)
|
|
vdVr.push_back( ( ptEnd.y + ptStart.y) / 2) ;
|
|
}
|
|
|
|
// Determino le posizioni particolari
|
|
DBLVECTOR vdPp ;
|
|
size_t nVr = vdVr.size() ;
|
|
double dSawOffs = 0.5 * m_TParams.m_dThick ;
|
|
double dFinOffs = m_Params.m_dSideStep - dSawOffs ;
|
|
// calcolo dell'inizio (Ymax)
|
|
double dRawMax = b3RawLoc.GetMax().y ; // inizio grezzo
|
|
double dStart = min( dRawMax - dFinOffs, b3Crv.GetMax().y) ; // inizio con aletta prima
|
|
if ( nVr > 0 &&
|
|
vdVr[0] > dStart + EPS_SMALL &&
|
|
vdVr[0] - dSawOffs < dRawMax - EPS_SMALL)
|
|
dStart = vdVr[0] ; // correzione per parete verticale
|
|
// calcolo della fine (Ymin)
|
|
double dRawMin = b3RawLoc.GetMin().y ; // fine grezzo
|
|
double dEnd = max( dRawMin + dFinOffs, b3Crv.GetMin().y) ; // fine con aletta dopo
|
|
if ( nVr > 0 &&
|
|
vdVr[nVr-1] < dEnd - EPS_SMALL &&
|
|
vdVr[nVr-1] + dSawOffs > dRawMax + EPS_SMALL)
|
|
dEnd = vdVr[nVr-1] ; // correzione per parete verticale
|
|
// assegno le posizioni particolari (ordinate in senso decrescente)
|
|
vdPp.push_back( dStart) ;
|
|
for ( size_t i = 0 ; i < nVr ; ++ i) {
|
|
if ( vdVr[i] < dStart - EPS_SMALL && vdVr[i] > dEnd + EPS_SMALL)
|
|
vdPp.push_back( vdVr[i]) ;
|
|
}
|
|
vdPp.push_back( dEnd) ;
|
|
|
|
// Determino versori fresa e correzione
|
|
Vector3d vtTool = Z_AX ;
|
|
|
|
// Imposto dati comuni
|
|
SetPathId( nPxId) ;
|
|
SetToolDir( vtTool) ;
|
|
|
|
// assegno il vettore estrazione al gruppo del percorso
|
|
m_pGeomDB->SetInfo( nPxId, KEY_EXTR, vtTool) ;
|
|
|
|
// Ciclo sugli intervalli tra le posizioni particolari per generare le passate
|
|
int nCount = 0 ;
|
|
for ( size_t j = 0 ; j < vdPp.size() ; ++ j) {
|
|
double dYmax = ( j > 0 ? vdPp[j-1] : vdPp[0]) ;
|
|
double dYmin = vdPp[j] ;
|
|
double dLargh = dYmax - dYmin ;
|
|
double dStep = max( m_Params.m_dSideStep, 10 * EPS_SMALL) ;
|
|
int nStep = max( 1, static_cast<int>( ceil( dLargh / dStep))) ;
|
|
dStep = dLargh / nStep ;
|
|
double dSectXMin = b3Crv.GetMin().x ;
|
|
double dSectXMax = b3Crv.GetMax().x ;
|
|
for ( int i = 1 ; i <= nStep ; ++ i) {
|
|
// flag per primo e ultimo taglio
|
|
bool bFirst = ( j == 0 && i == 1) ;
|
|
bool bLast = ( j == vdPp.size() -1 && i == nStep) ;
|
|
// determino l'ordinata della prima intersezione
|
|
double dY = dYmax - i * dStep ;
|
|
// determino l'ascissa della prima intersezione
|
|
double dX ;
|
|
if ( ! GetWidthOnSection( pCrv, dY, dSectXMin, dSectXMax, dX))
|
|
return false ;
|
|
// creo la curva di taglio
|
|
OffsetCurve OffsCrv ;
|
|
OffsCrv.Make( pGuide, dX, ICurve::OFF_FILLET) ;
|
|
PtrOwner<ICurveComposite> pCut ;
|
|
if ( ! pCut.Set( ConvertCurveToComposite( OffsCrv.GetLongerCurve())))
|
|
return false ;
|
|
VerifyArcs( pCut) ;
|
|
Vector3d vtMove = ( dY - m_TParams.m_dThick / 2) * Z_AX ;
|
|
pCut->Translate( vtMove) ;
|
|
// ne determino la massima elevazione
|
|
double dElev = 0 ;
|
|
CalculateSideElevation( pCut, dElev) ;
|
|
// la confronto con il massimo affondamento e con la massima lavorazione della lama
|
|
double dMaxDepth = min( dDepth, m_TParams.m_dMaxMat) ;
|
|
if ( dElev > dMaxDepth) {
|
|
double dOffs = dElev - dMaxDepth ;
|
|
pCut->SimpleOffset( dOffs) ;
|
|
dElev = dMaxDepth ;
|
|
}
|
|
else
|
|
pCut->SimpleOffset( SAWRF_OFFS, ICurve::OFF_FORCE_OPEN) ;
|
|
// esecuzione del taglio (per ora solo ZigZag)
|
|
if ( ! CalculateCurvedZigZagCut( pCut, vtTool, dElev, bFirst, bLast, nCount))
|
|
return false ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::CalculateSection( int nSectGrpId, ICurve*& pSect)
|
|
{
|
|
// recupero le sezioni
|
|
ICURVEPVECTOR vpSects ;
|
|
int nSectId = m_pGeomDB->GetFirstInGroup( nSectGrpId) ;
|
|
while ( nSectId != GDB_ID_NULL) {
|
|
// recupero il puntatore alla curva
|
|
vpSects.emplace_back( ::GetCurve( m_pGeomDB->GetGeoObj( nSectId))) ;
|
|
if ( vpSects.back() == nullptr)
|
|
return false ;
|
|
// passo alla successiva
|
|
nSectId = m_pGeomDB->GetNext( nSectId) ;
|
|
}
|
|
|
|
// elimino eventuali sottosquadra
|
|
ICURVEPOVECTOR vpNucCrvs ;
|
|
vpNucCrvs.reserve( vpSects.size()) ;
|
|
for ( const auto& pSect : vpSects) {
|
|
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
|
|
if ( IsNull( pCrvCompo) ||
|
|
! pCrvCompo->AddCurve( *pSect) ||
|
|
! pCrvCompo->RemoveUndercutOnY( LIN_TOL_STD, ANG_TOL_STD_DEG))
|
|
return false ;
|
|
vpNucCrvs.emplace_back( Release( pCrvCompo)) ;
|
|
}
|
|
|
|
// calcolo ordinamento delle curve secondo la X decrescente
|
|
typedef pair<int,double> INDASC ; // coppia indice, ascissa
|
|
typedef vector<INDASC> INDASCVECTOR ; // vettore di coppie indice, ascissa
|
|
INDASCVECTOR vIAsc ;
|
|
vIAsc.reserve( vpNucCrvs.size()) ;
|
|
for ( int i = 0 ; i < int( vpNucCrvs.size()) ; ++ i) {
|
|
Point3d ptStart ;
|
|
if ( ! vpNucCrvs[i]->GetStartPoint( ptStart))
|
|
return false ;
|
|
vIAsc.emplace_back( i, ptStart.x) ;
|
|
}
|
|
sort( vIAsc.begin(), vIAsc.end(), []( const INDASC& a, const INDASC& b)
|
|
{ return a.second > b.second ; }) ;
|
|
|
|
// unisco le diverse curve (ora aperte) in un unico profilo
|
|
PtrOwner<ICurveComposite> pCurve( CreateCurveComposite()) ;
|
|
if ( IsNull( pCurve))
|
|
return false ;
|
|
bool bFirst = true ;
|
|
for ( int i = 0 ; i < int( vpNucCrvs.size()) ; ++ i) {
|
|
if ( ! bFirst) {
|
|
Point3d ptStart ;
|
|
if ( ! vpNucCrvs[vIAsc[i].first]->GetStartPoint( ptStart) ||
|
|
! pCurve->AddLine( ptStart))
|
|
return false ;
|
|
}
|
|
if ( ! pCurve->AddCurve( Release( vpNucCrvs[vIAsc[i].first])))
|
|
return false ;
|
|
bFirst = false ;
|
|
}
|
|
|
|
// offset radiale delle sezioni per il sovramateriale
|
|
double dOffsR = GetOffsR() ;
|
|
PtrOwner<ICurve> pOvrCrv ;
|
|
OffsetCurve OffsCrv ;
|
|
OffsCrv.Make( pCurve, dOffsR, ICurve::OFF_FILLET) ;
|
|
pOvrCrv.Set( OffsCrv.GetLongerCurve()) ;
|
|
if ( IsNull( pOvrCrv)) {
|
|
m_pMchMgr->SetLastError( 2605, "Error in SawRoughing : OffsetCurve") ;
|
|
return false ;
|
|
}
|
|
|
|
// ricavo dalla sezione la curva per centro in basso della lama
|
|
double dOffsX = 0.5 * m_TParams.m_dThick + GetOffsL() - GetOffsR() ;
|
|
PtrOwner<ICurve> pCrv ;
|
|
OffsetCurveOnX OffsCrvX ;
|
|
OffsCrvX.Make( pOvrCrv, dOffsX) ;
|
|
pCrv.Set( OffsCrvX.GetLongerCurve()) ;
|
|
if ( IsNull( pCrv)) {
|
|
m_pMchMgr->SetLastError( 2606, "Error in SawRoughing : OffsetCurveOnX") ;
|
|
return false ;
|
|
}
|
|
|
|
// determino l'intervallo di curva da conservare
|
|
if ( ! TrimSection( pCrv)) {
|
|
m_pMchMgr->SetLastError( 2610, "Error in SawRoughing : TrimSection failed") ;
|
|
return false ;
|
|
}
|
|
|
|
pSect = Release( pCrv) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::TrimSection( ICurve* pCrv)
|
|
{
|
|
// se parametri di accorciamento iniziale e finale sono nulli, non faccio alcunché
|
|
if ( m_Params.m_dStartAddLen > - EPS_SMALL && m_Params.m_dEndAddLen > -EPS_SMALL)
|
|
return true ;
|
|
|
|
// box della sezione in locale
|
|
BBox3d b3Crv ;
|
|
pCrv->GetBBox( Frame3d(), b3Crv) ;
|
|
|
|
// riduco gli estremi in X
|
|
Point3d ptMin = b3Crv.GetMin() ;
|
|
Point3d ptMax = b3Crv.GetMax() ;
|
|
ptMin.x -= m_Params.m_dStartAddLen ;
|
|
ptMax.x += m_Params.m_dEndAddLen ;
|
|
double dDimX = ptMax.x - ptMin.x ;
|
|
double dDimY = ptMax.y - ptMin.y + 100 * EPS_SMALL ;
|
|
|
|
// regione del box nel piano XY
|
|
PtrOwner<ISurfFlatRegion> pSfr( GetSurfFlatRegionRectangle( dDimX, dDimY)) ;
|
|
if ( IsNull( pSfr))
|
|
return false ;
|
|
pSfr->Translate( Vector3d( ptMin.x, ptMin.y - 50 * EPS_SMALL, ptMin.z)) ;
|
|
|
|
// calcolo la classificazione della curva rispetto alla regione
|
|
CRVCVECTOR ccClass ;
|
|
if ( ! pSfr->GetCurveClassification( *pCrv, EPS_SMALL, ccClass))
|
|
return false ;
|
|
|
|
// determino l'intervallo di curva da conservare
|
|
Intervals inOk ;
|
|
for ( auto& ccOne : ccClass) {
|
|
if ( ccOne.nClass == CRVC_IN || ccOne.nClass == CRVC_ON_P || ccOne.nClass == CRVC_ON_M)
|
|
inOk.Add( ccOne.dParS, ccOne.dParE) ;
|
|
}
|
|
|
|
// eseguo trim
|
|
double dUmin, dUmax ;
|
|
if ( ! inOk.GetMinMax( dUmin, dUmax))
|
|
return false ;
|
|
return ( pCrv->TrimEndAtParam( dUmax) && pCrv->TrimStartAtParam( dUmin)) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::CalculateGuideLine( int nGuideId, const BBox3d& b3Sect, Point3d& ptGdStart, Point3d& ptGdEnd, Vector3d& vtGdDir)
|
|
{
|
|
// recupero la linea guida
|
|
ICurve* pGuide = ::GetCurve( m_pGeomDB->GetGeoObj( nGuideId)) ;
|
|
if ( pGuide == nullptr)
|
|
return false ;
|
|
// recupero gli estremi della linea guida
|
|
pGuide->GetStartPoint( ptGdStart) ;
|
|
pGuide->GetEndPoint( ptGdEnd) ;
|
|
// recupero la direzione della linea guida
|
|
pGuide->GetStartDir( vtGdDir) ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::AdaptGuideLineToRaw( Point3d& ptGdStart, Point3d& ptGdEnd, const Vector3d& vtGdDir, const BBox3d& b3Raw) const
|
|
{
|
|
// se il tipo di collegamento non richiede allungamento devo solo verificare che non ci siano parti nel vuoto
|
|
if ( m_Params.m_nLeadLinkType == SAWROU_LL_INT) {
|
|
// se guida allineata con asse
|
|
if ( AreSameVectorApprox( vtGdDir, X_AX)) {
|
|
ptGdStart.x = max( b3Raw.GetMin().x, ptGdStart.x) ;
|
|
ptGdEnd.x = min( b3Raw.GetMax().x, ptGdEnd.x) ;
|
|
}
|
|
else if ( AreOppositeVectorApprox( vtGdDir, X_AX)) {
|
|
ptGdStart.x = min( b3Raw.GetMax().x, ptGdStart.x) ;
|
|
ptGdEnd.x = max( b3Raw.GetMin().x, ptGdEnd.x) ;
|
|
}
|
|
else if ( AreSameVectorApprox( vtGdDir, Y_AX)) {
|
|
ptGdStart.y = max( b3Raw.GetMin().y, ptGdStart.y) ;
|
|
ptGdEnd.y = min( b3Raw.GetMax().y, ptGdEnd.y) ;
|
|
}
|
|
else if ( AreOppositeVectorApprox( vtGdDir, Y_AX)) {
|
|
ptGdStart.y = min( b3Raw.GetMax().y, ptGdStart.y) ;
|
|
ptGdEnd.y = max( b3Raw.GetMin().y, ptGdEnd.y) ;
|
|
}
|
|
// se direzione generica
|
|
else {
|
|
INTDBLVECTOR vInters ;
|
|
IntersLineBox( ptGdStart, ptGdEnd, b3Raw, vInters, true) ;
|
|
if ( vInters.size() != 2)
|
|
return false ;
|
|
ptGdEnd = ptGdStart + vtGdDir * vInters[1].second ;
|
|
ptGdStart = ptGdStart + vtGdDir * vInters[0].second ;
|
|
}
|
|
}
|
|
|
|
// se richiesto allungamento fino al bordo del grezzo
|
|
else {
|
|
// se guida allineata con asse
|
|
if ( AreSameVectorApprox( vtGdDir, X_AX)) {
|
|
ptGdStart.x = b3Raw.GetMin().x ;
|
|
ptGdEnd.x = b3Raw.GetMax().x ;
|
|
}
|
|
else if ( AreOppositeVectorApprox( vtGdDir, X_AX)) {
|
|
ptGdStart.x = b3Raw.GetMax().x ;
|
|
ptGdEnd.x = b3Raw.GetMin().x ;
|
|
}
|
|
else if ( AreSameVectorApprox( vtGdDir, Y_AX)) {
|
|
ptGdStart.y = b3Raw.GetMin().y ;
|
|
ptGdEnd.y = b3Raw.GetMax().y ;
|
|
}
|
|
else if ( AreOppositeVectorApprox( vtGdDir, Y_AX)) {
|
|
ptGdStart.y = b3Raw.GetMax().y ;
|
|
ptGdEnd.y = b3Raw.GetMin().y ;
|
|
}
|
|
// se direzione generica
|
|
else {
|
|
INTDBLVECTOR vInters ;
|
|
IntersLineBox( ptGdStart, ptGdEnd, b3Raw, vInters, false) ;
|
|
if ( vInters.size() != 2)
|
|
return false ;
|
|
ptGdEnd = ptGdStart + vtGdDir * vInters[1].second ;
|
|
ptGdStart = ptGdStart + vtGdDir * vInters[0].second ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::CalculateOneWayCut( const Point3d& ptStart, const Point3d& ptEnd, const Vector3d& vtDir,
|
|
const Vector3d& vtTool, const Vector3d& vtCorr, double dElev, bool bFirst, bool bLast, const BBox3d& b3Raw)
|
|
{
|
|
// recupero distanza di sicurezza
|
|
double dSafeZ = GetSafeZ() ;
|
|
// lunghezza di approccio/retrazione
|
|
double dAppr = m_Params.m_dStartPos ;
|
|
|
|
// se attacco/uscita/collegamento esterno allungo inizio
|
|
Point3d ptNewStart = ptStart ;
|
|
if ( m_Params.m_nLeadLinkType == SAWROU_LL_OUT) {
|
|
// distanza XY tra centro e bordo taglio
|
|
double dDeltaT = 0 ;
|
|
if ( dElev > 0.0 && dElev < 0.5 * m_TParams.m_dDiam)
|
|
dDeltaT = sqrt( dElev * m_TParams.m_dDiam - dElev * dElev) ;
|
|
// correzione per guida inclinata
|
|
Vector3d vtRef = Y_AX ;
|
|
if ( abs( ptStart.y - b3Raw.GetMin().y) < EPS_SMALL || abs( ptStart.y - b3Raw.GetMax().y) < EPS_SMALL)
|
|
vtRef = X_AX ;
|
|
dDeltaT += m_TParams.m_dThick * ( vtDir * vtRef) / ( vtDir ^ vtRef).Len() ;
|
|
// modifico inizio
|
|
ptNewStart = ptStart - vtDir * ( dDeltaT + dAppr) ;
|
|
}
|
|
|
|
// Se una sola passata
|
|
if ( m_Params.m_dStep < EPS_SMALL || dElev <= m_Params.m_dStep) {
|
|
// 1 -> approccio
|
|
if ( ! AddApproach( ptNewStart, vtCorr, bFirst, dSafeZ, dElev, dAppr))
|
|
return false ;
|
|
// 2 -> movimento in affondo al punto iniziale
|
|
SetFlag( 0) ;
|
|
if ( m_Params.m_nLeadLinkType != SAWROU_LL_OUT)
|
|
SetFeed( GetTipFeed()) ;
|
|
else
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptNewStart) == GDB_ID_NULL)
|
|
return false ;
|
|
// 3 -> movimento di lato al punto finale
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptEnd) == GDB_ID_NULL)
|
|
return false ;
|
|
// 4 -> retrazione
|
|
if ( ! AddRetract( ptEnd, vtCorr, dSafeZ, dElev, dAppr))
|
|
return false ;
|
|
}
|
|
|
|
// altrimenti più passate ad una via
|
|
else {
|
|
// 1 -> approccio
|
|
if ( ! AddApproach( ptNewStart, vtCorr, bFirst, dSafeZ, dElev, dAppr))
|
|
return false ;
|
|
// 2-3 -> lavorazione
|
|
// calcolo numero e valore degli step
|
|
double dCutH = dElev ;
|
|
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) ? i * dStep : 0) ;
|
|
// movimento in affondo al punto iniziale
|
|
SetFlag( 0) ;
|
|
if ( m_Params.m_nLeadLinkType != SAWROU_LL_OUT)
|
|
SetFeed( GetTipFeed()) ;
|
|
else
|
|
SetFeed( GetFeed()) ;
|
|
Point3d ptP2 = ptNewStart + vtCorr * dDelta ;
|
|
if ( AddLinearMove( ptP2) == GDB_ID_NULL)
|
|
return false ;
|
|
// movimento di lato al punto finale
|
|
SetFeed( GetFeed()) ;
|
|
Point3d ptP3 = ptEnd + 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( GetEndFeed()) ;
|
|
Point3d ptP4 = ptEnd + vtCorr * ( dElev + dAppr) ;
|
|
if ( AddLinearMove( ptP4) == GDB_ID_NULL)
|
|
return false ;
|
|
// movimento di ritorno spora il punto iniziale
|
|
SetFeed( GetEndFeed()) ;
|
|
Point3d ptP5 = ptNewStart + vtCorr * ( dElev + dAppr) ;
|
|
if ( AddLinearMove( ptP5) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
}
|
|
// 4 -> retrazione
|
|
if ( ! AddRetract( ptEnd, vtCorr, dSafeZ, dElev, dAppr))
|
|
return false ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::CalculateZigZagCut( const Point3d& ptStart, const Point3d& ptEnd, const Vector3d& vtDir,
|
|
const Vector3d& vtTool, const Vector3d& vtCorr, double dElev, bool bFirst, bool bLast,
|
|
int& nCount, const BBox3d& b3Raw)
|
|
{
|
|
// recupero distanza di sicurezza
|
|
double dSafeZ = GetSafeZ() ;
|
|
// lunghezza di approccio/retrazione
|
|
double dAppr = m_Params.m_dStartPos ;
|
|
|
|
// aggiorno inizio, fine e direzione movimento
|
|
Point3d ptOriStart = ptStart ;
|
|
Point3d ptOriEnd = ptEnd ;
|
|
Point3d ptNewStart = ptStart ;
|
|
Point3d ptNewEnd = ptEnd ;
|
|
Vector3d vtNewDir = vtDir ;
|
|
// se attacco/uscita/collegamento esterno allungo inizio e fine
|
|
if ( m_Params.m_nLeadLinkType == SAWROU_LL_OUT) {
|
|
// distanza XY tra centro e bordo taglio
|
|
double dDeltaT = 0 ;
|
|
if ( dElev > 0.0 && dElev < 0.5 * m_TParams.m_dDiam)
|
|
dDeltaT = sqrt( dElev * m_TParams.m_dDiam - dElev * dElev) ;
|
|
double dDeltaTSt = dDeltaT ;
|
|
double dDeltaTEn = dDeltaT ;
|
|
// calcolo correzione per guida inclinata per far fuoriuscire la lama di tutto lo spessore
|
|
// ricavo il lato di uscita dal grezzo dello start
|
|
Vector3d vtRef = Y_AX ;
|
|
if ( abs( ptStart.y - b3Raw.GetMin().y) < EPS_SMALL || abs( ptStart.y - b3Raw.GetMax().y) < EPS_SMALL)
|
|
vtRef = X_AX ;
|
|
dDeltaTSt += m_TParams.m_dThick * ( vtDir * vtRef) / ( vtDir ^ vtRef).Len() ;
|
|
// end
|
|
vtRef = Y_AX ;
|
|
if ( abs( ptEnd.y - b3Raw.GetMin().y) < EPS_SMALL || abs( ptEnd.y - b3Raw.GetMax().y) < EPS_SMALL)
|
|
vtRef = X_AX ;
|
|
dDeltaTEn += m_TParams.m_dThick * ( vtDir * vtRef) / ( vtDir ^ vtRef).Len() ;
|
|
|
|
// modifico inizio
|
|
ptNewStart = ptStart - vtDir * ( dDeltaTSt + dAppr) ;
|
|
// modifico fine
|
|
ptNewEnd = ptEnd + vtDir * ( dDeltaTEn + dAppr) ;
|
|
}
|
|
// le passate dispari sono al contrario
|
|
if ( ( nCount % 2) != 0) {
|
|
swap( ptOriStart, ptOriEnd) ;
|
|
swap( ptNewStart, ptNewEnd) ;
|
|
vtNewDir.Invert() ;
|
|
}
|
|
|
|
// Se una sola passata
|
|
if ( m_Params.m_dStep < EPS_SMALL || dElev <= m_Params.m_dStep) {
|
|
// 1 -> approccio
|
|
if ( bFirst || m_Params.m_nLeadLinkType != SAWROU_LL_OUT) {
|
|
if ( ! AddApproach( ptNewStart, vtCorr, bFirst, dSafeZ, dElev, dAppr))
|
|
return false ;
|
|
}
|
|
// 2 -> movimento in affondo al punto iniziale
|
|
SetFlag( 0) ;
|
|
// con attacco centrato sono sul materiale e devo usare feed di testa
|
|
if ( m_Params.m_nLeadLinkType != SAWROU_LL_OUT) {
|
|
SetFeed( GetTipFeed()) ;
|
|
Point3d ptCurr ; GetCurrPos( ptCurr) ;
|
|
if ( ! AreSamePointEpsilon( ptCurr, ptNewStart, 10 * EPS_SMALL)) {
|
|
if ( AddLinearMove( ptNewStart) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
}
|
|
// con attacco fuori sono in aria
|
|
else {
|
|
if ( bFirst) {
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptNewStart) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
else {
|
|
Point3d ptLast ;
|
|
GetCurrPos( ptLast) ;
|
|
double dDiff = ( ptNewStart - ptLast) * vtNewDir ;
|
|
// se precedente e corrente sono fuori allo stesso modo
|
|
if ( abs( dDiff) < 10 * EPS_SMALL) {
|
|
// inizio nuova passata
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptNewStart) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// se il precedente è più fuori
|
|
else if ( dDiff > 0) {
|
|
// allungo nuova passata
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptNewStart - dDiff * vtNewDir) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// se il corrente è più fuori
|
|
else {
|
|
// allungo passata precedente
|
|
if ( AddLinearMove( ptLast + dDiff * vtNewDir) == GDB_ID_NULL)
|
|
return false ;
|
|
// inizio nuova passata
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptNewStart) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
}
|
|
}
|
|
// 3 -> movimento di lato al punto finale
|
|
if ( m_Params.m_nLeadLinkType != SAWROU_LL_OUT) {
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptNewEnd) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
else {
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptOriEnd) == GDB_ID_NULL)
|
|
return false ;
|
|
SetFeed( GetEndFeed()) ;
|
|
if ( AddLinearMove( ptNewEnd) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// 4 -> retrazione
|
|
if ( bLast || m_Params.m_nLeadLinkType != SAWROU_LL_OUT) {
|
|
if ( ! AddRetract( ptNewEnd, vtCorr, dSafeZ, dElev, dAppr))
|
|
return false ;
|
|
}
|
|
// incremento contatore passate
|
|
++ nCount ;
|
|
}
|
|
|
|
// altrimenti più passate a zig-zag
|
|
else {
|
|
// 1 -> approccio
|
|
if ( bFirst || m_Params.m_nLeadLinkType != SAWROU_LL_OUT) {
|
|
if ( ! AddApproach( ptNewStart, vtCorr, bFirst, dSafeZ, dElev, dAppr))
|
|
return false ;
|
|
}
|
|
// 2-3 -> lavorazione
|
|
// calcolo numero e valore degli step
|
|
double dCutH = dElev ;
|
|
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 * dStep ;
|
|
// movimento in affondo al punto iniziale
|
|
// con attacco centrato sono sul materiale e devo usare feed di testa
|
|
if ( m_Params.m_nLeadLinkType != SAWROU_LL_OUT) {
|
|
SetFlag( 0) ;
|
|
SetFeed( GetTipFeed()) ;
|
|
Point3d ptP2 = ptNewStart + vtCorr * dDelta ;
|
|
if ( AddLinearMove( ptP2) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// con attacco fuori sono in aria
|
|
else {
|
|
if ( bFirst || i < nStep - 1) {
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptNewStart + vtCorr * dDelta) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
else {
|
|
Point3d ptLast ;
|
|
GetCurrPos( ptLast) ;
|
|
double dDiff = ( ptNewStart - ptLast) * vtNewDir ;
|
|
// se precedente e corrente sono fuori allo stesso modo
|
|
if ( abs( dDiff) < 10 * EPS_SMALL) {
|
|
// inizio nuova passata
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptNewStart + vtCorr * dDelta) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// se il precedente è più fuori
|
|
else if ( dDiff > 0) {
|
|
// allungo nuova passata
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptNewStart + vtCorr * dDelta - dDiff * vtNewDir) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// se il corrente è più fuori
|
|
else {
|
|
// allungo passata precedente
|
|
if ( AddLinearMove( ptLast + dDiff * vtNewDir) == GDB_ID_NULL)
|
|
return false ;
|
|
// inizio nuova passata
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptNewStart + vtCorr * dDelta) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
}
|
|
}
|
|
// movimento di lato al punto finale
|
|
if ( m_Params.m_nLeadLinkType != SAWROU_LL_OUT) {
|
|
SetFeed( GetFeed()) ;
|
|
Point3d ptP3 = ptNewEnd + vtCorr * dDelta ;
|
|
if ( AddLinearMove( ptP3) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
else {
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptOriEnd + vtCorr * dDelta) == GDB_ID_NULL)
|
|
return false ;
|
|
SetFeed( GetEndFeed()) ;
|
|
if ( AddLinearMove( ptNewEnd + vtCorr * dDelta) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// incremento contatore passate
|
|
++ nCount ;
|
|
// scambio inizio e fine
|
|
if ( i > 0) {
|
|
swap( ptNewStart, ptNewEnd) ;
|
|
swap( ptOriStart, ptOriEnd) ;
|
|
vtNewDir.Invert() ;
|
|
}
|
|
}
|
|
// 4 -> retrazione
|
|
if ( bLast || m_Params.m_nLeadLinkType != SAWROU_LL_OUT) {
|
|
if ( ! AddRetract( ptNewEnd, vtCorr, dSafeZ, dElev, dAppr))
|
|
return false ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::CalculateZConstCut( const ICurve* pCrv, double dXmin, double dXmax, bool bIncludeMax, bool bIncludeMin,
|
|
const Point3d& ptGdStart, const Point3d& ptGdEnd, const Vector3d& vtGdDir, const Frame3d& frSect,
|
|
const BBox3d& b3Raw, double dDepth, bool bFirstInterval, bool bLastInterval, int& nCount)
|
|
{
|
|
// calcolo step orizzontali
|
|
double dLargh = dXmax - dXmin ;
|
|
double dSideStep = max( m_Params.m_dSideStep, 10 * EPS_SMALL) ;
|
|
int nSideStep = max( 1, static_cast<int>( ceil( dLargh / dSideStep))) ;
|
|
dSideStep = dLargh / nSideStep ;
|
|
|
|
// determino le coordinate x e y di tutte le intersezioni con la sezione ordinate per x decrescente
|
|
BBox3d b3Crv ;
|
|
pCrv->GetLocalBBox( b3Crv) ;
|
|
double dSectYMin = b3Crv.GetMin().y ;
|
|
double dSectYMax = b3Crv.GetMax().y ;
|
|
int nSize = nSideStep + ( bIncludeMax ? 1 : 0) + ( bIncludeMin ? 0 : -1) ;
|
|
DBLVECTOR vIntersX( nSize) ;
|
|
DBLVECTOR vIntersY( nSize) ;
|
|
int nStart = ( bIncludeMax ? 0 : 1) ;
|
|
int nEnd = ( bIncludeMin ? nSideStep : nSideStep - 1) ;
|
|
for ( int i = nStart ; i <= nEnd ; ++ i) {
|
|
vIntersX[i-nStart] = dXmax - i * dSideStep ;
|
|
if ( ! GetHeightOnSection( pCrv, vIntersX[i-nStart], dSectYMin, dSectYMax, vIntersY[i-nStart]))
|
|
return false ;
|
|
}
|
|
|
|
// calcolo elevazione
|
|
double dTotElev = - INFINITO ;
|
|
double dRefQuote = 0 ;
|
|
for ( int i = 0 ; i < int( vIntersX.size()) ; i++) {
|
|
Vector3d vtMove = vIntersX[i] * frSect.VersX() + vIntersY[i] * frSect.VersY() - 0.5 * m_TParams.m_dThick * m_vtTool ;
|
|
Vector3d vtThick = m_vtTool * m_TParams.m_dThick ;
|
|
Point3d ptStart = ptGdStart + vtMove ;
|
|
Point3d ptEnd = ptGdEnd + vtMove ;
|
|
Point3d ptStart2 = ptStart + vtThick ;
|
|
Point3d ptEnd2 = ptEnd + vtThick ;
|
|
AdaptGuideLineToRaw( ptStart, ptEnd, vtGdDir, b3Raw) ;
|
|
AdaptGuideLineToRaw( ptStart2, ptEnd2, vtGdDir, b3Raw) ;
|
|
|
|
// determino l'elevazione del taglio
|
|
double dCurrElev1, dCurrElev2 ;
|
|
if ( ! GetElevation( m_nPhase, ptStart, ptEnd, m_vtCorr, dCurrElev1) ||
|
|
! GetElevation( m_nPhase, ptStart2, ptEnd2, m_vtCorr, dCurrElev2)) {
|
|
m_pMchMgr->SetLastError( 2609, "Error in SawRoughing : GetElevation") ;
|
|
return false ;
|
|
}
|
|
double dCurrElev = max( dCurrElev1, dCurrElev2) ;
|
|
if ( dCurrElev > dTotElev) {
|
|
dTotElev = dCurrElev ;
|
|
dRefQuote = vIntersY[i] ;
|
|
}
|
|
else if ( abs( dCurrElev - dTotElev) < EPS_SMALL && dRefQuote > vIntersY[i])
|
|
dRefQuote = vIntersY[i] ;
|
|
}
|
|
// eventuale correzione con depth
|
|
double dRealElev = min( dTotElev, dDepth) ;
|
|
|
|
// calcolo step verticali
|
|
int nStep = ( m_Params.m_dStep < EPS_SMALL ? 1 : static_cast<int>( ceil( dRealElev / m_Params.m_dStep))) ;
|
|
nStep = max( 1, nStep) ;
|
|
double dStep = dRealElev / nStep ;
|
|
|
|
// costruisco un vettore con le quote di lavoro e gli indici delle ascisse in vIntersX da lavorare a quella quota
|
|
vector<pair<double, INTVECTOR>> vStepCoord ;
|
|
vStepCoord.reserve( nStep) ;
|
|
for ( int j = 1 ; j <= nStep ; j++) {
|
|
vStepCoord.emplace_back( dRefQuote + dTotElev - j * dStep, INTVECTOR()) ;
|
|
vStepCoord.back().second.reserve( vIntersX.size()) ;
|
|
for ( int i = 0 ; i < int( vIntersX.size()) ; i ++) {
|
|
// l'ascissa va considerata solo se la quota di lavoro è maggiore di quella della sezione
|
|
if ( vStepCoord.back().first > vIntersY[i] - EPS_SMALL)
|
|
vStepCoord.back().second.emplace_back(i) ;
|
|
}
|
|
// se non ci sono punti da lavorare alla quota corrente la scarto
|
|
if ( vStepCoord.back().second.empty())
|
|
vStepCoord.pop_back() ;
|
|
}
|
|
|
|
// individuo piani orizzontali extra da lavorare
|
|
int nStartSearch = vStepCoord.size() ;
|
|
const ICurveComposite* pCompo = GetCurveComposite( pCrv) ;
|
|
if ( pCompo != nullptr) {
|
|
for ( int i = 0 ; i < pCompo->GetCurveCount() ; i++) {
|
|
const ICurve* pSimpCrv = pCompo->GetCurve( i) ;
|
|
Point3d ptStart, ptEnd ;
|
|
pSimpCrv->GetStartPoint( ptStart) ;
|
|
pSimpCrv->GetEndPoint( ptEnd) ;
|
|
// verifico se è nell'intervallo da lavorare
|
|
if ( ptEnd.x > dXmax - EPS_SMALL)
|
|
continue ;
|
|
if ( ptStart.x < dXmin + EPS_SMALL)
|
|
break ;
|
|
|
|
// verifico se tratto orizzontale
|
|
if ( abs( ptEnd.y - ptStart.y) < EPS_SMALL) {
|
|
double dY = ( ptEnd.y + ptStart.y) / 2 ;
|
|
// se sotto la quota minima di lavoro lo ignoro
|
|
if ( dY < dRefQuote + dTotElev - dRealElev - EPS_SMALL)
|
|
continue ;
|
|
// se quota già considerata negli step ( ovvero è multiplo di dStep) la ignoro
|
|
if ( dStep < EPS_SMALL) {
|
|
if ( abs( dRefQuote + dTotElev - dY) < EPS_SMALL)
|
|
continue ;
|
|
}
|
|
else {
|
|
double dRes = ( dRefQuote + dTotElev - dY) / dStep ;
|
|
if ( dRes > EPS_SMALL && abs( dRes - round( dRes)) < EPS_SMALL)
|
|
continue ;
|
|
}
|
|
|
|
// verifico se piano orizzontale già individuato tra i piani extra
|
|
auto it = find_if( vStepCoord.begin() + nStartSearch, vStepCoord.end(), [dY]( const pair<double, INTVECTOR>& a)
|
|
{ return abs( a.first - dY) < EPS_SMALL ;}) ;
|
|
// se non individuato lo aggiungo
|
|
if ( it == vStepCoord.end()) {
|
|
vStepCoord.emplace_back( dY, INTVECTOR()) ;
|
|
vStepCoord.back().second.reserve( vIntersX.size()) ;
|
|
it = vStepCoord.end() - 1 ;
|
|
}
|
|
// calcolo le ascisse da lavorare corrispondenti al piano
|
|
for ( int j = 0 ; j < int( vIntersX.size()) ; j ++) {
|
|
if ( vIntersX[j] < ptEnd.x - EPS_SMALL)
|
|
break ;
|
|
if ( vIntersX[j] < ptStart.x + EPS_SMALL && vIntersX[j] > ptEnd.x - EPS_SMALL)
|
|
it->second.emplace_back( j) ;
|
|
}
|
|
// se non ci sono punti da lavorare lo ignoro
|
|
if ( it->second.empty())
|
|
vStepCoord.pop_back() ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// riordino per quota di lavoro decrescente
|
|
sort( vStepCoord.begin(), vStepCoord.end(), []( const pair<double, INTVECTOR>& a, const pair<double, INTVECTOR>& b)
|
|
{ return a.first > b.first ;}) ;
|
|
|
|
// recupero distanza di sicurezza
|
|
double dSafeZ = GetSafeZ() ;
|
|
// lunghezza di approccio/retrazione
|
|
double dAppr = m_Params.m_dStartPos ;
|
|
|
|
double dLastX = 0 ;
|
|
double dElev = 0 ;
|
|
Point3d ptNewEnd ;
|
|
|
|
// ciclo sugli step verticali
|
|
for ( int j = 0 ; j < int( vStepCoord.size()) ; j++) {
|
|
|
|
// inverto lo step corrente se lo step precedente finisce più vicino all'ultima ascissa corrente
|
|
bool bInvertStep = false ;
|
|
if ( j > 0) {
|
|
double dXStepMax = vIntersX[vStepCoord[j].second.front()] ;
|
|
double dXStepMin = vIntersX[vStepCoord[j].second.back()] ;
|
|
if ( abs( dXStepMin - dLastX) < abs( dXStepMax - dLastX))
|
|
bInvertStep = true ;
|
|
}
|
|
|
|
// ciclo sui punti orizzontali
|
|
for ( int i = 0 ; i < int( vStepCoord[j].second.size()) ; ++ i) {
|
|
|
|
// se lo step è invertito leggo dal fondo
|
|
int nI = ( bInvertStep ? vStepCoord[j].second.size() - i - 1 : i) ;
|
|
// indice da considerare nel vettore delle coordinate
|
|
int nIdx = vStepCoord[j].second[nI] ;
|
|
|
|
bool bFirst = ( bFirstInterval && j == 0 && i == 0) ;
|
|
bool bLast = ( bLastInterval && j == vStepCoord.size() - 1 && i == vStepCoord[j].second.size() - 1) ;
|
|
bool bAlignedPoints = abs( dLastX - vIntersX[nIdx]) < EPS_SMALL ;
|
|
|
|
// 0 -> retrazione del precedente
|
|
if ( m_Params.m_nLeadLinkType != SAWROU_LL_OUT) {
|
|
// se punto intermedio dello step corrente va sempre aggiunta
|
|
if ( i > 0) {
|
|
if ( ! AddRetract( ptNewEnd, m_vtCorr, dSafeZ, dElev, dAppr))
|
|
return false ;
|
|
}
|
|
// se il punto è il primo dello step corrente va aggiunta solo se non è allineato con l'ultimo punto
|
|
// dello step precedente ( se allineati è semplice discesa senza rialzarsi)
|
|
else if ( j > 0 && ! bAlignedPoints) {
|
|
if ( ! AddRetract( ptNewEnd, m_vtCorr, dSafeZ, dElev, dAppr))
|
|
return false ;
|
|
}
|
|
}
|
|
|
|
// calcolo punti di riferimento della guida alla quota della sezione
|
|
dLastX = vIntersX[nIdx] ;
|
|
double dY = vIntersY[nIdx] ;
|
|
Vector3d vtMove = dLastX * frSect.VersX() + dY * m_vtCorr - 0.5 * m_TParams.m_dThick * m_vtTool ;
|
|
Point3d ptStart = ptGdStart + vtMove ;
|
|
Point3d ptEnd = ptGdEnd + vtMove ;
|
|
// adatto la guida corrente al grezzo
|
|
AdaptGuideLineToRaw( ptStart, ptEnd, vtGdDir, b3Raw) ;
|
|
|
|
// quantità necessaria per arrivare alla quota di lavoro dalla quota della sezione
|
|
double dDelta = vStepCoord[j].first - dY ;
|
|
// vera elevazione alla quota della sezione
|
|
dElev = max( 0.0, dRefQuote + dTotElev - dY) ;
|
|
|
|
Point3d ptOriStart = ptStart ;
|
|
Point3d ptOriEnd = ptEnd ;
|
|
Point3d ptNewStart = ptOriStart ;
|
|
ptNewEnd = ptOriEnd ;
|
|
Vector3d vtNewDir = vtGdDir ;
|
|
|
|
// se attacco/uscita/collegamento esterno allungo inizio e fine
|
|
if ( m_Params.m_nLeadLinkType == SAWROU_LL_OUT) {
|
|
// distanza XY tra centro e bordo taglio
|
|
double dCurrElev = dElev - dDelta ;
|
|
double dDeltaT = 0 ;
|
|
if ( dCurrElev > 0.0 && dCurrElev < 0.5 * m_TParams.m_dDiam)
|
|
dDeltaT = sqrt( dCurrElev * m_TParams.m_dDiam - dCurrElev * dCurrElev) ;
|
|
double dDeltaTSt = dDeltaT ;
|
|
double dDeltaTEn = dDeltaT ;
|
|
// calcolo correzione per guida inclinata per far fuoriuscire la lama di tutto lo spessore
|
|
// ricavo il lato di uscita dal grezzo dello start
|
|
Vector3d vtRef = Y_AX ;
|
|
if ( abs( ptStart.y - b3Raw.GetMin().y) < EPS_SMALL || abs( ptStart.y - b3Raw.GetMax().y) < EPS_SMALL)
|
|
vtRef = X_AX ;
|
|
dDeltaTSt += m_TParams.m_dThick * ( vtGdDir * vtRef) / ( vtGdDir ^ vtRef).Len() ;
|
|
// end
|
|
vtRef = Y_AX ;
|
|
if ( abs( ptEnd.y - b3Raw.GetMin().y) < EPS_SMALL || abs( ptEnd.y - b3Raw.GetMax().y) < EPS_SMALL)
|
|
vtRef = X_AX ;
|
|
dDeltaTEn += m_TParams.m_dThick * ( vtGdDir * vtRef) / ( vtGdDir ^ vtRef).Len() ;
|
|
|
|
// modifico inizio
|
|
ptNewStart = ptOriStart - vtNewDir * ( dDeltaTSt + dAppr) ;
|
|
// modifico fine
|
|
ptNewEnd = ptOriEnd + vtNewDir * ( dDeltaTEn + dAppr) ;
|
|
}
|
|
|
|
// le passate dispari sono al contrario
|
|
if ( ( nCount % 2) != 0) {
|
|
swap( ptOriStart, ptOriEnd) ;
|
|
swap( ptNewStart, ptNewEnd) ;
|
|
vtNewDir.Invert() ;
|
|
}
|
|
|
|
// 1 -> approccio
|
|
if ( m_Params.m_nLeadLinkType != SAWROU_LL_OUT) {
|
|
// se collegamento interno va fatto se è un intermedio, se è il primo del primo step oppure
|
|
// se è il primo di uno step intermedio ma non è allineato allo step precedente
|
|
if ( i > 0 || ( i == 0 && j == 0) || ( i == 0 && j > 0 && ! bAlignedPoints))
|
|
if ( ! AddApproach( ptNewStart, m_vtCorr, bFirst, dSafeZ, dElev, dAppr))
|
|
return false ;
|
|
}
|
|
// se collegamento out va fatto solo se è il primo in assoluto
|
|
else if ( bFirst)
|
|
if ( ! AddApproach( ptNewStart, m_vtCorr, bFirst, dSafeZ, dElev, dAppr))
|
|
return false ;
|
|
|
|
// 2 -> movimento in affondo al punto iniziale
|
|
// con attacco centrato sono sul materiale e devo usare feed di testa
|
|
if ( m_Params.m_nLeadLinkType != SAWROU_LL_OUT) {
|
|
SetFlag( 0) ;
|
|
SetFeed( GetTipFeed()) ;
|
|
Point3d ptP2 = ptNewStart + m_vtCorr * dDelta ;
|
|
if ( AddLinearMove( ptP2) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// con attacco fuori sono in aria
|
|
else {
|
|
if ( bFirst) {
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptNewStart + m_vtCorr * dDelta) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
else {
|
|
Point3d ptLast ;
|
|
GetCurrPos( ptLast) ;
|
|
double dDiff = ( ptNewStart - ptLast) * vtNewDir ;
|
|
// se precedente e corrente sono fuori allo stesso modo
|
|
if ( abs( dDiff) < 10 * EPS_SMALL) {
|
|
// inizio nuova passata
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptNewStart + m_vtCorr * dDelta) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// se il precedente è più fuori
|
|
else if ( dDiff > 0) {
|
|
// allungo nuova passata
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptNewStart + m_vtCorr * dDelta - dDiff * vtNewDir) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// se il corrente è più fuori
|
|
else {
|
|
// allungo passata precedente
|
|
if ( AddLinearMove( ptLast + dDiff * vtNewDir) == GDB_ID_NULL)
|
|
return false ;
|
|
// inizio nuova passata
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptNewStart + m_vtCorr * dDelta) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 3 -> movimento di lato al punto finale
|
|
if ( m_Params.m_nLeadLinkType != SAWROU_LL_OUT) {
|
|
SetFeed( GetFeed()) ;
|
|
Point3d ptP3 = ptNewEnd + m_vtCorr * dDelta ;
|
|
if ( AddLinearMove( ptP3) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
else {
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptOriEnd + m_vtCorr * dDelta) == GDB_ID_NULL)
|
|
return false ;
|
|
SetFeed( GetEndFeed()) ;
|
|
if ( AddLinearMove( ptNewEnd + m_vtCorr * dDelta) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
|
|
// 4 -> retrazione soltanto se ultimo in assoluto oppure se attacco interno e ultimo dell'ultimo step
|
|
if ( bLast ||
|
|
( m_Params.m_nLeadLinkType != SAWROU_LL_OUT && j == vStepCoord.size() - 1 && i == vStepCoord[j].second.size() - 1)) {
|
|
if ( ! AddRetract( ptNewEnd, m_vtCorr, dSafeZ, dElev, dAppr))
|
|
return false ;
|
|
}
|
|
|
|
// incremento contatore passate
|
|
++ nCount ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::CalculateCurvedZigZagCut( const ICurve* pCut, const Vector3d& vtTool, double dElev, bool bFirst, bool bLast,
|
|
int& nCount)
|
|
{
|
|
// recupero distanza di sicurezza
|
|
double dSafeZ = GetSafeZ() ;
|
|
// lunghezza di approccio/retrazione
|
|
double dAppr = m_Params.m_dStartPos ;
|
|
// verifico se passata da invertire (indice dispari)
|
|
bool bInvert = ( ( nCount % 2) != 0) ;
|
|
// recupero la passata
|
|
PtrOwner<ICurveComposite> pCompo( CreateCurveComposite()) ;
|
|
if ( IsNull( pCompo) || ! pCompo->AddCurve( *pCut))
|
|
return false ;
|
|
// eseguo eventuale inversione
|
|
if ( bInvert)
|
|
pCompo->Invert() ;
|
|
|
|
// aggiorno inizio, fine e direzione movimento
|
|
Point3d ptStart ; pCompo->GetStartPoint( ptStart) ;
|
|
Vector3d vtDirStart ; pCompo->GetStartDir( vtDirStart) ;
|
|
Vector3d vtOrtStart = vtDirStart ; vtOrtStart.Rotate( Z_AX, ( bInvert ? 90 : -90)) ;
|
|
Point3d ptEnd ; pCompo->GetEndPoint( ptEnd) ;
|
|
Vector3d vtDirEnd ; pCompo->GetEndDir( vtDirEnd) ;
|
|
Vector3d vtOrtEnd = vtDirEnd ; vtOrtEnd.Rotate( Z_AX, ( bInvert ? 90 : -90)) ;
|
|
Point3d ptNewStart = ptStart ;
|
|
Point3d ptNewEnd = ptEnd ;
|
|
|
|
// calcolo elevazioni
|
|
double dTgElevStart = 0 ;
|
|
GetElevation( m_nPhase, ptStart, - vtDirStart, dTgElevStart) ;
|
|
double dOrtElevStart = 0 ;
|
|
GetElevation( m_nPhase, ptStart, vtOrtStart, dOrtElevStart) ;
|
|
dOrtElevStart = max( dOrtElevStart, dElev) ;
|
|
double dTgElevEnd = 0 ;
|
|
GetElevation( m_nPhase, ptEnd, vtDirEnd, dTgElevEnd) ;
|
|
double dOrtElevEnd = 0 ;
|
|
GetElevation( m_nPhase, ptEnd, vtOrtEnd, dOrtElevEnd) ;
|
|
dOrtElevEnd = max( dOrtElevEnd, dElev) ;
|
|
|
|
// se attacco/uscita/collegamento esterno allungo inizio e fine
|
|
if ( m_Params.m_nLeadLinkType == SAWROU_LL_OUT) {
|
|
// distanza XY tra centro e bordo taglio
|
|
double dDeltaTStart = 0 ;
|
|
if ( dOrtElevStart > 0.0 && dOrtElevStart < 0.5 * m_TParams.m_dDiam)
|
|
dDeltaTStart = sqrt( dOrtElevStart * m_TParams.m_dDiam - dOrtElevStart * dOrtElevStart) ;
|
|
double dDeltaTEnd = 0 ;
|
|
if ( dOrtElevEnd > 0.0 && dOrtElevEnd < 0.5 * m_TParams.m_dDiam)
|
|
dDeltaTEnd = sqrt( dOrtElevEnd * m_TParams.m_dDiam - dOrtElevEnd * dOrtElevEnd) ;
|
|
// modifico inizio
|
|
ptNewStart = ptStart - vtDirStart * ( dTgElevStart + dDeltaTStart + dAppr) ;
|
|
// modifico fine
|
|
ptNewEnd = ptEnd + vtDirEnd * ( dTgElevEnd + dDeltaTEnd + dAppr) ;
|
|
}
|
|
|
|
// Se una sola passata
|
|
if ( m_Params.m_dStep < EPS_SMALL || dElev <= m_Params.m_dStep) {
|
|
SetCorrAuxDir( vtOrtStart) ;
|
|
// 1 -> approccio
|
|
if ( bFirst || m_Params.m_nLeadLinkType != SAWROU_LL_OUT) {
|
|
if ( ! AddApproach( ptNewStart, vtOrtStart, bFirst, dSafeZ, dOrtElevStart, dAppr))
|
|
return false ;
|
|
}
|
|
// 2 -> movimento in affondo al punto iniziale
|
|
SetFlag( 0) ;
|
|
// con attacco centrato sono sul materiale e devo usare feed di testa
|
|
if ( m_Params.m_nLeadLinkType != SAWROU_LL_OUT) {
|
|
SetFeed( GetTipFeed()) ;
|
|
Point3d ptCurr ; GetCurrPos( ptCurr) ;
|
|
if ( ! AreSamePointEpsilon( ptCurr, ptNewStart, 10 * EPS_SMALL)) {
|
|
if ( AddLinearMove( ptNewStart) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
}
|
|
// con attacco fuori sono in aria
|
|
else {
|
|
if ( bFirst) {
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptNewStart) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
else {
|
|
Point3d ptLast ;
|
|
GetCurrPos( ptLast) ;
|
|
double dDiff = ( ptNewStart - ptLast) * vtDirStart ;
|
|
// se precedente e corrente sono fuori allo stesso modo
|
|
if ( abs( dDiff) < 10 * EPS_SMALL) {
|
|
// inizio nuova passata
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptNewStart) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// se il precedente è più fuori
|
|
else if ( dDiff > 0) {
|
|
// allungo nuova passata
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptNewStart - dDiff * vtDirStart) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// se il corrente è più fuori
|
|
else {
|
|
// allungo passata precedente
|
|
if ( AddLinearMove( ptLast + dDiff * vtDirStart) == GDB_ID_NULL)
|
|
return false ;
|
|
// inizio nuova passata
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptNewStart) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
}
|
|
}
|
|
// se non ci sono già, vado all'inizio dell'arco
|
|
if ( ! SameAsCurrPos( ptStart) && AddLinearMove( ptStart) == GDB_ID_NULL)
|
|
return false ;
|
|
// 3 -> movimento di lato al punto finale
|
|
const ICurve* pCrv = pCompo->GetFirstCurve() ;
|
|
while ( pCrv != nullptr) {
|
|
Point3d ptEnd ; pCrv->GetEndPoint( ptEnd) ;
|
|
Vector3d vtDirEnd ; pCrv->GetEndDir( vtDirEnd) ;
|
|
Vector3d vtOrtEnd = vtDirEnd ; vtOrtEnd.Rotate( Z_AX, ( bInvert ? 90 : -90)) ;
|
|
SetCorrAuxDir( vtOrtEnd) ;
|
|
SetFeed( GetFeed()) ;
|
|
if ( pCrv->GetType() == CRV_LINE) {
|
|
if ( AddLinearMove( ptEnd) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
else {
|
|
Point3d ptCen ; pCrv->GetCenterPoint( ptCen) ;
|
|
double dAngCen = GetCurveArc( pCrv)->GetAngCenter() ;
|
|
if ( AddArcMove( ptEnd, ptCen, dAngCen, vtTool) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
pCrv = pCompo->GetNextCurve() ;
|
|
}
|
|
if ( m_Params.m_nLeadLinkType == SAWROU_LL_OUT) {
|
|
SetFeed( GetEndFeed()) ;
|
|
if ( AddLinearMove( ptNewEnd) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// 4 -> retrazione
|
|
if ( bLast || m_Params.m_nLeadLinkType != SAWROU_LL_OUT) {
|
|
if ( ! AddRetract( ptNewEnd, vtOrtEnd, dSafeZ, dOrtElevEnd, dAppr))
|
|
return false ;
|
|
}
|
|
// incremento contatore passate
|
|
++ nCount ;
|
|
}
|
|
|
|
// altrimenti più passate a zig-zag
|
|
else {
|
|
SetCorrAuxDir( vtOrtStart) ;
|
|
// 1 -> approccio
|
|
if ( bFirst || m_Params.m_nLeadLinkType != SAWROU_LL_OUT) {
|
|
if ( ! AddApproach( ptNewStart, vtOrtStart, bFirst, dSafeZ, dOrtElevStart, dAppr))
|
|
return false ;
|
|
}
|
|
// 2-3 -> lavorazione
|
|
// calcolo numero e valore degli step
|
|
double dCutH = dElev ;
|
|
int nStep = static_cast<int>( ceil( dCutH / m_Params.m_dStep)) ;
|
|
double dStep = dCutH / nStep ;
|
|
// offset iniziale della curva
|
|
pCompo->SimpleOffset( bInvert ? - nStep * dStep : nStep * dStep, ICurve::OFF_FORCE_OPEN) ;
|
|
// esecuzione degli step
|
|
for ( int i = nStep - 1 ; i >= 0 ; -- i) {
|
|
// distanza dal fondo
|
|
double dDelta = ( ( i != 0) ? i * dStep : 0) ;
|
|
pCompo->SimpleOffset( bInvert ? dStep : -dStep, ICurve::OFF_FORCE_OPEN) ;
|
|
// movimento in affondo al punto iniziale
|
|
// con attacco centrato sono sul materiale e devo usare feed di testa
|
|
if ( m_Params.m_nLeadLinkType != SAWROU_LL_OUT) {
|
|
SetFlag( 0) ;
|
|
if ( m_Params.m_nLeadLinkType != SAWROU_LL_OUT)
|
|
SetFeed( GetTipFeed()) ;
|
|
else
|
|
SetFeed( GetFeed()) ;
|
|
Point3d ptP2 = ptNewStart + vtOrtStart * dDelta ;
|
|
if ( AddLinearMove( ptP2) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// con attacco fuori sono in aria
|
|
else {
|
|
if ( bFirst || i < nStep - 1) {
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptNewStart + vtOrtStart * dDelta) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
else {
|
|
Point3d ptLast ;
|
|
GetCurrPos( ptLast) ;
|
|
double dDiff = ( ptNewStart - ptLast) * vtDirStart ;
|
|
// se precedente e corrente sono fuori allo stesso modo
|
|
if ( abs( dDiff) < 10 * EPS_SMALL) {
|
|
// inizio nuova passata
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptNewStart + vtOrtStart * dDelta) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// se il precedente è più fuori
|
|
else if ( dDiff > 0) {
|
|
// allungo nuova passata
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptNewStart + vtOrtStart * dDelta - dDiff * vtDirStart) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// se il corrente è più fuori
|
|
else {
|
|
// allungo passata precedente
|
|
if ( AddLinearMove( ptLast + dDiff * vtDirStart) == GDB_ID_NULL)
|
|
return false ;
|
|
// inizio nuova passata
|
|
SetFeed( GetFeed()) ;
|
|
if ( AddLinearMove( ptNewStart + vtOrtStart * dDelta) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
}
|
|
}
|
|
// se non ci sono già, vado all'inizio dell'arco
|
|
if ( ! SameAsCurrPos( ptStart + vtOrtStart * dDelta) && AddLinearMove( ptStart + vtOrtStart * dDelta) == GDB_ID_NULL)
|
|
return false ;
|
|
// movimento di lato al punto finale
|
|
const ICurve* pCrv = pCompo->GetFirstCurve() ;
|
|
while ( pCrv != nullptr) {
|
|
Point3d ptEnd ; pCrv->GetEndPoint( ptEnd) ;
|
|
Vector3d vtDirEnd ; pCrv->GetEndDir( vtDirEnd) ;
|
|
Vector3d vtOrtEnd = vtDirEnd ; vtOrtEnd.Rotate( Z_AX, ( bInvert ? 90 : -90)) ;
|
|
SetCorrAuxDir( vtOrtEnd) ;
|
|
SetFeed( GetFeed()) ;
|
|
if ( pCrv->GetType() == CRV_LINE) {
|
|
if ( AddLinearMove( ptEnd) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
else {
|
|
Point3d ptCen ; pCrv->GetCenterPoint( ptCen) ;
|
|
double dAngCen = GetCurveArc( pCrv)->GetAngCenter() ;
|
|
if ( AddArcMove( ptEnd, ptCen, dAngCen, vtTool) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
pCrv = pCompo->GetNextCurve() ;
|
|
}
|
|
if ( m_Params.m_nLeadLinkType == SAWROU_LL_OUT) {
|
|
SetFeed( GetEndFeed()) ;
|
|
if ( AddLinearMove( ptNewEnd + vtOrtEnd * dDelta) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// incremento contatore passate
|
|
++ nCount ;
|
|
// scambio inizio e fine
|
|
if ( i > 0) {
|
|
swap( ptStart, ptEnd) ;
|
|
swap( ptNewStart, ptNewEnd) ;
|
|
swap( vtOrtStart, vtOrtEnd) ;
|
|
swap( dOrtElevStart, dOrtElevEnd) ;
|
|
bInvert = ! bInvert ;
|
|
pCompo->Invert() ;
|
|
}
|
|
}
|
|
// 4 -> retrazione
|
|
if ( bLast || m_Params.m_nLeadLinkType != SAWROU_LL_OUT) {
|
|
if ( ! AddRetract( ptNewEnd, vtOrtEnd, dSafeZ, dOrtElevEnd, dAppr))
|
|
return false ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::AddApproach( const Point3d& ptP, const Vector3d& vtCorr, bool bFirst,
|
|
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
|
|
Point3d ptP1 = ptP + vtCorr * ( dElev + dAppr) ;
|
|
if ( bFirst) {
|
|
SetFlag( 1) ;
|
|
if ( AddRapidStart( ptP1) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
else {
|
|
SetFlag( 0) ;
|
|
if ( AddRapidMove( ptP1) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
}
|
|
else {
|
|
// 1a -> punto sopra inizio
|
|
Point3d ptP1b = ptP + vtCorr * ( dElev + dAppr) ;
|
|
Point3d ptP1a = ptP1b + vtCorr * ( dSafeZ - m_Params.m_dStartPos) ;
|
|
if ( bFirst) {
|
|
SetFlag( 1) ;
|
|
if ( AddRapidStart( ptP1a) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
else {
|
|
SetFlag( 0) ;
|
|
if ( AddRapidMove( ptP1a) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// 1b -> punto appena sopra inizio
|
|
SetFlag( 0) ;
|
|
if ( AddRapidMove( ptP1b) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::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( GetEndFeed()) ;
|
|
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( GetEndFeed()) ;
|
|
Point3d ptP4a = ptP + vtCorr * ( dElev + dAppr) ;
|
|
Point3d ptCurr ; GetCurrPos( ptCurr) ;
|
|
if ( ! AreSamePointEpsilon( ptCurr, ptP4a, 10 * EPS_SMALL)) {
|
|
if ( AddLinearMove( ptP4a) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
// 4b -> movimento di risalita sopra il punto finale
|
|
Point3d ptP4b = ptP4a + vtCorr * ( dSafeZ - m_Params.m_dStartPos) ;
|
|
if ( AddRapidMove( ptP4b) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::CalculateToolAndCorrVersors( const Vector3d& vtTang, int nHeadSide,
|
|
Vector3d& vtTool, Vector3d& vtCorr)
|
|
{
|
|
// Versore fresa : annullo la componente in Z e normalizzo
|
|
vtTool = vtTang ;
|
|
vtTool.z = 0 ;
|
|
if ( ! vtTool.Normalize())
|
|
return false ;
|
|
// ruoto attorno a Zglob+ a seconda del lato mandrino
|
|
if ( nHeadSide == SAW_HS_LEFT)
|
|
vtTool.Rotate( Z_AX, 0, 1) ;
|
|
else
|
|
vtTool.Rotate( Z_AX, 0, -1) ;
|
|
|
|
// Versore correzione
|
|
vtCorr = Z_AX ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::GetHeightOnSection( const ICurve* pSect, double dX, double dYmin, double dYmax, double& dY)
|
|
{
|
|
// creo raggio per intersezione con direzione Y+
|
|
PtrOwner<ICurveLine>pRay( CreateCurveLine()) ;
|
|
if ( IsNull( pRay) ||
|
|
! pRay->Set( Point3d( dX, dYmin - EPS_SMALL, 0), Point3d( dX, dYmax + EPS_SMALL, 0)))
|
|
return false ;
|
|
// eseguo intersezione (considero la prima perchè non ci sono sottosquadra)
|
|
IntersCurveCurve intCC( *pRay, *pSect) ;
|
|
IntCrvCrvInfo aInfo ;
|
|
if ( intCC.GetIntCrvCrvInfo( 0, aInfo)) {
|
|
// nel caso di sovrapposizione devo prendere la Y in basso del tratto
|
|
dY = aInfo.IciA[0].ptI.y ;
|
|
return true ;
|
|
}
|
|
// se non c'è intersezione assegno il minimo
|
|
dY = dYmin ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::GetWidthOnSection( const ICurve* pSect, double dY, double dXmin, double dXmax, double& dX)
|
|
{
|
|
// creo raggio per intersezione con direzione X-
|
|
PtrOwner<ICurveLine>pRay( CreateCurveLine()) ;
|
|
if ( IsNull( pRay) ||
|
|
! pRay->Set( Point3d( dXmax + EPS_SMALL, dY, 0), Point3d( dXmin - EPS_SMALL, dY, 0)))
|
|
return false ;
|
|
// eseguo intersezione (considero la prima perchè non ci sono sottosquadra)
|
|
IntersCurveCurve intCC( *pRay, *pSect) ;
|
|
IntCrvCrvInfo aInfo ;
|
|
if ( intCC.GetIntCrvCrvInfo( 0, aInfo)) {
|
|
// nel caso di sovrapposizione devo prendere la X massima del tratto
|
|
dX = aInfo.IciA[0].ptI.x ;
|
|
return true ;
|
|
}
|
|
// se non c'è intersezione assegno il massimo
|
|
dX = dXmax ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::CalculateSideElevation( const ICurve* pCut, double& dElev)
|
|
{
|
|
// Inizializzo elevazione
|
|
dElev = 0 ;
|
|
// Lunghezza della curva
|
|
double dTotLen ;
|
|
pCut->GetLength( dTotLen) ;
|
|
// Ciclo sulla curva
|
|
double dLen = 0 ;
|
|
while ( dLen <= dTotLen) {
|
|
double dU ;
|
|
if ( pCut->GetParamAtLength( dLen, dU)) {
|
|
Point3d ptP ;
|
|
Vector3d vtDir ;
|
|
pCut->GetPointD1D2( dU, ICurve::FROM_MINUS, ptP, &vtDir) ;
|
|
vtDir.Normalize() ;
|
|
vtDir.Rotate( Z_AX, -90) ;
|
|
double dCurrElev ;
|
|
if ( GetElevation(m_nPhase, ptP, vtDir, dCurrElev) && dCurrElev > dElev)
|
|
dElev = dCurrElev ;
|
|
}
|
|
dLen += 20 ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SawRoughing::GeneratePreView( int nPathId, const ICurve* pSect, const Frame3d& frSect, double dGuideLen,
|
|
const Vector3d& vtGdDir, const BBox3d& b3Raw)
|
|
{
|
|
// ricavo i riferimenti della regione di lavoro dalla sezione
|
|
BBox3d b3Sect ;
|
|
pSect->GetLocalBBox( b3Sect) ;
|
|
Point3d ptStart = b3Sect.GetMax() ;
|
|
ptStart.ToGlob( frSect) ;
|
|
ptStart += 0.5 * m_TParams.m_dThick * frSect.VersX() ;
|
|
double dDimX = dGuideLen ;
|
|
// se link non interno la lavorazione viene estesa fino al bordo del grezzo
|
|
if ( m_Params.m_nLeadLinkType != SAWROU_LL_INT) {
|
|
BBox3d b3RawLoc( b3Raw) ;
|
|
b3RawLoc.ToLoc( frSect) ;
|
|
double dMaxDim = max( b3RawLoc.GetDimX(), b3RawLoc.GetDimY()) ;
|
|
dDimX += 4 * dMaxDim ;
|
|
ptStart -= 2 * dMaxDim * vtGdDir ;
|
|
}
|
|
|
|
// regione di lavoro
|
|
ISurfFlatRegion* pSrf = GetSurfFlatRegionRectangle( dDimX, b3Sect.GetDimX() + m_TParams.m_dThick) ;
|
|
if ( pSrf == nullptr)
|
|
return false ;
|
|
Frame3d frRec ;
|
|
if ( ! frRec.Set( ptStart, vtGdDir, - frSect.VersX(), Z_AX))
|
|
return false ;
|
|
pSrf->ToGlob( frRec) ;
|
|
|
|
// regione del grezzo
|
|
PtrOwner<ISurfFlatRegion> pSrfRaw( GetSurfFlatRegionRectangle( b3Raw.GetDimX(), b3Raw.GetDimY())) ;
|
|
if ( IsNull( pSrfRaw))
|
|
return false ;
|
|
Frame3d frRaw ; frRaw.Set( b3Raw.GetMin(), Z_AX) ;
|
|
pSrfRaw->ToGlob( frRaw) ;
|
|
|
|
// limito la regione di lavoro al grezzo
|
|
pSrf->Intersect( *pSrfRaw) ;
|
|
|
|
// curva e regione di taglio ridotto per nesting
|
|
int nRrId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPathId, pSrf) ;
|
|
m_pGeomDB->SetName( nRrId, MCH_PV_RRCUT) ;
|
|
m_pGeomDB->SetMaterial( nRrId, INVISIBLE) ;
|
|
ICurveComposite* pBorder = GetCurveComposite( pSrf->GetLoop( 0, 0)) ;
|
|
if ( pBorder == nullptr)
|
|
return false ;
|
|
int nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPathId, pBorder) ;
|
|
m_pGeomDB->SetName( nId, MCH_PV_CUT) ;
|
|
m_pGeomDB->SetMaterial( nId, LIME) ;
|
|
|
|
// se collegamento interno preparo le aree dei baffi
|
|
if ( m_Params.m_nLeadLinkType == SAWROU_LL_INT) {
|
|
|
|
// stima dell'elevazione per il calcolo dei baffi considerando la quota minima della sezione
|
|
Point3d ptElev = b3Sect.GetMin() ;
|
|
ptElev.ToGlob( frSect) ;
|
|
int nStep = 50 ;
|
|
double dStep = b3Sect.GetDimX() / nStep ;
|
|
double dElev = 0 ;
|
|
for ( int i = 0 ; i <= nStep ; i ++) {
|
|
ptElev += i * dStep * frSect.VersX() ;
|
|
double dCurrElev = 0 ;
|
|
GetElevation( m_nPhase, ptElev, ptElev + dGuideLen * vtGdDir, m_vtCorr, dCurrElev) ;
|
|
if ( dCurrElev > dElev)
|
|
dElev = dCurrElev ;
|
|
}
|
|
double dDeltaT = 0 ;
|
|
if ( dElev > 0.0 && dElev < 0.5 * m_TParams.m_dDiam)
|
|
dDeltaT = sqrt( dElev * m_TParams.m_dDiam - dElev * dElev) ;
|
|
|
|
// individuo i tratti di bordo che definiscono il contorno delle regioni dei baffi. In generale sono i tratti compresi
|
|
// tra le due sottocurve parallele alla guida, ma può anche capitare che una di queste due sottocurve collassi in un punto
|
|
PtrOwner<ICurve> pBorderStart, pBorderEnd ;
|
|
// individuo i due sottotratti paralleli alla guida
|
|
int nCrv1 = -1, nCrv2 = -1 ;
|
|
for ( int i = 0 ; i < pBorder->GetCurveCount() ; i++) {
|
|
Vector3d vtDir ; pBorder->GetCurve( i)->GetStartDir( vtDir) ;
|
|
if ( AreSameVectorApprox( vtDir, vtGdDir))
|
|
nCrv1 = i ;
|
|
else if ( AreOppositeVectorApprox( vtDir, vtGdDir))
|
|
nCrv2 = i ;
|
|
if ( nCrv1 != -1 && nCrv2 != -1)
|
|
break ;
|
|
}
|
|
|
|
if ( nCrv1 != -1 && nCrv2 != -1) {
|
|
// se ho indiduato due sottotratti
|
|
pBorderEnd.Set( pBorder->CopyParamRange( nCrv1 + 1, nCrv2)) ;
|
|
pBorderStart.Set( pBorder->CopyParamRange( nCrv2 + 1, nCrv1)) ;
|
|
}
|
|
else if ( nCrv1 != -1 || nCrv2 != -1) {
|
|
// individuo il punto in cui è collassato uno dei due sottotratti come il vertice più distante dall'altro sottotratto
|
|
int nCrvId = ( nCrv1 != -1 ? nCrv1 : nCrv2) ;
|
|
Point3d ptLine ; pBorder->GetCurve( nCrvId)->GetStartPoint( ptLine) ;
|
|
int nJoint = -1 ;
|
|
double dMaxSqDist = -1 ;
|
|
for ( int i = 0 ; i < pBorder->GetCurveCount() ; i ++) {
|
|
if ( i == nCrvId || i == ( nCrvId + 1) % pBorder->GetCurveCount())
|
|
continue ;
|
|
Point3d ptCurr ; pBorder->GetCurve( i)->GetStartPoint( ptCurr) ;
|
|
double dProj = ( ptCurr - ptLine) * vtGdDir ;
|
|
double dSqDist = SqDist( ptCurr, ptLine) - dProj * dProj ;
|
|
if ( dSqDist > dMaxSqDist) {
|
|
dMaxSqDist = dSqDist ;
|
|
nJoint = i ;
|
|
}
|
|
}
|
|
if ( nJoint == -1)
|
|
return false ;
|
|
pBorderEnd.Set( pBorder->CopyParamRange( nCrvId + 1, nJoint)) ;
|
|
pBorderStart.Set( pBorder->CopyParamRange( nJoint, nCrvId)) ;
|
|
if ( nCrv1 == -1)
|
|
swap( pBorderEnd, pBorderStart) ;
|
|
}
|
|
else
|
|
return false ;
|
|
|
|
if ( IsNull( pBorderStart) || IsNull( pBorderEnd))
|
|
return false ;
|
|
|
|
// rettangolo per parte iniziale
|
|
PtrOwner<ICurveComposite> pCutStart( CreateCurveComposite()) ;
|
|
if ( IsNull( pCutStart))
|
|
return false ;
|
|
pCutStart->AddCurve( pBorderStart->Clone()) ;
|
|
pCutStart->Invert() ;
|
|
Point3d ptS ; pBorderStart->GetStartPoint( ptS) ;
|
|
pCutStart->AddLine( ptS - dDeltaT * vtGdDir) ;
|
|
pBorderStart->Translate( - dDeltaT * vtGdDir) ;
|
|
pCutStart->AddCurve( Release( pBorderStart)) ;
|
|
pCutStart->Close() ;
|
|
int nId2 = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPathId, Release( pCutStart)) ;
|
|
m_pGeomDB->SetName( nId2, MCH_PV_PRE_CUT) ;
|
|
m_pGeomDB->SetMaterial( nId2, BLUE) ;
|
|
|
|
// rettangolo per parte finale
|
|
PtrOwner<ICurveComposite> pCutEnd( CreateCurveComposite()) ;
|
|
if ( IsNull( pCutEnd))
|
|
return false ;
|
|
pCutEnd->AddCurve( pBorderEnd->Clone()) ;
|
|
pCutEnd->Invert() ;
|
|
Point3d ptE ; pBorderEnd->GetStartPoint( ptE) ;
|
|
pCutEnd->AddLine( ptE + dDeltaT * vtGdDir) ;
|
|
pBorderEnd->Translate( dDeltaT * vtGdDir) ;
|
|
pCutEnd->AddCurve( Release( pBorderEnd)) ;
|
|
pCutEnd->Close() ;
|
|
int nId3 = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPathId, Release( pCutEnd)) ;
|
|
m_pGeomDB->SetName( nId3, MCH_PV_POST_CUT) ;
|
|
m_pGeomDB->SetMaterial( nId3, BLUE) ;
|
|
|
|
// regione di ingresso al taglio
|
|
int nRsId = ExeCreateSurfFlatRegion( nPathId, { nId2}, nullptr) ;
|
|
m_pGeomDB->SetName( nRsId, MCH_PV_RLICUT) ;
|
|
m_pGeomDB->SetMaterial( nRsId, INVISIBLE) ;
|
|
// regione di uscita dal taglio
|
|
int nReId = ExeCreateSurfFlatRegion( nPathId, { nId3}, nullptr) ;
|
|
m_pGeomDB->SetName( nReId, MCH_PV_RLOCUT) ;
|
|
m_pGeomDB->SetMaterial( nReId, INVISIBLE) ;
|
|
// regione di taglio completo per nesting
|
|
int nRId = m_pGeomDB->CopyGlob( nRrId, GDB_ID_NULL, nPathId) ;
|
|
ExeSurfFrAdd( nRId, nRsId) ;
|
|
ExeSurfFrAdd( nRId, nReId) ;
|
|
m_pGeomDB->SetName( nRId, MCH_PV_RCUT) ;
|
|
m_pGeomDB->SetMaterial( nRId, INVISIBLE) ;
|
|
// regione up coincide con quella ridotta
|
|
int nSurfUpId = m_pGeomDB->CopyGlob( nRrId, GDB_ID_NULL, nPathId) ;
|
|
m_pGeomDB->SetName( nSurfUpId, MCH_PV_UP_RAWCUT) ;
|
|
m_pGeomDB->SetMaterial( nSurfUpId, INVISIBLE) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|