//---------------------------------------------------------------------------- // EgalTech 2014-2014 //---------------------------------------------------------------------------- // File : ImportDxfBlocks.cpp Data : 20.05.14 Versione : 1.5e4 // Contenuto : Implementazione di ImportDxf : gestione dei blocchi. // // // // Modifiche : 20.05.14 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "ImportDxf.h" #include "DxfConst.h" #include "DllMain.h" #include "/EgtDev/Include/EgtPointerOwner.h" #include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EGkGdbIterator.h" #include "/EgtDev/Include/EGnStringKeyVal.h" using namespace std ; //---------------------------------------------------------------------------- bool ImportDxf::ReadBlocks( bool& bFileEnd) { // ciclo di lettura bool bOk = true ; bool bSectEnd = false ; string sEntName ; do { // leggo intestazione entità, per avere il tipo bool bOkLoc = GetEntityName( sEntName, bSectEnd, bFileEnd) ; if ( bOkLoc && ! bSectEnd) { // se Blocco if ( sEntName == "BLOCK") { if ( ! ReadBlock( bFileEnd)) bOkLoc = false ; } // se Fine Blocco else if ( sEntName == "ENDBLK") { if ( ! ReadEndBlock( bFileEnd)) bOkLoc = false ; } // se Entità else if ( ReadOneEntity( sEntName, bOkLoc, bFileEnd)) ; // altrimenti ... else { string sOut = "ImportDxf : Skip entity " + sEntName + " at line " + ToString( m_theScanner.GetCurrLineNbr()) ; LOG_WARN( GetEExLogger(), sOut.c_str()) if ( ! SkipEntity( bFileEnd)) bOkLoc = false ; } } // gestisco eventuale errore if ( ! bOkLoc) { bOk = false ; string sOut = "ImportDxf : Error on line " + ToString( m_theScanner.GetCurrLineNbr()) ; LOG_ERROR( GetEExLogger(), sOut.c_str()) } } while ( ! bSectEnd) ; // risolvo eventuali riferimenti in sospeso a blocchi SolveBlockReferences() ; return bOk ; } //---------------------------------------------------------------------------- bool ImportDxf::ReadBlock( bool& bFileEnd) { Point3d ptP ; string sName ; string sLayer ; int nFlags = 0 ; // ciclo di lettura degli item della linea bFileEnd = false ; int nCode = CODE_NULL ; do { // leggo un Item nCode = ReadNextItem() ; if ( nCode == CODE_NULL) { bFileEnd = true ; return false ; } // eventuale gestione switch ( nCode) { case 2 : sName = m_sCurrItem ; break ; case 8 : sLayer = m_sCurrItem ; break ; case 10 : FromString( m_sCurrItem, ptP.x) ; break ; case 20 : FromString( m_sCurrItem, ptP.y) ; break ; case 30 : FromString( m_sCurrItem, ptP.z) ; break ; case 70 : FromString( m_sCurrItem, nFlags) ; break ; } } while ( nCode != 0) ; UngetItem() ; // eventuale aggiustamento del nome per caratteri non ammessi ValidateVal( sName) ; // eventuale aggiustamento del nome del layer per caratteri non ammessi ValidateVal( sLayer) ; // aggiusto per il fattore di scala ptP *= m_dScaleFactor ; // inserisco il blocco nel DB geometrico m_nIdCurrBlock = m_pGDB->AddGroup( GDB_ID_NULL, m_nIdBlocksParent, GLOB_FRM) ; if ( m_nIdCurrBlock == GDB_ID_NULL) return false ; // aggiorno Map dei Blocchi m_nmBlock.insert( NameMap::value_type( sName, m_nIdCurrBlock)) ; // assegnazione nome if ( ! m_pGDB->SetName( m_nIdCurrBlock, sName)) return false ; // assegnazione layer if ( ! sLayer.empty()) { if ( ! m_pGDB->SetInfo( m_nIdCurrBlock, LAYER_INFO, sLayer)) return false ; } // assegnazione punto di inserimento if ( ! m_pGDB->SetInfo( m_nIdCurrBlock, POINT_INFO, ptP)) return false ; // assegnazione flags if ( ! m_pGDB->SetInfo( m_nIdCurrBlock, FLAGS_INFO, nFlags)) return false ; // reset numero blocchi inseriti ma non risolti nel blocco corrente m_nNumNotBokInCurrBlock = 0 ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::ReadEndBlock( bool& bFileEnd) { if ( ! SkipEntity( bFileEnd)) return false ; if ( m_nNumNotBokInCurrBlock == 0) m_pGDB->SetInfo( m_nIdCurrBlock, BLKOK_INFO, 1) ; m_nIdCurrBlock = GDB_ID_NULL ; return true ; } //---------------------------------------------------------------------------- int ImportDxf::GetBlockId( const string& sName) { // se trovo il blocco nel map, ne restituisco l'Id NameMap::iterator Iter = m_nmBlock.find( sName) ; if ( Iter != m_nmBlock.end()) return Iter->second ; // altrimenti blocco non trovato return GDB_ID_NULL ; } //---------------------------------------------------------------------------- bool ImportDxf::SolveBlockReferences( void) { // creo gli iteratori PtrOwner pIBlo( CreateGdbIterator( m_pGDB)) ; if ( IsNull( pIBlo)) return false ; PtrOwner pIEnt( CreateGdbIterator( m_pGDB)) ; if ( IsNull( pIEnt)) return false ; // si ripete più volte, fino a completa soluzione o max iterazioni const int MAX_ITER = 5 ; bool bAllBok = false ; for ( int nIter = 0 ; ! bAllBok && nIter < MAX_ITER ; ++ nIter) { bAllBok = true ; // ciclo sui blocchi bool bBlo = pIBlo->GoToFirstInGroup( m_nIdBlocksParent) ; while ( bBlo) { // ciclo sulle entità di ogni blocco bool bBok = true ; bool bEnt = pIEnt->GoToFirstInGroup( *pIBlo) ; while ( bEnt) { // se gruppo di inserimento di altro blocco if ( pIEnt->GetGdbType() == GDB_TY_GROUP) { // recupero i dati InsertData insData ; if ( ! LoadInsertInfo( pIEnt->GetId(), insData)) return false ; // recupero l'identificativo del blocco da inserire int nIdIns = GetBlockId( insData.sName) ; if ( nIdIns == GDB_ID_NULL) return false ; // se blocco non ancora risolto, lascio come è if ( ! m_pGDB->ExistsInfo( nIdIns, BLKOK_INFO)) { bBok = false ; bAllBok = false ; bEnt = pIEnt->GoToNext() ; } // altrimenti, eseguo l'inserimento else { if ( ! InsertBlockInBlock( pIEnt->GetId(), nIdIns, insData)) return false ; // cancello il gruppo e passo all'oggetto successivo bEnt = pIEnt->EraseAndGoToNext() ; } } else bEnt = pIEnt->GoToNext() ; } // eventuale marcatura di blocco risolto if ( bBok) m_pGDB->SetInfo( pIBlo->GetId(), BLKOK_INFO, 1) ; // passo al blocco successivo bBlo = pIBlo->GoToNext() ; } } return true ; } //---------------------------------------------------------------------------- bool ImportDxf::SaveInsertInfo( int nId, const InsertData& insData) { if ( ! m_pGDB->SetName( nId, insData.sName)) return false ; if ( ! m_pGDB->SetInfo( nId, LAYER_INFO, insData.sLayer)) return false ; if ( ! m_pGDB->SetInfo( nId, POINT_INFO, insData.ptP)) return false ; if ( ! m_pGDB->SetInfo( nId, VTEXT_INFO, insData.vtExtr)) return false ; if ( ! m_pGDB->SetInfo( nId, ROTAT_INFO, insData.dRotAngDeg)) return false ; if ( ! m_pGDB->SetInfo( nId, SCALE_INFO, insData.vtScale)) return false ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::LoadInsertInfo( int nId, InsertData& insData) { if ( ! m_pGDB->GetName( nId, insData.sName)) return false ; if ( ! m_pGDB->GetInfo( nId, LAYER_INFO, insData.sLayer)) return false ; if ( ! m_pGDB->GetInfo( nId, POINT_INFO, insData.ptP)) return false ; if ( ! m_pGDB->GetInfo( nId, VTEXT_INFO, insData.vtExtr)) return false ; if ( ! m_pGDB->GetInfo( nId, ROTAT_INFO, insData.dRotAngDeg)) return false ; if ( ! m_pGDB->GetInfo( nId, SCALE_INFO, insData.vtScale)) return false ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::InsertBlockInBlock( int nIdDest, int nIdIns, const InsertData& insData) { // recupero il punto base del blocco di inserimento per determinare lo spostamento Point3d ptBase ; m_pGDB->GetInfo( nIdIns, POINT_INFO, ptBase) ; Vector3d vtMove = insData.ptP - ptBase ; // calcolo il riferimento OCS Frame3d frOCS ; if ( ! AreSameVectorExact( insData.vtExtr, Z_AX)) { if ( ! frOCS.Set( ORIG, insData.vtExtr)) return false ; } // copio tutte le entità del blocco, trasformandole opportunamente PtrOwner pIEnt( CreateGdbIterator( m_pGDB)) ; if ( IsNull( pIEnt)) return false ; bool bFound = pIEnt->GoToFirstInGroup( nIdIns) ; while ( bFound) { // copio l'entità geometrica IGeoObj* pGeoS = pIEnt->GetGeoObj() ; if ( pGeoS == nullptr) { string sOut = "ImportDxf : Block solve error" ; LOG_ERROR( GetEExLogger(), sOut.c_str()) bFound = pIEnt->GoToNext() ; continue ; } PtrOwner pGeo( pGeoS->Clone()) ; if ( IsNull( pGeo)) return false ; // inserisco l'entità nel DB int nIdE = m_pGDB->InsertGeoObj( GDB_ID_NULL, nIdDest, GDB_BEFORE, Release( pGeo)) ; if ( nIdE == GDB_ID_NULL) return false ; // eseguo le opportune trasformazioni m_pGDB->Scale( nIdE, Frame3d( ptBase), insData.vtScale.x, insData.vtScale.y, insData.vtScale.z) ; m_pGDB->Rotate( nIdE, ptBase, Z_AX, insData.dRotAngDeg) ; m_pGDB->Translate( nIdE, vtMove) ; m_pGDB->GetGeoObj( nIdE)->ToGlob( frOCS) ; // recupero il colore if ( ! SetColorForInsert( nIdE, pIEnt->GetId(), insData.sLayer)) return false ; // passo alla successiva bFound = pIEnt->GoToNext() ; } return true ; }