ab83b689ba
- aggiunta esportazione in formato SVG - in ExportDxf e ExportStl ora si usa il Writer.
444 lines
15 KiB
C++
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 ;
|
|
}
|