From 2ee127b352f5b9bbc00166b55682205513735a3e Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Wed, 16 Aug 2006 21:11:41 +0000
Subject: [PATCH] *** empty log message ***

---
 Common/Context.h        |   2 +-
 Common/DefaultOptions.h |   4 +-
 Common/Options.cpp      |  12 +-
 Common/Options.h        |   2 +-
 Fltk/Callbacks.cpp      |   4 +-
 Fltk/GUI.cpp            |  23 +--
 Geo/MRep.h              |   9 +-
 Graphics/Mesh.cpp       | 402 +++++++++++++++++++++++-----------------
 8 files changed, 262 insertions(+), 196 deletions(-)

diff --git a/Common/Context.h b/Common/Context.h
index 9d1fd3b53f..f885cbbf66 100644
--- a/Common/Context.h
+++ b/Common/Context.h
@@ -176,7 +176,7 @@ public :
     int histogram, initial_only;
     double normals, tangents, explode;
     int color_carousel;
-    int use_cut_plane, cut_plane_as_surface, cut_plane_only_volume;
+    int use_cut_plane, cut_plane_draw_intersect, cut_plane_only_volume;
     double cut_planea, cut_planeb, cut_planec, cut_planed;
     double evalCutPlane (double x, double y, double z){
       double val = cut_planea * x + cut_planeb * y + cut_planec * z + cut_planed; 
diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index 243938e97a..a2f37938fb 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -860,8 +860,8 @@ StringXNumber MeshOptions_Number[] = {
     "CPU time (in seconds) for the generation of the current mesh (read-only)" },
   { F,   "CutPlane" , opt_mesh_use_cut_plane , 0 ,
     "Enable mesh cut plane" },
-  { F,   "CutPlaneAsSurface" , opt_mesh_cut_plane_as_surface , 0 ,
-    "Draw the intersection volume layer as a surface" },
+  { F,   "CutPlaneDrawIntersect" , opt_mesh_cut_plane_draw_intersect , 0 ,
+    "Draw only the volume elements that intersect with the cut plane" },
   { F,   "CutPlaneOnlyVolume" , opt_mesh_cut_plane_only_volume , 0 ,
     "Cut only the volume elements" },
   { F,   "CutPlaneA" , opt_mesh_cut_planea , 1.0 , 
diff --git a/Common/Options.cpp b/Common/Options.cpp
index 0150f5df1a..9a70401150 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -1,4 +1,4 @@
-// $Id: Options.cpp,v 1.290 2006-08-15 21:22:12 geuzaine Exp $
+// $Id: Options.cpp,v 1.291 2006-08-16 21:11:41 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -4722,17 +4722,17 @@ double opt_mesh_use_cut_plane(OPT_ARGS_NUM)
   return CTX.mesh.use_cut_plane;
 }
 
-double opt_mesh_cut_plane_as_surface(OPT_ARGS_NUM)
+double opt_mesh_cut_plane_draw_intersect(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET){
-    if(CTX.mesh.cut_plane_as_surface != (int)val) CTX.mesh.changed = 1;
-    CTX.mesh.cut_plane_as_surface = (int)val;
+    if(CTX.mesh.cut_plane_draw_intersect != (int)val) CTX.mesh.changed = 1;
+    CTX.mesh.cut_plane_draw_intersect = (int)val;
   }
 #if defined(HAVE_FLTK)
   if(WID && (action & GMSH_GUI))
-    WID->mesh_butt[22]->value(CTX.mesh.cut_plane_as_surface);
+    WID->mesh_butt[22]->value(CTX.mesh.cut_plane_draw_intersect);
 #endif
-  return CTX.mesh.cut_plane_as_surface;
+  return CTX.mesh.cut_plane_draw_intersect;
 }
 
 double opt_mesh_cut_plane_only_volume(OPT_ARGS_NUM)
diff --git a/Common/Options.h b/Common/Options.h
index 92444ef109..97d782bae5 100644
--- a/Common/Options.h
+++ b/Common/Options.h
@@ -461,7 +461,7 @@ double opt_mesh_dual(OPT_ARGS_NUM);
 double opt_mesh_interactive(OPT_ARGS_NUM);
 double opt_mesh_initial_only(OPT_ARGS_NUM);
 double opt_mesh_use_cut_plane(OPT_ARGS_NUM);
-double opt_mesh_cut_plane_as_surface(OPT_ARGS_NUM);
+double opt_mesh_cut_plane_draw_intersect(OPT_ARGS_NUM);
 double opt_mesh_cut_plane_only_volume(OPT_ARGS_NUM);
 double opt_mesh_cut_planea(OPT_ARGS_NUM);
 double opt_mesh_cut_planeb(OPT_ARGS_NUM);
diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp
index 862d4b61b1..c49032122d 100644
--- a/Fltk/Callbacks.cpp
+++ b/Fltk/Callbacks.cpp
@@ -1,4 +1,4 @@
-// $Id: Callbacks.cpp,v 1.431 2006-08-15 21:22:12 geuzaine Exp $
+// $Id: Callbacks.cpp,v 1.432 2006-08-16 21:11:41 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -1122,7 +1122,7 @@ void mesh_options_ok_cb(CALLBACK_ARGS)
   opt_mesh_surfaces_num(0, GMSH_SET, WID->mesh_butt[14]->value());
   opt_mesh_volumes_num(0, GMSH_SET, WID->mesh_butt[15]->value());
   opt_mesh_use_cut_plane(0, GMSH_SET, WID->mesh_butt[16]->value());
-  opt_mesh_cut_plane_as_surface(0, GMSH_SET, WID->mesh_butt[22]->value());
+  opt_mesh_cut_plane_draw_intersect(0, GMSH_SET, WID->mesh_butt[22]->value());
   opt_mesh_cut_plane_only_volume(0, GMSH_SET, WID->mesh_butt[23]->value());
   opt_mesh_light(0, GMSH_SET, WID->mesh_butt[17]->value());
   opt_mesh_light_two_side(0, GMSH_SET, WID->mesh_butt[18]->value());
diff --git a/Fltk/GUI.cpp b/Fltk/GUI.cpp
index ed06b27ba7..00590c140a 100644
--- a/Fltk/GUI.cpp
+++ b/Fltk/GUI.cpp
@@ -1,4 +1,4 @@
-// $Id: GUI.cpp,v 1.517 2006-08-15 21:22:12 geuzaine Exp $
+// $Id: GUI.cpp,v 1.518 2006-08-16 21:11:41 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -725,24 +725,20 @@ int GUI::global_shortcuts(int event)
     return 1;
   }
   else if(Fl::test_shortcut(FL_ALT + FL_SHIFT + 'l')) {
-    opt_mesh_surfaces_edges(0, GMSH_SET | GMSH_GUI, 
-			    !opt_mesh_surfaces_edges(0, GMSH_GET, 0));
+    opt_mesh_lines(0, GMSH_SET | GMSH_GUI, 
+		   !opt_mesh_lines(0, GMSH_GET, 0));
     redraw_opengl();
     return 1;
   }
   else if(Fl::test_shortcut(FL_ALT + FL_SHIFT + 's')) {
-    int old = opt_mesh_surfaces_edges(0, GMSH_GET, 0) ||
-      opt_mesh_surfaces_faces(0, GMSH_GET, 0);
-    opt_mesh_surfaces_edges(0, GMSH_SET | GMSH_GUI, !old);
-    opt_mesh_surfaces_faces(0, GMSH_SET | GMSH_GUI, !old);
+    opt_mesh_surfaces_edges(0, GMSH_SET | GMSH_GUI,
+			    !opt_mesh_surfaces_edges(0, GMSH_GET, 0));
     redraw_opengl();
     return 1;
   }
   else if(Fl::test_shortcut(FL_ALT + FL_SHIFT + 'v')) {
-    int old = opt_mesh_volumes_edges(0, GMSH_GET, 0) || 
-      opt_mesh_volumes_faces(0, GMSH_GET, 0);
-    opt_mesh_volumes_edges(0, GMSH_SET | GMSH_GUI, !old);
-    opt_mesh_volumes_faces(0, GMSH_SET | GMSH_GUI, !old);
+    opt_mesh_volumes_edges(0, GMSH_SET | GMSH_GUI,
+			   !opt_mesh_volumes_edges(0, GMSH_GET, 0));
     redraw_opengl();
     return 1;
   }
@@ -2361,7 +2357,7 @@ void GUI::create_option_window()
       mesh_butt[8]->selection_color(GMSH_TOGGLE_COLOR);
 
       mesh_butt[9] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 4 * BH, BW / 2 - WB, BH, "Surface element faces");
-      mesh_butt[9]->tooltip("(Alt+Shift+s, Alt+Shift+d)");
+      mesh_butt[9]->tooltip("(Alt+Shift+d)");
       mesh_butt[9]->type(FL_TOGGLE_BUTTON);
       mesh_butt[9]->down_box(GMSH_TOGGLE_BOX);
       mesh_butt[9]->selection_color(GMSH_TOGGLE_COLOR);
@@ -2373,7 +2369,6 @@ void GUI::create_option_window()
       mesh_butt[10]->selection_color(GMSH_TOGGLE_COLOR);
 
       mesh_butt[11] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 6 * BH, BW / 2 - WB, BH, "Volume element faces");
-      mesh_butt[11]->tooltip("(Alt+Shift+v)");
       mesh_butt[11]->type(FL_TOGGLE_BUTTON);
       mesh_butt[11]->down_box(GMSH_TOGGLE_BOX);
       mesh_butt[11]->selection_color(GMSH_TOGGLE_COLOR);
@@ -2503,7 +2498,7 @@ void GUI::create_option_window()
       mesh_value[17]->minimum(-1.0);
       mesh_value[17]->maximum(1.0);
 
-      mesh_butt[22] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 6 * BH, BW, BH, "Draw intersecting volume layer as surface");
+      mesh_butt[22] = new Fl_Check_Button(L + 2 * WB, 2 * WB + 6 * BH, BW, BH, "Draw only intersecting volume layer");
       mesh_butt[22]->type(FL_TOGGLE_BUTTON);
       mesh_butt[22]->down_box(GMSH_TOGGLE_BOX);
       mesh_butt[22]->selection_color(GMSH_TOGGLE_COLOR);
diff --git a/Geo/MRep.h b/Geo/MRep.h
index 2497aca4b2..b22e83beeb 100644
--- a/Geo/MRep.h
+++ b/Geo/MRep.h
@@ -43,7 +43,6 @@ class MRep {
   template<class T>
   void generateEdgeRep(std::vector<T*> &elements)
   {
-    if(edges.size()) return;
     for(unsigned int i = 0; i < elements.size(); i++){
       for(int j = 0; j < elements[i]->getNumEdgesRep(); j++){
 	MEdge e = elements[i]->getEdgeRep(j);
@@ -54,7 +53,7 @@ class MRep {
   }
 
  public:
-  MRep() : va_lines(0), va_triangles(0), va_quads(0) {}
+  MRep() : va_lines(0), va_triangles(0), va_quads(0), allElementsVisible(true) {}
   virtual ~MRep(){}
 
   // generates the edge representation
@@ -78,6 +77,9 @@ class MRep {
     if(va_quads) delete va_quads;
     va_quads = 0;
   }
+
+  // a flag telling if all the elements in the entity are visible
+  bool allElementsVisible;
 };
 
 class MRepEdge : public MRep {
@@ -89,6 +91,7 @@ class MRepEdge : public MRep {
   virtual ~MRepEdge(){}
   virtual void generateEdgeRep()
   {
+    if(edges.size()) return;
     MRep::generateEdgeRep(_e->lines);
   }
 };
@@ -102,6 +105,7 @@ class MRepFace : public MRep {
   virtual ~MRepFace(){}
   virtual void generateEdgeRep()
   {
+    if(edges.size()) return;
     double t = Cpu();    
     MRep::generateEdgeRep(_f->triangles);
     MRep::generateEdgeRep(_f->quadrangles);
@@ -119,6 +123,7 @@ class MRepRegion : public MRep {
   virtual ~MRepRegion(){}
   virtual void generateEdgeRep()
   {
+    if(edges.size()) return;
     double t = Cpu();    
     MRep::generateEdgeRep(_r->tetrahedra);
     MRep::generateEdgeRep(_r->hexahedra);
diff --git a/Graphics/Mesh.cpp b/Graphics/Mesh.cpp
index b588fb65a4..17ea383fe3 100644
--- a/Graphics/Mesh.cpp
+++ b/Graphics/Mesh.cpp
@@ -1,4 +1,4 @@
-// $Id: Mesh.cpp,v 1.170 2006-08-16 17:14:57 geuzaine Exp $
+// $Id: Mesh.cpp,v 1.171 2006-08-16 21:11:41 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -58,24 +58,51 @@ static unsigned int getColor(GEntity *e, int forceColor, unsigned int color)
   return color;
 }
 
-static double intersectCutPlane(MElement *ele, int *edges=0, int *faces=0)
+static double intersectCutPlane(MElement *ele)
 {
   MVertex *v = ele->getVertex(0);
   double val = CTX.mesh.evalCutPlane(v->x(), v->y(), v->z());
   for(int i = 1; i < ele->getNumVertices(); i++){
     v = ele->getVertex(i);
-    if(val * CTX.mesh.evalCutPlane(v->x(), v->y(), v->z()) <= 0){
-      // the element intersects the cut plane
-      if(CTX.mesh.cut_plane_as_surface){
-	if(!*edges) *edges = CTX.mesh.surfaces_edges;
-	if(!*faces) *faces = CTX.mesh.surfaces_faces;
-      }
-      return 1.;
-    }
+    if(val * CTX.mesh.evalCutPlane(v->x(), v->y(), v->z()) <= 0)
+      return 0.; // the element intersects the cut plane
   }
   return val;
 }
 
+static bool isElementVisible(MElement *ele)
+{
+  if(!ele->getVisibility()) return false;
+  if(CTX.mesh.quality_sup) {
+    double q;
+    if(CTX.mesh.quality_type == 2)
+      q = ele->rhoShapeMeasure();
+    else if(CTX.mesh.quality_type == 1)
+      q = ele->etaShapeMeasure();
+    else
+      q = ele->gammaShapeMeasure();
+    if(q < CTX.mesh.quality_inf || q > CTX.mesh.quality_sup) return false;
+  }
+  if(CTX.mesh.radius_sup) {
+    double r = ele->maxEdge();
+    if(r < CTX.mesh.radius_inf || r > CTX.mesh.radius_sup) return false;
+  }
+  if(CTX.mesh.use_cut_plane){
+    if(ele->getDim() < 3 && CTX.mesh.cut_plane_only_volume){
+    }
+    else if(intersectCutPlane(ele) < 0) return false;
+  }
+  return true;
+}
+
+template<class T>
+static bool areAllElementsVisible(std::vector<T*> &elements)
+{
+  for(unsigned int i = 0; i < elements.size(); i++)
+    if(!isElementVisible(elements[i])) return false;
+  return true;
+}
+
 static int getLabelStep(int total)
 {
   int step;
@@ -87,15 +114,18 @@ static int getLabelStep(int total)
 }
 
 template<class T>
-static void drawLabels(GEntity *e, std::vector<T*> &elements, int labelStep,
-		       int &labelNum, int forceColor, unsigned int color)
+static void drawElementLabels(GEntity *e, std::vector<T*> &elements,
+			      int forceColor, unsigned int color)
 {
   unsigned col = getColor(e, forceColor, color);
   glColor4ubv((GLubyte *) & col);
+
+  int labelStep = getLabelStep(elements.size());
+
   for(unsigned int i = 0; i < elements.size(); i++){
     MElement *ele = elements[i];
-    labelNum++;
-    if(labelNum % labelStep == 0) {
+    if(!isElementVisible(ele)) continue;
+    if(i % labelStep == 0) {
       SPoint3 pc = ele->barycenter();
       char str[256];
       if(CTX.mesh.label_type == 4)
@@ -129,10 +159,12 @@ static void drawNormals(std::vector<T*> &elements)
 {
   glColor4ubv((GLubyte *) & CTX.color.mesh.normals);
   for(unsigned int i = 0; i < elements.size(); i++){
-    SVector3 n = elements[i]->getFaceRep(0).normal();
+    MElement *ele = elements[i];
+    if(!isElementVisible(ele)) continue;
+    SVector3 n = ele->getFaceRep(0).normal();
     for(int j = 0; j < 3; j++)
       n[j] *= CTX.mesh.normals * CTX.pixel_equiv_x / CTX.s[j];
-    SPoint3 pc = elements[i]->barycenter();
+    SPoint3 pc = ele->barycenter();
     Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
 		CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius,
 		pc.x(), pc.y(), pc.z(), n[0], n[1], n[2], CTX.mesh.light);
@@ -144,17 +176,45 @@ static void drawTangents(std::vector<T*> &elements)
 {
   glColor4ubv((GLubyte *) & CTX.color.mesh.tangents);
   for(unsigned int i = 0; i < elements.size(); i++){
-    SVector3 t = elements[i]->getEdgeRep(0).tangent();
+    MElement *ele = elements[i];
+    if(!isElementVisible(ele)) continue;
+    SVector3 t = ele->getEdgeRep(0).tangent();
     for(int j = 0; j < 3; j++)
       t[j] *= CTX.mesh.tangents * CTX.pixel_equiv_x / CTX.s[j];
-    SPoint3 pc = elements[i]->barycenter();
+    SPoint3 pc = ele->barycenter();
     Draw_Vector(CTX.vector_type, 0, CTX.arrow_rel_head_radius, 
 		CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius,
 		pc.x(), pc.y(), pc.z(), t[0], t[1], t[2], CTX.mesh.light);
   }
 }
 
-static void drawVertices(GEntity *e)
+static void drawVertexLabel(GEntity *e, MVertex *v, int partition=-1)
+{
+  int np = e->physicals.size();
+  int physical = np ? e->physicals[np - 1] : 0;
+  char str[256];
+  if(CTX.mesh.label_type == 4)
+    sprintf(str, "(%g,%g,%g)", v->x(), v->y(), v->z());
+  else if(CTX.mesh.label_type == 3){
+    if(partition < 0)
+      sprintf(str, "NA");
+    else
+      sprintf(str, "%d", partition);
+  }
+  else if(CTX.mesh.label_type == 2)
+    sprintf(str, "%d", physical);
+  else if(CTX.mesh.label_type == 1)
+    sprintf(str, "%d", e->tag());
+  else
+    sprintf(str, "%d", v->getNum());
+  double offset = 0.3 * (CTX.mesh.point_size + CTX.gl_fontsize) * CTX.pixel_equiv_x;
+  glRasterPos3d(v->x() + offset / CTX.s[0],
+		v->y() + offset / CTX.s[1],
+		v->z() + offset / CTX.s[2]);
+  Draw_String(str);
+}
+
+static void drawVerticesPerEntity(GEntity *e)
 {
   glColor4ubv((GLubyte *) & CTX.color.mesh.vertex);
 
@@ -162,6 +222,7 @@ static void drawVertices(GEntity *e)
     if(CTX.mesh.point_type) {
       for(unsigned int i = 0; i < e->mesh_vertices.size(); i++){
 	MVertex *v = e->mesh_vertices[i];
+	if(!v->getVisibility()) continue;
 	Draw_Sphere(CTX.mesh.point_size, v->x(), v->y(), v->z(), CTX.mesh.light);
       }
     }
@@ -169,37 +230,40 @@ static void drawVertices(GEntity *e)
       glBegin(GL_POINTS);
       for(unsigned int i = 0; i < e->mesh_vertices.size(); i++){
 	MVertex *v = e->mesh_vertices[i];
+	if(!v->getVisibility()) continue;
 	glVertex3d(v->x(), v->y(), v->z());
       }
       glEnd();
     }
   }
-
-  int np = e->physicals.size();
-  int physical = np ? e->physicals[np - 1] : 0;
-  const int labelStep = getLabelStep(e->mesh_vertices.size());
-  int labelNum = 0;
   if(CTX.mesh.points_num) {
-    for(unsigned int i = 0; i < e->mesh_vertices.size(); i++){
-      MVertex *v = e->mesh_vertices[i];
-      labelNum++;
-      if(labelNum % labelStep == 0) {
-	char str[256];
-	if(CTX.mesh.label_type == 4)
-	  sprintf(str, "(%g,%g,%g)", v->x(), v->y(), v->z());
-	else if(CTX.mesh.label_type == 3)
-	  sprintf(str, "NA");
-	else if(CTX.mesh.label_type == 2)
-	  sprintf(str, "%d", physical);
-	else if(CTX.mesh.label_type == 1)
-	  sprintf(str, "%d", e->tag());
-	else
-	  sprintf(str, "%d", v->getNum());
-	double offset = 0.3 * (CTX.mesh.point_size + CTX.gl_fontsize) * CTX.pixel_equiv_x;
-	glRasterPos3d(v->x() + offset / CTX.s[0],
-		      v->y() + offset / CTX.s[1],
-		      v->z() + offset / CTX.s[2]);
-	Draw_String(str);
+    int labelStep = getLabelStep(e->mesh_vertices.size());
+    for(unsigned int i = 0; i < e->mesh_vertices.size(); i++)
+      if(i % labelStep == 0) drawVertexLabel(e, e->mesh_vertices[i]);
+  }
+}
+
+template<class T>
+static void drawVerticesPerElement(GEntity *e, std::vector<T*> &elements)
+{
+  glColor4ubv((GLubyte *) & CTX.color.mesh.vertex);
+  
+  for(unsigned int i = 0; i < elements.size(); i++){
+    MElement *ele = elements[i];
+    for(int j = 0; j < ele->getNumVertices(); j++){
+      MVertex *v = ele->getVertex(j);
+      if(isElementVisible(ele) && v->getVisibility()){
+	if(CTX.mesh.points) {
+	  if(CTX.mesh.point_type)
+	    Draw_Sphere(CTX.mesh.point_size, v->x(), v->y(), v->z(), CTX.mesh.light);
+	  else{
+	    glBegin(GL_POINTS);
+	    glVertex3d(v->x(), v->y(), v->z());
+	    glEnd();
+	  }
+	}
+	if(CTX.mesh.points_num)
+	  drawVertexLabel(e, v);
       }
     }
   }
@@ -215,6 +279,7 @@ static void drawBarycentricDual(std::vector<T*> &elements)
   glBegin(GL_LINES);
   for(unsigned int i = 0; i < elements.size(); i++){
     MElement *ele = elements[i];
+    if(!isElementVisible(ele)) continue;
     SPoint3 pc = ele->barycenter();
     if(ele->getDim() == 2){
       for(int j = 0; j < ele->getNumEdges(); j++){
@@ -245,81 +310,91 @@ static void drawBarycentricDual(std::vector<T*> &elements)
   gl2psDisable(GL2PS_LINE_STIPPLE);
 }
 
+// Routine to fill the smooth normal container
+
 template<class T>
-static bool allElementsVisible(std::vector<T*> &elements)
+static void addSmoothNormals(GEntity *e, std::vector<T*> &elements)
 {
-  for(unsigned int i = 0; i < elements.size(); i++)
-    if(!elements[i]->getVisibility()) return false;
-  return true;
+  for(unsigned int i = 0; i < elements.size(); i++){
+    MElement *ele = elements[i];
+    for(int j = 0; j < ele->getNumFacesRep(); j++){
+      MFace fr = ele->getFaceRep(j);
+      SVector3 n = fr.normal();
+      SPoint3 pc;
+      if(CTX.mesh.explode != 1.) pc = ele->barycenter();
+      for(int k = 0; k < fr.getNumVertices(); k++){
+	MVertex *v = fr.getVertex(k);
+	SPoint3 p(v->x(), v->y(), v->z());
+	if(CTX.mesh.explode != 1.){
+	  for(int l = 0; l < 3; l++)
+	    p[l] = pc[l] + CTX.mesh.explode * (p[l] - pc[l]);
+	}
+	e->model()->normals->add(p[0], p[1], p[2], n[0], n[1], n[2]);
+      }
+    }
+  }
 }
 
 // Routines for filling and drawing the vertex arrays
 
-static void addEdgesInArrays(GEntity *e, VertexArray *va, MRep *m)
+static void addEdgesInArrays(GEntity *e)
 {
+  MRep *m = e->meshRep;
   for(MRep::eriter it = m->firstEdgeRep(); it != m->lastEdgeRep(); ++it){
     MVertex *v[2] = {it->first.first, it->first.second};
     MElement *ele = it->second;
     SVector3 n = ele->getFace(0).normal();
     int part = ele->getPartition();
     for(int i = 0; i < 2; i++){
-      if(CTX.mesh.smooth_normals)
+      if(e->dim() == 2 && CTX.mesh.smooth_normals)
 	e->model()->normals->get(v[i]->x(), v[i]->y(), v[i]->z(), n[0], n[1], n[2]);
-      va->add(v[i]->x(), v[i]->y(), v[i]->z(), n[0], n[1], n[2],
-	      CTX.color.mesh.carousel[abs(part % 20)]);
+      m->va_lines->add(v[i]->x(), v[i]->y(), v[i]->z(), n[0], n[1], n[2],
+		       CTX.color.mesh.carousel[abs(part % 20)]);
     }
   }
 }
 
 template<class T>
-static void addElementsInArrays(GEntity *e, VertexArray *va, std::vector<T*> &elements)
+static void addElementsInArrays(GEntity *e, std::vector<T*> &elements)
 {
+  MRep *m = e->meshRep;
   for(unsigned int i = 0; i < elements.size(); i++){
     MElement *ele = elements[i];
-    int part = ele->getPartition();
-    if(CTX.mesh.quality_sup) {
-      double q;
-      if(CTX.mesh.quality_type == 2)
-	q = ele->rhoShapeMeasure();
-      else if(CTX.mesh.quality_type == 1)
-	q = ele->etaShapeMeasure();
-      else
-	q = ele->gammaShapeMeasure();
-      if(q < CTX.mesh.quality_inf || q > CTX.mesh.quality_sup) continue;
-    }
-    if(CTX.mesh.radius_sup) {
-      double r = ele->maxEdge();
-      if(r < CTX.mesh.radius_inf || r > CTX.mesh.radius_sup) continue;
-    }
-    if(CTX.mesh.use_cut_plane && !CTX.mesh.cut_plane_only_volume){
-      if(intersectCutPlane(ele) < 0) continue;
+    if(!isElementVisible(ele)) continue;
+    if(CTX.mesh.use_cut_plane && CTX.mesh.cut_plane_draw_intersect){
+      if(e->dim() == 3 && intersectCutPlane(ele)) continue;
     }
+    int part = ele->getPartition();
+    SPoint3 pc;
+    if(CTX.mesh.explode != 1.) pc = ele->barycenter();
     if(ele->getNumFacesRep()){
       for(int j = 0; j < ele->getNumFacesRep(); j++){
 	MFace fr = ele->getFaceRep(j);
-	if(fr.getNumVertices() != va->type) continue;
 	SVector3 n = fr.normal();
-	SPoint3 pc;
-	if(CTX.mesh.explode != 1.) pc = ele->barycenter();
-	for(int k = 0; k < fr.getNumVertices(); k++){
+	int numverts = fr.getNumVertices();
+	for(int k = 0; k < numverts; k++){
 	  MVertex *v = fr.getVertex(k);
 	  SPoint3 p(v->x(), v->y(), v->z());
 	  if(CTX.mesh.explode != 1.){
 	    for(int l = 0; l < 3; l++)
 	      p[l] = pc[l] + CTX.mesh.explode * (p[l] - pc[l]);
 	  }
-	  if(CTX.mesh.smooth_normals)
+	  if(e->dim() == 2 && CTX.mesh.smooth_normals)
 	    e->model()->normals->get(p[0], p[1], p[2], n[0], n[1], n[2]);
-	  va->add(p[0], p[1], p[2], n[0], n[1], n[2],
-		  CTX.color.mesh.carousel[abs(part % 20)]);
+	  if(numverts == 3)
+	    m->va_triangles->add(p[0], p[1], p[2], n[0], n[1], n[2],
+					  CTX.color.mesh.carousel[abs(part % 20)]);
+	  else if(numverts == 4)
+	    m->va_quads->add(p[0], p[1], p[2], n[0], n[1], n[2],
+				      CTX.color.mesh.carousel[abs(part % 20)]);
 	}
       }
     }
     else{
+      SPoint3 pc;
+      if(CTX.mesh.explode != 1.) pc = ele->barycenter();
       for(int j = 0; j < ele->getNumEdgesRep(); j++){
 	MEdge er = ele->getEdgeRep(j);
-	SPoint3 pc;
-	if(CTX.mesh.explode != 1.) pc = ele->barycenter();
 	for(int k = 0; k < er.getNumVertices(); k++){
 	  MVertex *v = er.getVertex(k);
 	  SPoint3 p(v->x(), v->y(), v->z());
@@ -327,7 +402,7 @@ static void addElementsInArrays(GEntity *e, VertexArray *va, std::vector<T*> &el
 	    for(int l = 0; l < 3; l++)
 	      p[l] = pc[l] + CTX.mesh.explode * (p[l] - pc[l]);
 	  }
-	  va->add(p[0], p[1], p[2], CTX.color.mesh.carousel[abs(part % 20)]);
+	  m->va_lines->add(p[0], p[1], p[2], CTX.color.mesh.carousel[abs(part % 20)]);
 	}
       }
     }
@@ -389,7 +464,7 @@ class drawMeshGVertex {
     }
 
     if(CTX.mesh.points || CTX.mesh.points_num)
-      drawVertices(v);
+      drawVerticesPerEntity(v);
 
     if(CTX.render_mode == GMSH_SELECT) {
       glPopName();
@@ -410,10 +485,11 @@ class initMeshGEdge {
 
     MRep *m = e->meshRep;
     m->resetArrays();
+    m->allElementsVisible = areAllElementsVisible(e->lines);
 
     if(CTX.mesh.lines){
       m->va_lines = new VertexArray(2, e->lines.size());
-      addElementsInArrays(e, m->va_lines, e->lines);
+      addElementsInArrays(e, e->lines);
     }
   }
 };
@@ -435,14 +511,15 @@ class drawMeshGEdge {
       drawArrays(m->va_lines, GL_LINES, false, CTX.mesh.color_carousel == 3, 
 		 false,  getColor(e, false, CTX.color.mesh.line));
 
-    if(CTX.mesh.lines_num) {
-      const int labelStep = getLabelStep(e->lines.size());
-      int labelNum = 0;
-      drawLabels(e, e->lines, labelStep, labelNum, false, CTX.color.mesh.line);
-    }
+    if(CTX.mesh.lines_num)
+      drawElementLabels(e, e->lines, false, CTX.color.mesh.line);
 
-    if(CTX.mesh.points || CTX.mesh.points_num)
-      drawVertices(e);
+    if(CTX.mesh.points || CTX.mesh.points_num){
+      if(m->allElementsVisible)
+	drawVerticesPerEntity(e);
+      else
+	drawVerticesPerElement(e, e->lines);
+    }
 
     if(CTX.mesh.tangents)
       drawTangents(e->lines);
@@ -457,34 +534,11 @@ class drawMeshGEdge {
 // GFace drawing routines
 
 class initSmoothNormalsGFace {
- private:
-  template<class T>
-  void _addSmoothNormals(GFace *f, std::vector<T*> &elements)
-  {
-    for(unsigned int i = 0; i < elements.size(); i++){
-      MElement *ele = elements[i];
-      for(int j = 0; j < ele->getNumFacesRep(); j++){
-	MFace fr = ele->getFaceRep(j);
-	SVector3 n = fr.normal();
-	SPoint3 pc;
-	if(CTX.mesh.explode != 1.) pc = ele->barycenter();
-	for(int k = 0; k < fr.getNumVertices(); k++){
-	  MVertex *v = fr.getVertex(k);
-	  SPoint3 p(v->x(), v->y(), v->z());
-	  if(CTX.mesh.explode != 1.){
-	    for(int l = 0; l < 3; l++)
-	      p[l] = pc[l] + CTX.mesh.explode * (p[l] - pc[l]);
-	  }
-	  f->model()->normals->add(p[0], p[1], p[2], n[0], n[1], n[2]);
-	}
-      }
-    }
-  }
  public :
   void operator () (GFace *f)
   {
-    _addSmoothNormals(f, f->triangles);
-    _addSmoothNormals(f, f->quadrangles);
+    addSmoothNormals(f, f->triangles);
+    addSmoothNormals(f, f->quadrangles);
   }
 };
 
@@ -498,31 +552,32 @@ class initMeshGFace {
 
     MRep *m = f->meshRep;
     m->resetArrays();
+    m->allElementsVisible = 
+      areAllElementsVisible(f->triangles) && 
+      areAllElementsVisible(f->quadrangles);
 
-    // TODO: further optimizations are possible when useEdges is true:
-    //
-    // 1) store the unique vertices in the vertex array and use
-    //    glDrawElements() instead of glDrawArrays().
-    // 2) use tc to stripe the triangles and draw strips instead of individual
-    //    triangles
     bool useEdges = CTX.mesh.surfaces_edges ? true : false;
-    if(CTX.mesh.surfaces_faces /*this will change!*/ || CTX.mesh.explode != 1. || 
-       CTX.mesh.quality_sup || CTX.mesh.radius_sup || CTX.mesh.use_cut_plane ||
-       !allElementsVisible(f->triangles) || !allElementsVisible(f->quadrangles))
+    if(CTX.mesh.surfaces_faces /*this will change!*/ || 
+       CTX.mesh.explode != 1. || !m->allElementsVisible)
       useEdges = false;
+
+    // Further optimizations are possible when useEdges is true:
+    // 1) store the unique vertices in the vertex array and use
+    //    glDrawElements() instead of glDrawArrays().
+    // 2) use tc to stripe the triangles and draw strips instead of 
+    //    individual triangles
     
     if(useEdges){
       Msg(DEBUG, "Using edges to draw surface %d", f->tag());
       m->generateEdgeRep();
       m->va_lines = new VertexArray(2, m->getNumEdgeRep());
-      addEdgesInArrays(f, m->va_lines, m);
+      addEdgesInArrays(f);
     }
     else if(CTX.mesh.surfaces_edges || CTX.mesh.surfaces_faces){
       m->va_triangles = new VertexArray(3, f->triangles.size());
-      addElementsInArrays(f, m->va_triangles, f->triangles);
-
       m->va_quads = new VertexArray(4, f->quadrangles.size());
-      addElementsInArrays(f, m->va_quads, f->quadrangles);
+      addElementsInArrays(f, f->triangles);
+      addElementsInArrays(f, f->quadrangles);
     }
   }
 };
@@ -566,16 +621,18 @@ class drawMeshGFace {
     }
 
     if(CTX.mesh.surfaces_num) {
-      const int labelStep = getLabelStep(f->triangles.size() + f->quadrangles.size());
-      int labelNum = 0;
-      drawLabels(f, f->triangles, labelStep, labelNum,
-		 CTX.mesh.surfaces_faces, CTX.color.mesh.line);
-      drawLabels(f, f->quadrangles, labelStep, labelNum,
-		 CTX.mesh.surfaces_faces, CTX.color.mesh.line);
+      drawElementLabels(f, f->triangles, CTX.mesh.surfaces_faces, CTX.color.mesh.line);
+      drawElementLabels(f, f->quadrangles, CTX.mesh.surfaces_faces, CTX.color.mesh.line);
     }
 
-    if(CTX.mesh.points || CTX.mesh.points_num)
-      drawVertices(f);
+    if(CTX.mesh.points || CTX.mesh.points_num){
+      if(m->allElementsVisible)
+	drawVerticesPerEntity(f);
+      else{
+	drawVerticesPerElement(f, f->triangles);
+	drawVerticesPerElement(f, f->quadrangles);
+      }
+    }
 
     if(CTX.mesh.normals) {
       drawNormals(f->triangles);
@@ -606,34 +663,34 @@ class initMeshGRegion {
 
     MRep *m = r->meshRep;
     m->resetArrays();
+    m->allElementsVisible = 
+      areAllElementsVisible(r->tetrahedra) &&
+      areAllElementsVisible(r->hexahedra) &&
+      areAllElementsVisible(r->prisms) &&
+      areAllElementsVisible(r->pyramids);
 
     bool useEdges = CTX.mesh.volumes_edges ? true : false;
-    if(CTX.mesh.volumes_faces /*this will change!*/ || CTX.mesh.explode != 1. || 
-       CTX.mesh.quality_sup || CTX.mesh.radius_sup || CTX.mesh.use_cut_plane ||
-       !allElementsVisible(r->tetrahedra) || !allElementsVisible(r->hexahedra) ||
-       !allElementsVisible(r->prisms) || !allElementsVisible(r->pyramids))
+    if(CTX.mesh.volumes_faces /*this will change!*/ || 
+       CTX.mesh.explode != 1. || !m->allElementsVisible)
       useEdges = false;
-
+    
     if(useEdges){
       Msg(DEBUG, "Using edges to draw volume %d", r->tag());
       m->generateEdgeRep();
       m->va_lines = new VertexArray(2, m->getNumEdgeRep());
-      addEdgesInArrays(r, m->va_lines, m);
+      addEdgesInArrays(r);
     }
     else if(CTX.mesh.volumes_edges || CTX.mesh.volumes_faces){
       m->va_triangles = new VertexArray(3, 4 * r->tetrahedra.size() +
 					2 * r->prisms.size() + 
 					4 * r->pyramids.size());
-      addElementsInArrays(r, m->va_triangles, r->tetrahedra);
-      addElementsInArrays(r, m->va_triangles, r->prisms);
-      addElementsInArrays(r, m->va_triangles, r->pyramids);
-
       m->va_quads = new VertexArray(4, 6 * r->hexahedra.size() +
 				    3 * r->prisms.size() +
 				    r->pyramids.size());
-      addElementsInArrays(r, m->va_quads, r->hexahedra);
-      addElementsInArrays(r, m->va_quads, r->prisms);
-      addElementsInArrays(r, m->va_quads, r->pyramids);
+      addElementsInArrays(r, r->tetrahedra);
+      addElementsInArrays(r, r->hexahedra);
+      addElementsInArrays(r, r->prisms);
+      addElementsInArrays(r, r->pyramids);
     }
   }
 };
@@ -653,7 +710,7 @@ class drawMeshGRegion {
 
     if(CTX.mesh.volumes_edges){
       if(m->va_lines && m->va_lines->n()){
-	drawArrays(m->va_lines, GL_LINES, false, 
+	drawArrays(m->va_lines, GL_LINES, CTX.mesh.light && CTX.mesh.light_lines, 
 		   CTX.mesh.color_carousel == 3, false, 
 		   getColor(r, CTX.mesh.volumes_faces, CTX.color.mesh.line));
       }
@@ -668,31 +725,40 @@ class drawMeshGRegion {
     }
     
     if(CTX.mesh.volumes_faces){
+      // Note: color will be incorrect for mixed meshes when coloring
+      // by element type
+      unsigned int col3 = r->tetrahedra.size() ? CTX.color.mesh.tetrahedron :
+	r->prisms.size() ? CTX.color.mesh.prism : CTX.color.mesh.pyramid;
       drawArrays(m->va_triangles, GL_TRIANGLES, CTX.mesh.light, 
-		 CTX.mesh.color_carousel == 3, CTX.polygon_offset, 
-		 getColor(r, 0, CTX.color.mesh.tetrahedron));
+		 CTX.mesh.color_carousel == 3, CTX.polygon_offset, getColor(r, 0, col3));
+      unsigned int col4 = r->hexahedra.size() ? CTX.color.mesh.hexahedron :
+	r->prisms.size() ? CTX.color.mesh.prism : CTX.color.mesh.pyramid;
       drawArrays(m->va_quads, GL_QUADS, CTX.mesh.light, 
-		 CTX.mesh.color_carousel == 3, CTX.polygon_offset, 
-		 getColor(r, 0, CTX.color.mesh.hexahedron));
+		 CTX.mesh.color_carousel == 3, CTX.polygon_offset, getColor(r, 0, col4));
     }
-
+    
     if(CTX.mesh.volumes_num) {
-      const int labelStep = getLabelStep(r->tetrahedra.size() + r->hexahedra.size() + 
-					 r->prisms.size() + r->pyramids.size());
-      int labelNum = 0;
-      drawLabels(r, r->tetrahedra, labelStep, labelNum,
-		 CTX.mesh.volumes_faces || CTX.mesh.surfaces_faces, CTX.color.mesh.line);
-      drawLabels(r, r->hexahedra, labelStep, labelNum,
-		 CTX.mesh.volumes_faces || CTX.mesh.surfaces_faces, CTX.color.mesh.line);
-      drawLabels(r, r->prisms, labelStep, labelNum,
-		 CTX.mesh.volumes_faces || CTX.mesh.surfaces_faces, CTX.color.mesh.line);
-      drawLabels(r, r->pyramids, labelStep, labelNum,
-		 CTX.mesh.volumes_faces || CTX.mesh.surfaces_faces, CTX.color.mesh.line);
+      drawElementLabels(r, r->tetrahedra, CTX.mesh.volumes_faces || 
+			CTX.mesh.surfaces_faces, CTX.color.mesh.line);
+      drawElementLabels(r, r->hexahedra, CTX.mesh.volumes_faces || 
+			CTX.mesh.surfaces_faces, CTX.color.mesh.line);
+      drawElementLabels(r, r->prisms, CTX.mesh.volumes_faces || 
+			CTX.mesh.surfaces_faces, CTX.color.mesh.line);
+      drawElementLabels(r, r->pyramids, CTX.mesh.volumes_faces ||
+			CTX.mesh.surfaces_faces, CTX.color.mesh.line);
+    }
+
+    if(CTX.mesh.points || CTX.mesh.points_num){
+      if(m->allElementsVisible)
+	drawVerticesPerEntity(r);
+      else{
+	drawVerticesPerElement(r, r->tetrahedra);
+	drawVerticesPerElement(r, r->hexahedra);
+	drawVerticesPerElement(r, r->prisms);
+	drawVerticesPerElement(r, r->pyramids);
+      }
     }
 
-    if(CTX.mesh.points || CTX.mesh.points_num)
-      drawVertices(r);
-
     if(CTX.mesh.dual) {
       drawBarycentricDual(r->tetrahedra);
       drawBarycentricDual(r->hexahedra);
-- 
GitLab