//---------------------------------------------------------------------------- // EgalTech 2014-2017 //---------------------------------------------------------------------------- // File : ImportCnc.cpp Data : 26.03.17 Versione : 1.8c4 // Contenuto : Implementazione della classe per l'importazione di CNC. // // // // Modifiche : 15.09.14 DS Creazione modulo. // 26/03/17 DS Gestione punto come solo cambio assi rotanti. // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "ImportCnc.h" #include "DllMain.h" #include "/EgtDev/Include/EExDllMain.h" #include "/EgtDev/Include/EGkGeomDB.h" #include "/EgtDev/Include/EGkGdbIterator.h" #include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EGkGeoPoint3d.h" #include "/EgtDev/Include/EGkCurveLine.h" #include "/EgtDev/Include/EGkCurveArc.h" #include "/EgtDev/Include/EGkCurveComposite.h" #include "/EgtDev/Include/EGkArcSpecial.h" #include "/EgtDEv/Include/EGnScanner.h" #include "/EgtDev/Include/SELkKeyProc.h" #include "/EgtDev/Include/EgtKeyCodes.h" #include "/EgtDev/Include/EgtStringConverter.h" #include "/EgtDev/Include/EgtPointerOwner.h" using namespace std ; //---------------------------------------------------------------------------- static const string NAME_ERROR = "Error" ; static const Color COL_RAPID( 0, 192, 192, 50) ; static const Color COL_ERROR( 255, 0, 0, 100) ; static const string KEY_TCS = "TCS" ; static const string KEY_TCOMP = "TCOMP" ; static const string KEY_TNAME = "TNAME" ; static const string KEY_EXIT = "EXIT" ; static const string KEY_TPOS = "TPOS" ; static const string KEY_TPOS2 = "TPOS2" ; static const string KEY_SPEED = "SPEED" ; static const string KEY_ROTAX_A = "A" ; static const string KEY_ROTAX_B = "B" ; static const string KEY_ROTAX_C = "C" ; static const string KEY_INFO = "INFO" ; //---------------------------------------------------------------------------- IImportCnc* CreateImportCnc( void) { // verifico la chiave e le opzioni if ( ! VerifyKey( KEYOPT_EEX_INPBASE)) return nullptr ; // creo l'oggetto return static_cast ( new(nothrow) ImportCnc) ; } //---------------------------------------------------------------------------- bool ImportCnc::Import( const string& sFile, IGeomDB* pGDB, int nIdGroup, int nFlag) { // verifico il DB geometrico if ( pGDB == nullptr) { LOG_ERROR( GetEExLogger(), "ImportCnc : Error on GeomDB") return false ; } m_pGDB = pGDB ; // verifico l'Id di gruppo if ( ! m_pGDB->ExistsObj( nIdGroup)) { LOG_ERROR( GetEExLogger(), "ImportCnc : Error on IdGroup") return false ; } m_nIdGroup = nIdGroup ; // ricavo il riferimento del gruppo if ( ! m_pGDB->GetGroupGlobFrame( m_nIdGroup, m_frGroup)) { LOG_ERROR( GetEExLogger(), "ImportCnc : Error on Group Frame3d") return false ; } // imposto le opzioni di importazione m_nFlag = nFlag ; // inizializzo lo scanner Scanner TheScanner ; if ( ! TheScanner.Init( sFile, "")) { LOG_ERROR( GetEExLogger(), "ImportCnc : Error on Init") return false ; } // inizializzo lo stato m_nLine = 0 ; m_nCNC = CNC_STD ; m_bToMove = false ; m_bLoadTool = false ; m_nTool = 0 ; m_nNextTool = 0 ; m_nFirstGroup = GDB_ID_NULL ; m_nMoveType = RAPID ; m_nCharsOn = 0 ; m_bZeroMach = false ; m_bAbsCoord = true ; m_nInterpPl = XY ; m_nArcType = NO_ARCTYPE ; m_nComp = 0 ; m_nCompSide = NO_COMP ; m_ptHome = ORIG ; m_ptLast = ORIG ; m_ptNext = ORIG ; m_ptCen = ORIG ; m_vtOffs = V_NULL ; m_dLinCoeff = ONEMM ; m_dRadius = 0 ; m_dRotAxA = NAN ; m_dRotAxB = NAN ; m_dRotAxC = NAN ; SaveRotAxes() ; m_dOffsAxA = 0 ; m_dOffsAxB = 0 ; m_dOffsAxC = 0 ; m_colCurr = BLACK ; m_sToolName.clear() ; m_nExit = 1 ; // se estensione xpi è NUM string sFileTitle, sFileExt ; SplitLast( sFile, ".", sFileTitle, sFileExt) ; ToUpper( sFileExt) ; if ( sFileExt == "XPI") m_nCNC = CNC_NUM ; else if ( sFileExt == "MPF") m_nCNC = CNC_SIEMENS ; else if ( sFileExt == "ISO") m_nCNC = CNC_TPA ; else if ( sFileExt == "CNC") m_nCNC = CNC_OSAI ; else if ( sFileExt == "EIA") m_nCNC = CNC_MAZAK ; else if ( sFileExt == "PIM") m_nCNC = CNC_FAGOR ; // ciclo di lettura delle linee bool bOk = true ; string sLine ; while ( TheScanner.GetLine( sLine)) { m_nLine = TheScanner.GetCurrLineNbr() ; if ( ! ProcessLine( sLine)) { bOk = false ; string sErr = "ImportCnc : Error on line " + ToString( m_nLine) ; LOG_ERROR( GetEExLogger(), sErr.c_str()) } } // se importazione riuscita eseguo elaborazione finale if ( bOk) bOk = PostProcess() ; return bOk ; } //---------------------------------------------------------------------------- bool ImportCnc::ProcessLine( const string& sLine) { // eventuale gestione linea di commento o con etichetta if ( sLine[0] == '(' || sLine[0] == ';' || sLine[0] == '\"') return ParseRemark( sLine) ; // altre linee da saltare if ( sLine[0] == '$' || sLine[0] == '!' || ( sLine[0] == 'M' && sLine[1] == 'S' && sLine[2] == 'G')) return true ; // eliminazione di commenti intermedi o finali string sMyLine = sLine ; // se controllo OSAI elimino le parti dopo ; if ( m_nCNC == CNC_OSAI) { size_t nStart = sMyLine.find( ';') ; if ( nStart != string::npos) sMyLine.erase( nStart) ; } // se controllo NUM elimino le parti tra parentesi tonde else if ( m_nCNC == CNC_NUM) { size_t nStart = sMyLine.find( '(') ; if ( nStart != string::npos) { size_t nEnd = sMyLine.find( ')', nStart) ; if ( nEnd != string::npos) sMyLine.erase( nStart, nEnd - nStart + 1) ; else sMyLine.erase( nStart) ; } } // se controllo SIEMENS elimino i cicli 800 e 832 else if ( m_nCNC == CNC_SIEMENS) { size_t nStart = sMyLine.find( "CYCLE800") ; if ( nStart == string::npos) nStart = sMyLine.find( "CYCLE832") ; if ( nStart != string::npos) sMyLine.erase( nStart) ; } // divido la linea in parti STRVECTOR vsTokens ; TokenizePlus( sMyLine, "NGXYZIJKPQRUVWABCFTMHhDEL", vsTokens) ; // analizzo ogni singola parte for ( size_t i = 0 ; i < vsTokens.size() ; ++ i) { // analizzo per categorie determinate dal primo carattere del token switch ( vsTokens[i][0]) { case 'G' : ParseG( vsTokens[i]) ; break ; case 'X' : ParseX( vsTokens[i]) ; break ; case 'Y' : ParseY( vsTokens[i]) ; break ; case 'Z' : ParseZ( vsTokens[i]) ; break ; case 'I' : ParseI( vsTokens[i]) ; break ; case 'J' : ParseJ( vsTokens[i]) ; break ; case 'K' : ParseK( vsTokens[i]) ; break ; case 'P' : ParseR( vsTokens[i]) ; break ; case 'Q' : ParseR( vsTokens[i]) ; break ; case 'R' : ParseR( vsTokens[i]) ; break ; case 'A' : ParseA( vsTokens[i]) ; break ; case 'B' : ParseB( vsTokens[i]) ; break ; case 'C' : ParseC( vsTokens[i]) ; break ; case 'T' : ParseT( vsTokens[i]) ; break ; case 'M' : ParseM( vsTokens[i]) ; break ; case 'H' : if ( m_nCNC == CNC_FANUC) ParseH( vsTokens[i]) ; break ; case 'h' : if ( m_nCNC == CNC_OSAI) ParseH( vsTokens[i]) ; break ; case 'D' : if ( m_nCNC != CNC_FANUC && m_nCNC != CNC_OSAI) ParseH( vsTokens[i]) ; break ; } } bool bOk = true ; // se utensile da caricare if ( m_bLoadTool) m_nTool = m_nNextTool ; // se comando di movimento o riconosciuto movimento, lo eseguo if ( m_nCommand == MOVE || m_bToMove) bOk = ExecMovement() ; // se comando di impostazione piano di interpolazione else if ( m_nCommand == IPL) bOk = ExecSetIPL() ; // reset stato comandi m_nCommand = NO_CMD ; m_nCharsOn = 0 ; m_bToMove = false ; m_bZeroMach = false ; m_bLoadTool = false ; m_nArcType = NO_ARCTYPE ; m_nCompSide = NO_COMP ; // centro archi non modale m_ptCen = ORIG ; return bOk ; } //---------------------------------------------------------------------------- bool ImportCnc::ParseRemark( const string& sLine) { // verifico se commento tra parentesi bool bBrackets = ( sLine[0] == '(') ; // cerco indicazione tipo controllo numerico string::size_type iCnc = sLine.find( "CNC/") ; if ( iCnc == string::npos) iCnc = sLine.find( "CNC=") ; if ( iCnc != string::npos) { string sCNC = sLine.substr( iCnc + 4) ; TrimRight( sCNC, " )") ; sCNC = ToUpper( sCNC) ; if ( sCNC == "OSAI") m_nCNC = CNC_OSAI ; else if ( sCNC == "FANUC") m_nCNC = CNC_FANUC ; else if ( sCNC == "NUM") m_nCNC = CNC_NUM ; else if ( sCNC == "SIEMENS") m_nCNC = CNC_SIEMENS ; else if ( sCNC == "TPA") m_nCNC = CNC_TPA ; else if ( sCNC == "MAZAK") m_nCNC = CNC_MAZAK ; else if ( sCNC == "FAGOR") m_nCNC = CNC_FAGOR ; } // cerco indicazione di posizione Home string::size_type iFrom = sLine.find( "FROM/") ; if ( iFrom == string::npos) iFrom = sLine.find( "FROM=") ; if ( iFrom != string::npos) { Point3d ptHome ; if ( FromString( sLine.substr( iFrom + 5), ptHome)) { m_ptHome = ptHome ; m_ptLast = m_ptHome ; m_ptNext = m_ptLast ; } return true ; } // cerco indicazione di colore string::size_type iCol = sLine.find( "COLOR/") ; if ( iCol == string::npos) iCol = sLine.find( "COLOR=") ; if ( iCol != string::npos) { int vnVal[3] ; if ( FromString( sLine.substr( iCol + 6), vnVal)) { m_colCurr.Set( vnVal[0], vnVal[1], vnVal[2]) ; } return true ; } // cerco indicazione nome utensile string::size_type iTool = sLine.find( "TOOL/") ; if ( iTool == string::npos) iTool = sLine.find( "TOOL=") ; if ( iTool != string::npos) { m_sToolName = sLine.substr( iTool + 5) ; if ( bBrackets) TrimRight( m_sToolName, " )") ; return true ; } // cerco indicazione uscita in uso string::size_type iExit = sLine.find( "EXIT/") ; if ( iExit == string::npos) iExit = sLine.find( "EXIT=") ; if ( iExit != string::npos) { FromString( sLine.substr( iExit + 5), m_nExit) ; return true ; } // cerco indicazione posizione nel TC string::size_type iTpos = sLine.find( "TPOS/") ; if ( iTpos == string::npos) iTpos = sLine.find( "TPOS=") ; if ( iTpos != string::npos) { m_sToolPos = sLine.substr( iTpos + 5) ; if ( bBrackets) TrimRight( m_sToolPos, " )") ; return true ; } // cerco indicazione seconda posizione nel TC string::size_type iTpos2 = sLine.find( "TPOS2/") ; if ( iTpos2 == string::npos) iTpos2 = sLine.find( "TPOS2=") ; if ( iTpos2 != string::npos) { m_sToolPos2 = sLine.substr( iTpos2 + 6) ; if ( bBrackets) TrimRight( m_sToolPos2, " )") ; return true ; } // cerco indicazione Speed string::size_type iSpeed = sLine.find( "SPEED/") ; if ( iSpeed == string::npos) iSpeed = sLine.find( "SPEED=") ; if ( iSpeed != string::npos) { m_sSpeed = sLine.substr( iSpeed + 6) ; if ( bBrackets) TrimRight( m_sSpeed, " )") ; return true ; } // cerco informazione da inserire nella prossima entità string::size_type iInfo = sLine.find( "INFO/") ; if ( iInfo == string::npos) iInfo = sLine.find( "INFO=") ; if ( iInfo != string::npos) { m_vInfos.push_back( sLine.substr( iInfo + 5)) ; if ( bBrackets) TrimRight( m_vInfos.back(), " )") ; return true ; } return true ; } //---------------------------------------------------------------------------- bool ImportCnc::ParseG( const string& sToken) { int nVal ; int nStart = ( sToken[1] == '=' ? 2 : 1) ; if ( ! FromString( sToken.substr( nStart), nVal)) nVal = 0 ; switch ( nVal) { case 0 : m_nCommand = MOVE ; m_nMoveType = RAPID ; break ; case 1 : m_nCommand = MOVE ; m_nMoveType = LINE ; break ; case 2 : m_nCommand = MOVE ; m_nMoveType = ARC_CW ; break ; case 3 : m_nCommand = MOVE ; m_nMoveType = ARC_CCW ; break ; case 14 : m_nCommand = MOVE ; m_nMoveType = ARC_MID_3D ; break ; case 23 : m_nCommand = MOVE ; m_nMoveType = ARC_MID_2D ; break ; case 16 : m_nCommand = IPL ; break ; case 17 : m_nInterpPl = XY ; break ; case 18 : m_nInterpPl = ZX ; break ; case 19 : m_nInterpPl = YZ ; break ; case 20 : m_dLinCoeff = ONEINCH ; break ; case 21 : m_dLinCoeff = ONEMM ; break ; case 40 : m_nCompSide = G40 ; break ; case 41 : m_nCompSide = G41 ; break ; case 42 : m_nCompSide = G42 ; break ; case 54 : case 55 : case 56 : case 57 : m_vtOffs = V_NULL ; m_dOffsAxA = 0 ; m_dOffsAxB = 0 ; m_dOffsAxC = 0 ; break ; case 58 : case 59 : m_nCommand = OFFS ; m_vtOffs = V_NULL ; m_dOffsAxA = 0 ; m_dOffsAxB = 0 ; m_dOffsAxC = 0 ; break ; case 70 : m_dLinCoeff = ONEINCH ; break ; case 71 : m_dLinCoeff = ONEMM ; break ; case 79 : m_bZeroMach = true ; break ; case 90 : m_bAbsCoord = true ; break ; case 91 : m_bAbsCoord = false ; break ; } // per saltare le macro custom su NUM (tipo G101... di S3) if ( m_nCNC == CNC_NUM && nVal > 99) { m_nCommand = NO_CMD ; m_nMoveType = RAPID ; m_bZeroMach = true ; } return true ; } //---------------------------------------------------------------------------- bool ImportCnc::ParseX( const string& sToken) { double dVal ; int nStart = ( sToken[1] == '=' ? 2 : 1) ; if ( ! FromString( sToken.substr( nStart), dVal)) dVal = 0 ; dVal *= m_dLinCoeff ; switch ( m_nCommand) { case IPL : break ; case OFFS : m_vtOffs.x = dVal ; break ; default : if ( m_bZeroMach) m_ptNext.x = m_ptHome.x + dVal ; else m_ptNext.x = ( m_bAbsCoord ? m_vtOffs.x + dVal : m_ptLast.x + dVal) ; m_bToMove = true ; break ; } m_nCharsOn |= X_ON ; return true ; } //---------------------------------------------------------------------------- bool ImportCnc::ParseY( const string& sToken) { double dVal ; int nStart = ( sToken[1] == '=' ? 2 : 1) ; if ( ! FromString( sToken.substr( nStart), dVal)) dVal = 0 ; dVal *= m_dLinCoeff ; switch ( m_nCommand) { case IPL : break ; case OFFS : m_vtOffs.y = dVal ; break ; default : if ( m_bZeroMach) m_ptNext.y = m_ptHome.y + dVal ; else m_ptNext.y = ( m_bAbsCoord ? m_vtOffs.y + dVal : m_ptLast.y + dVal) ; m_bToMove = true ; break ; } m_nCharsOn |= Y_ON ; return true ; } //---------------------------------------------------------------------------- bool ImportCnc::ParseZ( const string& sToken) { double dVal ; int nStart = ( sToken[1] == '=' ? 2 : 1) ; if ( ! FromString( sToken.substr( nStart), dVal)) dVal = 0 ; dVal *= m_dLinCoeff ; switch ( m_nCommand) { case IPL : break ; case OFFS : m_vtOffs.z = dVal ; break ; default : if ( m_bZeroMach) m_ptNext.z = m_ptHome.z + dVal ; else m_ptNext.z = ( m_bAbsCoord ? m_vtOffs.z + dVal : m_ptLast.z + dVal) ; m_bToMove = true ; break ; } m_nCharsOn |= Z_ON ; return true ; } //---------------------------------------------------------------------------- bool ImportCnc::ParseI( const string& sToken) { double dVal ; int nStart = ( sToken[1] == '=' ? 2 : 1) ; if ( ! FromString( sToken.substr( nStart), dVal)) dVal = 0 ; dVal *= m_dLinCoeff ; if ( m_nCNC != CNC_OSAI) m_ptCen.x = dVal ; else { switch ( m_nInterpPl) { case XY : m_ptCen.x = dVal ; break ; case YZ : m_ptCen.y = dVal ; break ; case ZX : m_ptCen.z = dVal ; break ; } } m_nArcType = CENTER ; m_bToMove = true ; return true ; } //---------------------------------------------------------------------------- bool ImportCnc::ParseJ( const string& sToken) { double dVal ; int nStart = ( sToken[1] == '=' ? 2 : 1) ; if ( ! FromString( sToken.substr( nStart), dVal)) dVal = 0 ; dVal *= m_dLinCoeff ; if ( m_nCNC != CNC_OSAI) m_ptCen.y = dVal ; else { switch ( m_nInterpPl) { case XY : m_ptCen.y = dVal ; break ; case YZ : m_ptCen.z = dVal ; break ; case ZX : m_ptCen.x = dVal ; break ; } } m_nArcType = CENTER ; m_bToMove = true ; return true ; } //---------------------------------------------------------------------------- bool ImportCnc::ParseK( const string& sToken) { if ( m_nCNC == CNC_OSAI) return true ; // Z del centro dell'arco double dVal ; int nStart = ( sToken[1] == '=' ? 2 : 1) ; if ( ! FromString( sToken.substr( nStart), dVal)) dVal = 0 ; dVal *= m_dLinCoeff ; m_ptCen.z = dVal ; m_nArcType = CENTER ; m_bToMove = true ; return true ; } //---------------------------------------------------------------------------- bool ImportCnc::ParseP( const string& sToken) { // se direzione utensile NUM (G16) salto e resetto comando if ( m_nCommand == IPL) { m_nCommand = NO_CMD ; return true ; } return true ; } //---------------------------------------------------------------------------- bool ImportCnc::ParseQ( const string& sToken) { // se direzione utensile NUM (G16) salto e resetto comando if ( m_nCommand == IPL) { m_nCommand = NO_CMD ; return true ; } return true ; } //---------------------------------------------------------------------------- bool ImportCnc::ParseR( const string& sToken) { // se direzione utensile NUM (G16) salto e resetto comando if ( m_nCommand == IPL) { m_nCommand = NO_CMD ; return true ; } double dVal ; int nStart = ( sToken[1] == '=' ? 2 : 1) ; if ( ! FromString( sToken.substr( nStart), dVal)) dVal = 0 ; dVal *= m_dLinCoeff ; m_dRadius = dVal ; m_nArcType = RADIUS ; return true ; } //---------------------------------------------------------------------------- bool ImportCnc::ParseA( const string& sToken) { double dVal ; int nStart = ( sToken[1] == '=' ? 2 : 1) ; if ( FromString( sToken.substr( nStart), dVal)) { if ( m_nCommand == OFFS) m_dOffsAxA = dVal ; else { m_dRotAxA = ( m_bAbsCoord ? m_dOffsAxA + dVal : m_dRotAxA + dVal) ; m_bToMove = true ; } } return true ; } //---------------------------------------------------------------------------- bool ImportCnc::ParseB( const string& sToken) { double dVal ; int nStart = ( sToken[1] == '=' ? 2 : 1) ; if ( FromString( sToken.substr( nStart), dVal)) { if ( m_nCommand == OFFS) m_dOffsAxB = dVal ; else { m_dRotAxB = ( m_bAbsCoord ? m_dOffsAxB + dVal : m_dRotAxB + dVal) ; m_bToMove = true ; } } return true ; } //---------------------------------------------------------------------------- bool ImportCnc::ParseC( const string& sToken) { // cerco l'impostazione del raggio con CR= (Siemens) if ( sToken.find( "CR=") == 0) { double dVal ; int nStart = 3 ; if ( ! FromString( sToken.substr( nStart), dVal)) dVal = 0 ; m_dRadius = dVal ; m_nArcType = RADIUS ; return true ; } // altrimenti può essere l'asse rotante C double dVal ; int nStart = ( sToken[1] == '=' ? 2 : 1) ; if ( FromString( sToken.substr( nStart), dVal)) { if ( m_nCommand == OFFS) m_dOffsAxC = dVal ; else { m_dRotAxC = ( m_bAbsCoord ? m_dOffsAxC + dVal : m_dRotAxC + dVal) ; m_bToMove = true ; } } return true ; } //---------------------------------------------------------------------------- bool ImportCnc::ParseT( const string& sToken) { int nVal ; int nStart = ( sToken[1] == '=' ? 2 : 1) ; if ( ! FromString( sToken.substr( nStart), nVal)) nVal = 0 ; m_nNextTool = nVal ; return true ; } //---------------------------------------------------------------------------- bool ImportCnc::ParseM( const string& sToken) { int nVal ; int nStart = ( sToken[1] == '=' ? 2 : 1) ; if ( ! FromString( sToken.substr( nStart), nVal)) nVal = 0 ; if ( nVal == 6) m_bLoadTool = true ; return true ; } //---------------------------------------------------------------------------- bool ImportCnc::ParseH( const string& sToken) { int nVal ; int nStart = ( sToken[1] == '=' ? 2 : 1) ; if ( ! FromString( sToken.substr( nStart), nVal)) nVal = 0 ; m_nComp = nVal ; return true ; } //---------------------------------------------------------------------------- bool ImportCnc::ExecSetIPL( void) { if ( ( m_nCharsOn & X_ON) != 0 && ( m_nCharsOn & Y_ON)) { m_nInterpPl = XY ; return true ; } else if ( ( m_nCharsOn & Y_ON) != 0 && ( m_nCharsOn & Z_ON)) { m_nInterpPl = YZ ; return true ; } else if ( ( m_nCharsOn & Z_ON) != 0 && ( m_nCharsOn & X_ON)) { m_nInterpPl = ZX ; return true ; } return false ; } //---------------------------------------------------------------------------- bool ImportCnc::ExecMovement( void) { // se richiesto di ignorare i movimenti in Zero Macchina if ( ( m_nFlag & EICFLAG_SKIP_ZEROMACH) != 0 && m_bZeroMach) return true ; // eseguo movimento switch ( m_nMoveType) { case RAPID : if ( AreSamePointApprox( m_ptLast, m_ptNext)) return ( RotAxesChanged() ? AddPoint( P_RAPID) : true) ; else return AddLine( L_RAPID) ; case LINE : if ( AreSamePointApprox( m_ptLast, m_ptNext)) return ( RotAxesChanged() ? AddPoint( P_PNT) : true) ; else return AddLine( L_LINE) ; case ARC_CW : case ARC_CCW : if ( AddArc( m_nMoveType == ARC_CCW)) return true ; if ( AreSamePointApprox( m_ptLast, m_ptNext)) AddPoint( P_ERROR) ; else AddLine( L_ERROR) ; return false ; case ARC_MID_2D : case ARC_MID_3D : if ( AddArc3P( m_nMoveType == ARC_MID_2D)) return true ; if ( AreSamePointApprox( m_ptLast, m_ptNext)) AddPoint( P_ERROR) ; else AddLine( L_ERROR) ; return false ; } return false ; } //---------------------------------------------------------------------------- bool ImportCnc::AddPoint( int nPntType) { // creo il punto PtrOwner pGeoPnt( CreateGeoPoint3d()) ; if ( IsNull( pGeoPnt)) return false ; // setto il punto if ( ! pGeoPnt->Set( 0.5 * ( m_ptLast + m_ptNext))) return false ; // porto il punto nel riferimento del gruppo pGeoPnt->ToLoc( m_frGroup) ; // inserisco il punto nel DB int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, GetToolGroup(), Release( pGeoPnt)) ; if ( nId == GDB_ID_NULL) return false ; // attributi switch ( nPntType) { case P_RAPID : m_pGDB->SetMaterial( nId, COL_RAPID) ; break ; case P_PNT : m_pGDB->SetMaterial( nId, m_colCurr) ; break ; case P_ERROR : m_pGDB->SetMaterial( nId, COL_ERROR) ; m_pGDB->SetName( nId, NAME_ERROR) ; break ; } // assegnazione numero di linea m_pGDB->SetName( nId, ToString( m_nLine)) ; // assegnazione eventuale uscita if ( m_nExit != 0) { m_pGDB->SetInfo( nId, KEY_EXIT, m_nExit) ; m_nExit = 0 ; } // assegnazione eventuali assi rotanti if ( ! isnan( m_dRotAxA)) m_pGDB->SetInfo( nId, KEY_ROTAX_A, m_dRotAxA) ; if ( ! isnan( m_dRotAxB)) m_pGDB->SetInfo( nId, KEY_ROTAX_B, m_dRotAxB) ; if ( ! isnan( m_dRotAxC)) m_pGDB->SetInfo( nId, KEY_ROTAX_C, m_dRotAxC) ; // assegnazione eventuali info SetInfos( nId) ; m_vInfos.clear() ; // movimento effettuato m_ptLast = m_ptNext ; SaveRotAxes() ; return true ; } //---------------------------------------------------------------------------- bool ImportCnc::AddLine( int nLineType) { // creo la linea PtrOwner pCrvLine( CreateCurveLine()) ; if ( IsNull( pCrvLine)) return false ; // setto la linea if ( ! pCrvLine->Set( m_ptLast, m_ptNext)) return false ; // porto la linea nel riferimento del gruppo pCrvLine->ToLoc( m_frGroup) ; // inserisco la linea nel DB int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, GetToolGroup(), Release( pCrvLine)) ; if ( nId == GDB_ID_NULL) return false ; // attributi switch ( nLineType) { case L_RAPID : m_pGDB->SetMaterial( nId, COL_RAPID) ; break ; case L_LINE : m_pGDB->SetMaterial( nId, m_colCurr) ; break ; case L_ERROR : m_pGDB->SetMaterial( nId, COL_ERROR) ; m_pGDB->SetName( nId, NAME_ERROR) ; break ; } // eventuale info sul correttore (se non è riferito a zero macchina) if ( m_nComp != 0 && ! m_bZeroMach) m_pGDB->SetInfo( nId, KEY_TCOMP, m_nComp) ; // eventuale info su lato di correzione if ( m_nCompSide != NO_COMP) m_pGDB->SetInfo( nId, KEY_TCS, m_nCompSide) ; // assegnazione numero di linea m_pGDB->SetName( nId, ToString( m_nLine)) ; // assegnazione eventuale uscita if ( m_nExit != 0) { m_pGDB->SetInfo( nId, KEY_EXIT, m_nExit) ; m_nExit = 0 ; } // assegnazione eventuali assi rotanti if ( ! isnan( m_dRotAxA)) m_pGDB->SetInfo( nId, KEY_ROTAX_A, m_dRotAxA) ; if ( ! isnan( m_dRotAxB)) m_pGDB->SetInfo( nId, KEY_ROTAX_B, m_dRotAxB) ; if ( ! isnan( m_dRotAxC)) m_pGDB->SetInfo( nId, KEY_ROTAX_C, m_dRotAxC) ; // assegnazione eventuali info SetInfos( nId) ; m_vInfos.clear() ; // movimento effettuato m_ptLast = m_ptNext ; SaveRotAxes() ; return true ; } //---------------------------------------------------------------------------- bool ImportCnc::AddArc( bool bCCW) { // creo l'arco PtrOwner pCrvArc( CreateCurveArc()) ; if ( IsNull( pCrvArc)) return false ; // determino la normale al piano di interpolazione Vector3d vtN = Z_AX ; if ( m_nInterpPl == ZX) vtN = Y_AX ; else if ( m_nInterpPl == YZ) vtN = X_AX ; // se arco definito con raggio if ( m_nArcType == RADIUS) { // punti estremi, raggio e senso di rotazione if ( ! pCrvArc->Set2PNRS( m_ptLast, m_ptNext, vtN, abs( m_dRadius), bCCW)) return false ; // se raggio negativo, si deve prendere la soluzione con AngCen > 180deg if ( m_dRadius < 0) { if ( ! pCrvArc->Flip() || ! pCrvArc->ToExplementary()) return false ; } } // se arco definito con centro else if ( m_nArcType == CENTER) { // determino se valido switch ( VerifyArcCenter( vtN)) { case A_ARC : // punti estremi e centro pCrvArc.Set( GetArc2PCN( m_ptLast, m_ptNext, m_ptCen, vtN)) ; if ( IsNull( pCrvArc)) return false ; // verifico senso di rotazione if ( ( bCCW && pCrvArc->GetAngCenter() < 0) || ( ! bCCW && pCrvArc->GetAngCenter() > 0)) { if ( ! pCrvArc->ToExplementary()) return false ; } break ; case A_CIRC : // calcolo standard if ( ! SetCircC2PN( m_ptCen, m_ptLast, m_ptNext, vtN, pCrvArc)) return false ; // verifico senso di rotazione if ( ( bCCW && pCrvArc->GetAngCenter() < 0) || ( ! bCCW && pCrvArc->GetAngCenter() > 0)) { if ( ! pCrvArc->Invert()) return false ; } break ; default : return false ; } } // altrimenti errore else return false ; // porto l'arco nel riferimento del gruppo pCrvArc->ToLoc( m_frGroup) ; // inserisco l'arco nel DB int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, GetToolGroup(), Release( pCrvArc)) ; if ( nId == GDB_ID_NULL) return false ; // assegnazione del colore if ( ! m_pGDB->SetMaterial( nId, m_colCurr)) return false ; // assegnazione numero di linea m_pGDB->SetName( nId, ToString( m_nLine)) ; // assegnazione eventuale uscita if ( m_nExit != 0) { m_pGDB->SetInfo( nId, KEY_EXIT, m_nExit) ; m_nExit = 0 ; } // assegnazione eventuali assi rotanti if ( ! isnan( m_dRotAxA)) m_pGDB->SetInfo( nId, KEY_ROTAX_A, m_dRotAxA) ; if ( ! isnan( m_dRotAxB)) m_pGDB->SetInfo( nId, KEY_ROTAX_B, m_dRotAxB) ; if ( ! isnan( m_dRotAxC)) m_pGDB->SetInfo( nId, KEY_ROTAX_C, m_dRotAxC) ; // assegnazione eventuali info SetInfos( nId) ; m_vInfos.clear() ; // movimento effettuato m_ptLast = m_ptNext ; SaveRotAxes() ; return true ; } //---------------------------------------------------------------------------- bool ImportCnc::AddArc3P( bool bIs2D) { // creo l'arco PtrOwner pCrvArc( CreateCurveArc()) ; if ( IsNull( pCrvArc)) return false ; // se arco definito in 2D if ( bIs2D) { // determino la normale al piano di interpolazione Vector3d vtN = Z_AX ; if ( m_nInterpPl == ZX) vtN = Y_AX ; else if ( m_nInterpPl == YZ) vtN = X_AX ; // calcolo le proiezioni dei punti intermedio e finale nel piano del punto iniziale Point3d ptCen2D = m_ptCen - ( m_ptCen - m_ptLast) * vtN * vtN ; Point3d ptNext2D = m_ptNext - ( m_ptNext - m_ptLast) * vtN * vtN ; // punto iniziale, intermedio e finale in 2D if ( ! pCrvArc->Set3P( m_ptLast, ptCen2D, ptNext2D)) return false ; // se normale arco opposta a normale piano interpolazione, sistemo if ( ! AreSameVectorApprox( vtN, pCrvArc->GetNormVersor())) pCrvArc->InvertN() ; // aggiusto per il punto finale pCrvArc->ChangeDeltaN( ( m_ptNext - ptNext2D) * vtN) ; } // altrimenti è in 3D else { // punto iniziale, intermedio e finale if ( ! pCrvArc->Set3P( m_ptLast, m_ptCen, m_ptNext)) return false ; } // porto l'arco nel riferimento del gruppo pCrvArc->ToLoc( m_frGroup) ; // inserisco l'arco nel DB int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, GetToolGroup(), Release( pCrvArc)) ; if ( nId == GDB_ID_NULL) return false ; // assegnazione del colore if ( ! m_pGDB->SetMaterial( nId, m_colCurr)) return false ; // assegnazione numero di linea m_pGDB->SetName( nId, ToString( m_nLine)) ; // assegnazione eventuale uscita if ( m_nExit != 0) { m_pGDB->SetInfo( nId, KEY_EXIT, m_nExit) ; m_nExit = 0 ; } // assegnazione eventuali assi rotanti if ( ! isnan( m_dRotAxA)) m_pGDB->SetInfo( nId, KEY_ROTAX_A, m_dRotAxA) ; if ( ! isnan( m_dRotAxB)) m_pGDB->SetInfo( nId, KEY_ROTAX_B, m_dRotAxB) ; if ( ! isnan( m_dRotAxC)) m_pGDB->SetInfo( nId, KEY_ROTAX_C, m_dRotAxC) ; // assegnazione eventuali info SetInfos( nId) ; m_vInfos.clear() ; // movimento effettuato m_ptLast = m_ptNext ; SaveRotAxes() ; return true ; } //---------------------------------------------------------------------------- int ImportCnc::VerifyArcCenter( const Vector3d& vtN) { // calcolo il riferimento OCS derivato da vtN Frame3d frOcs ; if ( ! frOcs.Set( ORIG, vtN)) return A_ERROR ; // porto i punti in questo riferimento Point3d ptLloc = GetToLoc( m_ptLast, frOcs) ; Point3d ptNloc = GetToLoc( m_ptNext, frOcs) ; Point3d ptCloc = GetToLoc( m_ptCen, frOcs) ; Vector3d vtOloc = GetToLoc( m_vtOffs, frOcs) ; // verifico se circonferenza int nRet = ( SqDistXY( ptLloc, ptNloc) > EPS_SMALL * EPS_SMALL) ? A_ARC : A_CIRC ; // se controllo Fanuc o Fagor, centro è sempre in relativo if ( m_nCNC == CNC_FANUC || m_nCNC == CNC_FAGOR) { // centro in relativo Point3d ptCrl = ptCloc + ptLloc ; double dRadLast = DistXY( ptLloc, ptCrl) ; double dRadNext = DistXY( ptNloc, ptCrl) ; if ( abs( dRadNext - dRadLast) < 100 * EPS_SMALL) { m_ptCen = GetToGlob( ptCrl, frOcs) ; return nRet ; } } // se coordinate in assoluto prima verifico in assoluto else if ( m_bAbsCoord) { // centro in assoluto Point3d ptCas = ptCloc + vtOloc ; double dRadCasLast = DistXY( ptLloc, ptCas) ; double dRadCasNext = DistXY( ptNloc, ptCas) ; // centro in relativo Point3d ptCrl = ptCloc + ptLloc ; double dRadCrlLast = DistXY( ptLloc, ptCrl) ; double dRadCrlNext = DistXY( ptNloc, ptCrl) ; // controlli con precisione più elevata if ( abs( dRadCasNext - dRadCasLast) < 10 * EPS_SMALL) { m_ptCen += m_vtOffs ; return nRet ; } if ( abs( dRadCrlNext - dRadCrlLast) < 10 * EPS_SMALL) { m_ptCen = GetToGlob( ptCrl, frOcs) ; return nRet ; } // controlli con precisione più bassa if ( abs( dRadCasNext - dRadCasLast) < 100 * EPS_SMALL) { m_ptCen += m_vtOffs ; return nRet ; } if ( abs( dRadCrlNext - dRadCrlLast) < 100 * EPS_SMALL) { m_ptCen = GetToGlob( ptCrl, frOcs) ; return nRet ; } } // altrimenti coordinate in relativo e prima provo queste else { // centro in relativo Point3d ptCrl = ptCloc + ptLloc ; double dRadCrlLast = DistXY( ptLloc, ptCrl) ; double dRadCrlNext = DistXY( ptNloc, ptCrl) ; // centro in assoluto Point3d ptCas = ptCloc + vtOloc ; double dRadCasLast = DistXY( ptLloc, ptCas) ; double dRadCasNext = DistXY( ptNloc, ptCas) ; // controlli con precisione più elevata if ( abs( dRadCrlNext - dRadCrlLast) < 10 * EPS_SMALL) { m_ptCen = GetToGlob( ptCrl, frOcs) ; return nRet ; } if ( abs( dRadCasNext - dRadCasLast) < 10 * EPS_SMALL) { m_ptCen += m_vtOffs ; return nRet ; } // controlli con precisione più bassa if ( abs( dRadCrlNext - dRadCrlLast) < 100 * EPS_SMALL) { m_ptCen = GetToGlob( ptCrl, frOcs) ; return nRet ; } if ( abs( dRadCasNext - dRadCasLast) < 100 * EPS_SMALL) { m_ptCen += m_vtOffs ; return nRet ; } } return A_ERROR ; } //---------------------------------------------------------------------------- bool ImportCnc::SetCircC2PN( const Point3d& ptCen, const Point3d& ptStart, const Point3d& ptNearEnd, const Vector3d& vtN, ICurveArc* pCrvArc) { // calcolo il riferimento OCS derivato da vtN Frame3d frOcs ; if ( ! frOcs.Set( ORIG, vtN)) return false ; // porto i punti in questo riferimento Point3d ptCloc = GetToLoc( ptCen, frOcs) ; Point3d ptSloc = GetToLoc( ptStart, frOcs) ; Point3d ptNEloc = GetToLoc( ptNearEnd, frOcs) ; // calcolo il cerchio in questo piano double dRad = 0.5 * ( DistXY( ptCloc, ptSloc) + DistXY( ptCloc, ptNEloc)) ; ptCloc.z = ptSloc.z ; Vector3d vtS = ptSloc - ptCloc ; if ( ! pCrvArc->Set( ptCloc, Z_AX, dRad, vtS, ANG_FULL, ptNEloc.z - ptSloc.z)) return false ; // riporto l'arco nel riferimento naturale return pCrvArc->ToGlob( frOcs) ; } //---------------------------------------------------------------------------- int ImportCnc::GetToolGroup( void) { // assegno il nome dell'utensile string sTool = "T" + ToString( m_nTool, 2) ; // se trovo un gruppo con il nome dell'utensile, ne restituisco l'Id if ( m_nFirstGroup != GDB_ID_NULL) { string sName ; if ( m_pGDB->GetName( m_nFirstGroup, sName) && sName == sTool) return m_nFirstGroup ; int nId = m_pGDB->GetNextName( m_nFirstGroup, sTool) ; if ( nId != GDB_ID_NULL) return nId ; } // inserisco un nuovo layer nel DB geometrico int nId = m_pGDB->AddGroup( GDB_ID_NULL, m_nIdGroup, GLOB_FRM) ; if ( nId == GDB_ID_NULL) return GDB_ID_NULL ; // assegnazione nome if ( ! m_pGDB->SetName( nId, sTool)) return GDB_ID_NULL ; // se definito nome utensile, assegno info relativa if ( ! m_sToolName.empty()) m_pGDB->SetInfo( nId, KEY_TNAME, m_sToolName) ; m_sToolName.clear() ; // se definita posizione utensile, assegno info relativa if ( ! m_sToolPos.empty()) m_pGDB->SetInfo( nId, KEY_TPOS, m_sToolPos) ; m_sToolPos.clear() ; // se definita seconda posizione utensile, assegno info relativa if ( ! m_sToolPos2.empty()) m_pGDB->SetInfo( nId, KEY_TPOS2, m_sToolPos2) ; m_sToolPos2.clear() ; // se definita speed utensile, assegno info relativa if ( ! m_sSpeed.empty()) m_pGDB->SetInfo( nId, KEY_SPEED, m_sSpeed) ; m_sSpeed.clear() ; // se è il primo, lo salvo if ( m_nFirstGroup == GDB_ID_NULL) m_nFirstGroup = nId ; return nId ; } //---------------------------------------------------------------------------- bool ImportCnc::PostProcess( void) { // se richiesto concatenamento dei percorsi if ( ( m_nFlag & EICFLAG_CHAIN) != 0) { // gestore di curva composita PtrOwner pCompo ; // ciclo sui gruppi int nGroupId = m_nFirstGroup ; while ( nGroupId != GDB_ID_NULL) { // ciclo sulle entità del gruppo Color cCol ; int nComp = 0 ; int nCompSide = 0 ; int nId = m_pGDB->GetFirstInGroup( nGroupId) ; while ( nId != GDB_ID_NULL) { // leggo eventuali info correttore utensile int nTcomp = 0 ; m_pGDB->GetInfo( nId, KEY_TCOMP, nTcomp) ; // leggo eventuali info di correzione raggio utensile int nTcs = 0 ; m_pGDB->GetInfo( nId, KEY_TCS, nTcs) ; // se curva e G40/G41/G42 o non rapido, la aggiungo alla composita if ( ( m_pGDB->GetGeoType( nId) & GEO_CURVE) != 0 && ( nTcs == 40 || nTcs == 41 || nTcs == 42 || ! IsRapid( nId))) { // se G41 o G42 termino eventuale precedente composita if ( ( nTcs == 41 || nTcs == 42) && ! IsNull( pCompo) && pCompo->GetCurveCount() > 0) { if ( ! InsertCurveComposite( Release( pCompo), cCol, nComp, nCompSide, nId, GDB_BEFORE)) return false ; } // se non c'è la composita, la creo ed assegno colore e lato di lavoro if ( IsNull( pCompo)) { pCompo.Set( CreateCurveComposite()) ; if ( IsNull( pCompo)) return false ; m_pGDB->GetMaterial( nId, cCol) ; // considero inserimento correttore sempre in feed if ( ( nTcs == 41 || nTcs == 42) && cCol == COL_RAPID) cCol = BLACK ; nComp = nTcomp ; nCompSide = nTcs ; } // calcolo prossimo Id int nNextId = m_pGDB->GetNext( nId) ; // estraggo la curva e la accodo alla composita ICurve* pCrv = GetCurve( m_pGDB->RemoveGeoObjAndErase( nId)) ; if ( ! pCompo->AddCurve( pCrv, true, 10 * EPS_SMALL)) return false ; // passo alla successiva nId = nNextId ; // se G40 termino la composita if ( nTcs == 40) { if ( nId != GDB_ID_NULL) { if ( ! InsertCurveComposite( Release( pCompo), cCol, nComp, nCompSide, nId, GDB_BEFORE)) return false ; } else { if ( ! InsertCurveComposite( Release( pCompo), cCol, nComp, nCompSide, nGroupId, GDB_LAST_SON)) return false ; } } } // altrimenti else { // se c'è curva in costruzione con qualcosa, la salvo if ( ! IsNull( pCompo) && pCompo->GetCurveCount() > 0) { if ( ! InsertCurveComposite( Release( pCompo), cCol, nComp, nCompSide, nId, GDB_BEFORE)) return false ; } // passo alla successiva nId = m_pGDB->GetNext( nId) ; } } // se c'è curva in costruzione con qualcosa, la salvo if ( ! IsNull( pCompo) && pCompo->GetCurveCount() > 0) { if ( ! InsertCurveComposite( Release( pCompo), cCol, nComp, nCompSide, nGroupId, GDB_LAST_SON)) return false ; } // passo al gruppo successivo nGroupId = m_pGDB->GetNextGroup( nGroupId) ; } } // se richiesta eliminazione dei movimenti in rapido if ( ( m_nFlag & EICFLAG_SKIP_RAPID) != 0) { // ciclo sui gruppi int nGroupId = m_nFirstGroup ; while ( nGroupId != GDB_ID_NULL) { // ciclo sulle entità del gruppo int nId = m_pGDB->GetFirstInGroup( nGroupId) ; while ( nId != GDB_ID_NULL) { // se movimento in rapido, lo cancello if ( IsRapid( nId)) { int nNextId = m_pGDB->GetNext( nId) ; m_pGDB->Erase( nId) ; nId = nNextId ; } // altrimenti passo oltre else nId = m_pGDB->GetNext( nId) ; } // passo al gruppo successivo nGroupId = m_pGDB->GetNextGroup( nGroupId) ; } } return true ; } //---------------------------------------------------------------------------- bool ImportCnc::IsRapid( int nId) { Color cCol ; return ( m_pGDB != nullptr && m_pGDB->GetMaterial( nId, cCol) && cCol == COL_RAPID) ; } //---------------------------------------------------------------------------- bool ImportCnc::InsertCurveComposite( ICurveComposite* pCompo, Color cCol, int nComp, int nSide, int nRefId, int nSonBeforeAfter) { int nCmpId = m_pGDB->InsertGeoObj( GDB_ID_NULL, nRefId, nSonBeforeAfter, pCompo) ; if ( nCmpId == GDB_ID_NULL) return false ; m_pGDB->SetMaterial( nCmpId, cCol) ; if ( nComp != 0) m_pGDB->SetInfo( nCmpId, KEY_TCOMP, nComp) ; if ( nSide != 0) m_pGDB->SetInfo( nCmpId, KEY_TCS, nSide) ; return true ; } //---------------------------------------------------------------------------- bool ImportCnc::SetInfos( int nId) { for ( int i = 0, j = 1 ; i < int( m_vInfos.size()) ; ++ i) { string sKey, sVal ; SplitFirst( m_vInfos[i], "=", sKey, sVal) ; if ( ! sKey.empty() && ! sVal.empty()) m_pGDB->SetInfo( nId, sKey, sVal) ; else m_pGDB->SetInfo( nId, KEY_INFO + ToString( j ++), m_vInfos[i]) ; } return true ; }