//---------------------------------------------------------------------------- // EgalTech 2019-2019 //---------------------------------------------------------------------------- // File : ExportStl.cpp Data : 15.09.19 Versione : 2.1i2 // Contenuto : Implementazione della classe per l'esportazione in formato SVG. // // // // Modifiche : 15.09.19 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "ExportSvg.h" #include "DllMain.h" #include "/EgtDev/Include/EExDllMain.h" #include "/EgtDev/Include/EGkGeomDB.h" #include "/EgtDev/Include/EGkCurveLine.h" #include "/EgtDev/Include/EGkCurveArc.h" #include "/EgtDev/Include/EGkCurveComposite.h" #include "/EgtDev/Include/EGkExtText.h" #include "/EgtDev/Include/EGkGdbIterator.h" #include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EGnStringUtils.h" #include "/EgtDev/Include/SELkKeyProc.h" #include "/EgtDev/Include/EgtKeyCodes.h" #include "/EgtDev/Include/EgtStringConverter.h" #include "/EgtDev/Include/EgtPointerOwner.h" #include using namespace std ; //---------------------------------------------------------------------------- IExportSvg* CreateExportSvg( void) { // verifico la chiave e le opzioni if ( ! TestKeyForEEx( GetEExKey(), KEYOPT_EEX_EXPBASE, GetEExLogger())) return false ; // creo l'oggetto return static_cast ( new(nothrow) ExportSvg) ; } //---------------------------------------------------------------------------- bool ExportSvg::SetOptions( int nFilter) { m_nFilter = nFilter ; return true ; } //---------------------------------------------------------------------------- bool ExportSvg::Export( IGeomDB* pGDB, int nId, const string& sFile) { // verifico il DB geometrico if ( pGDB == nullptr) { LOG_ERROR( GetEExLogger(), "ExportSvg : Error on GeomDB") return false ; } // verifico l'Id dell'oggetto da esportare if ( ! pGDB->ExistsObj( nId)) { LOG_ERROR( GetEExLogger(), "ExportSvg : Error on Id") return false ; } // apro il file di testo in scrittura m_Writer.Close() ; if ( ! m_Writer.Init( sFile)) { LOG_ERROR( GetEExLogger(), "ExportSvg : Error on open file") return false ; } // Inizializzazioni m_vtMove = V_NULL ; m_usNames.clear() ; bool bOk = true ; // scrivo la sezione di intestazione if ( ! ExportHeader()) bOk = false ; // scrivo le entità if ( ! ExportEntities( pGDB, nId)) bOk = false ; // terminazione file if ( ! ExportFooter()) bOk = false ; // chiudo il file if ( ! m_Writer.Close()) bOk = false ; return bOk ; } //---------------------------------------------------------------------------- bool ExportSvg::ExportHeader( void) { if ( ! m_Writer.OutText( "")) return false ; if ( ! m_Writer.OutText( "")) return false ; return true ; } //---------------------------------------------------------------------------- bool ExportSvg::ExportFooter( void) { if ( ! m_Writer.OutText( "")) return false ; return true ; } //---------------------------------------------------------------------------- bool ExportSvg::ExportEntities( IGeomDB* pGDB, int nId) { // recupero ingombro del progetto BBox3d b3All ; pGDB->GetGlobalBBox( GDB_ID_ROOT, b3All) ; // determino il vettore movimento (le Z sono ignorate) m_vtMove = ( b3All.IsEmpty() ? V_NULL : Point3d( 10, -10, 0) - Point3d( b3All.GetMin().x, b3All.GetMax().y, 0)) ; // creo un iteratore PtrOwner pIter( CreateGdbIterator( pGDB)) ; if ( IsNull( pIter)) return false ; pIter->GoTo( nId) ; // esporto l'oggetto e i suoi eventuali figli return ExportObject( *pIter) ; } //---------------------------------------------------------------------------- bool ExportSvg::ExportObject( const IGdbIterator& iIter) { switch ( iIter.GetGdbType()) { case 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 eventuale nome string sName = "" ; if ( iIter.GetName( sName)) { if ( m_usNames.find( sName) == m_usNames.end()) m_usNames.emplace( sName) ; else sName += "_" + ToString( iIter.GetId()) ; } else sName += "_" + ToString( iIter.GetId()) ; // recupero il colore Color colObj ; iIter.GetCalcMaterial( colObj) ; // emetto l'oggetto switch ( pGeoObj->GetType()) { case CRV_LINE : if ( ! ExportLine( sName, colObj, pGeoObj, frFrame)) return false ; break ; case CRV_ARC : if ( ! ExportArc( sName, colObj, pGeoObj, frFrame)) return false ; break ; case CRV_COMPO : if ( ! ExportComposite( sName, colObj, pGeoObj, frFrame)) return false ; break ; case EXT_TEXT : if ( ! ExportText( sName, colObj, pGeoObj, frFrame)) return false ; break ; default : break ; } } } return true ; case GDB_TY_GROUP : // esploro il gruppo return ScanGroup( iIter) ; default : return false ; } } //---------------------------------------------------------------------------- bool ExportSvg::ScanGroup( const IGdbIterator& iIter) { // creo un iteratore PtrOwner pIter( CreateGdbIterator( iIter.GetGDB())) ; if ( IsNull( pIter)) return false ; // scandisco il gruppo bool bOk = true ; for ( bool bNext = pIter->GoToFirstInGroup( iIter) ; bNext ; bNext = pIter->GoToNext()) { if ( ! ExportObject( *pIter)) bOk = false ; } return bOk ; } //---------------------------------------------------------------------------- bool ExportSvg::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 ExportSvg::ExportLine( const string& sName, const Color& colObj, const IGeoObj* pGeoObj, const Frame3d& frFrame) { // verifico oggetto const ICurveLine* pLine = GetCurveLine( pGeoObj) ; if ( pLine == nullptr) return false ; // assegno tipo string sOut = " GetStart() ; ptStart.ToGlob( frFrame) ; ptStart += m_vtMove ; Point3d ptEnd = pLine->GetEnd() ; ptEnd.ToGlob( frFrame) ; ptEnd += m_vtMove ; sOut += " x1=\"" + ToString( ptStart.x, 3) + "\" y1=\"" + ToString( -ptStart.y, 3) + "\" x2=\"" + ToString( ptEnd.x, 3) + "\" y2=\"" + ToString( -ptEnd.y, 3) + "\"" ; // colore e spessore sOut += " stroke=\"" + GetColorString( colObj) + "\" stroke-width=\"1\"" ; // termino sOut += " />" ; // emetto return m_Writer.OutText( sOut) ; } //---------------------------------------------------------------------------- bool ExportSvg::ExportArc( const string& sName, const Color& colObj, const IGeoObj* pGeoObj, const Frame3d& frFrame) { // verifico oggetto const ICurveArc* pArc = GetCurveArc( pGeoObj) ; if ( pArc == nullptr) return false ; // assegno tipo string sOut = " GetStartPoint( ptStart) ; ptStart.ToGlob( frFrame) ; ptStart += m_vtMove ; Point3d ptEnd ; pArc->GetEndPoint( ptEnd) ; ptEnd.ToGlob( frFrame) ; ptEnd += m_vtMove ; double dRad = pArc->GetRadius() ; bool bCCW = ( pArc->GetAngCenter() > 0) ; // assegno l'inizio dell'arco sOut += " d=\"M " + ToString( ptStart.x, 3) + "," + ToString( -ptStart.y, 3) ; // se arco esportabile in una parte if ( abs( pArc->GetAngCenter()) <= ANG_STRAIGHT + 10 * EPS_ANG_SMALL) { sOut += " A " + ToString( dRad, 3) + "," + ToString( dRad, 3) + " 0 0," + ( bCCW ? "0 " : "1 ") + ToString( ptEnd.x, 3) + "," + ToString( -ptEnd.y, 3) + "\"" ; } // altrimenti lo esporto in due parti else { // recupero il punto medio Point3d ptMid ; pArc->GetMidPoint( ptMid) ; ptMid.ToGlob( frFrame) ; ptMid += m_vtMove ; sOut += " A " + ToString( dRad, 3) + "," + ToString( dRad, 3) + " 0 0," + ( bCCW ? "0 " : "1 ") + ToString( ptMid.x, 3) + "," + ToString( -ptMid.y, 3) + " A " + ToString( dRad, 3) + "," + ToString( dRad, 3) + " 0 0," + ( bCCW ? "0 " : "1 ") + ToString( ptEnd.x, 3) + "," + ToString( -ptEnd.y, 3) + "\"" ; } // colore e spessore sOut += " fill=\"none\" stroke=\""+ GetColorString( colObj) + "\" stroke-width=\"1\"" ; // termino sOut += " />" ; // emetto return m_Writer.OutText( sOut) ; } //---------------------------------------------------------------------------- bool ExportSvg::ExportComposite( const string& sName, const Color& colObj, const IGeoObj* pGeoObj, const Frame3d& frFrame) { // verifico oggetto const ICurveComposite* pCompo = GetCurveComposite( pGeoObj) ; if ( pCompo == nullptr) return false ; // assegno tipo string sOut = " GetStartPoint( ptStart) ; ptStart.ToGlob( frFrame) ; ptStart += m_vtMove ; sOut += " d=\"M " + ToString( ptStart.x, 3) + "," + ToString( -ptStart.y, 3) ; // ciclo sulle curve elementari const ICurve* pCrv = pCompo->GetFirstCurve() ; while ( pCrv != nullptr) { if ( pCrv->GetType() == CRV_LINE) { // recupero la linea const ICurveLine* pLine = GetCurveLine( pCrv) ; if ( pLine == nullptr) return false ; // recupero il punto finale Point3d ptEnd = pLine->GetEnd() ; ptEnd.ToGlob( frFrame) ; ptEnd += m_vtMove ; // aggiungo il punto sOut += " L " + ToString( ptEnd.x, 3) + "," + ToString( -ptEnd.y, 3) ; } else if ( pCrv->GetType() == CRV_ARC) { // recupero l'arco const ICurveArc* pArc = GetCurveArc( pCrv) ; if ( pArc == nullptr) return false ; // recupero i dati geometrici dell'arco (estremi, angolo al centro e senso) Point3d ptStart ; pArc->GetStartPoint( ptStart) ; ptStart.ToGlob( frFrame) ; ptStart += m_vtMove ; Point3d ptEnd ; pArc->GetEndPoint( ptEnd) ; ptEnd.ToGlob( frFrame) ; ptEnd += m_vtMove ; double dRad = pArc->GetRadius() ; bool bCCW = ( pArc->GetAngCenter() > 0) ; // se arco esportabile in una parte if ( abs( pArc->GetAngCenter()) <= ANG_STRAIGHT + 10 * EPS_ANG_SMALL) { sOut += " A " + ToString( dRad, 3) + "," + ToString( dRad, 3) + " 0 0," + ( bCCW ? "0 " : "1 ") + ToString( ptEnd.x, 3) + "," + ToString( -ptEnd.y, 3) ; } // altrimenti lo esporto in due parti else { // recupero il punto medio Point3d ptMid ; pArc->GetMidPoint( ptMid) ; ptMid.ToGlob( frFrame) ; ptMid += m_vtMove ; sOut += " A " + ToString( dRad, 3) + "," + ToString( dRad, 3) + " 0 0," + ( bCCW ? "0 " : "1 ") + ToString( ptMid.x, 3) + "," + ToString( -ptMid.y, 3) + " A " + ToString( dRad, 3) + "," + ToString( dRad, 3) + " 0 0," + ( bCCW ? "0 " : "1 ") + ToString( ptEnd.x, 3) + "," + ToString( -ptEnd.y, 3) ; } } else return false ; pCrv = pCompo->GetNextCurve() ; } // termino i dati geometrici sOut += "\"" ; // colore e spessore sOut += " fill=\"none\" stroke=\"" + GetColorString( colObj) + "\" stroke-width=\"1\"" ; // termino sOut += " />" ; // emetto return m_Writer.OutText( sOut) ; } //---------------------------------------------------------------------------- bool ExportSvg::ExportText( const string& sName, const Color& colObj, const IGeoObj* pGeoObj, const Frame3d& frFrame) { // verifico oggetto const IExtText* pText = GetExtText( pGeoObj) ; if ( pText == nullptr) return false ; // assegno tipo string sOut = " GetStartPoint( ptStart) ; ptStart.ToGlob( frFrame) ; ptStart += m_vtMove ; sOut += " x=\"" + ToString( ptStart.x, 3) + "\" y=\"" + ToString( -ptStart.y, 3) + "\"" ; // dimensione del font double dH = pText->GetHeight() ; sOut += " font-size=\"" + ToString( dH, 3) + "\"" ; // colore sOut += " fill=\"" + GetColorString( colObj) + "\">" ; // recupero il contenuto string sText = pText->GetText() ; sOut += sText ; // termino sOut += "" ; // emetto return m_Writer.OutText( sOut) ; } //---------------------------------------------------------------------------- string ExportSvg::GetColorString( const Color& colObj) { string sCol = "rgb(" + ToString( colObj.GetIntRed()) + "," + ToString( colObj.GetIntGreen()) + "," + ToString( colObj.GetIntBlue()) + ")" ; return sCol ; }