Skip to content
Snippets Groups Projects
Forked from gmsh / gmsh
21339 commits behind the upstream repository.
Views.cpp 26.94 KiB
// $Id: Views.cpp,v 1.27 2001-02-02 15:05:03 geuzaine Exp $

#include <set>
#include "Gmsh.h"
#include "Views.h"
#include "Context.h"
#include "ColorTable.h"

List_T  *Post_ViewList = NULL;
Post_View  *ActualView;

extern Context_T   CTX ;

static int  ActualViewNum=0;
static int  NbPoints, NbLines, NbTriangles, NbTetrahedra;

/* ------------------------------------------------------------------------ */
/*  V i e w s                                                               */
/* ------------------------------------------------------------------------ */

int fcmpPostViewNum(const void *v1, const void *v2){
  return (((Post_View *)v1)->Num - ((Post_View *)v2)->Num);
}

int fcmpPostViewDuplicateOf(const void *v1, const void *v2){
  return (((Post_View *)v1)->DuplicateOf - ((Post_View *)v2)->DuplicateOf);
}

void BeginView(int allocate){
  ActualView = (Post_View*)Malloc(sizeof(Post_View));

  NbPoints = NbLines = NbTriangles = NbTetrahedra = 0;

  ActualView->NbSP = ActualView->NbVP = ActualView->NbTP = 0;
  ActualView->NbSL = ActualView->NbVL = ActualView->NbTL = 0;
  ActualView->NbST = ActualView->NbVT = ActualView->NbTT = 0;
  ActualView->NbSS = ActualView->NbVS = ActualView->NbTS = 0;

  if(allocate){
    ActualView->datasize = sizeof(double);

    ActualView->Time = List_Create(100,1000,sizeof(double));

    ActualView->SP = List_Create(100,1000,sizeof(double));
    ActualView->VP = List_Create(100,1000,sizeof(double));
    ActualView->TP = List_Create(100,1000,sizeof(double));
    
    ActualView->SL = List_Create(100,1000,sizeof(double));
    ActualView->VL = List_Create(100,1000,sizeof(double));
    ActualView->TL = List_Create(100,1000,sizeof(double));
    
    ActualView->ST = List_Create(100,1000,sizeof(double));
    ActualView->VT = List_Create(100,1000,sizeof(double));
    ActualView->TT = List_Create(100,1000,sizeof(double));
    
    ActualView->SS = List_Create(100,1000,sizeof(double));
    ActualView->VS = List_Create(100,1000,sizeof(double));
    ActualView->TS = List_Create(100,1000,sizeof(double));
  }
  else{
    ActualView->Time = NULL;
    ActualView->SP = NULL; ActualView->VP = NULL; ActualView->TP = NULL;
    ActualView->SL = NULL; ActualView->VL = NULL; ActualView->TL = NULL;
    ActualView->ST = NULL; ActualView->VT = NULL; ActualView->TT = NULL;
    ActualView->SS = NULL; ActualView->VS = NULL; ActualView->TS = NULL;
  }

  ActualView->Changed = 1;
  ActualView->Links = 0;
  ActualView->DuplicateOf = 0;
  ActualView->Min = 1.e200;
  ActualView->Max = -1.e200;
  ActualView->NbIso = CTX.post.initial_nbiso;
  ActualView->IntervalsType = CTX.post.initial_intervals;
  ActualView->Light = 0;
  ActualView->ShowElement = 0;
  ActualView->ShowTime = 1;
  ActualView->Visible = CTX.post.initial_visibility;
  ActualView->TimeStep = 0;
  ActualView->ArrowScale = 100.; 
  ActualView->ArrowType = DRAW_POST_ARROW; 
  ActualView->ArrowLocation = DRAW_POST_LOCATE_COG; 
  ActualView->RangeType = DRAW_POST_DEFAULT; 
  ActualView->ShowScale = 1;
  ActualView->TransparentScale = 1;
  ActualView->ScaleType = DRAW_POST_LINEAR; 
  ActualView->Raise[0] = 0.0;
  ActualView->Raise[1] = 0.0;
  ActualView->Raise[2] = 0.0;
  ActualView->ScalarOnly = 1;
  ActualView->NbTimeStep = 0;
  ActualView->CT.size = 255;
  ActualView->CT.ipar[COLORTABLE_MODE] = COLORTABLE_RGB;
  ActualView->normals = 0;
  ColorTable_InitParam(1, &ActualView->CT, 1, 1);
  ColorTable_Recompute(&ActualView->CT, 1, 1);
}

void Stat_ScalarSimplex(int nbnod, int N, double *V){
  int i;

  if(!NbPoints && !NbLines && !NbTriangles && !NbTetrahedra){
    ActualView->Min = V[0];
    ActualView->Max = V[0];
    ActualView->NbTimeStep = N/nbnod;
  }
  else if(N/nbnod < ActualView->NbTimeStep)
    ActualView->NbTimeStep = N/nbnod ;

  for(i=0 ; i<N ; i++){
    if(V[i] < ActualView->Min) ActualView->Min = V[i] ;
    if(V[i] > ActualView->Max) ActualView->Max = V[i] ;
  }

  switch(nbnod){
  case 1 : NbPoints++; break;
  case 2 : NbLines++; break;
  case 3 : NbTriangles++; break;
  case 4 : NbTetrahedra++; break;
  }
}

void Stat_VectorSimplex(int nbnod, int N, double *V){
  double l0;
  int i;

  if(!NbPoints && !NbLines && !NbTriangles && !NbTetrahedra){
    l0 = sqrt(DSQR(V[0])+DSQR(V[1])+DSQR(V[2]));
    ActualView->Min = l0;
    ActualView->Max = l0;
    ActualView->NbTimeStep = N/(3*nbnod) ;
  }
  else if(N/(3*nbnod) < ActualView->NbTimeStep)
    ActualView->NbTimeStep = N/(3*nbnod) ;

  for(i=0 ; i<N ; i+=3){
    l0 = sqrt(DSQR(V[i])+DSQR(V[i+1])+DSQR(V[i+2]));
    if(l0 < ActualView->Min) ActualView->Min = l0 ;
    if(l0 > ActualView->Max) ActualView->Max = l0 ;
  }

  ActualView->ScalarOnly = 0;

  switch(nbnod){
  case 1 : NbPoints++; break;
  case 2 : NbLines++; break;
  case 3 : NbTriangles++; break;
  case 4 : NbTetrahedra++; break;
  }
}

void Stat_TensorSimplex(int nbnod, int N, double *v){
  Msg(GERROR, "Tensor Field Views not Implemented Yet");
}

void EndView(int AddInUI, int Number, char *FileName, char *Name, 
             double XOffset, double YOffset, double ZOffset){
  int i, nb;
  double d;
  extern int AddViewInUI(int , char *, int);

  // Points

  if(ActualView->NbSP){
    nb = List_Nbr(ActualView->SP) / ActualView->NbSP ;
    for(i = 0 ; i < List_Nbr(ActualView->SP) ; i+=nb)
      Stat_ScalarSimplex(1, nb-3, (double*)List_Pointer(ActualView->SP,i+3));
  }
  if(ActualView->NbVP){
    nb = List_Nbr(ActualView->VP) / ActualView->NbVP ;
    for(i = 0 ; i < List_Nbr(ActualView->VP) ; i+=nb)
      Stat_VectorSimplex(1, nb-3, (double*)List_Pointer(ActualView->VP,i+3));
  }
  if(ActualView->NbTP){
    nb = List_Nbr(ActualView->TP) / ActualView->NbTP ;
    for(i = 0 ; i < List_Nbr(ActualView->TP) ; i+=nb)
      Stat_TensorSimplex(1, nb-3, (double*)List_Pointer(ActualView->TP,i+3));
  }

  // Lines

  if(ActualView->NbSL){
    nb = List_Nbr(ActualView->SL) / ActualView->NbSL ;
    for(i = 0 ; i < List_Nbr(ActualView->SL) ; i+=nb)
      Stat_ScalarSimplex(2, nb-6, (double*)List_Pointer(ActualView->SL,i+6));
  }
  if(ActualView->NbVL){
    nb = List_Nbr(ActualView->VL) / ActualView->NbVL ;
    for(i = 0 ; i < List_Nbr(ActualView->VL) ; i+=nb)
      Stat_VectorSimplex(2, nb-6, (double*)List_Pointer(ActualView->VL,i+6));
  }
  if(ActualView->NbTL){
    nb = List_Nbr(ActualView->TL) / ActualView->NbTL ;
    for(i = 0 ; i < List_Nbr(ActualView->TL) ; i+=nb)
      Stat_TensorSimplex(2, nb-6, (double*)List_Pointer(ActualView->TL,i+6));
  }

  // Triangles

  if(ActualView->NbST){
    nb = List_Nbr(ActualView->ST) / ActualView->NbST ;
    for(i = 0 ; i < List_Nbr(ActualView->ST) ; i+=nb)
      Stat_ScalarSimplex(3, nb-9, (double*)List_Pointer(ActualView->ST,i+9));
  }
  if(ActualView->NbVT){
    nb = List_Nbr(ActualView->VT) / ActualView->NbVT ;
    for(i = 0 ; i < List_Nbr(ActualView->VT) ; i+=nb)
      Stat_VectorSimplex(3, nb-9, (double*)List_Pointer(ActualView->VT,i+9));
  }
  if(ActualView->NbTT){
    nb = List_Nbr(ActualView->TT) / ActualView->NbTT ;
    for(i = 0 ; i < List_Nbr(ActualView->TT) ; i+=nb)
      Stat_TensorSimplex(3, nb-9, (double*)List_Pointer(ActualView->TT,i+9));
  }

  // Tetrahedra

  if(ActualView->NbSS){
    nb = List_Nbr(ActualView->SS) / ActualView->NbSS ;
    for(i = 0 ; i < List_Nbr(ActualView->SS) ; i+=nb)
      Stat_ScalarSimplex(4, nb-12, (double*)List_Pointer(ActualView->SS,i+12));
  }
  if(ActualView->NbVS){
    nb = List_Nbr(ActualView->VS) / ActualView->NbVS ;
    for(i = 0 ; i < List_Nbr(ActualView->VS) ; i+=nb)
      Stat_VectorSimplex(4, nb-12, (double*)List_Pointer(ActualView->VS,i+12));
  }
  if(ActualView->NbTS){
    nb = List_Nbr(ActualView->TS) / ActualView->NbTS ;
    for(i = 0 ; i < List_Nbr(ActualView->TS) ; i+=nb)
      Stat_TensorSimplex(4, nb-12, (double*)List_Pointer(ActualView->TS,i+12));
  }

  // Dummy time values if using old parsed format...
  if(!List_Nbr(ActualView->Time)){
    for(i=0 ; i<ActualView->NbTimeStep ; i++){
      d = (double)i;
      List_Add(ActualView->Time, &d);
    }
  }

  strcpy(ActualView->FileName,FileName);
  strcpy(ActualView->Name,Name);
  strcpy(ActualView->Format, "%.3e");
  if(ActualView->Min > ActualView->Max)
    ActualView->Min = ActualView->Max = 0.0 ;
  ActualView->CustomMin = ActualView->Min;
  ActualView->CustomMax = ActualView->Max;
  ActualView->Offset[0] = XOffset*(CTX.range[0]?CTX.range[0]:CTX.lc)*1.e-3;
  ActualView->Offset[1] = YOffset*(CTX.range[1]?CTX.range[1]:CTX.lc)*1.e-3;
  ActualView->Offset[2] = ZOffset*(CTX.range[2]?CTX.range[2]:CTX.lc)*1.e-3;

  /* j'en alloue directement le max pour eviter les problemes de
     reallocation (avec CurrentView) */
  if(!Post_ViewList) 
    Post_ViewList = List_Create(100,1,sizeof(Post_View));

  if(!Number){
    ActualView->Num = ++ActualViewNum;    
    List_Add(Post_ViewList,ActualView);
    CTX.post.nb_views = List_Nbr(Post_ViewList);
    if(AddInUI)
      AddViewInUI(List_Nbr(Post_ViewList), ActualView->Name, ActualView->Num);
  }
  else{
    ActualView->Num = Number;    
    List_Replace(Post_ViewList,ActualView,fcmpPostViewNum);
  }

  // it's a test, smoothing views in the volume !!!
  // in the future, we'll have normals smoothed
  if(CTX.post.smooth) ActualView->smooth();
  ActualView = NULL;
}

bool FreeView(int num){
  Post_View *v;

  Msg(DEBUG, "Trying to free view %d",num);
  
  if(num < 0 || num >= List_Nbr(Post_ViewList)){
    return false ;
  }
  v = (Post_View*)List_Pointer(Post_ViewList, num);
  FreeView(v);
  List_Suppress(Post_ViewList, v, fcmpPostViewNum);
  CTX.post.nb_views = List_Nbr(Post_ViewList);

  Msg(INFO, "View %d deleted (%d views left)",num, List_Nbr(Post_ViewList));
  return true;
}


void FreeView(Post_View *v){
  Post_View vv,*v2;
  int free = 1;

  if(v->DuplicateOf){
    vv.Num = v->DuplicateOf ;
    Msg(DEBUG, "This View is a Duplicata");
    if(!(v2 = (Post_View*)List_PQuery(Post_ViewList, &vv, fcmpPostViewNum))){
      Msg(DEBUG, " ->The Original View is Gone");
      if(!(v2 = (Post_View*)List_PQuery(Post_ViewList, v, fcmpPostViewDuplicateOf))){
        Msg(DEBUG, " ->There are no other duplicata");
        free = 1 ;
      }
      else{
        free = 0 ;
      }
    }
    else{
      v2->Links--;
      free = 0 ;
      Msg(DEBUG, " ->The original still exists, so I dont't free anything now");
    }
  }

  if(v->Links)
    Msg(DEBUG, " ->This view is linked: Cannot free");

  if(free && !v->Links){
    Msg(DEBUG, " ->Freeing View");
    List_Delete(v->Time);
    List_Delete(v->SP); List_Delete(v->VP); List_Delete(v->TP);
    List_Delete(v->SL); List_Delete(v->VL); List_Delete(v->TL);
    List_Delete(v->ST); List_Delete(v->VT); List_Delete(v->TT);
    List_Delete(v->SS); List_Delete(v->VS); List_Delete(v->TS);
  }
  v->reset_normals();
}

void CopyViewOptions(Post_View *src, Post_View *dest){
  strcpy(dest->Format, src->Format);
  dest->CustomMin = src->CustomMin;
  dest->CustomMax = src->CustomMax;
  dest->Offset[0] = src->Offset[0];
  dest->Offset[1] = src->Offset[1];
  dest->Offset[2] = src->Offset[2];
  dest->Raise[0] = src->Raise[0];
  dest->Raise[1] = src->Raise[1];
  dest->Raise[2] = src->Raise[2];
  dest->ArrowScale = src->ArrowScale;
  dest->Visible = src->Visible;
  dest->IntervalsType = src->IntervalsType;
  dest->NbIso = src->NbIso;
  dest->Light = src->Light ;
  dest->ShowElement = src->ShowElement;
  dest->ShowTime = src->ShowTime;
  dest->ShowScale = src->ShowScale;
  dest->TransparentScale = src->TransparentScale;
  dest->ScaleType = src->ScaleType;
  dest->RangeType = src->RangeType;
  dest->ArrowType = src->ArrowType;
  dest->ArrowLocation = src->ArrowLocation;
  dest->TimeStep = src->TimeStep;
  ColorTable_Copy(&src->CT);
  ColorTable_Paste(&dest->CT);
}

char *Get_StringViewOption(int num, char *str, int *type){
  Post_View *v;

  if(num < 0 || num >= List_Nbr(Post_ViewList)){
    *type = -1 ;
    return NULL ;
  }
  v = (Post_View*)List_Pointer(Post_ViewList, num);

  if(!strcmp(str, "Format")) return v->Format ;
  else if(!strcmp(str, "FileName")) return v->FileName ;
  else if(!strcmp(str, "Name")) return v->Name ;
  else return NULL ;

}

void Print_StringViewOptions(int num, FILE *file){
  Post_View *v;

  if(num < 0 || num >= List_Nbr(Post_ViewList))
    return ;
  v = (Post_View*)List_Pointer(Post_ViewList, num);

  fprintf(file, "PostProcessing.View[%d].Format = \"%s\";\n", num, v->Format);
  fprintf(file, "PostProcessing.View[%d].FileName = \"%s\";\n", num, v->FileName);
  fprintf(file, "PostProcessing.View[%d].Name = \"%s\";\n", num, v->Name);
}

void *Get_NumberViewOption(int num, char *str, int *type){
  Post_View *v;

  if(num < 0 || num >= List_Nbr(Post_ViewList)){
    *type = -1 ;
    return NULL ;
  }
  v = (Post_View*)List_Pointer(Post_ViewList, num);

  if(!strcmp(str, "NbTimeStep")) { *type = GMSH_INT; return (void*)&v->NbTimeStep; }
  else if(!strcmp(str, "TimeStep")) { *type = GMSH_INT; return (void*)&v->TimeStep; }
  else if(!strcmp(str, "Min")) { *type = GMSH_DOUBLE; return (void*)&v->Min ; }
  else if(!strcmp(str, "Max")) { *type = GMSH_DOUBLE ; return (void*)&v->Max ; }
  else if(!strcmp(str, "CustomMin")) { *type = GMSH_DOUBLE ; return (void*)&v->CustomMin ; }
  else if(!strcmp(str, "CustomMax")) { *type = GMSH_DOUBLE ; return (void*)&v->CustomMax ; }
  else if(!strcmp(str, "Offset0")) { *type = GMSH_DOUBLE ; return (void*)&v->Offset[0] ; }
  else if(!strcmp(str, "Offset1")) { *type = GMSH_DOUBLE ; return (void*)&v->Offset[1] ; }
  else if(!strcmp(str, "Offset2")) { *type = GMSH_DOUBLE ; return (void*)&v->Offset[2] ; }
  else if(!strcmp(str, "Raise0")) { *type = GMSH_DOUBLE ; return (void*)&v->Raise[0] ; }
  else if(!strcmp(str, "Raise1")) { *type = GMSH_DOUBLE ; return (void*)&v->Raise[1] ; }
  else if(!strcmp(str, "Raise2")) { *type = GMSH_DOUBLE ; return (void*)&v->Raise[2] ; }
  else if(!strcmp(str, "ArrowScale")) { *type = GMSH_DOUBLE ; return (void*)&v->ArrowScale ; }
  else if(!strcmp(str, "Visible")) { *type = GMSH_INT ; return (void*)&v->Visible ; }
  else if(!strcmp(str, "IntervalsType")) { *type = GMSH_INT ; return (void*)&v->IntervalsType ; }
  else if(!strcmp(str, "NbIso")) { *type = GMSH_INT ; return (void*)&v->NbIso ; }
  else if(!strcmp(str, "Light")) { *type = GMSH_INT ; return (void*)&v->Light ; }
  else if(!strcmp(str, "ShowElement")) { *type = GMSH_INT ; return (void*)&v->ShowElement ; }
  else if(!strcmp(str, "ShowTime")) { *type = GMSH_INT ; return (void*)&v->ShowTime ; }
  else if(!strcmp(str, "ShowScale")) { *type = GMSH_INT ; return (void*)&v->ShowScale ; }
  else if(!strcmp(str, "TransparentScale")) { *type = GMSH_INT ; return (void*)&v->TransparentScale ; }
  else if(!strcmp(str, "ScaleType")) { *type = GMSH_INT ; return (void*)&v->ScaleType ; }
  else if(!strcmp(str, "RangeType")) { *type = GMSH_INT ; return (void*)&v->RangeType ; }
  else if(!strcmp(str, "ArrowType")) { *type = GMSH_INT ; return (void*)&v->ArrowType ; }
  else if(!strcmp(str, "ArrowLocation")) { *type = GMSH_INT ; return (void*)&v->ArrowLocation ; }
  else{
    return NULL ;
  }
}

void Print_NumberViewOptions(int num, FILE *file){
  Post_View *v;

  if(num < 0 || num >= List_Nbr(Post_ViewList))
    return ;
  v = (Post_View*)List_Pointer(Post_ViewList, num);

  fprintf(file, "PostProcessing.View[%d].NbTimeStep = %d;\n", num, v->NbTimeStep);
  fprintf(file, "PostProcessing.View[%d].TimeStep = %d;\n", num, v->TimeStep);
  fprintf(file, "PostProcessing.View[%d].Min = %g;\n", num, v->Min);
  fprintf(file, "PostProcessing.View[%d].Max = %g;\n", num, v->Max);
  fprintf(file, "PostProcessing.View[%d].CustomMin = %g;\n", num, v->CustomMin);
  fprintf(file, "PostProcessing.View[%d].CustomMax = %g;\n", num, v->CustomMax);
  fprintf(file, "PostProcessing.View[%d].ArrowScale = %g;\n", num, v->ArrowScale);
  fprintf(file, "PostProcessing.View[%d].Visible = %d;\n", num, v->Visible);
  fprintf(file, "PostProcessing.View[%d].IntervalsType = %d;\n", num, v->IntervalsType);
  fprintf(file, "PostProcessing.View[%d].NbIso = %d;\n", num, v->NbIso);
  fprintf(file, "PostProcessing.View[%d].Light = %d;\n", num, v->Light);
  fprintf(file, "PostProcessing.View[%d].ShowElement = %d;\n", num, v->ShowElement);
  fprintf(file, "PostProcessing.View[%d].ShowTime = %d;\n", num, v->ShowTime);
  fprintf(file, "PostProcessing.View[%d].ShowScale = %d;\n", num, v->ShowScale);
  fprintf(file, "PostProcessing.View[%d].TransparentScale = %d;\n", num, v->TransparentScale);
  fprintf(file, "PostProcessing.View[%d].ScaleType = %d;\n", num, v->ScaleType);
  fprintf(file, "PostProcessing.View[%d].RangeType = %d;\n", num, v->RangeType);
  fprintf(file, "PostProcessing.View[%d].ArrowType = %d;\n", num, v->ArrowType);
  fprintf(file, "PostProcessing.View[%d].ArrowLocation = %d;\n", num, v->ArrowLocation);
  fprintf(file, "PostProcessing.View[%d].Offset0 = %g;\n", num, v->Offset[0]);
  fprintf(file, "PostProcessing.View[%d].Offset1 = %g;\n", num, v->Offset[1]);
  fprintf(file, "PostProcessing.View[%d].Offset2 = %g;\n", num, v->Offset[2]);
  fprintf(file, "PostProcessing.View[%d].Raise0 = %g;\n", num, v->Raise[0]);
  fprintf(file, "PostProcessing.View[%d].Raise1 = %g;\n", num, v->Raise[1]);
  fprintf(file, "PostProcessing.View[%d].Raise2 = %g;\n", num, v->Raise[2]);
  fprintf(file, "PostProcessing.View[%d].Color = { ", num);
  ColorTable_Print(&v->CT, file);
  fprintf(file, " };\n");

}

ColorTable *Get_ColorTableViewOption(int num){
  Post_View *v;

  if(num < 0 || num >= List_Nbr(Post_ViewList))
    return NULL ;
  v = (Post_View*)List_Pointer(Post_ViewList, num);
  return &v->CT ;
}

/* ------------------------------------------------------------------------ */
/*  R e a d _ V i e w                                                       */
/* ------------------------------------------------------------------------ */

extern int Force_ViewNumber;

void Read_View(FILE *file, char *filename){
  char   str[NAME_STR_L], name[NAME_STR_L];
  int    nb, format, size, testone, swap;
  double version;

  while (1) {

    do { 
      fgets(str, NAME_STR_L, file) ; 
      if (feof(file))  break ;
    } while (str[0] != '$') ;  

    if (feof(file))  break ;

    /*  F o r m a t  */

    if (!strncmp(&str[1], "PostFormat", 10)){
      fscanf(file, "%lf %d %d\n", &version, &format, &size) ;
      if(version < 1.0){
        Msg(GERROR, "The Version of this File is too old (%g < 1.0)", version);
        return;
      }
      if(size == sizeof(double))
	Msg(DEBUG, "Data is in Double Precision Format (size==%d)", size);
      else if(size == sizeof(float))
	Msg(DEBUG, "Data is in Single Precision Format (size==%d)", size);
      else{
        Msg(GERROR, "Unknown Type of Data (Size = %d) in Post-Processing File", 
	    size);
        return;
      }
      if(format == 0)
	format = LIST_FORMAT_ASCII ;
      else if(format == 1)
	format = LIST_FORMAT_BINARY ;
      else{
	Msg(GERROR, "Unknown Format for View");
	return ;
      }
    }

    /*  V i e w  */

    if (!strncmp(&str[1], "View", 4)) {

      BeginView(0);

      fscanf(file, "%s %d %d %d %d %d %d %d %d %d %d %d %d %d\n", 
             name, &ActualView->NbTimeStep,
             &ActualView->NbSP, &ActualView->NbVP, &ActualView->NbTP, 
             &ActualView->NbSL, &ActualView->NbVL, &ActualView->NbTL, 
             &ActualView->NbST, &ActualView->NbVT, &ActualView->NbTT, 
             &ActualView->NbSS, &ActualView->NbVS, &ActualView->NbTS);

      swap = 0 ;
      if(format == LIST_FORMAT_BINARY){
	fread(&testone, sizeof(int), 1, file);
	if(testone != 1){
	  Msg(INFO, "Swapping Bytes from Binary File");
	  swap = 1;
	}
      }

      ActualView->datasize = size ;

      // Time values
      ActualView->Time = List_CreateFromFile(ActualView->NbTimeStep, 
					     size, file, format, swap);

      // Points
      nb = ActualView->NbSP ? ActualView->NbSP * (ActualView->NbTimeStep  +3) : 0 ;
      ActualView->SP = List_CreateFromFile(nb, size, file, format, swap);

      nb = ActualView->NbVP ? ActualView->NbVP * (ActualView->NbTimeStep*3+3) : 0 ;
      ActualView->VP = List_CreateFromFile(nb, size, file, format, swap);

      nb = ActualView->NbTP ? ActualView->NbTP * (ActualView->NbTimeStep*9+3) : 0 ;
      ActualView->TP = List_CreateFromFile(nb, size, file, format, swap);

      // Lines
      nb = ActualView->NbSL ? ActualView->NbSL * (ActualView->NbTimeStep*2  +6) : 0 ;
      ActualView->SL = List_CreateFromFile(nb, size, file, format, swap);

      nb = ActualView->NbVL ? ActualView->NbVL * (ActualView->NbTimeStep*2*3+6) : 0 ;
      ActualView->VL = List_CreateFromFile(nb, size, file, format, swap);

      nb = ActualView->NbTL ? ActualView->NbTL * (ActualView->NbTimeStep*2*9+6) : 0 ;
      ActualView->TL = List_CreateFromFile(nb, size, file, format, swap);

      // Triangles
      nb = ActualView->NbST ? ActualView->NbST * (ActualView->NbTimeStep*3  +9) : 0 ;
      ActualView->ST = List_CreateFromFile(nb, size, file, format, swap);

      nb = ActualView->NbVT ? ActualView->NbVT * (ActualView->NbTimeStep*3*3+9) : 0 ;
      ActualView->VT = List_CreateFromFile(nb, size, file, format, swap);

      nb = ActualView->NbTT ? ActualView->NbTT * (ActualView->NbTimeStep*3*9+9) : 0 ;
      ActualView->TT = List_CreateFromFile(nb, size, file, format, swap);

      // Tetrahedra
      nb = ActualView->NbSS ? ActualView->NbSS * (ActualView->NbTimeStep*4  +12) : 0 ;
      ActualView->SS = List_CreateFromFile(nb, size, file, format, swap);

      nb = ActualView->NbVS ? ActualView->NbVS * (ActualView->NbTimeStep*4*3+12) : 0 ;
      ActualView->VS = List_CreateFromFile(nb, size, file, format, swap);

      nb = ActualView->NbTS ? ActualView->NbTS * (ActualView->NbTimeStep*4*9+12) : 0 ;
      ActualView->TS = List_CreateFromFile(nb, size, file, format, swap);

      Msg(DEBUG, "Read View '%s' (%d TimeSteps): %d %d %d %d %d %d %d %d %d %d %d %d",
          name, ActualView->NbTimeStep,
          ActualView->NbSP, ActualView->NbVP, ActualView->NbTP, 
          ActualView->NbSL, ActualView->NbVL, ActualView->NbTL, 
          ActualView->NbST, ActualView->NbVT, ActualView->NbTT, 
          ActualView->NbSS, ActualView->NbVS, ActualView->NbTS);
      Msg(DEBUG, "List_Nbrs: %d %d %d %d %d %d %d %d %d %d %d %d",
          List_Nbr(ActualView->SP), List_Nbr(ActualView->VP), List_Nbr(ActualView->TP), 
          List_Nbr(ActualView->SL), List_Nbr(ActualView->VL), List_Nbr(ActualView->TL), 
          List_Nbr(ActualView->ST), List_Nbr(ActualView->VT), List_Nbr(ActualView->TT), 
          List_Nbr(ActualView->SS), List_Nbr(ActualView->VS), List_Nbr(ActualView->TS));

      EndView(1, Force_ViewNumber, filename, name, 0., 0., 0.); 
    }

    do {
      fgets(str, NAME_STR_L, file) ;
      if (feof(file)) Msg(GERROR,"Prematured End of File");
    } while (str[0] != '$') ;

  }   /* while 1 ... */

}


/*
  A little util for smoothing a view.
*/

using namespace std;
struct xyzv
{
private:
public:
  double x,y,z,*vals;
  int nbvals;
  int nboccurences;
  static double eps;
  void update (int nbVals, double *);
  xyzv(double x, double y, double z);
  ~xyzv();
  xyzv & operator = ( const xyzv &);
  xyzv ( const xyzv &);
};

double xyzv::eps = 0.0;

xyzv::xyzv (double xx, double yy, double zz) : x(xx),y(yy),z(zz),vals(0),nbvals(0),nboccurences(0){}
xyzv::~xyzv()
{
  if(vals)delete [] vals;
}
xyzv::xyzv(const xyzv &other)
{
  x = other.x;
  y = other.y;
  z = other.z;
  nbvals = other.nbvals;
  nboccurences = other.nboccurences;
  if(other.vals && other.nbvals)
    {
      vals = new double[other.nbvals];
      for(int i=0;i<nbvals;i++)vals[i] = other.vals[i];
    }
}
xyzv & xyzv::operator = (const xyzv &other)
{
  if(this != &other)
    { 
      x = other.x;
      y = other.y;
      z = other.z;
      nbvals = other.nbvals;
      nboccurences = other.nboccurences;
      if(other.vals && other.nbvals)
	{
	  vals = new double[other.nbvals];
	  for(int i=0;i<nbvals;i++)vals[i] = other.vals[i];
	}
    }
  return *this;
}

void xyzv::update (int n, double *v)
{
  int i;
  if(!vals)
    {
      vals = new double[n];
      for(i=0;i<nbvals;i++)vals[i] = 0.0;
      nbvals = n;
      nboccurences = 0;
    }
  else if (nbvals != n)
    {
      throw n;
    }

  //  if(n==3)printf("val(%d,%f,%f,%f) = %f %f %f\n",nboccurences,x,y,z,v[0],v[1],v[2]);

  double x1 = (double)(nboccurences)/ (double)(nboccurences + 1);
  double x2 = 1./(double)(nboccurences + 1);
  for(i=0;i<nbvals;i++)vals[i] = (x1 * vals[i] + x2 * v[i]);
  nboccurences++;
}


struct lessthanxyzv
{
  bool operator () (const xyzv & p2, const xyzv &p1) const
  {
    if( p1.x - p2.x > xyzv::eps)return true;  
    if( p1.x - p2.x <-xyzv::eps)return false;  
    if( p1.y - p2.y > xyzv::eps)return true;  
    if( p1.y - p2.y <-xyzv::eps)return false;  
    if( p1.z - p2.z > xyzv::eps)return true;  
    return false;  
  }
};

typedef set<xyzv,lessthanxyzv> mycont;
typedef mycont::const_iterator iter;

class smooth_container 
{
public :
  mycont c;
};

void smooth_list (List_T *SS ,
		  int NbTimeStep,
		  int nbvert,
		  int nb, 
		  mycont & connectivities)
{
  double *x,*y,*z,*v;
  int i,j,k;
  double *vals = new double[NbTimeStep];
  for(i = 0 ; i < List_Nbr(SS) ; i+=nb)
    {
      x = (double*)List_Pointer_Fast(SS,i);
      y = (double*)List_Pointer_Fast(SS,i+nbvert);
      z = (double*)List_Pointer_Fast(SS,i+2*nbvert);
      v = (double*)List_Pointer_Fast(SS,i+3*nbvert);
      
      for(j=0;j<nbvert;j++)
	{
	  for(k=0;k<NbTimeStep;k++)vals[k] = v[j+k*8];
	  xyzv x(x[j],y[j],z[j]);
	  iter it = connectivities.find(x);
	  if(it == connectivities.end())
	    {
	      x.update(NbTimeStep,vals);
	      connectivities.insert(x);
	    }
	  else
	    {
	      xyzv *xx = (xyzv*) &(*it); // a little weird ... becaus we know that 
	      // this will not destroy the set ordering
	      xx->update(NbTimeStep,vals);
	    }
	}
    }   
  
  for(i = 0 ; i < List_Nbr(SS) ; i+=nb)
    {
      x = (double*)List_Pointer_Fast(SS,i);
      y = (double*)List_Pointer_Fast(SS,i+nbvert);
      z = (double*)List_Pointer_Fast(SS,i+2*nbvert);
      v = (double*)List_Pointer_Fast(SS,i+3*nbvert);
      for(j=0;j<nbvert;j++)
	{
	  xyzv xyz(x[j],y[j],z[j]);
	  //double l = sqrt((x[j])*(x[j]) + y[j]*y[j] + z[j] * z[j]);
	  iter it = connectivities.find(xyz);
	  for(k=0;k<NbTimeStep;k++)v[j+k*8] = (*it).vals[k];
	  //for(k=0;k<NbTimeStep;k++)v[j+k*8] = l;


	}
    } 
  delete [] vals;
}

void Post_View :: smooth ()
{
  xyzv::eps = CTX.lc * 1.e-6;
  int nb;

  if(NbSS){
    mycont conSS;
    Msg(INFO,"Smoothing SS vector in a view ...");
    nb = List_Nbr(SS) / NbSS ;
    smooth_list (SS , NbTimeStep, 4, nb, conSS);
    Msg(INFO,"...done");
  }
  if(NbST){
    mycont conST;
    Msg(INFO,"Smoothing ST vector in a view ...");
    nb = List_Nbr(ST) / NbST ;
    smooth_list (ST , NbTimeStep, 3, nb, conST);
    Msg(INFO,"...done");
  }
  
}

/*
  Another util to smooth normals
*/

void Post_View :: reset_normals()
{
  if(normals)delete normals;
  normals  = 0;
}

void Post_View :: add_normal(double x, double y, double z, 
			     double nx, double ny, double nz)
{
  if(!normals)normals = new smooth_container;
  xyzv xyz(x,y,z);
  double n[3] = {nx,ny,nz};
  iter it = normals->c.find(xyz);
  if(it == normals->c.end())
    {
      xyz.update(3,n);
      normals->c.insert(xyz);
    }
  else
    {
      xyzv *xx = (xyzv*) &(*it); 
      xx->update(3,n);
    }
}

bool Post_View :: get_normal(double x, double y, double z, 
			     double &nx, double &ny, double &nz)
{
  if(!normals)
    return false;
  xyzv xyz(x,y,z);
  iter it = normals->c.find(xyz);
  if(it == normals->c.end())return false;
  nx = (*it).vals[0];
  ny = (*it).vals[1];
  nz = (*it).vals[2];
  return true;
}