From cf27b169274b68454ecb7dfe43beb7f25585a384 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Tue, 7 Dec 2004 04:52:27 +0000
Subject: [PATCH] - Moved all the Raise[][] stuff out of the drawing routines,
 and into   Graphics/Post.cpp

- New 'generalized raise' mode (can use arbitrary expressions, possibly
  with external data sources, to raise/offset views dynamically). Original
  patch by Nicolas Tardieu. Merci Nico!
---
 Common/DefaultOptions.h     |  15 +
 Common/Makefile             |   4 +-
 Common/Options.cpp          |  93 ++++-
 Common/Options.h            |   6 +
 Common/Views.cpp            |  92 ++++-
 Common/Views.h              |  20 +-
 Fltk/Callbacks.cpp          |  39 ++-
 Fltk/GUI.cpp                |  55 ++-
 Graphics/Draw.h             |   9 +-
 Graphics/Entity.cpp         |  35 +-
 Graphics/Geom.cpp           |   8 +-
 Graphics/Iso.cpp            |  23 +-
 Graphics/Mesh.cpp           |   8 +-
 Graphics/Post.cpp           | 237 ++++++++++---
 Graphics/PostElement.cpp    | 672 +++++++++++++-----------------------
 Plugin/Extract.cpp          |   8 +-
 Plugin/Lambda2.cpp          |   5 +-
 Plugin/StructuralSolver.cpp |   2 +-
 doc/FAQ                     |  12 +-
 doc/VERSIONS                |   7 +-
 doc/texinfo/opt_solver.texi |   2 +-
 doc/texinfo/opt_view.texi   |  30 ++
 22 files changed, 817 insertions(+), 565 deletions(-)

diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index 8cc6cb3e02..cb705078b1 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -373,8 +373,16 @@ StringXString ViewOptions_String[] = {
   { F|O, "Format" , opt_view_format , "%.3e" , 
     "Number format (in standard C form)" },
 
+  { F|O, "GeneralizedRaiseX" , opt_view_gen_raise0 , "" , 
+    "Generalized elevation of the view along X-axis (in model coordinates)" },
+  { F|O, "GeneralizedRaiseY" , opt_view_gen_raise1 , "" , 
+    "Generalized elevation of the view along Y-axis (in model coordinates)" },
+  { F|O, "GeneralizedRaiseZ" , opt_view_gen_raise2 , "v0" , 
+    "Generalized elevation of the view along Z-axis (in model coordinates)" },
+
   { F,   "Name" , opt_view_name , "" , 
     "Default post-processing view name" },
+
   { 0, NULL , NULL , NULL , NULL }
 } ;
 
@@ -1034,6 +1042,10 @@ StringXNumber ViewOptions_Number[] = {
   { F|O, "ExternalView" , opt_view_external_view , -1. ,
     "Index of the view used to color vector fields (-1=self)" },
 
+  { F|O, "GeneralizedRaiseFactor" , opt_view_gen_raise_factor , 1. ,
+    "Generalized raise amplification factor" },
+  { F|O, "GeneralizedRaiseView" , opt_view_gen_raise_view , -1. ,
+    "Index of the view used for generalized raise (-1=self)" },
   { F|O, "Grid" , opt_view_grid , 2 ,
     "Grid mode for 2D graphs (0=none, 1=simple, 2=frame, 3=grid)" },
 
@@ -1113,6 +1125,9 @@ StringXNumber ViewOptions_Number[] = {
   { F, "Type" , opt_view_type , DRAW_POST_3D ,
     "Type of graph (1=3D, 2=2D-space, 3=2D-time)" },
 
+  { F|O, "UseGeneralizedRaise" , opt_view_use_gen_raise , 0 ,
+    "Use generalized raise?" },
+
   { F|O, "VectorType" , opt_view_vector_type , DRAW_POST_ARROW3D ,
     "Vector display type (1=segment, 2=arrow, 3=pyramid, 4=3D arrow, 5=displacement)" },
   { F,   "Visible" , opt_view_visible , 1. ,
diff --git a/Common/Makefile b/Common/Makefile
index a6474375aa..dd94bf9f77 100644
--- a/Common/Makefile
+++ b/Common/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.66 2004-12-06 04:59:08 geuzaine Exp $
+# $Id: Makefile,v 1.67 2004-12-07 04:52:25 geuzaine Exp $
 #
 # Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 #
@@ -22,7 +22,7 @@
 include ../variables
 
 LIB     = ../lib/libGmshCommon.a
-INCLUDE = -I../Common -I../DataStr -I../Geo -I../Graphics\
+INCLUDE = -I../Common -I../DataStr -I../Geo -I../Graphics -I../MathEval\
           -I../Mesh -I../Numeric -I../Parser -I../Plugin -I../Fltk
 CFLAGS  = ${OPTIM} ${FLAGS} ${INCLUDE}
 
diff --git a/Common/Options.cpp b/Common/Options.cpp
index 2adab0081f..097791e240 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -1,4 +1,4 @@
-// $Id: Options.cpp,v 1.208 2004-12-06 06:54:32 geuzaine Exp $
+// $Id: Options.cpp,v 1.209 2004-12-07 04:52:25 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -1889,8 +1889,49 @@ char *opt_view_abscissa_format(OPT_ARGS_STR)
   return v->AbscissaFormat;
 }
 
-// Numeric option routines
+char * opt_view_gen_raise0(OPT_ARGS_STR)
+{
+  GET_VIEW("");
+  if(action & GMSH_SET) {
+    strcpy(v->GenRaiseX, val);
+    v->Changed = 1;
+  }
+#if defined(HAVE_FLTK)
+  if(_gui_action_valid(action, num))
+    WID->view_input[4]->value(v->GenRaiseX);
+#endif
+  return v->GenRaiseX;
+}
+
+char * opt_view_gen_raise1(OPT_ARGS_STR)
+{
+  GET_VIEW("");
+  if(action & GMSH_SET) {
+    strcpy(v->GenRaiseY, val);
+    v->Changed = 1;
+  }
+#if defined(HAVE_FLTK)
+  if(_gui_action_valid(action, num))
+    WID->view_input[5]->value(v->GenRaiseY);
+#endif
+  return v->GenRaiseY;
+}
+
+char * opt_view_gen_raise2(OPT_ARGS_STR)
+{
+  GET_VIEW("");
+  if(action & GMSH_SET) {
+    strcpy(v->GenRaiseZ, val);
+    v->Changed = 1;
+  }
+#if defined(HAVE_FLTK)
+  if(_gui_action_valid(action, num))
+    WID->view_input[6]->value(v->GenRaiseZ);
+#endif
+  return v->GenRaiseZ;
+}
 
+// Numeric option routines
 
 double opt_general_initial_context(OPT_ARGS_NUM)
 {
@@ -5384,6 +5425,54 @@ double opt_view_external_view(OPT_ARGS_NUM)
   return v->ExternalViewIndex;
 }
 
+double opt_view_gen_raise_view(OPT_ARGS_NUM)
+{
+  GET_VIEW(0.);
+  if(action & GMSH_SET) {
+    v->ViewIndexForGenRaise = (int)val;
+    v->Changed = 1;
+  }
+#if defined(HAVE_FLTK)
+  if(_gui_action_valid(action, num)){
+    // warning: Fl_Choice::size() returns number of items+1
+    int item = v->ViewIndexForGenRaise + 1;
+    if(item > -1 && item < WID->view_choice[11]->size()-1)
+      WID->view_choice[11]->value(item);
+    else
+      WID->view_choice[11]->value(0);
+  }
+#endif
+  return v->ViewIndexForGenRaise;
+}
+
+double opt_view_gen_raise_factor(OPT_ARGS_NUM)
+{
+  GET_VIEW(0.);
+  if(action & GMSH_SET) {
+    v->GenRaiseFactor = val;
+    v->Changed = 1;
+  }
+#if defined(HAVE_FLTK)
+  if(_gui_action_valid(action, num))
+    WID->view_value[2]->value(v->GenRaiseFactor);
+#endif
+  return v->GenRaiseFactor;
+}
+
+double opt_view_use_gen_raise(OPT_ARGS_NUM)
+{
+  GET_VIEW(0.);
+  if(action & GMSH_SET) {
+    v->UseGenRaise = (int)val;
+    v->Changed = 1;
+  }
+#if defined(HAVE_FLTK)
+  if(_gui_action_valid(action, num))
+    WID->view_butt[6]->value(v->UseGenRaise);
+#endif
+  return v->UseGenRaise;
+}
+
 double opt_print_format(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
diff --git a/Common/Options.h b/Common/Options.h
index 743cdfb266..a5ac67c5c6 100644
--- a/Common/Options.h
+++ b/Common/Options.h
@@ -197,6 +197,9 @@ char * opt_view_format(OPT_ARGS_STR);
 char * opt_view_filename(OPT_ARGS_STR);
 char * opt_view_abscissa_name(OPT_ARGS_STR);
 char * opt_view_abscissa_format(OPT_ARGS_STR);
+char * opt_view_gen_raise0(OPT_ARGS_STR);
+char * opt_view_gen_raise1(OPT_ARGS_STR);
+char * opt_view_gen_raise2(OPT_ARGS_STR);
 
 // NUMBERS
 
@@ -482,6 +485,9 @@ double opt_view_max_recursion_level(OPT_ARGS_NUM);
 double opt_view_target_error(OPT_ARGS_NUM);
 double opt_view_alpha_channel(OPT_ARGS_NUM);
 double opt_view_external_view(OPT_ARGS_NUM);
+double opt_view_gen_raise_view(OPT_ARGS_NUM);
+double opt_view_gen_raise_factor(OPT_ARGS_NUM);
+double opt_view_use_gen_raise(OPT_ARGS_NUM);
 double opt_view_type(OPT_ARGS_NUM);
 double opt_view_grid(OPT_ARGS_NUM);
 double opt_view_position0(OPT_ARGS_NUM);
diff --git a/Common/Views.cpp b/Common/Views.cpp
index 07bd5a9571..012c406ce2 100644
--- a/Common/Views.cpp
+++ b/Common/Views.cpp
@@ -1,4 +1,4 @@
-// $Id: Views.cpp,v 1.147 2004-11-25 22:07:50 geuzaine Exp $
+// $Id: Views.cpp,v 1.148 2004-12-07 04:52:25 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -18,6 +18,9 @@
 // USA.
 // 
 // Please report all bugs and problems to <gmsh@geuz.org>.
+//
+// Contributor(s):
+//   Nicolas Tardieu
 
 #include <set>
 #include "Gmsh.h"
@@ -28,6 +31,10 @@
 #include "ColorTable.h"
 #include "SmoothNormals.h"
 
+#if defined(HAVE_MATH_EVAL)
+#include "matheval.h"
+#endif
+
 extern Context_T CTX;
 
 #if defined(HAVE_FLTK)
@@ -172,6 +179,8 @@ Post_View *BeginView(int allocate)
     v->BBox[2 * i] = VAL_INF;
     v->BBox[2 * i + 1] = -VAL_INF;
   }
+  for(i = 0; i < 3; i++)
+    v->GenRaise_f[i] = NULL;
 
   return v;
 }
@@ -575,6 +584,7 @@ void FreeView(Post_View * v)
     if(v->normals) delete v->normals;
     if(v->TriVertexArray) delete v->TriVertexArray;
     if(v->adaptive) delete v->adaptive;
+    FreeGeneralizedRaise(v);
     Free(v);
   }
 }
@@ -645,6 +655,12 @@ void CopyViewOptions(Post_View * src, Post_View * dest)
   dest->LineType = src->LineType;
   dest->Grid = src->Grid;
   dest->ExternalViewIndex = src->ExternalViewIndex;
+  dest->ViewIndexForGenRaise = src->ViewIndexForGenRaise;
+  dest->UseGenRaise = src->UseGenRaise;
+  dest->GenRaiseFactor = src->GenRaiseFactor;
+  strcpy(dest->GenRaiseX, src->GenRaiseX);
+  strcpy(dest->GenRaiseY, src->GenRaiseY);
+  strcpy(dest->GenRaiseZ, src->GenRaiseZ);
   ColorTable_Copy(&src->CT);
   ColorTable_Paste(&dest->CT);
 }
@@ -1514,3 +1530,77 @@ void Post_View::get_raw_data(int type, List_T **list, int **nbe, int *nbc, int *
   default: Msg(GERROR, "Wrong type in Post_View::get_raw_data"); break;
   }
 }
+
+// Generalized raise
+
+void InitGeneralizedRaise(Post_View *v)
+{
+  FreeGeneralizedRaise(v);
+
+  char *expr[3] = { v->GenRaiseX, v->GenRaiseY, v->GenRaiseZ };
+#if defined(HAVE_MATH_EVAL)
+  for(int i = 0; i < 3; i++) {
+    if(strlen(expr[i])) {
+      if(!(v->GenRaise_f[i] = evaluator_create(expr[i])))
+        Msg(GERROR, "Invalid expression '%s'", expr[i]);
+    }
+  }
+#else
+  for(int i = 0; i < 3; i++) {
+    if(!strcmp(expr[i], "v0")) v->GenRaise_f[i] = (void*)0;
+    else if(!strcmp(expr[i], "v1")) v->GenRaise_f[i] = (void*)1;
+    else if(!strcmp(expr[i], "v2")) v->GenRaise_f[i] = (void*)2;
+    else if(!strcmp(expr[i], "v3")) v->GenRaise_f[i] = (void*)3;
+    else if(!strcmp(expr[i], "v4")) v->GenRaise_f[i] = (void*)4;
+    else if(!strcmp(expr[i], "v5")) v->GenRaise_f[i] = (void*)5;
+    else if(!strcmp(expr[i], "v6")) v->GenRaise_f[i] = (void*)6;
+    else if(!strcmp(expr[i], "v7")) v->GenRaise_f[i] = (void*)7;
+    else if(!strcmp(expr[i], "v8")) v->GenRaise_f[i] = (void*)8;
+    else if(strlen(expr[i])) {
+      Msg(GERROR, "Invalid expression '%s'", expr[i]);
+      return;
+    }
+  }
+#endif
+}
+
+void FreeGeneralizedRaise(Post_View *v)
+{
+  for(int i = 0; i < 3; i++){
+#if defined(HAVE_MATH_EVAL)
+    if(v->GenRaise_f[i])
+      evaluator_destroy(v->GenRaise_f[i]);
+    v->GenRaise_f[i] = NULL;
+#else
+    v->GenRaise_f[i] = (void*)-1;
+#endif
+  }
+}
+
+void ApplyGeneralizedRaise(Post_View * v, int numNodes, int numComp, double *vals,
+			   double *x, double *y, double *z)
+{
+  double *coords[3] = { x, y, z };
+
+  for(int k = 0; k < numNodes; k++) {
+    double d[9] = {0., 0., 0., 0., 0., 0., 0., 0., 0.};
+    for(int l = 0; l < numComp; l++)
+      d[l] = vals[numComp * k + l];
+#if defined(HAVE_MATH_EVAL)
+    char *names[] = { "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8" };
+    double values[] = { d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8] };
+    for(int i = 0; i < 3; i++) {
+      if(v->GenRaise_f[i])
+        coords[i][k] += 
+	  evaluator_evaluate(v->GenRaise_f[i], sizeof(names) / 
+			     sizeof(names[0]), names, values) * v->GenRaiseFactor;
+    }
+#else
+    for(int i = 0; i < 3; i++){
+      int comp = (int)v->GenRaise_f[i];
+      if(comp >= 0)
+	coords[i][k] += d[comp] * v->GenRaiseFactor;
+    }
+#endif
+  }
+}
diff --git a/Common/Views.h b/Common/Views.h
index e4942ec486..f81d4a2c48 100644
--- a/Common/Views.h
+++ b/Common/Views.h
@@ -31,6 +31,15 @@
 #define VIEW_MAX_ELEMENT_NODES  8
 #define VAL_INF 1.e200
 
+#define POST_POINT           0
+#define POST_LINE            1
+#define POST_TRIANGLE        2
+#define POST_QUADRANGLE      3
+#define POST_TETRAHEDRON     4
+#define POST_HEXAHEDRON      5
+#define POST_PRISM           6
+#define POST_PYRAMID         7
+
 class Post_View{
  public :
   // intrinsic to a view
@@ -86,7 +95,11 @@ class Post_View{
   int Boundary, Grid, PointType, LineType;
   double PointSize, LineWidth;
   GmshColorTable CT;
-  int ExternalViewIndex;
+  int ExternalViewIndex, ViewIndexForGenRaise;
+  int UseGenRaise;
+  double GenRaiseFactor;
+  char GenRaiseX[256], GenRaiseY[256], GenRaiseZ[256];
+  void *GenRaise_f[3];
 
   // dynamic
   double (*GVFI) (double min, double max, int nb, int index);
@@ -185,4 +198,9 @@ void Print_ColorTable(int num, int diff, char *prefix, FILE *file);
 
 double ComputeVonMises(double* val);
 
+void InitGeneralizedRaise(Post_View *v);
+void FreeGeneralizedRaise(Post_View *v);
+void ApplyGeneralizedRaise(Post_View * v, int numNodes, int numComp, double *vals,
+			   double *x, double *y, double *z);
+
 #endif
diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp
index b8f8322ec9..9c0ba24c0a 100644
--- a/Fltk/Callbacks.cpp
+++ b/Fltk/Callbacks.cpp
@@ -1,4 +1,4 @@
-// $Id: Callbacks.cpp,v 1.301 2004-12-06 06:54:32 geuzaine Exp $
+// $Id: Callbacks.cpp,v 1.302 2004-12-07 04:52:25 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -3482,6 +3482,8 @@ void view_options_ok_cb(CALLBACK_ARGS)
   double range_type = opt_view_range_type(current, GMSH_GET, 0);
   double grid = opt_view_grid(current, GMSH_GET, 0);
   double boundary = opt_view_boundary(current, GMSH_GET, 0);
+  double external_view = opt_view_external_view(current, GMSH_GET, 0);
+  double gen_raise_view = opt_view_gen_raise_view(current, GMSH_GET, 0);
 
   double type = opt_view_type(current, GMSH_GET, 0);
   double saturate_values = opt_view_saturate_values(current, GMSH_GET, 0);
@@ -3506,9 +3508,10 @@ void view_options_ok_cb(CALLBACK_ARGS)
   double draw_scalars = opt_view_draw_scalars(current, GMSH_GET, 0);
   double draw_vectors = opt_view_draw_vectors(current, GMSH_GET, 0);
   double draw_tensors = opt_view_draw_tensors(current, GMSH_GET, 0);
+  double use_gen_raise = opt_view_use_gen_raise(current, GMSH_GET, 0);
+
   double normals = opt_view_normals(current, GMSH_GET, 0);
   double tangents = opt_view_tangents(current, GMSH_GET, 0);
-
   double custom_min = opt_view_custom_min(current, GMSH_GET, 0);
   double custom_max = opt_view_custom_max(current, GMSH_GET, 0);
   double nb_iso = opt_view_nb_iso(current, GMSH_GET, 0);
@@ -3522,7 +3525,6 @@ void view_options_ok_cb(CALLBACK_ARGS)
   double arrow_size = opt_view_arrow_size(current, GMSH_GET, 0);
   double arrow_size_proportional = opt_view_arrow_size_proportional(current, GMSH_GET, 0);
   double displacement_factor = opt_view_displacement_factor(current, GMSH_GET, 0);
-  double external_view = opt_view_external_view(current, GMSH_GET, 0);
   double point_size = opt_view_point_size(current, GMSH_GET, 0);
   double line_width = opt_view_line_width(current, GMSH_GET, 0);
   double explode = opt_view_explode(current, GMSH_GET, 0);
@@ -3532,6 +3534,7 @@ void view_options_ok_cb(CALLBACK_ARGS)
   double size0 = opt_view_size0(current, GMSH_GET, 0);
   double size1 = opt_view_size1(current, GMSH_GET, 0);
   double nb_abscissa = opt_view_nb_abscissa(current, GMSH_GET, 0);
+  double gen_raise_factor = opt_view_gen_raise_factor(current, GMSH_GET, 0);
 
   char name[256];
   strcpy(name, opt_view_name(current, GMSH_GET, NULL));
@@ -3541,6 +3544,12 @@ void view_options_ok_cb(CALLBACK_ARGS)
   strcpy(abscissa_name, opt_view_abscissa_name(current, GMSH_GET, NULL));
   char abscissa_format[256];
   strcpy(abscissa_format, opt_view_abscissa_format(current, GMSH_GET, NULL));
+  char gen_raise0[256];
+  strcpy(gen_raise0, opt_view_gen_raise0(current, GMSH_GET, NULL));
+  char gen_raise1[256];
+  strcpy(gen_raise1, opt_view_gen_raise1(current, GMSH_GET, NULL));
+  char gen_raise2[256];
+  strcpy(gen_raise2, opt_view_gen_raise2(current, GMSH_GET, NULL));
 
   // modify only the views that need to be updated
   for(int i = 0; i < List_Nbr(CTX.post.list); i++) {
@@ -3662,6 +3671,10 @@ void view_options_ok_cb(CALLBACK_ARGS)
       if(force || (val != external_view))
         opt_view_external_view(i, GMSH_SET, val);
 
+      val = WID->view_choice[11]->value()-1;
+      if(force || (val != gen_raise_view))
+        opt_view_gen_raise_view(i, GMSH_SET, val);
+
       // view_butts
 
       val = WID->view_butt[0]->value();
@@ -3753,6 +3766,10 @@ void view_options_ok_cb(CALLBACK_ARGS)
       if(force || (val != draw_tensors))
         opt_view_draw_tensors(i, GMSH_SET, val);
 
+      val = WID->view_butt[6]->value();
+      if(force || (val != use_gen_raise))
+        opt_view_use_gen_raise(i, GMSH_SET, val);
+
       // view_values
       
       val = WID->view_value[0]->value();
@@ -3855,6 +3872,10 @@ void view_options_ok_cb(CALLBACK_ARGS)
       if(force || (val != nb_abscissa))
         opt_view_nb_abscissa(i, GMSH_SET, val);
 
+      val = WID->view_value[2]->value();
+      if(force || (val != gen_raise_factor))
+        opt_view_gen_raise_factor(i, GMSH_SET, val);
+
       // view_inputs
 
       char *str;
@@ -3875,6 +3896,18 @@ void view_options_ok_cb(CALLBACK_ARGS)
       if(force || strcmp(str, abscissa_format))
         opt_view_abscissa_format(i, GMSH_SET, str);
 
+      str = (char *)WID->view_input[4]->value();
+      if(force || strcmp(str, gen_raise0))
+        opt_view_gen_raise0(i, GMSH_SET, str);
+
+      str = (char *)WID->view_input[5]->value();
+      if(force || strcmp(str, gen_raise1))
+        opt_view_gen_raise1(i, GMSH_SET, str);
+
+      str = (char *)WID->view_input[6]->value();
+      if(force || strcmp(str, gen_raise2))
+        opt_view_gen_raise2(i, GMSH_SET, str);
+
       // colorbar window
 
       if(force || (WID->view_colorbar_window->changed() && i != current)) {
diff --git a/Fltk/GUI.cpp b/Fltk/GUI.cpp
index 5f300b4272..69d50865f1 100644
--- a/Fltk/GUI.cpp
+++ b/Fltk/GUI.cpp
@@ -1,4 +1,4 @@
-// $Id: GUI.cpp,v 1.386 2004-12-06 06:54:32 geuzaine Exp $
+// $Id: GUI.cpp,v 1.387 2004-12-07 04:52:25 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -1480,13 +1480,18 @@ void GUI::reset_external_view_list()
 {
   char str[32];
   view_choice[10]->clear();
+  view_choice[11]->clear();
   view_choice[10]->add("Self");
+  view_choice[11]->add("Self");
   for(int i = 0; i < List_Nbr(CTX.post.list); i++) {
     sprintf(str, "View [%d]", i);
     view_choice[10]->add(str, 0, NULL);
+    view_choice[11]->add(str, 0, NULL);
   }
-  if(view_number >= 0)
+  if(view_number >= 0){
     opt_view_external_view(view_number, GMSH_GUI, 0);
+    opt_view_gen_raise_view(view_number, GMSH_GUI, 0);
+  }
 }
 
 void GUI::check_rotation_center_button()
@@ -2624,24 +2629,45 @@ void GUI::create_option_window()
       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Offset");
       o->hide();
 
-      view_value[40] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 1 * BH, IW, BH, "X offset");
+      view_value[40] = new Fl_Value_Input(L + width / 2, 2 * WB + 1 * BH, IW, BH, "X offset");
       view_value[40]->align(FL_ALIGN_RIGHT);
 
-      view_value[41] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 2 * BH, IW, BH, "Y offset");
+      view_value[41] = new Fl_Value_Input(L + width / 2, 2 * WB + 2 * BH, IW, BH, "Y offset");
       view_value[41]->align(FL_ALIGN_RIGHT);
 
-      view_value[42] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 3 * BH, IW, BH, "Z offset");
+      view_value[42] = new Fl_Value_Input(L + width / 2, 2 * WB + 3 * BH, IW, BH, "Z offset");
       view_value[42]->align(FL_ALIGN_RIGHT);
 
-      view_value[43] = new Fl_Value_Input(L + width / 2, 2 * WB + 1 * BH, IW, BH, "X raise");
+      view_value[43] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 1 * BH, IW, BH, "X raise");
       view_value[43]->align(FL_ALIGN_RIGHT);
 
-      view_value[44] = new Fl_Value_Input(L + width / 2, 2 * WB + 2 * BH, IW, BH, "Y raise");
+      view_value[44] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 2 * BH, IW, BH, "Y raise");
       view_value[44]->align(FL_ALIGN_RIGHT);
 
-      view_value[45] = new Fl_Value_Input(L + width / 2, 2 * WB + 3 * BH, IW, BH, "Z raise");
+      view_value[45] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 3 * BH, IW, BH, "Z raise");
       view_value[45]->align(FL_ALIGN_RIGHT);
 
+      view_butt[6] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 4 * BH, BW, BH, "Use general raise expressions");
+      view_butt[6]->type(FL_TOGGLE_BUTTON);
+      view_butt[6]->down_box(TOGGLE_BOX);
+      view_butt[6]->selection_color(TOGGLE_COLOR);
+
+      view_choice[11] = new Fl_Choice(L + 2 * WB, 2 * WB + 5 * BH, IW, BH, "Raise data source");
+      view_choice[11]->align(FL_ALIGN_RIGHT);
+      view_choice[11]->add("Self");
+
+      view_value[2] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 6 * BH, IW, BH, "Raise factor");
+      view_value[2]->align(FL_ALIGN_RIGHT);
+
+      view_input[4] = new Fl_Input(L + 2 * WB, 2 * WB + 7 * BH, IW, BH, "X raise expression");
+      view_input[4]->align(FL_ALIGN_RIGHT);
+
+      view_input[5] = new Fl_Input(L + 2 * WB, 2 * WB + 8 * BH, IW, BH, "Y raise expression");
+      view_input[5]->align(FL_ALIGN_RIGHT);
+
+      view_input[6] = new Fl_Input(L + 2 * WB, 2 * WB + 9 * BH, IW, BH, "Z raise expression");
+      view_input[6]->align(FL_ALIGN_RIGHT);
+
       o->end();
     }
     {
@@ -2790,6 +2816,8 @@ void GUI::update_view_window(int num)
 
   double maxval = MAX(fabs(v->Min), fabs(v->Max));
   if(!maxval) maxval = 1.;
+  double val1 = 10. * CTX.lc;
+  double val2 = 2. * CTX.lc / maxval;
 
   opt_view_name(num, GMSH_GUI, NULL);
   opt_view_format(num, GMSH_GUI, NULL);
@@ -2881,7 +2909,6 @@ void GUI::update_view_window(int num)
   opt_view_offset0(num, GMSH_GUI, 0);
   opt_view_offset1(num, GMSH_GUI, 0);
   opt_view_offset2(num, GMSH_GUI, 0);
-  double val1 = 10. * CTX.lc;
   for(int i = 40; i <= 42; i++) {
     view_value[i]->step(val1/100.);
     view_value[i]->minimum(-val1);
@@ -2890,12 +2917,20 @@ void GUI::update_view_window(int num)
   opt_view_raise0(num, GMSH_GUI, 0);
   opt_view_raise1(num, GMSH_GUI, 0);
   opt_view_raise2(num, GMSH_GUI, 0);
-  double val2 = 2. * CTX.lc / maxval;
   for(int i = 43; i <= 45; i++) {
     view_value[i]->step(val2/100.);
     view_value[i]->minimum(-val2);
     view_value[i]->maximum(val2);
   }
+  opt_view_use_gen_raise(num, GMSH_GUI, 0);
+  opt_view_gen_raise_view(num, GMSH_GUI, 0);
+  opt_view_gen_raise_factor(num, GMSH_GUI, 0);
+  opt_view_gen_raise0(num, GMSH_GUI, 0);
+  opt_view_gen_raise1(num, GMSH_GUI, 0);
+  opt_view_gen_raise2(num, GMSH_GUI, 0);
+  view_value[2]->step(val2/100.);
+  view_value[2]->minimum(-val2);
+  view_value[2]->maximum(val2);
 
   if(v->NbTimeStep == 1) {
     view_value[50]->deactivate();
diff --git a/Graphics/Draw.h b/Graphics/Draw.h
index af683a629a..e008a4ea87 100644
--- a/Graphics/Draw.h
+++ b/Graphics/Draw.h
@@ -72,13 +72,13 @@ void Draw_Disk(double size, double rint, double x, double y, double z, int light
 void Draw_Sphere(double size, double x, double y, double z, int light);
 void Draw_Cylinder(double width, double *x, double *y, double *z, int light);
 void Draw_Point(int type, double size, double *x, double *y, double *z, 
-		double Raise[3][8], int light);
+		int light);
 void Draw_Line(int type, double width, double *x, double *y, double *z,
-	       double Raise[3][8], int light);
+	       int light);
 void Draw_Vector(int Type, int Fill,
 		 double relHeadRadius, double relStemLength, double relStemRadius,
 		 double x, double y, double z, double dx, double dy, double dz,
-		 double Raise[3][8], int light);
+		 int light);
 
 void Draw_Mesh(Mesh *M);
 void Draw_Mesh_Volume(void *a, void *b);
@@ -141,4 +141,7 @@ int GiveIndexFromValue_Lin(double ValMin, double ValMax, int NbIso, double Val);
 int GiveIndexFromValue_Log(double ValMin, double ValMax, int NbIso, double Val);
 int GiveIndexFromValue_DoubleLog(double ValMin, double ValMax, int NbIso, double Val);
 
+int GetValuesFromExternalView(Post_View *v, int type, int refcomp, 
+			      int *nbcomp, double **vals, int viewIndex);
+
 #endif
diff --git a/Graphics/Entity.cpp b/Graphics/Entity.cpp
index b233c8ccf0..24013fa804 100644
--- a/Graphics/Entity.cpp
+++ b/Graphics/Entity.cpp
@@ -1,4 +1,4 @@
-// $Id: Entity.cpp,v 1.47 2004-09-14 10:33:37 remacle Exp $
+// $Id: Entity.cpp,v 1.48 2004-12-07 04:52:26 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -120,14 +120,13 @@ void Draw_PlaneInBoundingBox(double xmin, double ymin, double zmin,
 }
 
 void Draw_Point(int type, double size, double *x, double *y, double *z,
-                double Raise[3][8], int light)
+                int light)
 {
   if(type)
-    Draw_Sphere(size, x[0] + Raise[0][0], y[0] + Raise[1][0],
-                z[0] + Raise[2][0], light);
+    Draw_Sphere(size, x[0], y[0], z[0], light);
   else {
     glBegin(GL_POINTS);
-    glVertex3d(x[0] + Raise[0][0], y[0] + Raise[1][0], z[0] + Raise[2][0]);
+    glVertex3d(x[0], y[0], z[0]);
     glEnd();
   }
 }
@@ -217,24 +216,14 @@ void Draw_Cylinder(double width, double *x, double *y, double *z, int light)
 }
 
 void Draw_Line(int type, double width, double *x, double *y, double *z,
-               double Raise[3][8], int light)
+               int light)
 {
-  double X[2], Y[2], Z[2];
-
-  X[0] = x[0] + Raise[0][0];
-  Y[0] = y[0] + Raise[1][0];
-  Z[0] = z[0] + Raise[2][0];
-
-  X[1] = x[1] + Raise[0][1];
-  Y[1] = y[1] + Raise[1][1];
-  Z[1] = z[1] + Raise[2][1];
-
   if(type)
-    Draw_Cylinder(width, X, Y, Z, light);
+    Draw_Cylinder(width, x, y, z, light);
   else {
     glBegin(GL_LINES);
-    glVertex3d(X[0], Y[0], Z[0]);
-    glVertex3d(X[1], Y[1], Z[1]);
+    glVertex3d(x[0], y[0], z[0]);
+    glVertex3d(x[1], y[1], z[1]);
     glEnd();
   }
 }
@@ -442,19 +431,13 @@ void Draw_3DArrow(double relHeadRadius, double relStemLength, double relStemRadi
 void Draw_Vector(int Type, int Fill,
 		 double relHeadRadius, double relStemLength, double relStemRadius,
                  double x, double y, double z, double dx, double dy, double dz,
-                 double Raise[3][8], int light)
+                 int light)
 {
   double length = sqrt(dx * dx + dy * dy + dz * dz);
 
   if(length == 0.0)
     return;
 
-  if(Raise != NULL) {
-    x += Raise[0][0];
-    y += Raise[1][0];
-    z += Raise[2][0];
-  }
-
   switch(Type){
   case DRAW_POST_SEGMENT:
     glBegin(GL_LINES);
diff --git a/Graphics/Geom.cpp b/Graphics/Geom.cpp
index b756cae0e6..a0219b5627 100644
--- a/Graphics/Geom.cpp
+++ b/Graphics/Geom.cpp
@@ -1,4 +1,4 @@
-// $Id: Geom.cpp,v 1.73 2004-10-28 03:44:37 geuzaine Exp $
+// $Id: Geom.cpp,v 1.74 2004-12-07 04:52:26 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -221,7 +221,7 @@ void Draw_Curve(void *a, void *b)
     Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
 		CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius,
 		v.Pos.X, v.Pos.Y, v.Pos.Z,
-                dv.Pos.X, dv.Pos.Y, dv.Pos.Z, NULL, CTX.geom.light);
+                dv.Pos.X, dv.Pos.Y, dv.Pos.Z, CTX.geom.light);
   }
 
   if(CTX.render_mode == GMSH_SELECT) {
@@ -514,7 +514,7 @@ void Draw_Plane_Surface(Surface * s)
       glColor4ubv((GLubyte *) & CTX.color.geom.normals);
       Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
 		  CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius, 
-		  x, y, z, n[0], n[1], n[2], NULL, CTX.geom.light);
+		  x, y, z, n[0], n[1], n[2], CTX.geom.light);
     }
 
   }
@@ -595,7 +595,7 @@ void Draw_NonPlane_Surface(Surface * s)
     glColor4ubv((GLubyte *) & CTX.color.geom.normals);
     Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
 		CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius,
-		v1.Pos.X, v1.Pos.Y, v1.Pos.Z, n[0], n[1], n[2], NULL,
+		v1.Pos.X, v1.Pos.Y, v1.Pos.Z, n[0], n[1], n[2],
 		CTX.geom.light);
   }
 }
diff --git a/Graphics/Iso.cpp b/Graphics/Iso.cpp
index 64b15deff1..56de5f08f1 100644
--- a/Graphics/Iso.cpp
+++ b/Graphics/Iso.cpp
@@ -1,4 +1,4 @@
-// $Id: Iso.cpp,v 1.31 2004-12-06 04:59:08 geuzaine Exp $
+// $Id: Iso.cpp,v 1.32 2004-12-07 04:52:26 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -54,14 +54,8 @@ void IsoTriangle(Post_View * View, double *X, double *Y, double *Z,
     nb++;
   }
   
-  if(nb == 2) {
-    double Raise[3][8];
-    for(int i = 0; i < 3; i++)
-      for(int l = 0; l < 2; l++)
-	Raise[i][l] = View->Raise[i] * V;
-    Draw_Line(View->LineType, View->LineWidth, Xp, Yp, Zp,
-	      Raise, View->Light);
-  }
+  if(nb == 2)
+    Draw_Line(View->LineType, View->LineWidth, Xp, Yp, Zp, View->Light);
 }
 
 // Compute the polygon between the two iso-lines V1 and V2 in a
@@ -238,10 +232,7 @@ void IsoLine(Post_View *View, double *X, double *Y, double *Z,
 
   if((Val[0] >= V && Val[1] <= V) || (Val[1] >= V && Val[0] <= V)) {
     InterpolateIso(X, Y, Z, Val, V, 0, 1, Xp, Yp, Zp);
-    double Raise[3][8];
-    for(int i = 0; i < 3; i++)
-      Raise[i][0] = View->Raise[i] * V;
-    Draw_Point(View->PointType, View->PointSize, Xp, Yp, Zp, Raise, View->Light);
+    Draw_Point(View->PointType, View->PointSize, Xp, Yp, Zp, View->Light);
   }
 }
 
@@ -482,12 +473,6 @@ void IsoSimplex(Post_View * View, int preproNormals,
   if(nb < 3 || nb > 4)
     return;
 
-  for(int i = 0; i < nb; i++){
-    Xp[i] += View->Raise[0] * V;
-    Yp[i] += View->Raise[1] * V;
-    Zp[i] += View->Raise[2] * V;
-  }
-
   EnhanceSimplexPolygon(View, nb, Xp, Yp, Zp, PVals, X, Y, Z, Val, norms,
                         preproNormals);
 
diff --git a/Graphics/Mesh.cpp b/Graphics/Mesh.cpp
index b375603d22..35b2790dc3 100644
--- a/Graphics/Mesh.cpp
+++ b/Graphics/Mesh.cpp
@@ -1,4 +1,4 @@
-// $Id: Mesh.cpp,v 1.113 2004-11-19 18:26:47 geuzaine Exp $
+// $Id: Mesh.cpp,v 1.114 2004-12-07 04:52:26 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -546,7 +546,7 @@ void Draw_Mesh_Line(void *a, void *b)
     m[2] *= CTX.mesh.tangents * CTX.pixel_equiv_x / CTX.s[2];
     Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
 		CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius,
-		Xc, Yc, Zc, m[0], m[1], m[2], NULL, CTX.mesh.light);
+		Xc, Yc, Zc, m[0], m[1], m[2], CTX.mesh.light);
   }
 }
 
@@ -886,7 +886,7 @@ void Draw_Mesh_Triangle(void *a, void *b)
     n[2] *= CTX.mesh.normals * CTX.pixel_equiv_x / CTX.s[2];
     Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
 		CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius,
-		Xc, Yc, Zc, n[0], n[1], n[2], NULL, CTX.mesh.light);
+		Xc, Yc, Zc, n[0], n[1], n[2], CTX.mesh.light);
   }
 }
 
@@ -1048,7 +1048,7 @@ void Draw_Mesh_Quadrangle(void *a, void *b)
     n[2] *= CTX.mesh.normals * CTX.pixel_equiv_x / CTX.s[2];
     Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
 		CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius,
-		Xc, Yc, Zc, n[0], n[1], n[2], NULL, CTX.mesh.light);
+		Xc, Yc, Zc, n[0], n[1], n[2], CTX.mesh.light);
   }
 }
 
diff --git a/Graphics/Post.cpp b/Graphics/Post.cpp
index c95347fa7d..c2027fd7a0 100644
--- a/Graphics/Post.cpp
+++ b/Graphics/Post.cpp
@@ -1,4 +1,4 @@
-// $Id: Post.cpp,v 1.85 2004-11-25 02:10:32 geuzaine Exp $
+// $Id: Post.cpp,v 1.86 2004-12-07 04:52:26 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -126,20 +126,112 @@ unsigned int PaletteDiscrete(Post_View * v, int nbi, int i)
   return v->CT.table[index];
 }
 
-// Compute node coordinates taking Offset and Explode into account
+// Get values from a compatible external view (i.e., a view that has
+// the same number of elements as the {type,refcomp} list in the
+// reference view, and the same number of time steps)
 
-void Get_Coords(double Explode, double *Offset, int nbnod,
-                double *x1, double *y1, double *z1,
+int GetValuesFromExternalView(Post_View *v, int type, int refcomp, 
+			      int *nbcomp, double **vals, int viewIndex)
+{
+  Post_View **vv = (Post_View **) List_Pointer_Test(CTX.post.list, viewIndex);  
+
+  if(!vv){
+    if(!v->ExternalElementIndex)
+      Msg(GERROR, "Nonexistent external view: drawing self instead");
+    return 0;
+  }
+
+  Post_View *v2 = *vv;
+  int nbelm = 0, comp = 0, nbnod = 0, ref;
+  List_T *l = NULL;
+
+  switch(type){
+  case POST_POINT:
+    nbnod = 1;
+    ref = (refcomp == 1) ? v->NbSP : ((refcomp == 3) ? v->NbVP : v->NbTP);
+    if(ref == v2->NbSP){ nbelm = v2->NbSP; l = v2->SP; comp = 1; }
+    else if(ref == v2->NbVP){ nbelm = v2->NbVP; l = v2->VP; comp = 3; }
+    else if(ref == v2->NbTP){ nbelm = v2->NbTP; l = v2->TP; comp = 9; }
+    break;
+  case POST_LINE:
+    nbnod = 2;
+    ref = (refcomp == 1) ? v->NbSL : ((refcomp == 3) ? v->NbVL : v->NbTL);
+    if(ref == v2->NbSL){ nbelm = v2->NbSL; l = v2->SL; comp = 1; } 
+    else if(ref == v2->NbVL){ nbelm = v2->NbVL; l = v2->VL; comp = 3; } 
+    else if(ref == v2->NbTL){ nbelm = v2->NbTL; l = v2->TL; comp = 9; } 
+    break;
+  case POST_TRIANGLE:
+    nbnod = 3;
+    ref = (refcomp == 1) ? v->NbST : ((refcomp == 3) ? v->NbVT : v->NbTT);
+    if(ref == v2->NbST){ nbelm = v2->NbST; l = v2->ST; comp = 1;  } 
+    else if(ref == v2->NbVT){ nbelm = v2->NbVT; l = v2->VT; comp = 3;  } 
+    else if(ref == v2->NbTT){ nbelm = v2->NbTT; l = v2->TT; comp = 9;  } 
+    break;
+  case POST_QUADRANGLE:
+    nbnod = 4;
+    ref = (refcomp == 1) ? v->NbSQ : ((refcomp == 3) ? v->NbVQ : v->NbTQ);
+    if(ref == v2->NbSQ){ nbelm = v2->NbSQ; l = v2->SQ; comp = 1;  } 
+    else if(ref == v2->NbVQ){ nbelm = v2->NbVQ; l = v2->VQ; comp = 3;  } 
+    else if(ref == v2->NbTQ){ nbelm = v2->NbTQ; l = v2->TQ; comp = 9;  } 
+    break;
+  case POST_TETRAHEDRON:
+    nbnod = 4;
+    ref = (refcomp == 1) ? v->NbSS : ((refcomp == 3) ? v->NbVS : v->NbTS);
+    if(ref == v2->NbSS){ nbelm = v2->NbSS; l = v2->SS; comp = 1;  } 
+    else if(ref == v2->NbVS){ nbelm = v2->NbVS; l = v2->VS; comp = 3;  } 
+    else if(ref == v2->NbTS){ nbelm = v2->NbTS; l = v2->TS; comp = 9;  } 
+    break;
+  case POST_HEXAHEDRON:
+    nbnod = 8;
+    ref = (refcomp == 1) ? v->NbSH : ((refcomp == 3) ? v->NbVH : v->NbTH);
+    if(ref == v2->NbSH){ nbelm = v2->NbSH; l = v2->SH; comp = 1;  }
+    else if(ref == v2->NbVH){ nbelm = v2->NbVH; l = v2->VH; comp = 3;  }
+    else if(ref == v2->NbTH){ nbelm = v2->NbTH; l = v2->TH; comp = 9;  }
+    break;
+  case POST_PRISM:
+    nbnod = 6;
+    ref = (refcomp == 1) ? v->NbSI : ((refcomp == 3) ? v->NbVI : v->NbTI);
+    if(ref == v2->NbSI){ nbelm = v2->NbSI; l = v2->SI; comp = 1;  }
+    else if(ref == v2->NbVI){ nbelm = v2->NbVI; l = v2->VI; comp = 3;  }
+    else if(ref == v2->NbTI){ nbelm = v2->NbTI; l = v2->TI; comp = 9;  }
+    break;
+  case POST_PYRAMID:
+    nbnod = 5;
+    ref = (refcomp == 1) ? v->NbSY : ((refcomp == 3) ? v->NbVY : v->NbTY);
+    if(ref == v2->NbSY){ nbelm = v2->NbSY; l = v2->SY; comp = 1;  } 
+    else if(ref == v2->NbVY){ nbelm = v2->NbVY; l = v2->VY; comp = 3;  } 
+    else if(ref == v2->NbTY){ nbelm = v2->NbTY; l = v2->TY; comp = 9;  } 
+    break;
+  }
+
+  if(!l || !nbelm || v2->NbTimeStep != v->NbTimeStep ||
+     v->ExternalElementIndex < 0 || v->ExternalElementIndex >= nbelm){
+    if(!v->ExternalElementIndex)
+      Msg(GERROR, "Incompatible external view: drawing self instead");
+    return 0;
+  }
+
+  int nb = List_Nbr(l) / nbelm;
+  *nbcomp = comp;
+  *vals = (double *)List_Pointer(l, v->ExternalElementIndex * nb + 
+				 3 * nbnod + comp * nbnod * v->TimeStep);
+  return 1;
+}
+
+// Compute node coordinates taking Offset, Raise and Explode into account
+
+void Get_Coords(Post_View *v, int type, int nbnod, int nbcomp,
+                double *x1, double *y1, double *z1, double *vals,
                 double *x2, double *y2, double *z2)
 {
   int i;
   double xc = 0., yc = 0., zc = 0.;
 
-  if(Explode == 1) {
+  if(v->Explode == 1.) {
     for(i = 0; i < nbnod; i++) {
-      x2[i] = x1[i] + Offset[0];
-      y2[i] = y1[i] + Offset[1];
-      z2[i] = z1[i] + Offset[2];
+      x2[i] = x1[i] + v->Offset[0];
+      y2[i] = y1[i] + v->Offset[1];
+      z2[i] = z1[i] + v->Offset[2];
     }
   }
   else {
@@ -152,11 +244,37 @@ void Get_Coords(double Explode, double *Offset, int nbnod,
     yc /= (double)nbnod;
     zc /= (double)nbnod;
     for(i = 0; i < nbnod; i++) {
-      x2[i] = xc + Explode * (x1[i] - xc) + Offset[0];
-      y2[i] = yc + Explode * (y1[i] - yc) + Offset[1];
-      z2[i] = zc + Explode * (z1[i] - zc) + Offset[2];
+      x2[i] = xc + v->Explode * (x1[i] - xc) + v->Offset[0];
+      y2[i] = yc + v->Explode * (y1[i] - yc) + v->Offset[1];
+      z2[i] = zc + v->Explode * (z1[i] - zc) + v->Offset[2];
+    }
+  }
+
+  if(v->Raise[0] || v->Raise[1] || v->Raise[2]){
+    for(int k = 0; k < nbnod; k++){
+      double norm = 0.;
+      if(nbcomp == 1)
+	norm = vals[k];
+      else if(nbcomp == 3)
+	norm = sqrt(vals[3*k] * vals[3*k] + 
+		    vals[3*k+1] * vals[3*k+1] + 
+		    vals[3*k+2] * vals[3*k+2]);
+      else if(nbcomp == 9)
+	norm = ComputeVonMises(vals + 9*k);
+      x2[k] += v->Raise[0] * norm;
+      y2[k] += v->Raise[1] * norm;
+      z2[k] += v->Raise[2] * norm;
     }
   }
+
+  if(v->UseGenRaise){
+    int ext_nbcomp = nbcomp;
+    double *ext_vals = vals;
+    if(v->ViewIndexForGenRaise >= 0)
+      GetValuesFromExternalView(v, type, nbcomp, &ext_nbcomp, &ext_vals, 
+				v->ViewIndexForGenRaise);
+    ApplyGeneralizedRaise(v, nbnod, ext_nbcomp, ext_vals, x2, y2, z2);
+  }
 }
 
 // Compare barycenters with viewpoint (eye)
@@ -181,8 +299,6 @@ int changedEye()
   return 0;
 }
 
-// to be rigorous, we should take Raise into account
-
 int compareEye(double *q, double *w, int nbnodes)
 {
   double d, dq, dw, cgq[3] = { 0., 0., 0. }, cgw[3] = { 0., 0., 0.};
@@ -231,8 +347,8 @@ int compareEye8Nodes(const void *a, const void *b)
 
 // Draw_Post
 
-void Draw_List(Post_View * v, double ValMin, double ValMax,
-	       List_T * list, int nbelm, int nbnod,
+void Draw_List(Post_View * v, double ValMin, double ValMax, int type,
+	       List_T * list, int nbelm, int nbnod, int nbcomp,
 	       void (*draw) (Post_View *, int, double, double, double *, 
 			     double *, double *, double *))
 {
@@ -246,10 +362,13 @@ void Draw_List(Post_View * v, double ValMin, double ValMax,
       Msg(DEBUG, "Preprocessing of normals in View[%d]", v->Index);
       v->ExternalElementIndex = 0;
       for(i = 0; i < List_Nbr(list); i += nb) {
-        Get_Coords(v->Explode, v->Offset, nbnod,
+        Get_Coords(v, type, nbnod, nbcomp,
                    (double *)List_Pointer_Fast(list, i),
                    (double *)List_Pointer_Fast(list, i + nbnod),
-                   (double *)List_Pointer_Fast(list, i + 2 * nbnod), X, Y, Z);
+                   (double *)List_Pointer_Fast(list, i + 2 * nbnod), 
+		   (double *)List_Pointer_Fast(list, i + 3 * nbnod +
+					       v->TimeStep * nbnod * nbcomp),
+		   X, Y, Z);
         draw(v, 1, ValMin, ValMax, X, Y, Z,
              (double *)List_Pointer_Fast(list, i + 3 * nbnod));
 	v->ExternalElementIndex++;
@@ -258,10 +377,13 @@ void Draw_List(Post_View * v, double ValMin, double ValMax,
 
     v->ExternalElementIndex = 0;
     for(i = 0; i < List_Nbr(list); i += nb) {
-      Get_Coords(v->Explode, v->Offset, nbnod,
+      Get_Coords(v, type, nbnod, nbcomp,
                  (double *)List_Pointer_Fast(list, i),
                  (double *)List_Pointer_Fast(list, i + nbnod),
-                 (double *)List_Pointer_Fast(list, i + 2 * nbnod), X, Y, Z);
+                 (double *)List_Pointer_Fast(list, i + 2 * nbnod),
+		 (double *)List_Pointer_Fast(list, i + 3 * nbnod +
+					     v->TimeStep * nbnod * nbcomp),
+		 X, Y, Z);
       draw(v, 0, ValMin, ValMax, X, Y, Z,
            (double *)List_Pointer_Fast(list, i + 3 * nbnod));
       v->ExternalElementIndex++;
@@ -396,6 +518,9 @@ void Draw_Post(void)
       if(v->Light && v->SmoothNormals && v->Changed)
 	v->reset_normals();
 
+      if(v->UseGenRaise)
+	InitGeneralizedRaise(v);
+
       // initialize alpha blending for transparency
       if(CTX.alpha && ColorTable_IsAlpha(&v->CT)){
 	if(CTX.fake_transparency){
@@ -446,19 +571,25 @@ void Draw_Post(void)
 
       if(v->DrawPoints) {
 	if(v->Type == DRAW_POST_3D && v->DrawScalars)
-	  Draw_List(v, ValMin, ValMax, v->SP, v->NbSP, 1, Draw_ScalarPoint);
+	  Draw_List(v, ValMin, ValMax, POST_POINT, v->SP, v->NbSP, 1, 1, 
+		    Draw_ScalarPoint);
 	if(v->DrawVectors)
-	  Draw_List(v, ValMin, ValMax, v->VP, v->NbVP, 1, Draw_VectorPoint);
+	  Draw_List(v, ValMin, ValMax, POST_POINT, v->VP, v->NbVP, 1, 3, 
+		    Draw_VectorPoint);
 	if(v->DrawTensors)
-	  Draw_List(v, ValMin, ValMax, v->TP, v->NbTP, 1, Draw_TensorPoint);
+	  Draw_List(v, ValMin, ValMax, POST_POINT, v->TP, v->NbTP, 1, 9, 
+		    Draw_TensorPoint);
       }
       if(v->DrawLines) {
 	if(v->DrawScalars)
-	  Draw_List(v, ValMin, ValMax, v->SL, v->NbSL, 2, Draw_ScalarLine);
+	  Draw_List(v, ValMin, ValMax, POST_LINE, v->SL, v->NbSL, 2, 1,
+		    Draw_ScalarLine);
 	if(v->DrawVectors)
-	  Draw_List(v, ValMin, ValMax, v->VL, v->NbVL, 2, Draw_VectorLine);
+	  Draw_List(v, ValMin, ValMax, POST_LINE, v->VL, v->NbVL, 2, 3, 
+		    Draw_VectorLine);
 	if(v->DrawTensors)
-	  Draw_List(v, ValMin, ValMax, v->TL, v->NbTL, 2, Draw_TensorLine);
+	  Draw_List(v, ValMin, ValMax, POST_LINE, v->TL, v->NbTL, 2, 9, 
+		    Draw_TensorLine);
       }
 
       for(int pass = 0; pass < 2; pass++){
@@ -494,51 +625,69 @@ void Draw_Post(void)
       pass_0:
 	if(v->DrawTriangles) {
 	  if(!skip_2d && v->DrawScalars)
-	    Draw_List(v, ValMin, ValMax, v->ST, v->NbST, 3, Draw_ScalarTriangle);
+	    Draw_List(v, ValMin, ValMax, POST_TRIANGLE, v->ST, v->NbST, 3, 1,
+		      Draw_ScalarTriangle);
 	  if(v->DrawVectors)
-	    Draw_List(v, ValMin, ValMax, v->VT, v->NbVT, 3, Draw_VectorTriangle);
+	    Draw_List(v, ValMin, ValMax, POST_TRIANGLE, v->VT, v->NbVT, 3, 3,
+		      Draw_VectorTriangle);
 	  if(v->DrawTensors)
-	    Draw_List(v, ValMin, ValMax, v->TT, v->NbTT, 3, Draw_TensorTriangle);
+	    Draw_List(v, ValMin, ValMax, POST_TRIANGLE, v->TT, v->NbTT, 3, 9,
+		      Draw_TensorTriangle);
 	}
 	if(v->DrawQuadrangles) {
 	  if(!skip_2d && v->DrawScalars)
-	    Draw_List(v, ValMin, ValMax, v->SQ, v->NbSQ, 4, Draw_ScalarQuadrangle);
+	    Draw_List(v, ValMin, ValMax, POST_QUADRANGLE, v->SQ, v->NbSQ, 4, 1,
+		      Draw_ScalarQuadrangle);
 	  if(v->DrawVectors)
-	    Draw_List(v, ValMin, ValMax, v->VQ, v->NbVQ, 4, Draw_VectorQuadrangle);
+	    Draw_List(v, ValMin, ValMax, POST_QUADRANGLE, v->VQ, v->NbVQ, 4, 3,
+		      Draw_VectorQuadrangle);
 	  if(v->DrawTensors)
-	    Draw_List(v, ValMin, ValMax, v->TQ, v->NbTQ, 4, Draw_TensorQuadrangle);
+	    Draw_List(v, ValMin, ValMax, POST_QUADRANGLE, v->TQ, v->NbTQ, 4, 9,
+		      Draw_TensorQuadrangle);
 	}
 	if(v->DrawTetrahedra) {
 	  if(!skip_3d && v->DrawScalars)
-	    Draw_List(v, ValMin, ValMax, v->SS, v->NbSS, 4, Draw_ScalarTetrahedron);
+	    Draw_List(v, ValMin, ValMax, POST_TETRAHEDRON, v->SS, v->NbSS, 4, 1,
+		      Draw_ScalarTetrahedron);
 	  if(v->DrawVectors)
-	    Draw_List(v, ValMin, ValMax, v->VS, v->NbVS, 4, Draw_VectorTetrahedron);
+	    Draw_List(v, ValMin, ValMax, POST_TETRAHEDRON, v->VS, v->NbVS, 4, 3,
+		      Draw_VectorTetrahedron);
 	  if(v->DrawTensors)
-	    Draw_List(v, ValMin, ValMax, v->TS, v->NbTS, 4, Draw_TensorTetrahedron);
+	    Draw_List(v, ValMin, ValMax, POST_TETRAHEDRON, v->TS, v->NbTS, 4, 9,
+		      Draw_TensorTetrahedron);
 	}
 	if(v->DrawHexahedra) {
 	  if(!skip_3d && v->DrawScalars)
-	    Draw_List(v, ValMin, ValMax, v->SH, v->NbSH, 8, Draw_ScalarHexahedron);
+	    Draw_List(v, ValMin, ValMax, POST_HEXAHEDRON, v->SH, v->NbSH, 8, 1,
+		      Draw_ScalarHexahedron);
 	  if(v->DrawVectors)
-	    Draw_List(v, ValMin, ValMax, v->VH, v->NbVH, 8, Draw_VectorHexahedron);
+	    Draw_List(v, ValMin, ValMax, POST_HEXAHEDRON, v->VH, v->NbVH, 8, 3,
+		      Draw_VectorHexahedron);
 	  if(v->DrawTensors)
-	    Draw_List(v, ValMin, ValMax, v->TH, v->NbTH, 8, Draw_TensorHexahedron);
+	    Draw_List(v, ValMin, ValMax, POST_HEXAHEDRON, v->TH, v->NbTH, 8, 9,
+		      Draw_TensorHexahedron);
 	}
 	if(v->DrawPrisms) {
 	  if(!skip_3d && v->DrawScalars)
-	    Draw_List(v, ValMin, ValMax, v->SI, v->NbSI, 6, Draw_ScalarPrism);
+	    Draw_List(v, ValMin, ValMax, POST_PRISM, v->SI, v->NbSI, 6, 1,
+		      Draw_ScalarPrism);
 	  if(v->DrawVectors)
-	    Draw_List(v, ValMin, ValMax, v->VI, v->NbVI, 6, Draw_VectorPrism);
+	    Draw_List(v, ValMin, ValMax, POST_PRISM, v->VI, v->NbVI, 6, 3,
+		      Draw_VectorPrism);
 	  if(v->DrawTensors)
-	    Draw_List(v, ValMin, ValMax, v->TI, v->NbTI, 6, Draw_TensorPrism);
+	    Draw_List(v, ValMin, ValMax, POST_PRISM, v->TI, v->NbTI, 6, 9,
+		      Draw_TensorPrism);
 	}
 	if(v->DrawPyramids) {
 	  if(!skip_3d && v->DrawScalars)
-	    Draw_List(v, ValMin, ValMax, v->SY, v->NbSY, 5, Draw_ScalarPyramid);
+	    Draw_List(v, ValMin, ValMax, POST_PYRAMID, v->SY, v->NbSY, 5, 1,
+		      Draw_ScalarPyramid);
 	  if(v->DrawVectors)
-	    Draw_List(v, ValMin, ValMax, v->VY, v->NbVY, 5, Draw_VectorPyramid);
+	    Draw_List(v, ValMin, ValMax, POST_PYRAMID, v->VY, v->NbVY, 5, 3,
+		      Draw_VectorPyramid);
 	  if(v->DrawTensors)
-	    Draw_List(v, ValMin, ValMax, v->TY, v->NbTY, 5, Draw_TensorPyramid);
+	    Draw_List(v, ValMin, ValMax, POST_PYRAMID, v->TY, v->NbTY, 5, 9,
+		      Draw_TensorPyramid);
 	}
 
       pass_1:
@@ -591,7 +740,7 @@ void Draw_Post(void)
 
       for(int i = 0; i < 6; i++)
 	glDisable((GLenum)(GL_CLIP_PLANE0 + i));
-      
+
       v->Changed = 0;
     }
   }
diff --git a/Graphics/PostElement.cpp b/Graphics/PostElement.cpp
index 841e7d2999..cf1ca21e3b 100644
--- a/Graphics/PostElement.cpp
+++ b/Graphics/PostElement.cpp
@@ -1,4 +1,4 @@
-// $Id: PostElement.cpp,v 1.54 2004-11-25 02:10:32 geuzaine Exp $
+// $Id: PostElement.cpp,v 1.55 2004-12-07 04:52:27 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -32,146 +32,115 @@
 #include "Context.h"
 #include "Numeric.h"
 
-#define POINT           0
-#define LINE            1
-#define TRIANGLE        2
-#define QUADRANGLE      3
-#define TETRAHEDRON     4
-#define HEXAHEDRON      5
-#define PRISM           6
-#define PYRAMID         7
-
 extern Context_T CTX;
 
-void Draw_ElementBoundary(int type, Post_View * View, double *X, double *Y,
-                          double *Z, double Raise[3][8])
+void Draw_ElementBoundary(int type, Post_View * View, 
+			  double *X, double *Y, double *Z)
 {
-  double xx[8], yy[8], zz[8];
-
   glColor4ubv((GLubyte *) & CTX.color.fg);
   switch (type) {
-  case POINT:
-    Draw_Point(View->PointType, View->PointSize, X, Y, Z, Raise, View->Light);
+  case POST_POINT:
+    Draw_Point(View->PointType, View->PointSize, X, Y, Z, View->Light);
     break;
-  case LINE:
-    Draw_Line(0, View->LineWidth, X, Y, Z, Raise, View->Light);
+  case POST_LINE:
+    Draw_Line(0, View->LineWidth, X, Y, Z, View->Light);
     break;
-  case TRIANGLE:
+  case POST_TRIANGLE:
     glBegin(GL_LINE_LOOP);
     for(int k = 0; k < 3; k++)
-      glVertex3d(X[k] + Raise[0][k], Y[k] + Raise[1][k], Z[k] + Raise[2][k]);
+      glVertex3d(X[k], Y[k], Z[k]);
     glEnd();
     break;
-  case TETRAHEDRON:
-    for(int k = 0; k < 4; k++) {
-      xx[k] = X[k] + Raise[0][k];
-      yy[k] = Y[k] + Raise[1][k];
-      zz[k] = Z[k] + Raise[2][k];
-    }
+  case POST_TETRAHEDRON:
     glBegin(GL_LINES);
-    glVertex3d(xx[0], yy[0], zz[0]);
-    glVertex3d(xx[1], yy[1], zz[1]);
-    glVertex3d(xx[0], yy[0], zz[0]);
-    glVertex3d(xx[2], yy[2], zz[2]);
-    glVertex3d(xx[0], yy[0], zz[0]);
-    glVertex3d(xx[3], yy[3], zz[3]);
-    glVertex3d(xx[1], yy[1], zz[1]);
-    glVertex3d(xx[2], yy[2], zz[2]);
-    glVertex3d(xx[1], yy[1], zz[1]);
-    glVertex3d(xx[3], yy[3], zz[3]);
-    glVertex3d(xx[2], yy[2], zz[2]);
-    glVertex3d(xx[3], yy[3], zz[3]);
+    glVertex3d(X[0], Y[0], Z[0]);
+    glVertex3d(X[1], Y[1], Z[1]);
+    glVertex3d(X[0], Y[0], Z[0]);
+    glVertex3d(X[2], Y[2], Z[2]);
+    glVertex3d(X[0], Y[0], Z[0]);
+    glVertex3d(X[3], Y[3], Z[3]);
+    glVertex3d(X[1], Y[1], Z[1]);
+    glVertex3d(X[2], Y[2], Z[2]);
+    glVertex3d(X[1], Y[1], Z[1]);
+    glVertex3d(X[3], Y[3], Z[3]);
+    glVertex3d(X[2], Y[2], Z[2]);
+    glVertex3d(X[3], Y[3], Z[3]);
     glEnd();
     break;
-  case QUADRANGLE:
+  case POST_QUADRANGLE:
     glBegin(GL_LINE_LOOP);
     for(int k = 0; k < 4; k++)
-      glVertex3d(X[k] + Raise[0][k], Y[k] + Raise[1][k], Z[k] + Raise[2][k]);
+      glVertex3d(X[k], Y[k], Z[k]);
     glEnd();
     break;
-  case HEXAHEDRON:
-    for(int k = 0; k < 8; k++) {
-      xx[k] = X[k] + Raise[0][k];
-      yy[k] = Y[k] + Raise[1][k];
-      zz[k] = Z[k] + Raise[2][k];
-    }
+  case POST_HEXAHEDRON:
     glBegin(GL_LINES);
-    glVertex3d(xx[0], yy[0], zz[0]);
-    glVertex3d(xx[1], yy[1], zz[1]);
-    glVertex3d(xx[0], yy[0], zz[0]);
-    glVertex3d(xx[3], yy[3], zz[3]);
-    glVertex3d(xx[0], yy[0], zz[0]);
-    glVertex3d(xx[4], yy[4], zz[4]);
-    glVertex3d(xx[1], yy[1], zz[1]);
-    glVertex3d(xx[2], yy[2], zz[2]);
-    glVertex3d(xx[1], yy[1], zz[1]);
-    glVertex3d(xx[5], yy[5], zz[5]);
-    glVertex3d(xx[2], yy[2], zz[2]);
-    glVertex3d(xx[3], yy[3], zz[3]);
-    glVertex3d(xx[2], yy[2], zz[2]);
-    glVertex3d(xx[6], yy[6], zz[6]);
-    glVertex3d(xx[3], yy[3], zz[3]);
-    glVertex3d(xx[7], yy[7], zz[7]);
-    glVertex3d(xx[4], yy[4], zz[4]);
-    glVertex3d(xx[5], yy[5], zz[5]);
-    glVertex3d(xx[4], yy[4], zz[4]);
-    glVertex3d(xx[7], yy[7], zz[7]);
-    glVertex3d(xx[5], yy[5], zz[5]);
-    glVertex3d(xx[6], yy[6], zz[6]);
-    glVertex3d(xx[6], yy[6], zz[6]);
-    glVertex3d(xx[7], yy[7], zz[7]);
+    glVertex3d(X[0], Y[0], Z[0]);
+    glVertex3d(X[1], Y[1], Z[1]);
+    glVertex3d(X[0], Y[0], Z[0]);
+    glVertex3d(X[3], Y[3], Z[3]);
+    glVertex3d(X[0], Y[0], Z[0]);
+    glVertex3d(X[4], Y[4], Z[4]);
+    glVertex3d(X[1], Y[1], Z[1]);
+    glVertex3d(X[2], Y[2], Z[2]);
+    glVertex3d(X[1], Y[1], Z[1]);
+    glVertex3d(X[5], Y[5], Z[5]);
+    glVertex3d(X[2], Y[2], Z[2]);
+    glVertex3d(X[3], Y[3], Z[3]);
+    glVertex3d(X[2], Y[2], Z[2]);
+    glVertex3d(X[6], Y[6], Z[6]);
+    glVertex3d(X[3], Y[3], Z[3]);
+    glVertex3d(X[7], Y[7], Z[7]);
+    glVertex3d(X[4], Y[4], Z[4]);
+    glVertex3d(X[5], Y[5], Z[5]);
+    glVertex3d(X[4], Y[4], Z[4]);
+    glVertex3d(X[7], Y[7], Z[7]);
+    glVertex3d(X[5], Y[5], Z[5]);
+    glVertex3d(X[6], Y[6], Z[6]);
+    glVertex3d(X[6], Y[6], Z[6]);
+    glVertex3d(X[7], Y[7], Z[7]);
     glEnd();
     break;
-  case PRISM:
-    for(int k = 0; k < 6; k++) {
-      xx[k] = X[k] + Raise[0][k];
-      yy[k] = Y[k] + Raise[1][k];
-      zz[k] = Z[k] + Raise[2][k];
-    }
+  case POST_PRISM:
     glBegin(GL_LINES);
-    glVertex3d(xx[0], yy[0], zz[0]);
-    glVertex3d(xx[1], yy[1], zz[1]);
-    glVertex3d(xx[0], yy[0], zz[0]);
-    glVertex3d(xx[2], yy[2], zz[2]);
-    glVertex3d(xx[0], yy[0], zz[0]);
-    glVertex3d(xx[3], yy[3], zz[3]);
-    glVertex3d(xx[1], yy[1], zz[1]);
-    glVertex3d(xx[2], yy[2], zz[2]);
-    glVertex3d(xx[1], yy[1], zz[1]);
-    glVertex3d(xx[4], yy[4], zz[4]);
-    glVertex3d(xx[2], yy[2], zz[2]);
-    glVertex3d(xx[5], yy[5], zz[5]);
-    glVertex3d(xx[3], yy[3], zz[3]);
-    glVertex3d(xx[4], yy[4], zz[4]);
-    glVertex3d(xx[3], yy[3], zz[3]);
-    glVertex3d(xx[5], yy[5], zz[5]);
-    glVertex3d(xx[4], yy[4], zz[4]);
-    glVertex3d(xx[5], yy[5], zz[5]);
+    glVertex3d(X[0], Y[0], Z[0]);
+    glVertex3d(X[1], Y[1], Z[1]);
+    glVertex3d(X[0], Y[0], Z[0]);
+    glVertex3d(X[2], Y[2], Z[2]);
+    glVertex3d(X[0], Y[0], Z[0]);
+    glVertex3d(X[3], Y[3], Z[3]);
+    glVertex3d(X[1], Y[1], Z[1]);
+    glVertex3d(X[2], Y[2], Z[2]);
+    glVertex3d(X[1], Y[1], Z[1]);
+    glVertex3d(X[4], Y[4], Z[4]);
+    glVertex3d(X[2], Y[2], Z[2]);
+    glVertex3d(X[5], Y[5], Z[5]);
+    glVertex3d(X[3], Y[3], Z[3]);
+    glVertex3d(X[4], Y[4], Z[4]);
+    glVertex3d(X[3], Y[3], Z[3]);
+    glVertex3d(X[5], Y[5], Z[5]);
+    glVertex3d(X[4], Y[4], Z[4]);
+    glVertex3d(X[5], Y[5], Z[5]);
     glEnd();
     break;
-  case PYRAMID:
-    for(int k = 0; k < 5; k++) {
-      xx[k] = X[k] + Raise[0][k];
-      yy[k] = Y[k] + Raise[1][k];
-      zz[k] = Z[k] + Raise[2][k];
-    }
+  case POST_PYRAMID:
     glBegin(GL_LINES);
-    glVertex3d(xx[0], yy[0], zz[0]);
-    glVertex3d(xx[1], yy[1], zz[1]);
-    glVertex3d(xx[1], yy[1], zz[1]);
-    glVertex3d(xx[2], yy[2], zz[2]);
-    glVertex3d(xx[3], yy[3], zz[3]);
-    glVertex3d(xx[2], yy[2], zz[2]);
-    glVertex3d(xx[0], yy[0], zz[0]);
-    glVertex3d(xx[3], yy[3], zz[3]);
-    glVertex3d(xx[0], yy[0], zz[0]);
-    glVertex3d(xx[4], yy[4], zz[4]);
-    glVertex3d(xx[1], yy[1], zz[1]);
-    glVertex3d(xx[4], yy[4], zz[4]);
-    glVertex3d(xx[3], yy[3], zz[3]);
-    glVertex3d(xx[4], yy[4], zz[4]);
-    glVertex3d(xx[2], yy[2], zz[2]);
-    glVertex3d(xx[4], yy[4], zz[4]);
+    glVertex3d(X[0], Y[0], Z[0]);
+    glVertex3d(X[1], Y[1], Z[1]);
+    glVertex3d(X[1], Y[1], Z[1]);
+    glVertex3d(X[2], Y[2], Z[2]);
+    glVertex3d(X[3], Y[3], Z[3]);
+    glVertex3d(X[2], Y[2], Z[2]);
+    glVertex3d(X[0], Y[0], Z[0]);
+    glVertex3d(X[3], Y[3], Z[3]);
+    glVertex3d(X[0], Y[0], Z[0]);
+    glVertex3d(X[4], Y[4], Z[4]);
+    glVertex3d(X[1], Y[1], Z[1]);
+    glVertex3d(X[4], Y[4], Z[4]);
+    glVertex3d(X[3], Y[3], Z[3]);
+    glVertex3d(X[4], Y[4], Z[4]);
+    glVertex3d(X[2], Y[2], Z[2]);
+    glVertex3d(X[4], Y[4], Z[4]);
     glEnd();
     break;
   }
@@ -241,22 +210,18 @@ void Draw_ScalarPoint(Post_View * View, int preproNormals,
       d = ValMin;
   }
 
-  double Raise[3][8];
-  for(int i = 0; i < 3; i++)
-    Raise[i][0] = View->Raise[i] * d;
-
   if(View->ShowElement)
-    Draw_ElementBoundary(POINT, View, X, Y, Z, Raise);
+    Draw_ElementBoundary(POST_POINT, View, X, Y, Z);
 
   if(d >= ValMin && d <= ValMax) {
     PaletteContinuous(View, ValMin, ValMax, d);
     if(View->IntervalsType == DRAW_POST_NUMERIC) {
-      glRasterPos3d(X[0] + Raise[0][0], Y[0] + Raise[1][0], Z[0] + Raise[2][0]);
+      glRasterPos3d(X[0], Y[0], Z[0]);
       sprintf(Num, View->Format, d);
       Draw_String(Num);
     }
     else
-      Draw_Point(View->PointType, View->PointSize, X, Y, Z, Raise, View->Light);
+      Draw_Point(View->PointType, View->PointSize, X, Y, Z, View->Light);
   }
 }
 
@@ -287,18 +252,11 @@ void Draw_ScalarLine(Post_View * View, int preproNormals,
 
   SaturateValues(View->SaturateValues, ValMin, ValMax, vv, Val, 2);
 
-  double Raise[3][8];
-  for(int i = 0; i < 3; i++)
-    for(int k = 0; k < 2; k++)
-      Raise[i][k] = View->Raise[i] * Val[k];
-
   if(View->ShowElement)
-    Draw_ElementBoundary(LINE, View, X, Y, Z, Raise);
+    Draw_ElementBoundary(POST_LINE, View, X, Y, Z);
 
   if(View->Tangents){
-    double t[3] = { (X[1] + Raise[0][1]) - (X[0] + Raise[0][0]),
-		    (Y[1] + Raise[1][1]) - (Y[0] + Raise[1][0]),
-		    (Z[1] + Raise[2][1]) - (Z[0] + Raise[2][0]) };
+    double t[3] = { X[1] - X[0], Y[1] - Y[0], Z[1] - Z[0] };
     norme(t);
     t[0] *= View->Tangents * CTX.pixel_equiv_x / CTX.s[0];
     t[1] *= View->Tangents * CTX.pixel_equiv_x / CTX.s[1];
@@ -306,10 +264,8 @@ void Draw_ScalarLine(Post_View * View, int preproNormals,
     glColor4ubv((GLubyte *) & CTX.color.mesh.tangents);
     Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
 		CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius, 
-		(X[0] + Raise[0][0] + X[1] + Raise[0][1]) / 2.,
-		(Y[0] + Raise[1][0] + Y[1] + Raise[1][1]) / 2.,
-		(Z[0] + Raise[2][0] + Z[1] + Raise[2][1]) / 2.,
-		t[0], t[1], t[2], NULL, View->Light);
+		(X[0] + X[1]) / 2., (Y[0] + Y[1]) / 2.,	(Z[0] + Z[1]) / 2.,
+		t[0], t[1], t[2], View->Light);
   }
   
   if(View->IntervalsType == DRAW_POST_NUMERIC) {
@@ -317,9 +273,7 @@ void Draw_ScalarLine(Post_View * View, int preproNormals,
     if(d >= ValMin && d <= ValMax) {
       PaletteContinuous(View, ValMin, ValMax, d);
       sprintf(Num, View->Format, d);
-      glRasterPos3d((X[0] + Raise[0][0] + X[1] + Raise[0][1]) / 2.,
-                    (Y[0] + Raise[1][0] + Y[1] + Raise[1][1]) / 2.,
-                    (Z[0] + Raise[2][0] + Z[1] + Raise[2][1]) / 2.);
+      glRasterPos3d((X[0] + X[1]) / 2., (Y[0] + Y[1]) / 2., (Z[0] + Z[1]) / 2.);
       Draw_String(Num);
     }
   }
@@ -330,14 +284,14 @@ void Draw_ScalarLine(Post_View * View, int preproNormals,
       if(View->LineType) {
 	// not perfect...
 	PaletteContinuous(View, ValMin, ValMax, Val[0]);
-	Draw_Line(View->LineType, View->LineWidth, X, Y, Z, Raise, View->Light);
+	Draw_Line(View->LineType, View->LineWidth, X, Y, Z, View->Light);
       }
       else {
 	glBegin(GL_LINES);
 	PaletteContinuous(View, ValMin, ValMax, Val[0]);
-	glVertex3d(X[0] + Raise[0][0], Y[0] + Raise[1][0], Z[0] + Raise[2][0]);
+	glVertex3d(X[0], Y[0], Z[0]);
 	PaletteContinuous(View, ValMin, ValMax, Val[1]);
-	glVertex3d(X[1] + Raise[0][1], Y[1] + Raise[1][1], Z[1] + Raise[2][1]);
+	glVertex3d(X[1], Y[1], Z[1]);
 	glEnd();
       }
     }
@@ -355,12 +309,8 @@ void Draw_ScalarLine(Post_View * View, int preproNormals,
 	      View->GVFI(ValMin, ValMax, View->NbIso + 1, k),
 	      View->GVFI(ValMin, ValMax, View->NbIso + 1, k + 1),
 	      Xp, Yp, Zp, &nb, Vp);
-      if(nb == 2) {
-	for(int i = 0; i < 3; i++)
-	  for(int l = 0; l < 2; l++)
-	    Raise[i][l] = View->Raise[i] * Vp[l];
-	Draw_Line(View->LineType, View->LineWidth, Xp, Yp, Zp, Raise, View->Light);
-      }
+      if(nb == 2)
+	Draw_Line(View->LineType, View->LineWidth, Xp, Yp, Zp, View->Light);
       if(ValMin == ValMax)
 	break;
     }
@@ -387,7 +337,7 @@ void Draw_ScalarTriangle(Post_View * View, int preproNormals,
   int nb = 0;
   double d;
   double x1x0, y1y0, z1z0, x2x0, y2y0, z2z0, nn[3], norms[30];
-  double Xp[10], Yp[10], Zp[10], Vp[10], xx[10], yy[10], zz[10], Val[3];
+  double Xp[10], Yp[10], Zp[10], Vp[10], Val[3];
   char Num[100];
 
   double *vv = &V[3 * View->TimeStep];
@@ -407,20 +357,15 @@ void Draw_ScalarTriangle(Post_View * View, int preproNormals,
 
   SaturateValues(View->SaturateValues, ValMin, ValMax, vv, Val, 3);
 
-  double Raise[3][8];
-  for(int i = 0; i < 3; i++)
-    for(int k = 0; k < 3; k++)
-      Raise[i][k] = View->Raise[i] * Val[k];
-
   if(preproNormals || View->Normals ||
      (View->Light && 
       (!View->TriVertexArray || (View->TriVertexArray && View->TriVertexArray->fill)))) {
-    x1x0 = (X[1] + Raise[0][1]) - (X[0] + Raise[0][0]);
-    y1y0 = (Y[1] + Raise[1][1]) - (Y[0] + Raise[1][0]);
-    z1z0 = (Z[1] + Raise[2][1]) - (Z[0] + Raise[2][0]);
-    x2x0 = (X[2] + Raise[0][2]) - (X[0] + Raise[0][0]);
-    y2y0 = (Y[2] + Raise[1][2]) - (Y[0] + Raise[1][0]);
-    z2z0 = (Z[2] + Raise[2][2]) - (Z[0] + Raise[2][0]);
+    x1x0 = X[1] - X[0];
+    y1y0 = Y[1] - Y[0];
+    z1z0 = Z[1] - Z[0];
+    x2x0 = X[2] - X[0];
+    y2y0 = Y[2] - Y[0];
+    z2z0 = Z[2] - Z[0];
     nn[0] = y1y0 * z2z0 - z1z0 * y2y0;
     nn[1] = z1z0 * x2x0 - x1x0 * z2z0;
     nn[2] = x1x0 * y2y0 - y1y0 * x2x0;
@@ -428,7 +373,7 @@ void Draw_ScalarTriangle(Post_View * View, int preproNormals,
   }
 
   if(!preproNormals && View->ShowElement)
-    Draw_ElementBoundary(TRIANGLE, View, X, Y, Z, Raise);
+    Draw_ElementBoundary(POST_TRIANGLE, View, X, Y, Z);
 
   if(!preproNormals && View->Normals){
     double t[3] = { nn[0], nn[1], nn[2] };
@@ -438,10 +383,10 @@ void Draw_ScalarTriangle(Post_View * View, int preproNormals,
     glColor4ubv((GLubyte *) & CTX.color.mesh.normals);
     Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
 		CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius, 
-		(X[0] + Raise[0][0] + X[1] + Raise[0][1] + X[2] + Raise[0][2]) / 3.,
-		(Y[0] + Raise[1][0] + Y[1] + Raise[1][1] + Y[2] + Raise[1][2]) / 3.,
-		(Z[0] + Raise[2][0] + Z[1] + Raise[2][1] + Z[2] + Raise[2][2]) / 3.,
-		t[0], t[1], t[2], NULL, View->Light);
+		(X[0] + X[1] + X[2]) / 3.,
+		(Y[0] + Y[1] + Y[2]) / 3.,
+		(Z[0] + Z[1] + Z[2]) / 3.,
+		t[0], t[1], t[2], View->Light);
   }
   
   if(!preproNormals && View->IntervalsType == DRAW_POST_NUMERIC) {
@@ -449,9 +394,9 @@ void Draw_ScalarTriangle(Post_View * View, int preproNormals,
     if(d >= ValMin && d <= ValMax) {
       PaletteContinuous(View, ValMin, ValMax, d);
       sprintf(Num, View->Format, d);
-      glRasterPos3d((X[0] + Raise[0][0] + X[1] + Raise[0][1] + X[2] + Raise[0][2]) / 3.,
-                    (Y[0] + Raise[1][0] + Y[1] + Raise[1][1] + Y[2] + Raise[1][2]) / 3.,
-                    (Z[0] + Raise[2][0] + Z[1] + Raise[2][1] + Z[2] + Raise[2][2]) / 3.);
+      glRasterPos3d((X[0] + X[1] + X[2]) / 3.,
+                    (Y[0] + Y[1] + Y[2]) / 3.,
+                    (Z[0] + Z[1] + Z[2]) / 3.);
       Draw_String(Num);
     }
   }
@@ -463,14 +408,9 @@ void Draw_ScalarTriangle(Post_View * View, int preproNormals,
     if(Val[0] >= ValMin && Val[0] <= ValMax &&
        Val[1] >= ValMin && Val[1] <= ValMax &&
        Val[2] >= ValMin && Val[2] <= ValMax) {
-      for(int i = 0; i < 3; i++) {
-	xx[i] = X[i] + Raise[0][i];
-	yy[i] = Y[i] + Raise[1][i];
-	zz[i] = Z[i] + Raise[2][i];
-      }
       if(preproNormals){
 	for(int i = 0; i < 3; i++)
-	  View->normals->add(xx[i], yy[i], zz[i], nn[0], nn[1], nn[2]);
+	  View->normals->add(X[i], Y[i], Z[i], nn[0], nn[1], nn[2]);
 	return;
       }
       for(int i = 0; i < 3; i++) {
@@ -480,14 +420,14 @@ void Draw_ScalarTriangle(Post_View * View, int preproNormals,
       }
       if(View->SmoothNormals)
 	for(int i = 0; i < 3; i++)
-	  View->normals->get(xx[i], yy[i], zz[i], norms[3*i], norms[3*i+1], norms[3*i+2],
+	  View->normals->get(X[i], Y[i], Z[i], norms[3*i], norms[3*i+1], norms[3*i+2],
 			     View->AngleSmoothNormals);
      
       if(View->TriVertexArray && View->TriVertexArray->fill){
 	unsigned int col;
 	for(int i = 0; i < 3; i++){
 	  col = PaletteContinuous(View, ValMin, ValMax, Val[i]);
-	  View->TriVertexArray->add(xx[i], yy[i], zz[i], 
+	  View->TriVertexArray->add(X[i], Y[i], Z[i], 
 				    norms[3*i], norms[3*i+1], norms[3*i+2], col);
 	}
 	View->TriVertexArray->num++;
@@ -499,7 +439,7 @@ void Draw_ScalarTriangle(Post_View * View, int preproNormals,
 	for(int i = 0; i < 3; i++){
 	  PaletteContinuous(View, ValMin, ValMax, Val[i]);
 	  if(View->Light) glNormal3dv(&norms[3*i]);
-	  glVertex3d(xx[i], yy[i], zz[i]);
+	  glVertex3d(X[i], Y[i], Z[i]);
 	}
 	glEnd();
 	glDisable(GL_POLYGON_OFFSET_FILL);
@@ -509,14 +449,9 @@ void Draw_ScalarTriangle(Post_View * View, int preproNormals,
     else {
       CutTriangle(X, Y, Z, Val, ValMin, ValMax, Xp, Yp, Zp, &nb, Vp);
       if(nb >= 3) {
-	for(int i = 0; i < nb; i++) {
-	  xx[i] = Xp[i] + View->Raise[0] * Vp[i];
-	  yy[i] = Yp[i] + View->Raise[1] * Vp[i];
-	  zz[i] = Zp[i] + View->Raise[2] * Vp[i];
-	}
 	if(preproNormals){
 	  for(int i = 0; i < nb; i++)
-	    View->normals->add(xx[i], yy[i], zz[i], nn[0], nn[1], nn[2]);
+	    View->normals->add(Xp[i], Yp[i], Zp[i], nn[0], nn[1], nn[2]);
 	  return;
 	}
 	for(int i = 0; i < nb; i++) {
@@ -526,20 +461,20 @@ void Draw_ScalarTriangle(Post_View * View, int preproNormals,
 	}
 	if(View->SmoothNormals)
 	  for(int i = 0; i < nb; i++)
-	    View->normals->get(xx[i], yy[i], zz[i], norms[3*i], norms[3*i+1], norms[3*i+2],
+	    View->normals->get(Xp[i], Yp[i], Zp[i], norms[3*i], norms[3*i+1], norms[3*i+2],
 			       View->AngleSmoothNormals);
 	
 	if(View->TriVertexArray && View->TriVertexArray->fill){
 	  for(int i = 2; i < nb; i++) {
 	    unsigned int col;
 	    col = PaletteContinuous(View, ValMin, ValMax, Vp[0]);
-	    View->TriVertexArray->add(xx[0], yy[0], zz[0], 
+	    View->TriVertexArray->add(Xp[0], Yp[0], Zp[0], 
 				      norms[0], norms[1], norms[2], col);
 	    col = PaletteContinuous(View, ValMin, ValMax, Vp[i-1]);
-	    View->TriVertexArray->add(xx[i-1], yy[i-1], zz[i-1],
+	    View->TriVertexArray->add(Xp[i-1], Yp[i-1], Zp[i-1],
 				      norms[3*(i-1)], norms[3*(i-1)+1], norms[3*(i-1)+2], col);
 	    col = PaletteContinuous(View, ValMin, ValMax, Vp[i]);
-	    View->TriVertexArray->add(xx[i], yy[i], zz[i], 
+	    View->TriVertexArray->add(Xp[i], Yp[i], Zp[i], 
 				      norms[3*i], norms[3*i+1], norms[3*i+2], col);
 	    View->TriVertexArray->num++;	    
 	  }
@@ -551,7 +486,7 @@ void Draw_ScalarTriangle(Post_View * View, int preproNormals,
 	  for(int i = 0; i < nb; i++) {
 	    PaletteContinuous(View, ValMin, ValMax, Vp[i]);
 	    if(View->Light) glNormal3dv(&norms[3*i]);
-	    glVertex3d(xx[i], yy[i], zz[i]);
+	    glVertex3d(Xp[i], Yp[i], Zp[i]);
 	  }
 	  glEnd();
 	  glDisable(GL_POLYGON_OFFSET_FILL);
@@ -573,14 +508,9 @@ void Draw_ScalarTriangle(Post_View * View, int preproNormals,
 		  View->GVFI(ValMin, ValMax, View->NbIso + 1, k + 1),
 		  Xp, Yp, Zp, &nb, Vp);
       if(nb >= 3) {
-	for(int i = 0; i < nb; i++) {
-	  xx[i] = Xp[i] + View->Raise[0] * Vp[i];
-	  yy[i] = Yp[i] + View->Raise[1] * Vp[i];
-	  zz[i] = Zp[i] + View->Raise[2] * Vp[i];
-	}
 	if(preproNormals){
 	  for(int i = 0; i < nb; i++)
-	    View->normals->add(xx[i], yy[i], zz[i], nn[0], nn[1], nn[2]);
+	    View->normals->add(Xp[i], Yp[i], Zp[i], nn[0], nn[1], nn[2]);
 	}
 	else{
 	  for(int i = 0; i < nb; i++) {
@@ -590,16 +520,16 @@ void Draw_ScalarTriangle(Post_View * View, int preproNormals,
 	  }
 	  if(View->SmoothNormals)
 	    for(int i = 0; i < nb; i++)
-	      View->normals->get(xx[i], yy[i], zz[i], norms[3*i], norms[3*i+1], norms[3*i+2],
+	      View->normals->get(Xp[i], Yp[i], Zp[i], norms[3*i], norms[3*i+1], norms[3*i+2],
 				 View->AngleSmoothNormals);
 
 	  if(View->TriVertexArray && View->TriVertexArray->fill){
 	    for(int i = 2; i < nb; i++) {
-	      View->TriVertexArray->add(xx[0], yy[0], zz[0], 
+	      View->TriVertexArray->add(Xp[0], Yp[0], Zp[0], 
 					norms[0], norms[1], norms[2], col);
-	      View->TriVertexArray->add(xx[i-1], yy[i-1], zz[i-1],
+	      View->TriVertexArray->add(Xp[i-1], Yp[i-1], Zp[i-1],
 					norms[3*(i-1)], norms[3*(i-1)+1], norms[3*(i-1)+2], col);
-	      View->TriVertexArray->add(xx[i], yy[i], zz[i],
+	      View->TriVertexArray->add(Xp[i], Yp[i], Zp[i],
 					norms[3*i], norms[3*i+1], norms[3*i+2], col);
 	      View->TriVertexArray->num++;
 	    }
@@ -610,7 +540,7 @@ void Draw_ScalarTriangle(Post_View * View, int preproNormals,
 	    glBegin(GL_POLYGON);
 	    for(int i = 0; i < nb; i++){
 	      if(View->Light) glNormal3dv(&norms[3*i]);
-	      glVertex3d(xx[i], yy[i], zz[i]);
+	      glVertex3d(Xp[i], Yp[i], Zp[i]);
 	    }
 	    glEnd();
 	    glDisable(GL_POLYGON_OFFSET_FILL);
@@ -666,25 +596,17 @@ void Draw_ScalarTetrahedron(Post_View * View, int preproNormals,
 
   SaturateValues(View->SaturateValues, ValMin, ValMax, vv, Val, 4);
 
-  double Raise[3][8];
-  for(int i = 0; i < 3; i++)
-    for(int k = 0; k < 4; k++)
-      Raise[i][k] = View->Raise[i] * Val[k];
-
   if(!preproNormals && View->ShowElement)
-    Draw_ElementBoundary(TETRAHEDRON, View, X, Y, Z, Raise);
+    Draw_ElementBoundary(POST_TETRAHEDRON, View, X, Y, Z);
 
   if(!preproNormals && View->IntervalsType == DRAW_POST_NUMERIC) {
     d = 0.25 * (Val[0] + Val[1] + Val[2] + Val[3]);
     if(d >= ValMin && d <= ValMax) {
       PaletteContinuous(View, ValMin, ValMax, d);
       sprintf(Num, View->Format, d);
-      glRasterPos3d(0.25 * (X[0] + Raise[0][0] + X[1] + Raise[0][1] +
-                            X[2] + Raise[0][2] + X[3] + Raise[0][3]),
-                    0.25 * (Y[0] + Raise[1][0] + Y[1] + Raise[1][1] +
-                            Y[2] + Raise[1][2] + Y[3] + Raise[1][3]),
-                    0.25 * (Z[0] + Raise[2][0] + Z[1] + Raise[2][1] +
-                            Z[2] + Raise[2][2] + Z[3] + Raise[2][3]));
+      glRasterPos3d(0.25 * (X[0] + X[1] + X[2] + X[3]),
+                    0.25 * (Y[0] + Y[1] + Y[2] + Y[3]),
+                    0.25 * (Z[0] + Z[1] + Z[2] + Z[3]));
       Draw_String(Num);
     }
   }
@@ -729,11 +651,7 @@ void Draw_ScalarQuadrangle(Post_View * View, int preproNormals,
 
   if(!preproNormals && show) {
     SaturateValues(View->SaturateValues, ValMin, ValMax, vv, Val, 4);
-    double Raise[3][8];
-    for(int i = 0; i < 3; i++)
-      for(int k = 0; k < 4; k++)
-	Raise[i][k] = View->Raise[i] * Val[k];
-    Draw_ElementBoundary(QUADRANGLE, View, X, Y, Z, Raise);
+    Draw_ElementBoundary(POST_QUADRANGLE, View, X, Y, Z);
   }
 
   Draw_ScalarTriangle(View, preproNormals, ValMin, ValMax, X, Y, Z, vv); // 012
@@ -778,11 +696,7 @@ void Draw_ScalarHexahedron(Post_View * View, int preproNormals,
 
   if(!preproNormals && show) {
     SaturateValues(View->SaturateValues, ValMin, ValMax, vv, Val, 8);
-    double Raise[3][8];
-    for(int i = 0; i < 3; i++)
-      for(int k = 0; k < 8; k++)
-	Raise[i][k] = View->Raise[i] * Val[k];
-    Draw_ElementBoundary(HEXAHEDRON, View, X, Y, Z, Raise);
+    Draw_ElementBoundary(POST_HEXAHEDRON, View, X, Y, Z);
   }
 
   REORDER6(0, 1, 3, 4, 5, 7);
@@ -826,11 +740,7 @@ void Draw_ScalarPrism(Post_View * View, int preproNormals,
 
   if(!preproNormals && show) {
     SaturateValues(View->SaturateValues, ValMin, ValMax, vv, Val, 6);
-    double Raise[3][8];
-    for(int i = 0; i < 3; i++)
-      for(int k = 0; k < 6; k++)
-	Raise[i][k] = View->Raise[i] * Val[k];
-    Draw_ElementBoundary(PRISM, View, X, Y, Z, Raise);
+    Draw_ElementBoundary(POST_PRISM, View, X, Y, Z);
   }
 
   Draw_ScalarTetrahedron(View, preproNormals, ValMin, ValMax, X, Y, Z, vv); // 0123
@@ -876,11 +786,7 @@ void Draw_ScalarPyramid(Post_View * View, int preproNormals,
 
   if(!preproNormals && show) {
     SaturateValues(View->SaturateValues, ValMin, ValMax, vv, Val, 6);
-    double Raise[3][8];
-    for(int i = 0; i < 3; i++)
-      for(int k = 0; k < 5; k++)
-	Raise[i][k] = View->Raise[i] * Val[k];
-    Draw_ElementBoundary(PYRAMID, View, X, Y, Z, Raise);
+    Draw_ElementBoundary(POST_PYRAMID, View, X, Y, Z);
   }
 
   REORDER4(0, 1, 2, 4);
@@ -897,153 +803,33 @@ void Draw_ScalarElement(int type, Post_View * View, int preproNormals,
                         double *X, double *Y, double *Z, double *V)
 {
   switch(type){
-  case POINT:
+  case POST_POINT:
     Draw_ScalarPoint(View, preproNormals, ValMin, ValMax, X, Y, Z, V);
     break;
-  case LINE:
+  case POST_LINE:
     Draw_ScalarLine(View, preproNormals, ValMin, ValMax, X, Y, Z, V);
     break;
-  case TRIANGLE:
+  case POST_TRIANGLE:
     Draw_ScalarTriangle(View, preproNormals, ValMin, ValMax, X, Y, Z, V);
     break;
-  case QUADRANGLE:
+  case POST_QUADRANGLE:
     Draw_ScalarQuadrangle(View, preproNormals, ValMin, ValMax, X, Y, Z, V);
     break;
-  case TETRAHEDRON:
+  case POST_TETRAHEDRON:
     Draw_ScalarTetrahedron(View, preproNormals, ValMin, ValMax, X, Y, Z, V);
     break;
-  case HEXAHEDRON:
+  case POST_HEXAHEDRON:
     Draw_ScalarHexahedron(View, preproNormals, ValMin, ValMax, X, Y, Z, V);
     break;
-  case PRISM:
+  case POST_PRISM:
     Draw_ScalarPrism(View, preproNormals, ValMin, ValMax, X, Y, Z, V);
     break;
-  case PYRAMID:
+  case POST_PYRAMID:
     Draw_ScalarPyramid(View, preproNormals, ValMin, ValMax, X, Y, Z, V);
     break;
   }
 }
 
-int GetDataFromOtherView(int type, Post_View *v, int *nbcomp,
-			 double *norm, double **vals, int *vectype)
-{
-  Post_View **vv = (Post_View **)List_Pointer_Test(CTX.post.list, 
-						   v->ExternalViewIndex);
-
-  if(!vv){
-    if(!v->ExternalElementIndex)
-      Msg(GERROR, "Nonexistent external view: drawing self instead");
-    return 0;
-  }
-
-  Post_View *v2 = *vv;
-
-  int nbelm = 0, comp = 0, nbnod = 0;
-  List_T *l;
-  switch (type) {
-  case POINT:
-    nbnod = 1;
-    if(v->NbVP == v2->NbSP){ nbelm = v2->NbSP; l = v2->SP; comp = 1; }
-    else if(v->NbVP == v2->NbVP){ nbelm = v2->NbVP; l = v2->VP; comp = 3; }
-    else if(v->NbVP == v2->NbTP){ nbelm = v2->NbTP; l = v2->TP; comp = 9; }
-    break;
-  case LINE:
-    nbnod = 2;
-    if(v->NbVL == v2->NbSL){ nbelm = v2->NbSL; l = v2->SL; comp = 1; } 
-    else if(v->NbVL == v2->NbVL){ nbelm = v2->NbVL; l = v2->VL; comp = 3; } 
-    else if(v->NbVL == v2->NbTL){ nbelm = v2->NbTL; l = v2->TL; comp = 9; } 
-    break;
-  case TRIANGLE:
-    nbnod = 3;
-    if(v->NbVT == v2->NbST){ nbelm = v2->NbST; l = v2->ST; comp = 1;  } 
-    else if(v->NbVT == v2->NbVT){ nbelm = v2->NbVT; l = v2->VT; comp = 3;  } 
-    else if(v->NbVT == v2->NbTT){ nbelm = v2->NbTT; l = v2->TT; comp = 9;  } 
-    break;
-  case QUADRANGLE:
-    nbnod = 4;
-    if(v->NbVQ == v2->NbSQ){ nbelm = v2->NbSQ; l = v2->SQ; comp = 1;  } 
-    else if(v->NbVQ == v2->NbVQ){ nbelm = v2->NbVQ; l = v2->VQ; comp = 3;  } 
-    else if(v->NbVQ == v2->NbTQ){ nbelm = v2->NbTQ; l = v2->TQ; comp = 9;  } 
-    break;
-  case TETRAHEDRON:
-    nbnod = 4;
-    if(v->NbVS == v2->NbSS){ nbelm = v2->NbSS; l = v2->SS; comp = 1;  } 
-    else if(v->NbVS == v2->NbVS){ nbelm = v2->NbVS; l = v2->VS; comp = 3;  } 
-    else if(v->NbVS == v2->NbTS){ nbelm = v2->NbTS; l = v2->TS; comp = 9;  } 
-    break;
-  case HEXAHEDRON:
-    nbnod = 8;
-    if(v->NbVH == v2->NbSH){ nbelm = v2->NbSH; l = v2->SH; comp = 1;  }
-    else if(v->NbVH == v2->NbVH){ nbelm = v2->NbVH; l = v2->VH; comp = 3;  }
-    else if(v->NbVH == v2->NbTH){ nbelm = v2->NbTH; l = v2->TH; comp = 9;  }
-    break;
-  case PRISM:
-    nbnod = 6;
-    if(v->NbVI == v2->NbSI){ nbelm = v2->NbSI; l = v2->SI; comp = 1;  }
-    else if(v->NbVI == v2->NbVI){ nbelm = v2->NbVI; l = v2->VI; comp = 3;  }
-    else if(v->NbVI == v2->NbTI){ nbelm = v2->NbTI; l = v2->TI; comp = 9;  }
-    break;
-  case PYRAMID:
-    nbnod = 5;
-    if(v->NbVY == v2->NbSY){ nbelm = v2->NbSY; l = v2->SY; comp = 1;  } 
-    else if(v->NbVY == v2->NbVY){ nbelm = v2->NbVY; l = v2->VY; comp = 3;  } 
-    else if(v->NbVY == v2->NbTY){ nbelm = v2->NbTY; l = v2->TY; comp = 9;  } 
-    break;
-  }
-
-  if(!nbelm || v2->NbTimeStep != v->NbTimeStep ||
-     v->ExternalElementIndex < 0 || v->ExternalElementIndex >= nbelm){
-    if(!v->ExternalElementIndex)
-      Msg(GERROR, "Incompatible external view: drawing self instead");
-    return 0;
-  }
-
-  int nb = List_Nbr(l) / nbelm;
-  double *vp = (double *)List_Pointer(l, v->ExternalElementIndex * nb + 3 * nbnod + 
-				      comp * nbnod * v->TimeStep);
-  for(int k = 0; k < nbnod; k++){
-    if(comp == 1)
-      norm[k] = vp[k];
-    else if(comp == 3)
-      norm[k] = sqrt(vp[3*k] * vp[3*k] + 
-		     vp[3*k+1] * vp[3*k+1] + 
-		     vp[3*k+2] * vp[3*k+2]);
-    else if(comp == 9)
-      norm[k] = ComputeVonMises(vp + 9*k);
-  }
-
-  *vals = vp;
-  
-  switch (v->RangeType) {
-  case DRAW_POST_RANGE_DEFAULT:
-    v->ExternalMin = v2->Min;
-    v->ExternalMax = v2->Max;
-    break;
-  case DRAW_POST_RANGE_CUSTOM: // yes, take the values from v!
-    v->ExternalMin = v->CustomMin;
-    v->ExternalMax = v->CustomMax;
-    break;
-  case DRAW_POST_RANGE_PER_STEP:
-    if(v->TimeStepMin && v->TimeStepMax){
-      v->ExternalMin = v2->TimeStepMin[v->TimeStep];
-      v->ExternalMax = v2->TimeStepMax[v->TimeStep];
-    }
-    else{
-      v->ExternalMin = v2->Min;
-      v->ExternalMax = v2->Max;
-    }
-    break;
-  }
-
-  if(v2->VectorType == DRAW_POST_DISPLACEMENT)
-    *vectype = DRAW_POST_ARROW3D; // avoid recursion
-  else
-    *vectype = v2->VectorType;
-  *nbcomp = comp;
-
-  return 1;
-}
-
 // Vector Elements
 
 void Draw_VectorElement(int type, Post_View * View, int preproNormals,
@@ -1052,14 +838,14 @@ void Draw_VectorElement(int type, Post_View * View, int preproNormals,
 {
   int nbnod = 0;
   switch (type) {
-  case POINT: nbnod = 1; break;
-  case LINE: nbnod = 2; break;
-  case TRIANGLE: nbnod = 3; break;
-  case QUADRANGLE: nbnod = 4; break;
-  case TETRAHEDRON: nbnod = 4; break;
-  case HEXAHEDRON: nbnod = 8; break;
-  case PRISM: nbnod = 6; break;
-  case PYRAMID: nbnod = 5; break;
+  case POST_POINT: nbnod = 1; break;
+  case POST_LINE: nbnod = 2; break;
+  case POST_TRIANGLE: nbnod = 3; break;
+  case POST_QUADRANGLE: nbnod = 4; break;
+  case POST_TETRAHEDRON: nbnod = 4; break;
+  case POST_HEXAHEDRON: nbnod = 8; break;
+  case POST_PRISM: nbnod = 6; break;
+  case POST_PYRAMID: nbnod = 5; break;
   }
 
   double Val[8][3], norm[8];
@@ -1076,25 +862,57 @@ void Draw_VectorElement(int type, Post_View * View, int preproNormals,
   for(int k = 0; k < nbnod; k++)
     ext_norm[k] = norm[k];
 
-  if(View->ExternalViewIndex >= 0){
-    GetDataFromOtherView(type, View, &ext_nbcomp, ext_norm, &ext_vals, &ext_vectype);
+  if(View->ExternalViewIndex >= 0 &&
+     GetValuesFromExternalView(View, type, 3, &ext_nbcomp, &ext_vals, 
+			       View->ExternalViewIndex)){
+    for(int k = 0; k < nbnod; k++){
+      if(ext_nbcomp == 1)
+	ext_norm[k] = ext_vals[k];
+      else if(ext_nbcomp == 3)
+	ext_norm[k] = sqrt(ext_vals[3*k] * ext_vals[3*k] + 
+			   ext_vals[3*k+1] * ext_vals[3*k+1] + 
+			   ext_vals[3*k+2] * ext_vals[3*k+2]);
+      else if(ext_nbcomp == 9)
+	ext_norm[k] = ComputeVonMises(ext_vals + 9*k);
+    }
+    Post_View *v2 = *(Post_View**)List_Pointer_Fast(CTX.post.list, 
+						    View->ExternalViewIndex);
+    switch (View->RangeType) {
+    case DRAW_POST_RANGE_DEFAULT:
+      View->ExternalMin = v2->Min;
+      View->ExternalMax = v2->Max;
+      break;
+    case DRAW_POST_RANGE_CUSTOM: // yes, take the values from View!
+      View->ExternalMin = View->CustomMin;
+      View->ExternalMax = View->CustomMax;
+      break;
+    case DRAW_POST_RANGE_PER_STEP:
+      if(View->TimeStepMin && View->TimeStepMax){
+	View->ExternalMin = v2->TimeStepMin[View->TimeStep];
+	View->ExternalMax = v2->TimeStepMax[View->TimeStep];
+      }
+      else{
+	View->ExternalMin = v2->Min;
+	View->ExternalMax = v2->Max;
+      }
+      break;
+    }
     ext_min = View->ExternalMin;
     ext_max = View->ExternalMax;
+    if(v2->VectorType == DRAW_POST_DISPLACEMENT)
+      ext_vectype = DRAW_POST_ARROW3D; // avoid recursion
+    else
+      ext_vectype = v2->VectorType;
   }
 
-  double Raise[3][8];
-  for(int i = 0; i < 3; i++)
-    for(int k = 0; k < nbnod; k++)
-      Raise[i][k] = View->Raise[i] * norm[k];
-
   if(View->VectorType == DRAW_POST_DISPLACEMENT){
 
     double fact = View->DisplacementFactor;
     double xx[8], yy[8], zz[8];
     for(int k = 0; k < nbnod; k++) {
-      xx[k] = X[k] + fact * Val[k][0] + Raise[0][k];
-      yy[k] = Y[k] + fact * Val[k][1] + Raise[1][k];
-      zz[k] = Z[k] + fact * Val[k][2] + Raise[2][k];
+      xx[k] = X[k] + fact * Val[k][0];
+      yy[k] = Y[k] + fact * Val[k][1];
+      zz[k] = Z[k] + fact * Val[k][2];
     }
     
     int ts = View->TimeStep;
@@ -1104,13 +922,9 @@ void Draw_VectorElement(int type, Post_View * View, int preproNormals,
     
     if(ext_nbcomp == 1){
       Draw_ScalarElement(type, View, preproNormals, ext_min, ext_max, xx, yy, zz, ext_norm);
-      if(type == POINT && ts > 0) {  // draw point "trajectory"
+      if(type == POST_POINT && ts > 0) {  // draw point "trajectory"
 	if(View->LineType) {
 	  double dx, dy, dz, dx2, dy2, dz2, XX[2], YY[2], ZZ[2];
-	  // warning, warning...
-	  Raise[0][1] = Raise[0][0];
-	  Raise[1][1] = Raise[1][0];
-	  Raise[2][1] = Raise[2][0];
 	  for(int j = 0; j < ts; j++) {
 	    dx = V[3 * (ts - j)];
 	    dy = V[3 * (ts - j) + 1];
@@ -1127,7 +941,7 @@ void Draw_VectorElement(int type, Post_View * View, int preproNormals,
 	    YY[1] = Y[0] + fact * dy2;
 	    ZZ[0] = Z[0] + fact * dz;
 	    ZZ[1] = Z[0] + fact * dz2;
-	    Draw_Line(View->LineType, View->LineWidth, XX, YY, ZZ, Raise, View->Light);
+	    Draw_Line(View->LineType, View->LineWidth, XX, YY, ZZ, View->Light);
 	  }
 	}
 	else {
@@ -1138,9 +952,9 @@ void Draw_VectorElement(int type, Post_View * View, int preproNormals,
 	    double dz = V[3 * (ts - j) + 2];
 	    double dd = sqrt(dx * dx + dy * dy + dz * dz);
 	    PaletteContinuous(View, ValMin, ValMax, dd);
-	    glVertex3d(X[0] + fact * dx + Raise[0][0],
-		       Y[0] + fact * dy + Raise[1][0],
-		       Z[0] + fact * dz + Raise[2][0]);
+	    glVertex3d(X[0] + fact * dx,
+		       Y[0] + fact * dy,
+		       Z[0] + fact * dz);
 	  }
 	  glEnd();
 	}
@@ -1162,29 +976,29 @@ void Draw_VectorElement(int type, Post_View * View, int preproNormals,
     return;
 
   if(View->ShowElement)
-    Draw_ElementBoundary(type, View, X, Y, Z, Raise);
+    Draw_ElementBoundary(type, View, X, Y, Z);
 
   double xc = 0., yc = 0., zc = 0.;
   if(View->Normals || View->Tangents || 
      View->IntervalsType == DRAW_POST_NUMERIC ||
      View->ArrowLocation == DRAW_POST_LOCATE_COG){
     for(int k = 0; k < nbnod; k++) {
-      xc += X[k] + Raise[0][k];
-      yc += Y[k] + Raise[1][k];
-      zc += Z[k] + Raise[2][k];
+      xc += X[k];
+      yc += Y[k];
+      zc += Z[k];
     }
     xc /= (double)nbnod;
     yc /= (double)nbnod;
     zc /= (double)nbnod;
   }
 
-  if(View->Normals && (type == TRIANGLE || type == QUADRANGLE)){
-    double x1x0 = (X[1] + Raise[0][1]) - (X[0] + Raise[0][0]);
-    double y1y0 = (Y[1] + Raise[1][1]) - (Y[0] + Raise[1][0]);
-    double z1z0 = (Z[1] + Raise[2][1]) - (Z[0] + Raise[2][0]);
-    double x2x0 = (X[2] + Raise[0][2]) - (X[0] + Raise[0][0]);
-    double y2y0 = (Y[2] + Raise[1][2]) - (Y[0] + Raise[1][0]);
-    double z2z0 = (Z[2] + Raise[2][2]) - (Z[0] + Raise[2][0]);
+  if(View->Normals && (type == POST_TRIANGLE || type == POST_QUADRANGLE)){
+    double x1x0 = X[1] - X[0];
+    double y1y0 = Y[1] - Y[0];
+    double z1z0 = Z[1] - Z[0];
+    double x2x0 = X[2] - X[0];
+    double y2y0 = Y[2] - Y[0];
+    double z2z0 = Z[2] - Z[0];
     double nn[3];
     nn[0] = y1y0 * z2z0 - z1z0 * y2y0;
     nn[1] = z1z0 * x2x0 - x1x0 * z2z0;
@@ -1196,13 +1010,11 @@ void Draw_VectorElement(int type, Post_View * View, int preproNormals,
     glColor4ubv((GLubyte *) & CTX.color.mesh.normals);
     Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
 		CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius, 
-		xc, yc, zc, nn[0], nn[1], nn[2], NULL, View->Light);
+		xc, yc, zc, nn[0], nn[1], nn[2], View->Light);
   }
 
-  if(View->Tangents && (type == LINE)){
-    double t[3] = { (X[1] + Raise[0][1]) - (X[0] + Raise[0][0]),
-		    (Y[1] + Raise[1][1]) - (Y[0] + Raise[1][0]),
-		    (Z[1] + Raise[2][1]) - (Z[0] + Raise[2][0]) };
+  if(View->Tangents && (type == POST_LINE)){
+    double t[3] = { X[1] - X[0], Y[1] - Y[0], Z[1] - Z[0] };
     norme(t);
     t[0] *= View->Tangents * CTX.pixel_equiv_x / CTX.s[0];
     t[1] *= View->Tangents * CTX.pixel_equiv_x / CTX.s[1];
@@ -1210,7 +1022,7 @@ void Draw_VectorElement(int type, Post_View * View, int preproNormals,
     glColor4ubv((GLubyte *) & CTX.color.mesh.tangents);
     Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
 		CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius, 
-		xc, yc, zc, t[0], t[1], t[2], NULL, View->Light);
+		xc, yc, zc, t[0], t[1], t[2], View->Light);
   }
 
   if(View->ArrowLocation == DRAW_POST_LOCATE_COG ||
@@ -1258,7 +1070,7 @@ void Draw_VectorElement(int type, Post_View * View, int preproNormals,
         Draw_Vector(View->VectorType, View->IntervalsType != DRAW_POST_ISO,
 		    View->ArrowRelHeadRadius, View->ArrowRelStemLength,
 		    View->ArrowRelStemRadius, xc, yc, zc, 
-		    fact * dx, fact * dy, fact * dz, NULL, View->Light);
+		    fact * dx, fact * dy, fact * dz, View->Light);
       }
     }
   }
@@ -1281,13 +1093,11 @@ void Draw_VectorElement(int type, Post_View * View, int preproNormals,
           Val[k][1] *= norm[k];
           Val[k][2] *= norm[k];
         }
-	for(int i = 0; i < 3; i++)
-	  Raise[i][0] = View->Raise[i] * norm[k];
         Draw_Vector(View->VectorType, View->IntervalsType != DRAW_POST_ISO,
 		    View->ArrowRelHeadRadius, View->ArrowRelStemLength,
 		    View->ArrowRelStemRadius, X[k], Y[k], Z[k], 
 		    fact * Val[k][0], fact * Val[k][1], fact * Val[k][2], 
-		    Raise, View->Light);
+		    View->Light);
       }
     }
   }
@@ -1299,42 +1109,42 @@ void Draw_VectorElement(int type, Post_View * View, int preproNormals,
 
 void Draw_VectorPoint(ARGS)
 {
-  Draw_VectorElement(POINT, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
+  Draw_VectorElement(POST_POINT, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
 }
 
 void Draw_VectorLine(ARGS)
 {
-  Draw_VectorElement(LINE, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
+  Draw_VectorElement(POST_LINE, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
 }
 
 void Draw_VectorTriangle(ARGS)
 {
-  Draw_VectorElement(TRIANGLE, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
+  Draw_VectorElement(POST_TRIANGLE, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
 }
 
 void Draw_VectorTetrahedron(ARGS)
 {
-  Draw_VectorElement(TETRAHEDRON, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
+  Draw_VectorElement(POST_TETRAHEDRON, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
 }
 
 void Draw_VectorQuadrangle(ARGS)
 {
-  Draw_VectorElement(QUADRANGLE, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
+  Draw_VectorElement(POST_QUADRANGLE, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
 }
 
 void Draw_VectorHexahedron(ARGS)
 {
-  Draw_VectorElement(HEXAHEDRON, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
+  Draw_VectorElement(POST_HEXAHEDRON, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
 }
 
 void Draw_VectorPrism(ARGS)
 {
-  Draw_VectorElement(PRISM, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
+  Draw_VectorElement(POST_PRISM, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
 }
 
 void Draw_VectorPyramid(ARGS)
 {
-  Draw_VectorElement(PYRAMID, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
+  Draw_VectorElement(POST_PYRAMID, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
 }
 
 #undef ARGS
@@ -1348,14 +1158,14 @@ void Draw_TensorElement(int type, Post_View * View, int preproNormals,
   int nbnod = 0;
 
   switch (type) {
-  case POINT: nbnod = 1; break;
-  case LINE: nbnod = 2; break;
-  case TRIANGLE: nbnod = 3; break;
-  case QUADRANGLE: nbnod = 4; break;
-  case TETRAHEDRON: nbnod = 4; break;
-  case HEXAHEDRON: nbnod = 8; break;
-  case PRISM: nbnod = 6; break;
-  case PYRAMID: nbnod = 5; break;
+  case POST_POINT: nbnod = 1; break;
+  case POST_LINE: nbnod = 2; break;
+  case POST_TRIANGLE: nbnod = 3; break;
+  case POST_QUADRANGLE: nbnod = 4; break;
+  case POST_TETRAHEDRON: nbnod = 4; break;
+  case POST_HEXAHEDRON: nbnod = 8; break;
+  case POST_PRISM: nbnod = 6; break;
+  case POST_PYRAMID: nbnod = 5; break;
   }
 
   /// By lack of any current better solution, tensors are displayed as
@@ -1382,42 +1192,42 @@ void Draw_TensorElement(int type, Post_View * View, int preproNormals,
 
 void Draw_TensorPoint(ARGS)
 {
-  Draw_TensorElement(POINT, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
+  Draw_TensorElement(POST_POINT, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
 }
 
 void Draw_TensorLine(ARGS)
 {
-  Draw_TensorElement(LINE, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
+  Draw_TensorElement(POST_LINE, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
 }
 
 void Draw_TensorTriangle(ARGS)
 {
-  Draw_TensorElement(TRIANGLE, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
+  Draw_TensorElement(POST_TRIANGLE, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
 }
 
 void Draw_TensorTetrahedron(ARGS)
 {
-  Draw_TensorElement(TETRAHEDRON, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
+  Draw_TensorElement(POST_TETRAHEDRON, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
 }
 
 void Draw_TensorQuadrangle(ARGS)
 {
-  Draw_TensorElement(QUADRANGLE, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
+  Draw_TensorElement(POST_QUADRANGLE, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
 }
 
 void Draw_TensorHexahedron(ARGS)
 {
-  Draw_TensorElement(HEXAHEDRON, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
+  Draw_TensorElement(POST_HEXAHEDRON, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
 }
 
 void Draw_TensorPrism(ARGS)
 {
-  Draw_TensorElement(PRISM, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
+  Draw_TensorElement(POST_PRISM, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
 }
 
 void Draw_TensorPyramid(ARGS)
 {
-  Draw_TensorElement(PYRAMID, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
+  Draw_TensorElement(POST_PYRAMID, View, preproNormals, ValMin, ValMax, X, Y, Z, V);
 }
 
 #undef ARGS
diff --git a/Plugin/Extract.cpp b/Plugin/Extract.cpp
index b7e25a8704..2f74dad5ba 100644
--- a/Plugin/Extract.cpp
+++ b/Plugin/Extract.cpp
@@ -1,4 +1,4 @@
-// $Id: Extract.cpp,v 1.15 2004-12-06 04:59:09 geuzaine Exp $
+// $Id: Extract.cpp,v 1.16 2004-12-07 04:52:27 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -134,18 +134,18 @@ static void extract(char *expr[3], List_T *inList, int inNb,
   // otherwise, we only allow to extract single components
 
 #if defined(HAVE_MATH_EVAL)
-  void *f[3];
+  void *f[3] = { NULL, NULL, NULL };
   for(int i = 0; i < outNbComp; i++){
     f[i] = evaluator_create(expr[i]);
     if(!f[i]){
       Msg(GERROR, "Invalid expression '%s'", expr[i]);
       for(int j = 0; j < i; j++)
-	evaluator_destroy(f[j]);
+	if(f[j]) evaluator_destroy(f[j]);
       return;
     }
   }
 #else
-  int comp[3];
+  int comp[3] = { 0, 0, 0 };
   for(int i = 0; i < outNbComp; i++){
     if     (!strcmp(expr[i], "v0")) comp[i] = 0;
     else if(!strcmp(expr[i], "v1")) comp[i] = 1;
diff --git a/Plugin/Lambda2.cpp b/Plugin/Lambda2.cpp
index 056c602634..b968faad0f 100644
--- a/Plugin/Lambda2.cpp
+++ b/Plugin/Lambda2.cpp
@@ -1,4 +1,4 @@
-// $Id: Lambda2.cpp,v 1.2 2004-11-26 16:16:39 geuzaine Exp $
+// $Id: Lambda2.cpp,v 1.3 2004-12-07 04:52:27 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -116,9 +116,6 @@ static void eigen(List_T *inList, int inNb,
     
     for(int j = 0; j < nbTime; j++){
       
-      double *x = (double *)List_Pointer_Fast(inList, i);
-      double *y = (double *)List_Pointer_Fast(inList, i + nbNod);
-      double *z = (double *)List_Pointer_Fast(inList, i + 2 * nbNod);
       double *v = (double *)List_Pointer_Fast(inList, i + 3 * nbNod + 
 					      nbNod * nbComp * j + nbComp * 0);
       double GradVel[3][3];
diff --git a/Plugin/StructuralSolver.cpp b/Plugin/StructuralSolver.cpp
index 9758d71f2b..ff415b0331 100644
--- a/Plugin/StructuralSolver.cpp
+++ b/Plugin/StructuralSolver.cpp
@@ -945,7 +945,7 @@ bool StructuralSolver :: GL_enhancePoint ( Vertex *v)
 		  Draw_Vector (CTX.vector_type,  0, CTX.arrow_rel_head_radius, 
 			       CTX.arrow_rel_stem_length, 0.5*CTX.arrow_rel_stem_radius,
 			       v->Pos.X-dv[0]*kk, v->Pos.Y-dv[1]*kk, v->Pos.Z-dv[2]*kk,
-			       dv[0]*kk, dv[1]*kk, dv[2]*kk, NULL, CTX.geom.light);
+			       dv[0]*kk, dv[1]*kk, dv[2]*kk, CTX.geom.light);
 		  sprintf(Num, "%g kN", l);
 		  glRasterPos3d((v->Pos.X + dv[0])+ offset / CTX.s[0],
 				(v->Pos.Y + dv[1])+ offset / CTX.s[1],
diff --git a/doc/FAQ b/doc/FAQ
index 5369b34200..e2e731e044 100644
--- a/doc/FAQ
+++ b/doc/FAQ
@@ -1,4 +1,4 @@
-$Id: FAQ,v 1.45 2004-10-27 20:53:04 geuzaine Exp $
+$Id: FAQ,v 1.46 2004-12-07 04:52:27 geuzaine Exp $
 
 This is the Gmsh FAQ
 
@@ -263,6 +263,10 @@ is too small (or too large), you can scale it with the 'Displacement
 factor' option. (Remember that you can drag the mouse in all numeric
 input fields to slide the value!)
 
+Another option is to use the "general raise expressions" (in
+View->Options->Offset) on a scalar view, with the displacement map
+selected as the raise data source.
+
 * 7.4 Can I visualize a field on a deformed mesh?
 
 Yes, there are several ways to do that. 
@@ -277,7 +281,11 @@ point to the second view. (You might want to make the second view
 invisible, too. If you want to amplify or decrease the amount of
 deformation, just modify the 'Displacement factor' option.)
 
-Another solution is to use the DiplacementRaise plugin.
+Another solution is to use the "general raise expressions" (in
+View->Options->Offset) on the field you want to display, with the
+displacement map selected as the raise data source.
+
+And yet another solution is to use the DiplacementRaise plugin.
 
 * 7.5 Can I color the arrows representing a vector field with data
 from a scalar field?
diff --git a/doc/VERSIONS b/doc/VERSIONS
index c286535c08..42b1752bf4 100644
--- a/doc/VERSIONS
+++ b/doc/VERSIONS
@@ -1,4 +1,4 @@
-$Id: VERSIONS,v 1.270 2004-12-06 07:05:38 geuzaine Exp $
+$Id: VERSIONS,v 1.271 2004-12-07 04:52:27 geuzaine Exp $
 
 New in 1.57: generalized displacement maps to display arbitrary view
 types; the arrows representing a vector field can now also be colored
@@ -10,8 +10,9 @@ solver plugin popups; enhanced interactive plugin behaviour; new
 plugins (HarmonicToTime and Integrate); tetrahedral mesh file reading
 speedup (50% faster on large meshes); large memory footprint reduction
 (up to 50%) for the visualization of triangular/tetrahadral meshes;
-the solver interface now supports TCP/IP connections; various small
-bug fixes and enhancements;
+the solver interface now supports TCP/IP connections; new generalized
+raise mode (allows to use complex expressions to offset
+post-processing maps); various small bug fixes and enhancements;
 
 New in 1.56: new post-processing option to draw a scalar view raised
 by a displacement view without using Plugin(DisplacementRaise) (makes
diff --git a/doc/texinfo/opt_solver.texi b/doc/texinfo/opt_solver.texi
index 3444da6c3f..a28b13e224 100644
--- a/doc/texinfo/opt_solver.texi
+++ b/doc/texinfo/opt_solver.texi
@@ -1,6 +1,6 @@
 @ftable @code
 @item Solver.SocketName
-Name of socket (TCP/IP socket if it contains `:', UNIX socket otherwise)@*
+Name of socket (TCP/IP if it contains the `:' character, UNIX otherwise)@*
 Default value: @code{".gmshsock"}@*
 Saved in: @code{General.OptionsFileName}
 
diff --git a/doc/texinfo/opt_view.texi b/doc/texinfo/opt_view.texi
index 01bad3bdde..1cbdca3134 100644
--- a/doc/texinfo/opt_view.texi
+++ b/doc/texinfo/opt_view.texi
@@ -19,6 +19,21 @@ Number format (in standard C form)@*
 Default value: @code{"%.3e"}@*
 Saved in: @code{General.OptionsFileName}
 
+@item View.GeneralizedRaiseX
+Generalized elevation of the view along X-axis (in model coordinates)@*
+Default value: @code{""}@*
+Saved in: @code{General.OptionsFileName}
+
+@item View.GeneralizedRaiseY
+Generalized elevation of the view along Y-axis (in model coordinates)@*
+Default value: @code{""}@*
+Saved in: @code{General.OptionsFileName}
+
+@item View.GeneralizedRaiseZ
+Generalized elevation of the view along Z-axis (in model coordinates)@*
+Default value: @code{"v0"}@*
+Saved in: @code{General.OptionsFileName}
+
 @item View.Name
 Default post-processing view name@*
 Default value: @code{""}@*
@@ -159,6 +174,16 @@ Index of the view used to color vector fields (-1=self)@*
 Default value: @code{-1}@*
 Saved in: @code{General.OptionsFileName}
 
+@item View.GeneralizedRaiseFactor
+Generalized raise amplification factor@*
+Default value: @code{1}@*
+Saved in: @code{General.OptionsFileName}
+
+@item View.GeneralizedRaiseView
+Index of the view used for generalized raise (-1=self)@*
+Default value: @code{-1}@*
+Saved in: @code{General.OptionsFileName}
+
 @item View.Grid
 Grid mode for 2D graphs (0=none, 1=simple, 2=frame, 3=grid)@*
 Default value: @code{2}@*
@@ -329,6 +354,11 @@ Type of graph (1=3D, 2=2D-space, 3=2D-time)@*
 Default value: @code{1}@*
 Saved in: @code{-}
 
+@item View.UseGeneralizedRaise
+Use generalized raise?@*
+Default value: @code{0}@*
+Saved in: @code{General.OptionsFileName}
+
 @item View.VectorType
 Vector display type (1=segment, 2=arrow, 3=pyramid, 4=3D arrow, 5=displacement)@*
 Default value: @code{4}@*
-- 
GitLab