//---------------------------------------------------------------------------- // EgalTech 2015-2015 //---------------------------------------------------------------------------- // File : Machining.cpp Data : 10.06.15 Versione : 1.6f2 // Contenuto : Implementazione gestione base lavorazioni. // // // // Modifiche : 10.06.15 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "MachMgr.h" #include "Machining.h" #include "MachiningConst.h" #include "CamData.h" #include "/EgtDev/Include/EGkGeoPoint3d.h" #include "/EgtDev/Include/EGkCurveLine.h" #include "/EgtDev/Include/EGkIntersLineSurfTm.h" #include "/EgtDev/Include/EGkGeomDB.h" #include "/EgtDev/Include/EgtPointerOwner.h" using namespace std ; //---------------------------------------------------------------------------- bool Machining::SetOwner( int nId, IGeomDB* pGDB) { m_nOwnerId = nId ; m_pGeomDB = pGDB ; return ( m_nOwnerId != GDB_ID_NULL && m_pGeomDB != nullptr) ; } //---------------------------------------------------------------------------- int Machining::GetOwner( void) const { return m_nOwnerId ; } //---------------------------------------------------------------------------- IGeomDB* Machining::GetGeomDB( void) const { return m_pGeomDB ; } //---------------------------------------------------------------------------- bool Machining::Init( MachMgr* pMchMgr) { m_pMchMgr = pMchMgr ; if ( m_pMchMgr == nullptr) return false ; if ( m_pMchMgr->GetGeomDB() != m_pGeomDB) return false ; return true ; } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- Machining::Machining( void) : m_nOwnerId( GDB_ID_NULL), m_pGeomDB( nullptr), m_pMchMgr( nullptr), m_nPathId( GDB_ID_NULL), m_bCurr( false), m_ptCurr(), m_vtTool(), m_vtCorr(), m_vtAux(), m_dFeed( 0), m_nFlag( 0) { } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- bool Machining::GetElevation( const Point3d& ptP, const Vector3d& vtDir, double& dElev) { if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr) return false ; // inizializzo elevazione dElev = INFINITO ; // ciclo sui grezzi bool bFound = false ; int nRawId = m_pMchMgr->GetFirstRawPart() ; while ( nRawId != GDB_ID_NULL) { // intersezione del raggio dal punto alla trimesh del grezzo const double RAY_LEN = 10000 ; int nStmId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ; ISurfTriMesh* pStm = GetSurfTriMesh( m_pGeomDB->GetGeoObj( nStmId)) ; if ( pStm != nullptr) { bFound = true ; // recupero il riferimento della trimesh Frame3d frStm ; m_pGeomDB->GetGlobFrame( nStmId, frStm) ; // porto il raggio in questo riferimento Point3d ptPL = ptP ; ptPL.ToLoc( frStm) ; Vector3d vtDirL = vtDir ; vtDirL.ToLoc( frStm) ; ILSIVECTOR vInfo ; if ( IntersLineSurfTm( ptPL, vtDirL, RAY_LEN, *pStm, vInfo)) { for ( const auto& Info : vInfo) { // se tratto di intersezione coincidente, considero la posizione pił lontana, ovvero 2 if ( Info.nILTT == ILTT_SEGM || Info.nILTT == ILTT_SEGM_ON_EDGE) { // se prosegue un tratto precedente, non devo controllare sia minimo if ( fabs( dElev - Info.dU) < EPS_SMALL) dElev = Info.dU2 ; else dElev = min( dElev, Info.dU2) ; } // altrimenti intersezione puntuale, verifico che esca (coseno >= 0) else if ( Info.dCosDN > - COS_ORTO_ANG_ZERO) { dElev = min( dElev, Info.dU) ; } } } } // passo al grezzo successivo nRawId = m_pMchMgr->GetNextRawPart( nRawId) ; } // se non trovate intersezioni, elevazione nulla if ( dElev > INFINITO - 1) dElev = 0 ; return bFound ; } //---------------------------------------------------------------------------- bool Machining::GetElevation( const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtDir, double& dElev) { if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr) return false ; // inizializzo elevazione dElev = INFINITO ; // ciclo sui grezzi bool bFound = false ; int nRawId = m_pMchMgr->GetFirstRawPart() ; while ( nRawId != GDB_ID_NULL) { // intersezione del raggio dal punto alla trimesh del grezzo const double RAY_LEN = 10000 ; int nStmId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ; ISurfTriMesh* pStm = GetSurfTriMesh( m_pGeomDB->GetGeoObj( nStmId)) ; if ( pStm != nullptr) { bFound = true ; // recupero il riferimento della trimesh Frame3d frStm ; m_pGeomDB->GetGlobFrame( nStmId, frStm) ; // porto il segmento e la direzione in questo riferimento Point3d ptP1L = ptP1 ; ptP1L.ToLoc( frStm) ; Point3d ptP2L = ptP2 ; ptP2L.ToLoc( frStm) ; Vector3d vtDirL = vtDir ; vtDirL.ToLoc( frStm) ; ILSIVECTOR vInfo ; // inizializzo elevazione della superficie double dElevS = 0 ; // faccio test con un insieme di punti ( !!! sostituire con intersezione tra rettangolo e trimesh !!!) const double STEP = 50 ; int nStep = max( (int) ceil( ApproxDist( ptP1L, ptP2L) / STEP), 3) ; for ( int i = 0 ; i <= nStep ; ++ i) { // calcolo punto di test double dFraz = i / (double) nStep ; Point3d ptPL = Media( ptP1L, ptP2L, dFraz) ; // inizializzo elevazione del punto double dElevP = INFINITO ; // calcolo elevazione sul punto if ( IntersLineSurfTm( ptPL, vtDirL, RAY_LEN, *pStm, vInfo)) { for ( const auto& Info : vInfo) { // se tratto di intersezione coincidente, considero la posizione pił lontana, ovvero 2 if ( Info.nILTT == ILTT_SEGM || Info.nILTT == ILTT_SEGM_ON_EDGE) { // se prosegue un tratto precedente, non devo controllare sia minimo if ( fabs( dElevP - Info.dU) < EPS_SMALL) dElevP = Info.dU2 ; else dElevP = min( dElevP, Info.dU2) ; } // altrimenti intersezione puntuale, verifico che esca (coseno >= 0) else if ( Info.dCosDN > - COS_ORTO_ANG_ZERO) { dElevP = min( dElevP, Info.dU) ; } } } // se elevazione calcolata, aggiorno quella della superficie if ( dElevP < INFINITO - 1) dElevS = max( dElevS, dElevP) ; } // aggiorno elevazione complessiva if ( dElevS > 0) dElev = min( dElev, dElevS) ; } // passo al grezzo successivo nRawId = m_pMchMgr->GetNextRawPart( nRawId) ; } // se non trovate intersezioni, elevazione nulla if ( dElev > INFINITO - 1) dElev = 0 ; return bFound ; } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- bool Machining::SetPathId( int nPathId) { m_nPathId = nPathId ; return true ; } //---------------------------------------------------------------------------- bool Machining::SetToolDir( const Vector3d& vtDir) { m_vtTool = vtDir ; return ( m_vtTool.Normalize()) ; } //---------------------------------------------------------------------------- bool Machining::SetCorrDir( const Vector3d& vtDir) { m_vtCorr = vtDir ; return ( ! m_vtCorr.IsSmall()) ; } //---------------------------------------------------------------------------- bool Machining::SetAuxDir( const Vector3d& vtDir) { m_vtAux = vtDir ; return true ; } //---------------------------------------------------------------------------- bool Machining::SetFeed( double dFeed) { m_dFeed = dFeed ; return true ; } //---------------------------------------------------------------------------- bool Machining::SetFlag( int nFlag) { m_nFlag = nFlag ; return true ; } //---------------------------------------------------------------------------- int Machining::AddStart( const Point3d& ptP) { // verifico di essere in uno stato valido per inizio if ( m_vtTool.IsSmall()) return GDB_ID_NULL ; // creo oggetto punto per DB geometrico PtrOwner pGP( CreateGeoPoint3d()) ; if ( IsNull( pGP)) return GDB_ID_NULL ; // assegno le coordinate del punto pGP->Set( ptP) ; // inserisco l'oggetto nel DB geometrico int nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, m_nPathId, Release( pGP)) ; if ( nId == GDB_ID_NULL) return GDB_ID_NULL ; // creo oggetto dati Cam PtrOwner pCam( new( nothrow) CamData) ; if ( IsNull( pCam)) return GDB_ID_NULL ; // assegno valori pCam->SetToolDir( m_vtTool) ; pCam->SetCorrDir( m_vtCorr) ; pCam->SetAuxDir( m_vtAux) ; pCam->SetBasePoint( ptP) ; // associo questo oggetto a quello geometrico m_pGeomDB->SetUserObj( nId, Release( pCam)) ; // salvo la posizione corrente m_bCurr = true ; m_ptCurr = ptP ; return nId ; } //---------------------------------------------------------------------------- int Machining::AddLinearMove( const Point3d& ptP) { // verifico di essere in uno stato valido per un movimento lineare if ( ! m_bCurr || m_vtTool.IsSmall() || m_dFeed < EPS_SMALL) return GDB_ID_NULL ; // creo oggetto linea per DB geometrico PtrOwner pLine( CreateCurveLine()) ; if ( IsNull( pLine)) return GDB_ID_NULL ; // assegno le coordinate degli estremi if ( ! pLine->Set( m_ptCurr, ptP)) return GDB_ID_NULL ; // inserisco l'oggetto nel DB geometrico int nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, m_nPathId, Release( pLine)) ; if ( nId == GDB_ID_NULL) return GDB_ID_NULL ; // creo oggetto dati Cam PtrOwner pCam( new( nothrow) CamData) ; if ( IsNull( pCam)) return GDB_ID_NULL ; // assegno valori pCam->SetToolDir( m_vtTool) ; pCam->SetCorrDir( m_vtCorr) ; pCam->SetAuxDir( m_vtAux) ; pCam->SetBasePoint( ptP) ; pCam->SetFeed( m_dFeed) ; pCam->SetFlag( m_nFlag) ; // associo questo oggetto a quello geometrico m_pGeomDB->SetUserObj( nId, Release( pCam)) ; // salvo la posizione corrente m_ptCurr = ptP ; return nId ; } //---------------------------------------------------------------------------- bool Machining::ResetMoveData( void) { m_bCurr = false ; m_ptCurr = ORIG ; m_vtTool = V_NULL ; m_vtCorr = V_NULL ; m_vtAux = V_NULL ; m_dFeed = 0 ; m_nFlag = 0 ; return true ; } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- bool Machining::GetFinalAxesValues( DBLVECTOR& vAxVal) { // recupero gruppo per geometria di lavorazione (Cutter Location) int nClId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_CL) ; if ( nClId == GDB_ID_NULL) return false ; // recupero l'ultimo percorso CL int nClPathId = m_pGeomDB->GetLastGroupInGroup( nClId) ; // recupero l'ultima entitą di questo percorso int nEntId = m_pGeomDB->GetLastInGroup( nClPathId) ; // recupero i dati Cam dell'entitą CamData* pCamData = dynamic_cast( m_pGeomDB->GetUserObj( nEntId)) ; if ( pCamData == nullptr) return false ; // assegno i valori degli assi vAxVal = pCamData->GetAxisVal() ; return true ; } //---------------------------------------------------------------------------- bool Machining::CalculateAxesValues( void) { // recupero la lavorazione precedente int nPrevOpId = m_pMchMgr->GetPrevOperation( GetOwner()) ; Machining* pPrevMch = dynamic_cast( m_pGeomDB->GetUserObj( nPrevOpId)) ; // recupero l'utensile precedente string sPrevTool ; if ( pPrevMch != nullptr) pPrevMch->GetParam( MPA_TOOL, sPrevTool) ; // imposto l'utensile per i calcoli macchina if ( ! m_pMchMgr->SetCalcTool( GetToolData().m_sName, GetToolData().m_sHead, GetToolData().m_nExit)) return false ; // recupero il numero di assi lineari e rotanti attivi int nLinAxes = m_pMchMgr->GetCurrLinAxes() ; int nRotAxes = m_pMchMgr->GetCurrRotAxes() ; // assegno gli angoli iniziali double dAngAprec = 0 ; double dAngBprec = 0 ; // se utensile non cambiato, uso gli angoli finali della lavorazione precedente if ( ! sPrevTool.empty() && GetToolData().m_sName == sPrevTool) { DBLVECTOR vAxVal ; pPrevMch->GetFinalAxesValues( vAxVal) ; if ( nRotAxes >= 1) dAngAprec = vAxVal[nLinAxes - 1 + 1] ; if ( nRotAxes >= 2) dAngBprec = vAxVal[nLinAxes - 1 + 2] ; } // altrimenti uso gli angoli home else { DBLVECTOR vAxVal ; m_pMchMgr->GetAllCalcAxesHomePos( vAxVal) ; if ( nRotAxes >= 1) dAngAprec = vAxVal[nLinAxes - 1 + 1] ; if ( nRotAxes >= 2) dAngBprec = vAxVal[nLinAxes - 1 + 2] ; } // recupero peso primo asse rotante di testa double dRot1W = m_pMchMgr->GetCalcRot1W() ; // recupero gruppo della geometria di lavorazione (Cutter Location) int nClId = m_pGeomDB->GetFirstNameInGroup( m_nOwnerId, MCH_CL) ; if ( nClId == GDB_ID_NULL) return false ; // calcolo il valore degli assi macchina di tutti i movimenti bool bOk = true ; int nClPathId = m_pGeomDB->GetFirstGroupInGroup( nClId) ; while ( nClPathId != GDB_ID_NULL) { if ( ! CalculateClPathAxesValues( nClPathId, nLinAxes, nRotAxes, dRot1W, dAngAprec, dAngBprec)) bOk = false ; nClPathId = m_pGeomDB->GetNextGroup( nClPathId) ; } return bOk ; } //---------------------------------------------------------------------------- bool Machining::CalculateClPathAxesValues( int nClPathId, int nLinAxes, int nRotAxes, double dRot1W, double& dAngAprec, double& dAngBprec) { // recupero il numero degli assi lineari e rotanti // predispongo variabile per valori assi DBLVECTOR vAxVal ; vAxVal.reserve( 8) ; // ciclo su tutte le entitą del percorso CL bool bOk = true ; for ( int nEntId = m_pGeomDB->GetFirstInGroup( nClPathId) ; nEntId != GDB_ID_NULL ; nEntId = m_pGeomDB->GetNext( nEntId)) { // recupero i dati Cam dell'entitą CamData* pCamData = dynamic_cast( m_pGeomDB->GetUserObj( nEntId)) ; if ( pCamData == nullptr) continue ; // calcolo degli assi rotanti della macchina int nRStat ; double dAngA1, dAngB1, dAngA2, dAngB2 ; bool bROk = m_pMchMgr->GetCalcAngles( pCamData->GetToolDir(), pCamData->GetCorrDir(), nRStat, dAngA1, dAngB1, dAngA2, dAngB2) ; if ( ! bROk || nRStat == 0) { bOk = false ; pCamData->SetAxes( CamData::AS_ERR, vAxVal) ; continue ; } if ( nRStat == 1) { // porto gli angoli ai valori pił vicini ai precedenti con offset di uno o pił giri m_pMchMgr->GetNearestAngleInStroke( 1, dAngAprec, dAngA1) ; m_pMchMgr->GetNearestAngleInStroke( 2, dAngBprec, dAngB1) ; } if ( nRStat == 2) { // porto gli angoli ai valori pił vicini ai precedenti con offset di uno o pił giri m_pMchMgr->GetNearestAngleInStroke( 1, dAngAprec, dAngA1) ; m_pMchMgr->GetNearestAngleInStroke( 2, dAngBprec, dAngB1) ; m_pMchMgr->GetNearestAngleInStroke( 1, dAngAprec, dAngA2) ; m_pMchMgr->GetNearestAngleInStroke( 2, dAngBprec, dAngB2) ; // scelgo la soluzione pił vicina ai precedenti double dDeltaA1 = dRot1W * fabs( dAngA1 - dAngAprec) ; double dDeltaB1 = fabs( dAngB1 - dAngBprec) ; double dDeltaA2 = dRot1W * fabs( dAngA2 - dAngAprec) ; double dDeltaB2 = fabs( dAngB2 - dAngBprec) ; if ( dDeltaA2 + dDeltaB2 < dDeltaA1 + dDeltaB1 - 1.) { dAngA1 = dAngA2 ; dAngB1 = dAngB2 ; } } // ricavo posizione con eventuali modifiche dipendenti dalla lavorazione Point3d ptP = pCamData->GetBasePoint() ; AdjustPositionForAxesCalc( pCamData, ptP) ; // calcolo gli assi lineari della macchina int nLStat ; double dX, dY, dZ ; bool bLOk = m_pMchMgr->GetCalcPositions( ptP, dAngA1, dAngB1, nLStat, dX, dY, dZ) ; if ( ! bLOk || nLStat != 0) { bOk = false ; pCamData->SetAxes( CamData::AS_ERR, vAxVal) ; continue ; } // assegno valori assi vAxVal.clear() ; vAxVal.emplace_back( dX) ; vAxVal.emplace_back( dY) ; vAxVal.emplace_back( dZ) ; vAxVal.emplace_back( dAngA1) ; vAxVal.emplace_back( dAngB1) ; // verifico i limiti di corsa degli assi int nStat ; bool bOsOk = m_pMchMgr->VerifyOutOfStroke( dX, dY, dZ, dAngA1, dAngB1, nStat) ; if ( ! bOsOk || nStat != 0) { bOk = false ; pCamData->SetAxes( CamData::AS_OUTSTROKE, vAxVal) ; continue ; } // salvo i valori degli assi pCamData->SetAxes( CamData::AS_OK, vAxVal) ; // memorizzo i valori degli angoli come nuovi precedenti dAngAprec = dAngA1 ; dAngBprec = dAngB1 ; } return bOk ; }