From d9d25071f081e800e1b5be1d1e379c79c22a836f Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Tue, 26 Oct 2004 00:43:23 +0000
Subject: [PATCH] added small option to color the arrows representing a vector
 field according to the data from another view

---
 Common/DefaultOptions.h  |   4 +-
 Common/Options.cpp       |  16 ++++--
 Common/Options.h         |   2 +-
 Common/Views.cpp         |   4 +-
 Common/Views.h           |   8 +--
 Fltk/Callbacks.cpp       |  13 +++--
 Fltk/GUI.cpp             |  32 +++++++----
 Fltk/GUI.h               |   1 +
 Graphics/Post.cpp        |  18 +++---
 Graphics/PostElement.cpp | 116 +++++++++++++++++++++------------------
 Graphics/Scale.cpp       |   8 +--
 TODO                     |   8 +--
 doc/FAQ                  |  26 ++++++---
 doc/VERSIONS             |   8 ++-
 14 files changed, 151 insertions(+), 113 deletions(-)

diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index 05951d252b..df213ebd07 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -1020,6 +1020,8 @@ StringXNumber ViewOptions_Number[] = {
 
   { F|O, "Explode" , opt_view_explode , 1. , 
     "Explode elements (0: reduced to point; 1: not transformed)" },
+  { F|O, "ExternalView" , opt_view_external_view , -1. ,
+    "Index of the view raised by a vector field or used to color a vector field (-1=self)" },
 
   { F|O, "Grid" , opt_view_grid , 2 ,
     "Grid mode for 2D graphs (0=none, 1=simple, 2=frame, 3=grid)" },
@@ -1067,8 +1069,6 @@ StringXNumber ViewOptions_Number[] = {
   { F|O, "PositionY" , opt_view_position1 , 50. , 
     "Vertical position (in pixels) of the upper left corner of the scale or 2D graph" }, 
 
-  { F|O, "RaisedView" , opt_view_raised_view , 0. ,
-    "Index of the view raised by the displacement field" },
   { F,   "RaiseX" , opt_view_raise0 , 0. , 
     "Elevation of the view along X-axis (in model coordinates)" },
   { F,   "RaiseY" , opt_view_raise1 , 0. , 
diff --git a/Common/Options.cpp b/Common/Options.cpp
index f6c3d3ee31..b79101415d 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -1,4 +1,4 @@
-// $Id: Options.cpp,v 1.194 2004-10-25 19:19:29 geuzaine Exp $
+// $Id: Options.cpp,v 1.195 2004-10-26 00:43:21 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -5278,18 +5278,22 @@ double opt_view_alpha_channel(OPT_ARGS_NUM)
   return v->AlphaChannel;
 }
 
-double opt_view_raised_view(OPT_ARGS_NUM)
+double opt_view_external_view(OPT_ARGS_NUM)
 {
   GET_VIEW(0.);
   if(action & GMSH_SET) {
-    v->RaisedView = (int)val;
+    v->ExternalViewIndex = (int)val;
     v->Changed = 1;
   }
 #if defined(HAVE_FLTK)
-  if(_gui_action_valid(action, num))
-    WID->view_value[64]->value(v->RaisedView);
+  if(_gui_action_valid(action, num)){
+    if(v->ExternalViewIndex <= -2 ||
+       v->ExternalViewIndex >= WID->view_choice[10]->size()-1)
+      WID->view_choice[10]->value(0);
+    WID->view_choice[10]->value(v->ExternalViewIndex+1);
+  }
 #endif
-  return v->RaisedView;
+  return v->ExternalViewIndex;
 }
 
 double opt_print_format(OPT_ARGS_NUM)
diff --git a/Common/Options.h b/Common/Options.h
index a3171417f5..63bf21b7c3 100644
--- a/Common/Options.h
+++ b/Common/Options.h
@@ -474,7 +474,7 @@ double opt_view_intervals_type(OPT_ARGS_NUM);
 double opt_view_saturate_values(OPT_ARGS_NUM);
 double opt_view_global_zoom(OPT_ARGS_NUM);
 double opt_view_alpha_channel(OPT_ARGS_NUM);
-double opt_view_raised_view(OPT_ARGS_NUM);
+double opt_view_external_view(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 5cc2a666fc..e8602a8fdb 100644
--- a/Common/Views.cpp
+++ b/Common/Views.cpp
@@ -1,4 +1,4 @@
-// $Id: Views.cpp,v 1.142 2004-10-25 19:19:29 geuzaine Exp $
+// $Id: Views.cpp,v 1.143 2004-10-26 00:43:22 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -663,7 +663,7 @@ void CopyViewOptions(Post_View * src, Post_View * dest)
   dest->PointType = src->PointType;
   dest->LineType = src->LineType;
   dest->Grid = src->Grid;
-  dest->RaisedView = src->RaisedView;
+  dest->ExternalViewIndex = src->ExternalViewIndex;
   ColorTable_Copy(&src->CT);
   ColorTable_Paste(&dest->CT);
 }
diff --git a/Common/Views.h b/Common/Views.h
index da1021ae19..5f85da4c41 100644
--- a/Common/Views.h
+++ b/Common/Views.h
@@ -165,14 +165,14 @@ class Post_View{
   int Boundary, Grid, PointType, LineType;
   double PointSize, LineWidth;
   GmshColorTable CT;
-  int RaisedView;
+  int ExternalViewIndex;
 
   // dynamic
   double (*GVFI) (double min, double max, int nb, int index);
   int (*GIFV) (double min, double max, int nb, double value);
-  int ElementForDisplacement;
-  Post_View *ViewForDisplacement;
-  double MinForDisplacement, MaxForDisplacement;
+  int ExternalElementIndex;
+  Post_View *ExternalView;
+  double ExternalMin, ExternalMax;
 
   // smooth the view
   void smooth();
diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp
index 8f758b8ece..50ef603687 100644
--- a/Fltk/Callbacks.cpp
+++ b/Fltk/Callbacks.cpp
@@ -1,4 +1,4 @@
-// $Id: Callbacks.cpp,v 1.289 2004-10-25 19:19:30 geuzaine Exp $
+// $Id: Callbacks.cpp,v 1.290 2004-10-26 00:43:22 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -181,6 +181,7 @@ void UpdateViewsInGUI()
       WID->set_context(menu_post, 0);
     WID->reset_option_browser();
     WID->reset_clip_browser();
+    WID->reset_external_view_list();
   }
 }
 
@@ -3470,7 +3471,7 @@ 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 raised_view = opt_view_raised_view(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);
@@ -3609,6 +3610,10 @@ void view_options_ok_cb(CALLBACK_ARGS)
       if(force || (val != boundary))
         opt_view_boundary(i, GMSH_SET, val);
 
+      val = WID->view_choice[10]->value()-1;
+      if(force || (val != external_view))
+        opt_view_external_view(i, GMSH_SET, val);
+
       // view_butts
 
       val = WID->view_butt[0]->value();
@@ -3754,10 +3759,6 @@ void view_options_ok_cb(CALLBACK_ARGS)
       if(force || (val != displacement_factor))
         opt_view_displacement_factor(i, GMSH_SET, val);
 
-      val = WID->view_value[64]->value();
-      if(force || (val != raised_view))
-        opt_view_raised_view(i, GMSH_SET, val);
-
       val = WID->view_value[61]->value();
       if(force || (val != point_size))
         opt_view_point_size(i, GMSH_SET, val);
diff --git a/Fltk/GUI.cpp b/Fltk/GUI.cpp
index 41d47c5271..2e51417823 100644
--- a/Fltk/GUI.cpp
+++ b/Fltk/GUI.cpp
@@ -1,4 +1,4 @@
-// $Id: GUI.cpp,v 1.368 2004-10-25 19:19:30 geuzaine Exp $
+// $Id: GUI.cpp,v 1.369 2004-10-26 00:43:22 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -1429,16 +1429,15 @@ void GUI::create_view_options_window(int num)
 
 void GUI::reset_option_browser()
 {
-  int i, select;
   char str[128];
-  select = opt_browser->value();
+  int select = opt_browser->value();
   opt_browser->clear();
   opt_browser->add("General");
   opt_browser->add("Geometry");
   opt_browser->add("Mesh");
   opt_browser->add("Solver");
   opt_browser->add("Post-processing");
-  for(i = 0; i < List_Nbr(CTX.post.list); i++) {
+  for(int i = 0; i < List_Nbr(CTX.post.list); i++) {
     sprintf(str, "View [%d]", i);
     opt_browser->add(str);
   }
@@ -1446,6 +1445,22 @@ void GUI::reset_option_browser()
     opt_browser->value(select);
 }
 
+void GUI::reset_external_view_list()
+{
+  char str[32];
+  int select = view_choice[10]->value();
+  view_choice[10]->clear();
+  view_choice[10]->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);
+  }
+  if(select <= view_choice[10]->size())
+    view_choice[10]->value(select);
+  else
+    view_choice[10]->value(0);
+}
+
 void GUI::check_rotation_center_button()
 {
   if(gen_butt[15]->value()) {
@@ -2638,11 +2653,8 @@ void GUI::create_option_window()
         view_value[63]->step(0.01);
         view_value[63]->align(FL_ALIGN_RIGHT);
 
-        view_value[64] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 9 * BH, IW, BH, "Raised view number");
-        view_value[64]->minimum(0);
-        view_value[64]->maximum(10);
-        view_value[64]->step(1);
-        view_value[64]->align(FL_ALIGN_RIGHT);
+        view_choice[10] = new Fl_Choice(L + 2 * WB, 2 * WB + 9 * BH, IW, BH, "External data source");
+        view_choice[10]->align(FL_ALIGN_RIGHT);
 
         static Fl_Menu_Item menu_vecloc[] = {
           {"Cell centered", 0, 0, 0},
@@ -2856,7 +2868,7 @@ void GUI::update_view_window(int num)
   view_value[63]->step(val3/100.);
   view_value[63]->maximum(val3);
 
-  opt_view_raised_view(num, GMSH_GUI, 0);
+  opt_view_external_view(num, GMSH_GUI, 0);
   opt_view_arrow_location(num, GMSH_GUI, 0);
   //opt_view_tensor_type(num, GMSH_GUI, 0);
   view_push_butt[0]->callback(view_arrow_param_cb, (void*)num);
diff --git a/Fltk/GUI.h b/Fltk/GUI.h
index 6af3b83c33..954c1e4c42 100644
--- a/Fltk/GUI.h
+++ b/Fltk/GUI.h
@@ -296,6 +296,7 @@ public:
   void reset_visibility();
   void reset_option_browser();
   void reset_clip_browser();
+  void reset_external_view_list();
   int  selection, try_selection, quit_selection, end_selection, undo_selection;
 
 };
diff --git a/Graphics/Post.cpp b/Graphics/Post.cpp
index 09b9a23bae..12f450ba14 100644
--- a/Graphics/Post.cpp
+++ b/Graphics/Post.cpp
@@ -1,4 +1,4 @@
-// $Id: Post.cpp,v 1.80 2004-10-21 17:02:26 geuzaine Exp $
+// $Id: Post.cpp,v 1.81 2004-10-26 00:43:23 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -242,12 +242,12 @@ void Draw_List(Post_View * v, double ValMin, double ValMax,
   if(nbelm) {
     nb = List_Nbr(list) / nbelm;
 
-    v->ViewForDisplacement = 
-      (Post_View*)List_Pointer_Test(CTX.post.list, v->RaisedView);
+    v->ExternalView = 
+      (Post_View*)List_Pointer_Test(CTX.post.list, v->ExternalViewIndex);
 
     if(v->Light && v->SmoothNormals && v->Changed) {
       Msg(DEBUG, "Preprocessing of normals in View[%d]", v->Index);
-      v->ElementForDisplacement = 0;
+      v->ExternalElementIndex = 0;
       for(i = 0; i < List_Nbr(list); i += nb) {
         Get_Coords(v->Explode, v->Offset, nbnod,
                    (double *)List_Pointer_Fast(list, i),
@@ -255,11 +255,11 @@ void Draw_List(Post_View * v, double ValMin, double ValMax,
                    (double *)List_Pointer_Fast(list, i + 2 * nbnod), X, Y, Z);
         draw(v, 1, ValMin, ValMax, X, Y, Z,
              (double *)List_Pointer_Fast(list, i + 3 * nbnod));
-	v->ElementForDisplacement++;
+	v->ExternalElementIndex++;
       }
     }
 
-    v->ElementForDisplacement = 0;
+    v->ExternalElementIndex = 0;
     for(i = 0; i < List_Nbr(list); i += nb) {
       Get_Coords(v->Explode, v->Offset, nbnod,
                  (double *)List_Pointer_Fast(list, i),
@@ -267,7 +267,7 @@ void Draw_List(Post_View * v, double ValMin, double ValMax,
                  (double *)List_Pointer_Fast(list, i + 2 * nbnod), X, Y, Z);
       draw(v, 0, ValMin, ValMax, X, Y, Z,
            (double *)List_Pointer_Fast(list, i + 3 * nbnod));
-      v->ElementForDisplacement++;
+      v->ExternalElementIndex++;
     }
   }
 }
@@ -378,8 +378,8 @@ void Draw_Post(void)
 	}
 	break;
       }
-      v->MinForDisplacement = ValMin;
-      v->MaxForDisplacement = ValMax;
+      v->ExternalMin = ValMin;
+      v->ExternalMax = ValMax;
       
       switch (v->ScaleType) {
       case DRAW_POST_LINEAR:
diff --git a/Graphics/PostElement.cpp b/Graphics/PostElement.cpp
index 98879ec125..ea48743cca 100644
--- a/Graphics/PostElement.cpp
+++ b/Graphics/PostElement.cpp
@@ -1,4 +1,4 @@
-// $Id: PostElement.cpp,v 1.48 2004-10-25 19:19:30 geuzaine Exp $
+// $Id: PostElement.cpp,v 1.49 2004-10-26 00:43:23 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -898,12 +898,12 @@ int GetDataFromOtherView(int type, int nbnod, Post_View *v, int *nbcomp,
 {
   static int error1 = -1;
   static int error2 = -1;
-  Post_View *v2 = v->ViewForDisplacement;
-  int num = v->ElementForDisplacement;
+  Post_View *v2 = v->ExternalView;
+  int num = v->ExternalElementIndex;
 
   if(!v2){
     if(error1 != v->Num){
-      Msg(GERROR, "Non-existent view for displacement plot");
+      Msg(GERROR, "Nonexistent external view");
       error1 = v->Num;
     }
     return 0;
@@ -956,7 +956,7 @@ int GetDataFromOtherView(int type, int nbnod, Post_View *v, int *nbcomp,
 
   if(!nbelm || num < 0 || v2->NbTimeStep != v->NbTimeStep){
     if(error2 != v->Num){
-      Msg(GERROR, "Incompatible view for displacement plot");
+      Msg(GERROR, "Incompatible external view");
       error2 = v->Num;
     }
     return 0;
@@ -980,21 +980,21 @@ int GetDataFromOtherView(int type, int nbnod, Post_View *v, int *nbcomp,
   
   switch (v->RangeType) {
   case DRAW_POST_RANGE_DEFAULT:
-    v->MinForDisplacement = v2->Min;
-    v->MaxForDisplacement = v2->Max;
+    v->ExternalMin = v2->Min;
+    v->ExternalMax = v2->Max;
     break;
   case DRAW_POST_RANGE_CUSTOM: // yes, take the values from v!
-    v->MinForDisplacement = v->CustomMin;
-    v->MaxForDisplacement = v->CustomMax;
+    v->ExternalMin = v->CustomMin;
+    v->ExternalMax = v->CustomMax;
     break;
   case DRAW_POST_RANGE_PER_STEP:
     if(v->TimeStepMin && v->TimeStepMax){
-      v->MinForDisplacement = v2->TimeStepMin[v->TimeStep];
-      v->MaxForDisplacement = v2->TimeStepMax[v->TimeStep];
+      v->ExternalMin = v2->TimeStepMin[v->TimeStep];
+      v->ExternalMax = v2->TimeStepMax[v->TimeStep];
     }
     else{
-      v->MinForDisplacement = v2->Min;
-      v->MaxForDisplacement = v2->Max;
+      v->ExternalMin = v2->Min;
+      v->ExternalMax = v2->Max;
     }
     break;
   }
@@ -1018,11 +1018,6 @@ void Draw_VectorElement(int type, Post_View * View, int preproNormals,
                         double *X, double *Y, double *Z, double *V)
 {
   int nbnod = 0;
-  double fact, xx[8], yy[8], zz[8], xc = 0., yc = 0., zc = 0.;
-  double Val[8][3], norm[8];
-  double dx = 0., dy = 0., dz = 0., dd;
-  char Num[100];
-
   switch (type) {
   case POINT: nbnod = 1; break;
   case LINE: nbnod = 2; break;
@@ -1034,6 +1029,7 @@ void Draw_VectorElement(int type, Post_View * View, int preproNormals,
   case PYRAMID: nbnod = 5; break;
   }
 
+  double Val[8][3], norm[8];
   for(int k = 0; k < nbnod; k++) {
     Val[k][0] = V[3 * nbnod * View->TimeStep + 3 * k];
     Val[k][1] = V[3 * nbnod * View->TimeStep + 3 * k + 1];
@@ -1041,12 +1037,16 @@ void Draw_VectorElement(int type, Post_View * View, int preproNormals,
     norm[k] = sqrt(Val[k][0] * Val[k][0] + Val[k][1] * Val[k][1] + Val[k][2] * Val[k][2]);
   }
 
-  double *ext_vals = NULL;
-  int nbcomp = 1, ext_vectype = 0;
-  if(View->VectorType == DRAW_POST_DISPLACEMENT_EXTERNAL){
-    GetDataFromOtherView(type, nbnod, View, &nbcomp, norm, &ext_vals, &ext_vectype);
-    ValMin = View->MinForDisplacement;
-    ValMax = View->MaxForDisplacement;
+  int ext_nbcomp = 3, ext_vectype = DRAW_POST_ARROW3D;
+  double *ext_vals = &V[3 * nbnod * View->TimeStep];
+  double ext_min = ValMin, ext_max = ValMax, ext_norm[8];
+  for(int k = 0; k < nbnod; k++)
+    ext_norm[k] = norm[k];
+  
+  if(View->ExternalViewIndex >= 0){
+    GetDataFromOtherView(type, nbnod, View, &ext_nbcomp, ext_norm, &ext_vals, &ext_vectype);
+    ext_min = View->ExternalMin;
+    ext_max = View->ExternalMax;
   }
 
   double Raise[3][8];
@@ -1056,8 +1056,12 @@ void Draw_VectorElement(int type, Post_View * View, int preproNormals,
 
   if(View->VectorType == DRAW_POST_DISPLACEMENT ||
      View->VectorType == DRAW_POST_DISPLACEMENT_EXTERNAL){
-    
-    fact = View->DisplacementFactor;
+
+    if(View->VectorType == DRAW_POST_DISPLACEMENT)
+      ext_nbcomp = 1;
+
+    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];
@@ -1069,11 +1073,11 @@ void Draw_VectorElement(int type, Post_View * View, int preproNormals,
     int vt = View->VectorType;
     View->VectorType = ext_vectype;
     
-    if(nbcomp == 1){
-      Draw_ScalarElement(type, View, preproNormals, ValMin, ValMax, xx, yy, zz, norm);
+    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(View->LineType) {
-	  double dx2, dy2, dz2, XX[2], YY[2], ZZ[2];
+	  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];
@@ -1085,7 +1089,7 @@ void Draw_VectorElement(int type, Post_View * View, int preproNormals,
 	    dx2 = V[3 * (ts - j - 1)];
 	    dy2 = V[3 * (ts - j - 1) + 1];
 	    dz2 = V[3 * (ts - j - 1) + 2];
-	    dd = sqrt(dx * dx + dy * dy + dz * dz);
+	    double dd = sqrt(dx * dx + dy * dy + dz * dz);
 	    // not perfect...
 	    PaletteContinuous(View, ValMin, ValMax, dd);
 	    XX[0] = X[0] + fact * dx;
@@ -1100,10 +1104,10 @@ void Draw_VectorElement(int type, Post_View * View, int preproNormals,
 	else {
 	  glBegin(GL_LINE_STRIP);
 	  for(int j = 0; j < ts + 1; j++) {
-	    dx = V[3 * (ts - j)];
-	    dy = V[3 * (ts - j) + 1];
-	    dz = V[3 * (ts - j) + 2];
-	    dd = sqrt(dx * dx + dy * dy + dz * dz);
+	    double dx = V[3 * (ts - j)];
+	    double dy = V[3 * (ts - j) + 1];
+	    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],
@@ -1113,11 +1117,11 @@ void Draw_VectorElement(int type, Post_View * View, int preproNormals,
 	}
       }
     }
-    else if(nbcomp == 3){
-      Draw_VectorElement(type, View, preproNormals, ValMin, ValMax, xx, yy, zz, ext_vals);
+    else if(ext_nbcomp == 3){
+      Draw_VectorElement(type, View, preproNormals, ext_min, ext_max, xx, yy, zz, ext_vals);
     }
-    else if(nbcomp == 9){
-      Draw_TensorElement(type, View, preproNormals, ValMin, ValMax, xx, yy, zz, ext_vals);
+    else if(ext_nbcomp == 9){
+      Draw_TensorElement(type, View, preproNormals, ext_min, ext_max, xx, yy, zz, ext_vals);
     }
 
     View->TimeStep = ts;
@@ -1133,36 +1137,44 @@ void Draw_VectorElement(int type, Post_View * View, int preproNormals,
 
   if(View->ArrowLocation == DRAW_POST_LOCATE_COG ||
      View->IntervalsType == DRAW_POST_NUMERIC) {
+    double dd = 0., ext_dd = 0., dx = 0., dy = 0., dz = 0.;
+    double xc = 0., yc = 0., zc = 0.;
     for(int k = 0; k < nbnod; k++) {
+      dd += norm[k];
+      ext_dd += ext_norm[k];
       dx += Val[k][0];
-      xc += X[k] + Raise[0][k];
       dy += Val[k][1];
-      yc += Y[k] + Raise[1][k];
       dz += Val[k][2];
+      xc += X[k] + Raise[0][k];
+      yc += Y[k] + Raise[1][k];
       zc += Z[k] + Raise[2][k];
     }
+    dd /= (double)nbnod;
+    ext_dd /= (double)nbnod;
     dx /= (double)nbnod;
-    xc /= (double)nbnod;
     dy /= (double)nbnod;
-    yc /= (double)nbnod;
     dz /= (double)nbnod;
+    xc /= (double)nbnod;
+    yc /= (double)nbnod;
     zc /= (double)nbnod;
-    dd = sqrt(dx * dx + dy * dy + dz * dz);
 
     // allow for some roundoff error due to the computation at the barycenter
-    if(dd != 0.0 && dd >= ValMin * (1. - 1.e-15) && dd <= ValMax * (1. + 1.e-15)) {
+    if(ext_dd != 0.0 && 
+       ext_dd >= ext_min * (1. - 1.e-15) && 
+       ext_dd <= ext_max * (1. + 1.e-15)) {
       if(View->IntervalsType == DRAW_POST_CONTINUOUS)
-	PaletteContinuous(View, ValMin, ValMax, dd);
+	PaletteContinuous(View, ext_min, ext_max, ext_dd);
       else
 	PaletteDiscrete(View, View->NbIso,
-			View->GIFV(ValMin, ValMax, View->NbIso, dd));
+			View->GIFV(ext_min, ext_max, View->NbIso, ext_dd));
       if(View->IntervalsType == DRAW_POST_NUMERIC) {
+	char Num[100];
         glRasterPos3d(xc, yc, zc);
-        sprintf(Num, View->Format, dd);
+        sprintf(Num, View->Format, ext_dd);
         Draw_String(Num);
       }
       else {
-        fact = CTX.pixel_equiv_x / CTX.s[0] * View->ArrowSize / 
+        double fact = CTX.pixel_equiv_x / CTX.s[0] * View->ArrowSize / 
 	  (View->ArrowSizeProportional ? ValMax : dd);
         if(View->ScaleType == DRAW_POST_LOGARITHMIC && ValMin > 0) {
           dx /= dd;
@@ -1182,13 +1194,13 @@ void Draw_VectorElement(int type, Post_View * View, int preproNormals,
   }
   else {
     for(int k = 0; k < nbnod; k++) {
-      if(norm[k] != 0.0 && norm[k] >= ValMin && norm[k] <= ValMax) {
+      if(ext_norm[k] != 0.0 && ext_norm[k] >= ext_min && ext_norm[k] <= ext_max) {
 	if(View->IntervalsType == DRAW_POST_CONTINUOUS)
-	  PaletteContinuous(View, ValMin, ValMax, norm[k]);
+	  PaletteContinuous(View, ext_min, ext_max, ext_norm[k]);
 	else
 	  PaletteDiscrete(View, View->NbIso,
-			  View->GIFV(ValMin, ValMax, View->NbIso, norm[k]));
-        fact = CTX.pixel_equiv_x / CTX.s[0] * View->ArrowSize /
+			  View->GIFV(ext_min, ext_max, View->NbIso, ext_norm[k]));
+        double fact = CTX.pixel_equiv_x / CTX.s[0] * View->ArrowSize /
 	  (View->ArrowSizeProportional ? ValMax : norm[k]);
         if(View->ScaleType == DRAW_POST_LOGARITHMIC && ValMin > 0) {
           Val[k][0] /= norm[k];
diff --git a/Graphics/Scale.cpp b/Graphics/Scale.cpp
index 3caf1b0ca0..20da8843bd 100644
--- a/Graphics/Scale.cpp
+++ b/Graphics/Scale.cpp
@@ -1,4 +1,4 @@
-// $Id: Scale.cpp,v 1.51 2004-10-11 22:52:43 geuzaine Exp $
+// $Id: Scale.cpp,v 1.52 2004-10-26 00:43:23 geuzaine Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -56,9 +56,9 @@ void draw_scale(Post_View * v,
   gl2psLineWidth(v->LineWidth * CTX.print.eps_line_width_factor);
 
   double ValMin, ValMax;
-  if(v->VectorType == DRAW_POST_DISPLACEMENT_EXTERNAL){
-    ValMin = v->MinForDisplacement;
-    ValMax = v->MaxForDisplacement;
+  if(v->ExternalViewIndex >= 0){
+    ValMin = v->ExternalMin;
+    ValMax = v->ExternalMax;
   }
   else{
     switch(v->RangeType){
diff --git a/TODO b/TODO
index 4e1d3f21c7..e3f780f8bf 100644
--- a/TODO
+++ b/TODO
@@ -1,4 +1,4 @@
-$Id: TODO,v 1.65 2004-10-25 19:31:35 geuzaine Exp $
+$Id: TODO,v 1.66 2004-10-26 00:43:21 geuzaine Exp $
 
 add an interactive way to choose the orientation of surfaces in
 surface loops and lines in line loops
@@ -20,12 +20,6 @@ Raise & offsets should modify the bounding boxes... (maybe?)
 
 ********************************************************************
 
-In the same way as we can specify 'Vector Type->Raised View', we
-should implement 'Vector Type->Colored View', so that we could draw a
-vector field colored by another view.
-
-********************************************************************
-
 Test and reintroduce the cylindrical surfaces (cylinder, cone, torus)
 
 ********************************************************************
diff --git a/doc/FAQ b/doc/FAQ
index bdac824f30..a1be513496 100644
--- a/doc/FAQ
+++ b/doc/FAQ
@@ -1,4 +1,4 @@
-$Id: FAQ,v 1.40 2004-10-23 23:53:31 geuzaine Exp $
+$Id: FAQ,v 1.41 2004-10-26 00:43:23 geuzaine Exp $
 
 This is the Gmsh FAQ
 
@@ -263,19 +263,31 @@ displacement field (a vector view that will be used to deform the
 mesh), and the second one containing the field you want to display
 (this view has to contain the same number of elements as the
 displacement view). You should then set 'Vector type' to 'Raised view'
-in the first view, as well as set the 'Raised view number' to the
-actual number of 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.)
+in the first view, as well as set 'External data source' 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.
 
-* 7.4 Is there a way to save animations?
+* 7.4 Can I color the arrows representing a vector field with data
+from a scalar field?
+
+Yes: load both the vector and the scalar fields (the two views must
+have the same number of elements) and, in the vector field options,
+set 'External data source' to the scalar view.
+
+* 7.5 Can I color iso-value surfaces with data from another scalar
+view?
+
+Yes, using the CutMap plugin.
+
+* 7.6 Is there a way to save animations?
 
 Yes. For example, have a look at tutorial/t8.geo or
 demos/anim-seq.script.
 
-* 7.5 Is there a way to visualize only certain components of
+* 7.7 Is there a way to visualize only certain components of
 vector/tensor fields?
 
 Yes: use 'View->Plugin->Extract'.
diff --git a/doc/VERSIONS b/doc/VERSIONS
index 755db4576b..9541f9f381 100644
--- a/doc/VERSIONS
+++ b/doc/VERSIONS
@@ -1,8 +1,10 @@
-$Id: VERSIONS,v 1.258 2004-10-25 19:21:00 geuzaine Exp $
+$Id: VERSIONS,v 1.259 2004-10-26 00:43:23 geuzaine Exp $
 
 New since 1.56: generalized 'raised view' for displacement maps of
-arbitrary view types; new adaptive high order visualization mode; new
-options for solvers (SocketCommand and NameCommand) and views
+arbitrary view types; the arrows representing a vector field can now
+also be colored by the values from other scalar, vector or tensor
+fields; new adaptive high order visualization mode; new options for
+solvers (SocketCommand and NameCommand) and views
 (ArrowSizeProportional);
 
 New in 1.56: new post-processing option to draw a scalar view raised
-- 
GitLab