//---------------------------------------------------------------------------- // EgalTech 2014-2014 //---------------------------------------------------------------------------- // File : ImportCnc.cpp Data : 15.09.14 Versione : 1.5i3 // Contenuto : Implementazione della classe per l'importazione di CNC. // // // // Modifiche : 15.09.14 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- 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/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 ; //---------------------------------------------------------------------------- IImportCnc* CreateImportCnc( void) { // verifico la chiave e le opzioni if ( ! TestKeyForEEx( GetEExKey(), KEYOPT_EEX_INPBASE, GetEExLogger())) return false ; // creo l'oggetto return static_cast ( new(nothrow) ImportCnc) ; } //---------------------------------------------------------------------------- bool ImportCnc::Import( const string& sFile, IGeomDB* pGDB, int nIdGroup) { // 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 ; } // inizializzo lo scanner Scanner TheScanner ; if ( ! TheScanner.Init( sFile, "")) { LOG_ERROR( GetEExLogger(), "ImportCnc : Error on Init") return false ; } // inizializzo lo stato m_bToMove = false ; m_nTool = 0 ; m_nNextTool = 0 ; m_nMoveType = RAPID ; m_nCharsOn = 0 ; m_bAbsCoord = true ; m_nInterpPl = XY ; m_nArcType = NONE ; m_ptLast = ORIG ; m_ptNext = ORIG ; m_ptCen = ORIG ; m_vtOffs = V_NULL ; m_dRadius = 0 ; m_colCurr = BLACK ; // ciclo di lettura delle linee bool bOk = true ; string sLine ; while ( TheScanner.GetLine( sLine)) { if ( ! ProcessLine( sLine)) { bOk = false ; string sErr = "ImportCnc : Error on line " + ToString( TheScanner.GetCurrLineNbr()) ; LOG_ERROR( GetEExLogger(), sErr.c_str()) } } return bOk ; } //---------------------------------------------------------------------------- bool ImportCnc::ProcessLine( const string& sLine) { // eventuale gestione linea di commento if ( sLine[0] == '(' || sLine[0] == ';') return ParseRemark( sLine) ; // altre linee da saltare if ( sLine[0] == '$') return true ; // divido la linea in parti STRVECTOR vsTokens ; Tokenize( sLine, "NGXYZIJKRUVWABCFTMH", 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 'R' : ParseR( vsTokens[i]) ; break ; case 'C' : ParseC( vsTokens[i]) ; break ; case 'T' : ParseT( vsTokens[i]) ; break ; case 'M' : ParseM( vsTokens[i]) ; break ; } } // se comando di movimento o riconosciuto movimento, lo eseguo if ( m_nCommand == MOVE || m_bToMove) return ExecMovement() ; // se comando di impostazione piano di interpolazione else if ( m_nCommand == IPL) return ExecSetIPL() ; // reset stato comandi m_nCommand = NO_CMD ; m_nCharsOn = 0 ; m_bToMove = false ; m_nArcType = NONE ; return true ; } //---------------------------------------------------------------------------- bool ImportCnc::Tokenize( const string& sString, const string& sHeaders, STRVECTOR& vsTokens) { string::size_type iPosStart ; string::size_type iPosEnd ; // pulisco il risultato vsTokens.clear() ; // parto dall'inizio iPosStart = ( sString.empty() ? string::npos : sString.find_first_of( sHeaders, 0)) ; // mentre esiste un nuovo inizio di token while ( iPosStart != string::npos) { // cerco il successivo carattere di intestazione iPosEnd = sString.find_first_of( sHeaders, iPosStart + 1) ; // aggiungo il token al vettore vsTokens.push_back( sString.substr( iPosStart, iPosEnd - iPosStart)) ; // cerco l'inizio di un nuovo token iPosStart = iPosEnd ; } return true ; } //---------------------------------------------------------------------------- bool ImportCnc::ParseRemark( const string& sLine) { // cerco indicazione di posizione Home string::size_type iFrom = sLine.find( "FROM/") ; if ( iFrom != string::npos) { Point3d ptHome ; if ( FromString( sLine.substr( iFrom + 5), ptHome)) { m_ptLast = ptHome ; m_ptNext = m_ptLast ; } return true ; } // cerco indicazione di colore string::size_type 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 ; } 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 16 : m_nCommand = IPL ; break ; case 17 : m_nInterpPl = XY ; break ; case 18 : m_nInterpPl = ZX ; break ; case 19 : m_nInterpPl = YZ ; break ; case 54 : case 55 : case 56 : case 57 : m_vtOffs = V_NULL ; break ; case 58 : case 59 : m_nCommand = OFFS ; m_vtOffs = V_NULL ; break ; case 90 : m_bAbsCoord = true ; break ; case 91 : m_bAbsCoord = false ; break ; } return true ; } //---------------------------------------------------------------------------- bool ImportCnc::ParseX( const string& sToken) { double dVal ; int nStart = ( sToken[1] == '=' ? 2 : 1) ; if ( ! FromString( sToken.substr( nStart), dVal)) dVal = 0 ; switch ( m_nCommand) { case IPL : break ; case OFFS : m_vtOffs.x = dVal ; break ; default : 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 ; switch ( m_nCommand) { case IPL : break ; case OFFS : m_vtOffs.y = dVal ; break ; default : 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 ; switch ( m_nCommand) { case IPL : break ; case OFFS : m_vtOffs.z = dVal ; break ; default : 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 ; m_ptCen.x = dVal ; m_nArcType = CENTER ; return true ; } //---------------------------------------------------------------------------- bool ImportCnc::ParseJ( const string& sToken) { double dVal ; int nStart = ( sToken[1] == '=' ? 2 : 1) ; if ( ! FromString( sToken.substr( nStart), dVal)) dVal = 0 ; m_ptCen.y = dVal ; m_nArcType = CENTER ; return true ; } //---------------------------------------------------------------------------- bool ImportCnc::ParseK( const string& sToken) { double dVal ; int nStart = ( sToken[1] == '=' ? 2 : 1) ; if ( ! FromString( sToken.substr( nStart), dVal)) dVal = 0 ; m_ptCen.z = dVal ; m_nArcType = CENTER ; return true ; } //---------------------------------------------------------------------------- bool ImportCnc::ParseR( const string& sToken) { double dVal ; int nStart = ( sToken[1] == '=' ? 2 : 1) ; if ( ! FromString( sToken.substr( nStart), dVal)) dVal = 0 ; m_dRadius = dVal ; m_nArcType = RADIUS ; return true ; } //---------------------------------------------------------------------------- bool ImportCnc::ParseC( const string& sToken) { // cerco l'impostazione del raggio con CR= (Siemens) if ( sToken.find( "CR=") != 0) return true ; double dVal ; int nStart = 3 ; if ( ! FromString( sToken.substr( nStart), dVal)) dVal = 0 ; m_dRadius = dVal ; m_nArcType = RADIUS ; 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_nTool = m_nNextTool ; 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) { switch ( m_nMoveType) { case RAPID : return AddLine( L_RAPID) ; case LINE : 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() ; else AddLine(L_ERROR) ; return false ; } return false ; } //---------------------------------------------------------------------------- bool ImportCnc::AddPoint( void) { // creo il punto PtrOwner pGeoPnt( CreateGeoPoint3d()) ; if ( IsNull( pGeoPnt)) return false ; // setto il puto if ( ! pGeoPnt->Set( 0.5 * ( m_ptLast + m_ptNext))) return false ; // porto la linea nel riferimento del gruppo pGeoPnt->ToLoc( m_frGroup) ; // inserisco il punto nel DB int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, GetToolGroup( m_nTool), Release( pGeoPnt)) ; if ( nId == GDB_ID_NULL) return false ; // attributi m_pGDB->SetMaterial( nId, RED) ; m_pGDB->SetName( nId, "Error") ; // movimento effettuato m_ptLast = m_ptNext ; return true ; } //---------------------------------------------------------------------------- bool ImportCnc::AddLine( int nLineType) { // se la linea è nulla, non la inserisco ma proseguo senza errore if ( AreSamePointApprox( m_ptLast, m_ptNext)) return true ; // 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( m_nTool), Release( pCrvLine)) ; if ( nId == GDB_ID_NULL) return false ; // attributi switch ( nLineType) { case L_RAPID : m_pGDB->SetMaterial( nId, Color( 0, 192, 192)) ; break ; case L_LINE : m_pGDB->SetMaterial( nId, m_colCurr) ; break ; case L_ERROR : m_pGDB->SetMaterial( nId, RED) ; m_pGDB->SetName( nId, "Error") ; break ; } // movimento effettuato m_ptLast = m_ptNext ; 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, fabs( 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 if ( ! pCrvArc->SetC2PN( m_ptCen, m_ptLast, m_ptNext, vtN)) return false ; break ; case A_CIRC : // calcolo standard if ( ! SetCircC2PN( m_ptCen, m_ptLast, m_ptNext, vtN, Get( pCrvArc))) return false ; break ; default : return false ; } // verifico senso di rotazione if ( ( bCCW && pCrvArc->GetAngCenter() < 0) || ( ! bCCW && pCrvArc->GetAngCenter() > 0)) { if ( ! pCrvArc->ToExplementary()) 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( m_nTool), Release( pCrvArc)) ; if ( nId == GDB_ID_NULL) return false ; // assegnazione del colore if ( ! m_pGDB->SetMaterial( nId, m_colCurr)) return false ; // movimento effettuato m_ptLast = m_ptNext ; 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 = m_ptLast ; ptLloc.ToLoc( frOcs) ; Point3d ptNloc = m_ptNext ; ptNloc.ToLoc( frOcs) ; Point3d ptCloc = m_ptCen ; ptCloc.ToLoc( frOcs) ; Vector3d vtOloc = m_vtOffs ; vtOloc.ToLoc( frOcs) ; // verifico se circonferenza int nRet = ( SqDistXY( ptLloc, ptNloc) > EPS_SMALL * EPS_SMALL) ? A_ARC : A_CIRC ; // se coordinate in assoluto prima verifico in assoluto if ( m_bAbsCoord) { // centro in assoluto Point3d ptCas = ptCloc + vtOloc ; double dRadLast = DistXY( ptLloc, ptCas) ; double dRadNext = DistXY( ptNloc, ptCas) ; if ( fabs ( dRadNext - dRadLast) < 10 * EPS_SMALL) { m_ptCen += m_vtOffs ; return nRet ; } // centro in relativo Point3d ptCrl = ptCloc + ptLloc ; dRadLast = DistXY( ptLloc, ptCrl) ; dRadNext = DistXY( ptNloc, ptCrl) ; if ( fabs ( dRadNext - dRadLast) < 10 * EPS_SMALL) { m_ptCen = ptCrl ; m_ptCen.ToGlob( frOcs) ; return nRet ; } } // altrimenti coordinate in relativo e prima provo queste else { // centro in relativo Point3d ptCrl = ptCloc + ptLloc ; double dRadLast = DistXY( ptLloc, ptCrl) ; double dRadNext = DistXY( ptNloc, ptCrl) ; if ( fabs ( dRadNext - dRadLast) < 10 * EPS_SMALL) { m_ptCen = ptCrl ; m_ptCen.ToGlob( frOcs) ; return nRet ; } // centro in assoluto Point3d ptCas = ptCloc + vtOloc ; dRadLast = DistXY( ptLloc, ptCas) ; dRadNext = DistXY( ptNloc, ptCas) ; if ( fabs ( dRadNext - dRadLast) < 10 * 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 = ptCen ; ptCloc.ToLoc( frOcs) ; Point3d ptSloc = ptStart ; ptSloc.ToLoc( frOcs) ; Point3d ptNEloc = ptNearEnd ; ptNEloc.ToLoc( 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( int nTool) { // assegno il nome dell'utensile string sTool = "T" + ToString( nTool, 2) ; // se trovo un gruppo con il nome dell'utensile, ne restituisco l'Id PtrOwner pIter( CreateGdbIterator( m_pGDB)) ; if ( IsNull( pIter)) return false ; for ( bool bNext = pIter->GoToFirstInGroup( m_nIdGroup) ; bNext ; bNext = pIter->GoToNext()) { string sName ; if ( pIter->GetName( sName) && sName == sTool) return pIter->GetId() ; } // 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 ; return nId ; }