8426092c6f
- migliorato controllo gestione chiave di rete.
796 lines
27 KiB
C++
796 lines
27 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/EGkGeoPoint3d.h"
|
|
#include "/EgtDev/Include/EGkCurveLine.h"
|
|
#include "/EgtDev/Include/EGkCurveArc.h"
|
|
#include "/EgtDev/Include/EGkCurveBezier.h"
|
|
#include "/EgtDev/Include/EGkCurveComposite.h"
|
|
#include "/EgtDev/Include/EGkSurfFlatRegion.h"
|
|
#include "/EgtDev/Include/EGkSurfTriMesh.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 ( ! VerifyKey( KEYOPT_EEX_EXPBASE))
|
|
return nullptr ;
|
|
// 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 ;
|
|
|
|
// recupero l'elenco degli oggetti da esportare e il loro ingombro totale
|
|
INTDBLVECTOR vEnt ;
|
|
BBox3d b3All ;
|
|
CalcEntBBox( pGDB, nId, vEnt, b3All) ;
|
|
|
|
// ordino gli oggetti secondo la Z crescente
|
|
stable_sort( vEnt.begin(), vEnt.end(), []( const INTDBL& a, const INTDBL& b)
|
|
{ return a.second < b.second ; }) ;
|
|
|
|
// scrivo la sezione di intestazione
|
|
double dDimX = b3All.GetDimX() ;
|
|
double dDimY = b3All.GetDimY() ;
|
|
if ( ! ExportHeader( dDimX, dDimY))
|
|
bOk = false ;
|
|
|
|
// scrivo le entità
|
|
if ( ! ExportEntities( pGDB, vEnt, b3All))
|
|
bOk = false ;
|
|
|
|
// terminazione file
|
|
if ( ! ExportFooter())
|
|
bOk = false ;
|
|
|
|
// chiudo il file
|
|
if ( ! m_Writer.Close())
|
|
bOk = false ;
|
|
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExportSvg::CalcEntBBox( IGeomDB* pGDB, int nId, INTDBLVECTOR& vEnt, BBox3d& b3Box)
|
|
{
|
|
// reset del bounding box
|
|
b3Box.Reset() ;
|
|
// creo un iteratore
|
|
PtrOwner<IGdbIterator> pIter( CreateGdbIterator( pGDB)) ;
|
|
if ( IsNull( pIter))
|
|
return false ;
|
|
pIter->GoTo( nId) ;
|
|
// eseguo il calcolo
|
|
return CalcGdbObjectEntBBox( *pIter, vEnt, b3Box) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExportSvg::CalcGdbObjectEntBBox( const IGdbIterator& iIter, INTDBLVECTOR& vEnt, BBox3d& b3Box)
|
|
{
|
|
// se gruppo
|
|
if ( iIter.GetGdbType() == GDB_TY_GROUP) {
|
|
// esploro il gruppo
|
|
return CalcGdbGroupEntBBox( iIter, vEnt, b3Box) ;
|
|
}
|
|
// se oggetto geometrico
|
|
else if ( iIter.GetGdbType() == GDB_TY_GEO) {
|
|
// 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)) {
|
|
BBox3d b3Tmp ;
|
|
if ( iIter.GetGlobalBBox( b3Tmp, BBF_EXACT)) {
|
|
vEnt.emplace_back( iIter.GetId(), ( b3Tmp.GetMin().z + b3Tmp.GetMax().z) / 2) ;
|
|
b3Box.Add( b3Tmp) ;
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
// altrimenti errore
|
|
else
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExportSvg::CalcGdbGroupEntBBox( const IGdbIterator& iIter, INTDBLVECTOR& vEnt, BBox3d& b3Box)
|
|
{
|
|
// 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 ( ! CalcGdbObjectEntBBox( *pIter, vEnt, b3Box))
|
|
bOk = false ;
|
|
}
|
|
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExportSvg::ExportHeader( double dDimX, double dDimY)
|
|
{
|
|
if ( ! m_Writer.OutText( "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"))
|
|
return false ;
|
|
const double MIN_DIM = 10 ;
|
|
dDimX = max( dDimX, MIN_DIM) ;
|
|
dDimY = max( dDimY, MIN_DIM) ;
|
|
const double COEFF = 0.05 ;
|
|
double dExtraX = COEFF * dDimX ;
|
|
double dExtraY = COEFF * dDimY ;
|
|
string sOut = "<svg viewBox=\"" + ToString( - dExtraX, 0) + " " + ToString( - dExtraY, 0) + " " +
|
|
ToString( dDimX + 2 * dExtraX, 0) + " " + ToString( dDimY + 2 * dExtraY, 0) + "\"" +
|
|
" xmlns=\"http://www.w3.org/2000/svg\">" ;
|
|
if ( ! m_Writer.OutText( sOut))
|
|
return false ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExportSvg::ExportFooter( void)
|
|
{
|
|
if ( ! m_Writer.OutText( "</svg>"))
|
|
return false ;
|
|
return true ;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExportSvg::ExportEntities( IGeomDB* pGDB, const INTDBLVECTOR& vEnt, const BBox3d& b3All)
|
|
{
|
|
// determino il vettore movimento (le Z sono ignorate)
|
|
m_vtMove = ( b3All.IsEmpty() ? V_NULL : Point3d( 0, 0, 0) - Point3d( b3All.GetMin().x, b3All.GetMax().y, 0)) ;
|
|
// ciclo sulle entità da esportare
|
|
bool bOk = true ;
|
|
for ( int i = 0 ; i < int( vEnt.size()) ; ++i) {
|
|
// recupero l'oggetto geometrico
|
|
const IGeoObj* pGeoObj = pGDB->GetGeoObj( vEnt[i].first) ;
|
|
if ( pGeoObj == nullptr) {
|
|
bOk = false ;
|
|
continue ;
|
|
}
|
|
// recupero il riferimento globale dell'oggetto
|
|
Frame3d frFrame ;
|
|
if ( ! pGDB->GetGlobFrame( vEnt[i].first, frFrame)) {
|
|
bOk = false ;
|
|
continue ;
|
|
}
|
|
// recupero eventuale nome
|
|
string sName = "" ;
|
|
if ( pGDB->GetName( vEnt[i].first, sName)) {
|
|
if ( m_usNames.find( sName) == m_usNames.end())
|
|
m_usNames.emplace( sName) ;
|
|
else
|
|
sName += "_" + ToString( vEnt[i].first) ;
|
|
}
|
|
else
|
|
sName += "_" + ToString( vEnt[i].first) ;
|
|
// recupero il colore
|
|
Color colObj ;
|
|
pGDB->GetCalcMaterial( vEnt[i].first, colObj) ;
|
|
// emetto l'oggetto
|
|
switch ( pGeoObj->GetType()) {
|
|
case GEO_PNT3D :
|
|
if ( ! ExportPoint( sName, colObj, pGeoObj, frFrame))
|
|
bOk = false ;
|
|
break ;
|
|
case CRV_LINE :
|
|
if ( ! ExportLine( sName, colObj, pGeoObj, frFrame))
|
|
bOk = false ;
|
|
break ;
|
|
case CRV_ARC :
|
|
if ( ! ExportArc( sName, colObj, pGeoObj, frFrame, false))
|
|
bOk = false ;
|
|
break ;
|
|
case CRV_BEZIER :
|
|
if ( ! ExportBezier( sName, colObj, pGeoObj, frFrame, false))
|
|
bOk = false ;
|
|
break ;
|
|
case CRV_COMPO :
|
|
if ( ! ExportComposite( sName, colObj, pGeoObj, frFrame, false))
|
|
bOk = false ;
|
|
break ;
|
|
case SRF_FLATRGN :
|
|
if ( ! ExportFlatRegion( sName, colObj, pGeoObj, frFrame))
|
|
bOk = false ;
|
|
break ;
|
|
case SRF_TRIMESH :
|
|
if ( ! ExportTriMesh( sName, colObj, pGeoObj, frFrame))
|
|
bOk = false ;
|
|
break ;
|
|
case EXT_TEXT :
|
|
if ( ! ExportText( sName, colObj, pGeoObj, frFrame))
|
|
bOk = false ;
|
|
break ;
|
|
}
|
|
}
|
|
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::ExportPoint( const string& sName, const Color& colObj, const IGeoObj* pGeoObj, const Frame3d& frFrame)
|
|
{
|
|
// verifico oggetto
|
|
const IGeoPoint3d* pGpt = GetGeoPoint3d( pGeoObj) ;
|
|
if ( pGpt == nullptr)
|
|
return false ;
|
|
// lo copio e lo porto in globale
|
|
PtrOwner<IGeoPoint3d> pMyGpt( pGpt->Clone()) ;
|
|
if ( IsNull( pMyGpt))
|
|
return false ;
|
|
pMyGpt->ToGlob( frFrame) ;
|
|
// assegno tipo
|
|
string sOut = " <circle" ;
|
|
// aggiungo nome e Id
|
|
sOut += " id=\"" + sName + "\"" ;
|
|
// punto centro
|
|
Point3d ptCen = pGpt->GetPoint() ;
|
|
ptCen.ToGlob( frFrame) ;
|
|
ptCen += m_vtMove ;
|
|
sOut += " cx=\"" + ToString( ptCen.x, 3) + "\" cy=\"" + ToString( -ptCen.y, 3) + "\" r=\"2\"" ;
|
|
// colore e spessore
|
|
sOut += " fill=\"" + GetColorString( colObj) + "\" stroke=\"" + GetColorString( colObj) + "\" stroke-width=\"1\"" ;
|
|
// termino
|
|
sOut += " />" ;
|
|
// emetto
|
|
return m_Writer.OutText( sOut) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
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 ;
|
|
// la copio e la porto in globale
|
|
PtrOwner<ICurveLine> pMyLine( pLine->Clone()) ;
|
|
if ( IsNull( pMyLine))
|
|
return false ;
|
|
pMyLine->ToGlob( frFrame) ;
|
|
// porto nel piano XY globale (se si riduce ad un punto la salto)
|
|
if ( ! pMyLine->Scale( GLOB_FRM, 1, 1, 0))
|
|
return true ;
|
|
// questo oggetto non può avere fill
|
|
bool bFill = false ;
|
|
// assegno tipo
|
|
string sOut = " <path" ;
|
|
// aggiungo nome e Id
|
|
sOut += " id=\"" + sName + "\"" ;
|
|
// aggiungo inizio dati geometrici
|
|
sOut += " d=\"" ;
|
|
// punto iniziale
|
|
sOut +=GetStartString( pMyLine) ;
|
|
// arco
|
|
sOut += GetCurveString( pMyLine) ;
|
|
// termino i dati geometrici
|
|
sOut += "\"" ;
|
|
// colore e spessore
|
|
sOut += " fill=\"" + ( bFill ? GetColorString( colObj) : "none") + "\" 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, bool bFill)
|
|
{
|
|
// verifico oggetto
|
|
const ICurveArc* pArc = GetCurveArc( pGeoObj) ;
|
|
if ( pArc == nullptr)
|
|
return false ;
|
|
// lo inglobo in una curva composita e lo porto in globale
|
|
PtrOwner<ICurveComposite> pMyCompo( CreateCurveComposite()) ;
|
|
if ( IsNull( pMyCompo))
|
|
return false ;
|
|
pMyCompo->AddCurve( *pArc) ;
|
|
pMyCompo->ToGlob( frFrame) ;
|
|
// verifico se la curva giace in un piano parallelo a XY globale
|
|
Plane3d plPlane ;
|
|
if ( ! pMyCompo->IsFlat( plPlane, false, 10 * EPS_SMALL) ||
|
|
! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), Z_AX)) {
|
|
// porto nel piano XY globale
|
|
pMyCompo->Scale( GLOB_FRM, 1, 1, 0) ;
|
|
}
|
|
// assegno tipo
|
|
string sOut = " <path" ;
|
|
// aggiungo nome e Id
|
|
sOut += " id=\"" + sName + "\"" ;
|
|
// aggiungo inizio dati geometrici
|
|
sOut += " d=\"" ;
|
|
// punto iniziale
|
|
sOut +=GetStartString( pMyCompo) ;
|
|
// arco
|
|
sOut += GetCurveString( pMyCompo) ;
|
|
// termino i dati geometrici
|
|
sOut += "\"" ;
|
|
// colore e spessore
|
|
sOut += " fill=\"" + ( bFill ? GetColorString( colObj) : "none") + "\" stroke=\"" + GetColorString( colObj) + "\" stroke-width=\"1\"" ;
|
|
// termino
|
|
sOut += " />" ;
|
|
// emetto
|
|
return m_Writer.OutText( sOut) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExportSvg::ExportBezier( const string& sName, const Color& colObj, const IGeoObj* pGeoObj, const Frame3d& frFrame, bool bFill)
|
|
{
|
|
// verifico oggetto
|
|
const ICurveBezier* pBez = GetCurveBezier( pGeoObj) ;
|
|
if ( pBez == nullptr)
|
|
return false ;
|
|
// la copio e la porto in globale
|
|
PtrOwner<ICurveBezier> pMyBez( pBez->Clone()) ;
|
|
if ( IsNull( pMyBez))
|
|
return false ;
|
|
pMyBez->ToGlob( frFrame) ;
|
|
// verifico se la curva giace in un piano parallelo a XY globale
|
|
Plane3d plPlane ;
|
|
if ( ! pMyBez->IsFlat( plPlane, false, 10 * EPS_SMALL) ||
|
|
! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), Z_AX)) {
|
|
// la porto nel piano XY globale (se si riduce ad un punto la salto)
|
|
if ( ! pMyBez->Scale( GLOB_FRM, 1, 1, 0))
|
|
return true ;
|
|
}
|
|
// assegno tipo
|
|
string sOut = " <path" ;
|
|
// aggiungo nome e Id
|
|
sOut += " id=\"" + sName + "\"" ;
|
|
// aggiungo inizio dati geometrici
|
|
sOut += " d=\"" ;
|
|
// punto iniziale
|
|
sOut +=GetStartString( pMyBez) ;
|
|
// curva di Bezier
|
|
sOut += GetCurveString( pMyBez) ;
|
|
// termino i dati geometrici
|
|
sOut += "\"" ;
|
|
// colore e spessore
|
|
sOut += " fill=\"" + ( bFill ? GetColorString( colObj) : "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, bool bFill)
|
|
{
|
|
// verifico oggetto
|
|
const ICurveComposite* pCompo = GetCurveComposite( pGeoObj) ;
|
|
if ( pCompo == nullptr)
|
|
return false ;
|
|
// la copio e la porto in globale
|
|
PtrOwner<ICurveComposite> pMyCompo( pCompo->Clone()) ;
|
|
if ( IsNull( pMyCompo))
|
|
return false ;
|
|
pMyCompo->ToGlob( frFrame) ;
|
|
// verifico se la curva giace in un piano parallelo a XY globale
|
|
Plane3d plPlane ;
|
|
if ( ! pMyCompo->IsFlat( plPlane, false, 10 * EPS_SMALL) ||
|
|
! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), Z_AX)) {
|
|
// la porto nel piano XY globale (se si riduce ad un punto la salto)
|
|
if ( ! pMyCompo->Scale( GLOB_FRM, 1, 1, 0))
|
|
return true ;
|
|
}
|
|
// assegno tipo
|
|
string sOut = " <path" ;
|
|
// aggiungo nome e Id
|
|
sOut += " id=\"" + sName + "\"" ;
|
|
// aggiungo inizio dati geometrici
|
|
sOut += " d=\"" ;
|
|
// punto iniziale
|
|
sOut += GetStartString( pMyCompo) ;
|
|
// curva composita
|
|
sOut += GetCurveString( pMyCompo) ;
|
|
// termino i dati geometrici
|
|
sOut += "\"" ;
|
|
// colore e spessore
|
|
sOut += " fill=\"" + ( bFill ? GetColorString( colObj) : "none") + "\" stroke=\"" + GetColorString( colObj) + "\" stroke-width=\"1\"" ;
|
|
// termino
|
|
sOut += " />" ;
|
|
// emetto
|
|
return m_Writer.OutText( sOut) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExportSvg::ExportFlatRegion( const string& sName, const Color& colObj, const IGeoObj* pGeoObj, const Frame3d& frFrame)
|
|
{
|
|
// verifico oggetto
|
|
const ISurfFlatRegion* pSfr = GetSurfFlatRegion( pGeoObj) ;
|
|
if ( pSfr == nullptr)
|
|
return false ;
|
|
// verifico che almeno in parte guardi verso Z+ globale
|
|
Vector3d vtN = pSfr->GetNormVersor() ;
|
|
vtN.ToGlob( frFrame) ;
|
|
if ( vtN.z < EPS_SMALL)
|
|
return true ;
|
|
// questo oggetto deve avere fill
|
|
bool bFill = true ;
|
|
// assegno tipo
|
|
string sOut = " <path" ;
|
|
// aggiungo nome e Id
|
|
sOut += " id=\"" + sName + "\"" ;
|
|
// aggiungo inizio dati geometrici
|
|
sOut += " d=\"" ;
|
|
// ciclo sui chunk
|
|
for ( int nC = 0 ; nC < pSfr->GetChunkCount() ; ++ nC) {
|
|
// ciclo sui loop
|
|
for ( int nL = 0 ; nL < pSfr->GetLoopCount( nC) ; ++ nL) {
|
|
// recupero il loop
|
|
PtrOwner<ICurve> pLoop( pSfr->GetLoop( nC, nL)) ;
|
|
if ( IsNull( pLoop))
|
|
return false ;
|
|
// porto la curva in globale
|
|
pLoop->ToGlob( frFrame) ;
|
|
// se necessario, proietto sul piano XY globale
|
|
if ( ! AreSameOrOppositeVectorApprox( vtN, Z_AX)) {
|
|
// se arco devo convertirlo in composita
|
|
if ( pLoop->GetType() == CRV_ARC) {
|
|
PtrOwner<ICurveComposite> pMyCompo( CreateCurveComposite()) ;
|
|
if ( IsNull( pMyCompo))
|
|
return false ;
|
|
pMyCompo->AddCurve( Release( pLoop)) ;
|
|
pLoop.Set( pMyCompo) ;
|
|
}
|
|
pLoop->Scale( GLOB_FRM, 1, 1, 0) ;
|
|
}
|
|
// punto iniziale
|
|
sOut += GetStartString( pLoop) ;
|
|
// curva
|
|
if ( pLoop->GetType() == CRV_LINE)
|
|
sOut += GetCurveString( GetCurveLine( pLoop)) ;
|
|
else if ( pLoop->GetType() == CRV_ARC)
|
|
sOut += GetCurveString( GetCurveArc( pLoop)) ;
|
|
else if ( pLoop->GetType() == CRV_BEZIER)
|
|
sOut += GetCurveString( GetCurveBezier( pLoop)) ;
|
|
else if ( pLoop->GetType() == CRV_COMPO)
|
|
sOut += GetCurveString( GetCurveComposite( pLoop)) ;
|
|
else
|
|
return false ;
|
|
}
|
|
}
|
|
// termino i dati geometrici
|
|
sOut += "\"" ;
|
|
// colore e spessore
|
|
sOut += " fill=\"" + ( bFill ? GetColorString( colObj) : "none") +
|
|
"\" fill-opacity=\"" + ToString( colObj.GetAlpha(), 2) +
|
|
"\" stroke=\"" + GetColorString( colObj) +
|
|
"\" stroke-opacity=\"" + ToString( colObj.GetAlpha(), 2) +
|
|
"\" stroke-width=\"1\"" ;
|
|
// termino
|
|
sOut += " />" ;
|
|
// emetto
|
|
return m_Writer.OutText( sOut) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExportSvg::ExportTriMesh( const string& sName, const Color& colObj, const IGeoObj* pGeoObj, const Frame3d& frFrame)
|
|
{
|
|
// verifico oggetto
|
|
const ISurfTriMesh* pStm = GetSurfTriMesh( pGeoObj) ;
|
|
if ( pStm == nullptr)
|
|
return false ;
|
|
// almeno una faccia deve guardare verzo Z+ globale
|
|
bool bTop = false ;
|
|
for ( int nF = 0 ; nF < pStm->GetFacetCount() ; ++ nF) {
|
|
Vector3d vtN ;
|
|
if ( pStm->GetFacetNormal( nF, vtN) && vtN.ToGlob( frFrame) && vtN.z > EPS_SMALL) {
|
|
bTop = true ;
|
|
break ;
|
|
}
|
|
}
|
|
if ( ! bTop)
|
|
return true ;
|
|
// questo oggetto deve avere fill
|
|
bool bFill = true ;
|
|
// assegno tipo
|
|
string sOut = " <path" ;
|
|
// aggiungo nome e Id
|
|
sOut += " id=\"" + sName + "\"" ;
|
|
// aggiungo inizio dati geometrici
|
|
sOut += " d=\"" ;
|
|
// ciclo sulle facce
|
|
for ( int nF = 0 ; nF < pStm->GetFacetCount() ; ++ nF) {
|
|
// verifico che guardi verso l'alto
|
|
Vector3d vtN ;
|
|
if ( ! pStm->GetFacetNormal( nF, vtN) || ! vtN.ToGlob( frFrame) || vtN.z < EPS_SMALL)
|
|
continue ;
|
|
POLYLINEVECTOR vPL ;
|
|
if ( ! pStm->GetFacetLoops( nF, vPL))
|
|
return false ;
|
|
// ciclo sui loop di una faccia
|
|
for ( int nL = 0 ; nL < int( vPL.size()) ; ++ nL) {
|
|
PtrOwner<ICurveComposite> pLoop( CreateCurveComposite()) ;
|
|
if ( IsNull( pLoop) || ! pLoop->FromPolyLine( vPL[nL]))
|
|
return false ;
|
|
// porto in globale
|
|
pLoop->ToGlob( frFrame) ;
|
|
// punto iniziale
|
|
sOut += GetStartString( pLoop) ;
|
|
// curva
|
|
sOut += GetCurveString( pLoop) ;
|
|
}
|
|
}
|
|
// termino i dati geometrici
|
|
sOut += "\"" ;
|
|
// colore e spessore
|
|
sOut += " fill=\"" + ( bFill ? GetColorString( colObj) : "none") +
|
|
"\" fill-opacity=\"" + ToString( colObj.GetAlpha(), 2) +
|
|
"\" stroke=\"" + GetColorString( colObj) +
|
|
"\" stroke-opacity=\"" + ToString( colObj.GetAlpha(), 2) +
|
|
"\" 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 ;
|
|
// verifico giacitura nel piano XY
|
|
Vector3d vtN = pText->GetNormVersor() ;
|
|
vtN.ToGlob( frFrame) ;
|
|
if ( ! AreSameOrOppositeVectorApprox( vtN, Z_AX))
|
|
return true ;
|
|
// 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 += " transform=\"translate(" + ToString( ptStart.x, 3) + "," + ToString( -ptStart.y, 3) + ")" ;
|
|
// eventuale rotazione
|
|
Vector3d vtDir = pText->GetDirVersor() ;
|
|
vtDir.ToGlob( frFrame) ;
|
|
double dAngH ;
|
|
vtDir.ToSpherical( nullptr, nullptr, &dAngH) ;
|
|
sOut += "rotate(" + ToString( -dAngH, 3) + ")\"" ;
|
|
// famiglia del font
|
|
string sFont = pText->GetFont() ;
|
|
sOut += " font-family=\"" + sFont + "\"" ;
|
|
// dimensione del font
|
|
double dH = pText->GetHeight() ;
|
|
sOut += " font-size=\"" + ToString( dH, 3) + "\"" ;
|
|
// lunghezza suggerita
|
|
Point3d ptEnd ; pText->GetEndPoint( ptEnd) ;
|
|
ptEnd.ToGlob( frFrame) ;
|
|
ptEnd += m_vtMove ;
|
|
double dLen = DistXY( ptStart, ptEnd) ;
|
|
sOut += " textLength=\"" + ToString( dLen, 3) + "\"" ;
|
|
// colore
|
|
sOut += " fill=\"" + GetColorString( colObj) + "\">" ;
|
|
// recupero il contenuto e converto i caratteri speciali
|
|
string sText = pText->GetText() ;
|
|
ReplaceString( sText, "&", "&") ;
|
|
ReplaceString( sText, "<", "<") ;
|
|
sOut += sText ;
|
|
// termino
|
|
sOut += "</text>" ;
|
|
// emetto
|
|
return m_Writer.OutText( sOut) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
string
|
|
ExportSvg::GetStartString( const ICurve* pCrv)
|
|
{
|
|
// verifica
|
|
if ( pCrv == nullptr)
|
|
return "" ;
|
|
Point3d ptStart ; pCrv->GetStartPoint( ptStart) ;
|
|
ptStart += m_vtMove ;
|
|
return " M " + ToString( ptStart.x, 3) + "," + ToString( -ptStart.y, 3) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
string
|
|
ExportSvg::GetCurveString( const ICurveLine* pLine)
|
|
{
|
|
// verifica
|
|
if ( pLine == nullptr)
|
|
return "" ;
|
|
// recupero il punto finale
|
|
Point3d ptEnd = pLine->GetEnd() ;
|
|
ptEnd += m_vtMove ;
|
|
// aggiungo il punto
|
|
return " L " + ToString( ptEnd.x, 3) + "," + ToString( -ptEnd.y, 3) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
string
|
|
ExportSvg::GetCurveString( const ICurveArc* pArc)
|
|
{
|
|
// verifica
|
|
if ( pArc == nullptr)
|
|
return "" ;
|
|
// recupero i dati geometrici dell'arco (estremi, angolo al centro e senso)
|
|
Point3d ptStart ; pArc->GetStartPoint( ptStart) ;
|
|
ptStart += m_vtMove ;
|
|
Point3d ptEnd ; pArc->GetEndPoint( ptEnd) ;
|
|
ptEnd += m_vtMove ;
|
|
double dRad = pArc->GetRadius() ;
|
|
bool bCCW = ( ( pArc->GetAngCenter() > 0 && pArc->GetNormVersor().IsZplus()) ||
|
|
( pArc->GetAngCenter() < 0 && pArc->GetNormVersor().IsZminus())) ;
|
|
// se arco esportabile in una parte
|
|
if ( abs( pArc->GetAngCenter()) <= ANG_STRAIGHT + 10 * EPS_ANG_SMALL) {
|
|
return " 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 += m_vtMove ;
|
|
return " 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) ;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
string
|
|
ExportSvg::GetCurveString( const ICurveBezier* pBez)
|
|
{
|
|
// verifica
|
|
if ( pBez == nullptr)
|
|
return "" ;
|
|
// approssimo con archi e rette
|
|
const double BEZ_LIN_APPROX = 0.01 ;
|
|
const double BEZ_ANG_APPROX_DEG = 5.0 ;
|
|
PtrOwner<ICurveComposite> pCC( CreateCurveComposite()) ;
|
|
PolyArc PA ;
|
|
if ( ! pBez->ApproxWithArcs( BEZ_LIN_APPROX, BEZ_ANG_APPROX_DEG, PA) || ! pCC->FromPolyArc( PA))
|
|
return "" ;
|
|
return GetCurveString( pCC) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
string
|
|
ExportSvg::GetCurveString( const ICurveComposite* pCompo)
|
|
{
|
|
// verifica
|
|
if ( pCompo == nullptr)
|
|
return "" ;
|
|
// ciclo sulle curve elementari
|
|
string sOut ;
|
|
const ICurve* pCrv = pCompo->GetFirstCurve() ;
|
|
while ( pCrv != nullptr) {
|
|
if ( pCrv->GetType() == CRV_LINE)
|
|
sOut += GetCurveString( GetCurveLine( pCrv)) ;
|
|
else if ( pCrv->GetType() == CRV_ARC)
|
|
sOut += GetCurveString( GetCurveArc( pCrv)) ;
|
|
else if ( pCrv->GetType() == CRV_BEZIER)
|
|
sOut += GetCurveString( GetCurveBezier( pCrv)) ;
|
|
else
|
|
return "" ;
|
|
pCrv = pCompo->GetNextCurve() ;
|
|
}
|
|
return sOut ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
string
|
|
ExportSvg::GetColorString( const Color& colObj)
|
|
{
|
|
string sCol = "rgb(" + ToString( colObj.GetIntRed()) + "," +
|
|
ToString( colObj.GetIntGreen()) + "," +
|
|
ToString( colObj.GetIntBlue()) + ")" ;
|
|
return sCol ;
|
|
}
|