//---------------------------------------------------------------------------- // EgalTech 2014-2014 //---------------------------------------------------------------------------- // File : ExportDxf.cpp Data : 07.08.14 Versione : 1.5h2 // Contenuto : Implementazione della classe per l'esportazione in formato DXF. // // // // Modifiche : 07.08.14 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "ExportDxf.h" #include "DxfConst.h" #include "DxfColors.h" #include "DllMain.h" #include "/EgtDev/Include/EExDllMain.h" #include "/EgtDev/Include/EGkGeomDB.h" #include "/EgtDev/Include/EGkGdbIterator.h" #include "/EgtDev/Include/EGkGeoPoint3d.h" #include "/EgtDev/Include/EGkGeoVector3d.h" #include "/EgtDev/Include/EGkCurveLine.h" #include "/EgtDev/Include/EGkCurveArc.h" #include "/EgtDev/Include/EGkCurveBezier.h" #include "/EgtDev/Include/EGkCurveComposite.h" #include "/EgtDev/Include/EGkCurveAux.h" #include "/EgtDev/Include/EGkSurfFlatRegion.h" #include "/EgtDev/Include/EGkSurfTriMesh.h" #include "/EgtDev/Include/EGkExtText.h" #include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EGnStringUtils.h" #include "/EgtDev/Include/EGnFileUtils.h" #include "/EgtDev/Include/SELkKeyProc.h" #include "/EgtDev/Include/EgtKeyCodes.h" #include "/EgtDev/Include/EgtStringConverter.h" #include "/EgtDev/Include/EgtStringDecoder.h" #include "/EgtDev/Include/EgtPointerOwner.h" using namespace std ; //---------------------------------------------------------------------------- IExportDxf* CreateExportDxf( void) { // verifico la chiave e le opzioni if ( ! TestKeyForEEx( GetEExKey(), KEYOPT_EEX_EXPBASE, GetEExLogger())) return false ; // creo l'oggetto return static_cast ( new(nothrow) ExportDxf) ; } //---------------------------------------------------------------------------- bool ExportDxf::SetOptions( int nFilter, int nFlag) { m_nFilter = nFilter ; m_bCompoundLayer = ( nFlag & EEXFLAG_COMP_LAYER) ; return true ; } //---------------------------------------------------------------------------- bool ExportDxf::Export( IGeomDB* pGDB, int nId, const string& sFile) { // verifico il DB geometrico if ( pGDB == nullptr) { LOG_ERROR( GetEExLogger(), "ExportDxf : Error on GeomDB") return false ; } // verifico l'Id dell'oggetto da esportare if ( ! pGDB->ExistsObj( nId)) { LOG_ERROR( GetEExLogger(), "ExportDxf : Error on Id") return false ; } // apro il file di testo in scrittura m_OutFile.open( stringtoW( sFile), ios::out, _SH_DENYWR) ; if ( ! m_OutFile.good()) { LOG_ERROR( GetEExLogger(), "ExportDxf : Error on open file") return false ; } bool bOk = true ; // scrivo la sezione di intestazione if ( ! ExportHeader( pGDB, nId)) bOk = false ; // scrivo la sezione tavole if ( ! ExportTables( pGDB, nId)) bOk = false ; // scrivo la sezione entità if ( ! ExportEntities( pGDB, nId)) bOk = false ; // terminazione file if ( ! WriteItem( 0, "EOF")) bOk = false ; // chiudo il file if ( ! m_OutFile.good() || ! m_OutFile.is_open()) bOk = false ; if ( m_OutFile.is_open()) m_OutFile.close() ; return bOk ; } //---------------------------------------------------------------------------- bool ExportDxf::ExportHeader( IGeomDB* pGDB, int nId) { // intestazione sezione header if ( ! WriteItem( 0, "SECTION") || ! WriteItem( 2, "HEADER")) return false ; // versione DXF if ( ! WriteItem( 9, "$ACADVER") || ! WriteItem( 1, "AC1009")) return false ; // estensione BBox3d b3Glob ; if ( ! pGDB->GetGlobalBBox( nId, b3Glob)) return false ; if ( ! WriteItem( 9, "$EXTMIN") || ! WriteItem( 10, b3Glob.GetMin().x) || ! WriteItem( 20, b3Glob.GetMin().y) || ! WriteItem( 30, b3Glob.GetMin().z)) return false ; if ( ! WriteItem( 9, "$EXTMAX") || ! WriteItem( 10, b3Glob.GetMax().x) || ! WriteItem( 20, b3Glob.GetMax().y) || ! WriteItem( 30, b3Glob.GetMax().z)) return false ; // terminazione sezione header if ( ! WriteItem( 0, "ENDSEC")) return false ; return true ; } //---------------------------------------------------------------------------- bool ExportDxf::ExportTables( IGeomDB* pGDB, int nId) { // intestazione sezione tables if ( ! WriteItem( 0, "SECTION") || ! WriteItem( 2, "TABLES")) return false ; // scrittura tavola per tipi di linea if ( ! WriteLinetypesTable( pGDB, nId)) return false ; // scrittura tavola per i layers if ( ! WriteLayersTable( pGDB, nId)) return false ; // scrittura tavola per stili di testo if ( ! WriteStylesTable( pGDB, nId)) return false ; // terminazione sezione tables if ( ! WriteItem( 0, "ENDSEC")) return false ; return true ; } //---------------------------------------------------------------------------- bool ExportDxf::WriteLinetypesTable( IGeomDB* pGDB, int nId) { // scrittura intestazione della tavola if ( ! WriteItem( 0, "TABLE") || ! WriteItem( 2, "LTYPE")) return false ; // un solo tipo di linea if ( ! WriteItem( 70, 1)) return false ; // tipo di linea continuo if ( ! WriteItem( 0, "LTYPE")) return false ; if ( ! WriteItem( 2, "CONTINUOUS")) return false ; if ( ! WriteItem( 70, 0)) return false ; if ( ! WriteItem( 3, "Solid line")) return false ; if ( ! WriteItem( 72, 65)) return false ; if ( ! WriteItem( 73, 0)) return false ; if ( ! WriteItem( 40, 0.0)) return false ; // scrittura terminazione della tavola if ( ! WriteItem( 0, "ENDTAB")) return false ; return true ; } //---------------------------------------------------------------------------- bool ExportDxf::WriteLayersTable( IGeomDB* pGDB, int nId) { // ciclo di ricerca dei layer // creo un iteratore PtrOwner pIter( CreateGdbIterator( pGDB)) ; if ( IsNull( pIter)) return false ; pIter->GoTo( nId) ; // eseguo la ricerca LAYDATVECTOR vLayDat ; if ( ! FindLayers( *pIter, LAY_DEFAULT, vLayDat)) return false ; // scrittura intestazione della tavola if ( ! WriteItem( 0, "TABLE") || ! WriteItem( 2, "LAYER")) return false ; // numero di layer int nLayNbr = int( vLayDat.size()) ; if ( ! WriteItem( 70, nLayNbr)) return false ; // scrittura dei layers for ( int i = 0 ; i < nLayNbr ; ++i) { if ( ! WriteLayer( vLayDat[i].first, 0, vLayDat[i].second, LINETYPE_DEFAULT)) return false ; } // scrittura terminazione della tavola if ( ! WriteItem( 0, "ENDTAB")) return false ; return true ; } //---------------------------------------------------------------------------- bool ExportDxf::FindLayers( const IGdbIterator& iIter, const string& sLay, LAYDATVECTOR& vLayDat) { // se non è un gruppo, esco subito if ( iIter.GetGdbType() != GDB_TY_GROUP) return true ; // aggiorno nome layer bool bExactLay ; string sNewLay = UpdateLayerName( iIter, sLay, &bExactLay) ; // recupero il colore corrente Color cCol ; int nCol ; if ( iIter.GetCalcMaterial( cCol)) ColorToACI( cCol, nCol) ; // se layer non presente, lo aggiungo al vettore dei layer bool bFound = false ; for ( int i = 0 ; ! bFound && i < int( vLayDat.size()) ; ++ i) { string s1 = vLayDat[i].first ; string s2 = sNewLay ; if ( ToUpper( s1) == ToUpper( s2)) { bFound = true ; // se è il nome esatto, aggiorno il colore if ( bExactLay) vLayDat[i].second = nCol ; } } if ( ! bFound) vLayDat.emplace_back( sNewLay, nCol) ; // scandisco il gruppo alla ricerca di sottogruppi PtrOwner pIter( CreateGdbIterator( iIter.GetGDB())) ; if ( IsNull( pIter)) return false ; bool bOk = true ; for ( bool bNext = pIter->GoToFirstInGroup( iIter) ; bNext ; bNext = pIter->GoToNext()) { if ( ! FindLayers( *pIter, sNewLay, vLayDat)) bOk = false ; } return bOk ; } //---------------------------------------------------------------------------- bool ExportDxf::WriteLayer( const string& sLay, int nFlag, int nCol, const string& sLineType) { // intestazione layer if ( ! WriteItem( 0, "LAYER")) return false ; // nome layer if ( ! WriteItem( 2, sLay)) return false ; // flag if ( ! WriteItem( 70, nFlag)) return false ; // colore if ( ! WriteItem( 62, nCol)) return false ; // tipo linea if ( ! WriteItem( 6, sLineType)) return false ; return true ; } //---------------------------------------------------------------------------- bool ExportDxf::WriteStylesTable( IGeomDB* pGDB, int nId) { // ciclo di ricerca dei testi // creo un iteratore PtrOwner pIter( CreateGdbIterator( pGDB)) ; if ( IsNull( pIter)) return false ; pIter->GoTo( nId) ; // eseguo la ricerca STRVECTOR vFontName ; if ( ! FindTextStyles( *pIter, vFontName)) return false ; // scrittura intestazione della tavola if ( ! WriteItem( 0, "TABLE") || ! WriteItem( 2, "STYLE")) return false ; // numero di stili di testo int nFontNbr = int( vFontName.size()) ; if ( ! WriteItem( 70, 1 + nFontNbr)) return false ; // scrittura stile di testo standard if ( ! WriteStyle( "STANDARD", "isocp.shx")) return false ; // scrittura degli stili di testo for ( int i = 0 ; i < nFontNbr ; ++i) { if ( ! WriteStyle( FontNameToStyle( vFontName[i]), AdjustFontName( vFontName[i]))) return false ; } // scrittura terminazione della tavola if ( ! WriteItem( 0, "ENDTAB")) return false ; return true ; } //---------------------------------------------------------------------------- bool ExportDxf::FindTextStyles( const IGdbIterator& iIter, STRVECTOR& vFontName) { // se è una entità geometrica if ( iIter.GetGdbType() == GDB_TY_GEO) { // se è un testo if ( const IExtText* pTXT = GetExtText( iIter.GetGeoObj())) { // se font non presente, lo aggiungo al vettore dei font bool bFound = false ; for ( int i = 0 ; ! bFound && i < int( vFontName.size()) ; ++ i) { string s1 = vFontName[i] ; string s2 = pTXT->GetFont() ; if ( ToUpper( s1) == ToUpper( s2)) bFound = true ; } if ( ! bFound) vFontName.push_back( pTXT->GetFont()) ; } return true ; } // se un gruppo, scandisco i suoi figli else if ( iIter.GetGdbType() == GDB_TY_GROUP) { // scandisco il gruppo PtrOwner pIter( CreateGdbIterator( iIter.GetGDB())) ; if ( IsNull( pIter)) return false ; bool bOk = true ; for ( bool bNext = pIter->GoToFirstInGroup( iIter) ; bNext ; bNext = pIter->GoToNext()) { if ( ! FindTextStyles( *pIter, vFontName)) bOk = false ; } return bOk ; } else return true ; } //---------------------------------------------------------------------------- bool ExportDxf::WriteStyle( const string& sStyle, const string& sFont) { // intestazione layer if ( ! WriteItem( 0, "STYLE")) return false ; // nome stile if ( ! WriteItem( 2, sStyle)) return false ; // flag if ( ! WriteItem( 70, 0)) return false ; // altezza testo if ( ! WriteItem( 40, 0)) return false ; // rapporto altezza/larghezza if ( ! WriteItem( 41, 1)) return false ; // angolo obliquo if ( ! WriteItem( 50, 0)) return false ; // flag di generazione if ( ! WriteItem( 71, 0)) return false ; // ultima altezza usata if ( ! WriteItem( 42, 10)) return false ; // nome font if ( ! WriteItem( 3, sFont)) return false ; // big font file name if ( ! WriteItem( 4, "")) return false ; return true ; } //---------------------------------------------------------------------------- bool ExportDxf::ExportEntities( IGeomDB* pGDB, int nId) { // intestazione sezione entità if ( ! WriteItem( 0, "SECTION") || ! WriteItem( 2, "ENTITIES")) return false ; // creo un iteratore PtrOwner pIter( CreateGdbIterator( pGDB)) ; if ( IsNull( pIter)) return false ; pIter->GoTo( nId) ; // esporto l'oggetto e i suoi eventuali figli if ( ! ExportGdbObject( *pIter, LAY_DEFAULT)) return false ; // terminazione sezione entità if ( ! WriteItem( 0, "ENDSEC")) return false ; return true ; } //---------------------------------------------------------------------------- bool ExportDxf::ExportGdbObject( const IGdbIterator& iIter, const string& sLay) { // recupero il tipo dell'oggetto int nGdbType = iIter.GetGdbType() ; // se oggetto geometrico if ( nGdbType == GDB_TY_GEO) { // recupero l'oggetto geometrico const IGeoObj* pGeoObj = iIter.GetGeoObj() ; if ( pGeoObj == nullptr) return true ; // recupero il riferimento globale dell'oggetto Frame3d frFrame ; if ( ! iIter.GetGlobFrame( frFrame)) return false ; // recupero il livello dell'oggetto int nLev = GDB_LV_USER ; iIter.GetCalcLevel( nLev) ; // recupero il modo dell'oggetto int nMode = GDB_MD_STD ; iIter.GetCalcMode( nMode) ; // recupero lo stato dell'oggetto int nStat = GDB_ST_ON ; iIter.GetCalcStatus( nStat) ; // se il filtro lo abilita if ( TestFilter( nLev, nMode, nStat)) { // recupero colore (trasformato in formato ACI) int nCol = COL_DEFAULT ; Color cCol ; if ( ( m_bColorByLayer && iIter.GetMaterial( cCol)) || ( ! m_bColorByLayer && iIter.GetCalcMaterial( cCol))) ColorToACI( cCol, nCol) ; // emetto l'oggetto switch ( pGeoObj->GetType()) { case GEO_PNT3D : if ( ! ExportPoint( sLay, nCol, pGeoObj, frFrame)) return false ; break ; case GEO_VECT3D : if ( ! ExportVector( sLay, nCol, pGeoObj, frFrame)) return false ; break ; case CRV_LINE : if ( ! ExportLine( sLay, nCol, pGeoObj, frFrame)) return false ; break ; case CRV_ARC : if ( ! ExportArc( sLay, nCol, pGeoObj, frFrame)) return false ; break ; case CRV_BEZ : if ( ! ExportCrvBezier( sLay, nCol, pGeoObj, frFrame)) return false ; break ; case CRV_COMPO : if ( ! ExportCrvCompo( sLay, nCol, pGeoObj, frFrame)) return false ; break ; case SRF_TRIMESH : if ( ! ExportSTM( sLay, nCol, pGeoObj, frFrame)) return false ; break ; case SRF_FLATRGN : if ( ! ExportSFR( sLay, nCol, pGeoObj, frFrame)) return false ; break ; case EXT_TEXT : if ( ! ExportText( sLay, nCol, pGeoObj, frFrame)) return false ; break ; } } return true ; } // se gruppo di oggetti else if ( nGdbType == GDB_TY_GROUP) { // esporto il gruppo return ExportGdbGroup( iIter, sLay) ; } else return false ; } //---------------------------------------------------------------------------- bool ExportDxf::ExportGdbGroup( const IGdbIterator& iIter, const string& sLay) { // creo un iteratore PtrOwner pIter( CreateGdbIterator( iIter.GetGDB())) ; if ( IsNull( pIter)) return false ; // aggiorno nome layer string sNewLay = UpdateLayerName( iIter, sLay) ; // scandisco il gruppo bool bOk = true ; for ( bool bNext = pIter->GoToFirstInGroup( iIter) ; bNext ; bNext = pIter->GoToNext()) { if ( ! ExportGdbObject( *pIter, sNewLay)) bOk = false ; } return bOk ; } //---------------------------------------------------------------------------- bool ExportDxf::ExportPoint( const string& sLay, int nCol, const IGeoObj* pGeoObj, const Frame3d& frFrame) { // verifico oggetto const IGeoPoint3d* pGPnt = GetGeoPoint3d( pGeoObj) ; if ( pGPnt == nullptr) return false ; // scrittura del punto return WritePoint( sLay, nCol, pGPnt->GetPoint(), V_NULL, frFrame) ; } //---------------------------------------------------------------------------- bool ExportDxf::ExportVector( const string& sLay, int nCol, const IGeoObj* pGeoObj, const Frame3d& frFrame) { // verifico oggetto const IGeoVector3d* pGVect = GetGeoVector3d( pGeoObj) ; if ( pGVect == nullptr) return false ; // scrittura del vettore con punto base return WritePoint( sLay, nCol, pGVect->GetBase(), pGVect->GetVector(), frFrame) ; } //---------------------------------------------------------------------------- bool ExportDxf::ExportLine( const string& sLay, int nCol, const IGeoObj* pGeoObj, const Frame3d& frFrame) { // verifico oggetto const ICurveLine* pLine = GetCurveLine( pGeoObj) ; if ( pLine == nullptr) return false ; // scrivo l'entità return WriteLine( sLay, nCol, pLine, frFrame) ; } //---------------------------------------------------------------------------- bool ExportDxf::ExportArc( const string& sLay, int nCol, const IGeoObj* pGeoObj, const Frame3d& frFrame) { // verifico oggetto const ICurveArc* pArc = GetCurveArc( pGeoObj) ; if ( pArc == nullptr) return false ; // se è un'elica o con estrusione non parallela a N if ( ! pArc->IsFlat()) { // esporto come polilinea 3d return WriteCurve3d( sLay, nCol, pArc, frFrame) ; } // se circonferenza if ( pArc->IsACircle()) { // esporto come cerchio return WriteCircle( sLay, nCol, pArc, frFrame) ; } // altrimenti arco 2d return WriteArc( sLay, nCol, pArc, frFrame) ; } //---------------------------------------------------------------------------- bool ExportDxf::ExportCrvBezier( const string& sLay, int nCol, const IGeoObj* pGeoObj, const Frame3d& frFrame) { // deve essere una curva di Bezier const ICurveBezier* pCBez = GetCurveBezier( pGeoObj) ; if ( pCBez == nullptr) return false ; // verifico se piana Plane3d plPlane ; if ( pCBez->IsFlat( plPlane)) { Frame3d frPlane ; frPlane.Set( ( ORIG + plPlane.dDist * plPlane.vtN), plPlane.vtN) ; return WriteCurve2d( sLay, nCol, pCBez, frPlane, frFrame) ; } // esporto come polilinea 3d return WriteCurve3d( sLay, nCol, pCBez, frFrame) ; } //---------------------------------------------------------------------------- bool ExportDxf::ExportCrvCompo( const string& sLay, int nCol, const IGeoObj* pGeoObj, const Frame3d& frFrame) { // deve essere una curva composita const ICurveComposite* pCC = GetCurveComposite( pGeoObj) ; if ( pCC == nullptr) return false ; // verifico se piana Plane3d plPlane ; if ( pCC->IsFlat( plPlane)) { Frame3d frPlane ; frPlane.Set( ( ORIG + plPlane.dDist * plPlane.vtN), plPlane.vtN) ; return WriteCurve2d( sLay, nCol, pCC, frPlane, frFrame) ; } // altrimenti esporto come polilinea 3d return WriteCurve3d( sLay, nCol, pCC, frFrame) ; } //---------------------------------------------------------------------------- bool ExportDxf::ExportSFR( const string& sLay, int nCol, const IGeoObj* pGeoObj, const Frame3d& frFrame) { // deve essere una superficie regione piatta const ISurfFlatRegion* pSFR = GetSurfFlatRegion( pGeoObj) ; if ( pSFR == nullptr) return false ; // ricavo la trimesh equivalente const ISurfTriMesh* pStm = pSFR->GetAuxSurf() ; return ExportSTM( sLay, nCol, pStm, frFrame) ; } //---------------------------------------------------------------------------- bool ExportDxf::ExportSTM( const string& sLay, int nCol, const IGeoObj* pGeoObj, const Frame3d& frFrame) { // deve essere una superficie trimesh const ISurfTriMesh* pSTM = GetSurfTriMesh( pGeoObj) ; if ( pSTM == nullptr) return false ; // posso esportare come unica polymesh solo se il numero dei vertici e dei triangoli è inferiore a 32767 if ( pSTM->GetVertexCount() < SHRT_MAX && pSTM->GetTriangleCount() < SHRT_MAX) { // identificativo entità if ( ! WriteItem( 0, "POLYLINE")) return false ; // layer if ( ! WriteItem( 8, sLay)) return false ; // colore if ( ! WriteItem( 62, nCol)) return false ; // flag segnalazione entità successive dipendenti (vertex) if ( ! WriteItem( 66, 1)) return false ; // punto inutile ma obbligatorio if ( ! WriteItem( 10, 0) || ! WriteItem( 20, 0) || ! WriteItem( 30, 0)) return false ; // flag (polyface mesh 3d) if ( ! WriteItem( 70, 64)) return false ; // numero di vertici if ( ! WriteItem( 71, pSTM->GetVertexCount())) return false ; // numero di facce if ( ! WriteItem( 72, pSTM->GetTriangleCount())) return false ; // ciclo sui vertici Point3d ptP ; for ( int nId = pSTM->GetFirstVertex( ptP) ; nId != SVT_NULL ; nId = pSTM->GetNextVertex( nId, ptP)) { ptP.ToGlob( frFrame) ; // entità vertice if ( ! WriteItem( 0, "VERTEX")) return false ; // layer if ( ! WriteItem( 8, sLay)) return false ; // punto corrente if ( ! WriteItem( 10, ptP.x) || ! WriteItem( 20, ptP.y) || ! WriteItem( 30, ptP.z)) return false ; // flag (3d polygon mesh + polyface mesh vertex) if ( ! WriteItem( 70, 64 + 128)) return false ; } // ciclo sui triangoli int nIdVert[3] ; for ( int nId = pSTM->GetFirstTriangle( nIdVert) ; nId != SVT_NULL ; nId = pSTM->GetNextTriangle( nId, nIdVert)) { // entità vertice if ( ! WriteItem( 0, "VERTEX")) return false ; // layer if ( ! WriteItem( 8, sLay)) return false ; // colore (unico colore riconosciuto) if ( ! WriteItem( 62, nCol)) return false ; // punto inutile ma obbligatorio if ( ! WriteItem( 10, 0) || ! WriteItem( 20, 0) || ! WriteItem( 30, 0)) return false ; // flag (polyface mesh vertex) if ( ! WriteItem( 70, 128)) return false ; // indici dei vertici (1-based) if ( ! WriteItem( 71, nIdVert[0] + 1) || ! WriteItem( 72, nIdVert[1] + 1) || ! WriteItem( 73, nIdVert[2] + 1)) return false ; } // entità termine dei vertici if ( ! WriteItem( 0, "SEQEND")) return false ; // layer if ( ! WriteItem( 8, sLay)) return false ; return true ; } // altrimenti devo esportare come insieme di facce triangolari else { // ciclo sui triangoli Triangle3d Tria ; for ( int nId = pSTM->GetFirstTriangle( Tria) ; nId != SVT_NULL ; nId = pSTM->GetNextTriangle( nId, Tria)) { Tria.ToGlob( frFrame) ; // entità 3dface if ( ! WriteItem( 0, "3DFACE")) return false ; // layer if ( ! WriteItem( 8, sLay)) return false ; // colore (unico colore riconosciuto) if ( ! WriteItem( 62, nCol)) return false ; // primo vertice if ( ! WriteItem( 10, Tria.GetP(0).x) || ! WriteItem( 20, Tria.GetP(0).y) || ! WriteItem( 30, Tria.GetP(0).z)) return false ; // secondo vertice if ( ! WriteItem( 11, Tria.GetP(1).x) || ! WriteItem( 21, Tria.GetP(1).y) || ! WriteItem( 31, Tria.GetP(1).z)) return false ; // terzo vertice if ( ! WriteItem( 12, Tria.GetP(2).x) || ! WriteItem( 22, Tria.GetP(2).y) || ! WriteItem( 32, Tria.GetP(2).z)) return false ; // quarto vertice (ripete il terzo) if ( ! WriteItem( 13, Tria.GetP(2).x) || ! WriteItem( 23, Tria.GetP(2).y) || ! WriteItem( 33, Tria.GetP(2).z)) return false ; // flag (default) if ( ! WriteItem( 70, 0)) return false ; } return true ; } } //---------------------------------------------------------------------------- bool ExportDxf::ExportText( const string& sLay, int nCol, const IGeoObj* pGeoObj, const Frame3d& frFrame) { // deve essere un testo const IExtText* pTXT = GetExtText( pGeoObj) ; if ( pTXT == nullptr) return false ; // calcolo riferimento OCS Vector3d vtN = pTXT->GetNormVersor() ; vtN.ToGlob( frFrame) ; Frame3d frOCS ; frOCS.Set( ORIG, vtN) ; // divido il testo in testi monolinea IEXTTEXTPVECTOR vTxt ; pTXT->SplitOnLineBreak( vTxt) ; // ciclo sui diversi testi semplici bool bOk = true ; for ( int i = 0 ; i < int( vTxt.size()) ; ++ i) { // identificativo entità if ( ! WriteItem( 0, "TEXT")) return false ; // layer if ( ! WriteItem( 8, sLay)) return false ; // colore if ( ! WriteItem( 62, nCol)) return false ; // punto di inserimento in OCS Point3d ptP = vTxt[i]->GetPoint() ; ptP.LocToLoc( frFrame, frOCS) ; if ( ! WriteItem( 10, ptP.x) || ! WriteItem( 20, ptP.y) || ! WriteItem( 30, ptP.z)) return false ; // altezza if ( ! WriteItem( 40, vTxt[i]->GetHeight())) return false ; // stringa di testo string sText = vTxt[i]->GetText() ; if ( ! AdjustText( sText)) return false ; if ( ! WriteItem( 1, sText)) return false ; // angolo di rotazione Vector3d vtDir = vTxt[i]->GetDirVersor() ; vtDir.LocToLoc( frFrame, frOCS) ; double dDirDeg ; vtDir.ToSpherical( nullptr, nullptr, &dDirDeg) ; if ( ! WriteItem( 50, dDirDeg)) return false ; // rapporto altezza/larghezza if ( ! WriteItem( 41, vTxt[i]->GetRatio())) return false ; // stile if ( ! WriteItem( 7, FontNameToStyle( vTxt[i]->GetFont()))) return false ; // vettore estrusione if ( ! WriteItem( 210, vtN.x) || ! WriteItem( 220, vtN.y) || ! WriteItem( 230, vtN.z)) return false ; // libero l'entità delete vTxt[i] ; } return bOk ; } //---------------------------------------------------------------------------- bool ExportDxf::AdjustText( string& sText) { // gestione del % ReplaceString( sText, "%", "%%%") ; // converto i byte della stringa in codici carattere UINTVECTOR vCode ; if ( ! GetCodePoints( sText, vCode)) return false ; // ricostruisco la stringa dai codici sText.clear() ; for ( int i = 0 ; i < int( vCode.size()) ; ++ i) { // caratteri ASCII stampabili if ( vCode[i] >= 32 && vCode[i] <= 126) sText += string( 1, vCode[i]) ; // carattere speciale grado else if ( vCode[i] == 176) sText += "%%d" ; // carattere speciale +/- else if ( vCode[i] == 177) sText += "%%p" ; // carattere speciale diametro else if ( vCode[i] == 216) sText += "%%c" ; // altri caratteri UNICODE else sText += "_" ; } return true ; } //---------------------------------------------------------------------------- bool ExportDxf::WritePoint( const string& sLay, int nCol, const Point3d& ptP, const Vector3d& vtV, const Frame3d& frFrame) { // identificativo entità if ( ! WriteItem( 0, "POINT")) return false ; // layer if ( ! WriteItem( 8, sLay)) return false ; // colore if ( ! WriteItem( 62, nCol)) return false ; // punto Point3d ptOut = ptP ; ptOut.ToGlob( frFrame) ; if ( ! WriteItem( 10, ptOut.x) || ! WriteItem( 20, ptOut.y) || ! WriteItem( 30, ptOut.z)) return false ; // eventuale versore estrusione e spessore if ( ! vtV.IsSmall()) { double dTh = vtV.Len() ; Vector3d vtExtr = vtV / dTh ; if ( ! WriteItem( 39, dTh) || ! WriteItem( 210, vtExtr.x) || ! WriteItem( 220, vtExtr.y) || ! WriteItem( 230, vtExtr.z)) return false ; } return true ; } //---------------------------------------------------------------------------- bool ExportDxf::WriteLine( const string& sLay, int nCol, const ICurveLine* pLine, const Frame3d& frFrame) { // verifico validità linea if ( pLine == nullptr) return false ; // identificativo entità if ( ! WriteItem( 0, "LINE")) return false ; // layer if ( ! WriteItem( 8, sLay)) return false ; // colore if ( ! WriteItem( 62, nCol)) return false ; // punto iniziale Point3d ptStart = pLine->GetStart() ; ptStart.ToGlob( frFrame) ; if ( ! WriteItem( 10, ptStart.x) || ! WriteItem( 20, ptStart.y) || ! WriteItem( 30, ptStart.z)) return false ; // punto finale Point3d ptEnd = pLine->GetEnd() ; ptEnd.ToGlob( frFrame) ; if ( ! WriteItem( 11, ptEnd.x) || ! WriteItem( 21, ptEnd.y) || ! WriteItem( 31, ptEnd.z)) return false ; // spessore double dThick = 0 ; pLine->GetThickness( dThick) ; if ( fabs( dThick) > EPS_SMALL) { if ( ! WriteItem( 39, dThick)) return false ; } // vettore estrusione Vector3d vtExtr ; pLine->GetExtrusion( vtExtr) ; vtExtr.ToGlob( frFrame) ; if ( ! vtExtr.IsSmall() && ! vtExtr.IsZplus()) { if ( ! WriteItem( 210, vtExtr.x) || ! WriteItem( 220, vtExtr.y) || ! WriteItem( 230, vtExtr.z)) return false ; } return true ; } //---------------------------------------------------------------------------- bool ExportDxf::WriteCircle( const string& sLay, int nCol, const ICurveArc* pArc, const Frame3d& frFrame) { // verifico validità arco if ( pArc == nullptr) return false ; // verifico verso eventuale estrusione Vector3d vtN = pArc->GetNormVersor() ; Vector3d vtExtr ; pArc->GetExtrusion( vtExtr) ; bool bExtrOpposite = AreOppositeVectorApprox( vtN, vtExtr) ; // calcolo riferimento OCS vtN.ToGlob( frFrame) ; Frame3d frOCS ; frOCS.Set( ORIG, vtN) ; // identificativo entità if ( ! WriteItem( 0, "CIRCLE")) return false ; // layer if ( ! WriteItem( 8, sLay)) return false ; // colore if ( ! WriteItem( 62, nCol)) return false ; // centro Point3d ptCen = pArc->GetCenter() ; ptCen.LocToLoc( frFrame, frOCS) ; if ( ! WriteItem( 10, ptCen.x) || ! WriteItem( 20, ptCen.y) || ! WriteItem( 30, ptCen.z)) return false ; // raggio double dRad = pArc->GetRadius() ; if ( ! WriteItem( 40, dRad)) return false ; // spessore double dThick = 0 ; pArc->GetThickness( dThick) ; if ( fabs( dThick) > EPS_SMALL) { if ( ! WriteItem( 39, ( bExtrOpposite ? - dThick : dThick))) return false ; } // vettore estrusione if ( ! WriteItem( 210, vtN.x) || ! WriteItem( 220, vtN.y) || ! WriteItem( 230, vtN.z)) return false ; return true ; } //---------------------------------------------------------------------------- bool ExportDxf::WriteArc( const string& sLay, int nCol, const ICurveArc* pArc, const Frame3d& frFrame) { // verifico validità arco if ( pArc == nullptr) return false ; // verifico verso eventuale estrusione Vector3d vtN = pArc->GetNormVersor() ; Vector3d vtExtr ; pArc->GetExtrusion( vtExtr) ; bool bExtrOpposite = AreOppositeVectorApprox( vtN, vtExtr) ; // calcolo riferimento OCS vtN.ToGlob( frFrame) ; Frame3d frOCS ; frOCS.Set( ORIG, vtN) ; // identificativo entità if ( ! WriteItem( 0, "ARC")) return false ; // layer if ( ! WriteItem( 8, sLay)) return false ; // colore if ( ! WriteItem( 62, nCol)) return false ; // centro Point3d ptCen = pArc->GetCenter() ; ptCen.LocToLoc( frFrame, frOCS) ; if ( ! WriteItem( 10, ptCen.x) || ! WriteItem( 20, ptCen.y) || ! WriteItem( 30, ptCen.z)) return false ; // angoli iniziale e finale (archi sempre CCW) double dStartAngDeg, dEndAngDeg ; Vector3d vtS = pArc->GetStartVersor() ; vtS.LocToLoc( frFrame, frOCS) ; vtS.ToSpherical( nullptr, nullptr, &dStartAngDeg) ; double dCenAngDeg = pArc->GetAngCenter() ; dEndAngDeg = dStartAngDeg + dCenAngDeg ; if ( dCenAngDeg < 0) swap( dStartAngDeg, dEndAngDeg) ; if ( ! WriteItem( 50, dStartAngDeg) || ! WriteItem( 51, dEndAngDeg)) return false ; // raggio double dRad = pArc->GetRadius() ; if ( ! WriteItem( 40, dRad)) return false ; // spessore double dThick = 0 ; pArc->GetThickness( dThick) ; if ( fabs( dThick) > EPS_SMALL) { if ( ! WriteItem( 39, ( bExtrOpposite ? - dThick : dThick))) return false ; } // vettore estrusione if ( ! WriteItem( 210, vtN.x) || ! WriteItem( 220, vtN.y) || ! WriteItem( 230, vtN.z)) return false ; return true ; } //---------------------------------------------------------------------------- bool ExportDxf::WriteCurve2d( const string& sLay, int nCol, const ICurve* pCrv, const Frame3d& frPlane, const Frame3d& frFrame) { // verifico validità curva if ( pCrv == nullptr) return false ; // trasformo in poliarco Frame3d frGlob ; PolyArc PA ; // se il piano non coincide con il piano XY globale, devo trasformare la curva if ( ! AreSameFrame( frPlane, GLOB_FRM)) { // creo una copia della curva (da buttare alla fine) PtrOwner pModCrv( pCrv->Clone()) ; if ( IsNull( pModCrv)) return false ; // eseguo la trasformazione pModCrv->ToLoc( frPlane) ; // esplodo in archi if ( ! pModCrv->ApproxWithArcs( BEZ_LIN_APPROX, BEZ_ANG_APPROX_DEG, PA)) return false ; // calcolo il riferimento in cui sono espressi gli archi frGlob = frPlane ; frGlob.ToGlob( frFrame) ; } // altrimenti posso operare direttamente sulla curva originale else { // esplodo in archi if ( ! pCrv->ApproxWithArcs( BEZ_LIN_APPROX, BEZ_ANG_APPROX_DEG, PA)) return false ; // assegno il riferimento in cui sono espressi gli archi frGlob = frFrame ; } // calcolo il riferimento OCS con la stessa Z del riferimento degli archi Frame3d frOCS ; frOCS.Set( ORIG, frGlob.VersZ()) ; // esporto come polyline 2d if ( ! WriteItem( 0, "POLYLINE")) return false ; // layer if ( ! WriteItem( 8, sLay)) return false ; // colore if ( ! WriteItem( 62, nCol)) return false ; // flag segnalazione entità successive dipendenti (vertex) if ( ! WriteItem( 66, 1)) return false ; // punto per sola elevazione : X,Y inutili Z elevazione Point3d ptE = ORIG ; ptE.LocToLoc( frGlob, frOCS) ; if ( ! WriteItem( 10, 0) || ! WriteItem( 20, 0) || ! WriteItem( 30, ptE.z)) return false ; // flag bool bClosed = pCrv->IsClosed() ; if ( ! WriteItem( 70, ( bClosed ? 1 : 0))) return false ; // spessore double dThick = 0 ; pCrv->GetThickness( dThick) ; if ( fabs( dThick) > EPS_SMALL) { if ( ! WriteItem( 39, dThick)) return false ; } // vettore estrusione ( versore Z di OCS) if ( ! WriteItem( 210, frGlob.VersZ().x) || ! WriteItem( 220, frGlob.VersZ().y) || ! WriteItem( 230, frGlob.VersZ().z)) return false ; // emetto i vertici double dBulge ; Point3d ptP ; for ( bool bPnt = PA.GetFirstPoint( ptP, dBulge) ; bPnt ; bPnt = PA.GetNextPoint( ptP, dBulge, bClosed)) { // entità vertice if ( ! WriteItem( 0, "VERTEX")) return false ; // layer if ( ! WriteItem( 8, sLay)) return false ; // punto corrente ptP.LocToLoc( frGlob, frOCS) ; if ( ! WriteItem( 10, ptP.x) || ! WriteItem( 20, ptP.y) || ! WriteItem( 30, ptP.z)) return false ; // bulge if ( ! WriteItem( 42, dBulge)) return false ; // flag if ( ! WriteItem( 70, 0)) return false ; } // entità termine dei vertici if ( ! WriteItem( 0, "SEQEND")) return false ; // layer if ( ! WriteItem( 8, sLay)) return false ; return true ; } //---------------------------------------------------------------------------- bool ExportDxf::WriteCurve3d( const string& sLay, int nCol, const ICurve* pCrv, const Frame3d& frFrame) { // verifico validità curva if ( pCrv == nullptr) return false ; // trasformo in polilinea PolyLine PL ; if ( ! pCrv->ApproxWithLines( BEZ_LIN_APPROX, BEZ_ANG_APPROX_DEG, ICurve::APL_SPECIAL, PL)) return false ; // recupero lo spessore double dThick = 0 ; pCrv->GetThickness( dThick) ; // recupero il vettore estrusione Vector3d vtExtr ; pCrv->GetExtrusion( vtExtr) ; vtExtr.ToGlob( frFrame) ; // se senza spessore o con estrusione nulla, polilinea 3d if ( fabs( dThick) < EPS_SMALL || vtExtr.IsSmall()) { // esporto come polyline 3d if ( ! WriteItem( 0, "POLYLINE")) return false ; // layer if ( ! WriteItem( 8, sLay)) return false ; // colore if ( ! WriteItem( 62, nCol)) return false ; // flag segnalazione entità successive dipendenti (vertex) if ( ! WriteItem( 66, 1)) return false ; // punto inutile ma obbligatorio if ( ! WriteItem( 10, 0) || ! WriteItem( 20, 0) || ! WriteItem( 30, 0)) return false ; // flag (3d) if ( ! WriteItem( 70, 8)) return false ; // emetto i vertici Point3d ptP ; for ( bool bPnt = PL.GetFirstPoint( ptP) ; bPnt ; bPnt = PL.GetNextPoint( ptP)) { // entità vertice if ( ! WriteItem( 0, "VERTEX")) return false ; // layer if ( ! WriteItem( 8, sLay)) return false ; // punto corrente ptP.ToGlob( frFrame) ; if ( ! WriteItem( 10, ptP.x) || ! WriteItem( 20, ptP.y) || ! WriteItem( 30, ptP.z)) return false ; // flag (3d polyline) if ( ! WriteItem( 70, 32)) return false ; } // entità termine dei vertici if ( ! WriteItem( 0, "SEQEND")) return false ; // layer if ( ! WriteItem( 8, sLay)) return false ; } // altrimenti insieme di segmenti di retta else { Point3d ptStart, ptEnd ; for ( bool bPnt = PL.GetFirstLine( ptStart, ptEnd) ; bPnt ; bPnt = PL.GetNextLine( ptStart, ptEnd)) { // identificativo entità if ( ! WriteItem( 0, "LINE")) return false ; // layer if ( ! WriteItem( 8, sLay)) return false ; // colore if ( ! WriteItem( 62, nCol)) return false ; // punto iniziale ptStart.ToGlob( frFrame) ; if ( ! WriteItem( 10, ptStart.x) || ! WriteItem( 20, ptStart.y) || ! WriteItem( 30, ptStart.z)) return false ; // punto finale ptEnd.ToGlob( frFrame) ; if ( ! WriteItem( 11, ptEnd.x) || ! WriteItem( 21, ptEnd.y) || ! WriteItem( 31, ptEnd.z)) return false ; // spessore if ( fabs( dThick) > EPS_SMALL) { if ( ! WriteItem( 39, dThick)) return false ; } // vettore estrusione if ( ! vtExtr.IsZplus()) { if ( ! WriteItem( 210, vtExtr.x) || ! WriteItem( 220, vtExtr.y) || ! WriteItem( 230, vtExtr.z)) return false ; } } } return true ; } //---------------------------------------------------------------------------- bool ExportDxf::TestFilter( int nLev, int nMode, int nStat) { if ( ( nLev == GDB_LV_USER && ( m_nFilter & EEXFLT_LEVUSER) == 0) || ( nLev == GDB_LV_SYSTEM && ( m_nFilter & EEXFLT_LEVSYSTEM) == 0) || ( nLev == GDB_LV_TEMP && ( m_nFilter & EEXFLT_LEVTEMP) == 0)) return false ; if ( ( nMode == GDB_MD_STD && ( m_nFilter & EEXFLT_MODESTD) == 0) || ( nMode == GDB_MD_LOCKED && ( m_nFilter & EEXFLT_MODELOCKED) == 0) || ( nMode == GDB_MD_HIDDEN && ( m_nFilter & EEXFLT_MODEHIDDEN) == 0)) return false ; if ( ( nStat == GDB_ST_OFF && ( m_nFilter & EEXFLT_STAOFF) == 0) || ( nStat == GDB_ST_ON && ( m_nFilter & EEXFLT_STAON) == 0) || ( nStat == GDB_ST_SEL && ( m_nFilter & EEXFLT_STASEL) == 0)) return false ; return true ; } //---------------------------------------------------------------------------- bool ExportDxf::WriteItem( int nCode, int nVal) { try { m_OutFile << ( nCode < 10 ? " " : nCode < 100 ? " " : "") << ToString( nCode) << endl ; m_OutFile << ToString( nVal) << endl ; } catch( ...) { return false ; } return true ; } //---------------------------------------------------------------------------- bool ExportDxf::WriteItem( int nCode, double dVal, int nPrec) { try { m_OutFile << ( nCode < 10 ? " " : nCode < 100 ? " " : "") << ToString( nCode) << endl ; m_OutFile << ToString( dVal, nPrec) << endl ; } catch( ...) { return false ; } return true ; } //---------------------------------------------------------------------------- bool ExportDxf::WriteItem( int nCode, const string& sVal) { try { m_OutFile << ( nCode < 10 ? " " : nCode < 100 ? " " : "") << ToString( nCode) << endl ; m_OutFile << sVal << endl ; } catch( ...) { return false ; } return true ; } //---------------------------------------------------------------------------- bool ExportDxf::ColorToACI( const Color& cCol, int& nColor) { // recupero RGB int nRed = cCol.GetIntRed() ; int nGreen = cCol.GetIntGreen() ; int nBlue = cCol.GetIntBlue() ; // colori speciali (con indice 1...9) if ( nRed == MAX_RGB && nGreen == 0 && nBlue == 0) { nColor = 1 ; // rosso return true ; } else if ( nRed == MAX_RGB && nGreen == MAX_RGB && nBlue == 0) { nColor = 2 ; // giallo return true ; } else if ( nRed == 0 && nGreen == MAX_RGB && nBlue == 0) { nColor = 3 ; // verde return true ; } else if ( nRed == 0 && nGreen == MAX_RGB && nBlue == MAX_RGB) { nColor = 4 ; // ciano return true ; } else if ( nRed == 0 && nGreen == 0 && nBlue == MAX_RGB) { nColor = 5 ; // blu return true ; } else if ( nRed == MAX_RGB && nGreen == 0 && nBlue == MAX_RGB) { nColor = 6 ; // magenta return true ; } else if ( nRed == MAX_RGB && nGreen == MAX_RGB && nBlue == MAX_RGB) { nColor = 7 ; // bianco return true ; } else if ( nRed == 128 && nGreen == 128 && nBlue == 128) { nColor = 8 ; // grigio return true ; } else if ( nRed == 192 && nGreen == 192 && nBlue == 192) { nColor = 9 ; // grigio chiaro return true ; } // calcolo HSV int nH = max( max( nRed, nGreen), nBlue) ; int nL = min( min( nRed, nGreen), nBlue) ; double dValue = nH / double( MAX_RGB) ; double dSat = 0.0 ; if ( nH > 0) dSat = ( nH - nL) / double( nH) ; double dHue = 0.0 ; if ( nH == nL) dHue = 0.0 ; else if ( nH == nRed) { dHue = 0.0 + ( 60.0 * ( nGreen - nBlue) / double( nH - nL)) ; if ( dHue < 0) dHue += 360 ; } else if ( nH == nGreen) dHue = 120.0 + ( 60.0 * ( nBlue - nRed) / double( nH - nL)) ; else if ( nH == nBlue) dHue = 240.0 + ( 60.0 * ( nRed - nGreen) / double( nH - nL)) ; // calcolo indice ACI // scala di grigi -> 250...255 if ( dSat < 0.1) { if ( dValue < 0.3) nColor = 250 ; else if ( dValue < 0.45) nColor = 251 ; else if ( dValue < 0.6) nColor = 252 ; else if ( dValue < 0.75) nColor = 253 ; else if ( dValue < 0.9) nColor = 254 ; else nColor = 255 ; return true ; } // colori generali -> 10...249 // prime due cifre sono dHue (angolo) / 1.5, con offset di 10 // ultima cifra 0,1 = 100% dValue, 2,3 = 80%, 4,5 = 60%, 6,7 = 50%, 8,9 = 30% // ultima cifra dispari se dSat < 50% altrimenti pari nColor = 10 + int( dHue / 1.5 + 0.9) ; nColor = max( 10, min( 249, nColor)) ; nColor -= ( nColor % 10) ; // per avere l'ultima cifra uguale a 0 if ( dValue < 0.31) nColor += 8 ; else if ( dValue < 0.51) nColor += 6 ; else if ( dValue < 0.61) nColor += 4 ; else if ( dValue < 0.81) nColor += 2 ; else nColor += 0 ; if ( dSat < 0.55) nColor += 1 ; return true ; } //---------------------------------------------------------------------------- string ExportDxf::UpdateLayerName( const IGdbIterator& iIter, const string& sLay, bool* pbExact) { string sNewLay ; string sName ; if ( iIter.GetName( sName)) { if ( m_bCompoundLayer && sLay != LAY_DEFAULT) sNewLay = sLay + "_" + sName ; else sNewLay = sName ; if ( pbExact != nullptr) *pbExact = true ; } else { sNewLay = sLay ; if ( pbExact != nullptr) *pbExact = false ; } ValidateDxfName( sNewLay) ; return sNewLay ; } //---------------------------------------------------------------------------- string ExportDxf::FontNameToStyle( const string& sFontName) { string sStyle = sFontName ; // se Nfe sostituisco con shx if ( FileExtensionMatches( sStyle, "NFE")) { sStyle.erase( sStyle.size() - 4, 4) ; sStyle += "_shx" ; } return sStyle ; } //---------------------------------------------------------------------------- string ExportDxf::AdjustFontName( const string& sFontName) { string sStyle = sFontName ; // se Nfe sostituisco con shx if ( FileExtensionMatches( sStyle, "NFE")) { sStyle.erase( sStyle.size() - 4, 4) ; sStyle += ".shx" ; } return sStyle ; }