//---------------------------------------------------------------------------- // EgalTech 2015-2015 //---------------------------------------------------------------------------- // File : Sawing.cpp Data : 24.10.15 Versione : 1.6j3 // Contenuto : Implementazione gestione tagli con lama. // // Note : Questa lavorazione è sempre espressa nel riferimento globale. // // Modifiche : 07.06.15 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "MachMgr.h" #include "DllMain.h" #include "Sawing.h" #include "OperationConst.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/EGkChainCurves.h" #include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EGkSfrCreate.h" #include "/EgtDev/Include/EGkSurfTriMesh.h" #include "/EgtDev/Include/EGkUserObjFactory.h" #include "/EgtDev/Include/EGnStringKeyVal.h" #include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EgtPointerOwner.h" // per far dimenticare macro di WinUser.h #undef GetClassName using namespace std ; //------------------------------ Errors -------------------------------------- // 2201 = "Error in Sawing : UpdateToolData failed" // 2202 = "Error in Sawing : Center work not allowed with side angle" // 2203 = "Error in Sawing : External side angle HeadSide must equal WorkSide" // 2204 = "Error in Sawing : Internal side angle HeadSide must opposite WorkSide" // 2205 = "Error in Sawing : Depth not computable" // 2206 = "Error in Sawing : machining depth (xx) bigger than MaxMaterial (yy)" // 2207 = "Error in Sawing : SideAngle not allowed on Internal Arc" // 2208 = "Error in Sawing : Entity CalculateToolAndCorrVersors" // 2209 = "Error in Sawing : Entity AdjustForSide" // 2210 = "Error in Sawing : Entity GetElevation" // 2211 = "Error in Sawing : Entity AdjustForEdges" // 2212 = "Error in Sawing : Entity CalculateToolAndCorrVersors 2nd" // 2213 = "Error in Sawing : Center work not allowed with internal arc" // 2214 = "Error in Sawing : Chaining failed" // 2215 = "Error in Sawing : axes values not calculable" // 2216 = "Error in Sawing : outstroke xxx" // 2217 = "Error in Sawing : link movements not calculable" // 2218 = "Error in Sawing : link outstroke xxx" // 2219 = "Error in Sawing : post apply not calculable" // 2251 = "Warning in Sawing : Skipped entity xxx" // 2252 = "Warning in Sawing : No machinable path" // 2253 = "Warning in Sawing : Tool name changed (xx)" // 2254 = "Warning in Sawing : Tool data changed (xx)" // 2255 = "Warning in Sawing : skipped Path too short" // 2256 = "Warning in Sawing : Skipped Arc" // 2257 = "Warning in Sawing : skipped Entity too small" // 2258 = "Warning in Sawing : Radius too small in ExtSawArc" // 2259 = "Warning in Sawing : Radius too small in IntSawArc" //---------------------------------------------------------------------------- struct FseVar { double dLenStart ; double dPuStart ; double dLenEnd ; double dPuEnd ; FseVar( void) : dLenStart( 0), dPuStart( 0), dLenEnd( 0), dPuEnd( 0) {} } ; //---------------------------------------------------------------------------- USEROBJ_REGISTER( GetOperationClass( OPER_SAWING), Sawing) ; //---------------------------------------------------------------------------- const string& Sawing::GetClassName( void) const { return USEROBJ_GETNAME( Sawing) ; } //---------------------------------------------------------------------------- Sawing* Sawing::Clone( void) const { // alloco oggetto Sawing* pSaw = new(nothrow) Sawing ; // eseguo copia dei dati if ( pSaw != nullptr) { try { pSaw->m_vId = m_vId ; 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 Sawing::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 ; 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 Sawing::Save( int nBaseId, STRVECTOR& vString) const { try { int nSize = 1 + m_Params.GetSize() + m_TParams.GetSize() + 3 ; 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 ; } catch( ...) { return false ; } return true ; } //---------------------------------------------------------------------------- bool Sawing::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 ; } } return true ; } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- Sawing::Sawing( 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 ; } //---------------------------------------------------------------------------- bool Sawing::Prepare( const string& sSawName) { // verifico il gestore lavorazioni if ( m_pMchMgr == nullptr) return false ; // recupero il gestore DB utensili della macchina corrente ToolsMgr* pTMgr = m_pMchMgr->GetCurrToolsMgr() ; if ( pTMgr == nullptr) return false ; // recupero il gestore DB lavorazioni della macchina corrente MachiningsMgr* pMMgr = m_pMchMgr->GetCurrMachiningsMgr() ; if ( pMMgr == nullptr) return false ; // ricerca della lavorazione di libreria con il nome indicato const SawingData* pDdata = GetSawingData( pMMgr->GetMachining( sSawName)) ; if ( pDdata == nullptr) return false ; m_Params = *pDdata ; // ricerca dell'utensile usato dalla lavorazione const ToolData* pTdata = pTMgr->GetTool( m_Params.m_ToolUuid) ; if ( pTdata == nullptr) return false ; m_TParams = *pTdata ; m_Params.m_sToolName = m_TParams.m_sName ; return true ; } //---------------------------------------------------------------------------- bool Sawing::SetParam( int nType, bool bVal) { switch ( nType) { case MPA_INVERT : if ( bVal != m_Params.m_bInvert) m_nStatus |= MCH_ST_PARAM_MODIF ; m_Params.m_bInvert = bVal ; return true ; } return false ; } //---------------------------------------------------------------------------- bool Sawing::SetParam( int nType, int nVal) { switch ( nType) { case MPA_WORKSIDE : if ( ! m_Params.VerifyWorkSide( nVal)) return false ; if ( nVal != m_Params.m_nWorkSide) m_nStatus |= MCH_ST_PARAM_MODIF ; m_Params.m_nWorkSide = nVal ; return true ; 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_LEADINTYPE : if ( ! m_Params.VerifyLeadInType( nVal)) return false ; if ( nVal != m_Params.m_nLeadInType) m_nStatus |= MCH_ST_PARAM_MODIF ; m_Params.m_nLeadInType = nVal ; return true ; case MPA_EXTLINKTYPE : if ( ! m_Params.VerifyExtLinkType( nVal)) return false ; if ( nVal != m_Params.m_nExtLinkType) m_nStatus |= MCH_ST_PARAM_MODIF ; m_Params.m_nExtLinkType = nVal ; return true ; case MPA_LEADOUTTYPE : if ( ! m_Params.VerifyLeadOutType( nVal)) return false ; if ( nVal != m_Params.m_nLeadOutType) m_nStatus |= MCH_ST_PARAM_MODIF ; m_Params.m_nLeadOutType = nVal ; return true ; case MPA_CURVEUSE : if ( ! m_Params.VerifyCurveUse( nVal)) return false ; if ( nVal != m_Params.m_nCurveUse) m_nStatus |= MCH_ST_PARAM_MODIF ; m_Params.m_nCurveUse = 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 Sawing::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_BACKFEED : if ( AreSameLenValue( dVal, m_TParams.m_dFeed)) dVal = 0 ; if ( ! AreSameLenValue( dVal, m_Params.m_dBackFeed)) m_nStatus |= MCH_ST_PARAM_MODIF ; m_Params.m_dBackFeed = dVal ; return true ; case MPA_SIDEANGFEED : if ( AreSameLenValue( dVal, m_TParams.m_dFeed)) dVal = 0 ; if ( ! AreSameLenValue( dVal, m_Params.m_dSideAngFeed)) m_nStatus |= MCH_ST_PARAM_MODIF ; m_Params.m_dSideAngFeed = 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_STEP : if ( ! AreSameLenValue( dVal, m_Params.m_dStep)) m_nStatus |= MCH_ST_PARAM_MODIF ; m_Params.m_dStep = dVal ; return true ; case MPA_STEPBACK : if ( AreSameLenValue( dVal, m_Params.m_dStep)) dVal = UNKNOWN_PAR ; if ( ! AreSameLenValue( dVal, m_Params.m_dStepBack)) m_nStatus |= MCH_ST_PARAM_MODIF ; m_Params.m_dStepBack = dVal ; return true ; case MPA_STEPLAST : if ( AreSameLenValue( dVal, m_Params.m_dStepBack)) dVal = UNKNOWN_PAR ; if ( ! AreSameLenValue( dVal, m_Params.m_dStepLast)) m_nStatus |= MCH_ST_PARAM_MODIF ; m_Params.m_dStepLast = dVal ; return true ; case MPA_STEPEXTARC : if ( ! AreSameLenValue( dVal, m_Params.m_dStepExtArc)) m_nStatus |= MCH_ST_PARAM_MODIF ; m_Params.m_dStepExtArc = dVal ; return true ; case MPA_STEPINTARC : if ( ! AreSameLenValue( dVal, m_Params.m_dStepIntArc)) m_nStatus |= MCH_ST_PARAM_MODIF ; m_Params.m_dStepIntArc = dVal ; return true ; case MPA_STEPSIDEANG : if ( AreSameLenValue( dVal, m_Params.m_dStep)) dVal = UNKNOWN_PAR ; if ( ! AreSameLenValue( dVal, m_Params.m_dStepSideAng)) m_nStatus |= MCH_ST_PARAM_MODIF ; m_Params.m_dStepSideAng = dVal ; return true ; case MPA_STEPSIDEANGBACK : if ( AreSameLenValue( dVal, m_Params.m_dStepSideAng) || ( IsUnknownValue( m_Params.m_dStepSideAng) && AreSameLenValue( dVal, m_Params.m_dStep))) dVal = UNKNOWN_PAR ; if ( ! AreSameLenValue( dVal, m_Params.m_dStepSideAngBack)) m_nStatus |= MCH_ST_PARAM_MODIF ; m_Params.m_dStepSideAngBack = dVal ; return true ; case MPA_SIDEANGLE : if ( ! m_Params.VerifySideAngle( dVal)) return false ; if ( ! AreSameAngValue( dVal, m_Params.m_dSideAngle)) m_nStatus |= MCH_ST_PARAM_MODIF ; m_Params.m_dSideAngle = 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 ; 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_LIELEV : if ( ! AreSameLenValue( dVal, m_Params.m_dLiElev)) m_nStatus |= MCH_ST_PARAM_MODIF ; m_Params.m_dLiElev = dVal ; return true ; case MPA_LITANG : if ( ! AreSameLenValue( dVal, m_Params.m_dLiTang)) m_nStatus |= MCH_ST_PARAM_MODIF ; m_Params.m_dLiTang = dVal ; return true ; } return false ; } //---------------------------------------------------------------------------- bool Sawing::SetParam( int nType, const string& sVal) { switch ( nType) { case MPA_TOOL : { const ToolData* pTdata ; if ( ! m_Params.VerifyTool( m_pMchMgr->GetCurrToolsMgr(), sVal, pTdata)) return false ; 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 Sawing::SetGeometry( const SELVECTOR& vIds) { // verifico validità gestore DB geometrico if ( m_pGeomDB == nullptr) return false ; // reset della geometria corrente m_vId.clear() ; // verifico che gli identificativi rappresentino delle entità ammissibili int nType = GEO_NONE ; for ( const auto& Id : vIds) { // test sull'entità int nSubs ; if ( ! VerifyGeometry( Id, nSubs, nType)) { string sInfo = "Warning in Sawing : Skipped entity " + ToString( Id) ; m_pMchMgr->SetWarning( 2251, sInfo) ; continue ; } // posso aggiungere alla lista m_vId.emplace_back( Id) ; } // aggiorno lo stato m_nStatus |= MCH_ST_GEO_MODIF ; // restituisco presenza geometria da lavorare return ( ! m_vId.empty() || vIds.empty()) ; } //---------------------------------------------------------------------------- bool Sawing::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 ; // recupero gruppo per geometria ausiliaria int nAuxId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_AUX) ; bool bChain = false ; // se non c'è, lo aggiungo if ( nAuxId == GDB_ID_NULL) { nAuxId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ; if ( nAuxId == GDB_ID_NULL) return false ; m_pGeomDB->SetName( nAuxId, MCH_AUX) ; m_pGeomDB->SetStatus( nAuxId, GDB_ST_OFF) ; bChain = true ; } // altrimenti, se chiesto ricalcolo, lo svuoto else if ( bRecalc) { m_pGeomDB->EmptyGroup( nAuxId) ; bChain = true ; } // aggiorno dati geometrici dell'utensile if ( ! UpdateToolData()) { m_pMchMgr->SetLastError( 2201, "Error in Sawing : UpdateToolData failed") ; return false ; } // se necessario, eseguo concatenamento ed inserisco i percorsi sotto la geometria ausiliaria if ( bChain && ! Chain( nAuxId)) { m_pMchMgr->SetLastError( 2214, "Error in Sawing : Chaining failed") ; return false ; } // verifiche per angolo di sbandamento if ( ! VerifySideAngle()) return false ; // recupero gruppo per anteprima di lavorazione (PreView) int nPvId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_PV) ; // se non c'è, lo aggiungo if ( nPvId == GDB_ID_NULL) { nPvId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ; if ( nPvId == GDB_ID_NULL) return false ; m_pGeomDB->SetName( nPvId, MCH_PV) ; } // altrimenti lo svuoto else m_pGeomDB->EmptyGroup( nPvId) ; // calcolo anteprima di ogni singola catena int nPathId = m_pGeomDB->GetFirstGroupInGroup( nAuxId) ; while ( nPathId != GDB_ID_NULL) { if ( ! ProcessPath( nPathId, nPvId, GDB_ID_NULL)) return false ; nPathId = m_pGeomDB->GetNextGroup( nPathId) ; } return true ; } //---------------------------------------------------------------------------- bool Sawing::Apply( bool bRecalc, 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 bool bToolChanged = true ; if ( ! UpdateToolData( &bToolChanged)) { m_pMchMgr->SetLastError( 2201, "Error in Sawing : UpdateToolData failed") ; return false ; } // verifico se necessario continuare nell'aggiornamento if ( ! bRecalc && ! bToolChanged && ( m_nStatus == MCH_ST_OK || ( ! bPostApply && m_nStatus == MCH_ST_NO_POSTAPPL))) { // confermo i percorsi di lavorazione m_nCuts = nCurrCuts ; LOG_DBG_INFO( GetEMkLogger(), "Sawing apply skipped : status already ok") ; // eseguo aggiornamento assi macchina e collegamento con operazione precedente if ( ! Update( bPostApply)) return false ; 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) ; bool bChain = false ; // se non c'è, lo aggiungo if ( nAuxId == GDB_ID_NULL) { nAuxId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ; if ( nAuxId == GDB_ID_NULL) return false ; m_pGeomDB->SetName( nAuxId, MCH_AUX) ; m_pGeomDB->SetStatus( nAuxId, GDB_ST_OFF) ; bChain = true ; } // altrimenti, se chiesto ricalcolo, lo svuoto else if ( bRecalc) { m_pGeomDB->EmptyGroup( nAuxId) ; bChain = true ; } // se necessario, eseguo concatenamento ed inserisco i percorsi sotto la geometria ausiliaria if ( bChain && ! Chain( nAuxId)) { m_pMchMgr->SetLastError( 2214, "Error in Sawing : Chaining failed") ; return false ; } // verifiche per angolo di sbandamento if ( ! VerifySideAngle()) return false ; // recupero gruppo per geometria di lavorazione (Cutter Location) int nClId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_CL) ; // se non c'è, lo aggiungo if ( nClId == GDB_ID_NULL) { nClId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ; if ( nClId == GDB_ID_NULL) return false ; m_pGeomDB->SetName( nClId, MCH_CL) ; } // altrimenti lo svuoto else m_pGeomDB->EmptyGroup( nClId) ; // lavoro ogni singola catena bool bOk = true ; int nPathId = m_pGeomDB->GetFirstGroupInGroup( nAuxId) ; while ( nPathId != GDB_ID_NULL) { if ( ! ProcessPath( nPathId, GDB_ID_NULL, nClId)) bOk = false ; nPathId = m_pGeomDB->GetNextGroup( nPathId) ; } if ( ! bOk) return false ; // 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(), "Sawing apply done") ; return true ; } //---------------------------------------------------------------------------- bool Sawing::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( 2252, "Warning in Sawing : No machinable path") ; return true ; } // 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( 2215, "Error in Sawing : axes values not calculable") ; else m_pMchMgr->SetLastError( 2216, "Error in Sawing : outstroke ") ; return false ; } // aggiustamento feed per movimenti 4 assi AdjustFeeds() ; // assegno estremi degli assi dei vari percorsi di lavorazione e della lavorazione nel suo complesso CalcAndSetAxesBBox() ; // 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( 2217, "Error in Sawing : link movements not calculable") ; else m_pMchMgr->SetLastError( 2218, "Error in Sawing : link outstroke ") ; return false ; } // esecuzione eventuali personalizzazioni string sErr ; if ( bPostApply && ! PostApply( sErr)) { if ( ! IsEmptyOrSpaces( sErr)) m_pMchMgr->SetLastError( 2219, sErr) ; else m_pMchMgr->SetLastError( 2219, "Error in Sawing : post apply not calculable") ; return false ; } return true ; } //---------------------------------------------------------------------------- bool Sawing::AdjustFeeds( void) { // controlli su GeomDB e simili non ripetuti perchè già fatti // recupero gruppo della geometria di lavorazione (Cutter Location) int nClId = m_pGeomDB->GetFirstNameInGroup( GetOwner(), MCH_CL) ; if ( nClId == GDB_ID_NULL) return false ; // ciclo sui gruppi CL int nClPathId = m_pGeomDB->GetFirstGroupInGroup( nClId) ; while ( nClPathId != GDB_ID_NULL) { // ciclo su tutte le entità del percorso CL for ( int nEntId = m_pGeomDB->GetFirstInGroup( nClPathId) ; nEntId != GDB_ID_NULL ; nEntId = m_pGeomDB->GetNext( nEntId)) { // recupero i dati Cam dell'entità CamData* pCamData = GetCamData( m_pGeomDB->GetUserObj( nEntId)) ; if ( pCamData == nullptr) continue ; // se arco if ( pCamData->IsArc()) { // determino lunghezza di movimento del tip utensile Vector3d vtCenEnd = pCamData->GetEndPoint() - pCamData->GetCenter() ; Vector3d vtTipRad = vtCenEnd - vtCenEnd * pCamData->GetNormDir() * pCamData->GetNormDir() ; double dTipRad = vtTipRad.Len() ; double dTipAngCen = pCamData->GetAngCen() ; double dTipLen = dTipRad * abs( dTipAngCen) * DEGTORAD ; // determino lunghezza di movimento degli assi utensile double dAxRad = pCamData->GetAxesRad() ; double dAxAngCen = pCamData->GetAxesAngCen() ; double dAxLenXYZ = dAxRad * dAxAngCen * DEGTORAD ; double dAxLen = sqrt( max( dAxLenXYZ * dAxLenXYZ + dAxAngCen * dAxAngCen, 0.)) ; // correggo la feed di movimento if ( dTipLen > EPS_SMALL && dAxLen > EPS_SMALL) { double dCoeff = dAxLen / dTipLen ; double dOrigFeed = pCamData->GetOrigFeed() ; if ( dOrigFeed < 0) { dOrigFeed = pCamData->GetFeed() ; pCamData->SetOrigFeed( dOrigFeed) ; } pCamData->SetFeed( dOrigFeed * dCoeff) ; } } } nClPathId = m_pGeomDB->GetNextGroup( nClPathId) ; } return true ; } //---------------------------------------------------------------------------- bool Sawing::GetParam( int nType, bool& bVal) const { switch ( nType) { case MPA_INVERT : bVal = m_Params.m_bInvert ; return true ; } bVal = false ; return false ; } //---------------------------------------------------------------------------- bool Sawing::GetParam( int nType, int& nVal) const { switch ( nType) { case MPA_TYPE : nVal = MT_SAWING ; return true ; case MPA_WORKSIDE : nVal = m_Params.m_nWorkSide ; return true ; case MPA_HEADSIDE : nVal = m_Params.m_nHeadSide ; return true ; case MPA_STEPTYPE : nVal = m_Params.m_nStepType ; return true ; case MPA_LEADINTYPE : nVal = m_Params.m_nLeadInType ; return true ; case MPA_EXTLINKTYPE : nVal = m_Params.m_nExtLinkType ; return true ; case MPA_LEADOUTTYPE : nVal = m_Params.m_nLeadOutType ; return true ; case MPA_CURVEUSE : nVal = m_Params.m_nCurveUse ; return true ; case MPA_SCC : nVal = m_Params.m_nSolCh ; return true ; } nVal = 0 ; return false ; } //---------------------------------------------------------------------------- bool Sawing::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_BACKFEED : dVal = GetBackFeed() ; return true ; case MPA_SIDEANGFEED : dVal = GetSideAngFeed() ; 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_STEP : dVal = m_Params.m_dStep ; return true ; case MPA_STEPBACK : dVal = GetStepBack() ; return true ; case MPA_STEPLAST : dVal = GetStepLast() ; return true ; case MPA_STEPEXTARC : dVal = m_Params.m_dStepExtArc ; return true ; case MPA_STEPINTARC : dVal = m_Params.m_dStepIntArc ; return true ; case MPA_STEPSIDEANG : dVal = GetStepSideAng() ; return true ; case MPA_STEPSIDEANGBACK : dVal = GetStepSideAngBack() ; return true ; case MPA_SIDEANGLE : dVal = m_Params.m_dSideAngle ; return true ; case MPA_STARTADDLEN : dVal = m_Params.m_dStartAddLen ; return true ; case MPA_ENDADDLEN : dVal = m_Params.m_dEndAddLen ; return true ; case MPA_APPROX : dVal = m_Params.m_dApprox ; return true ; case MPA_LIELEV : dVal = m_Params.m_dLiElev ; return true ; case MPA_LITANG : dVal = m_Params.m_dLiTang ; return true ; } dVal = 0 ; return false ; } //---------------------------------------------------------------------------- bool Sawing::GetParam( int nType, string& sVal) const { switch ( nType) { case MPA_NAME : sVal = m_Params.m_sName ; return true ; case MPA_TOOL : sVal = m_Params.m_sToolName ; return true ; case MPA_DEPTH_STR : sVal = m_Params.m_sDepth ; return true ; case MPA_TUUID : sVal = ToString( m_Params.m_ToolUuid) ; return true ; case MPA_UUID : sVal = ToString( m_Params.m_Uuid) ; return true ; 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& Sawing::GetToolData( void) const { return m_TParams ; } //---------------------------------------------------------------------------- bool Sawing::UpdateToolData( bool* pbChanged) { // recupero il gestore DB utensili della macchina corrente ToolsMgr* pTMgr = m_pMchMgr->GetCurrToolsMgr() ; if ( pTMgr == nullptr) return false ; // recupero l'utensile nel DB utensili const ToolData* pTdata = pTMgr->GetTool( m_Params.m_ToolUuid) ; if ( pTdata == nullptr) return false ; // verifico se sono diversi (ad esclusione del nome) m_TParams.m_sName = pTdata->m_sName ; bool bChanged = ! SameTool( m_TParams, *pTdata) ; // aggiorno comunque i parametri m_TParams = *pTdata ; // eventuali segnalazioni if ( ! EqualNoCase( m_Params.m_sToolName, m_TParams.m_sName)) { string sInfo = "Warning in Sawing : tool name changed (" + m_Params.m_sToolName + "->" + m_TParams.m_sName + ")" ; m_pMchMgr->SetWarning( 2253, sInfo) ; m_Params.m_sToolName = m_TParams.m_sName ; } if ( bChanged) { string sInfo = "Warning in Sawing : tool data changed (" + m_Params.m_sToolName + ")" ; m_pMchMgr->SetWarning( 2254, sInfo) ; } // se definito parametro di ritorno, lo assegno if ( pbChanged != nullptr) *pbChanged = bChanged ; return true ; } //---------------------------------------------------------------------------- bool Sawing::GetGeometry( SELVECTOR& vIds) const { // restituisco l'elenco delle entità vIds = m_vId ; return true ; } //---------------------------------------------------------------------------- bool Sawing::AdjustEndPointForAxesCalc( const CamData* pCamData, Point3d& ptP) const { // compenso il raggio dell'utensile ptP += pCamData->GetCorrDir() * ( m_TParams.m_dDiam / 2) ; return true ; } //---------------------------------------------------------------------------- bool Sawing::VerifyGeometry( SelData Id, int& nSubs, int& nType) { // ammessi : tutte curve o tutte facce di trimesh const IGeoObj* pGObj = m_pGeomDB->GetGeoObj( Id.nId) ; if ( pGObj == nullptr) return false ; // se ammesse curve ed è tale if ( ( nType == GEO_NONE || nType == GEO_CURVE) && ( pGObj->GetType() & GEO_CURVE) != 0) { nType = GEO_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) ; } // se altrimenti ammesse superfici trimesh ed è tale else if ( ( nType == GEO_NONE || nType == GEO_SURF) && pGObj->GetType() == SRF_TRIMESH) { nType = GEO_SURF ; const ISurfTriMesh* pSurf = ::GetSurfTriMesh( pGObj) ; if ( pSurf == nullptr) return false ; // se direttamente la superficie if ( Id.nSub == SEL_SUB_ALL) { nSubs = pSurf->GetFacetCount() ; } // altrimenti faccia di superficie trimesh else { // se faccia non esistente if ( Id.nSub > pSurf->GetFacetCount()) return false ; // tutto bene nSubs = 0 ; } return true ; } // se altrimenti ammesse regioni ed è tale else if ( ( nType == GEO_NONE || nType == GEO_SURF) && pGObj->GetType() == SRF_FLATRGN) { nType = GEO_SURF ; const ISurfFlatRegion* pReg = ::GetSurfFlatRegion( pGObj) ; if ( pReg == nullptr) return false ; // se direttamente la regione if ( Id.nSub == SEL_SUB_ALL) { nSubs = pReg->GetChunkCount() ; } // altrimenti chunk di regione else { // se chunk non esistente if ( Id.nSub >= pReg->GetChunkCount()) return false ; // tutto bene nSubs = 0 ; } return true ; } // altrimenti errore else return false ; } //---------------------------------------------------------------------------- ICurve* Sawing::GetCurve( SelData Id) { // ammessi : curve o facce di polymesh const IGeoObj* pGObj = m_pGeomDB->GetGeoObj( Id.nId) ; if ( pGObj == nullptr) return nullptr ; // ne recupero il riferimento globale Frame3d frGlob ; if ( ! m_pGeomDB->GetGlobFrame( Id.nId, frGlob)) return nullptr ; // se curva if ( ( pGObj->GetType() & GEO_CURVE) != 0) { PtrOwner pCurve ; // se direttamente curva if ( Id.nSub == SEL_SUB_ALL) { // recupero e duplico la curva const ICurve* pOriCurve = ::GetCurve( pGObj) ; if ( pOriCurve != nullptr) pCurve.Set( pOriCurve->Clone()) ; } // altrimenti sottocurva di composita else { // recupero la composita const ICurveComposite* pCompo = GetCurveComposite( pGObj) ; 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 ; // la porto in globale pCurve->ToGlob( frGlob) ; // la restituisco return Release( pCurve) ; } // se altrimenti superficie trimesh else if ( pGObj->GetType() == SRF_TRIMESH) { // recupero la trimesh const ISurfTriMesh* pSurf = ::GetSurfTriMesh( pGObj) ; if ( pSurf == nullptr) return nullptr ; // recupero l'indice della faccia int nFacet = ( ( Id.nSub == SEL_SUB_ALL) ? 0 : Id.nSub) ; // recupero i contorni della faccia POLYLINEVECTOR vPL ; pSurf->GetFacetLoops( nFacet, vPL) ; if ( vPL.empty()) return nullptr ; // recupero la normale esterna della faccia Vector3d vtN ; if ( ! pSurf->GetFacetNormal( nFacet, vtN)) return nullptr ; // creo la curva a partire da quello esterno PtrOwner pCrvCompo( CreateCurveComposite()) ; pCrvCompo->FromPolyLine( vPL[0]) ; if ( ! pCrvCompo->IsValid()) return nullptr ; // assegno l'estrusione dalla normale alla faccia pCrvCompo->SetExtrusion( vtN) ; // unisco le eventuali parti allineate pCrvCompo->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL) ; // la porto in globale pCrvCompo->ToGlob( frGlob) ; vtN.ToGlob( frGlob) ; // sistemazioni varie AdjustCurveFromSurf( pCrvCompo, TOOL_ORTUP, FACE_DOWN, 0, 1) ; // aggiusto lato lavoro e inverti, angolo di fianco e lato mandrino if ( m_Params.m_nWorkSide == SAW_WS_CENTER) m_Params.m_nWorkSide = SAW_WS_RIGHT ; m_Params.m_bInvert = ( m_Params.m_nWorkSide == SAW_WS_LEFT) ; double dSideAng ; Z_AX.GetAngle( vtN, dSideAng) ; // taglio verticale if ( abs( dSideAng - ANG_RIGHT) < 10 * EPS_ANG_SMALL) m_Params.m_dSideAngle = 0 ; // taglio soprasquadra else if ( dSideAng < ANG_RIGHT) { m_Params.m_dSideAngle = ANG_RIGHT - dSideAng ; m_Params.m_nHeadSide = ( m_Params.m_nWorkSide == SAW_WS_RIGHT ? SAW_HS_RIGHT : SAW_HS_LEFT) ; } // taglio sottosquadra else { m_Params.m_dSideAngle = ANG_RIGHT - dSideAng ; m_Params.m_nHeadSide = ( m_Params.m_nWorkSide == SAW_WS_RIGHT ? SAW_HS_LEFT : SAW_HS_RIGHT) ; } // assegno estrusione Z+ pCrvCompo->SetExtrusion( Z_AX) ; // la restituisco return Release( pCrvCompo) ; } // se altrimenti regione else if ( pGObj->GetType() == SRF_FLATRGN) { // recupero la regione const ISurfFlatRegion* pReg = ::GetSurfFlatRegion( pGObj) ; if ( pReg == nullptr) return nullptr ; // recupero l'indice del chunk int nChunk = ( ( Id.nSub == SEL_SUB_ALL) ? 0 : Id.nSub) ; // recupero il contorno esterno del chunk PtrOwner pCrvCompo( CreateCurveComposite()) ; if ( IsNull( pCrvCompo) || ! pCrvCompo->AddCurve( pReg->GetLoop( nChunk, 0))) return nullptr ; // recupero la normale della regione Vector3d vtN = pReg->GetNormVersor() ; if ( vtN.IsSmall()) return nullptr ; // assegno l'estrusione dalla normale alla faccia pCrvCompo->SetExtrusion( vtN) ; // unisco le eventuali parti allineate pCrvCompo->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL) ; // la porto in globale pCrvCompo->ToGlob( frGlob) ; vtN.ToGlob( frGlob) ; // sistemazioni varie AdjustCurveFromSurf( pCrvCompo, TOOL_ORTUP, FACE_DOWN, 0, 1) ; // aggiusto lato lavoro e inverti, angolo di fianco e lato mandrino if ( m_Params.m_nWorkSide == SAW_WS_CENTER) m_Params.m_nWorkSide = SAW_WS_RIGHT ; m_Params.m_bInvert = ( m_Params.m_nWorkSide == SAW_WS_LEFT) ; double dSideAng ; Z_AX.GetAngle( vtN, dSideAng) ; // taglio verticale if ( abs( dSideAng - ANG_RIGHT) < 10 * EPS_ANG_SMALL) m_Params.m_dSideAngle = 0 ; // taglio soprasquadra else if ( dSideAng < ANG_RIGHT) { m_Params.m_dSideAngle = ANG_RIGHT - dSideAng ; m_Params.m_nHeadSide = ( m_Params.m_nWorkSide == SAW_WS_RIGHT ? SAW_HS_RIGHT : SAW_HS_LEFT) ; } // taglio sottosquadra else { m_Params.m_dSideAngle = ANG_RIGHT - dSideAng ; m_Params.m_nHeadSide = ( m_Params.m_nWorkSide == SAW_WS_RIGHT ? SAW_HS_LEFT : SAW_HS_RIGHT) ; } // assegno estrusione Z+ pCrvCompo->SetExtrusion( Z_AX) ; // la restituisco return Release( pCrvCompo) ; } // altrimenti errore else return nullptr ; } //---------------------------------------------------------------------------- bool Sawing::Chain( int nGrpDestId) { // vettore puntatori alle curve ICURVEPOVECTOR vpCrvs ; vpCrvs.reserve( m_vId.size()) ; // recupero tutte le curve e le porto in globale for ( const auto& Id : m_vId) { // prendo curva vpCrvs.emplace_back( GetCurve( Id)) ; // ne verifico la validità if ( IsNull( vpCrvs.back())) { string sInfo = "Warning in Sawing : Skipped entity " + ToString( Id) ; m_pMchMgr->SetWarning( 2251, sInfo) ; vpCrvs.back().Reset() ; } } // preparo i dati per il concatenamento bool bFirst = true ; Point3d ptNear = ORIG ; double dToler = 10 * EPS_SMALL ; ChainCurves chainC ; chainC.Init( true, dToler, int( vpCrvs.size())) ; for ( size_t i = 0 ; i < vpCrvs.size() ; ++ i) { // recupero la curva e il suo riferimento ICurve* pCrv = vpCrvs[i] ; if ( pCrv == nullptr) continue ; // recupero i dati della curva necessari al concatenamento e li assegno Point3d ptStart, ptEnd ; Vector3d vtStart, vtEnd ; if ( ! pCrv->GetStartPoint( ptStart) || ! pCrv->GetStartDir( vtStart) || ! pCrv->GetEndPoint( ptEnd) || ! pCrv->GetEndDir( vtEnd)) return false ; if ( ! chainC.AddCurve( int( i + 1), ptStart, vtStart, ptEnd, vtEnd)) return false ; // se prima curva, assegno inizio della ricerca if ( bFirst) { ptNear = ptStart + 10 * EPS_SMALL * vtStart ; bFirst = false ; } } // recupero i percorsi concatenati int nCount = 0 ; INTVECTOR vnId2 ; while ( chainC.GetChainFromNear( ptNear, false, vnId2)) { // creo una curva composita PtrOwner pCrvCompo( CreateCurveComposite()) ; if ( IsNull( pCrvCompo)) return false ; // estrusione e spessore Vector3d vtExtr = Z_AX ; double dThick = 0 ; // vettore Id originali SELVECTOR vId2 ; vId2.reserve( vnId2.size()) ; // recupero le curve semplici e le inserisco nella curva composita for ( size_t i = 0 ; i < vnId2.size() ; ++ i) { int nId = abs( vnId2[i]) - 1 ; bool bInvert = ( vnId2[i] < 0) ; vId2.emplace_back( m_vId[nId]) ; // recupero la curva ICurve* pCrv = vpCrvs[nId] ; // se necessario, la inverto if ( bInvert) pCrv->Invert() ; // recupero eventuali estrusione e spessore Vector3d vtTemp ; if ( pCrv->GetExtrusion( vtTemp)) { vtExtr = vtTemp ; double dTemp ; if ( pCrv->GetThickness( dTemp) && abs( dTemp) > abs( dThick)) dThick = dTemp ; } // la aggiungo alla curva composta if ( ! pCrvCompo->AddCurve( ::Release( vpCrvs[nId]), true, dToler)) return false ; } // se non sono state inserite curve, vado oltre if ( pCrvCompo->GetCurveCount() == 0) continue ; // imposto estrusione e spessore pCrvCompo->SetExtrusion( vtExtr) ; pCrvCompo->SetThickness( dThick) ; // aggiorno il nuovo punto vicino pCrvCompo->GetEndPoint( ptNear) ; // creo nuovo gruppo int nPathId = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrpDestId, Frame3d()) ; if ( nPathId == GDB_ID_NULL) return false ; m_pGeomDB->SetName( nPathId, MCH_PATH + ToString( ++ nCount)) ; m_pGeomDB->SetInfo( nPathId, KEY_IDS, ToString( vId2)) ; // inserisco la curva composita nel gruppo destinazione int nNewId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPathId, ::Release( pCrvCompo)) ; if ( nNewId == GDB_ID_NULL) return false ; } return true ; } //---------------------------------------------------------------------------- bool Sawing::VerifySideAngle( void) { // verifiche per angolo di sbandamento if ( abs( m_Params.m_dSideAngle) > EPS_ANG_SMALL) { // non ammesso lato di lavoro in centro if ( m_Params.m_nWorkSide == SAW_WS_CENTER) { m_pMchMgr->SetLastError( 2202, "Error in Sawing : Center work not allowed with side angle") ; return false ; } // se angolo esterno lato mandrino deve uguagliare lato di lavoro if ( m_Params.m_dSideAngle > 0) { if ( m_Params.m_nWorkSide == SAW_WS_RIGHT) { if ( m_Params.m_nHeadSide == SAW_HS_LEFT) { m_pMchMgr->SetLastError( 2203, "Error in Sawing : External side angle HeadSide must equal WorkSide") ; m_Params.m_nHeadSide = SAW_HS_RIGHT ; } } if ( m_Params.m_nWorkSide == SAW_WS_LEFT) { if ( m_Params.m_nHeadSide == SAW_HS_RIGHT) { m_pMchMgr->SetLastError( 2203, "Error in Sawing : External side angle HeadSide must equal WorkSide") ; m_Params.m_nHeadSide = SAW_HS_LEFT ; } } } // altrimenti angolo interno, lato mandrino deve essere opposto a lato di lavoro else { if ( m_Params.m_nWorkSide == SAW_WS_RIGHT) { if ( m_Params.m_nHeadSide == SAW_HS_RIGHT) { m_pMchMgr->SetLastError( 2204, "Error in Sawing : Internal side angle HeadSide must opposite WorkSide") ; m_Params.m_nHeadSide = SAW_HS_LEFT ; } } if ( m_Params.m_nWorkSide == SAW_WS_LEFT) { if ( m_Params.m_nHeadSide == SAW_HS_LEFT) { m_pMchMgr->SetLastError( 2204, "Error in Sawing : Internal side angle HeadSide must opposite WorkSide") ; m_Params.m_nHeadSide = SAW_HS_RIGHT ; } } } } return true ; } //---------------------------------------------------------------------------- bool Sawing::ProcessPath( int nPathId, int nPvId, int nClId) { // recupero gruppo per geometria temporanea const string GRP_TEMP = "Temp" ; int nTempId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, GRP_TEMP) ; // se non c'è, lo aggiungo if ( nTempId == GDB_ID_NULL) { nTempId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_nOwnerId, Frame3d()) ; if ( nTempId == GDB_ID_NULL) return false ; m_pGeomDB->SetName( nTempId, GRP_TEMP) ; } // altrimenti lo svuoto else m_pGeomDB->EmptyGroup( nTempId) ; // in ogni caso lo dichiaro temporaneo e non visibile m_pGeomDB->SetLevel( nTempId, GDB_LV_TEMP) ; m_pGeomDB->SetStatus( nTempId, GDB_ST_OFF) ; // copio la curva composita da elaborare int nCrvId = m_pGeomDB->GetFirstInGroup( nPathId) ; if ( m_pGeomDB->GetGeoType( nCrvId) != CRV_COMPO) return false ; int nCopyId = m_pGeomDB->CopyGlob( nCrvId, GDB_ID_NULL, nTempId) ; if ( nCopyId == GDB_ID_NULL) return false ; ICurveComposite* pCompo = GetCurveComposite( m_pGeomDB->GetGeoObj( nCopyId)) ; // unisco le parti allineate if ( ! pCompo->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL)) return false ; // eventuale inversione percorso if ( m_Params.m_bInvert) pCompo->Invert() ; // verifico che il percorso sia abbastanza lungo double dLen ; pCompo->GetLength( dLen) ; if ( dLen + m_Params.m_dStartAddLen + m_Params.m_dEndAddLen < 10 * EPS_SMALL) { m_pMchMgr->SetWarning( 2255, "Warning in Sawing : skipped Path too short") ; return true ; } // eventuali allungamenti if ( m_Params.m_dStartAddLen > EPS_SMALL) { if ( ! pCompo->ExtendStartByLen( m_Params.m_dStartAddLen)) return false ; dLen += m_Params.m_dStartAddLen ; } if ( m_Params.m_dEndAddLen > EPS_SMALL) { if ( ! pCompo->ExtendEndByLen( m_Params.m_dEndAddLen)) return false ; dLen += m_Params.m_dEndAddLen ; } // eventuale accorciamenti (da fare dopo tutti gli allungamenti) if ( m_Params.m_dStartAddLen < - EPS_SMALL) { if ( ! pCompo->TrimStartAtLen( - m_Params.m_dStartAddLen)) return false ; dLen += m_Params.m_dStartAddLen ; } if ( m_Params.m_dEndAddLen < - EPS_SMALL) { if ( ! pCompo->TrimEndAtLen( dLen + m_Params.m_dEndAddLen)) return false ; dLen += m_Params.m_dEndAddLen ; } // elaboro la curva composita e la esplodo nelle curve componenti if ( m_Params.m_nCurveUse == SAW_CRV_APPROX || m_Params.m_nCurveUse == SAW_CRV_CONVEX) { // calcolo l'approssimazione lineare con eventuale convessità PolyLine PL ; int nType = ICurve::APL_STD ; if ( m_Params.m_nWorkSide == SAW_WS_LEFT) nType = (( m_Params.m_nCurveUse == SAW_CRV_APPROX) ? ICurve::APL_LEFT : ICurve::APL_LEFT_CONVEX) ; else if ( m_Params.m_nWorkSide == SAW_WS_RIGHT) nType = (( m_Params.m_nCurveUse == SAW_CRV_APPROX) ? ICurve::APL_RIGHT : ICurve::APL_RIGHT_CONVEX) ; if ( ! pCompo->ApproxWithLines( m_Params.m_dApprox, ANG_RIGHT, nType, PL)) return false ; // salvo estrusione e spessore Vector3d vtExtr ; pCompo->GetExtrusion( vtExtr) ; double dThick ; pCompo->GetThickness( dThick) ; // sostituisco la curva composita con la sua approssimazione if ( ! pCompo->Clear() || ! pCompo->FromPolyLine( PL)) return false ; // assegno estrusione e spessore originali pCompo->SetExtrusion( vtExtr) ; pCompo->SetThickness( dThick) ; } // se lama non centrata e richiesto, eseguo offset if ( m_Params.m_nWorkSide != SAW_WS_CENTER && abs( GetOffsL()) > EPS_SMALL) { double dOffs = ( m_Params.m_nWorkSide == SAW_WS_RIGHT) ? GetOffsL() : - GetOffsL() ; if ( ! pCompo->SimpleOffset( dOffs, ICurve::OFF_EXTEND)) return false ; } // recupero estrusione e spessore Vector3d vtExtr ; pCompo->GetExtrusion( vtExtr) ; double dThick ; pCompo->GetThickness( dThick) ; // recupero distanza da fondo dei grezzi interessati dal percorso double dRbDist, dAllRbDist ; double dToler = 2 * m_TParams.m_dThick + tan( abs( m_Params.m_dSideAngle) * DEGTORAD) * m_TParams.m_dMaxMat ; if ( ! GetDistanceFromRawBottom( m_nPhase, nCopyId, dToler, dRbDist, dAllRbDist)) return false ; if ( abs( dRbDist) < EPS_SMALL) dRbDist = dAllRbDist ; // valuto l'espressione dell'affondamento ExeLuaSetGlobNumVar( "TH", abs( dThick)) ; ExeLuaSetGlobNumVar( "RB", dRbDist) ; double dDepth ; string sMyDepth = m_Params.m_sDepth ; if ( ! ExeLuaEvalNumExpr( ToUpper( sMyDepth), &dDepth)) { m_pMchMgr->SetLastError( 2205, "Error in Sawing : Depth not computable") ; return false ; } // se spessore positivo, lo sottraggo dal risultato if ( dThick * vtExtr.z > 0) dDepth -= dThick ; // determino l'eccesso di taglio double dExtraCut = max( 0., dDepth - dRbDist) ; // determino la quota dal fondo del grezzo double dRbHeight = dRbDist - dDepth ; // correzione per angolo di fianco if ( abs( m_Params.m_dSideAngle) > EPS_ANG_SMALL) { // generale double dCoeff = 1 / cos( m_Params.m_dSideAngle * DEGTORAD) ; dDepth *= dCoeff ; dExtraCut *= dCoeff ; // se sottosquadra (controllo il lato opposto della lama, quindi ...) if ( m_Params.m_dSideAngle < 0) { dDepth += m_TParams.m_dThick * tan( abs( m_Params.m_dSideAngle) * DEGTORAD) ; dRbHeight -= m_TParams.m_dThick * sin( abs( m_Params.m_dSideAngle) * DEGTORAD) ; } } // verifico di non superare il massimo materiale if ( dDepth > m_TParams.m_dMaxMat + EPS_SMALL) { string sOut = "Error in Sawing : machining depth (" + ToString( dDepth, 1) + ") bigger than MaxMaterial (" + ToString( m_TParams.m_dMaxMat, 1) + ")" ; m_pMchMgr->SetLastError( 2206, sOut) ; return false ; } // recupero nome del path string sPathName ; m_pGeomDB->GetName( nPathId, sPathName) ; // verifiche sull'ampiezza dell'angolo al centro degli eventuali archi VerifyArcs( pCompo, 2 * MAX_ANG_CEN) ; // flag di curva chiusa bool bClosed = pCompo->IsClosed() ; // calcolo gli eventuali punti di perdita di tangenza e di cambio di concavità DBLVECTOR vU ; const double ANG_PERD_TG = 1.0 ; const ICurveArc* pArc = ( bClosed ? GetCurveArc( pCompo->GetLastCurve()) : nullptr) ; int nCurrConv = ( pArc != nullptr ? ( pArc->GetAngCenter() > 0 ? 1 : - 1) : 0) ; for ( int i = ( bClosed ? 0 : 1) ; i < pCompo->GetCurveCount() ; ++ i) { // verifico perdita di tangenza Point3d ptPrev, ptNext ; Vector3d vtPrev, vtNext ; if ( pCompo->GetPointTang( i, ICurve::FROM_MINUS, ptPrev, vtPrev) && pCompo->GetPointTang( i, ICurve::FROM_PLUS, ptNext, vtNext) && vtPrev * vtNext < cos( ANG_PERD_TG * DEGTORAD)) { vU.push_back( i) ; nCurrConv = 0 ; continue ; } // verifico cambio di concavità e/o lavorazione interna const ICurve* pCrv = pCompo->GetCurve( i) ; if ( pCrv->GetType() == CRV_ARC) { if ( GetCurveArc( pCrv)->GetAngCenter() > 0) { if ( nCurrConv == - 1 || m_Params.m_nWorkSide == SAW_WS_LEFT) vU.push_back( i) ; nCurrConv = 1 ; } else { if ( nCurrConv == 1 || m_Params.m_nWorkSide == SAW_WS_RIGHT) vU.push_back( i) ; nCurrConv = - 1 ; } } } // creo i tratti di curva continui e uniformi ICURVEPOVECTOR vpCrvs ; vpCrvs.reserve( vU.size() + 2) ; if ( vU.size() == 0) vpCrvs.emplace_back( pCompo->Clone()) ; else { if ( bClosed) { vpCrvs.emplace_back( pCompo->CopyParamRange( vU.back(), vU.front())) ; for ( int i = 1 ; i < int( vU.size()) ; ++ i) vpCrvs.emplace_back( pCompo->CopyParamRange( vU[i-1], vU[i])) ; } else { vpCrvs.emplace_back( pCompo->CopyParamRange( 0, vU.front())) ; for ( int i = 1 ; i < int( vU.size()) ; ++ i) vpCrvs.emplace_back( pCompo->CopyParamRange( vU[i-1], vU[i])) ; vpCrvs.emplace_back( pCompo->CopyParamRange( vU.back(), pCompo->GetCurveCount())) ; } } // ciclo sulle curve int nMaxInd = int( vpCrvs.size()) - 1 ; for ( int i = 0 ; i <= nMaxInd ; ++ i) { // curva precedente const ICurve* pCrvP = nullptr ; if ( i > 0) pCrvP = vpCrvs[i - 1] ; else if ( bClosed) pCrvP = vpCrvs[nMaxInd] ; // curva corrente const ICurve* pCrvC = vpCrvs[i] ; // curva successiva const ICurve* pCrvN = nullptr ; if ( i < nMaxInd) pCrvN = vpCrvs[i + 1] ; else if ( bClosed) pCrvN = vpCrvs[0] ; // elaborazioni sulla curva corrente string sName = sPathName + "_" + ToString( i) ; if ( ! ProcessEntity( pCrvP, pCrvC, pCrvN, dDepth, dExtraCut, dRbHeight, i == 0, i == nMaxInd, sName, nPvId, nClId)) return false ; } return true ; } //---------------------------------------------------------------------------- bool Sawing::ProcessEntity( const ICurve* pCrvP, const ICurve* pCrvC, const ICurve* pCrvN, double dDepth, double dExtraCut, double dRbHeight, bool bIsFirst, bool bIsLast, const string& sName, int nPvId, int nClId) { // la curva corrente deve essere una composita const ICurveComposite* pCompo = GetCurveComposite( pCrvC) ; if ( pCompo == nullptr) return false ; // se formata da una sola linea if ( pCompo->GetCurveCount() == 1 && pCompo->GetFirstCurve()->GetType() == CRV_LINE) { const ICurveLine* pLine = GetCurveLine( pCompo->GetFirstCurve()) ; if ( pLine == nullptr) return false ; return ProcessLine( pCrvP, pLine, pCrvN, dDepth, dExtraCut, dRbHeight, bIsFirst, bIsLast, sName, nPvId, nClId) ; } // altrimenti else { if ( m_Params.m_nCurveUse == SAW_CRV_KEEP) { // determino la convessità int nConv = 0 ; for ( int i = 0 ; i < pCompo->GetCurveCount() ; ++ i) { const ICurveArc* pArc = GetCurveArc( pCompo->GetCurve( i)) ; if ( pArc != nullptr) { nConv = ( pArc->GetAngCenter() > 0 ? 1 : - 1) ; break ; } } // se curva lavorata dall'esterno if ( ( nConv > 0 && m_Params.m_nWorkSide == SAW_WS_RIGHT) || ( nConv < 0 && m_Params.m_nWorkSide == SAW_WS_LEFT)) return ProcessExtCurve( pCrvP, pCompo, pCrvN, dDepth, dExtraCut, dRbHeight, bIsFirst, bIsLast, sName, nPvId, nClId) ; // altrimenti curva lavorata dall'interno else { // verifico che non ci sia angolo di fianco if ( abs( m_Params.m_dSideAngle) > EPS_ANG_SMALL) { m_pMchMgr->SetLastError( 2207, "Error in Sawing : SideAngle not allowed on Internal Arc") ; return false ; } // deve essere un solo arco const ICurveArc* pArc = GetCurveArc( pCompo->GetFirstCurve()) ; if ( pArc == nullptr || pCompo->GetCurveCount() != 1) return false ; // eseguo return ProcessIntArc( pCrvP, pArc, pCrvN, dDepth, dExtraCut, dRbHeight, bIsFirst, bIsLast, sName, nPvId, nClId) ; } } else { m_pMchMgr->SetWarning( 2256, "Warning in Sawing : Skipped Arc") ; return true ; } } } //---------------------------------------------------------------------------- bool Sawing::ProcessLine( const ICurve* pCrvP, const ICurveLine* pLineC, const ICurve* pCrvN, double dDepth, double dExtraCut, double dRbHeight, bool bIsFirst, bool bIsLast, const string& sName, int nPvId, int nClId) { // copio la curva PtrOwner pLine( pLineC->Clone()) ; if ( IsNull( pLine)) return false ; // direzione linea corrente Vector3d vtDirC ; pLine->GetStartDir( vtDirC) ; // calcolo i versori fresa e correzione Vector3d vtTool, vtCorr ; if ( ! CalculateToolAndCorrVersors( vtDirC, m_Params.m_nHeadSide, m_Params.m_nWorkSide, m_Params.m_dSideAngle, vtTool, vtCorr)) { m_pMchMgr->SetLastError( 2208, "Error in Sawing : Entity CalculateToolAndCorrVersors") ; return false ; } // correzioni per lato lama, lato mandrino if ( ! AdjustForSide( pLine)) { m_pMchMgr->SetLastError( 2209, "Error in Sawing : Entity AdjustForSide") ; return false ; } // aggiungo affondamento pLine->Translate( - vtCorr * dDepth) ; // calcolo elevazione (sui due bordi della striscia, leggermente allargata) const double DELTA_ELEV_THICK = 2.0 ; double dElev, dElev2 ; Vector3d vtToolH( vtTool.x, vtTool.y, 0) ; Vector3d vtSafe = vtToolH * DELTA_ELEV_THICK ; Vector3d vtThick = vtToolH * ( m_TParams.m_dThick / vtToolH.SqLen() + DELTA_ELEV_THICK) ; if ( ! GetElevation( m_nPhase, pLine->GetStart() - vtSafe, pLine->GetEnd() - vtSafe, vtCorr, dElev) || ! GetElevation( m_nPhase, pLine->GetStart() + vtThick, pLine->GetEnd() + vtThick, vtCorr, dElev2) ) { m_pMchMgr->SetLastError( 2210, "Error in Sawing : Entity GetElevation") ; return false ; } dElev = max( dElev, dElev2) ; // per gestire casi di taglio vicino a grezzi ma esterni ad essi if ( dElev < EPS_SMALL) dElev = max( 0., dDepth) ; // per posizionare l'anteprima alla quota standard else if ( nPvId != GDB_ID_NULL && nClId == GDB_ID_NULL) dElev = max( dElev, dDepth) ; // calcolo tipo angolo con precedente bool bExtAngPC = true ; if ( pCrvP != nullptr) { Vector3d vtDirP ; pCrvP->GetEndDir( vtDirP) ; double dAngPC ; vtDirP.GetAngleXY( vtDirC, dAngPC) ; if ( ( m_Params.m_nWorkSide == SAW_WS_LEFT && dAngPC > EPS_ANG_SMALL) || ( m_Params.m_nWorkSide == SAW_WS_RIGHT && dAngPC < - EPS_ANG_SMALL)) bExtAngPC = false ; } // calcolo tipo angolo con successivo bool bExtAngCN = true ; if ( pCrvN != nullptr) { Vector3d vtDirN ; pCrvN->GetStartDir( vtDirN) ; double dAngCN ; vtDirC.GetAngleXY( vtDirN, dAngCN) ; if ( ( m_Params.m_nWorkSide == SAW_WS_LEFT && dAngCN > EPS_ANG_SMALL) || ( m_Params.m_nWorkSide == SAW_WS_RIGHT && dAngCN < - EPS_ANG_SMALL)) bExtAngCN = false ; } // verifico eventuale attacco speciale a step (se parametri validi e su entità linea singola) double dLiStep = 0 ; double dLiElev = 0 ; if ( m_Params.m_dLiTang > 10 * EPS_SMALL && m_Params.m_dLiElev > 10 * EPS_SMALL && m_Params.m_dLiElev < dElev - 10 * EPS_SMALL && pCrvP == nullptr && pCrvN == nullptr) { int nLiSteps = int( ceil( ( ( dElev - dExtraCut) / m_Params.m_dLiElev))) ; dLiStep = ( dElev - dExtraCut) / nLiSteps ; dLiElev = dElev - dExtraCut - dLiStep ; } // aggiusto per tipo estremi bool bToSkip = false ; double dDeltaLiExt = 0, dDeltaLoExt = 0 ; if ( ! AdjustLineForEdges( pLine, dElev, vtCorr, vtThick, bIsFirst, bIsLast, bExtAngPC, bExtAngCN, dLiElev, bToSkip, dDeltaLiExt, dDeltaLoExt)) { m_pMchMgr->SetLastError( 2211, "Error in Sawing : Entity AdjustForEdges") ; return false ; } if ( bToSkip) { m_pMchMgr->SetWarning( 2257, "Warning in Sawing : skipped Entity too small") ; return true ; } // Eventuale variazioni di velocità all'inizio e alla fine del percorso FseVar FvVar ; if ( pCrvP == nullptr) { string sFsta = ExtractInfo( m_Params.m_sUserNotes, "Fsta:") ; if ( ! sFsta.empty()) { string sLen, sPu ; SplitFirst( sFsta, "=", sLen, sPu) ; FromString( sLen, FvVar.dLenStart) ; FvVar.dLenStart = max( FvVar.dLenStart, 0.) ; FromString( sPu, FvVar.dPuStart) ; FvVar.dPuStart = max( FvVar.dPuStart, 0.) ; } } if ( pCrvN == nullptr) { string sFend = ExtractInfo( m_Params.m_sUserNotes, "Fend:") ; if ( ! sFend.empty()) { string sLen, sPu ; SplitFirst( sFend, "=", sLen, sPu) ; FromString( sLen, FvVar.dLenEnd) ; FvVar.dLenEnd = max( FvVar.dLenEnd, 0.) ; FromString( sPu, FvVar.dPuEnd) ; FvVar.dPuEnd = max( FvVar.dPuEnd, 0.) ; } } // recupero eventuali estensioni dei baffi (whiskers) double dStartWhiskExt = 0 ; if ( m_Params.m_nLeadInType == SAW_LI_CENT) FromString( ExtractInfo( m_Params.m_sUserNotes, "SWE="), dStartWhiskExt) ; double dEndWhiskExt = 0 ; if ( m_Params.m_nLeadOutType == SAW_LO_CENT) FromString( ExtractInfo( m_Params.m_sUserNotes, "EWE="), dEndWhiskExt) ; // Se richiesto Preview if ( nPvId != GDB_ID_NULL) { if ( ! GenerateLinePv( pLine, vtTool, vtCorr, dElev, dExtraCut, dRbHeight, sName, dLiElev, dStartWhiskExt, dEndWhiskExt, nPvId)) return false ; } // Se richiesta geometria di lavorazione if ( nClId != GDB_ID_NULL) { if ( dStartWhiskExt > EPS_SMALL) pLine->ExtendStartByLen( dStartWhiskExt) ; if ( dEndWhiskExt > EPS_SMALL) pLine->ExtendEndByLen( dEndWhiskExt) ; if ( ! GenerateLineCl( pLine, vtTool, vtCorr, dElev, dExtraCut, sName, dLiStep, dDeltaLiExt, dDeltaLoExt, FvVar, nClId)) return false ; } // incremento numero di tagli ++ m_nCuts ; return true ; } //---------------------------------------------------------------------------- bool Sawing::GenerateLinePv( const ICurveLine* pLine, const Vector3d& vtTool, const Vector3d& vtCorr, double dElev, double dExtraCut, double dRbHeight, const string& sName, double dLiElev, double dStartWhiskExt, double dEndWhiskExt, int nPvId) { // creo gruppo per anteprima di lavorazione della linea int nPxId = m_pGeomDB->AddGroup( GDB_ID_NULL, nPvId, Frame3d()) ; if ( nPxId == GDB_ID_NULL) return false ; m_pGeomDB->SetName( nPxId, sName) ; m_pGeomDB->SetMaterial( nPxId, BLUE) ; // punti notevoli Point3d ptIni = pLine->GetStart() + dElev * vtCorr ; Point3d ptEnd = pLine->GetEnd() + dElev * vtCorr ; Vector3d vtToolH( vtTool.x, vtTool.y, 0) ; vtToolH *= m_TParams.m_dThick / vtToolH.SqLen() ; Point3d ptCross = ptEnd + vtToolH ; Vector3d vtDZ( 0, 0, 0.1) ; // distanza XY tra centro e bordo taglio double dDeltaT = (( dElev < 0.5 * m_TParams.m_dDiam) ? sqrt( dElev * m_TParams.m_dDiam - dElev * dElev) : 0) ; double dDeltaTi = dDeltaT ; if ( dLiElev > EPS_SMALL) dDeltaTi = m_Params.m_dLiTang + (( dLiElev < 0.5 * m_TParams.m_dDiam) ? sqrt( dLiElev * m_TParams.m_dDiam - dLiElev * dLiElev) : 0) ; double dDtIni = dDeltaTi + dStartWhiskExt ; double dDtEnd = dDeltaT + dEndWhiskExt ; // direzione del taglio Vector3d vtDir ; pLine->GetStartDir( vtDir) ; // colore taglio, dipendente da angolo di inclinazione Color colCut = LIME ; if ( abs( m_Params.m_dSideAngle) > EPS_ANG_SMALL) colCut = FUCHSIA ; // disabilito eventuale registrazione comandi EXE (riabilitazione automatica) CmdLogOff cmdLogOff ; // rettangolo per parte di taglio completo int nId = ExeCreateRectangle3P( nPxId, ptIni + vtDZ, ptCross + vtDZ, ptEnd + vtDZ, RTY_LOC) ; m_pGeomDB->SetName( nId, MCH_PV_CUT) ; m_pGeomDB->SetMaterial( nId, colCut) ; // rettangolo per parte parziale iniziale int nId2 = ExeCreateRectangle3P( nPxId, ptIni - vtDir * dDtIni, ptIni + vtToolH, ptIni, RTY_LOC) ; // assegno nome e colore m_pGeomDB->SetName( nId2, MCH_PV_PRE_CUT) ; m_pGeomDB->SetMaterial( nId2, BLUE) ; // rettangolo per parte parziale finale int nId3 = ExeCreateRectangle3P( nPxId, ptEnd, ptCross + vtDir * dDtEnd, ptEnd + vtDir * dDtEnd, RTY_LOC) ; // assegno nome e colore m_pGeomDB->SetName( nId3, MCH_PV_POST_CUT) ; m_pGeomDB->SetMaterial( nId3, BLUE) ; // valore di allungamento double dExtraL = m_pMchMgr->GetCurrMachiningsMgr()->GetExtraLOnCutRegion() ; // punti notevoli per regioni Point3d ptRIni = ptIni ; Point3d ptRCross = ptCross ; Point3d ptREnd = ptEnd ; Vector3d vtRToolH = vtToolH ; // allargamento per taglio sottosquadra (WorkSide e HeadSide sempre opposti) if ( m_Params.m_dSideAngle < - EPS_ANG_SMALL) { Vector3d vtOrtho = vtToolH ; vtOrtho.Normalize() ; ptRIni -= vtOrtho * dExtraL ; ptREnd -= vtOrtho * dExtraL ; vtRToolH += vtOrtho * dExtraL ; } // regione di taglio completo per nesting int nRId = ExeCreateSurfFrRectangle3P( nPxId, ptRIni - vtDir * ( dDtIni + dExtraL), ptRCross + vtDir * ( dDtEnd + dExtraL), ptREnd, RTY_LOC) ; m_pGeomDB->SetName( nRId, MCH_PV_RCUT) ; m_pGeomDB->SetMaterial( nRId, INVISIBLE) ; // regione di taglio ridotto per nesting (sono escluse le parti iniziale e finale) const double EXTRALEN_R = 10 * EPS_SMALL ; int nRrId = ExeCreateSurfFrRectangle3P( nPxId, ptRIni - vtDir * EXTRALEN_R, ptRCross + vtDir * EXTRALEN_R, ptREnd, RTY_LOC) ; m_pGeomDB->SetName( nRrId, MCH_PV_RRCUT) ; m_pGeomDB->SetMaterial( nRrId, INVISIBLE) ; // regione di ingresso al taglio (parte iniziale) int nRsId = ExeCreateSurfFrRectangle3P( nPxId, ptRIni - vtDir * ( dDtIni + dExtraL), ptRIni + vtRToolH, ptRIni, RTY_LOC) ; m_pGeomDB->SetName( nRsId, MCH_PV_RLICUT) ; m_pGeomDB->SetMaterial( nRsId, INVISIBLE) ; // regione di uscita dal taglio (parte finale) int nReId = ExeCreateSurfFrRectangle3P( nPxId, ptREnd, ptRCross + vtDir * ( dDtEnd + dExtraL), ptREnd + vtDir * ( dDtEnd + dExtraL) , RTY_LOC) ; m_pGeomDB->SetName( nReId, MCH_PV_RLOCUT) ; m_pGeomDB->SetMaterial( nReId, INVISIBLE) ; // eventuali ripetizioni in basso per tagli inclinati if ( abs( m_Params.m_dSideAngle) > EPS_ANG_SMALL) { // lunghezza movimento double dMove = ( dElev - dExtraCut) ; // se sottosquadra (controllo il lato opposto della lama, quindi ...) if ( m_Params.m_dSideAngle < 0) dMove = dElev - dExtraCut - m_TParams.m_dThick * tan( abs( m_Params.m_dSideAngle) * DEGTORAD) ; // altrimenti tengo conto di dove si trova il sopra del lato esterno else dMove = dElev - max( dExtraCut, m_TParams.m_dThick * tan( abs( m_Params.m_dSideAngle) * DEGTORAD)) ; // vettore movimento Vector3d vtMove = - dMove * vtCorr ; vtMove.z = 0 ; // rettangolo per parte di taglio completo int nDwnId = ExeCreateRectangle3P( nPxId, ptIni + vtDZ, ptCross + vtMove + vtDZ, ptEnd + vtDZ, RTY_LOC) ; m_pGeomDB->SetName( nDwnId, MCH_PV_DOWN_CUT) ; m_pGeomDB->SetMaterial( nDwnId, colCut) ; // rettangolo per parte parziale iniziale int nDwnId2 = ExeCreateRectangle3P( nPxId, ptIni - vtDir * dDtIni, ptIni + vtToolH + vtMove, ptIni, RTY_LOC) ; m_pGeomDB->SetName( nDwnId2, MCH_PV_DOWN_PRE_CUT) ; m_pGeomDB->SetMaterial( nDwnId2, BLUE) ; // rettangolo per parte parziale finale int nDwnId3 = ExeCreateRectangle3P( nPxId, ptEnd, ptCross + vtDir * dDtEnd + vtMove, ptEnd + vtDir * dDtEnd, RTY_LOC) ; m_pGeomDB->SetName( nDwnId3, MCH_PV_DOWN_POST_CUT) ; m_pGeomDB->SetMaterial( nDwnId3, BLUE) ; // regione di taglio completo per nesting int nDwnRId = m_pGeomDB->Copy( nRId, GDB_ID_NULL, nPxId) ; m_pGeomDB->Translate( nDwnRId, vtMove) ; m_pGeomDB->SetName( nDwnRId, MCH_PV_DOWN_RCUT) ; // regione di taglio ridotto per nesting (sono escluse le parti iniziale e finale) int nDwnRrId = m_pGeomDB->Copy( nRrId, GDB_ID_NULL, nPxId) ; m_pGeomDB->Translate( nDwnRrId, vtMove) ; m_pGeomDB->SetName( nDwnRrId, MCH_PV_DOWN_RRCUT) ; // regione di ingresso al taglio (parte iniziale) int nDwnRsId = m_pGeomDB->Copy( nRsId, GDB_ID_NULL, nPxId) ; m_pGeomDB->Translate( nDwnRsId, vtMove) ; m_pGeomDB->SetName( nDwnRsId, MCH_PV_DOWN_RLICUT) ; // regione di uscita dal taglio (parte finale) int nDwnReId = m_pGeomDB->Copy( nReId, GDB_ID_NULL, nPxId) ; m_pGeomDB->Translate( nDwnReId, vtMove) ; m_pGeomDB->SetName( nDwnReId, MCH_PV_DOWN_RLOCUT) ; // riduzione larghezza regioni per tagli da sopra if ( m_Params.m_dSideAngle > 0) { double dRefH = max( m_TParams.m_dThick * sin( m_Params.m_dSideAngle * DEGTORAD) - dExtraCut * cos( m_Params.m_dSideAngle * DEGTORAD), 0.) ; if ( dRefH > EPS_SMALL) { double dLargh = vtToolH.LenXY() ; double dRedLargh = dLargh - dRefH * tan( m_Params.m_dSideAngle * DEGTORAD) - EPS_SMALL ; double dCoeff = dRedLargh / dLargh ; Frame3d frScale ; frScale.Set( ptRCross + vtMove, Z_AX, vtDir) ; m_pGeomDB->Scale( nDwnRId, frScale, 1, dCoeff, 1) ; m_pGeomDB->Scale( nDwnRrId, frScale, 1, dCoeff, 1) ; m_pGeomDB->Scale( nDwnRsId, frScale, 1, dCoeff, 1) ; m_pGeomDB->Scale( nDwnReId, frScale, 1, dCoeff, 1) ; } } } // salvo in info gruppo : larghezza XY del taglio, distanza XY tra centro e bordo taglio, extra taglio e quota minima della lama m_pGeomDB->SetInfo( nPxId, MCH_PV_KEY_WT, vtToolH.LenXY()) ; if ( dLiElev > EPS_SMALL) m_pGeomDB->SetInfo( nPxId, MCH_PV_KEY_DTI, dDeltaTi) ; m_pGeomDB->SetInfo( nPxId, MCH_PV_KEY_DT, dDeltaT) ; m_pGeomDB->SetInfo( nPxId, MCH_PV_KEY_EC, dExtraCut) ; m_pGeomDB->SetInfo( nPxId, MCH_PV_KEY_RBH, dRbHeight) ; return true ; } //---------------------------------------------------------------------------- bool Sawing::GenerateLineCl( const ICurveLine* pLine, const Vector3d& vtTool, const Vector3d& vtCorr, double dElev, double dExtraCut, const string& sName, double dLiStep, double dDeltaLiExt, double dDeltaLoExt, const FseVar& FvVar, int nClId) { // creo gruppo per geometria di lavorazione della linea int nPxId = m_pGeomDB->AddGroup( GDB_ID_NULL, nClId, Frame3d()) ; if ( nPxId == GDB_ID_NULL) return false ; m_pGeomDB->SetName( nPxId, sName) ; m_pGeomDB->SetMaterial( nPxId, BLUE) ; // assegno il vettore estrazione al gruppo del percorso m_pGeomDB->SetInfo( nPxId, KEY_EXTR, Vector3d( 0, 0, 1)) ; // assegno i punti di inizio e fine al gruppo del percorso m_pGeomDB->SetInfo( nPxId, KEY_START, pLine->GetStart()) ; m_pGeomDB->SetInfo( nPxId, KEY_END, pLine->GetEnd()) ; // assegno l'elevazione massima m_pGeomDB->SetInfo( nPxId, KEY_ELEV, dElev) ; // assegno delta per taglio esteso al bordo grezzo m_pGeomDB->SetInfo( nPxId, KEY_DELTALIEXT, dDeltaLiExt) ; m_pGeomDB->SetInfo( nPxId, KEY_DELTALOEXT, dDeltaLoExt) ; // Imposto dati comuni SetPathId( nPxId) ; SetToolDir( vtTool) ; SetCorrAuxDir( vtCorr) ; // recupero distanza di sicurezza double dSafeZ = m_pMchMgr->GetCurrMachiningsMgr()->GetSafeZ() ; // distanza di approccio/retrazione double dAppr = m_Params.m_dStartPos ; // flag di taglio inclinato bool bSideAng = ( abs( m_Params.m_dSideAngle) > EPS_ANG_SMALL) ; // valori di step double dActStep = m_Params.m_dStep ; double dActBstep = GetStepBack() ; if ( bSideAng) { dActStep = GetStepSideAng() ; if ( dActStep < EPS_SMALL) dActStep = m_Params.m_dStep ; dActBstep = GetStepSideAngBack() ; } if ( dActBstep < EPS_SMALL) dActBstep = dActStep ; // direzione della linea Vector3d vtDir ; pLine->GetStartDir( vtDir) ; // Se una sola passata if ( dActStep < EPS_SMALL || ( dElev - dExtraCut) <= dActStep || ( ! bSideAng && m_Params.m_dStepLast > EPS_SMALL && ( dElev - dExtraCut) <= m_Params.m_dStepLast)) { // 1 -> approccio Point3d ptP1 = pLine->GetStart() - vtDir * m_Params.m_dLiTang ; if ( ! AddApproach( ptP1, vtCorr, dSafeZ, dElev, dAppr)) return false ; // 2 -> movimento in affondo al punto iniziale Point3d ptP2 = pLine->GetStart() ; // se con attacco a zig-zag if ( dLiStep > EPS_SMALL) { // mi porto sulla superficie del pezzo SetFlag( 0) ; SetFeed( GetTipFeed()) ; Point3d ptP1b = ptP1 + vtCorr * dElev ; Point3d ptP2b = ptP2 + vtCorr * dElev ; if ( AddLinearMove( ptP1b) == GDB_ID_NULL) return false ; // eseguo gli zigzag necessari double dZigZagLiFeed = GetStartFeed() * ( FvVar.dLenStart > EPS_SMALL ? FvVar.dPuStart : 1) ; int nStep = int( ( dElev - dExtraCut) / dLiStep + 0.1) ; for ( int i = 1 ; i <= nStep ; ++ i) { // aggiorno l'affondamento ptP1b -= vtCorr * ( i < nStep ? dLiStep : dLiStep + dExtraCut) ; ptP2b -= vtCorr * ( i < nStep ? dLiStep : dLiStep + dExtraCut) ; // andata SetFeed( dZigZagLiFeed) ; if ( AddLinearMove( ptP2b) == GDB_ID_NULL) return false ; // ritorno se non ultimo if ( i < nStep) { SetFeed( dZigZagLiFeed) ; if ( AddLinearMove( ptP1b) == GDB_ID_NULL) return false ; } } } // altrimenti standard else { SetFlag( 0) ; SetFeed( GetTipFeed()) ; if ( AddLinearMove( ptP2) == GDB_ID_NULL) return false ; } // 3 -> movimento di lato al punto finale if ( FvVar.dLenStart > EPS_SMALL || FvVar.dLenEnd > EPS_SMALL) { // lunghezza del taglio double dCutLen ; pLine->GetLength( dCutLen) ; double dStartFraz = FvVar.dLenStart / dCutLen ; double dEndFraz = FvVar.dLenEnd / dCutLen ; double dMidFraz = 1 - dEndFraz ; if ( dStartFraz + dEndFraz > 1) { dStartFraz /= ( dStartFraz + dEndFraz) ; dEndFraz = 1 - dStartFraz ; dMidFraz = dStartFraz ; } // punto finale Point3d ptP3 = pLine->GetEnd() ; // 3a -> eventuale movimento di lato a feed ridotta di inizio percorso if ( dStartFraz * dCutLen > EPS_SMALL) { SetFeed( FvVar.dPuStart * ( ! bSideAng ? GetFeed() : GetSideAngFeed())) ; if ( AddLinearMove( Media( ptP2, ptP3, dStartFraz)) == GDB_ID_NULL) return false ; } // 3b -> eventuale movimento di lato a feed normale if ( ( dMidFraz - dStartFraz) * dCutLen > EPS_SMALL) { SetFeed( ( ! bSideAng ? GetFeed() : GetSideAngFeed())) ; if ( AddLinearMove( Media( ptP2, ptP3, dMidFraz)) == GDB_ID_NULL) return false ; } // 3c -> eventuale movimento di lato a feed ridotta di fine percorso if ( dEndFraz * dCutLen > EPS_SMALL) { SetFeed( FvVar.dPuEnd * ( ! bSideAng ? GetFeed() : GetSideAngFeed())) ; if ( AddLinearMove( ptP3) == GDB_ID_NULL) return false ; } } else { SetFeed( ( ! bSideAng ? GetFeed() : GetSideAngFeed())) ; Point3d ptP3 = pLine->GetEnd() ; if ( AddLinearMove( ptP3) == GDB_ID_NULL) return false ; } // 4 -> retrazione if ( ! AddRetract( pLine->GetEnd(), vtCorr, dSafeZ, dElev, dAppr)) return false ; } // Se step a Zig-Zag o ToAndFrom else if ( m_Params.m_nStepType == SAW_ST_ZIGZAG || m_Params.m_nStepType == SAW_ST_TOANDFROM) { // 1 -> approccio if ( ! AddApproach( pLine->GetStart(), vtCorr, dSafeZ, dElev, dAppr)) return false ; // 2-3 -> lavorazione (sempre numero pari di passate) // calcolo numero e valore degli step double dCutH = dElev - dExtraCut ; int nStep = 2 ; if ( m_Params.m_nStepType == SAW_ST_ZIGZAG) nStep = 2 * static_cast( ceil( dCutH / ( dActStep + dActBstep + EPS_SMALL))) ; double dMeanStep = dCutH / nStep ; double dBstep = dActBstep * 2 * dMeanStep / ( dActStep + dActBstep) ; double dLastStep = dBstep ; if ( ! bSideAng && m_Params.m_dStepLast > EPS_SMALL) { dLastStep = m_Params.m_dStepLast ; double dCoeff = ( dCutH - dLastStep) / ( nStep / 2 * dActStep + ( nStep / 2 - 1) * dActBstep) ; dMeanStep = dCoeff * ( dActStep + dActBstep) / 2 ; dBstep = dCoeff * dActBstep ; } // esecuzione degli step for ( int i = nStep - 1 ; i >= 0 ; -- i) { // distanza dal fondo double dDelta = 0 ; if ( i > 0) dDelta = dExtraCut + dLastStep + ( IsEven( i) ? i * dMeanStep - dBstep : ( i - 1) * dMeanStep) ; // estremi del movimento (dispari vanno, pari tornano) Point3d ptP2 = pLine->GetStart() + vtCorr * dDelta ; Point3d ptP3 = pLine->GetEnd() + vtCorr * dDelta ; if ( IsEven( i)) swap( ptP2, ptP3) ; // movimento in affondo SetFlag( 0) ; SetFeed( GetTipFeed()) ; if ( AddLinearMove( ptP2) == GDB_ID_NULL) return false ; // movimento di lato SetFeed( ( ! bSideAng ? ( i == 0 ? GetBackFeed() : GetFeed()) : GetSideAngFeed())) ; if ( AddLinearMove( ptP3) == GDB_ID_NULL) return false ; } // 4 -> retrazione if ( ! AddRetract( pLine->GetStart(), vtCorr, dSafeZ, dElev, dAppr)) return false ; } // Altrimenti step a una via else { // 1 -> approccio if ( ! AddApproach( pLine->GetStart(), vtCorr, dSafeZ, dElev, dAppr)) return false ; // 2-3 -> lavorazione // calcolo numero e valore degli step double dCutH = dElev - dExtraCut ; int nStep = static_cast( ceil( dCutH / ( dActStep + EPS_SMALL))) ; double dStep = dCutH / nStep ; double dLastStep = dStep ; if ( ! bSideAng && m_Params.m_dStepLast > EPS_SMALL) { dLastStep = m_Params.m_dStepLast ; nStep = static_cast( ceil( ( dCutH - dLastStep) / ( dActStep + EPS_SMALL))) + 1 ; dStep = ( dCutH - dLastStep) / ( nStep - 1) ; } // esecuzione degli step for ( int i = nStep - 1 ; i >= 0 ; -- i) { // distanza dal fondo double dDelta = ( ( i != 0) ? dExtraCut + dLastStep + ( i - 1) * dStep : 0) ; // movimento in affondo al punto iniziale SetFlag( 0) ; SetFeed( GetTipFeed()) ; Point3d ptP2 = pLine->GetStart() + vtCorr * dDelta ; if ( AddLinearMove( ptP2) == GDB_ID_NULL) return false ; // movimento di lato al punto finale SetFeed( ( ! bSideAng ? GetFeed() : GetSideAngFeed())) ; Point3d ptP3 = pLine->GetEnd() + vtCorr * dDelta ; if ( AddLinearMove( ptP3) == GDB_ID_NULL) return false ; // se non è ultimo passo if ( i != 0) { // movimento di risalita sopra il punto finale SetFeed( GetEndFeed()) ; Point3d ptP4 = pLine->GetEnd() + vtCorr * ( dElev + dAppr / vtCorr.z) ; if ( AddLinearMove( ptP4) == GDB_ID_NULL) return false ; // movimento di ritorno spora il punto iniziale SetFeed( GetEndFeed()) ; Point3d ptP5 = pLine->GetStart() + vtCorr * ( dElev + dAppr / vtCorr.z) ; if ( AddLinearMove( ptP5) == GDB_ID_NULL) return false ; } } // 4 -> retrazione if ( ! AddRetract( pLine->GetEnd(), vtCorr, dSafeZ, dElev, dAppr)) return false ; } return true ; } //---------------------------------------------------------------------------- bool Sawing::ProcessExtCurve( const ICurve* pCrvP, const ICurveComposite* pCrvC, const ICurve* pCrvN, double dDepth, double dExtraCut, double dRbHeight, bool bIsFirst, bool bIsLast, const string& sName, int nPvId, int nClId) { // copio la curva PtrOwner pCrv( pCrvC->Clone()) ; if ( IsNull( pCrv)) return false ; // verifico che il raggio di ogni arco componente sia superiore al minimo double dMinRad = INFINITO ; for ( const ICurve* pSmpCrv = pCrv->GetFirstCurve() ; pSmpCrv != nullptr ; pSmpCrv = pCrv->GetNextCurve()) { if ( pSmpCrv->GetType() == CRV_ARC) { double dRad = GetCurveArc( pSmpCrv)->GetRadius() ; if ( dRad < dMinRad) dMinRad = dRad ; } } if ( dMinRad < m_pMchMgr->GetCurrMachiningsMgr()->GetExtSawArcMinRad()) { m_pMchMgr->SetWarning( 2258, "Warning in Sawing : Radius too small in ExtSawArc") ; return true ; } // se richiesta generazione, verifico limite standard angolo al centro archi if ( nClId != GDB_ID_NULL) VerifyArcs( pCrv) ; // se curva chiusa ne forzo il punto di partenza a Xmax o Xmin ( per limiti corse assi C Omag) if ( pCrv->IsClosed()) { BBox3d b3Crv ; pCrv->GetLocalBBox( b3Crv) ; Point3d ptTest = 0.5 * ( b3Crv.GetMin() + b3Crv.GetMax()) ; if ( m_Params.m_dSideAngle < EPS_ANG_SMALL) ptTest += Vector3d( 100000, 0, 0) ; else ptTest += Vector3d( -100000, 0, 0) ; DistPointCurve dstPtCurve( ptTest, *pCrv) ; double dU ; int nFlag ; if ( dstPtCurve.GetParamAtMinDistPoint( 0, dU, nFlag)) { dU = 0.1 * round( 10 * dU) ; pCrv->ChangeStartPoint( dU) ; pCrvP = pCrv ; pCrvN = pCrv ; } } // correzioni per lato lama, lato mandrino if ( ! AdjustForSide( pCrv)) { m_pMchMgr->SetLastError( 2209, "Error in Sawing : Entity AdjustForSide") ; return false ; } // aggiungo affondamento (sempre in Z globale) double dDepthZ = dDepth ; if ( abs( m_Params.m_dSideAngle) > EPS_ANG_SMALL) dDepthZ *= cos( m_Params.m_dSideAngle * DEGTORAD) ; pCrv->Translate( - Z_AX * dDepthZ) ; // offset per taglio inclinato double dOffs = 0 ; if ( abs( m_Params.m_dSideAngle) > EPS_ANG_SMALL) { dOffs = dDepth * sin( abs( m_Params.m_dSideAngle) * DEGTORAD) ; if ( m_Params.m_nHeadSide == SAW_HS_LEFT) dOffs = - dOffs ; pCrv->SimpleOffset( dOffs) ; } // calcolo elevazione (sui due bordi della striscia) double dElev = 0 ; for ( const ICurve* pSmpCrv = pCrv->GetFirstCurve() ; pSmpCrv != nullptr ; pSmpCrv = pCrv->GetNextCurve()) { Point3d ptSta, ptMid, ptEnd ; pSmpCrv->GetStartPoint( ptSta) ; pSmpCrv->GetMidPoint( ptMid) ; pSmpCrv->GetEndPoint( ptEnd) ; Vector3d vtStaDir, vtMidDir, vtEndDir ; pSmpCrv->GetStartDir( vtStaDir) ; pSmpCrv->GetMidDir( vtMidDir) ; pSmpCrv->GetEndDir( vtEndDir) ; Vector3d vtStaTool, vtStaCorr, vtMidTool, vtMidCorr, vtEndTool, vtEndCorr ; if ( ! CalculateToolAndCorrVersors( vtStaDir, m_Params.m_nHeadSide, m_Params.m_nWorkSide, m_Params.m_dSideAngle, vtStaTool, vtStaCorr) || ! CalculateToolAndCorrVersors( vtMidDir, m_Params.m_nHeadSide, m_Params.m_nWorkSide, m_Params.m_dSideAngle, vtMidTool, vtMidCorr) || ! CalculateToolAndCorrVersors( vtEndDir, m_Params.m_nHeadSide, m_Params.m_nWorkSide, m_Params.m_dSideAngle, vtEndTool, vtEndCorr) || abs( vtStaCorr.z - vtMidCorr.z) > EPS_SMALL || abs( vtStaCorr.z - vtEndCorr.z) > EPS_SMALL) { m_pMchMgr->SetLastError( 2208, "Error in Sawing : Entity CalculateToolAndCorrVersors") ; return false ; } Vector3d vtStaThick = vtStaTool * m_TParams.m_dThick ; Vector3d vtMidThick = vtMidTool * m_TParams.m_dThick ; Vector3d vtEndThick = vtEndTool * m_TParams.m_dThick ; double dElev1, dElev2 ; if ( ! GetElevation( m_nPhase, ptSta, ptMid, ptEnd, vtStaCorr, dElev1) || ! GetElevation( m_nPhase, ptSta + vtStaThick, ptMid + vtMidThick, ptEnd + vtEndThick, vtStaCorr, dElev2) ) { m_pMchMgr->SetLastError( 2210, "Error in Sawing : Entity GetElevation") ; return false ; } dElev = max( dElev, max( dElev1, dElev2)) ; } // calcolo tipo angolo con precedente bool bExtAngPC = true ; if ( pCrvP != nullptr) { Vector3d vtDirP ; pCrvP->GetEndDir( vtDirP) ; Vector3d vtStaDir ; pCrv->GetStartDir( vtStaDir) ; double dAngPC ; vtDirP.GetAngleXY( vtStaDir, dAngPC) ; if ( ( m_Params.m_nWorkSide == SAW_WS_LEFT && dAngPC > EPS_ANG_SMALL) || ( m_Params.m_nWorkSide == SAW_WS_RIGHT && dAngPC < - EPS_ANG_SMALL)) bExtAngPC = false ; } // calcolo tipo angolo con successivo bool bExtAngCN = true ; if ( pCrvN != nullptr) { Vector3d vtEndDir ; pCrv->GetEndDir( vtEndDir) ; Vector3d vtDirN ; pCrvN->GetStartDir( vtDirN) ; double dAngCN ; vtEndDir.GetAngleXY( vtDirN, dAngCN) ; if ( ( m_Params.m_nWorkSide == SAW_WS_LEFT && dAngCN > EPS_ANG_SMALL) || ( m_Params.m_nWorkSide == SAW_WS_RIGHT && dAngCN < - EPS_ANG_SMALL)) bExtAngCN = false ; } // aggiusto per tipo estremi bool bToSkip = false ; if ( ! AdjustCurveForEdges( pCrv, dElev, 1.0, bIsFirst, bIsLast, bExtAngPC, bExtAngCN, bToSkip)) { m_pMchMgr->SetLastError( 2211, "Error in Sawing : Entity AdjustForEdges") ; return false ; } if ( bToSkip) { m_pMchMgr->SetWarning( 2257, "Warning in Sawing : skipped Entity too small") ; return true ; } // Se richiesto Preview if ( nPvId != GDB_ID_NULL) { if ( ! GenerateExtCurvePv( pCrv, dOffs, dElev, dExtraCut, dRbHeight, sName, nPvId)) return false ; } // Se richiesta geometria di lavorazione if ( nClId != GDB_ID_NULL) { if ( ! GenerateExtCurveCl( pCrv, dElev, dExtraCut, sName, nClId)) return false ; } // incremento numero di tagli ++ m_nCuts ; return true ; } //---------------------------------------------------------------------------- bool Sawing::GenerateExtCurvePv( const ICurveComposite* pCrv, double dOffs, double dElev, double dExtraCut, double dRbHeight, const string& sName, int nPvId) { // creo gruppo per anteprima di lavorazione della curva int nPxId = m_pGeomDB->AddGroup( GDB_ID_NULL, nPvId, Frame3d()) ; if ( nPxId == GDB_ID_NULL) return false ; m_pGeomDB->SetName( nPxId, sName) ; m_pGeomDB->SetMaterial( nPxId, BLUE) ; // disabilito eventuale registrazione comandi EXE (riabilitazione automatica) CmdLogOff cmdLogOff ; // colore taglio, dipendente da angolo di inclinazione Color colCut = LIME ; if ( abs( m_Params.m_dSideAngle) > EPS_ANG_SMALL) colCut = FUCHSIA ; // dimensione da aggiungere alle regioni nelle parti in cui la lama è inclinata double dExtraL = m_pMchMgr->GetCurrMachiningsMgr()->GetExtraLOnCutRegion() ; // lunghezza taglio parziale double dDeltaT = (( dElev < 0.5 * m_TParams.m_dDiam) ? sqrt( dElev * m_TParams.m_dDiam - dElev * dElev) : 0) ; // massima larghezza di taglio double dMaxW = 0 ; // versore correzione sempre come Z+ Vector3d vtCorr = Z_AX ; // ciclo sulle curve int nMaxInd = pCrv->GetCurveCount() - 1 ; for ( int i = 0 ; i <= nMaxInd ; ++ i) { // flag per prima/ultima curva bool bFirst = ( i == 0) ; bool bLast = ( i == nMaxInd) ; // recupero curva, necessariamente linea o arco const ICurveLine* pLine = GetCurveLine( pCrv->GetCurve( i)) ; const ICurveArc* pArc = GetCurveArc( pCrv->GetCurve( i)) ; // se linea if ( pLine != nullptr) { dMaxW = max( dMaxW, m_TParams.m_dThick) ; } // se arco else if ( pArc != nullptr) { // seno e coseno di angolo di inclinazione double dSinAS = sin( m_Params.m_dSideAngle * DEGTORAD) ; double dCosAS = cos( m_Params.m_dSideAngle * DEGTORAD) ; // se taglio inclinato, devo applicare l'offset, aggiustare lo spessore lama e lo spostamento in Z PtrOwner< ICurveArc> pMyArc ; double dMyThick = m_TParams.m_dThick ; double dMyZmove = dElev ; if ( abs( m_Params.m_dSideAngle) > EPS_ANG_SMALL) { // offset arco pMyArc.Set( pArc->Clone()) ; if ( IsNull( pMyArc)) return false ; pMyArc->SimpleOffset( -dOffs) ; pArc = pMyArc ; // sistemazione spessore lama dMyThick = m_TParams.m_dThick / dCosAS ; // sistemazione spostamento in Z dMyZmove = dElev * dCosAS ; } // calcolo dei raggi double dIntRad ; double dExtRad ; if ( AreHeadWorkOnSameSide()) { dIntRad = pArc->GetRadius() ; double dRadTot = pArc->GetRadius() + dMyThick ; dExtRad = sqrt( dRadTot * dRadTot + dDeltaT * dDeltaT) ; if ( abs( m_Params.m_dSideAngle) > EPS_ANG_SMALL) dExtRad = max( dExtRad, dRadTot + ( dElev - dExtraCut) * dSinAS) ; } else { dIntRad = pArc->GetRadius() - dMyThick ; if ( abs( m_Params.m_dSideAngle) > EPS_ANG_SMALL) dIntRad -= ( dElev - dExtraCut - abs( dSinAS) * dMyThick) * abs( dSinAS) ; dExtRad = sqrt( pArc->GetRadius() * pArc->GetRadius() + dDeltaT * dDeltaT) ; } dMaxW = max( dMaxW, dExtRad - dIntRad) ; // contorno per parte di taglio completo PtrOwner pCompo( GenerateExtArcPvTrueCut( pArc, dIntRad, dExtRad, 0)) ; if ( IsNull( pCompo)) return false ; pCompo->Translate( dMyZmove * vtCorr + Vector3d( 0, 0, 0.1)) ; int nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPxId, Release( pCompo)) ; m_pGeomDB->SetName( nId, MCH_PV_CUT) ; m_pGeomDB->SetMaterial( nId, colCut) ; // contorno per parte iniziale di taglio PtrOwner pCompo2( GenerateExtArcPvPreCut( pArc, dIntRad, dExtRad, dDeltaT, 0)) ; if ( IsNull( pCompo2)) return false ; pCompo2->Translate( dMyZmove * vtCorr) ; int nId2 = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPxId, Release( pCompo2)) ; m_pGeomDB->SetName( nId2, ( bFirst ? MCH_PV_PRE_CUT : MCH_PV_CUT)) ; m_pGeomDB->SetMaterial( nId2, ( bFirst ? BLUE : colCut)) ; // contorno per parte finale di taglio PtrOwner pCompo3( GenerateExtArcPvPostCut( pArc, dIntRad, dExtRad, dDeltaT, 0)) ; if ( IsNull( pCompo3)) return false ; pCompo3->Translate( dMyZmove * vtCorr) ; int nId3 = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPxId, Release( pCompo3)) ; m_pGeomDB->SetName( nId3, ( bLast ? MCH_PV_POST_CUT : MCH_PV_CUT)) ; m_pGeomDB->SetMaterial( nId3, ( bLast ? BLUE : colCut)) ; // regione ridotta di taglio per nesting (escluse parti iniziali e finali) PtrOwner pCmpRr( GenerateExtArcPvTrueCut( pArc, dIntRad, dExtRad, dExtraL)) ; if ( IsNull( pCmpRr)) return false ; SurfFlatRegionByContours SfrCntrRr ; SfrCntrRr.AddCurve( Release( pCmpRr)) ; ISurfFlatRegion* pSfrRr = SfrCntrRr.GetSurf() ; if ( pSfrRr == nullptr) return false ; pSfrRr->Translate( dMyZmove * vtCorr) ; int nRrId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPxId, pSfrRr) ; m_pGeomDB->SetName( nRrId, MCH_PV_RRCUT) ; m_pGeomDB->SetMaterial( nRrId, INVISIBLE) ; // regione di pre-taglio PtrOwner pCmpRs( GenerateExtArcPvPreCut( pArc, dIntRad, dExtRad, dDeltaT, dExtraL)) ; if ( IsNull( pCmpRs)) return false ; SurfFlatRegionByContours SfrCntrRs ; SfrCntrRs.AddCurve( Release( pCmpRs)) ; ISurfFlatRegion* pSfrRs = SfrCntrRs.GetSurf() ; if ( pSfrRs == nullptr) return false ; pSfrRs->Translate( dMyZmove * vtCorr) ; int nRsId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPxId, pSfrRs) ; m_pGeomDB->SetName( nRsId, ( bFirst ? MCH_PV_RLICUT : MCH_PV_RRCUT)) ; m_pGeomDB->SetMaterial( nRsId, INVISIBLE) ; // regione di post-taglio PtrOwner pCmpRe( GenerateExtArcPvPostCut( pArc, dIntRad, dExtRad, dDeltaT, dExtraL)) ; if ( IsNull( pCmpRe)) return false ; SurfFlatRegionByContours SfrCntrRe ; SfrCntrRe.AddCurve( Release( pCmpRe)) ; ISurfFlatRegion* pSfrRe = SfrCntrRe.GetSurf() ; if ( pSfrRe == nullptr) return false ; pSfrRe->Translate( dMyZmove * vtCorr) ; int nReId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPxId, pSfrRe) ; m_pGeomDB->SetName( nReId, ( bLast ? MCH_PV_RLOCUT : MCH_PV_RRCUT)) ; m_pGeomDB->SetMaterial( nReId, INVISIBLE) ; // regione completa (unione delle tre precedenti) int nRId = m_pGeomDB->Copy( nRrId, GDB_ID_NULL, nRrId, GDB_BEFORE) ; m_pGeomDB->SetName( nRId, MCH_PV_RCUT) ; m_pGeomDB->SetMaterial( nRId, INVISIBLE) ; if ( nRId == GDB_ID_NULL) return false ; if ( ! ExeSurfFrAdd( nRId, nRsId) || ! ExeSurfFrAdd( nRId, nReId)) return false ; } // altrimenti errore else return false ; } // salvo in info gruppo : larghezza XY del taglio, distanza XY tra centro e bordo taglio, extra taglio e quota minima della lama m_pGeomDB->SetInfo( nPxId, MCH_PV_KEY_WT, dMaxW) ; m_pGeomDB->SetInfo( nPxId, MCH_PV_KEY_DT, dDeltaT) ; m_pGeomDB->SetInfo( nPxId, MCH_PV_KEY_EC, dExtraCut) ; m_pGeomDB->SetInfo( nPxId, MCH_PV_KEY_RBH, dRbHeight) ; return true ; } //---------------------------------------------------------------------------- ICurveComposite* Sawing::GenerateExtArcPvTrueCut( const ICurveArc* pArc, double dIntRad, double dExtRad, double dSafety) { // arco interno PtrOwner pIntArc( pArc->Clone()) ; if ( IsNull( pIntArc) || ! pIntArc->ChangeRadius( dIntRad)) return nullptr ; // arco esterno PtrOwner pExtArc( pArc->Clone()) ; if ( IsNull( pExtArc) || ! pExtArc->ChangeRadius( dExtRad + dSafety)) return nullptr ; pExtArc->Invert() ; // linea di raccordo PtrOwner pLine( CreateCurveLine()) ; if ( IsNull( pLine)) return nullptr ; Point3d ptEnd ; pIntArc->GetEndPoint( ptEnd) ; Point3d ptStart ; pExtArc->GetStartPoint( ptStart) ; pLine->Set( ptEnd, ptStart) ; // composizione PtrOwner pCompo( CreateCurveComposite()) ; if ( IsNull( pCompo) || ! pCompo->AddCurve( Release( pIntArc)) || ! pCompo->AddCurve( Release( pLine)) || ! pCompo->AddCurve( Release( pExtArc)) || ! pCompo->Close()) return nullptr ; // impongo senso CCW double dArea ; if ( ! pCompo->GetAreaXY( dArea)) return nullptr ; if ( dArea < 0) pCompo->Invert() ; return Release( pCompo) ; } //---------------------------------------------------------------------------- ICurveComposite* Sawing::GenerateExtArcPvPreCut( const ICurveArc* pArc, double dIntRad, double dExtRad, double dDeltaT, double dSafety) { // direzione iniziale del taglio Vector3d vtStaDir ; pArc->GetStartDir( vtStaDir) ; // direzione radiale iniziale Vector3d vtStaVer = pArc->GetStartVersor() ; // punto iniziale Point3d ptStart ; pArc->GetStartPoint( ptStart) ; if ( ! AreHeadWorkOnSameSide()) ptStart -= vtStaVer * m_TParams.m_dThick ; // punto prima di inizio Point3d ptPre = ptStart - vtStaDir * dDeltaT ; // punto fuori prima di inizio Point3d ptOutPre = ptPre + vtStaVer * m_TParams.m_dThick ; // punto fuori inizio Point3d ptOut = ptStart + vtStaVer * ( dExtRad - dIntRad) ; // linea di spessore lama PtrOwner pLine2( CreateCurveLine()) ; if ( IsNull( pLine2) || ! pLine2->Set( ptPre, ptOutPre)) return nullptr ; // arco PtrOwner pExtArc( CreateCurveArc()) ; if ( IsNull( pExtArc) || ! pExtArc->SetC2P( pArc->GetCenter(), ptOutPre, ptOut)) return nullptr ; PtrOwner pCompo( CreateCurveComposite()) ; if ( IsNull( pCompo) || ! pCompo->AddCurve( Release( pLine2)) || ! pCompo->AddCurve( Release( pExtArc))) return nullptr ; // eventuale offset per sicurezza if ( dSafety > EPS_SMALL) { double dOffs = ( pArc->GetAngCenter() > 0 ? dSafety : - dSafety) ; if ( ! pCompo->SimpleOffset( dOffs, ICurve::OFF_EXTEND)) return nullptr ; } // linea base Point3d ptJoin ; pCompo->GetStartPoint( ptJoin) ; PtrOwner pLine1( CreateCurveLine()) ; if ( IsNull( pLine1) || ! pLine1->Set( ptStart, ptJoin)) return nullptr ; if ( ! pCompo->AddCurve( Release( pLine1), false)) return nullptr ; // chiusura if ( ! pCompo->Close()) return nullptr ; // impongo senso CCW double dArea ; if ( ! pCompo->GetAreaXY( dArea)) return nullptr ; if ( dArea < 0) pCompo->Invert() ; return Release( pCompo) ; } //---------------------------------------------------------------------------- ICurveComposite* Sawing::GenerateExtArcPvPostCut( const ICurveArc* pArc, double dIntRad, double dExtRad, double dDeltaT, double dSafety) { // direzione finale del taglio Vector3d vtEndDir ; pArc->GetEndDir( vtEndDir) ; // punto finale e direzione radiale finale Point3d ptEnd ; pArc->GetEndPoint( ptEnd) ; Vector3d vtEndVer = ptEnd - pArc->GetCenter() ; vtEndVer.Normalize() ; if ( ! AreHeadWorkOnSameSide()) ptEnd -= vtEndVer * m_TParams.m_dThick ; // punto dopo fine Point3d ptPost = ptEnd + vtEndDir * dDeltaT ; // punto fuori dopo fine Point3d ptOutPost = ptPost + vtEndVer * m_TParams.m_dThick ; // punto fuori fine Point3d ptOut = ptEnd + vtEndVer * ( dExtRad - dIntRad) ; // linea di spessore lama PtrOwner pLine2( CreateCurveLine()) ; if ( IsNull( pLine2) || ! pLine2->Set( ptPost, ptOutPost)) return nullptr ; // arco PtrOwner pExtArc( CreateCurveArc()) ; if ( IsNull( pExtArc) || ! pExtArc->SetC2P( pArc->GetCenter(), ptOutPost, ptOut)) return nullptr ; PtrOwner pCompo( CreateCurveComposite()) ; if ( IsNull( pCompo) || ! pCompo->AddCurve( Release( pLine2)) || ! pCompo->AddCurve( Release( pExtArc))) return nullptr ; // eventuale offset per sicurezza if ( dSafety > EPS_SMALL) { double dOffs = ( pArc->GetAngCenter() > 0 ? - dSafety : dSafety) ; if ( ! pCompo->SimpleOffset( dOffs, ICurve::OFF_EXTEND)) return nullptr ; } // linea base Point3d ptJoin ; pCompo->GetStartPoint( ptJoin) ; PtrOwner pLine1( CreateCurveLine()) ; if ( IsNull( pLine1) || ! pLine1->Set( ptEnd, ptJoin)) return nullptr ; if ( ! pCompo->AddCurve( Release( pLine1), false)) return nullptr ; // chiusura if ( ! pCompo->Close()) return nullptr ; // impongo senso CCW double dArea ; if ( ! pCompo->GetAreaXY( dArea)) return nullptr ; if ( dArea < 0) pCompo->Invert() ; return Release( pCompo) ; } //---------------------------------------------------------------------------- bool Sawing::GenerateExtCurveCl( const ICurveComposite* pCrv, double dElev, double dExtraCut, const string& sName, int nClId) { // creo gruppo per geometria di lavorazione della curva int nPxId = m_pGeomDB->AddGroup( GDB_ID_NULL, nClId, Frame3d()) ; if ( nPxId == GDB_ID_NULL) return false ; m_pGeomDB->SetName( nPxId, sName) ; m_pGeomDB->SetMaterial( nPxId, BLUE) ; // calcolo dati di inizio Vector3d vtStaDir ; pCrv->GetStartDir( vtStaDir) ; Vector3d vtStaTool, vtStaCorr ; CalculateToolAndCorrVersors( vtStaDir, m_Params.m_nHeadSide, m_Params.m_nWorkSide, m_Params.m_dSideAngle, vtStaTool, vtStaCorr) ; // calcolo dati di fine Vector3d vtEndDir ; pCrv->GetEndDir( vtEndDir) ; Vector3d vtEndTool, vtEndCorr ; CalculateToolAndCorrVersors( vtEndDir, m_Params.m_nHeadSide, m_Params.m_nWorkSide, m_Params.m_dSideAngle, vtEndTool, vtEndCorr) ; // assegno il vettore estrusione al gruppo del percorso m_pGeomDB->SetInfo( nPxId, KEY_EXTR, Z_AX) ; // assegno i punti di inizio e fine al gruppo del percorso Point3d ptStart ; pCrv->GetStartPoint( ptStart) ; m_pGeomDB->SetInfo( nPxId, KEY_START, ptStart) ; Point3d ptEnd ; pCrv->GetEndPoint( ptEnd) ; m_pGeomDB->SetInfo( nPxId, KEY_END, ptEnd) ; // assegno l'elevazione massima m_pGeomDB->SetInfo( nPxId, KEY_ELEV, dElev) ; // Imposto dati comuni SetPathId( nPxId) ; SetCorrAuxDir( vtStaCorr) ; // recupero distanza di sicurezza double dSafeZ = m_pMchMgr->GetCurrMachiningsMgr()->GetSafeZ() ; // lunghezza di approccio/retrazione double dAppr = m_Params.m_dStartPos ; // Se una sola passata if ( m_Params.m_dStepExtArc < EPS_SMALL || ( dElev - dExtraCut) <= m_Params.m_dStepExtArc) { // 1 -> approccio SetToolDir( vtStaTool) ; SetCorrAuxDir( vtStaCorr) ; Point3d ptP1 ; pCrv->GetStartPoint( ptP1) ; if ( ! AddApproach( ptP1, vtStaCorr, dSafeZ, dElev, dAppr)) return false ; // 2 -> movimento in affondo al punto iniziale SetFlag( 0) ; SetFeed( GetTipFeed()) ; Point3d ptP2 ; pCrv->GetStartPoint( ptP2) ; if ( AddLinearMove( ptP2) == GDB_ID_NULL) return false ; // 3 -> movimento di lato al punto finale SetFeed( GetFeed()) ; for ( const ICurve* pSmpCrv = pCrv->GetFirstCurve() ; pSmpCrv != nullptr ; pSmpCrv = pCrv->GetNextCurve()) { Vector3d vtCurrDir ; pSmpCrv->GetEndDir( vtCurrDir) ; Vector3d vtCurrTool, vtCurrCorr ; CalculateToolAndCorrVersors( vtCurrDir, m_Params.m_nHeadSide, m_Params.m_nWorkSide, m_Params.m_dSideAngle, vtCurrTool, vtCurrCorr) ; SetToolDir( vtCurrTool) ; SetCorrAuxDir( vtCurrCorr) ; if ( AddCurveMove( pSmpCrv, true) == GDB_ID_NULL) return false ; } // 4 -> retrazione Point3d ptP4 ; pCrv->GetEndPoint( ptP4) ; if ( ! AddRetract( ptP4, vtEndCorr, dSafeZ, dElev, dAppr)) return false ; } // Se step a Zig-Zag o ToAndFrom else if ( m_Params.m_nStepType == SAW_ST_ZIGZAG || m_Params.m_nStepType == SAW_ST_TOANDFROM) { // 1 -> approccio SetToolDir( vtStaTool) ; SetCorrAuxDir( vtStaCorr) ; Point3d ptP1 ; pCrv->GetStartPoint( ptP1) ; if ( ! AddApproach( ptP1, vtStaCorr, dSafeZ, dElev, dAppr)) return false ; // 2-3 -> lavorazione (sempre numero pari di passate) // calcolo numero e valore degli step double dCutH = dElev - dExtraCut ; int nStep = 2 ; if ( m_Params.m_nStepType == SAW_ST_ZIGZAG) { nStep = static_cast( ceil( dCutH / ( m_Params.m_dStepExtArc + EPS_SMALL))) ; if ( ( nStep % 2) == 1) nStep += 1 ; } double dStep = dCutH / nStep ; // esecuzione degli step for ( int i = nStep - 1 ; i >= 0 ; -- i) { // distanza dal fondo double dDelta = ( ( i != 0) ? dExtraCut + i * dStep : 0) ; // estremi del movimento (dispari vanno, pari tornano) Point3d ptP2 ; pCrv->GetStartPoint( ptP2) ; ptP2 += vtStaCorr * dDelta ; Point3d ptP3 ; pCrv->GetEndPoint( ptP3) ; ptP3 += vtEndCorr * dDelta ; if ( ( i % 2) == 0) swap( ptP2, ptP3) ; // movimento in affondo SetToolDir( ( ( i % 2) == 0) ? vtEndTool : vtStaTool) ; SetCorrAuxDir( ( ( i % 2) == 0) ? vtEndCorr : vtStaCorr) ; SetFlag( 0) ; SetFeed( GetTipFeed()) ; if ( AddLinearMove( ptP2) == GDB_ID_NULL) return false ; // movimento di lato SetFeed( GetFeed()) ; // se andata if ( ( i % 2) != 0) { // ciclo diretto sulle curve semplici componenti for ( const ICurve* pSmpCrv = pCrv->GetFirstCurve() ; pSmpCrv != nullptr ; pSmpCrv = pCrv->GetNextCurve()) { // calcolo direzione utensile Vector3d vtCurrDir ; pSmpCrv->GetEndDir( vtCurrDir) ; Vector3d vtCurrTool, vtCurrCorr ; CalculateToolAndCorrVersors( vtCurrDir, m_Params.m_nHeadSide, m_Params.m_nWorkSide, m_Params.m_dSideAngle, vtCurrTool, vtCurrCorr) ; SetToolDir( vtCurrTool) ; SetCorrAuxDir( vtCurrCorr) ; // copia della curva PtrOwner pCopy( pSmpCrv->Clone()) ; if ( IsNull( pCopy)) return false ; // traslazione pCopy->Translate( Vector3d( 0, 0, vtCurrCorr.z * dDelta)) ; // eventuale offset per angolo di fianco if ( ! vtCurrCorr.IsSmallXY()) { double dOffs = vtCurrCorr.LenXY() * dDelta ; if ( CrossXY( vtCurrCorr, vtCurrDir) < 0) dOffs = - dOffs ; pCopy->SimpleOffset( dOffs) ; } // emissione if ( AddCurveMove( pCopy, true) == GDB_ID_NULL) return false ; } } // altrimenti ritorno else { // ciclo inverso sulle curve semplici componenti for ( const ICurve* pSmpCrv = pCrv->GetLastCurve() ; pSmpCrv != nullptr ; pSmpCrv = pCrv->GetPrevCurve()) { // calcolo direzione utensile Vector3d vtCurrDir ; pSmpCrv->GetStartDir( vtCurrDir) ; Vector3d vtCurrTool, vtCurrCorr ; CalculateToolAndCorrVersors( vtCurrDir, m_Params.m_nHeadSide, m_Params.m_nWorkSide, m_Params.m_dSideAngle, vtCurrTool, vtCurrCorr) ; SetToolDir( vtCurrTool) ; SetCorrAuxDir( vtCurrCorr) ; // copia della curva PtrOwner pCopy( pSmpCrv->Clone()) ; if ( IsNull( pCopy)) return false ; // traslazione pCopy->Translate( Vector3d( 0, 0, vtCurrCorr.z * dDelta)) ; // eventuale offset per angolo di fianco if ( ! vtCurrCorr.IsSmallXY()) { double dOffs = vtCurrCorr.LenXY() * dDelta ; if ( CrossXY( vtCurrCorr, vtCurrDir) < 0) dOffs = - dOffs ; pCopy->SimpleOffset( dOffs) ; } // inversione pCopy->Invert() ; // emissione if ( AddCurveMove( pCopy, true) == GDB_ID_NULL) return false ; } } } // 4 -> retrazione SetToolDir( vtStaTool) ; SetCorrAuxDir( vtStaCorr) ; Point3d ptP4 ; pCrv->GetStartPoint( ptP4) ; if ( ! AddRetract( ptP4, vtStaCorr, dSafeZ, dElev, dAppr)) return false ; } // Altrimenti step a una via else { // 1 -> approccio SetToolDir( vtStaTool) ; SetCorrAuxDir( vtStaCorr) ; Point3d ptP1 ; pCrv->GetStartPoint( ptP1) ; if ( ! AddApproach( ptP1, vtStaCorr, dSafeZ, dElev, dAppr)) return false ; // 2-3 -> lavorazione // calcolo numero e valore degli step double dCutH = dElev - dExtraCut ; int nStep = static_cast( ceil( dCutH / ( m_Params.m_dStepExtArc + EPS_SMALL))) ; double dStep = dCutH / nStep ; // esecuzione degli step for ( int i = nStep - 1 ; i >= 0 ; -- i) { // distanza dal fondo double dDelta = ( ( i != 0) ? dExtraCut + i * dStep : 0) ; // movimento in affondo al punto iniziale SetToolDir( vtStaTool) ; SetCorrAuxDir( vtStaCorr) ; SetFlag( 0) ; SetFeed( GetTipFeed()) ; Point3d ptP2 ; pCrv->GetStartPoint( ptP2) ; ptP2 += vtStaCorr * dDelta ; if ( AddLinearMove( ptP2) == GDB_ID_NULL) return false ; // movimento di lato al punto finale SetFeed( GetFeed()) ; for ( const ICurve* pSmpCrv = pCrv->GetFirstCurve() ; pSmpCrv != nullptr ; pSmpCrv = pCrv->GetNextCurve()) { Vector3d vtCurrDir ; pSmpCrv->GetEndDir( vtCurrDir) ; Vector3d vtCurrTool, vtCurrCorr ; CalculateToolAndCorrVersors( vtCurrDir, m_Params.m_nHeadSide, m_Params.m_nWorkSide, m_Params.m_dSideAngle, vtCurrTool, vtCurrCorr) ; SetToolDir( vtCurrTool) ; SetCorrAuxDir( vtCurrCorr) ; // copia della curva PtrOwner pCopy( pSmpCrv->Clone()) ; if ( IsNull( pCopy)) return false ; // traslazione pCopy->Translate( Vector3d( 0, 0, vtCurrCorr.z * dDelta)) ; // eventuale offset per angolo di fianco if ( ! vtCurrCorr.IsSmallXY()) { double dOffs = vtCurrCorr.LenXY() * dDelta ; if ( CrossXY( vtCurrCorr, vtCurrDir) < 0) dOffs = - dOffs ; pCopy->SimpleOffset( dOffs) ; } // emissione if ( AddCurveMove( pCopy, true) == GDB_ID_NULL) return false ; } // se non è ultimo passo if ( i != 0) { // ricavo punto di risalita e punto iniziale Point3d ptP4 ; pCrv->GetEndPoint( ptP4) ; ptP4 += vtEndCorr * ( dElev + dAppr / vtEndCorr.z) ; Point3d ptP5 ; pCrv->GetStartPoint( ptP5) ; ptP5 += vtStaCorr * ( dElev + dAppr / vtStaCorr.z) ; // se sono diversi o le direzioni utensile sono diverse if ( ! AreSamePointApprox( ptP4, ptP5) || ! AreSameVectorApprox( vtEndTool, vtStaTool)) { // movimento di risalita sopra il punto finale SetFeed( GetEndFeed()) ; if ( AddLinearMove( ptP4) == GDB_ID_NULL) return false ; // movimento di ritorno sopra il punto iniziale SetToolDir( vtStaTool) ; SetCorrAuxDir( vtStaCorr) ; SetFeed( GetEndFeed()) ; if ( AreSamePointEpsilon( ptP4, ptP5, 10 * EPS_SMALL)) ptP5 -= vtStaCorr * 10 * EPS_SMALL ; if ( AddLinearMove( ptP5) == GDB_ID_NULL) return false ; } } } // 4 -> retrazione Point3d ptP4 ; pCrv->GetEndPoint( ptP4) ; if ( ! AddRetract( ptP4, vtEndCorr, dSafeZ, dElev, dAppr)) return false ; } return true ; } //---------------------------------------------------------------------------- bool Sawing::ProcessIntArc( const ICurve* pCrvP, const ICurveArc* pArcC, const ICurve* pCrvN, double dDepth, double dExtraCut, double dRbHeight, bool bIsFirst, bool bIsLast, const string& sName, int nPvId, int nClId) { // copio la curva PtrOwner pArc( pArcC->Clone()) ; if ( IsNull( pArc)) return false ; // determino l'inclinazione per ottenere il raggio e ne verifico il limite double dMaxSideAng = m_pMchMgr->GetCurrMachiningsMgr()->GetIntSawArcMaxSideAng()+ EPS_ANG_SMALL ; double dSawRad = m_TParams.m_dDiam / 2 ; double dRad = pArc->GetRadius() ; double dSinA = dSawRad / dRad ; if ( dSinA > sin( dMaxSideAng * DEGTORAD)) { m_pMchMgr->SetWarning( 2259, "Warning in Sawing : Radius too small in IntSawArc") ; return true ; } double dSideAng = - asin( dSinA) * RADTODEG ; // Verifiche su lato di lavoro e lato testa (si lavora con angolo di sbandamento negativo) int nHeadSide = m_Params.m_nHeadSide ; if ( m_Params.m_nWorkSide == SAW_WS_CENTER) { m_pMchMgr->SetLastError( 2213, "Error in Sawing : Center work not allowed with internal arc") ; return false ; } else if ( m_Params.m_nWorkSide == SAW_WS_LEFT) { if ( m_Params.m_nHeadSide == SAW_HS_LEFT) nHeadSide = SAW_HS_RIGHT ; } else { if ( m_Params.m_nHeadSide == SAW_HS_RIGHT) nHeadSide = SAW_HS_LEFT ; } // Recupero le direzioni iniziale, intermedia e finale dell'arco Vector3d vtStaDirC ; pArc->GetStartDir( vtStaDirC) ; Vector3d vtMidDirC ; pArc->GetMidDir( vtMidDirC) ; Vector3d vtEndDirC ; pArc->GetEndDir( vtEndDirC) ; // calcolo i versori fresa e correzione Vector3d vtStaTool, vtStaCorr, vtMidTool, vtMidCorr, vtEndTool, vtEndCorr ; if ( ! CalculateToolAndCorrVersors( vtStaDirC, nHeadSide, m_Params.m_nWorkSide, dSideAng, vtStaTool, vtStaCorr) || ! CalculateToolAndCorrVersors( vtMidDirC, nHeadSide, m_Params.m_nWorkSide, dSideAng, vtMidTool, vtMidCorr) || ! CalculateToolAndCorrVersors( vtEndDirC, nHeadSide, m_Params.m_nWorkSide, dSideAng, vtEndTool, vtEndCorr)) { m_pMchMgr->SetLastError( 2208, "Error in Sawing : Entity CalculateToolAndCorrVersors") ; return false ; } // correzioni per lato lama, lato mandrino if ( ! AdjustIntArcForSide( pArc, dSideAng)) { m_pMchMgr->SetLastError( 2209, "Error in Sawing : Entity AdjustForSide") ; return false ; } // aggiungo affondamento pArc->Translate( - Z_AX * ( dDepth + dSinA * m_TParams.m_dThick)) ; // calcolo elevazione (sui due bordi della striscia) double dElev, dElev2 ; Point3d ptStart, ptMid, ptEnd ; pArc->GetStartPoint( ptStart) ; pArc->GetMidPoint( ptMid) ; pArc->GetEndPoint( ptEnd) ; Vector3d vtStaThick = vtStaTool * m_TParams.m_dThick ; Vector3d vtMidThick = vtMidTool * m_TParams.m_dThick ; Vector3d vtEndThick = vtEndTool * m_TParams.m_dThick ; if ( ! GetElevation( m_nPhase, ptStart, ptMid, ptEnd, Z_AX, dElev) || ! GetElevation( m_nPhase, ptStart + vtStaThick, ptMid + vtMidThick, ptEnd + vtEndThick, Z_AX, dElev2) ) { m_pMchMgr->SetLastError( 2210, "Error in Sawing : Entity GetElevation") ; return false ; } dElev = max( dElev, dElev2) ; // calcolo tipo angolo con precedente bool bExtAngPC = true ; if ( pCrvP != nullptr) { Vector3d vtDirP ; pCrvP->GetEndDir( vtDirP) ; double dAngPC ; vtDirP.GetAngleXY( vtStaDirC, dAngPC) ; if ( ( m_Params.m_nWorkSide == SAW_WS_LEFT && dAngPC > EPS_ANG_SMALL) || ( m_Params.m_nWorkSide == SAW_WS_RIGHT && dAngPC < - EPS_ANG_SMALL)) bExtAngPC = false ; } // calcolo tipo angolo con successivo bool bExtAngCN = true ; if ( pCrvN != nullptr) { Vector3d vtDirN ; pCrvN->GetStartDir( vtDirN) ; double dAngCN ; vtEndDirC.GetAngleXY( vtDirN, dAngCN) ; if ( ( m_Params.m_nWorkSide == SAW_WS_LEFT && dAngCN > EPS_ANG_SMALL) || ( m_Params.m_nWorkSide == SAW_WS_RIGHT && dAngCN < - EPS_ANG_SMALL)) bExtAngCN = false ; } // aggiusto per tipo estremi double dCosA = vtStaCorr.z ; double dSlantElev = dElev / dCosA ; double dDelta = dElev * dSinA / dCosA + m_TParams.m_dThick * dCosA ; // larghezza impronta double dLenCoeff = ( dRad + 0.8 * dDelta) / dRad ; // coefficiente per riportare lunghezza bool bToSkip = false ; if ( ! AdjustCurveForEdges( pArc, dSlantElev, dLenCoeff, bIsFirst, bIsLast, bExtAngPC, bExtAngCN, bToSkip)) { m_pMchMgr->SetLastError( 2211, "Error in Sawing : Entity AdjustForEdges") ; return false ; } if ( bToSkip) { m_pMchMgr->SetWarning( 2257, "Warning in Sawing : skipped Entity too small") ; return true ; } // ricalcolo i versori fresa alle estremità (potrebbero essere cambiate) pArc->GetStartDir( vtStaDirC) ; pArc->GetMidDir( vtMidDirC) ; pArc->GetEndDir( vtEndDirC) ; if ( ! CalculateToolAndCorrVersors( vtStaDirC, nHeadSide, m_Params.m_nWorkSide, dSideAng, vtStaTool, vtStaCorr) || ! CalculateToolAndCorrVersors( vtMidDirC, nHeadSide, m_Params.m_nWorkSide, dSideAng, vtMidTool, vtMidCorr) || ! CalculateToolAndCorrVersors( vtEndDirC, nHeadSide, m_Params.m_nWorkSide, dSideAng, vtEndTool, vtEndCorr)) { m_pMchMgr->SetLastError( 2212, "Error in Sawing : Entity CalculateToolAndCorrVersors 2nd") ; return false ; } // Se richiesto Preview if ( nPvId != GDB_ID_NULL) { if ( ! GenerateIntArcPv( pArc, vtStaTool, vtMidTool, vtEndTool, vtStaCorr, vtMidCorr, vtEndCorr, dElev, dExtraCut, dRbHeight, dLenCoeff, sName, nPvId)) return false ; } // Se richiesta geometria di lavorazione if ( nClId != GDB_ID_NULL) { if ( ! GenerateIntArcCl( pArc, vtStaTool, vtMidTool, vtEndTool, vtStaCorr, vtMidCorr, vtEndCorr, dElev, dExtraCut, sName, nClId)) return false ; } // incremento numero di tagli ++ m_nCuts ; return true ; } //---------------------------------------------------------------------------- bool Sawing::GenerateIntArcPv( const ICurveArc* pArc, const Vector3d& vtStaTool, const Vector3d& vtMidTool, const Vector3d& vtEndTool, const Vector3d& vtStaCorr, const Vector3d& vtMidCorr, const Vector3d& vtEndCorr, double dElev, double dExtraCut, double dRbHeight, double dLenCoeff, const string& sName, int nPvId) { // creo gruppo per anteprima di lavorazione dell'arco int nPxId = m_pGeomDB->AddGroup( GDB_ID_NULL, nPvId, Frame3d()) ; if ( nPxId == GDB_ID_NULL) return false ; m_pGeomDB->SetName( nPxId, sName) ; m_pGeomDB->SetMaterial( nPxId, BLUE) ; // disabilito eventuale registrazione comandi EXE (riabilitazione automatica) CmdLogOff cmdLogOff ; // seno e coseno dell'angolo di sbandamento double dSinA = sqrt( vtStaCorr.x * vtStaCorr.x + vtStaCorr.y * vtStaCorr.y) ; double dCosA = vtStaCorr.z ; // elevazione inclinata double dSlantElev = dElev / dCosA ; // lunghezza taglio parziale double dDeltaT = (( dSlantElev < 0.5 * m_TParams.m_dDiam) ? sqrt( dSlantElev * m_TParams.m_dDiam - dSlantElev * dSlantElev) : 0) ; // scostamenti da linea di lavoro (testa e lavoro sono da parti opposte) double dDeltaInt = dElev * dSinA / dCosA ; double dDeltaExt = m_TParams.m_dThick * dCosA ; // larghezza inclinata della lama (formula euristica che funziona abbastanza) double dSlantThick = m_TParams.m_dThick * dCosA ; // contorno per parte di taglio completo PtrOwner pCompo( GenerateIntArcPvTrueCut( pArc, dDeltaInt, dDeltaExt, 0)) ; if ( IsNull( pCompo)) return false ; pCompo->Translate( dElev * Z_AX + Vector3d( 0, 0, 0.1)) ; int nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPxId, Release( pCompo)) ; m_pGeomDB->SetName( nId, MCH_PV_CUT) ; m_pGeomDB->SetMaterial( nId, LIME) ; // contorno per parte iniziale di taglio PtrOwner pCompo2( GenerateIntArcPvPreCut( pArc, dDeltaInt, dDeltaExt, dSlantThick, dDeltaT, 0)) ; if ( IsNull( pCompo2)) return false ; pCompo2->Translate( dElev * Z_AX) ; int nId2 = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPxId, Release( pCompo2)) ; m_pGeomDB->SetName( nId2, MCH_PV_PRE_CUT) ; m_pGeomDB->SetMaterial( nId2, BLUE) ; // contorno per parte finale di taglio PtrOwner pCompo3( GenerateIntArcPvPostCut( pArc, dDeltaInt, dDeltaExt, dSlantThick, dDeltaT, 0)) ; if ( IsNull( pCompo3)) return false ; pCompo3->Translate( dElev * Z_AX) ; int nId3 = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPxId, Release( pCompo3)) ; m_pGeomDB->SetName( nId3, MCH_PV_POST_CUT) ; m_pGeomDB->SetMaterial( nId3, BLUE) ; // dimensione da aggiungere alle regioni nelle parti in cui la lama è inclinata double dExtraL = m_pMchMgr->GetCurrMachiningsMgr()->GetExtraLOnCutRegion() ; // regione ridotta di taglio per nesting (escluse parti iniziali e finali) PtrOwner pCmpRr( GenerateIntArcPvTrueCut( pArc, dDeltaInt, dDeltaExt, dExtraL)) ; if ( IsNull( pCmpRr)) return false ; SurfFlatRegionByContours SfrCntrRr ; SfrCntrRr.AddCurve( Release( pCmpRr)) ; ISurfFlatRegion* pSfrRr = SfrCntrRr.GetSurf() ; if ( pSfrRr == nullptr) return false ; pSfrRr->Translate( dElev * Z_AX) ; int nRrId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPxId, pSfrRr) ; m_pGeomDB->SetName( nRrId, MCH_PV_RRCUT) ; m_pGeomDB->SetMaterial( nRrId, INVISIBLE) ; // regione di pre-taglio PtrOwner pCmpRs( GenerateIntArcPvPreCut( pArc, dDeltaInt, dDeltaExt, dSlantThick, dDeltaT, dExtraL)) ; if ( IsNull( pCmpRs)) return false ; SurfFlatRegionByContours SfrCntrRs ; SfrCntrRs.AddCurve( Release( pCmpRs)) ; ISurfFlatRegion* pSfrRs = SfrCntrRs.GetSurf() ; if ( pSfrRs == nullptr) return false ; pSfrRs->Translate( dElev * Z_AX) ; int nRsId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPxId, pSfrRs) ; m_pGeomDB->SetName( nRsId, MCH_PV_RLICUT) ; m_pGeomDB->SetMaterial( nRsId, INVISIBLE) ; // regione di post-taglio PtrOwner pCmpRe( GenerateIntArcPvPostCut( pArc, dDeltaInt, dDeltaExt, dSlantThick, dDeltaT, dExtraL)) ; if ( IsNull( pCmpRe)) return false ; SurfFlatRegionByContours SfrCntrRe ; SfrCntrRe.AddCurve( Release( pCmpRe)) ; ISurfFlatRegion* pSfrRe = SfrCntrRe.GetSurf() ; if ( pSfrRe == nullptr) return false ; pSfrRe->Translate( dElev * Z_AX) ; int nReId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nPxId, pSfrRe) ; m_pGeomDB->SetName( nReId, MCH_PV_RLOCUT) ; m_pGeomDB->SetMaterial( nReId, INVISIBLE) ; // regione completa (unione delle tre precedenti) int nRId = m_pGeomDB->Copy( nRrId, GDB_ID_NULL, nRrId, GDB_BEFORE) ; m_pGeomDB->SetName( nRId, MCH_PV_RCUT) ; m_pGeomDB->SetMaterial( nRId, INVISIBLE) ; if ( nRId == GDB_ID_NULL) return false ; if ( ! ExeSurfFrAdd( nRId, nRsId) || ! ExeSurfFrAdd( nRId, nReId)) return false ; // salvo in info gruppo : larghezza XY del taglio, distanza XY tra centro e bordo taglio, extra taglio e quota minima della lama m_pGeomDB->SetInfo( nPxId, MCH_PV_KEY_WT, dDeltaInt + dDeltaExt) ; m_pGeomDB->SetInfo( nPxId, MCH_PV_KEY_DT, dDeltaT * dLenCoeff) ; m_pGeomDB->SetInfo( nPxId, MCH_PV_KEY_EC, dExtraCut) ; m_pGeomDB->SetInfo( nPxId, MCH_PV_KEY_RBH, dRbHeight) ; return true ; } //---------------------------------------------------------------------------- ICurveComposite* Sawing::GenerateIntArcPvTrueCut( const ICurveArc* pArc, double dDeltaInt, double dDeltaExt, double dSafety) { // arco interno PtrOwner pIntArc( pArc->Clone()) ; if ( IsNull( pIntArc) || ! pIntArc->ChangeRadius( pArc->GetRadius() - dDeltaInt - dSafety)) return nullptr ; // arco esterno PtrOwner pExtArc( pArc->Clone()) ; if ( IsNull( pExtArc) || ! pExtArc->ChangeRadius( pArc->GetRadius() + dDeltaExt)) return nullptr ; pExtArc->Invert() ; // linea di raccordo PtrOwner pLine( CreateCurveLine()) ; if ( IsNull( pLine)) return nullptr ; Point3d ptEnd ; pIntArc->GetEndPoint( ptEnd) ; Point3d ptStart ; pExtArc->GetStartPoint( ptStart) ; pLine->Set( ptEnd, ptStart) ; // composizione PtrOwner pCompo( CreateCurveComposite()) ; if ( IsNull( pCompo) || ! pCompo->AddCurve( Release( pIntArc)) || ! pCompo->AddCurve( Release( pLine)) || ! pCompo->AddCurve( Release( pExtArc)) || ! pCompo->Close()) return nullptr ; // impongo senso CCW double dArea ; if ( ! pCompo->GetAreaXY( dArea)) return nullptr ; if ( dArea < 0) pCompo->Invert() ; return Release( pCompo) ; } //---------------------------------------------------------------------------- ICurveComposite* Sawing::GenerateIntArcPvPreCut( const ICurveArc* pArc, double dDeltaInt, double dDeltaExt, double dSlantThick, double dDeltaT, double dSafety) { // direzione iniziale del taglio Vector3d vtStaDir ; pArc->GetStartDir( vtStaDir) ; // direzione radiale iniziale Vector3d vtStaVer = pArc->GetStartVersor() ; // punto iniziale Point3d ptStart ; pArc->GetStartPoint( ptStart) ; ptStart -= vtStaVer * dDeltaInt ; // punto prima di inizio Point3d ptPre = ptStart - vtStaDir * dDeltaT ; // punto fuori prima di inizio Point3d ptOutPre = ptPre + vtStaVer * dSlantThick ; // punto fuori inizio Point3d ptOut = ptStart + vtStaVer * ( dDeltaInt + dDeltaExt) ; // linea base PtrOwner pLine1( CreateCurveLine()) ; if ( IsNull( pLine1) || ! pLine1->Set( ptStart, ptPre)) return nullptr ; // linea di spessore lama PtrOwner pLine2( CreateCurveLine()) ; if ( IsNull( pLine2) || ! pLine2->Set( ptPre, ptOutPre)) return nullptr ; // composita delle due linee PtrOwner pCompo( CreateCurveComposite()) ; if ( IsNull( pCompo) || ! pCompo->AddCurve( Release( pLine1)) || ! pCompo->AddCurve( Release( pLine2))) return nullptr ; // eventuale offset per sicurezza if ( dSafety > EPS_SMALL) { double dOffs = ( pArc->GetAngCenter() > 0 ? dSafety : - dSafety) ; if ( ! pCompo->SimpleOffset( dOffs, ICurve::OFF_EXTEND)) return nullptr ; } // arco Point3d ptJoin ; pCompo->GetEndPoint( ptJoin) ; PtrOwner pExtArc( CreateCurveArc()) ; if ( IsNull( pExtArc) || ! pExtArc->Set2PVN( ptOut, ptJoin, - vtStaDir, Z_AX) || ! pExtArc->Invert()) return nullptr ; if ( ! pCompo->AddCurve( Release( pExtArc))) return nullptr ; // chiusura if ( ! pCompo->Close()) return nullptr ; // impongo senso CCW double dArea ; if ( ! pCompo->GetAreaXY( dArea)) return nullptr ; if ( dArea < 0) pCompo->Invert() ; return Release( pCompo) ; } //---------------------------------------------------------------------------- ICurveComposite* Sawing::GenerateIntArcPvPostCut( const ICurveArc* pArc, double dDeltaInt, double dDeltaExt, double dSlantThick, double dDeltaT, double dSafety) { // direzione finale del taglio Vector3d vtEndDir ; pArc->GetEndDir( vtEndDir) ; // punto finale e direzione radiale finale Point3d ptEnd ; pArc->GetEndPoint( ptEnd) ; Vector3d vtEndVer = ptEnd - pArc->GetCenter() ; vtEndVer.Normalize() ; ptEnd -= vtEndVer * dDeltaInt ; // punto dopo fine Point3d ptPost = ptEnd + vtEndDir * dDeltaT ; // punto fuori dopo fine Point3d ptOutPost = ptPost + vtEndVer * dSlantThick ; // punto fuori fine Point3d ptOut = ptEnd + vtEndVer * ( dDeltaInt + dDeltaExt) ; // linea base PtrOwner pLine1( CreateCurveLine()) ; if ( IsNull( pLine1) || ! pLine1->Set( ptEnd, ptPost)) return nullptr ; // linea di spessore lama PtrOwner pLine2( CreateCurveLine()) ; if ( IsNull( pLine2) || ! pLine2->Set( ptPost, ptOutPost)) return nullptr ; PtrOwner pCompo( CreateCurveComposite()) ; if ( IsNull( pCompo) || ! pCompo->AddCurve( Release( pLine1)) || ! pCompo->AddCurve( Release( pLine2))) return nullptr ; // eventuale offset per sicurezza if ( dSafety > EPS_SMALL) { double dOffs = ( pArc->GetAngCenter() > 0 ? - dSafety : dSafety) ; if ( ! pCompo->SimpleOffset( dOffs, ICurve::OFF_EXTEND)) return nullptr ; } // arco Point3d ptJoin ; pCompo->GetEndPoint( ptJoin) ; PtrOwner pExtArc( CreateCurveArc()) ; if ( IsNull( pExtArc) || ! pExtArc->Set2PVN( ptOut, ptJoin, vtEndDir, Z_AX) || ! pExtArc->Invert()) return nullptr ; if ( ! pCompo->AddCurve( Release( pExtArc))) return nullptr ; // chiusura if ( ! pCompo->Close()) return nullptr ; // impongo senso CCW double dArea ; if ( ! pCompo->GetAreaXY( dArea)) return nullptr ; if ( dArea < 0) pCompo->Invert() ; return Release( pCompo) ; } //---------------------------------------------------------------------------- bool Sawing::GenerateIntArcCl( const ICurveArc* pArc, const Vector3d& vtStaTool, const Vector3d& vtMidTool, const Vector3d& vtEndTool, const Vector3d& vtStaCorr, const Vector3d& vtMidCorr, const Vector3d& vtEndCorr, double dElev, double dExtraCut, const string& sName, int nClId) { // creo gruppo per geometria di lavorazione dell'arco int nPxId = m_pGeomDB->AddGroup( GDB_ID_NULL, nClId, Frame3d()) ; if ( nPxId == GDB_ID_NULL) return false ; m_pGeomDB->SetName( nPxId, sName) ; m_pGeomDB->SetMaterial( nPxId, BLUE) ; // assegno il vettore estrazione al gruppo del percorso m_pGeomDB->SetInfo( nPxId, KEY_EXTR, Z_AX) ; // assegno i punti di inizio e fine al gruppo del percorso Point3d ptStart ; pArc->GetStartPoint( ptStart) ; m_pGeomDB->SetInfo( nPxId, KEY_START, ptStart) ; Point3d ptEnd ; pArc->GetEndPoint( ptEnd) ; m_pGeomDB->SetInfo( nPxId, KEY_END, ptEnd) ; // assegno l'elevazione massima m_pGeomDB->SetInfo( nPxId, KEY_ELEV, dElev) ; // Imposto dati comuni SetPathId( nPxId) ; // recupero distanza di sicurezza double dSafeZ = m_pMchMgr->GetCurrMachiningsMgr()->GetSafeZ() ; // lunghezza di approccio/retrazione double dAppr = m_Params.m_dStartPos ; // Se una sola passata if ( m_Params.m_dStepIntArc < EPS_SMALL || ( dElev - dExtraCut) <= m_Params.m_dStepIntArc) { // 1 -> approccio SetToolDir( vtStaTool) ; SetCorrAuxDir( vtStaCorr) ; Point3d ptP1 ; pArc->GetStartPoint( ptP1) ; if ( ! AddApproach( ptP1, Z_AX, dSafeZ, dElev, dAppr)) return false ; // 2 -> movimento in affondo al punto iniziale SetFlag( 0) ; SetFeed( GetTipFeed()) ; Point3d ptP2 ; pArc->GetStartPoint( ptP2) ; if ( AddLinearMove( ptP2) == GDB_ID_NULL) return false ; // 3 -> movimento di lato al punto finale SetFeed( GetFeed()) ; Point3d ptCen = pArc->GetCenter() ; double dAngCen = pArc->GetAngCenter() ; Vector3d vtN = pArc->GetNormVersor() ; Point3d ptP3 ; pArc->GetEndPoint( ptP3) ; // se angolo al centro minore del limite, un solo arco if ( abs( pArc->GetAngCenter()) < MAX_ANG_CEN) { SetToolDir( vtEndTool) ; SetCorrAuxDir( vtEndCorr) ; if ( AddArcMove( ptP3, ptCen, dAngCen, vtN) == GDB_ID_NULL) return false ; } // altrimenti due archi else { Point3d ptMid ; pArc->GetMidPoint( ptMid) ; // prima metà arco SetToolDir( vtMidTool) ; SetCorrAuxDir( vtMidCorr) ; if ( AddArcMove( ptMid, ptCen, dAngCen / 2, vtN) == GDB_ID_NULL) return false ; // seconda metà arco SetToolDir( vtEndTool) ; SetCorrAuxDir( vtEndCorr) ; if ( AddArcMove( ptP3, ptCen, dAngCen / 2, vtN) == GDB_ID_NULL) return false ; } // 4 -> retrazione Point3d ptP4 ; pArc->GetEndPoint( ptP4) ; if ( ! AddRetract( ptP4, Z_AX, dSafeZ, dElev, dAppr)) return false ; } // Se step a Zig-Zag o ToAndFrom else if ( m_Params.m_nStepType == SAW_ST_ZIGZAG || m_Params.m_nStepType == SAW_ST_TOANDFROM) { // 1 -> approccio SetToolDir( vtStaTool) ; SetCorrAuxDir( vtStaCorr) ; Point3d ptP1 ; pArc->GetStartPoint( ptP1) ; if ( ! AddApproach( ptP1, Z_AX, dSafeZ, dElev, dAppr)) return false ; // 2-3 -> lavorazione (sempre numero pari di passate) // calcolo numero e valore degli step double dCutH = dElev - dExtraCut ; int nStep = 2 ; if ( m_Params.m_nStepType == SAW_ST_ZIGZAG) { nStep = static_cast( ceil( dCutH / ( m_Params.m_dStepIntArc + EPS_SMALL))) ; if ( ( nStep % 2) == 1) nStep += 1 ; } double dStep = dCutH / nStep ; // esecuzione degli step for ( int i = nStep - 1 ; i >= 0 ; -- i) { // distanza dal fondo double dDelta = ( ( i != 0) ? dExtraCut + i * dStep : 0) ; // estremi del movimento (dispari vanno, pari tornano) Point3d ptP2 ; pArc->GetStartPoint( ptP2) ; ptP2 += Z_AX * dDelta ; Point3d ptP3 ; pArc->GetEndPoint( ptP3) ; ptP3 += Z_AX * dDelta ; if ( ( i % 2) == 0) swap( ptP2, ptP3) ; // versori Vector3d vtTool2 = ( ( i % 2) == 0) ? vtEndTool : vtStaTool ; SetToolDir( vtTool2) ; Vector3d vtCorr2 = ( ( i % 2) == 0) ? vtEndCorr : vtStaCorr ; SetCorrAuxDir( vtCorr2) ; SetFlag( 0) ; // se non primo, movimento laterale sopra if ( i != nStep - 1) { Point3d ptUp = ptP2 + vtCorr2 * ( dElev - dDelta + dAppr) / vtCorr2.z ; SetFeed( GetEndFeed()) ; if ( AddLinearMove( ptUp) == GDB_ID_NULL) return false ; } // movimento in affondo SetFeed( GetTipFeed()) ; if ( AddLinearMove( ptP2) == GDB_ID_NULL) return false ; // movimento di lato SetFeed( GetFeed()) ; Point3d ptCen = pArc->GetCenter() ; double dAngCen = pArc->GetAngCenter() ; Vector3d vtN = pArc->GetNormVersor() ; // se angolo al centro minore del limite, un solo arco if ( abs( dAngCen) < MAX_ANG_CEN) { double dCurrAngCen = dAngCen * ((( i % 2) == 0) ? -1 : 1) ; SetToolDir( ( ( i % 2) == 0) ? vtStaTool : vtEndTool) ; SetCorrAuxDir( ( ( i % 2) == 0) ? vtStaCorr : vtEndCorr) ; if ( AddArcMove( ptP3, ptCen, dCurrAngCen, vtN) == GDB_ID_NULL) return false ; } // altrimenti due archi else { Point3d ptMid ; pArc->GetMidPoint( ptMid) ; ptMid += Z_AX * dDelta ; double dCurrAngCen = dAngCen / 2 * ((( i % 2) == 0) ? -1 : 1) ; // prima metà arco SetToolDir( vtMidTool) ; SetCorrAuxDir( vtMidCorr) ; if ( AddArcMove( ptMid, ptCen, dCurrAngCen, vtN) == GDB_ID_NULL) return false ; // seconda metà arco SetToolDir( ( ( i % 2) == 0) ? vtStaTool : vtEndTool) ; SetCorrAuxDir( ( ( i % 2) == 0) ? vtStaCorr : vtEndCorr) ; if ( AddArcMove( ptP3, ptCen, dCurrAngCen, vtN) == GDB_ID_NULL) return false ; } // se intermedio, risalita inclinata if ( i > 0) { Vector3d vtCorr3 = ( ( i % 2) == 0) ? vtStaCorr : vtEndCorr ; Point3d ptUp = ptP3 + vtCorr3 * ( dElev - dDelta + dAppr) / vtCorr3.z ; SetFeed( GetEndFeed()) ; if ( AddLinearMove( ptUp) == GDB_ID_NULL) return false ; } } // 4 -> retrazione SetToolDir( vtStaTool) ; SetCorrAuxDir( vtStaCorr) ; Point3d ptP4 ; pArc->GetStartPoint( ptP4) ; if ( ! AddRetract( ptP4, Z_AX, dSafeZ, dElev, dAppr)) return false ; } // Altrimenti step a una via else { // 1 -> approccio SetToolDir( vtStaTool) ; SetCorrAuxDir( vtStaCorr) ; Point3d ptP1 ; pArc->GetStartPoint( ptP1) ; if ( ! AddApproach( ptP1, Z_AX, dSafeZ, dElev, dAppr)) return false ; // 2-3 -> lavorazione // calcolo numero e valore degli step double dCutH = dElev - dExtraCut ; int nStep = static_cast( ceil( dCutH / ( m_Params.m_dStepIntArc + EPS_SMALL))) ; double dStep = dCutH / nStep ; // esecuzione degli step for ( int i = nStep - 1 ; i >= 0 ; -- i) { // distanza dal fondo double dDelta = ( ( i != 0) ? dExtraCut + i * dStep : 0) ; // se non primo, movimento laterale sopra if ( i != nStep - 1) { // movimento di ritorno sopra il punto iniziale SetToolDir( vtStaTool) ; SetCorrAuxDir( vtStaCorr) ; SetFeed( GetEndFeed()) ; Point3d ptP5 ; pArc->GetStartPoint( ptP5) ; ptP5 += Z_AX * dDelta + vtStaCorr * ( dElev - dDelta + dAppr) / vtStaCorr.z ; if ( AddLinearMove( ptP5) == GDB_ID_NULL) return false ; } // movimento in affondo al punto iniziale SetToolDir( vtStaTool) ; SetCorrAuxDir( vtStaCorr) ; SetFlag( 0) ; SetFeed( GetTipFeed()) ; Point3d ptP2 ; pArc->GetStartPoint( ptP2) ; ptP2 += Z_AX * dDelta ; if ( AddLinearMove( ptP2) == GDB_ID_NULL) return false ; // movimento di lato al punto finale SetFeed( GetFeed()) ; Point3d ptCen = pArc->GetCenter() ; double dAngCen = pArc->GetAngCenter() ; Vector3d vtN = pArc->GetNormVersor() ; Point3d ptP3 ; pArc->GetEndPoint( ptP3) ; ptP3 += Z_AX * dDelta ; // se angolo al centro minore del limite, un solo arco if ( abs( dAngCen) < MAX_ANG_CEN) { SetToolDir( vtEndTool) ; SetCorrAuxDir( vtEndCorr) ; if ( AddArcMove( ptP3, ptCen, dAngCen, vtN) == GDB_ID_NULL) return false ; } // altrimenti due archi else { Point3d ptMid ; pArc->GetMidPoint( ptMid) ; ptMid += Z_AX * dDelta ; // prima metà arco SetToolDir( vtMidTool) ; SetCorrAuxDir( vtMidCorr) ; if ( AddArcMove( ptMid, ptCen, dAngCen / 2, vtN) == GDB_ID_NULL) return false ; // seconda metà arco SetToolDir( vtEndTool) ; SetCorrAuxDir( vtEndCorr) ; if ( AddArcMove( ptP3, ptCen, dAngCen / 2, vtN) == GDB_ID_NULL) return false ; } // se non è ultimo passo if ( i != 0) { // movimento di risalita sopra il punto finale SetFeed( GetEndFeed()) ; Point3d ptP4 ; pArc->GetEndPoint( ptP4) ; ptP4 += Z_AX * ( dElev + dAppr) ; if ( AddLinearMove( ptP4) == GDB_ID_NULL) return false ; } } // 4 -> retrazione Point3d ptP4 ; pArc->GetEndPoint( ptP4) ; if ( ! AddRetract( ptP4, Z_AX, dSafeZ, dElev, dAppr)) return false ; } return true ; } //---------------------------------------------------------------------------- bool Sawing::AddApproach( const Point3d& ptP, const Vector3d& vtCorr, double dSafeZ, double dElev, double dAppr) { // se distanza di sicurezza minore di distanza di inizio if ( dSafeZ < m_Params.m_dStartPos + 10 * EPS_SMALL) { // 1 -> punto sopra inizio SetFlag( 1) ; Point3d ptP1 = ptP + vtCorr * ( dElev + dAppr / vtCorr.z) ; if ( AddRapidStart( ptP1) == GDB_ID_NULL) return false ; } else { // 1a -> punto sopra inizio SetFlag( 1) ; Point3d ptP1b = ptP + vtCorr * ( dElev + dAppr / vtCorr.z) ; Point3d ptP1a = ptP1b + Z_AX * ( dSafeZ - m_Params.m_dStartPos) ; if ( AddRapidStart( ptP1a) == GDB_ID_NULL) return false ; // 1b -> punto appena sopra inizio SetFlag( 0) ; if ( AddRapidMove( ptP1b) == GDB_ID_NULL) return false ; } return true ; } //---------------------------------------------------------------------------- bool Sawing::AddRetract( const Point3d& ptP, const Vector3d& vtCorr, double dSafeZ, double dElev, double dAppr) { if ( dSafeZ < m_Params.m_dStartPos + 10 * EPS_SMALL) { // 4 -> movimento di risalita sopra il punto finale SetFeed( GetEndFeed()) ; Point3d ptP4 = ptP + vtCorr * ( dElev + dAppr / vtCorr.z) ; 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 / vtCorr.z) ; if ( AddLinearMove( ptP4a) == GDB_ID_NULL) return false ; // 4b -> movimento di risalita sopra il punto finale Point3d ptP4b = ptP4a + Z_AX * ( dSafeZ - m_Params.m_dStartPos) ; if ( AddRapidMove( ptP4b) == GDB_ID_NULL) return false ; } return true ; } //---------------------------------------------------------------------------- bool Sawing::CalculateToolAndCorrVersors( const Vector3d& vtTang, int nHeadSide, int nWorkSide, double dSideAng, 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 ; // Se lama sbandata if ( abs( dSideAng) > EPS_ANG_SMALL) { if ( nWorkSide == SAW_WS_RIGHT) { vtTool.Rotate( vtTang, - dSideAng) ; vtCorr.Rotate( vtTang, - dSideAng) ; } else { vtTool.Rotate( vtTang, dSideAng) ; vtCorr.Rotate( vtTang, dSideAng) ; } } return true ; } //---------------------------------------------------------------------------- bool Sawing::AdjustForSide( ICurve* pCurve) { // se lato lavoro e lato mandrino coincidono, non devo fare alcunché if ( ( m_Params.m_nWorkSide == SAW_WS_LEFT && m_Params.m_nHeadSide == SAW_HS_LEFT) || ( m_Params.m_nWorkSide == SAW_WS_RIGHT && m_Params.m_nHeadSide == SAW_HS_RIGHT)) return true ; // calcolo offset curva double dOffs = 0 ; if ( m_Params.m_nWorkSide == SAW_WS_LEFT) dOffs = - m_TParams.m_dThick ; else if ( m_Params.m_nWorkSide == SAW_WS_RIGHT) dOffs = m_TParams.m_dThick ; else if ( m_Params.m_nHeadSide == SAW_HS_LEFT) // lama in centro dOffs = 0.5 * m_TParams.m_dThick ; else // testa a destra e lama in centro dOffs = - 0.5 * m_TParams.m_dThick ; // correzione per angolo di fianco if ( abs( m_Params.m_dSideAngle) > EPS_ANG_SMALL) dOffs /= cos( m_Params.m_dSideAngle * DEGTORAD) ; // eseguo offset curva ( nel piano XY globale) return pCurve->SimpleOffset( dOffs) ; } //---------------------------------------------------------------------------- bool Sawing::AdjustIntArcForSide( ICurve* pCurve, double dSideAng) { // calcolo offset curva double dOffs = 0 ; if ( m_Params.m_nWorkSide == SAW_WS_LEFT) dOffs = - m_TParams.m_dThick ; else dOffs = m_TParams.m_dThick ; // correzione per angolo di fianco if ( abs( dSideAng) > EPS_ANG_SMALL) dOffs *= cos( dSideAng * DEGTORAD) ; // eseguo offset curva ( nel piano XY globale) return pCurve->SimpleOffset( dOffs) ; } //---------------------------------------------------------------------------- bool Sawing::AdjustLineForEdges( ICurveLine* pLine, double dElev, const Vector3d& vtCorr, const Vector3d& vtThick, bool bIsFirst, bool bIsLast, bool bExtAngPC, bool bExtAngCN, double dLiElev, bool& bToSkip, double& dDeltaLiExt, double& dDeltaLoExt) { // distanza XY tra centro e bordo taglio double dDeltaT = (( dElev < 0.5 * m_TParams.m_dDiam) ? sqrt( dElev * m_TParams.m_dDiam - dElev * dElev) : 0) ; // lunghezza aggiuntiva per attacco speciale a zigzag double dDeltaLi = 0 ; if ( dLiElev > EPS_SMALL) dDeltaLi = m_Params.m_dLiTang + (( dLiElev < 0.5 * m_TParams.m_dDiam) ? sqrt( dLiElev * m_TParams.m_dDiam - dLiElev * dLiElev) : 0) ; // verifiche e aggiustamenti sull'inizio double dDeltaI = 0 ; dDeltaLiExt = 0 ; if ( ! bExtAngPC) dDeltaI = ( dDeltaLi < EPS_SMALL ? - dDeltaT : - dDeltaLi) ; else if ( bIsFirst) { if ( m_Params.m_nLeadInType == SAW_LI_STRICT) // all'interno dDeltaI = ( dDeltaLi < EPS_SMALL ? - dDeltaT : - dDeltaLi) ; else if ( m_Params.m_nLeadInType == SAW_LI_OUT) // all'esterno dDeltaI = dDeltaT ; else if ( m_Params.m_nLeadInType == SAW_LI_EXT_CENT || m_Params.m_nLeadInType == SAW_LI_EXT_OUT) { // porto il centro lama sul bordo del grezzo o all'esterno // calcolo punto di inizio e direzione (sono in globale) Point3d ptP ; pLine->GetStartPoint( ptP) ; Vector3d vtDir ; pLine->GetStartDir( vtDir) ; // determino la distanza dal bordo del grezzo double dDist[4] = {0, 0, 0, 0} ; if ( ! GetDistanceFromRawSide( m_nPhase, ptP, - vtDir, dDist[0]) || ! GetDistanceFromRawSide( m_nPhase, ptP + vtThick, - vtDir, dDist[1]) || ! GetDistanceFromRawSide( m_nPhase, ptP + vtCorr * dElev, - vtDir, dDist[2]) || ! GetDistanceFromRawSide( m_nPhase, ptP + vtCorr * dElev + vtThick, - vtDir, dDist[3])) return false ; dDeltaI = 0 ; for ( int i = 0 ; i < 4 ; ++i) dDeltaI = max( dDeltaI, dDist[i]) ; if ( m_Params.m_nLeadInType == SAW_LI_EXT_OUT) dDeltaI += dDeltaT ; dDeltaLiExt = dDeltaI ; } } else { if ( m_Params.m_nExtLinkType == SAW_EL_EXT_NEXT || m_Params.m_nExtLinkType == SAW_EL_EXT_BOTH) { // estendere al bordo del grezzo // calcolo punto di inizio e direzione (sono in globale) Point3d ptP ; pLine->GetStartPoint( ptP) ; Vector3d vtDir ; pLine->GetStartDir( vtDir) ; // determino la distanza dal bordo del grezzo double dDist[4] = {0, 0, 0, 0} ; if ( ! GetDistanceFromRawSide( m_nPhase, ptP, - vtDir, dDist[0]) || ! GetDistanceFromRawSide( m_nPhase, ptP + vtThick, - vtDir, dDist[1]) || ! GetDistanceFromRawSide( m_nPhase, ptP + vtCorr * dElev, - vtDir, dDist[2]) || ! GetDistanceFromRawSide( m_nPhase, ptP + vtCorr * dElev + vtThick, - vtDir, dDist[3])) return false ; dDeltaI = 0 ; for ( int i = 0 ; i < 4 ; ++i) dDeltaI = max( dDeltaI, dDist[i]) ; if ( m_Params.m_nLeadInType == SAW_LI_EXT_OUT) dDeltaI += dDeltaT ; dDeltaLiExt = dDeltaI ; } } // verifiche e aggiustamenti sulla fine double dDeltaF = 0 ; dDeltaLoExt = 0 ; if ( ! bExtAngCN) dDeltaF = - dDeltaT ; else if ( bIsLast) { if ( m_Params.m_nLeadOutType == SAW_LO_STRICT) // all'interno dDeltaF = - dDeltaT ; else if ( m_Params.m_nLeadOutType == SAW_LO_OUT) // all'esterno dDeltaF = dDeltaT ; else if ( m_Params.m_nLeadOutType == SAW_LO_EXT_CENT || m_Params.m_nLeadOutType == SAW_LO_EXT_OUT) { // estendo al bordo del grezzo o al suo esterno // calcolo punto di fine e direzione (sono in globale) Point3d ptP ; pLine->GetEndPoint( ptP) ; Vector3d vtDir ; pLine->GetEndDir( vtDir) ; // determino la distanza dal bordo del grezzo double dDist[4] = {0, 0, 0, 0} ; if ( ! GetDistanceFromRawSide( m_nPhase, ptP, vtDir, dDist[0]) || ! GetDistanceFromRawSide( m_nPhase, ptP + vtThick, vtDir, dDist[1]) || ! GetDistanceFromRawSide( m_nPhase, ptP + vtCorr * dElev, vtDir, dDist[2]) || ! GetDistanceFromRawSide( m_nPhase, ptP + vtCorr * dElev + vtThick, vtDir, dDist[3])) return false ; dDeltaF = 0 ; for ( int i = 0 ; i < 4 ; ++i) dDeltaF = max( dDeltaF, dDist[i]) ; if ( m_Params.m_nLeadOutType == SAW_LO_EXT_OUT) dDeltaF += dDeltaT ; dDeltaLoExt = dDeltaF ; } } else { if ( m_Params.m_nExtLinkType == SAW_EL_EXT_PREV || m_Params.m_nExtLinkType == SAW_EL_EXT_BOTH) { // estendo al bordo del grezzo // calcolo punto di fine e direzione (sono in globale) Point3d ptP ; pLine->GetEndPoint( ptP) ; Vector3d vtDir ; pLine->GetEndDir( vtDir) ; // determino la distanza dal bordo del grezzo double dDist[4] = {0, 0, 0, 0} ; if ( ! GetDistanceFromRawSide( m_nPhase, ptP, vtDir, dDist[0]) || ! GetDistanceFromRawSide( m_nPhase, ptP + vtThick, vtDir, dDist[1]) || ! GetDistanceFromRawSide( m_nPhase, ptP + vtCorr * dElev, vtDir, dDist[2]) || ! GetDistanceFromRawSide( m_nPhase, ptP + vtCorr * dElev + vtThick, vtDir, dDist[3])) return false ; dDeltaF = 0 ; for ( int i = 0 ; i < 4 ; ++i) dDeltaF = max( dDeltaF, dDist[i]) ; // se LeadOut EXT_OUT vado all'esterno if ( m_Params.m_nLeadOutType == SAW_LO_EXT_OUT) dDeltaF += dDeltaT ; dDeltaLoExt = dDeltaF ; } } // controllo se lunghezza entità accettabile const double MIN_LEN = 1 ; double dLenXY = DistXY( pLine->GetStart(), pLine->GetEnd()) ; if ( dDeltaI + dLenXY + dDeltaF < MIN_LEN) { bToSkip = true ; return true ; } bToSkip = false ; // modifico gli estremi : // eventuali allungamenti if ( dDeltaI > EPS_SMALL) { if ( ! pLine->ExtendStartByLen( dDeltaI)) return false ; dLenXY += dDeltaI ; } if ( dDeltaF > EPS_SMALL) { if ( ! pLine->ExtendEndByLen( dDeltaF)) return false ; dLenXY += dDeltaF ; } // eventuali accorciamenti (da fare dopo tutti gli allungamenti) if ( dDeltaI < - EPS_SMALL) { if ( ! pLine->TrimStartAtLen( - dDeltaI)) return false ; dLenXY += dDeltaI ; } if ( dDeltaF < - EPS_SMALL) { if ( ! pLine->TrimEndAtLen( dLenXY + dDeltaF)) return false ; dLenXY += dDeltaF ; } return true ; } //---------------------------------------------------------------------------- bool Sawing::AdjustCurveForEdges( ICurve* pCrv, double dElev, double dLenCoeff, bool bIsFirst, bool bIsLast, bool bExtAngPC, bool bExtAngCN, bool& bToSkip) { // --- gli archi non vanno estesi al bordo del grezzo --- // distanza XY tra centro e bordo taglio double dDeltaT = (( dElev < 0.5 * m_TParams.m_dDiam) ? sqrt( dElev * m_TParams.m_dDiam - dElev * dElev) : 0) ; // verifiche e aggiustamenti sull'inizio double dDeltaI = 0 ; if ( ! bExtAngPC) dDeltaI = - dDeltaT ; else if ( bIsFirst) { if ( m_Params.m_nLeadInType == SAW_LI_STRICT) // all'interno dDeltaI = - dDeltaT ; else if ( m_Params.m_nLeadInType == SAW_LI_OUT || m_Params.m_nLeadInType == SAW_LI_EXT_OUT) // all'esterno dDeltaI = dDeltaT ; } dDeltaI *= dLenCoeff ; // verifiche e aggiustamenti sulla fine double dDeltaF = 0 ; if ( ! bExtAngCN) dDeltaF = - dDeltaT ; else if ( bIsLast) { if ( m_Params.m_nLeadOutType == SAW_LO_STRICT) // all'interno dDeltaF = - dDeltaT ; else if ( m_Params.m_nLeadOutType == SAW_LO_OUT || m_Params.m_nLeadOutType == SAW_LO_EXT_OUT) // all'esterno dDeltaF = dDeltaT ; } dDeltaF *= dLenCoeff ; // controllo se lunghezza entità accettabile const double MIN_LEN = 1 ; double dLenXY ; pCrv->GetLength( dLenXY) ; if ( dDeltaI + dLenXY + dDeltaF < MIN_LEN) { bToSkip = true ; return true ; } bToSkip = false ; // modifico gli estremi // eventuali allungamenti if ( dDeltaI > EPS_SMALL) { if ( ! pCrv->ExtendStartByLen( dDeltaI)) return false ; dLenXY += dDeltaI ; } if ( dDeltaF > EPS_SMALL) { if ( ! pCrv->ExtendEndByLen( dDeltaF)) return false ; dLenXY += dDeltaF ; } // eventuali accorciamenti (da fare dopo tutti gli allungamenti) if ( dDeltaI < - EPS_SMALL) { if ( ! pCrv->TrimStartAtLen( - dDeltaI)) return false ; dLenXY += dDeltaI ; } if ( dDeltaF < - EPS_SMALL) { if ( ! pCrv->TrimEndAtLen( dLenXY + dDeltaF)) return false ; dLenXY += dDeltaF ; } return true ; } //---------------------------------------------------------------------------- bool Sawing::AreHeadWorkOnSameSide( void) const { return ( ( m_Params.m_nWorkSide == SAW_WS_LEFT && m_Params.m_nHeadSide == SAW_HS_LEFT) || ( m_Params.m_nWorkSide == SAW_WS_RIGHT && m_Params.m_nHeadSide == SAW_HS_RIGHT)) ; }