Files
Dario Sassi df864c93a8 EgtExchange 2.7k1 :
- adattamenti e ricompilazione per passaggio a C++ 20
2025-11-01 17:34:12 +01:00

970 lines
33 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2015-2015
//----------------------------------------------------------------------------
// File : ImportCsf.cpp Data : 17.05.15 Versione : 1.6e3
// Contenuto : Implementazione della classe per l'importazione di CSF.
//
//
//
// Modifiche : 17.05.15 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "ImportCsf.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/EGkCurveComposite.h"
#include "/EgtDev/Include/EGkCurveAux.h"
#include "/EgtDev/Include/EGkExtText.h"
#include "/EgtDev/Include/EGnStringUtils.h"
#include "/EgtDev/Include/EGnFileUtils.h"
#include "/EgtDev/Include/EgtStringConverter.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#include <fstream>
using namespace std ;
//----------------------------------------------------------------------------
const string INF_TH = "Th" ;
const string INF_SIDE = "Side" ;
const string INF_LBL = "Lbl" ;
const string INF_ATTR = "Attr" ;
//----------------------------------------------------------------------------
struct ExtendedText {
double dH ; // altezza del carattere
double dRat ; // rapporto altezza/larghezza
int nWeight ; // peso
int nColor ; // colore
bool bItalic ; // italico
bool bUnderline ; // sottolineato
bool bStrikeout ; // barrato
std::string sFont ; // nome del font
std::string sText ; // stringa di testo
PNTVECTOR vPnt ; // vettore dei punti di inserimento
DBLVECTOR vAng ; // vettore degli angoli
ExtendedText( void) : dH( 0), dRat( 0), nWeight( 400), nColor( 0),
bItalic( false), bUnderline( false), bStrikeout( false) {}
} ;
//----------------------------------------------------------------------------
IImportCsf*
CreateImportCsf( void)
{
// verifico la chiave e le opzioni
if ( ! VerifyKey( KEYOPT_EEX_INPBASE))
return nullptr ;
// creo l'oggetto
return static_cast<IImportCsf*> ( new(nothrow) ImportCsf) ;
}
//----------------------------------------------------------------------------
ImportCsf::ImportCsf( void)
{
m_pGDB = nullptr ;
m_bIsMM = true ;
m_dThick = 0 ;
m_nCurrPart = - 1 ;
m_nCurrLay = - 1 ;
m_nCurrPartId = GDB_ID_NULL ;
m_nCurrLayId = GDB_ID_NULL ;
}
//----------------------------------------------------------------------------
bool
ImportCsf::Import( const string& sFile, IGeomDB* pGDB)
{
// verifico il DB geometrico
if ( pGDB == nullptr) {
LOG_ERROR( GetEExLogger(), "ImportCsf : Error on GeomDB")
return false ;
}
m_pGDB = pGDB ;
// nomi dei file
string sHedFile = ChangeFileExtension( sFile, "hed") ;
string sEntFile = ChangeFileExtension( sFile, "ent") ;
string sEnsFile = ChangeFileExtension( sFile, "ens") ;
// apertura del file delle entità
ifstream InEntFile ;
InEntFile.open( stringtoW( sEntFile), ios::in | ios::binary) ;
if ( InEntFile.fail()) {
string sErr = "ImportCsf : Error opening " + sEntFile ;
LOG_ERROR( GetEExLogger(), sErr.c_str())
return false ;
}
// apertura del secondo file delle entità
m_InEnsFile.open( stringtoW( sEnsFile), ios::in | ios::binary) ;
if ( m_InEnsFile.fail()) {
string sErr = "ImportCsf : Error opening " + sEnsFile ;
LOG_ERROR( GetEExLogger(), sErr.c_str())
// non è detto sia un errore, potrebbe non essere necessario
}
// lettura dell'header
bool bOk = ReadHeader( sHedFile) ;
// lettura di eventuali attributi
bOk = ReadAttribs() && bOk ;
// impostazione del colore di default nero
m_pGDB->SetDefaultMaterial( BLACK) ;
// ciclo di lettura delle entità
while ( true) {
// lettura
CsfEnt csfEnt ;
InEntFile.read( reinterpret_cast<char*>( &csfEnt), CSFENT_SIZE) ;
if ( InEntFile.gcount() != CSFENT_SIZE)
break ;
// interpretazione
if ( ! ProcessEntity( csfEnt)) {
bOk = false ;
string sErr = "ImportCsf : Error on Entity" ;
LOG_ERROR( GetEExLogger(), sErr.c_str())
}
}
// chiusura dei file
InEntFile.close() ;
m_InEnsFile.close() ;
return bOk ;
}
//----------------------------------------------------------------------------
bool
ImportCsf::ReadHeader( const string& sHedFile)
{
// apertura del file di intestazione
ifstream InHedFile ;
InHedFile.open( stringtoW( sHedFile), ios::in | ios::binary) ;
if ( InHedFile.fail()) {
string sErr = "ImportCsf : Error opening " + sHedFile ;
LOG_ERROR( GetEExLogger(), sErr.c_str())
return false ;
}
// lettura dei dati
CsfHeader csfHed ;
InHedFile.read( reinterpret_cast<char*>( &csfHed), CSFHEADER_SIZE) ;
bool bOk = ( InHedFile.gcount() == CSFHEADER_SIZE) ;
// imposto unità di misura e spessore di progetto
m_bIsMM = ( csfHed.nUnits == 1) ;
m_dThick = - ConvertToMM( csfHed.dThick) ;
// chiusura del file
InHedFile.close() ;
return bOk ;
}
//----------------------------------------------------------------------------
bool
ImportCsf::ReadAttribs( void)
{
// verifico che il secondo file delle entità sia aperto
if ( ! m_InEnsFile.is_open())
return false ;
// mi porto all'inizio del file
m_InEnsFile.seekg( 0) ;
if ( m_InEnsFile.fail())
return false ;
// lettura del numero degli attributi
int nAttribNbr ;
m_InEnsFile.read( reinterpret_cast<char*>( &nAttribNbr), sizeof( nAttribNbr)) ;
if ( m_InEnsFile.gcount() != sizeof( nAttribNbr))
return false ;
// se non ci sono attributi, posso uscire
if ( nAttribNbr == 0)
return true ;
// preparo spazio per gli attributi
try { m_vAttrib.reserve( nAttribNbr) ; }
catch(...) { return false ; }
// leggo gli attributi
for ( int i = 0 ; i < nAttribNbr ; ++ i) {
// lettura
Attrib attr ;
m_InEnsFile.read( reinterpret_cast<char*>( &attr), ATTRIB_SIZE) ;
if ( m_InEnsFile.gcount() != ATTRIB_SIZE)
return false ;
// inserimento nel vettore
m_vAttrib.push_back( attr) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
ImportCsf::ProcessEntity( const CsfEnt& csfEnt)
{
switch ( csfEnt.nType) {
case 2 : // Linea
return ProcessLine( csfEnt) ;
case 3 : // Arco orario
case 4 : // Arco antiorario
return ProcessArc( csfEnt) ;
case 6 : // Foro
return ProcessHole( csfEnt) ;
case 8 : // Testo
return ProcessText( csfEnt) ;
case 11 : // Rettangolo
return ProcessRectangle( csfEnt) ;
case 12 : // Ellisse
return ProcessEllipse( csfEnt) ;
case 14 : // Proprietà
return ProcessProperty( csfEnt) ;
case 16 : // Curva Nurbs
return ProcessCNurbs( csfEnt) ;
case 28 : // Testo esteso
return ProcessExtendedText( csfEnt) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
ImportCsf::ProcessLine( const CsfEnt& csfEnt)
{
// recupero il gruppo di inserimento
int nGrpId = GetPartLayerId( csfEnt.nPart, csfEnt.nPath) ;
if ( nGrpId == GDB_ID_NULL)
return false ;
// creo la linea
PtrOwner<ICurveLine> pCrvLine( CreateCurveLine()) ;
if ( IsNull( pCrvLine))
return false ;
// setto la linea
if ( ! pCrvLine->Set( ConvertToPointMM( csfEnt.dP1x, csfEnt.dP1y, csfEnt.dP1z),
ConvertToPointMM( csfEnt.dP2x, csfEnt.dP2y, csfEnt.dP2z)))
return false ;
// inserisco la linea nel DB
bool bSingle = ( csfEnt.nPart == 0) ;
return AddCurve( Release( pCrvLine), nGrpId, csfEnt.nPar2, bSingle) ;
}
//----------------------------------------------------------------------------
bool
ImportCsf::ProcessArc( const CsfEnt& csfEnt)
{
// recupero il gruppo di inserimento
int nGrpId = GetPartLayerId( csfEnt.nPart, csfEnt.nPath) ;
if ( nGrpId == GDB_ID_NULL)
return false ;
// creo l'arco
PtrOwner<ICurveArc> pCrvArc( CreateCurveArc()) ;
if ( IsNull( pCrvArc))
return false ;
// setto l'arco
if ( ! pCrvArc->Set2PRS( ConvertToPointMM( csfEnt.dP1x, csfEnt.dP1y, csfEnt.dP1z),
ConvertToPointMM( csfEnt.dP2x, csfEnt.dP2y, csfEnt.dP2z),
ConvertToMM( csfEnt.dRad), ( csfEnt.nType == 4)))
return false ;
// inserisco l'arco nel DB
bool bSingle = ( csfEnt.nPart == 0) ;
return AddCurve( Release( pCrvArc), nGrpId, csfEnt.nPar2, bSingle) ;
}
//----------------------------------------------------------------------------
bool
ImportCsf::ProcessHole( const CsfEnt& csfEnt)
{
// recupero il gruppo di inserimento
int nGrpId = GetPartLayerId( csfEnt.nPart, csfEnt.nPath) ;
if ( nGrpId == GDB_ID_NULL)
return false ;
// creo la circonferenza
PtrOwner<ICurveArc> pCrvArc( CreateCurveArc()) ;
if ( IsNull( pCrvArc))
return false ;
// setto la circonferenza
Point3d ptTop = ConvertToPointMM( csfEnt.dP1x, csfEnt.dP1y, csfEnt.dP1z) ;
Point3d ptBot = ConvertToPointMM( csfEnt.dP2x, csfEnt.dP2y, csfEnt.dP2z) ;
Vector3d vtExtr = ptTop - ptBot ;
double dRad = ConvertToMM( csfEnt.dCenx) ;
if ( ! pCrvArc->Set( ptTop, vtExtr, dRad) ||
! pCrvArc->SetExtrusion( vtExtr) ||
! pCrvArc->SetThickness( - vtExtr.Len()))
return false ;
// inserisco la circonferenza nel DB
int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, nGrpId, Release( pCrvArc)) ;
return ( nId != GDB_ID_NULL && AddEntAttrib( nId, 1, csfEnt.nPar2)) ;
}
//----------------------------------------------------------------------------
bool
ImportCsf::ProcessText( const CsfEnt& csfEnt)
{
// recupero il gruppo di inserimento
int nGrpId = GetPartLayerId( csfEnt.nPart, csfEnt.nPath) ;
if ( nGrpId == GDB_ID_NULL)
return false ;
// creo il testo
PtrOwner<IExtText> pTxt( CreateExtText()) ;
if ( IsNull( pTxt))
return false ;
// assegno i dati
Point3d ptP = ConvertToPointMM( csfEnt.dP1x, csfEnt.dP1y, csfEnt.dP1z) ;
// la stringa di testo occupa i successivi 40 caratteri dell'entità
const char* szText = reinterpret_cast<const char*>( &csfEnt.dP2x) ;
// controllo non superi i 39 caratteri di lunghezza (più NULL finale)
if ( strnlen( szText, 40) == 40)
return false ;
string sText = szText ;
double dH = ConvertToMM( csfEnt.dCenz) ;
double dRat = csfEnt.dAng1Deg ;
double dAng = csfEnt.dAng2Deg ;
if ( ! pTxt->Set( ptP, Z_AX, FromPolar( 1, dAng), sText, "", 400, false, dH, dRat, 0))
return false ;
// inserisco il testo nel DB
int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, nGrpId, Release( pTxt)) ;
return ( nId != GDB_ID_NULL && AddEntAttrib( nId, 1, csfEnt.nPar2)) ;
}
//----------------------------------------------------------------------------
bool
ImportCsf::ProcessRectangle( const CsfEnt& csfEnt)
{
// recupero il gruppo di inserimento
int nGrpId = GetPartLayerId( csfEnt.nPart, csfEnt.nPath) ;
if ( nGrpId == GDB_ID_NULL)
return false ;
// creo la curva composita
PtrOwner<ICurveComposite> pCompo( CreateCurveComposite()) ;
if ( IsNull( pCompo))
return false ;
// recupero centro e semiassi del rettangolo
Point3d ptCen = ConvertToPointMM( csfEnt.dP1x, csfEnt.dP1y, csfEnt.dP1z) ;
Vector3d vtMajSax = ConvertToVectorMM( csfEnt.dP2x, csfEnt.dP2y, csfEnt.dP2z) ;
Vector3d vtMinSax = ConvertToVectorMM( csfEnt.dCenx, csfEnt.dCeny, csfEnt.dCenz) ;
if ( vtMajSax.IsSmall() || vtMinSax.IsSmall())
return false ;
// profondità
double dThick = - ConvertToMM( csfEnt.dAng1Deg) ;
// recupero tipo vertici e raggio raccordo o distanza smusso
#pragma pack(2)
struct VertRad { short nVert ; double dRad ; } ;
#pragma pack()
VertRad& VR = (VertRad&) csfEnt.dAng2Deg ;
int nVert = VR.nVert ;
double dRad = ConvertToMM( VR.dRad) ;
// definisco poliarco
PolyArc PA ;
// se spigoli vivi (0)
if ( nVert == 0) {
PA.AddUPoint( 0, ptCen - vtMajSax - vtMinSax, 0) ;
PA.AddUPoint( 1, ptCen + vtMajSax - vtMinSax, 0) ;
PA.AddUPoint( 2, ptCen + vtMajSax + vtMinSax, 0) ;
PA.AddUPoint( 3, ptCen - vtMajSax + vtMinSax, 0) ;
PA.Close() ;
}
// altrimenti raccordi (1) o smussi (2)
else {
Vector3d vtMajDelt = vtMajSax * dRad / vtMajSax.Len() ;
Vector3d vtMinDelt = vtMinSax * dRad / vtMinSax.Len() ;
double dCornBulge = ( ( nVert == 1) ? ( SQRT2 - 1) : 0) ;
PA.AddUPoint( 0, ptCen - vtMajSax - vtMinSax + vtMajDelt, 0) ;
PA.AddUPoint( 1, ptCen + vtMajSax - vtMinSax - vtMajDelt, dCornBulge) ;
PA.AddUPoint( 2, ptCen + vtMajSax - vtMinSax + vtMinDelt, 0) ;
PA.AddUPoint( 3, ptCen + vtMajSax + vtMinSax - vtMinDelt, dCornBulge) ;
PA.AddUPoint( 4, ptCen + vtMajSax + vtMinSax - vtMajDelt, 0) ;
PA.AddUPoint( 5, ptCen - vtMajSax + vtMinSax + vtMajDelt, dCornBulge) ;
PA.AddUPoint( 6, ptCen - vtMajSax + vtMinSax - vtMinDelt, 0) ;
PA.AddUPoint( 7, ptCen - vtMajSax - vtMinSax + vtMinDelt, dCornBulge) ;
PA.Close() ;
}
// costruisco la curva composita
if ( ! pCompo->FromPolyArc( PA))
return false ;
// assegno estrusione e spessore
if ( abs( dThick) > EPS_SMALL) {
pCompo->SetExtrusion( Z_AX) ;
pCompo->SetThickness( dThick) ;
}
// sposto inizio a metà del primo lato
pCompo->ChangeStartPoint( 0.5) ;
// recupero numero di curve componenti
int nCrvNbr = pCompo->GetCurveCount() ;
// inserisco la curva composita nel DB
int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, nGrpId, Release( pCompo)) ;
if ( nId == GDB_ID_NULL)
return false ;
// aggiungo eventuale attributo di entità
for ( int i = 1 ; i <= nCrvNbr ; ++ i)
AddEntAttrib( nId, i, csfEnt.nPar2) ;
return true ;
}
//----------------------------------------------------------------------------
bool
ImportCsf::ProcessEllipse( const CsfEnt& csfEnt)
{
// recupero il gruppo di inserimento
int nGrpId = GetPartLayerId( csfEnt.nPart, csfEnt.nPath) ;
if ( nGrpId == GDB_ID_NULL)
return false ;
// creo la curva composita
PtrOwner<ICurveComposite> pCompo( CreateCurveComposite()) ;
if ( IsNull( pCompo))
return false ;
// recupero centro e semiassi dell'ellisse
Point3d ptCen = ConvertToPointMM( csfEnt.dP1x, csfEnt.dP1y, csfEnt.dP1z) ;
Vector3d vtMajSax = ConvertToVectorMM( csfEnt.dP2x, csfEnt.dP2y, csfEnt.dP2z) ;
Vector3d vtMinSax = ConvertToVectorMM( csfEnt.dCenx, csfEnt.dCeny, csfEnt.dCenz) ;
if ( vtMajSax.IsSmall() || vtMinSax.IsSmall())
return false ;
// profondità
double dThick = - ConvertToMM( csfEnt.dAng1Deg) ;
// creo curva composita formata da circonferenza di semiasse minore
PolyArc PA ;
PA.AddUPoint( 0, ptCen - vtMinSax, 1) ;
PA.AddUPoint( 0, ptCen + vtMinSax, 1) ;
PA.Close() ;
// costruisco la curva composita
if ( ! pCompo->FromPolyArc( PA))
return false ;
// eseguo scalatura non uniforme
Frame3d frFrame ;
frFrame.Set( ptCen, ptCen + vtMajSax, ptCen + vtMinSax) ;
if ( ! pCompo->Scale( frFrame, vtMajSax.Len() / vtMinSax.Len(), 1, 1))
return false ;
// assegno estrusione e spessore
if ( abs( dThick) > EPS_SMALL) {
pCompo->SetExtrusion( Z_AX) ;
pCompo->SetThickness( dThick) ;
}
// recupero numero di curve componenti
int nCrvNbr = pCompo->GetCurveCount() ;
// inserisco la curva composita nel DB
int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, nGrpId, Release( pCompo)) ;
if ( nId == GDB_ID_NULL)
return false ;
// aggiungo eventuale attributo di entità
for ( int i = 1 ; i <= nCrvNbr ; ++ i)
AddEntAttrib( nId, i, csfEnt.nPar2) ;
return true ;
}
//----------------------------------------------------------------------------
bool
ImportCsf::ProcessProperty( const CsfEnt& csfEnt)
{
// tipi di proprietà
const int PROP_COLOR = 1 ;
const int PROP_5A_ATTRIB = 2 ;
const int PROP_VIEW_POINT = 3 ;
const int PROP_FRAME = 4 ;
const int PROP_ATTRIB = 5 ;
// ignoro la proprietà punto di vista
if ( csfEnt.nPar1 == PROP_VIEW_POINT)
return true ;
// recupero il gruppo di inserimento
int nGrpId = GetPartLayerId( csfEnt.nPart, csfEnt.nPath) ;
if ( nGrpId == GDB_ID_NULL)
return false ;
// assegno la proprietà caratteristica
switch ( csfEnt.nPar1) {
case PROP_COLOR :
// colore di percorso
if ( csfEnt.nPar3 == 0) {
Color cCol = CalcColor( csfEnt.nPar2) ;
m_pGDB->SetMaterial( nGrpId, cCol) ;
}
union { short i[4] ; double d ; } dVal ;
dVal.d = csfEnt.dP1x ;
// spessore di percorso
if ( dVal.i[0] != 0)
m_pGDB->SetInfo( nGrpId, INF_TH, - ConvertToMM( csfEnt.dP1y)) ;
// lato di correzione
if ( dVal.i[1] != 0)
m_pGDB->SetInfo( nGrpId, INF_SIDE, dVal.i[1]) ;
return true ;
case PROP_FRAME :
{ Frame3d frFrame ;
if ( ! frFrame.Set( ConvertToPointMM( csfEnt.dP1x, csfEnt.dP1y, csfEnt.dP1z),
Vector3d( csfEnt.dAng1Deg, csfEnt.dAng2Deg, csfEnt.dRad),
Vector3d( csfEnt.dP2x, csfEnt.dP2y, csfEnt.dP2z)))
return false ;
*(m_pGDB->GetGroupFrame( nGrpId)) = frFrame ; }
return true ;
case PROP_ATTRIB :
{ // la stringa occupa gli ultimi 40 caratteri dell'entità
const char* szLabel = reinterpret_cast<const char*>( &csfEnt.dCeny) ;
// controllo non superi i 39 caratteri di lunghezza (più NULL finale)
if ( strnlen( szLabel, 40) == 40)
return false ;
m_pGDB->SetInfo( nGrpId, INF_LBL, string( szLabel)) ; }
return true ;
default :
return true ;
}
}
//----------------------------------------------------------------------------
bool
ImportCsf::ProcessCNurbs( const CsfEnt& csfEnt)
{
// recupero il gruppo di inserimento
int nGrpId = GetPartLayerId( csfEnt.nPart, csfEnt.nPath) ;
if ( nGrpId == GDB_ID_NULL)
return false ;
// recupero offset da inizio dei dati nel file ENS
#pragma pack(2)
struct PosSize { int nPos ; int nSize ; } ;
#pragma pack()
PosSize& PS = (PosSize&) csfEnt.dRad ;
int nPos = PS.nPos ;
// leggo i dati dal file ENS
CNurbsData cnData ;
if ( ! ReadCNurbsData( nPos, cnData))
return false ;
// rendo canonica la rappresentazione della curva Nurbs
if ( ! NurbsCurveCanonicalize( cnData))
return false ;
// creo la curva equivalente alla Nurbs
PtrOwner<ICurve> pCrv( NurbsToBezierCurve( cnData)) ;
if ( IsNull( pCrv))
return false ;
if ( ! pCrv->IsValid())
return true ;
// inserisco la curva nel DB
// inserisco l'arco nel DB
bool bSingle = ( csfEnt.nPart == 0) ;
return AddCurve( Release( pCrv), nGrpId, csfEnt.nPar2, bSingle) ;
}
//----------------------------------------------------------------------------
bool
ImportCsf::ProcessExtendedText( const CsfEnt& csfEnt)
{
// recupero il gruppo di inserimento
int nGrpId = GetPartLayerId( csfEnt.nPart, csfEnt.nPath) ;
if ( nGrpId == GDB_ID_NULL)
return false ;
// recupero offset da inizio dei dati nel file ENS
#pragma pack(2)
struct PosSize { int nDummy ; int nPos ; int nSize ; } ;
#pragma pack()
PosSize& PS = (PosSize&) csfEnt.dCenx ;
int nPos = PS.nPos ;
// leggo i dati dal file ENS
ExtendedText etData ;
if ( ! ReadExtendedTextData( nPos, etData))
return false ;
// coefficienti correttivi empirici
etData.dH *= 0.60 ;
etData.dRat *= 1.75 ;
// salvataggio testo con singolo punto di inserimento
if ( etData.vPnt.size() == 1) {
// creo il testo
PtrOwner<IExtText> pTxt( CreateExtText()) ;
if ( IsNull( pTxt))
return false ;
// assegno i dati
if ( ! pTxt->Set( etData.vPnt[0], Z_AX, FromPolar( 1, etData.vAng[0]),
etData.sText, etData.sFont, etData.nWeight, etData.bItalic, etData.dH, etData.dRat, 0))
return false ;
// inserisco il testo nel DB
int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, nGrpId, Release( pTxt)) ;
if ( nId == GDB_ID_NULL)
return false ;
// assegno il colore (se non default)
if ( etData.nColor != 0) {
Color cCol = CalcColor( etData.nColor) ;
m_pGDB->SetMaterial( nId, cCol) ;
}
// assegno eventuale attributo di entità
AddEntAttrib( nId, 1, csfEnt.nPar2) ;
return true ;
}
// salvataggio testo con un punto di inserimento per ogni carattere
else if ( etData.sText.size() == etData.vPnt.size()) {
for ( int i = 0 ; i < ssize( etData.sText) ; ++ i) {
// creo il testo
PtrOwner<IExtText> pTxt( CreateExtText()) ;
if ( IsNull( pTxt))
return false ;
// assegno i dati
if ( ! pTxt->Set( etData.vPnt[i], Z_AX, FromPolar( 1, etData.vAng[i]),
etData.sText.substr( i, 1), etData.sFont, etData.nWeight, etData.bItalic, etData.dH, etData.dRat, 0))
return false ;
// inserisco il testo nel DB
int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, nGrpId, Release( pTxt)) ;
if ( nId == GDB_ID_NULL)
return false ;
// assegno il colore (se non default)
if ( etData.nColor != 0) {
Color cCol = CalcColor( etData.nColor) ;
m_pGDB->SetMaterial( nId, cCol) ;
}
// assegno eventuale attributo di entità
AddEntAttrib( nId, 1, csfEnt.nPar2) ;
}
return true ;
}
// altrimenti errore
else
return false ;
}
//----------------------------------------------------------------------------
double
ImportCsf::ConvertToMM( double dVal)
{
return ( m_bIsMM ? dVal : dVal * ONEINCH) ;
}
//----------------------------------------------------------------------------
Point3d
ImportCsf::ConvertToPointMM( double dX, double dY, double dZ)
{
if ( m_bIsMM)
return Point3d( dX, dY, dZ) ;
else
return Point3d( dX, dY, dZ) * ONEINCH ;
}
//----------------------------------------------------------------------------
Vector3d
ImportCsf::ConvertToVectorMM( double dX, double dY, double dZ)
{
if ( m_bIsMM)
return Vector3d( dX, dY, dZ) ;
else
return Vector3d( dX, dY, dZ) * ONEINCH ;
}
//----------------------------------------------------------------------------
int
ImportCsf::GetPartLayerId( int nPart, int nPath)
{
// se indici non validi
if ( nPart < 0 || nPath < 0)
return GDB_ID_NULL ;
// se il pezzo non è quello corrente
if ( nPart != m_nCurrPart) {
// cerco il pezzo con il nome desiderato
int nPartId = m_pGDB->GetFirstNameInGroup( GDB_ID_ROOT, ToString( nPart)) ;
// se non trovato, lo creo
if ( nPartId == GDB_ID_NULL) {
nPartId = m_pGDB->AddGroup( GDB_ID_NULL, GDB_ID_ROOT, GLOB_FRM) ;
if ( nPartId == GDB_ID_NULL)
return GDB_ID_NULL ;
m_pGDB->SetName( nPartId, ToString( nPart)) ;
}
m_nCurrPart = nPart ;
m_nCurrPartId = nPartId ;
m_nCurrLay = - 1 ;
m_nCurrLayId = GDB_ID_NULL ;
}
// se il layer non è quello corrente (ma il pezzo qui sicuramente lo è)
if ( nPath != m_nCurrLay) {
// cerco il layer con il nome desiderato
int nLayId = m_pGDB->GetFirstNameInGroup( m_nCurrPartId, ToString( nPath)) ;
// se non trovato, lo creo
if ( nLayId == GDB_ID_NULL) {
nLayId = m_pGDB->AddGroup( GDB_ID_NULL, m_nCurrPartId, GLOB_FRM) ;
if ( nLayId == GDB_ID_NULL)
return GDB_ID_NULL ;
m_pGDB->SetName( nLayId, ToString( nPath)) ;
}
// assegno i valori correnti e ritorno l'id del layer
m_nCurrLay = nPath ;
m_nCurrLayId = nLayId ;
}
// pezzo e layer cercati devono ora coincidere con quelli correnti
return m_nCurrLayId ;
}
//----------------------------------------------------------------------------
Color
ImportCsf::CalcColor( int nInd)
{
switch ( nInd) {
default :
return Color( 0.0, 0.0, 0.0, 1.0) ;
case 1 :
return Color( 0.0, 0.0, 0.5, 1.0) ;
case 2 :
return Color( 0.0, 0.5, 0.0, 1.0) ;
case 3 :
return Color( 0.0, 0.5, 0.5, 1.0) ;
case 4 :
return Color( 0.5, 0.0, 0.0, 1.0) ;
case 5 :
return Color( 0.5, 0.0, 0.5, 1.0) ;
case 6 :
return Color( 0.5, 0.5, 0.0, 1.0) ;
case 7 :
return Color( 0.75, 0.75, 0.75, 1.0) ;
case 8 :
return Color( 0.5, 0.5, 0.5, 1.0) ;
case 9 :
return Color( 0.0, 0.0, 1.0, 1.0) ;
case 10 :
return Color( 0.0, 1.0, 0.0, 1.0) ;
case 11 :
return Color( 0.0, 1.0, 1.0, 1.0) ;
case 12 :
return Color( 1.0, 0.0, 0.0, 1.0) ;
case 13 :
return Color( 1.0, 0.0, 1.0, 1.0) ;
case 14 :
return Color( 1.0, 1.0, 0.0, 1.0) ;
case 15 :
return Color( 1.0, 1.0, 1.0, 1.0) ;
}
}
//----------------------------------------------------------------------------
bool
ImportCsf::AddCurve( ICurve* pCrv, int nGrpId, int nAttribId, bool bSingle)
{
// prendo possesso della curva
PtrOwner<ICurve> pCurve( pCrv) ;
// recupero eventuale spessore del gruppo
double dThick = m_dThick ;
m_pGDB->GetInfo( nGrpId, INF_TH, dThick) ;
// se singola
if ( bSingle) {
if ( abs( dThick) > EPS_SMALL) {
pCurve->SetExtrusion( Z_AX) ;
pCurve->SetThickness( dThick) ;
}
int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, nGrpId, Release( pCurve)) ;
return ( nId != GDB_ID_NULL && AddEntAttrib( nId, 1, nAttribId)) ;
}
// altrimenti parte dell'unica curva composita del gruppo
// se esiste già la curva composita
int nId = m_pGDB->GetFirstInGroup( nGrpId) ;
if ( nId != GDB_ID_NULL) {
ICurveComposite* pCrvCompo = GetCurveComposite( m_pGDB->GetGeoObj( nId)) ;
return ( pCrvCompo != nullptr &&
pCrvCompo->AddCurve( Release( pCurve), true, 10 * EPS_SMALL) &&
AddEntAttrib( nId, pCrvCompo->GetCurveCount(), nAttribId)) ;
}
// altrimenti la creo
PtrOwner<ICurveComposite> pNewCompo( CreateCurveComposite()) ;
if ( IsNull( pNewCompo) || ! pNewCompo->AddCurve( Release( pCurve), true, 10 * EPS_SMALL))
return false ;
if ( abs( dThick) > EPS_SMALL) {
pNewCompo->SetExtrusion( Z_AX) ;
pNewCompo->SetThickness( dThick) ;
}
int nNewId = m_pGDB->AddGeoObj( GDB_ID_NULL, nGrpId, Release( pNewCompo)) ;
return ( nNewId != GDB_ID_NULL && AddEntAttrib( nNewId, 1, nAttribId)) ;
}
//----------------------------------------------------------------------------
bool
ImportCsf::AddEntAttrib( int nEntId, int nSubEntId, int nAttribId)
{
// attributo di entità non previsto
if ( nAttribId <= 0 || nAttribId > int( m_vAttrib.size()))
return true ;
// costruisco la chiave
string sKey = INF_ATTR + "_" + ToString( nSubEntId) ;
// assegno l'attributo
return m_pGDB->SetInfo( nEntId, sKey, string( m_vAttrib[ nAttribId - 1].szText)) ;
}
//----------------------------------------------------------------------------
bool
ImportCsf::ReadCNurbsData( int nPos, CNurbsData& cnData)
{
// verifico che il file sia aperto
if ( ! m_InEnsFile.is_open())
return false ;
// mi porto nella posizione indicata
m_InEnsFile.seekg( nPos) ;
if ( m_InEnsFile.fail())
return false ;
// leggo i dati fissi
#pragma pack( 2)
struct FixedCNurbs {
short nDeg ;
short nBaseType ;
short nExtType ;
short nParamType ;
short nCurveType ;
short nFlatCurve ;
short nIntervNbr ;
short nNodeNbr ;
short nCtrPntNbr ;
short nIntPntNbr ;
short nExtrType ;
short nCtrPntShow ;
short nQualityShow ;
double dStartPar ;
double dEndPar ;
};
const int FIXEDCNURBS_SIZE = sizeof( FixedCNurbs) ; // 42
#pragma pack()
FixedCNurbs FCN ;
m_InEnsFile.read( reinterpret_cast<char*>( &FCN), FIXEDCNURBS_SIZE) ;
if ( m_InEnsFile.gcount() != FIXEDCNURBS_SIZE)
return false ;
// assegno dati fissi
cnData.nDeg = FCN.nDeg ;
cnData.bRat = ( FCN.nBaseType == 0) ;
cnData.bPeriodic = ( FCN.nExtrType == 1) ;
cnData.bClosed = false ;
cnData.bExtraKnotes = false ;
// preparo spazio per dati variabili
cnData.vU.reserve( FCN.nNodeNbr) ;
cnData.vCP.reserve( FCN.nCtrPntNbr) ;
if ( cnData.bRat)
cnData.vW.reserve( FCN.nCtrPntNbr) ;
// leggo i nodi
for ( int i = 0 ; i < FCN.nNodeNbr ; ++ i) {
double dNode ;
m_InEnsFile.read( reinterpret_cast<char*>( &dNode), sizeof( dNode)) ;
if ( m_InEnsFile.gcount() != sizeof( dNode))
return false ;
cnData.vU.emplace_back( dNode) ;
}
// leggo i punti di controllo con eventuali pesi
for ( int i = 0 ; i < FCN.nCtrPntNbr ; ++ i) {
// leggo il punto di controllo
double dCoord[3] ;
m_InEnsFile.read( reinterpret_cast<char*>( dCoord), sizeof( dCoord)) ;
if ( m_InEnsFile.gcount() != sizeof( dCoord))
return false ;
cnData.vCP.emplace_back( ConvertToPointMM( dCoord[0], dCoord[1], dCoord[2])) ;
// se razionale leggo anche il peso
if ( cnData.bRat) {
double dWeight ;
m_InEnsFile.read( reinterpret_cast<char*>( &dWeight), sizeof( dWeight)) ;
if ( m_InEnsFile.gcount() != sizeof( dWeight))
return false ;
cnData.vW.emplace_back( ConvertToMM( dWeight)) ;
}
}
// Verifico il numero di nodi
if ( cnData.vU.size() != FCN.nNodeNbr || FCN.nNodeNbr < 2)
return false ;
// Verifico il numero di punti di controllo
if ( cnData.vCP.size() != FCN.nCtrPntNbr || FCN.nCtrPntNbr < 2)
return false ;
// Verifico il numero di pesi
if ( cnData.bRat && cnData.vW.size() != FCN.nCtrPntNbr)
return false ;
return true ;
}
//----------------------------------------------------------------------------
bool
ImportCsf::ReadExtendedTextData( int nPos, ExtendedText& etData)
{
// verifico che il file sia aperto
if ( ! m_InEnsFile.is_open())
return false ;
// mi porto nella posizione indicata
m_InEnsFile.seekg( nPos) ;
if ( m_InEnsFile.fail())
return false ;
// leggo i dati fissi
#pragma pack( 2)
struct FixedExtText {
double dH ;
double dRat ;
short nStyle ;
short nColor ;
int bItalic ;
int bUnderline ;
int bStrikeout ;
short nCharNbr ;
short nPntNbr ;
};
const int FIXEDEXTTEXT_SIZE = sizeof( FixedExtText) ; // 36
#pragma pack()
FixedExtText FET ;
m_InEnsFile.read( reinterpret_cast<char*>( &FET), FIXEDEXTTEXT_SIZE) ;
if ( m_InEnsFile.gcount() != FIXEDEXTTEXT_SIZE)
return false ;
// assegno i dati fissi
etData.dH = ConvertToMM( FET.dH) ;
etData.dRat = FET.dRat ;
etData.nWeight = FET.nStyle ;
etData.nColor = FET.nColor ;
etData.bItalic = ( FET.bItalic != 0) ;
etData.bUnderline = ( FET.bUnderline != 0) ;
etData.bStrikeout = ( FET.bStrikeout != 0) ;
// preparo spazio per dati variabili
const int FONTNAME_LEN = 31 ;
etData.sFont.reserve( FONTNAME_LEN) ;
etData.sText.reserve( FET.nCharNbr) ;
etData.vPnt.reserve( FET.nPntNbr) ;
etData.vAng.reserve( FET.nPntNbr) ;
// leggo il testo (l'ultimo carattere deve essere null)
for ( int i = 0 ; i < FET.nCharNbr ; ++ i) {
char cVal ;
m_InEnsFile.read( &cVal, 1) ;
if ( m_InEnsFile.gcount() != 1)
return false ;
if ( cVal != '\0')
etData.sText += cVal ;
}
// leggo i punti
for ( int i = 0 ; i < FET.nPntNbr ; ++ i) {
double dCoord[3] ;
m_InEnsFile.read( reinterpret_cast<char*>( dCoord), sizeof( dCoord)) ;
if ( m_InEnsFile.gcount() != sizeof( dCoord))
return false ;
etData.vPnt.emplace_back( ConvertToPointMM( dCoord[0], dCoord[1], dCoord[2])) ;
}
// leggo gli angoli
for ( int i = 0 ; i < FET.nPntNbr ; ++ i) {
double dAng ;
m_InEnsFile.read( reinterpret_cast<char*>( &dAng), sizeof( dAng)) ;
if ( m_InEnsFile.gcount() != sizeof( dAng))
return false ;
etData.vAng.emplace_back( dAng) ;
}
// leggo il font (devo salvare solo fino al primo null)
bool bSave = true ;
for ( int i = 0 ; i < FONTNAME_LEN ; ++ i) {
char cVal ;
m_InEnsFile.read( &cVal, 1) ;
if ( m_InEnsFile.gcount() != 1)
return false ;
bSave = bSave && ( cVal != '\0') ;
if ( bSave)
etData.sFont += cVal ;
}
// Verifico il numero di caratteri
if ( etData.sText.size() != FET.nCharNbr - 1)
return false ;
// Verifico il numero di punti
if ( etData.vPnt.size() != FET.nPntNbr)
return false ;
// Verifico il numero di angoli
if ( etData.vAng.size() != FET.nPntNbr)
return false ;
return true ;
}