Files
EgtExchange/ExportSvg.cpp
T
Dario Sassi ab83b689ba EgtExchange 2.1i2 :
- aggiunta esportazione in formato SVG
- in ExportDxf e ExportStl ora si usa il Writer.
2019-09-16 15:25:16 +00:00

444 lines
15 KiB
C++

//----------------------------------------------------------------------------
// 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 <fstream>
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<IExportSvg*> ( 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( "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"))
return false ;
if ( ! m_Writer.OutText( "<svg xmlns=\"http://www.w3.org/2000/svg\">"))
return false ;
return true ;
}
//----------------------------------------------------------------------------
bool
ExportSvg::ExportFooter( void)
{
if ( ! m_Writer.OutText( "</svg>"))
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<IGdbIterator> 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<IGdbIterator> 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 = " <line" ;
// aggiungo nome e Id
sOut += " id=\"" + sName + "\"" ;
// aggiungo le coordinate dei punti estremi (solo X e Y, con Y invertita di segno)
Point3d ptStart = pLine->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 = " <path" ;
// aggiungo nome e Id
sOut += " id=\"" + sName + "\"" ;
// 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) ;
// 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 = " <path" ;
// aggiungo nome e Id
sOut += " id=\"" + sName + "\"" ;
// inizio
Point3d ptStart ; pCompo->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 = " <text" ;
// aggiungo nome e Id
sOut += " id=\"" + sName + "\"" ;
// recupero posizione
Point3d ptStart ; pText->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 += "</text>" ;
// 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 ;
}