//---------------------------------------------------------------------------- // EgalTech 2014-2014 //---------------------------------------------------------------------------- // File : ExportDxf.cpp Data : 07.08.14 Versione : 1.5h2 // Contenuto : Implementazione della classe per l'esportazione in formato DXF. // Versione ACAD 1009 quindi DXF R12 (handles disabilitati). // // // 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 ( ! VerifyKey( KEYOPT_EEX_EXPBASE)) return nullptr ; // 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) != 0) ; m_bColorByLayer = (( nFlag & EEXFLAG_COL_BY_LAYER) != 0) ; m_bAdvancedNames = (( nFlag & EEXFLAG_ADV_NAMES) != 0) ; 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_Writer.Close() ; if ( ! m_Writer.Init( sFile)) { 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 blocchi if ( ! ExportBlocks( 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_Writer.Close()) bOk = false ; 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 ; // altri dati if ( ! WriteItem( 9, "$DWGCODEPAGE") || ! WriteItem( 3, "ansi_1252") || ! WriteItem( 9, "$INSBASE") || ! WriteItem( 10, "0.0") || ! WriteItem( 20, "0.0") || ! WriteItem( 30, "0.0")) 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 ; // altri dati if ( ! WriteItem( 9, "$LIMMIN") || ! WriteItem( 10, "0.0") || ! WriteItem( 20, "0.0") || ! WriteItem( 9, "$LIMMAX") || ! WriteItem( 10, "12.0") || ! WriteItem( 20, "9.0") || ! WriteItem( 9, "$ORTHOMODE") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$REGENMODE") || ! WriteItem( 70, "1") || ! WriteItem( 9, "$FILLMODE") || ! WriteItem( 70, "1") || ! WriteItem( 9, "$QTEXTMODE") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$MIRRTEXT") || ! WriteItem( 70, "1") || ! WriteItem( 9, "$DRAGMODE") || ! WriteItem( 70, "2") || ! WriteItem( 9, "$LTSCALE") || ! WriteItem( 40, "1.0") || ! WriteItem( 9, "$OSMODE") || ! WriteItem( 70, "37") || ! WriteItem( 9, "$ATTMODE") || ! WriteItem( 70, "1") || ! WriteItem( 9, "$TEXTSIZE") || ! WriteItem( 40, "10.0") || ! WriteItem( 9, "$TRACEWID") || ! WriteItem( 40, "0.05") || ! WriteItem( 9, "$TEXTSTYLE") || ! WriteItem( 7, "STANDARD") || ! WriteItem( 9, "$CLAYER") || ! WriteItem( 8, "0") || ! WriteItem( 9, "$CELTYPE") || ! WriteItem( 6, "BYBLOCK") || ! WriteItem( 9, "$CECOLOR") || ! WriteItem( 62, "256") || ! WriteItem( 9, "$DIMSCALE") || ! WriteItem( 40, "1.0") || ! WriteItem( 9, "$DIMASZ") || ! WriteItem( 40, "0.18") || ! WriteItem( 9, "$DIMEXO") || ! WriteItem( 40, "0.0625") || ! WriteItem( 9, "$DIMDLI") || ! WriteItem( 40, "0.38") || ! WriteItem( 9, "$DIMRND") || ! WriteItem( 40, "0.0") || ! WriteItem( 9, "$DIMDLE") || ! WriteItem( 40, "0.0") || ! WriteItem( 9, "$DIMEXE") || ! WriteItem( 40, "0.18") || ! WriteItem( 9, "$DIMTP") || ! WriteItem( 40, "0.0") || ! WriteItem( 9, "$DIMTM") || ! WriteItem( 40, "0.0") || ! WriteItem( 9, "$DIMTXT") || ! WriteItem( 40, "0.18") || ! WriteItem( 9, "$DIMCEN") || ! WriteItem( 40, "0.09") || ! WriteItem( 9, "$DIMTSZ") || ! WriteItem( 40, "0.0") || ! WriteItem( 9, "$DIMTOL") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$DIMLIM") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$DIMTIH") || ! WriteItem( 70, "1") || ! WriteItem( 9, "$DIMTOH") || ! WriteItem( 70, "1") || ! WriteItem( 9, "$DIMSE1") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$DIMSE2") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$DIMTAD") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$DIMZIN") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$DIMBLK") || ! WriteItem( 1, "") || ! WriteItem( 9, "$DIMASO") || ! WriteItem( 70, "1") || ! WriteItem( 9, "$DIMSHO") || ! WriteItem( 70, "1") || ! WriteItem( 9, "$DIMPOST") || ! WriteItem( 1, "") || ! WriteItem( 9, "$DIMAPOST") || ! WriteItem( 1, "") || ! WriteItem( 9, "$DIMALT") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$DIMALTD") || ! WriteItem( 70, "2") || ! WriteItem( 9, "$DIMALTF") || ! WriteItem( 40, "25.4") || ! WriteItem( 9, "$DIMLFAC") || ! WriteItem( 40, "1.0") || ! WriteItem( 9, "$DIMTOFL") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$DIMTVP") || ! WriteItem( 40, "0.0") || ! WriteItem( 9, "$DIMTIX") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$DIMSOXD") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$DIMSAH") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$DIMBLK1") || ! WriteItem( 1, "") || ! WriteItem( 9, "$DIMBLK2") || ! WriteItem( 1, "") || ! WriteItem( 9, "$DIMSTYLE") || ! WriteItem( 2, "STANDARD") || ! WriteItem( 9, "$DIMCLRD") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$DIMCLRE") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$DIMCLRT") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$DIMTFAC") || ! WriteItem( 40, "1.0") || ! WriteItem( 9, "$DIMGAP") || ! WriteItem( 40, "0.09") || ! WriteItem( 9, "$LUNITS") || ! WriteItem( 70, "2") || ! WriteItem( 9, "$LUPREC") || ! WriteItem( 70, "4") || ! WriteItem( 9, "$SKETCHINC") || ! WriteItem( 40, "0.1") || ! WriteItem( 9, "$FILLETRAD") || ! WriteItem( 40, "0.0") || ! WriteItem( 9, "$AUNITS") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$AUPREC") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$MENU") || ! WriteItem( 1, ".") || ! WriteItem( 9, "$ELEVATION") || ! WriteItem( 40, "0.0") || ! WriteItem( 9, "$PELEVATION") || ! WriteItem( 40, "0.0") || ! WriteItem( 9, "$THICKNESS") || ! WriteItem( 40, "0.0") || ! WriteItem( 9, "$LIMCHECK") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$CHAMFERA") || ! WriteItem( 40, "0.0") || ! WriteItem( 9, "$CHAMFERB") || ! WriteItem( 40, "0.0") || ! WriteItem( 9, "$SKPOLY") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$TDCREATE") || ! WriteItem( 40, "2459110.411952581") || ! WriteItem( 9, "$TDUPDATE") || ! WriteItem( 40, "2459110.411952651") || ! WriteItem( 9, "$TDINDWG") || ! WriteItem( 40, "0.0000000116") || ! WriteItem( 9, "$TDUSRTIMER") || ! WriteItem( 40, "0.0000000116") || ! WriteItem( 9, "$USRTIMER") || ! WriteItem( 70, "1") || ! WriteItem( 9, "$ANGBASE") || ! WriteItem( 50, "0.0") || ! WriteItem( 9, "$ANGDIR") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$PDMODE") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$PDSIZE") || ! WriteItem( 40, "0.0") || ! WriteItem( 9, "$PLINEWID") || ! WriteItem( 40, "0.0") || ! WriteItem( 9, "$COORDS") || ! WriteItem( 70, "1") || ! WriteItem( 9, "$SPLFRAME") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$SPLINETYPE") || ! WriteItem( 70, "6") || ! WriteItem( 9, "$SPLINESEGS") || ! WriteItem( 70, "8") || ! WriteItem( 9, "$ATTDIA") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$ATTREQ") || ! WriteItem( 70, "1") || ! WriteItem( 9, "$HANDLING") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$HANDSEED") || ! WriteItem( 5, "0") || ! WriteItem( 9, "$SURFTAB1") || ! WriteItem( 70, "6") || ! WriteItem( 9, "$SURFTAB2") || ! WriteItem( 70, "6") || ! WriteItem( 9, "$SURFTYPE") || ! WriteItem( 70, "6") || ! WriteItem( 9, "$SURFU") || ! WriteItem( 70, "6") || ! WriteItem( 9, "$SURFV") || ! WriteItem( 70, "6") || ! WriteItem( 9, "$UCSNAME") || ! WriteItem( 2, "") || ! WriteItem( 9, "$UCSORG") || ! WriteItem( 10, "0.0") || ! WriteItem( 20, "0.0") || ! WriteItem( 30, "0.0") || ! WriteItem( 9, "$UCSXDIR") || ! WriteItem( 10, "1.0") || ! WriteItem( 20, "0.0") || ! WriteItem( 30, "0.0") || ! WriteItem( 9, "$UCSYDIR") || ! WriteItem( 10, "0.0") || ! WriteItem( 20, "1.0") || ! WriteItem( 30, "0.0") || ! WriteItem( 9, "$PUCSNAME") || ! WriteItem( 2, "") || ! WriteItem( 9, "$PUCSORG") || ! WriteItem( 10, "0.0") || ! WriteItem( 20, "0.0") || ! WriteItem( 30, "0.0") || ! WriteItem( 9, "$PUCSXDIR") || ! WriteItem( 10, "1.0") || ! WriteItem( 20, "0.0") || ! WriteItem( 30, "0.0") || ! WriteItem( 9, "$PUCSYDIR") || ! WriteItem( 10, "0.0") || ! WriteItem( 20, "1.0") || ! WriteItem( 30, "0.0") || ! WriteItem( 9, "$USERI1") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$USERI2") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$USERI3") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$USERI4") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$USERI5") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$USERR1") || ! WriteItem( 40, "0.0") || ! WriteItem( 9, "$USERR2") || ! WriteItem( 40, "0.0") || ! WriteItem( 9, "$USERR3") || ! WriteItem( 40, "0.0") || ! WriteItem( 9, "$USERR4") || ! WriteItem( 40, "0.0") || ! WriteItem( 9, "$USERR5") || ! WriteItem( 40, "0.0") || ! WriteItem( 9, "$WORLDVIEW") || ! WriteItem( 70, "1") || ! WriteItem( 9, "$SHADEDGE") || ! WriteItem( 70, "3") || ! WriteItem( 9, "$SHADEDIF") || ! WriteItem( 70, "70") || ! WriteItem( 9, "$TILEMODE") || ! WriteItem( 70, "1") || ! WriteItem( 9, "$MAXACTVP") || ! WriteItem( 70, "64") || ! WriteItem( 9, "$PLIMCHECK") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$PEXTMIN") || ! WriteItem( 10, "1.000000000000000E+20") || ! WriteItem( 20, "1.000000000000000E+20") || ! WriteItem( 30, "1.000000000000000E+20") || ! WriteItem( 9, "$PEXTMAX") || ! WriteItem( 10, "-1.000000000000000E+20") || ! WriteItem( 20, "-1.000000000000000E+20") || ! WriteItem( 30, "-1.000000000000000E+20") || ! WriteItem( 9, "$PLIMMIN") || ! WriteItem( 10, "0.0") || ! WriteItem( 20, "0.0") || ! WriteItem( 9, "$PLIMMAX") || ! WriteItem( 10, "12.0") || ! WriteItem( 20, "9.0") || ! WriteItem( 9, "$UNITMODE") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$VISRETAIN") || ! WriteItem( 70, "1") || ! WriteItem( 9, "$PLINEGEN") || ! WriteItem( 70, "0") || ! WriteItem( 9, "$PSLTSCALE") || ! WriteItem( 70, "1") ) 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 VPORT if ( ! WriteVPortTable( pGDB, nId)) 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 ; // scrittura tavole varie if ( ! WriteOtherTables( pGDB, nId)) return false ; // terminazione sezione tables if ( ! WriteItem( 0, "ENDSEC")) return false ; return true ; } //---------------------------------------------------------------------------- bool ExportDxf::WriteVPortTable( IGeomDB* pGDB, int nId) { // scrittura intestazione della tavola if ( ! WriteItem( 0, "TABLE") || ! WriteItem( 2, "VPORT")) return false ; // dati if ( ! WriteItem( 70, "1") || ! WriteItem( 0, "VPORT") || ! WriteItem( 2, "*ACTIVE") || ! WriteItem( 70, "0") || ! WriteItem( 10, "0.0") || ! WriteItem( 20, "0.0") || ! WriteItem( 11, "1.0") || ! WriteItem( 21, "1.0") || ! WriteItem( 12, "10.42990654205607") || ! WriteItem( 22, "4.5") || ! WriteItem( 13, "0.0") || ! WriteItem( 23, "0.0") || ! WriteItem( 14, "0.5") || ! WriteItem( 24, "0.5") || ! WriteItem( 15, "0.5") || ! WriteItem( 25, "0.5") || ! WriteItem( 16, "0.0") || ! WriteItem( 26, "0.0") || ! WriteItem( 36, "1.0") || ! WriteItem( 17, "0.0") || ! WriteItem( 27, "0.0") || ! WriteItem( 37, "0.0") || ! WriteItem( 40, "9.0") || ! WriteItem( 41, "1.972972972850329") || ! WriteItem( 42, "50.0") || ! WriteItem( 43, "0.0") || ! WriteItem( 44, "0.0") || ! WriteItem( 50, "0.0") || ! WriteItem( 51, "0.0") || ! WriteItem( 71, "0") || ! WriteItem( 72, "100") || ! WriteItem( 73, "1") || ! WriteItem( 74, "3") || ! WriteItem( 75, "0") || ! WriteItem( 76, "0") || ! WriteItem( 77, "0") || ! WriteItem( 78, "0")) return false ; // scrittura terminazione della tavola if ( ! WriteItem( 0, "ENDTAB")) 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 ; // 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 non lo abilita, esco subito if ( ! TestFilter( nLev, nMode, nStat)) 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)) if ( ! WriteItem( 70, 1)) 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::WriteOtherTables( IGeomDB* pGDB, int nId) { // tavola VIEW if ( ! WriteItem( 0, "TABLE") || ! WriteItem( 2, "VIEW") || ! WriteItem( 70, "0") || ! WriteItem( 0, "ENDTAB")) return false ; // tavola UCS if ( ! WriteItem( 0, "TABLE") || ! WriteItem( 2, "UCS") || ! WriteItem( 70, "0") || ! WriteItem( 0, "ENDTAB")) return false ; // tavola APPID/ACAD if ( ! WriteItem( 0, "TABLE") || ! WriteItem( 2, "APPID") || ! WriteItem( 70, "1") || ! WriteItem( 0, "APPID") || ! WriteItem( 2, "ACAD") || ! WriteItem( 70, "0") || ! WriteItem( 0, "ENDTAB")) return false ; // tavola DIMSTYLE if ( ! WriteItem( 0, "TABLE") || ! WriteItem( 2, "DIMSTYLE") || ! WriteItem( 70, "1") || ! WriteItem( 0, "DIMSTYLE") || ! WriteItem( 2, "STANDARD") || ! WriteItem( 70, "0") || ! WriteItem( 3, "") || ! WriteItem( 4, "") || ! WriteItem( 5, "") || ! WriteItem( 6, "") || ! WriteItem( 7, "") || ! WriteItem( 40, "1.0") || ! WriteItem( 41, "0.18") || ! WriteItem( 42, "0.0625") || ! WriteItem( 43, "0.38") || ! WriteItem( 44, "0.18") || ! WriteItem( 45, "0.0") || ! WriteItem( 46, "0.0") || ! WriteItem( 47, "0.0") || ! WriteItem( 48, "0.0") || ! WriteItem( 140, "0.18") || ! WriteItem( 141, "0.09") || ! WriteItem( 142, "0.0") || ! WriteItem( 143, "25.4") || ! WriteItem( 144, "1.0") || ! WriteItem( 145, "0.0") || ! WriteItem( 146, "1.0") || ! WriteItem( 147, "0.09") || ! WriteItem( 71, "0") || ! WriteItem( 72, "0") || ! WriteItem( 73, "1") || ! WriteItem( 74, "1") || ! WriteItem( 75, "0") || ! WriteItem( 76, "0") || ! WriteItem( 77, "0") || ! WriteItem( 78, "0") || ! WriteItem( 170, "0") || ! WriteItem( 171, "2") || ! WriteItem( 172, "0") || ! WriteItem( 173, "0") || ! WriteItem( 174, "0") || ! WriteItem( 175, "0") || ! WriteItem( 176, "0") || ! WriteItem( 177, "0") || ! WriteItem( 178, "0") || ! WriteItem( 0, "ENDTAB")) return false ; return true ; } //---------------------------------------------------------------------------- bool ExportDxf::ExportBlocks( IGeomDB* pGDB, int nId) { // intestazione sezione blocks if ( ! WriteItem( 0, "SECTION") || ! WriteItem( 2, "BLOCKS")) return false ; // blocco ModelSpace if ( ! WriteItem( 0, "BLOCK") || ! WriteItem( 8, "0") || ! WriteItem( 2, "$MODEL_SPACE") || ! WriteItem( 70, "0") || ! WriteItem( 10, "0.0") || ! WriteItem( 20, "0.0") || ! WriteItem( 30, "0.0") || ! WriteItem( 3, "$MODEL_SPACE") || ! WriteItem( 1, "") || ! WriteItem( 0, "ENDBLK")) return false ; // blocco PaperSpace if ( ! WriteItem( 0, "BLOCK") || ! WriteItem( 67, "1") || ! WriteItem( 8, "0") || ! WriteItem( 2, "$PAPER_SPACE") || ! WriteItem( 70, "0") || ! WriteItem( 10, "0.0") || ! WriteItem( 20, "0.0") || ! WriteItem( 30, "0.0") || ! WriteItem( 3, "$PAPER_SPACE") || ! WriteItem( 1, "") || ! WriteItem( 0, "ENDBLK")) return false ; // terminazione sezione blocks if ( ! WriteItem( 0, "ENDSEC")) 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 gruppo di oggetti if ( nGdbType == GDB_TY_GROUP) { // esporto il gruppo return ExportGdbGroup( iIter, sLay) ; } // se oggetto geometrico else 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_BEZIER : 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 ; } 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->IsPlane()) { // 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.GetDist() * plPlane.GetVersN()), plPlane.GetVersN()) ; 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.GetDist() * plPlane.GetVersN()), plPlane.GetVersN()) ; 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 ( abs( 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 ( abs( 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 ( abs( 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 ( abs( 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 ( abs( 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 ( abs( 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) { bool bOk = m_Writer.OutText(( nCode < 10 ? " " : nCode < 100 ? " " : "") + ToString( nCode)) ; bOk = bOk && m_Writer.OutText( ToString( nVal)) ; return bOk ; } //---------------------------------------------------------------------------- bool ExportDxf::WriteItem( int nCode, double dVal, int nPrec) { bool bOk = m_Writer.OutText(( nCode < 10 ? " " : nCode < 100 ? " " : "") + ToString( nCode)) ; bOk = bOk && m_Writer.OutText( ToString( dVal, nPrec)) ; return bOk ; } //---------------------------------------------------------------------------- bool ExportDxf::WriteItem( int nCode, const string& sVal) { bool bOk = m_Writer.OutText(( nCode < 10 ? " " : nCode < 100 ? " " : "") + ToString( nCode)) ; bOk = bOk && m_Writer.OutText( sVal) ; return bOk ; } //---------------------------------------------------------------------------- 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, m_bAdvancedNames) ; ToUpper( 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 ; }