From 60f6e815dbcc8e6c036069d52a1aa18627c57573 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Wed, 22 Feb 2006 19:39:50 +0000
Subject: [PATCH] popup a warning when there is an obvious mistake in the
 choice of the characteristic lenghts, that would lead to HUGE meshes (this is
 one of the most common causes for erroneous bug reports on the mailing list)

---
 Common/Context.h        |  5 ++--
 Common/DefaultOptions.h |  5 ++--
 Common/Message.h        |  2 ++
 Common/Options.cpp      | 20 +++++++------
 Common/Options.h        |  2 +-
 Fltk/Callbacks.cpp      |  3 +-
 Fltk/GUI.cpp            | 27 ++++++++++-------
 Fltk/Message.cpp        | 14 ++++++++-
 Mesh/Create.cpp         |  8 +++---
 Mesh/Generator.cpp      | 64 +++++++++++++++++++++++++++++------------
 10 files changed, 101 insertions(+), 49 deletions(-)

diff --git a/Common/Context.h b/Common/Context.h
index f9eaca9e0d..9cdf746596 100644
--- a/Common/Context.h
+++ b/Common/Context.h
@@ -28,7 +28,6 @@ class Context_T {
 
 public :
 
-
   // general options
   char filename[256];         // the name of the currently opened file
   char base_filename[256];    // the same without the extension
@@ -137,6 +136,8 @@ public :
 
   int enable_mouse_selection; // enable selection using the mouse
 
+  int expert_mode; // to disable some warnings for beginners
+
   // geometry options 
   struct{
     int vis_type;
@@ -145,7 +146,7 @@ public :
     double point_size, line_width, point_sel_size, line_sel_width;
     int point_type, line_type; // flat or 3D
     int light;
-    int level, old_circle, circle_points, circle_warning;
+    int level, old_circle, circle_points;
     int extrude_spline_points, old_newreg;
     double normals, tangents;
     double scaling_factor;
diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index a7d5e68d6f..06e29f3f1a 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -546,6 +546,9 @@ StringXNumber GeneralOptions_Number[] = {
   { F|O, "DrawBoundingBoxes" , opt_general_draw_bounding_box, 0. ,
     "Draw bounding boxes" },
 
+  { F|O, "ExpertMode" , opt_general_expert_mode, 0. ,
+    "Enable expert mode (to disable all the messages meant for inexperienced users)" },
+
   { F|O, "FastRedraw" , opt_general_fast_redraw, 0. ,
     "Draw simplified model while rotating, panning and zooming" },
   { F|S, "FileChooserPositionX" , opt_general_file_chooser_position0 , 200. , 
@@ -768,8 +771,6 @@ StringXNumber GeometryOptions_Number[] = {
 
   { F|O, "CirclePoints" , opt_geometry_circle_points, 20. ,
     "Number of points used to draw a circle/ellipse" },
-  { F|O, "CircleWarning" , opt_geometry_circle_warning, 1. ,
-    "Warn if circle arc is greater than Pi" },
 
   { F|O, "ExtrudeSplinePoints" , opt_geometry_extrude_spline_points, 5. ,
     "Number of control points for splines created during extrusion" },
diff --git a/Common/Message.h b/Common/Message.h
index 3b440a4c4d..d935a92983 100644
--- a/Common/Message.h
+++ b/Common/Message.h
@@ -76,5 +76,7 @@ void   Msg(int level, char *fmt, ...);
 double Cpu(void);
 void   Exit(int);
 double GetValue(char *text, double defaultval);
+bool   GetBinaryAnswer(const char *question, const char *yes, const char *no, 
+		       bool defaultval=true);
 
 #endif
diff --git a/Common/Options.cpp b/Common/Options.cpp
index d744b45c7e..0c9ae70d18 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -1,4 +1,4 @@
-// $Id: Options.cpp,v 1.273 2006-01-26 13:41:44 geuzaine Exp $
+// $Id: Options.cpp,v 1.274 2006-02-22 19:39:49 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -3167,6 +3167,17 @@ double opt_general_zoom_factor(OPT_ARGS_NUM)
   return CTX.zoom_factor;
 }
 
+double opt_general_expert_mode(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET)
+    CTX.expert_mode = (int)val;
+#if defined(HAVE_FLTK)
+  if(WID && (action & GMSH_GUI))
+    WID->gen_butt[10]->value(CTX.expert_mode);
+#endif
+  return CTX.expert_mode;
+}
+
 double opt_general_clip0(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
@@ -3947,13 +3958,6 @@ double opt_geometry_circle_points(OPT_ARGS_NUM)
   return CTX.geom.circle_points;
 }
 
-double opt_geometry_circle_warning(OPT_ARGS_NUM)
-{
-  if(action & GMSH_SET)
-    CTX.geom.circle_warning = (int)val;
-  return CTX.geom.circle_warning;
-}
-
 double opt_geometry_extrude_spline_points(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
diff --git a/Common/Options.h b/Common/Options.h
index 4b46d1bb3f..05290ef8ed 100644
--- a/Common/Options.h
+++ b/Common/Options.h
@@ -316,6 +316,7 @@ double opt_general_arrow_stem_radius(OPT_ARGS_NUM);
 double opt_general_trackball(OPT_ARGS_NUM);
 double opt_general_rotation_center_cg(OPT_ARGS_NUM);
 double opt_general_zoom_factor(OPT_ARGS_NUM);
+double opt_general_expert_mode(OPT_ARGS_NUM);
 double opt_general_clip0(OPT_ARGS_NUM);
 double opt_general_clip0a(OPT_ARGS_NUM);
 double opt_general_clip0b(OPT_ARGS_NUM);
@@ -399,7 +400,6 @@ double opt_geometry_light(OPT_ARGS_NUM);
 double opt_geometry_old_circle(OPT_ARGS_NUM);
 double opt_geometry_old_newreg(OPT_ARGS_NUM);
 double opt_geometry_circle_points(OPT_ARGS_NUM);
-double opt_geometry_circle_warning(OPT_ARGS_NUM);
 double opt_geometry_extrude_spline_points(OPT_ARGS_NUM);
 double opt_geometry_scaling_factor(OPT_ARGS_NUM);
 double opt_geometry_snap0(OPT_ARGS_NUM);
diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp
index 89477690d7..30eb7e670b 100644
--- a/Fltk/Callbacks.cpp
+++ b/Fltk/Callbacks.cpp
@@ -1,4 +1,4 @@
-// $Id: Callbacks.cpp,v 1.406 2006-02-04 03:43:30 geuzaine Exp $
+// $Id: Callbacks.cpp,v 1.407 2006-02-22 19:39:49 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -985,6 +985,7 @@ void general_options_ok_cb(CALLBACK_ARGS)
   if(sessionrc && !opt_general_session_save(0, GMSH_GET, 0))
     Print_Options(0, GMSH_SESSIONRC, 1, 1, CTX.session_filename_fullpath);
   opt_general_options_save(0, GMSH_SET, WID->gen_butt[9]->value());
+  opt_general_expert_mode(0, GMSH_SET, WID->gen_butt[10]->value());
   opt_general_tooltips(0, GMSH_SET, WID->gen_butt[13]->value());
   opt_general_confirm_overwrite(0, GMSH_SET, WID->gen_butt[14]->value());
   opt_general_rotation_center_cg(0, GMSH_SET, WID->gen_butt[15]->value());
diff --git a/Fltk/GUI.cpp b/Fltk/GUI.cpp
index e766b8c745..e11329d38a 100644
--- a/Fltk/GUI.cpp
+++ b/Fltk/GUI.cpp
@@ -1,4 +1,4 @@
-// $Id: GUI.cpp,v 1.487 2006-02-02 16:01:13 geuzaine Exp $
+// $Id: GUI.cpp,v 1.488 2006-02-22 19:39:49 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -1709,45 +1709,50 @@ void GUI::create_option_window()
     {
       Fl_Group *o = new Fl_Group(L + WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "General");
 
-      gen_butt[13] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 1 * BH, BW, BH, "Show tooltips");
+      gen_butt[10] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 1 * BH, BW, BH, "Enable expert mode");
+      gen_butt[10]->type(FL_TOGGLE_BUTTON);
+      gen_butt[10]->down_box(GMSH_TOGGLE_BOX);
+      gen_butt[10]->selection_color(GMSH_TOGGLE_COLOR);
+
+      gen_butt[13] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 2 * BH, BW, BH, "Show tooltips");
       gen_butt[13]->type(FL_TOGGLE_BUTTON);
       gen_butt[13]->down_box(GMSH_TOGGLE_BOX);
       gen_butt[13]->selection_color(GMSH_TOGGLE_COLOR);
 
-      gen_butt[6] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 2 * BH, BW, BH, "Show bounding boxes");
+      gen_butt[6] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 3 * BH, BW, BH, "Show bounding boxes");
       gen_butt[6]->tooltip("(Alt+b)");
       gen_butt[6]->type(FL_TOGGLE_BUTTON);
       gen_butt[6]->down_box(GMSH_TOGGLE_BOX);
       gen_butt[6]->selection_color(GMSH_TOGGLE_COLOR);
 
-      gen_butt[2] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 3 * BH, BW, BH, "Draw simplified model while rotating, panning and zooming");
+      gen_butt[2] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 4 * BH, BW, BH, "Draw simplified model while rotating, panning and zooming");
       gen_butt[2]->tooltip("(Alt+f)");
       gen_butt[2]->type(FL_TOGGLE_BUTTON);
       gen_butt[2]->down_box(GMSH_TOGGLE_BOX);
       gen_butt[2]->selection_color(GMSH_TOGGLE_COLOR);
 
-      gen_butt[3] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 4 * BH, BW, BH, "Enable double buffering");
+      gen_butt[3] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 5 * BH, BW, BH, "Enable double buffering");
       gen_butt[3]->type(FL_TOGGLE_BUTTON);
       gen_butt[3]->down_box(GMSH_TOGGLE_BOX);
       gen_butt[3]->selection_color(GMSH_TOGGLE_COLOR);
 
-      gen_butt[5] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 5 * BH, BW, BH, "Use trackball rotation mode instead of Euler angles");
+      gen_butt[5] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 6 * BH, BW, BH, "Use trackball rotation mode instead of Euler angles");
       gen_butt[5]->type(FL_TOGGLE_BUTTON);
       gen_butt[5]->down_box(GMSH_TOGGLE_BOX);
       gen_butt[5]->selection_color(GMSH_TOGGLE_COLOR);
 
-      gen_butt[15] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 6 * BH, BW, BH, "Rotate around pseudo center of mass");
+      gen_butt[15] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 7 * BH, BW, BH, "Rotate around pseudo center of mass");
       gen_butt[15]->type(FL_TOGGLE_BUTTON);
       gen_butt[15]->down_box(GMSH_TOGGLE_BOX);
       gen_butt[15]->selection_color(GMSH_TOGGLE_COLOR);
       gen_butt[15]->callback(activate_cb, (void*)"rotation_center");
 
-      gen_push_butt[0] = new Fl_Button(L + 2 * IW - 2 * WB, 2 * WB + 7 * BH, BB, BH, "Select");
+      gen_push_butt[0] = new Fl_Button(L + 2 * IW - 2 * WB, 2 * WB + 8 * BH, BB, BH, "Select");
       gen_push_butt[0]->callback(general_options_rotation_center_select_cb);
 
-      gen_value[8] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 7 * BH, IW / 3, BH);
-      gen_value[9] = new Fl_Value_Input(L + 2 * WB + IW / 3, 2 * WB + 7 * BH, IW / 3, BH);
-      gen_value[10] = new Fl_Value_Input(L + 2 * WB + 2 * IW / 3, 2 * WB + 7 * BH, IW / 3, BH, "Rotation center");
+      gen_value[8] = new Fl_Value_Input(L + 2 * WB, 2 * WB + 8 * BH, IW / 3, BH);
+      gen_value[9] = new Fl_Value_Input(L + 2 * WB + IW / 3, 2 * WB + 8 * BH, IW / 3, BH);
+      gen_value[10] = new Fl_Value_Input(L + 2 * WB + 2 * IW / 3, 2 * WB + 8 * BH, IW / 3, BH, "Rotation center");
       gen_value[10]->align(FL_ALIGN_RIGHT);
 
       o->end();
diff --git a/Fltk/Message.cpp b/Fltk/Message.cpp
index 1a884255f4..550757a9b9 100644
--- a/Fltk/Message.cpp
+++ b/Fltk/Message.cpp
@@ -1,4 +1,4 @@
-// $Id: Message.cpp,v 1.68 2006-01-17 20:00:41 geuzaine Exp $
+// $Id: Message.cpp,v 1.69 2006-02-22 19:39:50 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -322,3 +322,15 @@ double GetValue(char *text, double defaultval)
       return atof(str);
   }
 }
+
+bool GetBinaryAnswer(const char *question, const char *yes, const char *no, 
+		     bool defaultval)
+{
+  if(CTX.nopopup || CTX.batch || !WID)
+    return defaultval;
+
+  if(fl_choice(question, no, yes, NULL))
+    return true;
+  else
+    return false;
+}
diff --git a/Mesh/Create.cpp b/Mesh/Create.cpp
index 7b35ae9e8e..9945360339 100644
--- a/Mesh/Create.cpp
+++ b/Mesh/Create.cpp
@@ -1,4 +1,4 @@
-// $Id: Create.cpp,v 1.81 2006-01-14 16:24:54 geuzaine Exp $
+// $Id: Create.cpp,v 1.82 2006-02-22 19:39:50 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -457,12 +457,12 @@ void End_Curve(Curve * c)
     for(i = 0; i < 4; i++)
       Curve->Circle.v[i] = v[i];
 
-    if(CTX.geom.circle_warning && Curve->Num > 0 && A3-A1 >= Pi){
+    if(!CTX.expert_mode && Curve->Num > 0 && A3-A1 >= Pi){
       Msg(GERROR1, "Circle or ellipse arc %d greater than/equal to Pi (angle=%g)",
 	  Curve->Num, A3-A1);
       Msg(GERROR2, "(If you understand what this implies, you can disable this error");
-      Msg(GERROR2, "message by setting Geometry.CircleWarning to 0. Otherwise, please");
-      Msg(GERROR3, "subdivide the arc in smaller pieces)");
+      Msg(GERROR2, "message by selecting `Enable expert mode' in the option dialog.");
+      Msg(GERROR3, "Otherwise, please subdivide the arc in smaller pieces.)");
     }
 
   }
diff --git a/Mesh/Generator.cpp b/Mesh/Generator.cpp
index 4df5babb39..68309758c4 100644
--- a/Mesh/Generator.cpp
+++ b/Mesh/Generator.cpp
@@ -1,4 +1,4 @@
-// $Id: Generator.cpp,v 1.77 2006-01-29 22:53:41 geuzaine Exp $
+// $Id: Generator.cpp,v 1.78 2006-02-22 19:39:50 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -174,12 +174,19 @@ void GetStatistics(double stat[50])
 
 }
 
+static double SumOfAllLc = 0.;
+void GetSumOfAllLc(void *a, void *b)
+{
+  Vertex *v = *(Vertex **) a;
+  SumOfAllLc += v->lc;
+}
+
 void ApplyLcFactor_Point(void *a, void *b)
 {
   Vertex *v = *(Vertex **) a;
   if(v->lc <= 0.0) {
-    Msg(GERROR,
-        "Wrong characteristic length (%g <= 0) for Point %d, defaulting to 1.0",
+    Msg(GERROR, 
+	"Wrong characteristic length (%g <= 0) for Point %d, defaulting to 1.0",
         v->lc, v->Num);
     v->lc = 1.0;
   }
@@ -232,35 +239,55 @@ void Move_SimplexBaseToSimplex(Mesh * M, int dimension)
   }
 }
 
+bool TooManyElements(Mesh *M, int dim){
+  if(CTX.expert_mode) return false;
+
+  // try to detect obvious mistakes in characteristic lenghts (one of
+  // the most common cause for erroneous bug reports on the mailing
+  // list)
+  SumOfAllLc = 0.;
+  Tree_Action(M->Points, GetSumOfAllLc);
+  SumOfAllLc /= (double)Tree_Nbr(M->Points);
+  if(pow(CTX.lc / SumOfAllLc, dim) < 1.e7) return false;
+
+  return !GetBinaryAnswer("Your choice of characteristic lengths will likely produce\n"
+			  "a very large mesh. Do you really want to continue?\n\n"
+			  "(To disable this warning in the future, select `Enable\n"
+			  "expert mode' in the option dialog.)",
+			  "Continue", "Cancel");
+}
+
 void Maillage_Dimension_1(Mesh * M)
 {
-  double t1, t2;
+  if(TooManyElements(M, 1)) return;
 
-  t1 = Cpu();
+  double t1 = Cpu();
 
   Tree_Action(M->Curves, Maillage_Curve);
 
-  t2 = Cpu();
+  double t2 = Cpu();
   M->timing[0] = t2 - t1;
 }
 
 void Maillage_Dimension_2(Mesh * M)
 {
-  int i;
-  Curve *c, *neew, C;
-  double t1, t2, shortest = 1.e300;
+  if(TooManyElements(M, 2)) return;
 
-  t1 = Cpu();
+  double shortest = 1.e300;
+
+  double t1 = Cpu();
 
   // create reverse 1D meshes
 
   List_T *Curves = Tree2List(M->Curves);
-  for(i = 0; i < List_Nbr(Curves); i++) {
+  for(int i = 0; i < List_Nbr(Curves); i++) {
+    Curve *c;
     List_Read(Curves, i, &c);
     if(c->Num > 0) {
       if(c->l < shortest)
         shortest = c->l;
-      neew = &C;
+      Curve C;
+      Curve *neew = &C;
       neew->Num = -c->Num;
       Tree_Query(M->Curves, &neew);
       neew->Vertices =
@@ -281,7 +308,7 @@ void Maillage_Dimension_2(Mesh * M)
   if(CTX.mesh.algo_recombine == 2)
     Recombine_All(M);
 
-  t2 = Cpu();
+  double t2 = Cpu();
 
   M->timing[1] = t2 - t1;
 }
@@ -300,16 +327,15 @@ void TransferData(void *a, void *b)
 
 void Maillage_Dimension_3(Mesh * M)
 {
-  Volume *v;
-  double t1, t2;
-  Volume *vol;
+  if(TooManyElements(M, 3)) return;
 
-  t1 = Cpu();
+  double t1 = Cpu();
 
   // merge all the delaunay parts in a single special volume
-  v = Create_Volume(99999, 99999);
+  Volume *v = Create_Volume(99999, 99999);
   List_T *list = Tree2List(M->Volumes);
   for(int i = 0; i < List_Nbr(list); i++) {
+    Volume *vol;
     List_Read(list, i, &vol);
     if((!vol->Extrude || !vol->Extrude->mesh.ExtrudeMesh) &&
        (vol->Method != TRANSFINI)) {
@@ -339,7 +365,7 @@ void Maillage_Dimension_3(Mesh * M)
 
   List_Delete(list);
 
-  t2 = Cpu();
+  double t2 = Cpu();
 
   M->timing[2] = t2 - t1;
 }
-- 
GitLab