From 25e918084340b857ace857551cb63008249be2f4 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Sat, 18 Sep 2010 06:36:26 +0000
Subject: [PATCH] new sampling options to diplay one out of N elements
 (post-pro) or labels (mesh; this replaces the old labelsFrequency opt)

---
 Common/Context.h           |  4 +--
 Common/DefaultOptions.h    |  9 ++++---
 Common/Options.cpp         | 26 ++++++++++++++++---
 Common/Options.h           |  3 ++-
 Fltk/optionWindow.cpp      | 21 ++++++++++++---
 Graphics/drawMesh.cpp      | 16 +++---------
 Graphics/drawPost.cpp      |  2 +-
 Post/PViewData.cpp         | 52 ++++++++++++++++++++++++++------------
 Post/PViewData.h           |  4 +--
 Post/PViewDataGModel.cpp   |  5 ++--
 Post/PViewDataGModel.h     |  3 ++-
 Post/PViewOptions.h        |  1 +
 Post/PViewVertexArrays.cpp |  2 +-
 13 files changed, 100 insertions(+), 48 deletions(-)

diff --git a/Common/Context.h b/Common/Context.h
index 0e0ab24442..6999f63533 100644
--- a/Common/Context.h
+++ b/Common/Context.h
@@ -22,12 +22,12 @@ struct contextMeshOptions {
   int pointsNum, linesNum, surfacesNum, volumesNum, qualityType, labelType;
   int optimize, optimizeNetgen, optimizeLloyd, refineSteps, remove4triangles;
   double normals, tangents, explode, angleSmoothNormals, allowSwapEdgeAngle;
-  double mshFileVersion, mshFilePartitioned, labelFrequency, pointSize, lineWidth;
+  double mshFileVersion, mshFilePartitioned, pointSize, lineWidth;
   double qualityInf, qualitySup, radiusInf, radiusSup;
   double scalingFactor, lcFactor, randFactor, lcIntegrationPrecision;
   double lcMin, lcMax, toleranceEdgeLength, anisoMax, smoothRatio;
   int lcFromPoints, lcFromCurvature, lcExtendFromBoundary;
-  int dual, voronoi, drawSkinOnly, colorCarousel;
+  int dual, voronoi, drawSkinOnly, colorCarousel, labelSampling;
   int fileFormat, nbSmoothing, algo2d, algo3d, algoSubdivide;
   int order, secondOrderLinear, secondOrderIncomplete;
   int secondOrderExperimental, meshOnlyVisible;
diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index 05e96a1aed..dde2fc4b5b 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -1100,8 +1100,8 @@ StringXNumber MeshOptions_Number[] = {
   { F|O, "Hexahedra" , opt_mesh_hexahedra , 1. , 
     "Display mesh hexahedra?" },
 
-  { F|O, "LabelsFrequency" , opt_mesh_label_frequency , 100. , 
-    "Labels display frequency?" },
+  { F|O, "LabelSampling" , opt_mesh_label_sampling , 1. , 
+    "Label sampling rate (display one label every `LabelSampling' elements)" },
   { F|O, "LabelType" , opt_mesh_label_type , 0. , 
     "Type of element label (0=element number, 1=elementary entity number, "
     "2=physical entity number, 3=partition number, 4=coordinates)" },
@@ -1153,7 +1153,8 @@ StringXNumber MeshOptions_Number[] = {
     "Weight of triangle for METIS load balancing" ,},
 
   { F|O, "PartitionByExtrusion" , opt_mesh_partition_by_extrusion, 0. ,
-    "Special partitioner that annotates all all extruded elements to the same node as the source element" },
+    "Special partitioner that annotates all all extruded elements to the same "
+    "node as the source element" },
     
   { F, "NbHexahedra" , opt_mesh_nb_hexahedra , 0. , 
     "Number of hexahedra in the current mesh (read-only)" },
@@ -1560,6 +1561,8 @@ StringXNumber ViewOptions_Number[] = {
   { F|O, "RangeType" , opt_view_range_type , 1 ,
     "Value scale range type (1=default, 2=custom, 3=per time step)" },
 
+  { F|O, "Sampling" , opt_view_sampling , 1. , 
+    "Element sampling rate (draw one out every `Sampling' elements)" },
   { F|O, "SaturateValues" , opt_view_saturate_values , 0. ,
     "Saturate the view values to custom min and max (1=true, 0=false)" },
   { F|O, "ScaleType" , opt_view_scale_type , 1 ,
diff --git a/Common/Options.cpp b/Common/Options.cpp
index f7373a8978..a70eec2f55 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -5374,17 +5374,17 @@ double opt_mesh_line_width(OPT_ARGS_NUM)
   return CTX::instance()->mesh.lineWidth;
 }
 
-double opt_mesh_label_frequency(OPT_ARGS_NUM)
+double opt_mesh_label_sampling(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET) {
-    CTX::instance()->mesh.labelFrequency = val;
+    CTX::instance()->mesh.labelSampling = val;
   }
 #if defined(HAVE_FLTK)
   if(FlGui::available() && (action & GMSH_GUI))
     FlGui::instance()->options->mesh.value[12]->value
-      (CTX::instance()->mesh.labelFrequency);
+      (CTX::instance()->mesh.labelSampling);
 #endif
-  return CTX::instance()->mesh.labelFrequency;
+  return CTX::instance()->mesh.labelSampling;
 }
 
 double opt_mesh_reverse_all_normals(OPT_ARGS_NUM)
@@ -7130,6 +7130,24 @@ double opt_view_position1(OPT_ARGS_NUM)
 #endif
 }
 
+double opt_view_sampling(OPT_ARGS_NUM)
+{
+#if defined(HAVE_POST)
+  GET_VIEW(0.);
+  if(action & GMSH_SET) {
+    opt->sampling = (int)val;
+    if(view) view->setChanged(true);
+  }
+#if defined(HAVE_FLTK)
+  if(_gui_action_valid(action, num))
+    FlGui::instance()->options->view.value[6]->value(opt->sampling);
+#endif
+  return opt->sampling;
+#else
+  return 1.;
+#endif
+}
+
 double opt_view_size0(OPT_ARGS_NUM)
 {
 #if defined(HAVE_POST)
diff --git a/Common/Options.h b/Common/Options.h
index 799568de88..1ac5159857 100644
--- a/Common/Options.h
+++ b/Common/Options.h
@@ -458,7 +458,7 @@ double opt_geometry_clip(OPT_ARGS_NUM);
 double opt_geometry_copy_meshing_method(OPT_ARGS_NUM);
 double opt_geometry_exact_extrusion(OPT_ARGS_NUM);
 double opt_geometry_match_geom_and_mesh(OPT_ARGS_NUM);
-double opt_mesh_label_frequency(OPT_ARGS_NUM);
+double opt_mesh_label_sampling(OPT_ARGS_NUM);
 double opt_mesh_optimize(OPT_ARGS_NUM);
 double opt_mesh_optimize_netgen(OPT_ARGS_NUM);
 double opt_mesh_remove_4_triangles(OPT_ARGS_NUM);
@@ -674,6 +674,7 @@ double opt_view_axes_zmax(OPT_ARGS_NUM);
 double opt_view_position0(OPT_ARGS_NUM);
 double opt_view_position1(OPT_ARGS_NUM);
 double opt_view_auto_position(OPT_ARGS_NUM);
+double opt_view_sampling(OPT_ARGS_NUM);
 double opt_view_size0(OPT_ARGS_NUM);
 double opt_view_size1(OPT_ARGS_NUM);
 double opt_view_nb_iso(OPT_ARGS_NUM);
diff --git a/Fltk/optionWindow.cpp b/Fltk/optionWindow.cpp
index 18e2f006ee..54d8c022d2 100644
--- a/Fltk/optionWindow.cpp
+++ b/Fltk/optionWindow.cpp
@@ -440,7 +440,7 @@ static void mesh_options_ok_cb(Fl_Widget *w, void *data)
   opt_mesh_tangents(0, GMSH_SET, o->mesh.value[13]->value());
   opt_mesh_point_size(0, GMSH_SET, o->mesh.value[10]->value());
   opt_mesh_line_width(0, GMSH_SET, o->mesh.value[11]->value());
-  opt_mesh_label_frequency(0, GMSH_SET, o->mesh.value[12]->value());
+  opt_mesh_label_sampling(0, GMSH_SET, o->mesh.value[12]->value());
   opt_mesh_angle_smooth_normals(0, GMSH_SET, o->mesh.value[18]->value());
 
   opt_mesh_point_type(0, GMSH_SET, o->mesh.choice[0]->value());
@@ -656,6 +656,7 @@ static void view_options_ok_cb(Fl_Widget *w, void *data)
   double component_map6 = opt_view_component_map6(current, GMSH_GET, 0);
   double component_map7 = opt_view_component_map7(current, GMSH_GET, 0);
   double component_map8 = opt_view_component_map8(current, GMSH_GET, 0);
+  double sampling = opt_view_sampling(current, GMSH_GET, 0);
 
   std::string name = opt_view_name(current, GMSH_GET, "");
   std::string format = opt_view_format(current, GMSH_GET, "");
@@ -1085,6 +1086,10 @@ static void view_options_ok_cb(Fl_Widget *w, void *data)
       if(force || (val != component_map8))
         opt_view_component_map8(i, GMSH_SET, val);
 
+      val = o->view.value[6]->value();
+      if(force || (val != sampling))
+        opt_view_sampling(i, GMSH_SET, val);
+
       // view_inputs
 
       std::string str;
@@ -2156,8 +2161,8 @@ optionWindow::optionWindow(int deltaFontSize)
       mesh.choice[7]->callback(mesh_options_ok_cb);
 
       mesh.value[12] = new Fl_Value_Input
-        (L + width / 2, 2 * WB + 6 * BH, width / 4 - 2 * WB, BH, "Frequency");
-      mesh.value[12]->minimum(0);
+        (L + width / 2, 2 * WB + 6 * BH, width / 4 - 2 * WB, BH, "Sampling");
+      mesh.value[12]->minimum(1);
       mesh.value[12]->maximum(100);
       mesh.value[12]->step(1);
       mesh.value[12]->align(FL_ALIGN_RIGHT);
@@ -2777,6 +2782,15 @@ optionWindow::optionWindow(int deltaFontSize)
         (L + 2 * WB, 2 * WB + 5 * BH, IW, BH, "Elements");
       view.menu[1]->menu(menu_view_element_types);
       view.menu[1]->callback(view_options_ok_cb);
+
+      view.value[6] = new Fl_Value_Input
+        (L + width / 2, 2 * WB + 5 * BH, width / 4 - 2 * WB, BH, "Sampling");
+      view.value[6]->minimum(1);
+      view.value[6]->maximum(100);
+      view.value[6]->step(1);
+      view.value[6]->align(FL_ALIGN_RIGHT);
+      view.value[6]->when(FL_WHEN_RELEASE);
+      view.value[6]->callback(view_options_ok_cb);
       
       static Fl_Menu_Item menu_boundary[] = {
         {"None", 0, 0, 0},
@@ -3309,6 +3323,7 @@ void optionWindow::updateViewGroup(int index)
   opt_view_draw_tensors(index, GMSH_GUI, 0);
   opt_view_normals(index, GMSH_GUI, 0);
   opt_view_tangents(index, GMSH_GUI, 0);
+  opt_view_sampling(index, GMSH_GUI, 0);
 
   opt_view_nb_iso(index, GMSH_GUI, 0);
   opt_view_intervals_type(index, GMSH_GUI, 0);
diff --git a/Graphics/drawMesh.cpp b/Graphics/drawMesh.cpp
index 108836ac4d..04477181ec 100644
--- a/Graphics/drawMesh.cpp
+++ b/Graphics/drawMesh.cpp
@@ -163,16 +163,6 @@ static bool areSomeElementsCurved(std::vector<T*> &elements)
   return false;
 }
 
-static int getLabelStep(int total)
-{
-  int step;
-  if(CTX::instance()->mesh.labelFrequency == 0.0) 
-    step = total;
-  else 
-    step = (int)(100.0 / CTX::instance()->mesh.labelFrequency);
-  return (step > total) ? total : step;
-}
-
 template<class T>
 static void drawElementLabels(drawContext *ctx, GEntity *e,
                               std::vector<T*> &elements, int forceColor=0,
@@ -181,7 +171,8 @@ static void drawElementLabels(drawContext *ctx, GEntity *e,
   unsigned col = forceColor ? color : getColorByEntity(e);
   glColor4ubv((GLubyte *) & col);
 
-  int labelStep = getLabelStep(elements.size());
+  int labelStep = CTX::instance()->mesh.labelSampling;
+  if(labelStep <= 0) labelStep = 1;
 
   for(unsigned int i = 0; i < elements.size(); i++){
     MElement *ele = elements[i];
@@ -301,7 +292,8 @@ static void drawVerticesPerEntity(drawContext *ctx, GEntity *e)
     }
   }
   if(CTX::instance()->mesh.pointsNum) {
-    int labelStep = getLabelStep(e->mesh_vertices.size());
+    int labelStep = CTX::instance()->mesh.labelSampling;
+    if(labelStep <= 0) labelStep = 1;
     for(unsigned int i = 0; i < e->mesh_vertices.size(); i++)
       if(i % labelStep == 0) drawVertexLabel(ctx, e, e->mesh_vertices[i]);
   }
diff --git a/Graphics/drawPost.cpp b/Graphics/drawPost.cpp
index 201ba341b4..b2196e549a 100644
--- a/Graphics/drawPost.cpp
+++ b/Graphics/drawPost.cpp
@@ -249,7 +249,7 @@ static void drawGlyphs(drawContext *ctx, PView *p)
   for(int ent = 0; ent < data->getNumEntities(opt->timeStep); ent++){
     if(data->skipEntity(opt->timeStep, ent)) continue;
     for(int i = 0; i < data->getNumElements(opt->timeStep, ent); i++){
-      if(data->skipElement(opt->timeStep, ent, i, true)) continue;
+      if(data->skipElement(opt->timeStep, ent, i, true, opt->sampling)) continue;
       int type = data->getType(opt->timeStep, ent, i);
       if(opt->skipElement(type)) continue;
       int dim = data->getDimension(opt->timeStep, ent, i);
diff --git a/Post/PViewData.cpp b/Post/PViewData.cpp
index 2586929079..6d095d4ff4 100644
--- a/Post/PViewData.cpp
+++ b/Post/PViewData.cpp
@@ -48,6 +48,13 @@ bool PViewData::empty()
   return (!getNumElements() && !getNumStrings2D() && !getNumStrings3D());
 }
 
+bool PViewData::skipElement(int step, int ent, int ele, bool checkVisibility,
+                            int samplingRate)
+{
+  if(samplingRate <= 1) return false;
+  return ele % samplingRate;
+}
+
 void PViewData::getScalarValue(int step, int ent, int ele, int nod, double &val)
 {
   int numComp = getNumComponents(step, ent, ele);
@@ -133,35 +140,44 @@ double PViewData::getValueBinding(int step, int ent, int ele, int nod, int comp)
   return val;
 }
 
-void PViewData::getAllValuesForElementBinding(int step, int ent, int ele, fullMatrix<double> &m) {
-  for (int i=0; i<m.size1(); i++)
-    for (int j=0; j<m.size2(); j++)
-       getValue(step,ent,ele,i,j,m(i,j));
+void PViewData::getAllValuesForElementBinding(int step, int ent, int ele, 
+                                              fullMatrix<double> &m)
+{
+  for (int i = 0; i < m.size1(); i++)
+    for (int j = 0; j < m.size2(); j++)
+      getValue(step, ent, ele, i, j, m(i, j));
 }
 
-void PViewData::getAllNodesForElementBinding(int step, int ent, int ele, fullMatrix<double> &m) {
-  for (int i=0; i<m.size1(); i++)
-    getNode(step,ent,ele,i,m(i,0),m(i,1),m(i,2));
+void PViewData::getAllNodesForElementBinding(int step, int ent, int ele,
+                                             fullMatrix<double> &m)
+{
+  for (int i = 0; i < m.size1(); i++)
+    getNode(step, ent, ele, i, m(i, 0), m(i, 1), m(i, 2));
 }
 
 #include "Bindings.h"
-void PViewData::registerBindings(binding *b) {
+void PViewData::registerBindings(binding *b)
+{
   classBinding *cb = b->addClass<PViewData>("PViewData");
   cb->setDescription("The data of a post-processing view");
   methodBinding *cm;
   cm = cb->addMethod("getNumEntities",&PViewData::getNumEntities);
   cm->setArgNames("step",NULL);
-  cm->setDescription("return the number of entities for a given time step (-1 for default)");
+  cm->setDescription("return the number of entities for a given time step "
+                     "(-1 for default)");
   cm = cb->addMethod("getNumElements",&PViewData::getNumElements);
   cm->setArgNames("step","entity",NULL);
-  cm->setDescription("return the number of entities for a given time step (-1 for default) for a given entity (-1 for all)");
+  cm->setDescription("return the number of entities for a given time step "
+                     "(-1 for default) for a given entity (-1 for all)");
   cm = cb->addMethod("getNumTriangles",&PViewData::getNumTriangles);
   cm->setArgNames("step",NULL);
-  cm->setDescription("return the number of triangles for a given time step (-1 for default)");
+  cm->setDescription("return the number of triangles for a given time step "
+                     "(-1 for default)");
 
   cm = cb->addMethod("getNumNodes",&PViewData::getNumNodes);
   cm->setArgNames("step","entity","element",NULL);
-  cm->setDescription("return the number of nodes of one element of an entity of a time step (-1 for default time step)");
+  cm->setDescription("return the number of nodes of one element of an entity "
+                     "of a time step (-1 for default time step)");
 
   cm = cb->addMethod("getElement",&PViewData::getElement);
   cm->setArgNames("step","entity","i",NULL);
@@ -169,11 +185,13 @@ void PViewData::registerBindings(binding *b) {
 
   cm = cb->addMethod("getNumValues",&PViewData::getNumValues);
   cm->setArgNames("step","entity","element",NULL);
-  cm->setDescription("return the number of values of one element of an entity of a time step (-1 for default time step)");
+  cm->setDescription("return the number of values of one element of an entity "
+                     "of a time step (-1 for default time step)");
 
   cm = cb->addMethod("getNumComponents",&PViewData::getNumComponents);
   cm->setArgNames("step","entity","element",NULL);
-  cm->setDescription("return the number of components of one element of an entity of a time step (-1 for default time step)");
+  cm->setDescription("return the number of components of one element of an entity "
+                     "of a time step (-1 for default time step)");
 
   cm = cb->addMethod("getValue",&PViewData::getValueBinding);
   cm->setArgNames("step","entity","element","node","component",NULL);
@@ -185,9 +203,11 @@ void PViewData::registerBindings(binding *b) {
 
   cm = cb->addMethod("getAllNodesForElement",&PViewData::getAllNodesForElementBinding);
   cm->setArgNames("step","entity","element","coordinates",NULL);
-  cm->setDescription("resize fill a fullMatrix with all coordinates of the nodes of the element");
+  cm->setDescription("resize fill a fullMatrix with all coordinates of the nodes "
+                     "of the element");
 
   cm = cb->addMethod("getDimension",&PViewData::getDimension);
   cm->setArgNames("step","entity","element",NULL);
-  cm->setDescription("return the geometrical dimension of the element-th element in the enttity-th entity");
+  cm->setDescription("return the geometrical dimension of the element-th element "
+                     "in the enttity-th entity");
 }
diff --git a/Post/PViewData.h b/Post/PViewData.h
index e2ccaabdae..d78559772d 100644
--- a/Post/PViewData.h
+++ b/Post/PViewData.h
@@ -168,8 +168,8 @@ class PViewData {
 
   // check if we should skip the given entity/element
   virtual bool skipEntity(int step, int ent){ return false; }
-  virtual bool skipElement(int step, int ent, int ele,
-                           bool checkVisibility=false){ return false; }
+  virtual bool skipElement(int step, int ent, int ele, bool checkVisibility=false,
+                           int samplingRate=1);
 
   // check if the data has the given step/partition/etc.
   virtual bool hasTimeStep(int step){ return step >= 0 && step < getNumTimeSteps(); }
diff --git a/Post/PViewDataGModel.cpp b/Post/PViewDataGModel.cpp
index 1b52eeff79..397d506724 100644
--- a/Post/PViewDataGModel.cpp
+++ b/Post/PViewDataGModel.cpp
@@ -552,7 +552,8 @@ bool PViewDataGModel::skipEntity(int step, int ent)
   return !_steps[step]->getEntity(ent)->getVisibility();
 }
 
-bool PViewDataGModel::skipElement(int step, int ent, int ele, bool checkVisibility)
+bool PViewDataGModel::skipElement(int step, int ent, int ele, bool checkVisibility,
+                                  int samplingRate)
 {
   if(step >= getNumTimeSteps()) return true;
   stepData<double> *sd = _steps[step];
@@ -566,7 +567,7 @@ bool PViewDataGModel::skipElement(int step, int ent, int ele, bool checkVisibili
   else{
     if(!sd->getData(e->getNum())) return true;
   }
-  return false;
+  return PViewData::skipElement(step, ent, ele, checkVisibility, samplingRate);
 }
 
 bool PViewDataGModel::hasTimeStep(int step)
diff --git a/Post/PViewDataGModel.h b/Post/PViewDataGModel.h
index 0119249e95..ff7365bfd2 100644
--- a/Post/PViewDataGModel.h
+++ b/Post/PViewDataGModel.h
@@ -211,7 +211,8 @@ class PViewDataGModel : public PViewData {
   void smooth();
   bool combineTime(nameData &nd);
   bool skipEntity(int step, int ent);
-  bool skipElement(int step, int ent, int ele, bool checkVisibility=false);
+  bool skipElement(int step, int ent, int ele, bool checkVisibility=false,
+                   int samplingRate=1);
   bool hasTimeStep(int step);
   bool hasPartition(int step, int part);
   bool hasMultipleMeshes();
diff --git a/Post/PViewOptions.h b/Post/PViewOptions.h
index fe63b92df3..febec84dc1 100644
--- a/Post/PViewOptions.h
+++ b/Post/PViewOptions.h
@@ -89,6 +89,7 @@ class PViewOptions {
   double targetError;
   int clip; // status of clip planes (bit array)
   int forceNumComponents, componentMap[9];
+  int sampling;
   struct{
     unsigned int point, line, triangle, quadrangle;
     unsigned int tetrahedron, hexahedron, prism, pyramid;
diff --git a/Post/PViewVertexArrays.cpp b/Post/PViewVertexArrays.cpp
index 80d29dab32..b5eee4f1b7 100644
--- a/Post/PViewVertexArrays.cpp
+++ b/Post/PViewVertexArrays.cpp
@@ -971,7 +971,7 @@ static void addElementsInArrays(PView *p, bool preprocessNormalsOnly)
   for(int ent = 0; ent < data->getNumEntities(opt->timeStep); ent++){
     if(data->skipEntity(opt->timeStep, ent)) continue;
     for(int i = 0; i < data->getNumElements(opt->timeStep, ent); i++){
-      if(data->skipElement(opt->timeStep, ent, i, true)) continue;
+      if(data->skipElement(opt->timeStep, ent, i, true, opt->sampling)) continue;
       int type = data->getType(opt->timeStep, ent, i);
       if(opt->skipElement(type)) continue;
       int numComp = data->getNumComponents(opt->timeStep, ent, i);
-- 
GitLab