From 4f69543e2393cd088acc5a5a96fedee25c972903 Mon Sep 17 00:00:00 2001
From: vigmond <ed.vigmond@gmail.com>
Date: Sat, 17 Oct 2020 14:14:36 +0200
Subject: [PATCH] Better display when Deaddata on. Preliminary work for
 element-based data.

---
 src/DataAllInMem.h | 22 +++++++++++-------
 src/DataClass.h    | 58 +++++++++++++++++++++++++++-------------------
 src/DataOnDemand.h | 32 ++++++++++++++++++++-----
 src/Model.cc       |  5 ++--
 src/Model.h        |  3 ++-
 src/TBmeshWin.cc   | 41 ++++++++++++++++++++------------
 src/TBmeshWin.h    |  2 +-
 7 files changed, 106 insertions(+), 57 deletions(-)

diff --git a/src/DataAllInMem.h b/src/DataAllInMem.h
index 55f9777..e4c7c1b 100644
--- a/src/DataAllInMem.h
+++ b/src/DataAllInMem.h
@@ -20,12 +20,13 @@ class DataAllInMem : public DataClass<T>
     using DataClass<T> :: last_tm;
     using DataClass<T> :: slice_size;
     using DataClass<T> :: filename;
+    using DataClass<T> :: _elebased;
     using DataClass<T> :: _ftype;
     using DataClass<T> :: _dt;
     using DataClass<T> :: _t0;
 
   public:
-    DataAllInMem( const char *fn, int, bool );
+    DataAllInMem( const char *fn, int, int, bool=false );
     ~DataAllInMem( );
     virtual T         max(int);	        // maximum value at a time instance
     virtual T         max();	        // maximum value
@@ -92,7 +93,6 @@ T DataAllInMem<T>::min( int tm )
 }
 
 
-
 template<class T>
 T* DataAllInMem<T>::slice( int tm )
 {
@@ -115,11 +115,12 @@ void DataAllInMem<T>::time_series( int offset, T* buffer )
  *  Read all data into a single buffer
  *
  *  \param fn    the file name of the data file
- *  \param slsz  slice size
+ *  \param slsz  number of points
+ *  \param slsz  number of elements
  *  \param base1 whether node numbering starts at one
  */
 template<class T>
-DataAllInMem<T>::DataAllInMem( const char *fn, int slsz, bool base1 )
+DataAllInMem<T>::DataAllInMem( const char *fn, int npts, int neles, bool base1 )
 {
   bool            IGBdata;
   int             j = 0;
@@ -137,7 +138,6 @@ DataAllInMem<T>::DataAllInMem( const char *fn, int slsz, bool base1 )
 
   _dt = 1;
   _t0 = 0;
-  slice_size = slsz;
 
   _ftype=FileTypeFinder( fn );
 
@@ -167,9 +167,15 @@ DataAllInMem<T>::DataAllInMem( const char *fn, int slsz, bool base1 )
 
   if ( _ftype == FTIGB ) {
     head = IGBheader( in, true );
-    if ( head.slice_sz() != slice_size ) {
-      maxtm = -1;
-      throw PointMismatch(slice_size,head.slice_sz());
+    if ( head.slice_sz() == npts ) {
+      slice_size = npts;
+      _elebased  = false;
+    }else if ( head.slice_sz() == neles ) {
+      slice_size = npts;
+      _elebased  = true;
+    } else {
+      maxtm      = -1;
+      throw PointMismatch(npts, neles, head.slice_sz());
     }
     _dt = head.inc_t();
     _t0 = head.org_t();
diff --git a/src/DataClass.h b/src/DataClass.h
index edf4180..28bd61d 100644
--- a/src/DataClass.h
+++ b/src/DataClass.h
@@ -25,9 +25,17 @@ class FrameMismatch
 
 class PointMismatch
 {
+    private:
+        bool single = true;
+        int expected1, got, expected2;
+        char msg[1024];
     public:
-        int expected, got;
-        PointMismatch( int a, int b ){expected=a;got=b;}
+        PointMismatch( int a, int b ){expected1=a;got=b;}
+        PointMismatch( int a, int b, int c ){expected1=a;expected2=b;got=c;single=false;}
+        const char* print(){
+          if(single)sprintf( msg, "Expected %d but got %d", expected1, got);
+          else sprintf( msg, "Expected %d or %d but got %d", expected1, expected2, got);
+          return msg; }
 };
 
 
@@ -36,33 +44,35 @@ template<class T>
 class DataClass
 {
   public:
-    virtual T      max(int)=0;	     //!< maximum data value at a time
-    virtual T      max()=0;	         //!< maximum data value at a time
-    virtual T      min(int)=0;       //!< minimum data value at a time
-    virtual T      min()=0;          //!< minimum data value at a time
-    virtual T*     slice(int)=0;     //!< pointer to time slice of data
-    virtual void   time_series( int, T* )=0; //!< time series for a point
-    virtual void   increment(int)=0;         //!< time slice increment
-    int      max_tm(){return maxtm;}          //!< maximum allowable time
-    int      slice_sz(){return slice_size;}   //!< size of 1 time slice
-    void     slice_sz(int a){slice_size=a;}   //!< set size of slice
-    string   file(){return filename;}         //!< return the file name
-    float    t0(void){ return _t0; }          //!< initial time read
-    float    dt(void){ return _dt; }          //!< time increment
-    fileType filetype(void){ return _ftype; } //!< type of file
+    virtual T      max(int)=0;	                  //!< maximum data value at a time
+    virtual T      max()=0;	                      //!< maximum data value at a time
+    virtual T      min(int)=0;                    //!< minimum data value at a time
+    virtual T      min()=0;                       //!< minimum data value at a time
+    virtual T*     slice(int)=0;                  //!< pointer to time slice of data
+    virtual void   time_series( int, T* )=0;      //!< time series for a point
+    virtual void   increment(int)=0;              //!< time slice increment
+    int      max_tm(){return maxtm;}              //!< maximum allowable time
+    int      slice_sz(){return slice_size;}       //!< size of 1 time slice
+    void     slice_sz(int a){slice_size=a;}       //!< set size of slice
+    string   file(){return filename;}             //!< return the file name
+    float    t0(void){ return _t0; }              //!< initial time read
+    float    dt(void){ return _dt; }              //!< time increment
+    fileType filetype(void){ return _ftype; }     //!< type of file
+    bool     ele_based(void){ return _elebased; } //!< is data element based?
 
     DataClass(){}
     virtual ~DataClass(){}
 
   protected:
-    T*       data=NULL;    //!< data
-    int      maxtm=0;      //!< number of time slice
-    int      last_tm=-1;   //!< last time that can be requested
-    int      slice_size=0; //!< amountof data in one time slice
-    float    _dt=1;        //!< time increment
-    float    _t0=0;        //!< initial time read in
-    string   filename;     //!< file containing data
-    fileType _ftype;       //!< file type
+    T*       data=NULL;       //!< data
+    int      maxtm=0;         //!< number of time slice
+    int      last_tm=-1;      //!< last time that can be requested
+    int      slice_size=0;    //!< amountof data in one time slice
+    float    _dt=1;           //!< time increment
+    float    _t0=0;           //!< initial time read in
+    string   filename;        //!< file containing data
+    fileType _ftype;          //!< file type
+    bool     _elebased=false; //!< element data read in?
 };
 
 #endif
diff --git a/src/DataOnDemand.h b/src/DataOnDemand.h
index 45b6772..ff9044b 100644
--- a/src/DataOnDemand.h
+++ b/src/DataOnDemand.h
@@ -26,7 +26,7 @@ class DataOnDemand: public DataClass<T>
     virtual void   time_series( int, T* );              //!< time series for a point
     virtual void   increment(int){}                     //!< time slice increment
 
-    DataOnDemand(const char *fn, int);
+    DataOnDemand(const char *fn, int, int=-1);
     virtual ~DataOnDemand(){free(data);if(databuf)free(databuf);}
 
   private:
@@ -42,14 +42,17 @@ class DataOnDemand: public DataClass<T>
     using DataClass<T> :: last_tm;
     using DataClass<T> :: slice_size;
     using DataClass<T> :: filename;
+    using DataClass<T> :: _elebased;
     using DataClass<T> :: _dt;
     using DataClass<T> :: _t0;
     using DataClass<T> :: _ftype;
 };
 
 template<class T>
-DataOnDemand<T>::DataOnDemand( const char *fn, int slsz )
+DataOnDemand<T>::DataOnDemand( const char *fn, int npts, int neles )
 {
+  if( neles<0) neles = npts;
+
   bool            IGBdata;
   int             j = 0;
   FILE           *in;
@@ -63,7 +66,6 @@ DataOnDemand<T>::DataOnDemand( const char *fn, int slsz )
 #endif
 
   filename       = fn;
-  slice_size     = slsz;
   _ftype         = FileTypeFinder( fn );
 
   if ( _ftype == FThdf5 )  {
@@ -87,7 +89,17 @@ DataOnDemand<T>::DataOnDemand( const char *fn, int slsz )
   // open file
   if ( _ftype == FTIGB || _ftype == FTDynPt) {
     hdr = new IGBheader( in, true );
-    if ( hdr->slice_sz() != slice_size ) {
+    if ( hdr->slice_sz() == npts ) {
+      slice_size = npts;
+      _elebased  = false;
+    }else if ( hdr->slice_sz() == neles ) {
+      slice_size = npts;
+      _elebased  = true;
+    } else {
+      maxtm      = -1;
+      throw PointMismatch(npts, neles, hdr->slice_sz());
+    }
+   if ( hdr->slice_sz() != slice_size ) {
       maxtm = -1;
       throw PointMismatch(slice_size,hdr->slice_sz());
     }
@@ -117,9 +129,17 @@ DataOnDemand<T>::DataOnDemand( const char *fn, int slsz )
   } else if( _ftype == FTascii ) {
     asciiRdr = new AsciiReader;
     asciiRdr->read_file( filename );
-    if( asciiRdr->num_lines() < slice_size ){
+        
+    if( asciiRdr->num_lines()<npts && asciiRdr->num_lines()<neles ){
       maxtm = -1;
-      throw PointMismatch(slice_size,asciiRdr->num_lines());
+      throw PointMismatch(npts, neles, asciiRdr->num_lines());
+    } else if(  asciiRdr->num_lines()<neles || 
+               (asciiRdr->num_lines()>=npts && asciiRdr->num_lines()%neles) ) {
+      slice_size =  npts;
+      _elebased  = false;
+    } else {
+      slice_size =  neles;
+      _elebased = true;
     }
     maxtm = asciiRdr->num_lines()/slice_size - 1;
   }
diff --git a/src/Model.cc b/src/Model.cc
index 20908cb..f602e35 100644
--- a/src/Model.cc
+++ b/src/Model.cc
@@ -631,9 +631,10 @@ void Model::find_max_dim_and_bounds()
       if ( fabs(p[i+j]-offset[j])>_maxdim ) 
         _maxdim = fabs(p[i+j]-offset[j]);
       
-  int i=0;
+  int i=1;
+  GLfloat z0 = pt.pt(0)[2];
   for( ; i<pt.num(); i++ )
-    if( pt.pt(i)[2] )
+    if( pt.pt(i)[2] != z0 )
       break;
   if( i==pt.num() )
     _2D = true;
diff --git a/src/Model.h b/src/Model.h
index 51ed9b6..2f03974 100644
--- a/src/Model.h
+++ b/src/Model.h
@@ -81,7 +81,7 @@ class Model
     float        size( Object_t o, int r ){ return _region[r<0?0:r]->size(o); }
     float        max_size( Object_t o );
     string       file()const{return _file;}
-    bool         twoD(){return _2D; }
+    bool         twoD(){return _2D; }  //!< is model a sheet in z-plane?
     Quaternion   syncRefRot( void ) {return _refRot; }
     void         syncRefRot( const Quaternion &q  ) { _refRot = q; }
 
@@ -89,6 +89,7 @@ class Model
     Connection*      _cnnx=NULL;
     vector<VolElement*> _vol;
     int               numSurf(void){return _surface.size();}
+    int               numSurfEle(void){int n=0;for(auto &s:_surface)n+=s->num();return n;}
     int              _numReg=0;
     int               localElemnum(int, int&);
     int               globalElemnum(int, int);
diff --git a/src/TBmeshWin.cc b/src/TBmeshWin.cc
index 77633c5..d1cc8c2 100644
--- a/src/TBmeshWin.cc
+++ b/src/TBmeshWin.cc
@@ -32,20 +32,29 @@ unsigned int TBmeshWin::MAX_MESSAGES_READ = 100;
 
 /** possible translucency 
  *
- * \param obj object to consider
- * \param col colour of undatified object
+ * \param obj   object to consider
+ * \param col   colour of undatified object
+ * \param mixed determine if translucent and opaque objects possible objects
  *
- * \return true iff translucency is possible
+ * \return true iff translucency is possible if mixed is false
+ * \return true iff both translucent and opaque objects are possible if mixed is true
  */
 bool 
-TBmeshWin::translucency( Object_t obj, GLfloat *col )
+TBmeshWin::translucency( Object_t obj, GLfloat *col, bool mixed )
 {
   bool showData = datadst&(1<<obj) && have_data!=NoData; 
   bool dopac_on = dataopac->dop[obj].on();
-  return  ( showData && dopac_on )                              || 
-          ( !showData && col[3]<OPAQUE_LIMIT )                  ||
-          ( showData && !dopac_on && col[3]<OPAQUE_LIMIT)       ||
-          ( cs->deadRange() && cs->deadColour()[3]<OPAQUE_LIMIT);
+  bool deaddat  = cs->deadRange() && cs->deadColour()[3]<OPAQUE_LIMIT;
+
+  if( mixed )
+      return   showData  && (dopac_on || deaddat );
+  else {
+      bool alpha    = col[3]<OPAQUE_LIMIT;
+      return  ( !showData && alpha )              ||
+              ( showData  && dopac_on )           || 
+              ( showData  && !dopac_on && alpha ) ||
+              ( showData  && deaddat );
+  }
 }
 
 
@@ -403,8 +412,10 @@ TBmeshWin::draw_surfaces( RenderTris &rd, vector<vtx_z> &trans, bool wireframe )
     }
   }
 
-  if( translucent && rd.num()>MAX_SURFELE_REALTIME && _spinning )
+  if( translucent && rd.num()>MAX_SURFELE_REALTIME && _spinning ){
+    rd.mesh_render(wireframe);
     return;
+  }
 
   bool newView = REBUFFER_SURF(_redraw_state) || ((REDRAW(VBO_View))&&translucent);
   if( newView )  { // refill buffer
@@ -479,10 +490,9 @@ TBmeshWin::draw_surface(Surfaces* sf, GLfloat *&vbobuf, bool wf )
     // all elements are opaque
     sf->buffer( s_colour, cs, showData?(facetshading?sf->to_elem(data).data():data):NULL,
  		NULL, vbobuf, facetshading );
-  else if( on_tr && showData && dataopac->dop[obj].on() ) {
+  else if( translucency( obj, s_colour, true ) )
     sf->buffer_opaque(  OPAQUE_LIMIT, s_colour, cs, facetshading?sf->to_elem(data).data():data,
                                        dataopac->dop+obj, vbobuf, facetshading );
-  }
   return sf->zl_sz();
 }
 
@@ -1152,11 +1162,12 @@ TBmeshWin :: get_data( const char *fn, Myslider *mslide )
     switch( drt ) {
       case AllInMem:
         newDataBuffer = new DataAllInMem<DATA_TYPE>( fn, model->pt.num(),
-                        model->base1() );
+                                                           model->base1() );
         break;
       case Threaded:
         //newDataBuffer = new ThreadedData<DATA_TYPE>( fn, model->pt.num() );
-        newDataBuffer = new DataOnDemand<DATA_TYPE>( fn, model->pt.num() );
+        newDataBuffer = new DataOnDemand<DATA_TYPE>( fn, model->pt.num(),
+                        model->numVol()?model->numVol():model->numSurfEle() ); 
         break;
       default:
         throw 1;
@@ -1167,7 +1178,7 @@ TBmeshWin :: get_data( const char *fn, Myslider *mslide )
     return 1;
   }
   catch ( PointMismatch pm ) {
-    fl_alert( "%s\nPoints number mismatch: expected %d but got %d", fn, pm.expected, pm.got );  
+    fl_alert( "%s\nPoints number mismatch: %s", fn, pm.print() );  
     return 2;
   }
   catch (...) {
@@ -2205,7 +2216,7 @@ TBmeshWin :: read_dynamic_pts( const char *fn, Myslider *mslide )
     return 1;
   }
   catch( PointMismatch pm ) {
-    fl_alert( "Incompatible number of points. Expected %d but got %d\n", pm.expected, pm.got );
+    fl_alert( "Incompatible number of points. %s\n", pm.print() );
     return 2;
   }
 
diff --git a/src/TBmeshWin.h b/src/TBmeshWin.h
index 21dc740..11d27bf 100644
--- a/src/TBmeshWin.h
+++ b/src/TBmeshWin.h
@@ -218,7 +218,7 @@ class TBmeshWin:public Fl_Gl_Tb_Window
     void      draw_iso_surfaces( );
     void      draw_iso_lines();
     void trim_vertices( vector<bool>&, bool );
-    bool translucency( Object_t, GLfloat * ); 
+    bool translucency( Object_t, GLfloat *, bool=false ); 
 
     GLenum    renderMode = GL_RENDER;// mode for drawing
     vector<bool> ptDrawn;			 // was a point drawn
-- 
GitLab