//---------------------------------------------------------------------------- // 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/SELkKeyProc.h" #include "/EgtDev/Include/EgtKeyCodes.h" #include "/EgtDev/Include/EgtStringConverter.h" #include "/EgtDev/Include/EgtPointerOwner.h" #include 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 ( 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( &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( &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( &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( &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 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 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 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 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( &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 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 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( &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 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 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 ( size_t i = 0 ; i < etData.sText.size() ; ++ i) { // creo il testo PtrOwner 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 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 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( &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( &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( 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( &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( &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( 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( &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 ; }