Back to index

salome-med  6.5.0
MEDMEM_EnsightUtils.hxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // This library is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU Lesser General Public
00005 // License as published by the Free Software Foundation; either
00006 // version 2.1 of the License.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // Lesser General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU Lesser General Public
00014 // License along with this library; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00016 //
00017 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00018 //
00019 
00020 // File      : MEDMEM_EnsightUtils.hxx
00021 // Created   : Tue May 27 12:24:11 2008
00022 // Author    : Edward AGAPOV (eap)
00023 //
00024 #ifndef MEDMEM_EnsightUtils_HeaderFile
00025 #define MEDMEM_EnsightUtils_HeaderFile
00026 
00027 #include "MEDMEM_GenDriver.hxx"
00028 #include "MEDMEM_Exception.hxx"
00029 #include "MEDMEM_DriverTools.hxx"
00030 #include "MEDMEM_Mesh.hxx"
00031 //#include "MEDMEM_Field.hxx"
00032 
00033 #include <set>
00034 #include <float.h>
00035 #include <cmath>
00036 
00037 #ifdef WNT
00038 #define isnan _isnan
00039 #endif
00040 
00041 namespace MEDMEM {
00042 
00043   // ==============================================================================
00048   // ==============================================================================
00049 
00050   enum EnSightFormat { ENSIGHT_6, ENSIGHT_GOLD };
00051 
00052   void MEDMEM_EXPORT setEnSightFormatForWriting (EnSightFormat format, bool isBinary);
00053 
00054   EnSightFormat getEnSightFormatForWriting();
00055   bool          isBinaryEnSightFormatForWriting();
00056 
00057   // ==============================================================================
00068   // ==============================================================================
00069 
00070   void MEDMEM_EXPORT setIgnoreIncompatibility(bool toIgnore=true);
00071 }
00072 
00073 namespace MEDMEM {
00074   class ENSIGHT_MESH_RDONLY_DRIVER;
00075   class ENSIGHT_FIELD_RDONLY_DRIVER;
00076   class ENSIGHT_MESH_WRONLY_DRIVER;
00077   class ENSIGHT_FIELD_WRONLY_DRIVER;
00078 }
00079 
00080 // ==============================================================================
00081 namespace MEDMEM_ENSIGHT { // INTERNAL MATTERS
00082 // ==============================================================================
00083 
00084   class _CaseFileDriver;
00085   class _CaseFileDriver_User;
00086   struct _InterMed;
00087   struct _SubPart;
00088   struct _SubPartDesc;
00089   struct _Support;
00090   typedef std::set< _SubPartDesc > _SupportDesc;
00091 
00092   using namespace MED_EN;
00093   using namespace MEDMEM;
00094   using namespace std;
00095 
00096   // ---------------------------------------------------------------
00101   STRING compatibilityPb(const string& exceptionText);
00102 
00103   // ---------------------------------------------------------------
00107   bool   toIgnoreIncompatibility();
00108 
00109   // ---------------------------------------------------------------
00111   bool contains( const char* what, const char* inString );
00112 
00113   // ---------------------------------------------------------------
00118   struct TEnSightElemType
00119   {
00120     string             _name;
00121     vector<int>        _medIndex;
00122     medGeometryElement _medType;
00123   };
00124   // ---------------------------------------------------------------
00128   const TEnSightElemType& getEnSightType(medGeometryElement medType);
00129 
00130   // ---------------------------------------------------------------
00134   const TEnSightElemType& getEnSightType(const string& typeName);
00135 
00136   // ---------------------------------------------------------------
00140   inline bool isGhostType(const string& typeName)
00141   { return ( typeName[0] == 'g' && typeName[1] == '_'); }
00142 
00143   // ---------------------------------------------------------------
00147   const int MAX_LINE_LENGTH = 80;
00148 
00149   // ---------------------------------------------------------------
00153   const int MAX_FIELD_NAME_LENGTH = 19;
00154 
00155   // ---------------------------------------------------------------
00159   const string ILLEGAL_FIELD_NAME_CHARACTERS = " !@#$^()[]*/+-"; // '.,' ????
00160 
00161   // ---------------------------------------------------------------
00165   const int INT_WIDTH_6 = 8;
00166   const int INT_WIDTH_GOLD = 10;
00167   const int FLT_WIDTH = 12;
00168 
00169   // ---------------------------------------------------------------
00173   const int SPACE_DIM = 3;
00174 
00175   // ---------------------------------------------------------------
00179   static const char* TIME_STEP_BEG = "BEGIN TIME STEP";
00180   static const char* TIME_STEP_END = "END TIME STEP";
00181   const size_t TIME_STEP_BEG_LEN = 15;
00182   const size_t TIME_STEP_END_LEN = 13;
00183   
00184 
00185   // ---------------------------------------------------------------
00189   static inline float _toFloat (const double & value) {
00190     if ( value >  FLT_MAX ) return  FLT_MAX;
00191     if ( value < -FLT_MAX ) return -FLT_MAX;
00192     if ( isnan( value ))    throw MEDEXCEPTION(compatibilityPb("NaN value not allowed"));
00193     return float( value );
00194   }
00195   static inline float _toFloat (const int & value) { return float( value ); }
00196   static inline float _toFloat (const long & value) { return float( value ); }
00197 
00198 // ==============================================================================
00206 // ==============================================================================
00207 
00208 class _CaseFileDriver
00209 {
00210 public:
00211   _CaseFileDriver(const string& fileName, const _CaseFileDriver_User* creator);
00212   ~_CaseFileDriver();
00213 
00214   void read() throw (MEDEXCEPTION);
00215 
00216   // ---------------
00217   // reading meshes
00218   // ---------------
00219 
00220   int  getNbMeshes() const;
00221 
00223   void setDataFileName(const int meshIndex, ENSIGHT_MESH_RDONLY_DRIVER* meshDriver);
00224 
00225   // ---------------
00226   // reading fields
00227   // ---------------
00228 
00229   int  getNbVariables() const;
00230 
00231   int  getNbVarSteps(const int variableIndex);
00232 
00234   int  getVariableIndex(const string & varName) const;
00235 
00237   int setDataFileName(const int                    varIndex,
00238                       const int                    stepIndex,
00239                       ENSIGHT_FIELD_RDONLY_DRIVER* fieldDriver);
00240 
00241   // --------
00242   // writing
00243   // --------
00244 
00246   void addMesh(const ENSIGHT_MESH_WRONLY_DRIVER* meshDriver);
00247 
00249   void addField(const ENSIGHT_FIELD_WRONLY_DRIVER * fieldDriver);
00250 
00252   void write() throw (MEDEXCEPTION);
00253 
00254 private:
00255 
00257   bool checkWasRead() const throw (MEDEXCEPTION);
00258 
00260   int  fixWildCardName(const int           timeStep,
00261                        const std::string & ts,
00262                        const std::string & fs,
00263                        std::string &       fileName,
00264                        std::string &       time);
00265 
00266   // --------------------------------------------------------------------------------
00267   // GEOMETRY section
00268   // model: [ts] [fs] filename [change_coords_only]
00269   //        ts = time set number as specified in TIME section. This is optional.
00270   //        fs = corresponding file set number as specified in FILE section below.
00271   //            (Note, if you specify fs, then ts is no longer optional and must also be
00272   //            specified.)
00273   // filename = The filename of the appropriate file.
00274   //            -> Model or measured filenames for a static geometry case, as well as match,
00275   //                   boundary, and rigid_body filenames will not contain "*" wildcards.
00276   //            -> Model or measured filenames for a changing geometry case will
00277   //                  contain "*" wildcards.
00278   // change_coords_only =         The option to indicate that the changing geometry (as
00279   //                              indicated by wildcards in the filename) is coords only.
00280   //                              Otherwise, changing geometry connectivity will be
00281   //                              assumed.
00282   struct _Model {
00283     string _timeSetNumber, _fileSetNumber; 
00284     string _fileName;                      
00285     string _change_coords_only;
00286   };
00287   // --------------------------------------------------------------------------------
00288   // VARIABLE section
00289   // ts             = The corresponding time set number (or index) as specified in TIME
00290   //                  section below. This is only required for transient constants and
00291   //                  variables.
00292   // fs             = The corresponding file set number (or index) as specified in FILE
00293   //                  section below.
00294   //                   (Note, if you specify fs, then ts is no longer optional and must
00295   //                    also be specified.)
00296   // description    = The variable (GUI) name (ex. Pressure, Velocity, etc.)
00297   // const_value(s) = The constant value. If constants change over time, then ns (see
00298   //                  TIME section below) constant values of ts.
00299   // cvfilename     = The filename containing the constant values, one value per time step.
00300   // filename       = The filename of the variable file. Note: only transient filenames
00301   //                     contain "*" wildcards.
00302   // Re_fn          = The filename for the file containing the real values of the complex
00303   //                  variable.
00304   // Im_fn          = The filename for the file containing the imaginary values of the
00305   //                  complex variable.
00306   // freq           = The corresponding harmonic frequency of the complex variable.
00307   //                  For complex variables where harmonic frequency is undefined,
00308   //                  simply use the text string: UNDEFINED.
00309   struct _Variable {
00310     string _type;                          
00311     string _name;                          
00312     string _timeSetNumber, _fileSetNumber; 
00313     string _fileNameOrData;                
00314   };
00315   // --------------------------------------------------------------------------------
00316   // FILE section
00317   // fs = file set number. This is the number referenced in the GEOMETRY
00318   //      and VARIABLE sections above.
00319   // ns = number of transient steps
00320   // fi = file index number in the file name (replaces "*" in the filenames)
00321   struct _FileSet {
00322     int                    _number;        
00323     std::list<int>         _nbStepsInFile; 
00324     std::list<std::string> _fileIndex;     
00325   };
00326   // --------------------------------------------------------------------------------
00327   // TIME section
00328   struct _TimeSet {
00329     int                      _number;    
00330     std::vector<std::string> _fileIndex; 
00331     std::vector<std::string> _times;     
00332 
00333     bool operator==(const _TimeSet& ts) const
00334     { return ( _fileIndex == ts._fileIndex && _times == ts._times ); }
00335   };
00336 
00337 private:
00338 
00339   std::string               _fileName;
00340   std::string               _directory;
00341   EnSightFormat             _format;
00342   _Model                    _model;
00343   std::map< int, _Variable> _variables; 
00344   std::map< int, _TimeSet > _timeSets;  
00345   std::map< int, _FileSet > _fileSets;  
00346 
00347   const _CaseFileDriver_User* _user; 
00348 
00349   std::list<ENSIGHT_MESH_WRONLY_DRIVER*> _meshDrivers; 
00350 
00351   typedef std::map<std::string, std::list< ENSIGHT_FIELD_WRONLY_DRIVER* > > TFieldDriversByName;
00352   TFieldDriversByName _fieldDrivers; 
00353 
00355   bool                      _blocked;
00356 };
00357 
00358   // ==============================================================================
00363 // ==============================================================================
00364 
00365 class MEDMEM_EXPORT _CaseFileDriver_User: public GENDRIVER
00366 {
00367 protected:
00368 
00369   _CaseFileDriver_User(const std::string&     caseFileName="",
00370                        MED_EN::med_mode_acces mode=MED_EN::RDWR);
00371 
00372   const std::string& getCaseFileName() const { return GENDRIVER::_fileName; }
00373 
00374   const std::string& getDataFileName() const { return _dataFileName; }
00375 
00376   bool isGoldFormat() const { return _isGoldFormat; }
00377 
00379   bool isSingleFileMode() const { return _singleFileMode; }
00380 
00382   int  getIndexInDataFile() const { return _indexInDataFile; }
00383 
00385   bool isTransientMode() const { return _transientMode; }
00386 
00388   double getTime() const { return atof(_time.c_str()); }
00389 
00390   // -------------------------------
00391   // pass mesh data to field driver
00392   // -------------------------------
00393 
00395   void setInterData(_InterMed* imed);
00396 
00398   _InterMed* getInterData();
00399 
00400   _SubPart* getSubPart(const _SubPartDesc & descriptor) throw (MEDEXCEPTION);
00401 
00402   _Support* getSupport(const _SupportDesc & descriptor,
00403                        const medEntityMesh  entity)  throw (MEDEXCEPTION);
00404 
00405 
00406 public:
00408   int getPartNumber(const SUPPORT* support) const;
00409 
00410   static bool canOpenFile(const string& fileName, med_mode_acces mode);
00411 
00412   static void getSupportNodes(const SUPPORT* sup, map<int, int> & nodeIds);
00413 
00415   static bool isBinaryDataFile(const string& dataFileName);
00416 
00417   static bool isTimeStepBeginning(const string& line)
00418   { return ( line == TIME_STEP_BEG ); }
00419 
00420   static bool isTimeStepEnd(const char* line)
00421   { return ( strncmp( line, TIME_STEP_END, TIME_STEP_END_LEN ) == 0 ); }
00422 
00423   static bool isToWriteEntity(const medEntityMesh entity, const GMESH* mesh);
00424 
00425   ~_CaseFileDriver_User();
00426 
00427   void merge( const GENDRIVER& driver);
00428 
00429 private:
00430 
00431   friend class _CaseFileDriver;
00432 
00433   // members set by _CaseFileDriver::setDataFileName(...) and _CaseFileDriver::write()
00434   std::string _dataFileName;
00435   bool        _isGoldFormat;
00436   bool        _transientMode;   
00437   bool        _singleFileMode;  
00438   int         _indexInDataFile; 
00439   std::string _time;            
00440 
00441   _InterMed* _imed;       
00442   string     _imedMapKey; 
00443 
00444 };
00445 
00446 // ==============================================================================
00450 // ==============================================================================
00451 
00452 struct _SubPartDesc: public std::pair<int, std::string >
00453 {
00454   _SubPartDesc(int                partNumber=-1,
00455                const std::string& typeName="")
00456     : std::pair<int, std::string > ( partNumber, typeName ) {}
00457 
00458   const int&    partNumber() const { return this->first; }
00459   const string& typeName()   const { return this->second; }
00460 
00461   static _SubPartDesc globalCoordDesc() { return _SubPartDesc(-1,"coordinates"); }
00462 };
00463 
00464 std::ostream& operator << (std::ostream& os, const _SubPartDesc& desc);
00465 
00466 // ==============================================================================
00471 // ==============================================================================
00472 
00473 struct _SubPart: public _SubPartDesc
00474 {
00475   // _SubPart describes both nodes and elements since "block" describes the both.
00476   // Mesh driver sets
00477   //   for cells: myNbCells and myCellGroupIndex
00478   //   for nodes: myNbNodes and myFirstNode
00479   // GROUP of cells is created always,
00480   // GROUP of nodes, only if nodal field support is required (see getSupport())
00481 
00482   int                  myNbCells;        
00483   int                  myCellGroupIndex; 
00484   _groupe::TMailleIter myFirstCell;      
00485 
00486   int                  myNbNodes;        
00487   mutable int          myNodeGroupIndex; 
00488   _maille::TNoeud      myFirstNode;      
00489 
00490   _SubPart(int                partNumber=-1,
00491            const std::string& typeName="")
00492     : _SubPartDesc(partNumber,typeName),
00493       myNbCells(0), myCellGroupIndex(-1),
00494       myNbNodes(0), myNodeGroupIndex(-1)
00495   {}
00496 
00497   _SubPartDesc getDescriptor() const { return _SubPartDesc( partNumber(), typeName() ); }
00498 };
00499 
00500 // ==============================================================================
00504 // ==============================================================================
00505 
00506 struct _Support
00507 {
00508   _groupe * myCellGroup; 
00509   _groupe * myNodeGroup; 
00510 
00511   _Support(): myCellGroup(0), myNodeGroup(0) {}
00512 
00513   void     setGroup( _groupe* g );
00514   SUPPORT* medSupport( medEntityMesh entity );
00515 
00516   int getIndex( const pair<const int,_noeud>& node);
00517   int getIndex( const _groupe::TMaille&       cell);
00518 
00519 //   medGeometryElement getType( const pair<const int,_noeud>& node);
00520 //   medGeometryElement getType( const _groupe::TMaille&       cell);
00521 };
00522 
00523 // ==============================================================================
00527 // ==============================================================================
00528 
00529 struct _InterMed : public _intermediateMED
00530 {
00531   MESH* _medMesh;
00532   bool  _isOwnMedMesh; 
00533   int   _nbUsers;      
00534 
00535   bool  _needSubParts; 
00536 
00537   map< _SubPartDesc, _SubPart > _subPartDescribed;
00538 
00539   map< _SupportDesc, _Support > _supportDescribed;
00540 
00541   void addSubPart(const _SubPart& subPart);
00542 
00543   ~_InterMed();
00544 };
00545 
00546 // ==============================================================================
00550 // ==============================================================================
00551 
00552 template <typename T> struct _ValueOwner {
00553   T * myValues;
00554   _ValueOwner(T* values):myValues(values) {}
00555   ~_ValueOwner() { if ( myValues ) delete [] myValues; }
00556   operator T*() { return myValues; }
00557 private:
00558   _ValueOwner(const _ValueOwner& other) {} // forbidden
00559 };
00560 // instantiations
00561 typedef _ValueOwner<char>   TStrOwner;
00562 typedef _ValueOwner<int>    TIntOwner;
00563 typedef _ValueOwner<double> TDblOwner;
00564 typedef _ValueOwner<float>  TFltOwner;
00565 
00566 // ==============================================================================
00570 // ==============================================================================
00571 
00572 template <typename T> class _ValueIterator
00573 {
00574 protected:
00575   const T* myPtr;
00576   int      myDelta;
00577 public:
00578   _ValueIterator() // by default next() returns zero
00579     : myPtr(zeroPtr()), myDelta( 0 ) {}
00580 
00581   _ValueIterator(const T* values, int delta): myPtr(values-delta), myDelta(delta) {}
00582 
00583   const T & next() { myPtr += myDelta; return *myPtr; }
00584 
00585   static const T* zeroPtr() { static T a0 = 0; return &a0; }
00586 };
00587 
00588 // ==============================================================================
00592 // ==============================================================================
00593 
00594 class _ASCIIFileReader
00595 {
00596 public:
00597   _ASCIIFileReader(const string& fileName) throw (MEDEXCEPTION);
00598 
00599   ~_ASCIIFileReader();
00600 
00601   bool eof();
00602 
00603   string getWord(); 
00604 
00605   int    getInt()  throw (MEDEXCEPTION) {
00606     if ( eof() ) throw MEDEXCEPTION("Unexpected EOF");
00607     return strtol(_ptr, &_ptr, 10);
00608   }
00609   float  getReal() throw (MEDEXCEPTION) {
00610     if ( eof() ) throw MEDEXCEPTION("Unexpected EOF");
00611 #ifdef WNT
00612 #else
00613     return strtof(_ptr, &_ptr);
00614 #endif
00615   }
00617   void toNextLine() {
00618     while (isspace(*_ptr)) if ((++_ptr)[-1]=='\n') break;
00619   }
00620   char*  getLine() throw (MEDEXCEPTION);
00621 
00622   const char* getCurrentPtr() const { return _ptr; }
00623 
00624   bool lookAt( const char* text );
00625 
00626   bool isTimeStepBeginning();
00627 
00628   bool isTimeStepEnd();
00629 
00631   void skip(int nbVals, int nbPerLine, int valWidth);
00632 
00634   void skip(int width, int nbLines);
00635 
00636   template <class T>
00637   char* convertReals( const int          nbValues,
00638                       const char*        undefValue = 0,
00639                       set<int>*          undefIndices = 0,
00640                       const vector<int>* partialIndices = 0,
00641                       const int          nbPartialComponents = 0)
00642     throw (MEDEXCEPTION)
00643   {
00644     T* result = new T[ nbValues ];
00645     T* ptrT = result;
00646     if ( undefValue ) // fill undefIndices
00647     {
00648       undefIndices->clear();
00649       float undef = atof( undefValue );
00650       for ( int i = 0; i < nbValues; ++i, ++ptrT ) {
00651         float value = getReal();
00652         (*ptrT) = (T) value;
00653         if ( value == undef )
00654           undefIndices->insert( undefIndices->end(), i+1 );
00655       }
00656     }
00657     else if ( partialIndices )
00658     {
00659       // partial variables are available in GOLD format only where
00660       // values are in no-interlace
00661       int shift = 1;
00662       for ( int j = 1; j <= nbPartialComponents; ++j ) {
00663         vector<int>::const_iterator i = partialIndices->begin(), iEnd = partialIndices->end();
00664         while ( i != iEnd )
00665           result[ *i++ - shift ] = (T) getReal();
00666         shift += nbValues;
00667       }
00668     }
00669     else
00670     {
00671       for ( int i = 0; i < nbValues; ++i, ++ptrT )
00672         (*ptrT) = (T) getReal();
00673     }
00674     return (char*) result;
00675   }
00676 
00677   //static string strip(char* & str);
00678 
00680   static int  split(const string& str,
00681                     string &      part1,
00682                     string &      part2,
00683                     const char    separator=' ',
00684                     const bool    fromBack=false);
00685 
00687   static int  split(const string&       str,
00688                     std::list<string> & parts,
00689                     const char          separator=' ',
00690                     const bool          fromBack=false);
00691 
00693   static bool isDigit(const string& str, const bool real=false);
00694 
00695 private:
00696 
00697   int   _file;
00698   char* _start; // buffer start
00699   char* _ptr;   // beginning of not read portion
00700   char* _eptr;  // end of buffer contents
00701 
00702   bool  _isWin;
00703 
00704 };// class _ASCIIFileReader
00705 
00706 
00707 // ==============================================================================
00711 // ==============================================================================
00712 
00713 class _BinaryFileReader
00714 {
00715 public:
00716   _BinaryFileReader(const string& fileName) throw (MEDEXCEPTION);
00717 
00718   ~_BinaryFileReader();
00719 
00720   void rewind(); 
00721 
00722   void swapBytes() 
00723   { _mySwapBytes = true; }
00724 
00725   int moreValuesAvailable() const; 
00726 
00727   bool eof();
00728 
00729   void skip(int size) throw (MEDEXCEPTION);
00730 
00731   void skipTimeStepBeginning() throw (MEDEXCEPTION);
00732 
00733   char*   getLine()      throw (MEDEXCEPTION)
00734   { return get<char>(80); }
00735 
00736   int*    getInt(int nb) throw (MEDEXCEPTION)
00737   { return get<int>(nb,_mySwapBytes); }
00738 
00739   float*  getFlt(int nb) throw (MEDEXCEPTION)
00740   { return get<float>(nb,_mySwapBytes); }
00741 
00742   ssize_t getPosition() const { return _pos; }
00743 
00744   template <class T>
00745   char* convertReals( const int          nbValues,
00746                       const char*        undefValue = 0,
00747                       set<int>*          undefIndices = 0,
00748                       const vector<int>* partialIndices = 0,
00749                       const int          nbPartialComponents = 0 )
00750     throw (MEDEXCEPTION)
00751   {
00752     T* result = new T[ nbValues ];
00753     T* ptrT = result, *endT = result + nbValues;
00754     int nb = partialIndices ? partialIndices->size() * nbPartialComponents : nbValues;
00755     TFltOwner fltData( getFlt( nb ));
00756     float* ptrFlt = fltData;
00757     if ( undefValue ) // fill undefIndices
00758     {
00759       undefIndices->clear();
00760       float undef = atof( undefValue );
00761       while ( ptrT < endT ) {
00762         float value = *ptrFlt++;
00763         *ptrT++ = (T) value;
00764         if ( std::abs( value - undef ) <= FLT_MIN )
00765           undefIndices->insert( undefIndices->end(), ptrT - result );
00766       }
00767     }
00768     else if ( partialIndices )
00769     {
00770       // partial variables are available in GOLD format only where
00771       // values are in no-interlace
00772       int shift = 1;
00773       for ( int j = 1; j <= nbPartialComponents; ++j ) {
00774         vector<int>::const_iterator i = partialIndices->begin(), iEnd = partialIndices->end();
00775         while ( i != iEnd )
00776           result[ *i++ - shift ] = (T) *ptrFlt++;
00777         shift += nbValues;
00778       }
00779     }
00780     else
00781     {
00782       while ( ptrT < endT )
00783         *ptrT++ = (T) *ptrFlt++;
00784     }
00785     return (char*) result;
00786   }
00787 private:
00788 
00789   int          _file;         
00790   MEDEXCEPTION _exception;    
00791   ssize_t      _pos, _maxPos; 
00792   bool         _mySwapBytes;  
00793 
00795   template <typename T> T* get(int nb, bool inverseBytes=false)
00796   {
00797     size_t bufSize = nb * sizeof( T );
00798     if ( int(bufSize) > _maxPos - _pos )
00799       throw _exception;
00800     T* buf = new T[ nb ];
00801 #ifdef WNT
00802 #else
00803     ssize_t nBytesRead = ::read (_file, buf, bufSize );
00804     _pos += nBytesRead;
00805     if ( int(nBytesRead) < int(bufSize) ) {
00806       delete buf;
00807       throw _exception;
00808     }
00809     if ( inverseBytes ) { // swap bytes
00810       int* intBuf = ((int*) buf) - 1;
00811       int* bufEnd = (int*)((char*) buf + nBytesRead);
00812       while ( ++intBuf < bufEnd )
00813         *intBuf = MEDMEM::swapBytes( *intBuf );
00814     }
00815 #endif
00816     return buf;
00817   }
00818 };
00819 
00820 // ==============================================================================
00824 // ==============================================================================
00825 
00826 class _BinaryFileWriter
00827 {
00828 public:
00829   _BinaryFileWriter(const string& fileName)  throw (MEDEXCEPTION);
00830 
00831   ~_BinaryFileWriter();
00832 
00834   void addString(const char* str)            throw (MEDEXCEPTION);
00835 
00837   void addString(const string& str)          throw (MEDEXCEPTION)
00838   { addString( str.c_str() ); }
00839 
00841   void addInt(const int value)               throw (MEDEXCEPTION)
00842   { add( &value, 1 ); }
00843   
00845   void addInt(const int* data, int nbValues) throw (MEDEXCEPTION)
00846   { add( data, nbValues ); }
00847 
00849   void addInt(const vector< int >& data)     throw (MEDEXCEPTION)
00850   { add( &data[0], data.size() ); }
00851   
00853   template <typename T>
00854   void addReal(const T* data, int nbValues)  throw (MEDEXCEPTION)
00855   {
00856     _RealData realData( data, nbValues );
00857     add( realData.values(), nbValues );
00858   }
00859 
00861   template <class TValueIterator>
00862   void addReal(vector< TValueIterator >& componentIt,
00863                const int                 nbValues,
00864                const medModeSwitch       interlace)  throw (MEDEXCEPTION)
00865   {
00866     _RealData realData( componentIt, nbValues, interlace );
00867     add( realData.values(), nbValues * componentIt.size() );
00868   }
00869 
00870 private:
00871 
00872   int          _file; 
00873   MEDEXCEPTION _exception; 
00874     
00876   template <typename T>
00877   void add(const T* data, int nbValues) throw (MEDEXCEPTION)
00878   {
00879 #ifdef WNT
00880 #else
00881     ssize_t nbWritten = ::write( _file, (const void *) data, nbValues * sizeof(T));
00882     if ( nbWritten < 0 ) throw _exception;
00883 #endif
00884   }
00885   // ------------------------------------------------------------------------
00889   // ------------------------------------------------------------------------
00890   class _RealData {
00891     PointerOf<float> _floatData;
00892   public:
00894     const float* values() { return _floatData; }
00895 
00897     template <typename T>
00898     _RealData(const T* data, int nbValues)
00899     {
00900       if ( sizeof( T ) == sizeof( float ))
00901         _floatData.set((const float*) data);
00902       else {
00903         _floatData.set(nbValues);
00904         float* floatPtr = _floatData;
00905         const T *tPtr = data, *tEnd = data + nbValues;
00906         while ( tPtr < tEnd )
00907           *floatPtr++ = _toFloat( *tPtr++ );
00908       }
00909     }
00910 
00912     template <class TValueIterator>
00913     _RealData(vector< TValueIterator >& componentIt,
00914               const int                 nbValues,
00915               const medModeSwitch       interlace)
00916     {
00917       int nbComponents = componentIt.size();
00918       _floatData.set(nbValues * nbComponents);
00919       float* floatPtr = _floatData;
00920       if ( interlace == MED_FULL_INTERLACE && nbComponents > 1 ) {
00921         for ( int i = 0; i < nbValues; ++i )
00922           for ( int j = 0; j < nbComponents; ++j )
00923             *floatPtr++ = _toFloat( componentIt[ j ].next() );
00924       }
00925       else {
00926         for ( int j = 0; j < nbComponents; ++j ) {
00927           TValueIterator & values = componentIt[ j ];
00928           for ( int i = 0; i < nbValues; ++i )
00929             *floatPtr++ = _toFloat( values.next() );
00930         }
00931       } 
00932     }
00933   }; // class _RealData
00934 
00935 }; // class _BinaryFileWriter
00936 
00937 }// namespace MEDMEM_ENSIGHT
00938 
00939 #endif