//---------------------------------------------------------------------------- // EgalTech 2015-2021 //---------------------------------------------------------------------------- // File : Machine.cpp Data : 14.10.21 Versione : 2.3j5 // Contenuto : Implementazione gestione macchina. // // // // Modifiche : 06.05.15 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "MachMgr.h" #include "DllMain.h" #include "Table.h" #include "Axis.h" #include "Head.h" #include "TcPos.h" #include "Exit.h" #include "/EgtDev/Include/EGkGeomDB.h" #include "/EgtDev/Include/EGkGeoVector3d.h" #include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EGnFileUtils.h" #include "/EgtDev/Include/EgtPointerOwner.h" #include using namespace std ; //---------------------------------------------------------------------------- Machine::Machine( void) { m_pMchMgr = nullptr ; m_pGeomDB = nullptr ; m_nContextId = 0 ; m_nGroupId = GDB_ID_NULL ; m_nTempGroupId = GDB_ID_NULL ; m_dAxisMaxAdjust = EPS_SMALL ; m_dAxisMaxRotAdj = 10 * EPS_ANG_SMALL ; m_dExitMaxAdjust = EPS_SMALL ; m_dExitMaxRotAdj = 10 * EPS_ANG_SMALL ; m_dAngDeltaMinForHome = INFINITO ; m_nMultiProcess = 0 ; m_nLinkAxesMoveOrder = 0 ; m_nNewLinkMgr = 0 ; m_nCalcTabId = GDB_ID_NULL ; m_nCalcHeadId = GDB_ID_NULL ; m_nCalcExitId = GDB_ID_NULL ; m_nCalcToolId = GDB_ID_NULL ; m_dCalcRot1W = ROT1_WEIGHT_DFLT ; m_dSingConeAng = SING_CONE_ANG_DFLT ; m_bCalcMaxDeltaR2On1 = true ; m_nCalcSolCh = MCH_SCC_NONE ; m_bSolChExact = false ; m_dCalcTLen = 0 ; m_dCalcTRad = 0 ; m_dCalcTOvLen = 0 ; m_dCalcTOvRad = 0 ; m_nTabLinAxes = 0 ; m_nTabRotAxes = 0 ; m_nHeadLinAxes = 0 ; m_nHeadRotAxes = 0 ; m_nHeadSpecRotAxis = -1 ; m_frLinAx.Reset( false) ; m_frRobot.Reset( false) ; m_nCalcChainType = KIN_CHAIN_NONE ; m_dPrevAngA = NAN ; m_nMachineLook = MCH_LOOK_NONE ; } //---------------------------------------------------------------------------- Machine::~Machine( void) { Clear() ; } //---------------------------------------------------------------------------- void Machine::Clear( void) { // cancellazione eventuali gruppi geometrici associati if ( m_pGeomDB != nullptr) { if ( m_nGroupId != GDB_ID_NULL) m_pGeomDB->Erase( m_nGroupId) ; if ( m_nTempGroupId != GDB_ID_NULL) m_pGeomDB->Erase( m_nTempGroupId) ; } // pulizia interprete lua di macchina LuaExit() ; // reset membri m_pMchMgr = nullptr ; m_pGeomDB = nullptr ; m_nContextId = 0 ; m_sName.clear() ; m_sMachineDir.clear() ; m_nGroupId = GDB_ID_NULL ; m_nTempGroupId = GDB_ID_NULL ; m_mapGroups.clear() ; m_mapGroups.rehash( 20) ; } //---------------------------------------------------------------------------- bool Machine::Init( const string& sMachineName, const string& sMachineDir, MachMgr* pMchMgr) { // pulisco Clear() ; // verifico ambiente if ( pMchMgr == nullptr || pMchMgr->GetContextId() == 0 || pMchMgr->GetGeomDB() == nullptr) return false ; m_pMchMgr = pMchMgr ; m_pGeomDB = m_pMchMgr->GetGeomDB() ; m_nContextId = m_pMchMgr->GetContextId() ; // verifico direttorio dati macchina m_sMachineDir = sMachineDir ; if ( ! ExistsDirectory( m_sMachineDir)) return false ; // creo il gruppo per la macchina int nId = m_pGeomDB->InsertGroup( GDB_ID_NULL, pMchMgr->GetMachAuxId(), GDB_LAST_SON, GLOB_FRM) ; if ( nId == GDB_ID_NULL) return false ; // imposto nome del gruppo m_pGeomDB->SetName( nId, sMachineName) ; // carico l'interprete lua dedicato alla macchina if ( ! LuaInit( sMachineName)) { m_pGeomDB->Erase( nId) ; return false ; } // salvo i dati m_nGroupId = nId ; m_sName = sMachineName ; // carico la macchina { string sMachineMlde = m_sMachineDir + "\\" + sMachineName + ".Mlde" ; if ( ! ExistsFile( sMachineMlde)) sMachineMlde = m_sMachineDir + "\\" + sMachineName + ".Mde" ; bool bOk = LuaLoadMachine( sMachineMlde) ; // cancello il gruppo temporaneo m_pGeomDB->Erase( m_nTempGroupId) ; m_nTempGroupId = GDB_ID_NULL ; // in caso di errore, cancello tutta la geometria if ( ! bOk) { m_pGeomDB->Erase( m_nGroupId) ; m_nGroupId = GDB_ID_NULL ; m_sName.clear() ; m_sMachineDir.clear() ; } // imposto stato di visualizzazione m_nMachineLook = ( bOk ? MCH_LOOK_ALL : MCH_LOOK_NONE) ; // metto tutti gli assi in posizione home bOk = bOk && ResetAllAxesPos( true, true) ; // reset catena cinematica corrente m_nCalcChainType = KIN_CHAIN_NONE ; return bOk ; } //---------------------------------------------------------------------------- bool Machine::LoadMachineGeometry( const string& sMGeoName, const Vector3d& vtOffset) { // creo un sotto gruppo temporaneo in cui caricare la macchina m_nTempGroupId = m_pGeomDB->AddGroup( GDB_ID_NULL, m_pMchMgr->GetMachAuxId(), GLOB_FRM) ; if ( m_nTempGroupId == GDB_ID_NULL) return false ; // carico la macchina string sMachineNge = m_sMachineDir + "\\" + sMGeoName ; if ( ! m_pGeomDB->Load( sMachineNge, m_nTempGroupId)) return false ; // applico offset return m_pGeomDB->TranslateGlob( m_nTempGroupId, vtOffset) ; } //---------------------------------------------------------------------------- bool Machine::LoadMachineBase( const string& sName, const string& sGeo, const STRVECTOR& vsAux) { // recupero pezzo e layer della geometria originale della base string sPart, sLay ; Split( sGeo, "/", true, sPart, sLay) ; // cerco il gruppo nella geometria originale int nPart = m_pGeomDB->GetFirstNameInGroup( m_nTempGroupId, sPart) ; int nLay = m_pGeomDB->GetFirstNameInGroup( nPart, sLay) ; if ( nLay == GDB_ID_NULL) return false ; // lo sposto nella radice della macchina if ( ! m_pGeomDB->RelocateGlob( nLay, m_nGroupId, GDB_LAST_SON)) return false ; // gli assegno il nome m_pGeomDB->SetName( nLay, sName) ; // sistemo la geometria ausiliaria if ( ! AdjustAuxGeometry( vsAux, nLay)) return false ; // lo inserisco nel dizionario dei gruppi della macchina return m_mapGroups.emplace( sName, nLay).second ; } //---------------------------------------------------------------------------- bool Machine::AdjustAuxGeometry( const STRVECTOR& vsAux, int nLay) { // sistemo la geometria ausiliaria for ( const auto& sAux : vsAux) { // recupero pezzo e layer della geometria ausiliaria string sAuxPart, sAuxLay ; Split( sAux, "/", true, sAuxPart, sAuxLay) ; // cerco il gruppo nella geometria originale int nAuxPart = m_pGeomDB->GetFirstNameInGroup( m_nTempGroupId, sAuxPart) ; int nAuxLay = m_pGeomDB->GetFirstNameInGroup( nAuxPart, sAuxLay) ; if ( nAuxLay == GDB_ID_NULL) return false ; // lo sposto nel gruppo if ( ! m_pGeomDB->RelocateGlob( nAuxLay, nLay, GDB_LAST_SON)) return false ; } return true ; } //---------------------------------------------------------------------------- bool Machine::LoadMachineTable( const string& sName, const string& sParent, int nType, const Point3d& ptRef1, double dCoeffX, double dCoeffY, double dCoeffZ, const STRVECTOR& vsColl, const string& sGeo, const STRVECTOR& vsAux) { // recupero pezzo e layer della geometria originale della tavola string sPart, sLay ; Split( sGeo, "/", true, sPart, sLay) ; // cerco il gruppo nella geometria originale int nPart = m_pGeomDB->GetFirstNameInGroup( m_nTempGroupId, sPart) ; int nLay = m_pGeomDB->GetFirstNameInGroup( nPart, sLay) ; if ( nLay == GDB_ID_NULL) return false ; // cerco il gruppo padre per spostarvelo int nParentId = GetGroup( sParent) ; if ( nParentId == GDB_ID_NULL || ! m_pGeomDB->RelocateGlob( nLay, nParentId, GDB_LAST_SON)) return false ; // gli assegno il nome m_pGeomDB->SetName( nLay, sName) ; // sistemo la geometria ausiliaria if ( ! AdjustAuxGeometry( vsAux, nLay)) return false ; // aggiusto la posizione della tavola if ( ! AdjustTable( nLay, ptRef1)) return false ; // eseguo eventuale scalatura if ( abs( dCoeffX - 1.0) > EPS_ZERO || abs( dCoeffY - 1.0) > EPS_ZERO || abs( dCoeffZ - 1.0) > EPS_ZERO) { if ( ! m_pGeomDB->ScaleGlob( nLay, Frame3d( ptRef1), dCoeffX, dCoeffY, dCoeffZ)) return false ; } // recupero l'area valida int nAreaId = m_pGeomDB->GetFirstNameInGroup( nLay, MCH_TAREA + "1") ; BBox3d b3Area1 ; if ( ! m_pGeomDB->GetGlobalBBox( nAreaId, b3Area1)) return false ; // installo e inizializzo il gestore della tavola Table* pTab = new(nothrow) Table ; if ( pTab == nullptr) return false ; pTab->Set( sName, nType, ptRef1, b3Area1, vsColl) ; m_pGeomDB->SetUserObj( nLay, pTab) ; // lo inserisco nel dizionario dei gruppi della macchina return m_mapGroups.emplace( sName, nLay).second ; } //---------------------------------------------------------------------------- bool Machine::AdjustTable( int nLay, const Point3d& ptRef1) { // riferimento globale del gruppo tavola Frame3d frTable ; m_pGeomDB->GetGroupGlobFrame( nLay, frTable) ; // recupero il primo riferimento della tavola int nRef1 = m_pGeomDB->GetFirstNameInGroup( nLay, MCH_TREF + "1") ; if ( nRef1 == GDB_ID_NULL || m_pGeomDB->GetGeoType( nRef1) != GEO_FRAME3D) { string sOut = " Missing " + MCH_TREF + "1" ; LOG_ERROR( GetEMkLogger(), sOut.c_str()) ; return false ; } // recupero frame const Frame3d& frFrame = GetGeoFrame3d( m_pGeomDB->GetGeoObj( nRef1))->GetFrame() ; // ne calcolo l'origine in globale Point3d ptPos = frFrame.Orig() ; ptPos.ToGlob( frTable) ; // verifico eventuale aggiustamento di posizione Vector3d vtMove = ptRef1 - ptPos ; if ( ! vtMove.IsSmall()) { string sOut = " Move = (" + ToString( vtMove) + ")" ; LOG_DBG_INFO( GetEMkLogger(), sOut.c_str()) ; return m_pGeomDB->TranslateGlob( nLay, vtMove) ; } else return true ; } //---------------------------------------------------------------------------- bool Machine::LoadMachineAxis( const string& sName, const string& sParent, const string& sToken, bool bInvert, double dOffset, int nType, int nUse, const Point3d& ptPos, const Vector3d& vtDir, const STROKE& Stroke, double dHome, bool bAdjustAux, const string& sGeo, const STRVECTOR& vsAux) { // verifico sia di tipo ammesso if ( nType != MCH_AT_LINEAR && nType != MCH_AT_ROTARY) { LOG_ERROR( GetEMkLogger(), " Wrong Axis Type") ; return false ; } // recupero pezzo e layer della geometria originale dell'asse string sPart, sLay ; Split( sGeo, "/", true, sPart, sLay) ; // cerco il gruppo nella geometria originale int nPart = m_pGeomDB->GetFirstNameInGroup( m_nTempGroupId, sPart) ; int nLay = m_pGeomDB->GetFirstNameInGroup( nPart, sLay) ; if ( nLay == GDB_ID_NULL) { string sOut = " Missing Axis Part " + sPart ; LOG_ERROR( GetEMkLogger(), sOut.c_str()) ; return false ; } // cerco il gruppo padre per spostarvelo int nParentId = GetGroup( sParent) ; if ( nParentId == GDB_ID_NULL || ! m_pGeomDB->RelocateGlob( nLay, nParentId, GDB_LAST_SON)) { string sOut = " Missing Parent Group " + sParent ; LOG_ERROR( GetEMkLogger(), sOut.c_str()) ; return false ; } // verifico che il valore di home sia nei limiti di corsa if ( dHome < Stroke.Min || dHome > Stroke.Max) { LOG_ERROR( GetEMkLogger(), " Home Position Out of stroke") ; return false ; } // gli assegno il nome m_pGeomDB->SetName( nLay, sName) ; // sistemo la geometria ausiliaria if ( ! AdjustAuxGeometry( vsAux, nLay)) return false ; // installo e inizializzo il gestore dell'asse Axis* pAxis = new(nothrow) Axis ; if ( pAxis == nullptr) return false ; pAxis->Set( sName, sToken, bInvert, dOffset, nType, nUse, ptPos, vtDir, Stroke, dHome) ; m_pGeomDB->SetUserObj( nLay, pAxis) ; // verifico il vettore rappresentativo dell'asse if ( ! AdjustAxis( nLay, sPart, sName, nType, ptPos, vtDir, bAdjustAux)) return false ; // lo inserisco nel dizionario dei gruppi della macchina return m_mapGroups.emplace( sName, nLay).second ; } //---------------------------------------------------------------------------- bool Machine::AdjustAxis( int nLay, const string& sPart, const string& sName, int nType, const Point3d& ptPos, const Vector3d& vtDir, bool bAdjustAux) { // verifico presenza vettore asse int nId = m_pGeomDB->GetFirstNameInGroup( nLay, sPart) ; if ( nId == GDB_ID_NULL || m_pGeomDB->GetGeoType( nId) != GEO_VECT3D) { string sOut = " Missing Axis Vector " + sPart ; LOG_ERROR( GetEMkLogger(), sOut.c_str()) ; return false ; } // lo sposto all'inizio del suo gruppo if ( ! m_pGeomDB->Relocate( nId, nLay, GDB_FIRST_SON)) return false ; // lo rinomino come l'asse if ( ! m_pGeomDB->SetName( nId, sName)) return false ; // lo nascondo if ( ! m_pGeomDB->SetMode( nId, GDB_MD_HIDDEN)) return false ; // riferimento globale del gruppo asse Frame3d frFrame ; m_pGeomDB->GetGroupGlobFrame( nLay, frFrame) ; // recupero punto base e vettore direzione IGeoVector3d* pGeoVct = GetGeoVector3d( m_pGeomDB->GetGeoObj( nId)) ; Point3d ptBase = pGeoVct->GetBase() ; Vector3d vtAxis = pGeoVct->GetVector() ; vtAxis.Normalize() ; // riassegno il vettore normalizzato pGeoVct->ChangeVector( vtAxis) ; // li porto in globale ptBase.ToGlob( frFrame) ; vtAxis.ToGlob( frFrame) ; // se asse lineare devo verificarne solo la direzione if ( nType == MCH_AT_LINEAR) { Vector3d vtDirN = vtDir ; if ( ! vtDirN.Normalize() || ! AreSameVectorApprox( vtAxis, vtDirN)) { string sOut = " Wrong Axis Vector or Dir " + sPart ; LOG_ERROR( GetEMkLogger(), sOut.c_str()) ; return false ; } } // altrimenti asse rotante, devo verificarne direzione e coassialitā (questa solo se non abilitato movimento) else { Vector3d vtDirN = vtDir ; if ( ! vtDirN.Normalize() || ! AreSameVectorEpsilon( vtAxis, vtDirN, 10 * SIN_EPS_ANG_SMALL)) { double dAngRot ; if ( ! vtAxis.GetAngle( vtDirN, dAngRot) || abs( dAngRot) > m_dAxisMaxRotAdj) { string sOut = " Wrong Axis Vector or Dir " + sPart ; LOG_ERROR( GetEMkLogger(), sOut.c_str()) ; return false ; } else { Vector3d vtRotAx = vtAxis ^ vtDirN ; vtRotAx.Normalize() ; string sOut = " Axis " + sName + " rotation = (" + ToString( dAngRot) + "/" + ToString( vtRotAx) + ")" ; LOG_DBG_INFO( GetEMkLogger(), sOut.c_str()) ; m_pGeomDB->RotateGlob( nId, ptBase, vtRotAx, dAngRot) ; } } Vector3d vtDelta = ptPos - ptBase ; Vector3d vtDeltaPerp = vtDelta - ( vtDelta * vtDirN) * vtDirN ; if ( ! vtDeltaPerp.IsSmall()) { if ( vtDeltaPerp.Len() > m_dAxisMaxAdjust && ! bAdjustAux) { string sOut = " Wrong Axis Base move = (" + ToString( vtDeltaPerp) + ")" ; LOG_ERROR( GetEMkLogger(), sOut.c_str()) ; return false ; } else { string sOut = " Axis " + sName + " move = (" + ToString( vtDelta) + ")" ; LOG_DBG_INFO( GetEMkLogger(), sOut.c_str()) ; m_pGeomDB->TranslateGlob( nId, vtDelta) ; } } } // se richiesto, muovo la geometria ausiliaria if ( bAdjustAux) { Vector3d vtDelta = ptPos - ptBase ; int nIdAux = m_pGeomDB->GetFirstInGroup( nLay) ; while ( nIdAux != GDB_ID_NULL) { if ( nIdAux != nId) m_pGeomDB->TranslateGlob( nIdAux, vtDelta) ; nIdAux = m_pGeomDB->GetNext( nIdAux) ; } } return true ; } //---------------------------------------------------------------------------- bool Machine::ModifyMachineAxisPosition( const string& sName, const Point3d& ptPos) { // controllo GeomDB if ( m_pGeomDB == nullptr) return false ; // recupero il gruppo dell'asse int nAxGrp = GetGroup( sName) ; // recupero il relativo gestore Axis* pAx = GetAxis( nAxGrp) ; if ( pAx == nullptr) return false ; // se valore dell'asse non nullo, lo annullo double dCurrVal = pAx->GetCurrVal() ; if ( abs( dCurrVal) > EPS_ZERO) SetAxisPos( sName, 0, false) ; // eseguo la modifica bool bOk = pAx->Modify( ptPos, m_dAxisMaxAdjust) ; // ripristino l'asse al valore corrente if ( abs( dCurrVal) > EPS_ZERO) SetAxisPos( sName, dCurrVal, false) ; return bOk ; } //---------------------------------------------------------------------------- bool Machine::ModifyMachineAxisDirection( const string& sName, const Vector3d& vtDir) { // controllo GeomDB if ( m_pGeomDB == nullptr) return false ; // recupero il gruppo dell'asse int nAxGrp = GetGroup( sName) ; // recupero il relativo gestore Axis* pAx = GetAxis( nAxGrp) ; if ( pAx == nullptr) return false ; // se valore dell'asse non nullo, lo annullo double dCurrVal = pAx->GetCurrVal() ; if ( abs( dCurrVal) > EPS_ZERO) SetAxisPos( sName, 0, false) ; // eseguo la modifica bool bOk = pAx->Modify( vtDir, m_dAxisMaxRotAdj) ; // ripristino l'asse al valore corrente if ( abs( dCurrVal) > EPS_ZERO) SetAxisPos( sName, dCurrVal, false) ; return bOk ; } //---------------------------------------------------------------------------- bool Machine::ModifyMachineAxisStroke( const string& sName, const STROKE& Stroke) { // controllo GeomDB if ( m_pGeomDB == nullptr) return false ; // recupero il gruppo dell'asse int nAxGrp = GetGroup( sName) ; // recupero il relativo gestore Axis* pAx = GetAxis( nAxGrp) ; if ( pAx == nullptr) return false ; // eseguo la modifica return pAx->Modify( Stroke) ; } //---------------------------------------------------------------------------- bool Machine::ModifyMachineAxisHome( const string& sName, double dHome) { // controllo GeomDB if ( m_pGeomDB == nullptr) return false ; // recupero il gruppo dell'asse int nAxGrp = GetGroup( sName) ; // recupero il relativo gestore Axis* pAx = GetAxis( nAxGrp) ; if ( pAx == nullptr) return false ; // eseguo la modifica return pAx->Modify( dHome) ; } //---------------------------------------------------------------------------- bool Machine::LoadMachineStdHead( const string& sName, const string& sParent, const string& sHSet, const Point3d& ptPos, const Vector3d& vtTDir, const Vector3d& vtADir, double dRot1W, bool bMaxDeltaR2On1, const STROKE& Rot2Stroke, int nSolCh, const STRVECTOR& vsOthColl, const string& sGeo, const STRVECTOR& vsAux) { // recupero pezzo e layer della geometria originale della testa string sPart, sLay ; Split( sGeo, "/", true, sPart, sLay) ; // cerco il gruppo nella geometria originale int nPart = m_pGeomDB->GetFirstNameInGroup( m_nTempGroupId, sPart) ; int nLay = m_pGeomDB->GetFirstNameInGroup( nPart, sLay) ; if ( nLay == GDB_ID_NULL) return false ; // cerco il gruppo padre per spostarvelo int nParentId = GetGroup( sParent) ; if ( nParentId == GDB_ID_NULL || ! m_pGeomDB->RelocateGlob( nLay, nParentId, GDB_LAST_SON)) return false ; // sistemo lo stato di visualizzazione bool bShow = ( sHSet == sName) ; m_pGeomDB->SetStatus( nLay, ( bShow ? GDB_ST_ON : GDB_ST_OFF)) ; // gli assegno il nome m_pGeomDB->SetName( nLay, sName) ; // sistemo la geometria ausiliaria if ( ! AdjustAuxGeometry( vsAux, nLay)) return false ; // installo e inizializzo il gestore della testa Head* pHead = new(nothrow) Head ; if ( pHead == nullptr) return false ; pHead->Set( sName, MCH_HT_STD, 1, sHSet, 0, vtADir, dRot1W, bMaxDeltaR2On1, Rot2Stroke, nSolCh, vsOthColl) ; m_pGeomDB->SetUserObj( nLay, pHead) ; // aggiorno la testa capostipite if ( ! AddHeadToSet( sHSet, sName)) return false ; // sistemo il riferimento dell'uscita rispetto alla direzione ausiliaria MUEXITVECTOR vMuExit ; vMuExit.emplace_back( ptPos, vtTDir) ; if ( ! AdjustExitFrames( nLay, vMuExit, vtADir)) return false ; // trasformazione del riferimento di uscita in gruppo di uscita if ( ! CreateExitGroups( nLay, vMuExit)) return false ; // lo inserisco nel dizionario dei gruppi della macchina return m_mapGroups.emplace( sName, nLay).second ; } //---------------------------------------------------------------------------- bool Machine::LoadMachineMultiHead( const string& sName, const string& sParent, const string& sHSet, int nSelectType, const MUEXITVECTOR& vMuExit, const Vector3d& vtADir, double dRot1W, bool bMaxDeltaR2On1, const STROKE& Rot2Stroke, int nSolCh, const STRVECTOR& vsOthColl, const string& sGeo, const STRVECTOR& vsAux) { // recupero pezzo e layer della geometria originale della testa string sPart, sLay ; Split( sGeo, "/", true, sPart, sLay) ; // cerco il gruppo nella geometria originale int nPart = m_pGeomDB->GetFirstNameInGroup( m_nTempGroupId, sPart) ; int nLay = m_pGeomDB->GetFirstNameInGroup( nPart, sLay) ; if ( nLay == GDB_ID_NULL) return false ; // cerco il gruppo padre per spostarvelo int nParentId = GetGroup( sParent) ; if ( nParentId == GDB_ID_NULL || ! m_pGeomDB->RelocateGlob( nLay, nParentId, GDB_LAST_SON)) return false ; // sistemo lo stato di visualizzazione bool bShow = ( sHSet == sName) ; m_pGeomDB->SetStatus( nLay, ( bShow ? GDB_ST_ON : GDB_ST_OFF)) ; // gli assegno il nome m_pGeomDB->SetName( nLay, sName) ; // sistemo la geometria ausiliaria if ( ! AdjustAuxGeometry( vsAux, nLay)) return false ; // installo e inizializzo il gestore della testa Head* pHead = new(nothrow) Head ; if ( pHead == nullptr) return false ; pHead->Set( sName, MCH_HT_MULTI, int( vMuExit.size()), sHSet, nSelectType, vtADir, dRot1W, bMaxDeltaR2On1, Rot2Stroke, nSolCh, vsOthColl) ; m_pGeomDB->SetUserObj( nLay, pHead) ; // aggiorno la testa capostipite if ( ! AddHeadToSet( sHSet, sName)) return false ; // sistemo i riferimenti delle uscite rispetto alla direzione ausiliaria if ( ! AdjustExitFrames( nLay, vMuExit, vtADir)) return false ; // trasformazione dei riferimenti di uscita in gruppi di uscita if ( ! CreateExitGroups( nLay, vMuExit)) return false ; // lo inserisco nel dizionario dei gruppi della macchina return m_mapGroups.emplace( sName, nLay).second ; } //---------------------------------------------------------------------------- bool Machine::LoadMachineSpecialHead( const string& sName, const string& sParent, const string& sHSet, const Point3d& ptPos, const Vector3d& vtTDir, const Vector3d& vtADir, double dRot1W, bool bMaxDeltaR2On1, const STROKE& Rot2Stroke, int nSolCh, const STRVECTOR& vsOthColl, const string& sGeo, const STRVECTOR& vsAux) { // recupero pezzo e layer della geometria originale della testa string sPart, sLay ; Split( sGeo, "/", true, sPart, sLay) ; // cerco il gruppo nella geometria originale int nPart = m_pGeomDB->GetFirstNameInGroup( m_nTempGroupId, sPart) ; int nLay = m_pGeomDB->GetFirstNameInGroup( nPart, sLay) ; if ( nLay == GDB_ID_NULL) return false ; // cerco il gruppo padre per spostarvelo int nParentId = GetGroup( sParent) ; if ( nParentId == GDB_ID_NULL || ! m_pGeomDB->RelocateGlob( nLay, nParentId, GDB_LAST_SON)) return false ; // sistemo lo stato di visualizzazione bool bShow = ( sHSet == sName) ; m_pGeomDB->SetStatus( nLay, ( bShow ? GDB_ST_ON : GDB_ST_OFF)) ; // gli assegno il nome m_pGeomDB->SetName( nLay, sName) ; // sistemo la geometria ausiliaria if ( ! AdjustAuxGeometry( vsAux, nLay)) return false ; // installo e inizializzo il gestore della testa Head* pHead = new(nothrow) Head ; if ( pHead == nullptr) return false ; pHead->Set( sName, MCH_HT_SPECIAL, 1, sHSet, 0, vtADir, dRot1W, bMaxDeltaR2On1, Rot2Stroke, nSolCh, vsOthColl) ; m_pGeomDB->SetUserObj( nLay, pHead) ; // aggiorno la testa capostipite if ( ! AddHeadToSet( sHSet, sName)) return false ; // sistemo il riferimento dell'uscita rispetto alla direzione ausiliaria MUEXITVECTOR vMuExit ; vMuExit.emplace_back( ptPos, vtTDir) ; if ( ! AdjustExitFrames( nLay, vMuExit, vtADir)) return false ; // trasformazione del riferimento di uscita in gruppo di uscita if ( ! CreateExitGroups( nLay, vMuExit)) return false ; // lo inserisco nel dizionario dei gruppi della macchina return m_mapGroups.emplace( sName, nLay).second ; } //---------------------------------------------------------------------------- bool Machine::LoadMachineStdTcPos( const string& sName, const string& sParent, const Point3d& ptPos, const Vector3d& vtTDir, const Vector3d& vtADir, const string& sGeo, const STRVECTOR& vsAux) { // recupero pezzo e layer della geometria originale della posizione nel cambio utensile string sPart, sLay ; Split( sGeo, "/", true, sPart, sLay) ; // cerco il gruppo nella geometria originale int nPart = m_pGeomDB->GetFirstNameInGroup( m_nTempGroupId, sPart) ; int nLay = m_pGeomDB->GetFirstNameInGroup( nPart, sLay) ; if ( nLay == GDB_ID_NULL) return false ; // cerco il gruppo padre per spostarvelo int nParentId = GetGroup( sParent) ; if ( nParentId == GDB_ID_NULL || ! m_pGeomDB->RelocateGlob( nLay, nParentId, GDB_LAST_SON)) return false ; // sistemo lo stato di visualizzazione m_pGeomDB->SetStatus( nLay, GDB_ST_ON) ; // gli assegno il nome m_pGeomDB->SetName( nLay, sName) ; // sistemo la geometria ausiliaria if ( ! AdjustAuxGeometry( vsAux, nLay)) return false ; // installo e inizializzo il gestore della posizione nel cambio utensile TcPos* pTcPos = new(nothrow) TcPos ; if ( pTcPos == nullptr) return false ; pTcPos->Set( sName, vtADir) ; m_pGeomDB->SetUserObj( nLay, pTcPos) ; // sistemo il riferimento dell'uscita rispetto alla direzione ausiliaria MUEXITVECTOR vMuExit ; vMuExit.emplace_back( ptPos, vtTDir) ; if ( ! AdjustExitFrames( nLay, vMuExit, vtADir)) return false ; // trasformazione del riferimento di uscita in gruppo di uscita if ( ! CreateExitGroups( nLay, vMuExit)) return false ; // lo inserisco nel dizionario dei gruppi della macchina return m_mapGroups.emplace( sName, nLay).second ; } //---------------------------------------------------------------------------- bool Machine::LoadMachineMultiTcPos( const string& sName, const string& sParent, const MUEXITVECTOR& vMuExit, const Vector3d& vtADir, const string& sGeo, const STRVECTOR& vsAux) { // recupero pezzo e layer della geometria originale della posizione nel cambio utensile string sPart, sLay ; Split( sGeo, "/", true, sPart, sLay) ; // cerco il gruppo nella geometria originale int nPart = m_pGeomDB->GetFirstNameInGroup( m_nTempGroupId, sPart) ; int nLay = m_pGeomDB->GetFirstNameInGroup( nPart, sLay) ; if ( nLay == GDB_ID_NULL) return false ; // cerco il gruppo padre per spostarvelo int nParentId = GetGroup( sParent) ; if ( nParentId == GDB_ID_NULL || ! m_pGeomDB->RelocateGlob( nLay, nParentId, GDB_LAST_SON)) return false ; // sistemo lo stato di visualizzazione m_pGeomDB->SetStatus( nLay, GDB_ST_ON) ; // gli assegno il nome m_pGeomDB->SetName( nLay, sName) ; // sistemo la geometria ausiliaria if ( ! AdjustAuxGeometry( vsAux, nLay)) return false ; // installo e inizializzo il gestore della posizione nel cambio utensile TcPos* pTcPos = new(nothrow) TcPos ; if ( pTcPos == nullptr) return false ; pTcPos->Set( sName, vtADir) ; m_pGeomDB->SetUserObj( nLay, pTcPos) ; // sistemo il riferimento dell'uscita rispetto alla direzione ausiliaria if ( ! AdjustExitFrames( nLay, vMuExit, vtADir)) return false ; // trasformazione del riferimento di uscita in gruppo di uscita if ( ! CreateExitGroups( nLay, vMuExit)) return false ; // lo inserisco nel dizionario dei gruppi della macchina return m_mapGroups.emplace( sName, nLay).second ; } //---------------------------------------------------------------------------- int Machine::GetGroup( const string& sGroup) const { STRINT_UMAP::const_iterator Iter = m_mapGroups.find( sGroup) ; return (( Iter != m_mapGroups.end()) ? Iter->second : GDB_ID_NULL) ; } //---------------------------------------------------------------------------- bool Machine::IsBaseGroup( int nGroup) const { if ( m_pGeomDB == nullptr) return false ; // deve essere nel primo gruppo della macchina return ( m_pGeomDB->GetParentId( nGroup) == m_nGroupId) ; } //---------------------------------------------------------------------------- Table* Machine::GetTable( int nGroup) const { return ( dynamic_cast( m_pGeomDB->GetUserObj( nGroup))) ; } //---------------------------------------------------------------------------- Axis* Machine::GetAxis( int nGroup) const { return ( dynamic_cast( m_pGeomDB->GetUserObj( nGroup))) ; } //---------------------------------------------------------------------------- bool Machine::IsLinearAxisGroup( int nGroup) const { Axis* pAx = GetAxis( nGroup) ; return ( pAx != nullptr && pAx->GetType() == MCH_AT_LINEAR) ; } //---------------------------------------------------------------------------- bool Machine::IsRotaryAxisGroup( int nGroup) const { Axis* pAx = GetAxis( nGroup) ; return ( pAx != nullptr && pAx->GetType() == MCH_AT_ROTARY) ; } //---------------------------------------------------------------------------- Head* Machine::GetHead( int nGroup) const { return ( dynamic_cast( m_pGeomDB->GetUserObj( nGroup))) ; } //---------------------------------------------------------------------------- TcPos* Machine::GetTcPos( int nGroup) const { return ( dynamic_cast( m_pGeomDB->GetUserObj( nGroup))) ; } //---------------------------------------------------------------------------- Exit* Machine::GetExit( int nGroup) const { return ( dynamic_cast( m_pGeomDB->GetUserObj( nGroup))) ; } //---------------------------------------------------------------------------- bool Machine::AddHeadToSet( const string& sHSet, const string& sName) { // se il capo-insieme coincide con la testa, non devo fare alcunchč if ( sHSet == sName) return true ; // recupero la testa capo-insieme Head* pHead = GetHead( GetGroup( sHSet)) ; if ( pHead == nullptr) return false ; // aggiungo questa testa all'insieme return pHead->AddHeadToHSet( sName) ; } //---------------------------------------------------------------------------- const STRVECTOR& Machine::GetHSet( const string& sHead) const { // vettore di stringhe vuoto, da restituire in caso di errore static const STRVECTOR vsNull ; // recupero la testa Head* pHead = GetHead( GetGroup( sHead)) ; if ( pHead == nullptr) return vsNull ; // recupero l'insieme di teste a cui appartiene const STRVECTOR& vsTmp = pHead->GetHSet() ; if ( vsTmp.empty()) return vsNull ; // se il primo membro coincide con la testa, allora č giā l'insieme di teste if ( vsTmp[0] == sHead) return vsTmp ; // altrimenti cerco l'insieme della prima testa return GetHSet( vsTmp[0]) ; } //---------------------------------------------------------------------------- bool Machine::EnableHeadInSet( const string& sHead) { // recupero l'insieme di teste const STRVECTOR& vsHSet = GetHSet( sHead) ; if ( vsHSet.empty()) return false ; // spengo tutte le teste dell'insieme tranne questa for ( size_t i = 0 ; i < vsHSet.size() ; ++ i) { int nH = GetGroup( vsHSet[i]) ; bool bShow = ( vsHSet[i] == sHead) ; m_pGeomDB->SetMode( nH, ( bShow ? GDB_MD_STD : GDB_MD_HIDDEN)) ; m_pGeomDB->SetStatus( nH, ( bShow ? GDB_ST_ON : GDB_ST_OFF)) ; } return true ; } //---------------------------------------------------------------------------- bool Machine::ModifyMachineHeadAuxDirection( const string& sHead, const Vector3d& vtADir) { // controllo GeomDB if ( m_pGeomDB == nullptr) return false ; // recupero testa int nHeadId = GetGroup( sHead) ; Head* pHead = GetHead( nHeadId) ; if ( pHead == nullptr) return false ; // eseguo la modifica return pHead->ModifyHeadAuxDirection( vtADir) ; } //---------------------------------------------------------------------------- bool Machine::AdjustExitFrames( int nLay, const MUEXITVECTOR& vMuExit, const Vector3d& vtADir) { // se il versore ausiliario non č definito, non sono necessari controlli if ( vtADir.IsSmall()) return true ; // riferimento globale del gruppo testa Frame3d frHead ; m_pGeomDB->GetGroupGlobFrame( nLay, frHead) ; // porto il vettore ausiliario nel riferimento testa Vector3d vtAuxL = vtADir ; vtAuxL.ToLoc( frHead) ; // ciclo sulle uscite for ( int i = 0 ; i < int( vMuExit.size()) ; ++ i) { string sName = MCH_EXIT + ToString( i + 1) ; // se trovo riferimento per uscita, lo verifico int nT = m_pGeomDB->GetFirstNameInGroup( nLay, sName) ; if ( nT != GDB_ID_NULL && m_pGeomDB->GetGeoType( nT) == GEO_FRAME3D) { // recupero frame IGeoFrame3d* pGF = GetGeoFrame3d( m_pGeomDB->GetGeoObj( nT)) ; Frame3d frFrame = pGF->GetFrame() ; // determino rotazione attorno a RifAxZ per massimo allineamento RifAxX con direzione ausiliaria bool bDet ; double dAngRotDeg ; if ( frFrame.VersX().GetRotation( vtAuxL, frFrame.VersZ(), dAngRotDeg, bDet) && bDet) { if ( abs( dAngRotDeg) > EPS_ANG_SMALL) { frFrame.Rotate( frFrame.Orig(), frFrame.VersZ(), dAngRotDeg) ; pGF->Set( frFrame) ; } } else { string sOut = " Exit " + sName + " with frame not adjustable for AuxDir" ; LOG_ERROR( GetEMkLogger(), sOut.c_str()) ; } // se prima uscita, aggiungo vettore ausiliario if ( i == 0) { PtrOwner pGVec( CreateGeoVector3d()) ; if ( ! IsNull( pGVec) && pGVec->Set( vtAuxL, frFrame.Orig())) { int nAvId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLay, Release( pGVec)) ; m_pGeomDB->SetName( nAvId, MCH_AUX_VECT) ; m_pGeomDB->SetMode( nAvId, GDB_MD_HIDDEN) ; } } } } return true ; } //---------------------------------------------------------------------------- bool Machine::CreateExitGroups( int nLay, const MUEXITVECTOR& vMuExit) { // riferimento globale del gruppo testa Frame3d frHead ; m_pGeomDB->GetGroupGlobFrame( nLay, frHead) ; // ciclo sulle uscite for ( int i = 0 ; i < int( vMuExit.size()) ; ++ i) { string sName = MCH_EXIT + ToString( i + 1) ; // se trovo riferimento per uscita, lo sostituisco con gruppo equivalente int nT = m_pGeomDB->GetFirstNameInGroup( nLay, sName) ; if ( nT != GDB_ID_NULL && m_pGeomDB->GetGeoType( nT) == GEO_FRAME3D) { // recupero frame Frame3d frFrame = GetGeoFrame3d( m_pGeomDB->GetGeoObj( nT))->GetFrame() ; // verifico dati frame rispetto ad uscita (in globale) Point3d ptPos = frFrame.Orig() ; ptPos.ToGlob( frHead) ; Vector3d vtTDir = frFrame.VersZ() ; vtTDir.ToGlob( frHead) ; vtTDir.Normalize() ; Vector3d vtDelta = vMuExit[i].ptPos - ptPos ; if ( ! vtDelta.IsSmall()) { if ( vtDelta.Len() > m_dExitMaxAdjust) { string sOut = " Wrong Exit Position " + sName + " move = (" + ToString( vtDelta) + ")" ; LOG_ERROR( GetEMkLogger(), sOut.c_str()) ; return false ; } else { string sOut = " Exit " + sName + " move = (" + ToString( vtDelta) + ")" ; LOG_DBG_INFO( GetEMkLogger(), sOut.c_str()) ; vtDelta.ToLoc( frHead) ; frFrame.Translate( vtDelta) ; GetGeoFrame3d( m_pGeomDB->GetGeoObj( nT))->Set( frFrame) ; } } Vector3d vtDirN = vMuExit[i].vtTDir ; if ( ! vtDirN.Normalize() || ! AreSameVectorEpsilon( vtTDir, vtDirN, 10 * SIN_EPS_ANG_SMALL)) { double dAngRot ; if ( ! vtTDir.GetAngle( vtDirN, dAngRot) || abs( dAngRot) > m_dExitMaxRotAdj) { string sOut = " Wrong Exit Vector " + sName ; LOG_ERROR( GetEMkLogger(), sOut.c_str()) ; return false ; } else { Vector3d vtRotAx = vtTDir ^ vtDirN ; vtRotAx.Normalize( EPS_ZERO) ; string sOut = " Exit " + sName + " rotation = (" + ToString( dAngRot) + "/" + ToString( vtRotAx) + ")" ; LOG_DBG_INFO( GetEMkLogger(), sOut.c_str()) ; vtRotAx.ToLoc( frHead) ; frFrame.Rotate( frFrame.Orig(), vtRotAx, dAngRot) ; GetGeoFrame3d( m_pGeomDB->GetGeoObj( nT))->Set( frFrame) ; } } // inserisco gruppo con riferimento del frame int nGT = m_pGeomDB->InsertGroup( GDB_ID_NULL, nT, GDB_BEFORE, frFrame) ; if ( nGT == GDB_ID_NULL) { string sOut = " Error inserting group " + sName ; LOG_ERROR( GetEMkLogger(), sOut.c_str()) ; return false ; } // cambio nome al riferimento e lo nascondo m_pGeomDB->SetName( nT, "_" + sName) ; m_pGeomDB->SetStatus( nT, GDB_ST_OFF) ; // assegno nome al gruppo m_pGeomDB->SetName( nGT, sName) ; // copio le info m_pGeomDB->CopyAllInfoFrom( nGT, nT) ; // assegno info per eventuale movimento (sempre in Z globale) m_pGeomDB->SetInfo( nGT, MCH_EXIT_VAL, 0) ; // installo e inizializzo il gestore dell'uscita Exit* pExit = new(nothrow) Exit ; if ( pExit == nullptr) return false ; pExit->Set( sName, vMuExit[i].ptPos, vMuExit[i].vtTDir) ; m_pGeomDB->SetUserObj( nGT, pExit) ; } else { string sOut = " Error finding frame " + sName ; LOG_ERROR( GetEMkLogger(), sOut.c_str()) ; return false ; } } return true ; } //---------------------------------------------------------------------------- bool Machine::ModifyMachineExitPosition( const string& sHead, int nExit, const Point3d& ptPos) { // controllo GeomDB if ( m_pGeomDB == nullptr) return false ; // recupero testa int nHeadId = GetGroup( sHead) ; Head* pHead = GetHead( nHeadId) ; if ( pHead == nullptr) return false ; // recupero uscita int nExitId = m_pGeomDB->GetFirstNameInGroup( nHeadId, MCH_EXIT + ToString( nExit)) ; Exit* pExit = GetExit( nExitId) ; if ( pExit == nullptr) return false ; // eseguo la modifica if ( ! pExit->Modify( ptPos, m_dExitMaxAdjust)) return false ; // eventuale aggiornamento variabile lua EMC.EXITPOS con la nuova posizione LuaSetGlobVar( "EMC.EXITPOS", ptPos) ; return true ; } //---------------------------------------------------------------------------- bool Machine::SetLook( int nFlag) { // verifico validitā flag if ( nFlag < MCH_LOOK_TAB || nFlag > MCH_LOOK_ALL) return false ; // verifico DB geometrico if ( m_pGeomDB == nullptr) return false ; // recupero l'identificativo del gruppo di base della macchina int nMBaseId = m_pGeomDB->GetFirstInGroup( GetMachineId()) ; // recupero la tavola corrente (se non definita, prendo la prima) int nTabId = GetCurrTable() ; if ( nTabId == GDB_ID_NULL) nTabId = GetFirstTable() ; if ( nTabId == GDB_ID_NULL) return false ; // il gruppo tavola corrente deve essere sempre visibile m_pGeomDB->SetStatus( nTabId, GDB_ST_ON) ; // nascondo o visualizzo i fratelli e tutti i fratelli degli ascendenti della tavola bool bTabOnly = ( nFlag != MCH_LOOK_ALL) ; int nTabCurrId = nTabId ; int nParentId = m_pGeomDB->GetParentId( nTabCurrId) ; while ( nParentId != GDB_ID_NULL && nParentId != nMBaseId) { int nId = m_pGeomDB->GetFirstInGroup( nParentId) ; while ( nId != GDB_ID_NULL) { if ( nId != nTabCurrId) { if ( m_pGeomDB->GetGeoType( nId) != GEO_FRAME3D) m_pGeomDB->SetStatus( nId, ( bTabOnly ? GDB_ST_OFF : GDB_ST_ON)) ; else m_pGeomDB->SetStatus( nId, GDB_ST_OFF) ; } nId = m_pGeomDB->GetNext( nId) ; } nTabCurrId = nParentId ; nParentId = m_pGeomDB->GetParentId( nParentId) ; } // recupero l'utensile e l'uscita correnti (per gestire casi senza utensile) int nToolId = GetCurrTool() ; int nExitId = m_nCalcExitId ; // nascondo o visualizzo i fratelli e tutti i fratelli degli ascendenti bool bToolOnly = ( nFlag > MCH_LOOK_TAB && nFlag < MCH_LOOK_ALL) ; int nToolCurrId = ( nToolId != GDB_ID_NULL ? nToolId : nExitId) ; nParentId = m_pGeomDB->GetParentId( nToolCurrId) ; while ( nParentId != GDB_ID_NULL && nParentId != nMBaseId) { bool bHide = bToolOnly ; if ( nFlag == MCH_LOOK_TAB_HEAD || ( nFlag == MCH_LOOK_TAB_TOOL && nToolId == GDB_ID_NULL)) { if ( IsHeadGroup( nParentId) || IsRotaryAxisGroup( nParentId)) bHide = false ; } int nId = m_pGeomDB->GetFirstInGroup( nParentId) ; while ( nId != GDB_ID_NULL) { if ( m_pGeomDB->GetGeoType( nId) != GEO_FRAME3D) { if ( nId != nToolCurrId) m_pGeomDB->SetStatus( nId, ( bHide ? GDB_ST_OFF : GDB_ST_ON)) ; else m_pGeomDB->SetStatus( nId, GDB_ST_ON) ; } else m_pGeomDB->SetStatus( nId, GDB_ST_OFF) ; nId = m_pGeomDB->GetNext( nId) ; } nToolCurrId = nParentId ; nParentId = m_pGeomDB->GetParentId( nParentId) ; } // sistemo gli oggetti del gruppo di base int nId = m_pGeomDB->GetFirstInGroup( nMBaseId) ; while ( nId != GDB_ID_NULL) { if ( m_pGeomDB->GetGeoType( nId) != GEO_FRAME3D) { if ( nId != nTabCurrId && nId != nToolCurrId) m_pGeomDB->SetStatus( nId, ( nFlag != MCH_LOOK_ALL ? GDB_ST_OFF : GDB_ST_ON)) ; else if ( nId == nTabCurrId) m_pGeomDB->SetStatus( nId, GDB_ST_ON) ; else m_pGeomDB->SetStatus( nId, ( nFlag == MCH_LOOK_TAB ? GDB_ST_OFF : GDB_ST_ON)) ; } else m_pGeomDB->SetStatus( nId, GDB_ST_OFF) ; nId = m_pGeomDB->GetNext( nId) ; } // aggiorno stato di visualizzazione m_nMachineLook = nFlag ; return true ; } //---------------------------------------------------------------------------- bool Machine::LinkRawPartToGroup( int nRawPartId, const string& sGroupName) { // verifico DB geometrico e gestore lavorazioni if ( m_pGeomDB == nullptr || m_pMchMgr == nullptr) return false ; // recupero l'identificativo del gruppo di base dei grezzi int nRawGrpId = m_pMchMgr->GetCurrRawGroupId() ; if ( nRawGrpId == GDB_ID_NULL) return false ; // verifico che il grezzo appartenga a questo gruppo if ( m_pGeomDB->GetParentId( nRawPartId) != nRawGrpId) return false ; // recupero il gruppo di macchina indicato int nGrpId = GetGroup( sGroupName) ; if ( nGrpId == GDB_ID_NULL) return false ; // aggancio il grezzo al gruppo if ( ! m_pGeomDB->RelocateGlob( nRawPartId, nGrpId)) return false ; // inserisco il grezzo nell'elenco dei linkati m_vLinkedRawParts.push_back( nRawPartId) ; return true ; } //---------------------------------------------------------------------------- bool Machine::IsLinkedRawPart( int nRawId) const { return ( find( m_vLinkedRawParts.begin(), m_vLinkedRawParts.end(), nRawId) != m_vLinkedRawParts.end()) ; } //---------------------------------------------------------------------------- const INTVECTOR& Machine:: GetAllLinkedRawParts( void) const { return m_vLinkedRawParts ; } //---------------------------------------------------------------------------- bool Machine::UnlinkRawPartFromGroup( int nRawPartId) { // verifico DB geometrico e gestore lavorazioni if ( m_pGeomDB == nullptr || m_pMchMgr == nullptr) return false ; // recupero il gruppo dei grezzi dalla macchina int nRawGrpId = m_pMchMgr->GetCurrRawGroupId() ; if ( nRawGrpId == GDB_ID_NULL) return false ; // verifico che il grezzo indicato sia nell'elenco dei linkati auto iIter = find( m_vLinkedRawParts.begin(), m_vLinkedRawParts.end(), nRawPartId) ; if ( iIter == m_vLinkedRawParts.end()) return false ; // riporto il grezzo nel gruppo dei grezzi (conservando l'ordine di definizione quindi Id crescenti) int nCurrId = m_pGeomDB->GetFirstInGroup( nRawGrpId) ; while ( nCurrId != GDB_ID_NULL && nCurrId < nRawPartId) nCurrId = m_pGeomDB->GetNext( nCurrId) ; if ( nCurrId == GDB_ID_NULL) { if ( ! m_pGeomDB->RelocateGlob( nRawPartId, nRawGrpId, GDB_LAST_SON)) return false ; } else { if ( ! m_pGeomDB->RelocateGlob( nRawPartId, nCurrId, GDB_BEFORE)) return false ; } // tolgo il grezzo dall'elenco dei linkati m_vLinkedRawParts.erase( iIter) ; return true ; } //---------------------------------------------------------------------------- bool Machine::UnlinkAllRawPartsFromGroups( void) { while ( m_vLinkedRawParts.size() > 0) { int nRawId = m_vLinkedRawParts.back() ; if ( ! UnlinkRawPartFromGroup( nRawId)) return false ; } return true ; } //---------------------------------------------------------------------------- bool Machine::LinkFixtureToGroup( int nFxtId, const string& sGroupName) { // verifico DB geometrico e gestore lavorazioni if ( m_pGeomDB == nullptr || m_pMchMgr == nullptr) return false ; // recupero il gruppo delle fixtures nella macchinata corrente int nFixtGrpId = m_pMchMgr->GetCurrFixtGroupId() ; if ( nFixtGrpId == GDB_ID_NULL) return GDB_ID_NULL ; // verifico che il bloccaggio appartenga a questo gruppo if ( m_pGeomDB->GetParentId( nFxtId) != nFixtGrpId) return false ; // recupero il gruppo di macchina indicato int nGrpId = GetGroup( sGroupName) ; if ( nGrpId == GDB_ID_NULL) return false ; // aggancio il bloccaggio al gruppo if ( ! m_pGeomDB->RelocateGlob( nFxtId, nGrpId)) return false ; // inserisco il bloccaggio nell'elenco dei linkati m_vLinkedFixtures.push_back( nFxtId) ; return true ; } //---------------------------------------------------------------------------- bool Machine::IsLinkedFixture( int nFxtId) const { return ( find( m_vLinkedFixtures.begin(), m_vLinkedFixtures.end(), nFxtId) != m_vLinkedFixtures.end()) ; } //---------------------------------------------------------------------------- bool Machine::UnlinkFixtureFromGroup( int nFxtId) { // verifico DB geometrico e gestore lavorazioni if ( m_pGeomDB == nullptr || m_pMchMgr == nullptr) return false ; // recupero il gruppo delle fixtures nella macchinata corrente int nFixtGrpId = m_pMchMgr->GetCurrFixtGroupId() ; if ( nFixtGrpId == GDB_ID_NULL) return GDB_ID_NULL ; // verifico che il bloccaggio indicato sia nell'elenco dei linkati auto iIter = find( m_vLinkedFixtures.begin(), m_vLinkedFixtures.end(), nFxtId) ; if ( iIter == m_vLinkedFixtures.end()) return false ; // riporto il bloccaggio nel gruppo delle fixtures if ( ! m_pGeomDB->RelocateGlob( nFxtId, nFixtGrpId)) return false ; // tolgo il bloccaggio dall'elenco dei linkati m_vLinkedFixtures.erase( iIter) ; return true ; } //---------------------------------------------------------------------------- bool Machine::UnlinkAllFixturesFromGroups( void) { while ( m_vLinkedFixtures.size() > 0) { int nFxtId = m_vLinkedFixtures.back() ; if ( ! UnlinkFixtureFromGroup( nFxtId)) return false ; } return true ; } //---------------------------------------------------------------------------- const string KEY_SOURCE_RAW_ID = "SouRawId" ; const string KEY_ORIG_REF = "OrigRef" ; //---------------------------------------------------------------------------- bool Machine::LinkPartToGroup( int nPartId, const string& sGroupName) { // verifico DB geometrico e gestore lavorazioni if ( m_pGeomDB == nullptr || m_pMchMgr == nullptr) return false ; // verifico appartenenza del pezzo ad un grezzo int nRawId = m_pMchMgr->GetRawPartFromPart( nPartId) ; if ( nRawId == GDB_ID_NULL) return false ; // recupero il gruppo di macchina indicato int nGrpId = GetGroup( sGroupName) ; if ( nGrpId == GDB_ID_NULL) return false ; // scrivo nel pezzo l'identificativo del grezzo di origine m_pGeomDB->SetInfo( nPartId, KEY_SOURCE_RAW_ID, nRawId) ; // scrivo nel pezzo il suo riferimento originale m_pGeomDB->SetInfo( nPartId, KEY_ORIG_REF, *m_pGeomDB->GetGroupFrame( nPartId)) ; // aggancio il pezzo al gruppo if ( ! m_pGeomDB->RelocateGlob( nPartId, nGrpId)) return false ; // inserisco il pezzo nell'elenco dei linkati m_vLinkedParts.push_back( nPartId) ; return true ; } //---------------------------------------------------------------------------- bool Machine::IsLinkedPart( int nPartId) const { return ( find( m_vLinkedParts.begin(), m_vLinkedParts.end(), nPartId) != m_vLinkedParts.end()) ; } //---------------------------------------------------------------------------- bool Machine::UnlinkPartFromGroup( int nPartId) { // verifico DB geometrico e gestore lavorazioni if ( m_pGeomDB == nullptr || m_pMchMgr == nullptr) return false ; // recupero il riferimento originale del pezzo Frame3d frPart ; if ( ! m_pGeomDB->GetInfo( nPartId, KEY_ORIG_REF, frPart)) return false ; m_pGeomDB->RemoveInfo( nPartId, KEY_ORIG_REF) ; // recupero il grezzo di origine dalle info del pezzo int nRawId ; if ( ! m_pGeomDB->GetInfo( nPartId, KEY_SOURCE_RAW_ID, nRawId)) return false ; m_pGeomDB->RemoveInfo( nPartId, KEY_SOURCE_RAW_ID) ; // verifico che il pezzo indicato sia nell'elenco dei linkati auto iIter = find( m_vLinkedParts.begin(), m_vLinkedParts.end(), nPartId) ; if ( iIter == m_vLinkedParts.end()) return false ; // riporto il pezzo nel suo grezzo if ( ! m_pGeomDB->Relocate( nPartId, nRawId)) return false ; *m_pGeomDB->GetGroupFrame( nPartId) = frPart ; // tolgo il pezzo dall'elenco dei linkati m_vLinkedParts.erase( iIter) ; return true ; } //---------------------------------------------------------------------------- bool Machine::UnlinkAllPartsFromGroups( void) { while ( m_vLinkedParts.size() > 0) { int nPartId = m_vLinkedParts.back() ; if ( ! UnlinkPartFromGroup( nPartId)) return false ; } return true ; }