diff --git a/Common/Makefile b/Common/Makefile
index 9c5c3ab1088f9774d8a02357d4565e3e33e8f352..ae9f8f2f2e74654a7cca7c8dd21bbcc0ea4af2a3 100644
--- a/Common/Makefile
+++ b/Common/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.103 2006-08-15 02:17:25 geuzaine Exp $
+# $Id: Makefile,v 1.104 2006-08-16 17:14:56 geuzaine Exp $
 #
 # Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 #
@@ -126,10 +126,10 @@ CommandLine.o: CommandLine.cpp Gmsh.h Message.h ../DataStr/Malloc.h \
   ../Geo/MVertex.h ../Geo/SPoint3.h ../Geo/GPoint.h ../Geo/GEdge.h \
   ../Geo/GEntity.h ../Geo/GVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h \
   ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/MElement.h ../Geo/MVertex.h \
-  ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/MFace.h ../Geo/MVertex.h \
-  ../Geo/SVector3.h ../Geo/GFace.h ../Geo/GPoint.h ../Geo/GEntity.h \
-  ../Geo/MElement.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
-  ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/MElement.h \
+  ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h \
+  ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/GFace.h ../Geo/GPoint.h \
+  ../Geo/GEntity.h ../Geo/MElement.h ../Geo/SPoint2.h ../Geo/SVector3.h \
+  ../Geo/Pair.h ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/MElement.h \
   ../Geo/SBoundingBox3d.h ../Common/SmoothNormals.h OS.h
 # 1 "/Users/geuzaine/.gmsh/Common//"
 OS.o: OS.cpp Message.h
@@ -145,13 +145,14 @@ Visibility.o: Visibility.cpp Visibility.h GmshDefines.h ../Geo/GVertex.h \
   ../Geo/MVertex.h ../Geo/SPoint3.h ../Geo/GPoint.h ../Geo/GEdge.h \
   ../Geo/GEntity.h ../Geo/GVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h \
   ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/MElement.h ../Geo/MVertex.h \
-  ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/MFace.h ../Geo/MVertex.h \
-  ../Geo/SVector3.h ../Numeric/Numeric.h ../Geo/GFace.h ../Geo/GPoint.h \
-  ../Geo/GEntity.h ../Geo/MElement.h ../Geo/SPoint2.h ../Geo/SVector3.h \
-  ../Geo/Pair.h ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/MElement.h \
-  ../Geo/GModel.h ../Geo/GVertex.h ../Geo/GEdge.h ../Geo/GFace.h \
-  ../Geo/GRegion.h ../Geo/SBoundingBox3d.h ../Common/SmoothNormals.h \
-  ../Parser/Parser.h ../DataStr/List.h ../DataStr/Tree.h ../DataStr/avl.h
+  ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h \
+  ../Geo/MVertex.h ../Geo/SVector3.h ../Numeric/Numeric.h ../Geo/GFace.h \
+  ../Geo/GPoint.h ../Geo/GEntity.h ../Geo/MElement.h ../Geo/SPoint2.h \
+  ../Geo/SVector3.h ../Geo/Pair.h ../Geo/GRegion.h ../Geo/GEntity.h \
+  ../Geo/MElement.h ../Geo/GModel.h ../Geo/GVertex.h ../Geo/GEdge.h \
+  ../Geo/GFace.h ../Geo/GRegion.h ../Geo/SBoundingBox3d.h \
+  ../Common/SmoothNormals.h ../Parser/Parser.h ../DataStr/List.h \
+  ../DataStr/Tree.h ../DataStr/avl.h
 # 1 "/Users/geuzaine/.gmsh/Common//"
 Trackball.o: Trackball.cpp Trackball.h
 # 1 "/Users/geuzaine/.gmsh/Common//"
diff --git a/Fltk/Makefile b/Fltk/Makefile
index 4122be215287d05aed2fec64ffc0860604abe058..f7b13b6416e5d5d702a3d27c3e39ce6cfddcc40b 100644
--- a/Fltk/Makefile
+++ b/Fltk/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.100 2006-08-15 02:17:25 geuzaine Exp $
+# $Id: Makefile,v 1.101 2006-08-16 17:14:56 geuzaine Exp $
 #
 # Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 #
@@ -87,10 +87,11 @@ Main.o: Main.cpp GUI.h Opengl_Window.h ../Mesh/Mesh.h \
   ../Geo/SPoint3.h ../Geo/GPoint.h ../Geo/GEdge.h ../Geo/GEntity.h \
   ../Geo/GVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint3.h \
   ../Geo/SPoint2.h ../Geo/MElement.h ../Geo/MVertex.h ../Geo/MEdge.h \
-  ../Geo/MVertex.h ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
-  ../Geo/GFace.h ../Geo/GPoint.h ../Geo/GEntity.h ../Geo/MElement.h \
-  ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h ../Geo/GRegion.h \
-  ../Geo/GEntity.h ../Geo/MElement.h ../Geo/SBoundingBox3d.h
+  ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h \
+  ../Geo/SVector3.h ../Geo/GFace.h ../Geo/GPoint.h ../Geo/GEntity.h \
+  ../Geo/MElement.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
+  ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/MElement.h \
+  ../Geo/SBoundingBox3d.h
 # 1 "/Users/geuzaine/.gmsh/Fltk//"
 Message.o: Message.cpp ../Common/Gmsh.h ../Common/Message.h \
   ../DataStr/Malloc.h ../DataStr/List.h ../DataStr/Tree.h \
@@ -159,12 +160,12 @@ Callbacks.o: Callbacks.cpp ../Common/Gmsh.h ../Common/Message.h \
   ../Geo/SPoint3.h ../Geo/GPoint.h ../Geo/GEdge.h ../Geo/GEntity.h \
   ../Geo/GVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint3.h \
   ../Geo/SPoint2.h ../Geo/MElement.h ../Geo/MVertex.h ../Geo/MEdge.h \
-  ../Geo/MVertex.h ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
-  ../Geo/GFace.h ../Geo/GPoint.h ../Geo/GEntity.h ../Geo/MElement.h \
-  ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h ../Geo/GRegion.h \
-  ../Geo/GEntity.h ../Geo/MElement.h Solvers.h ../Common/OS.h \
-  ../Geo/GModel.h ../Geo/GVertex.h ../Geo/GEdge.h ../Geo/GFace.h \
-  ../Geo/GRegion.h ../Geo/SBoundingBox3d.h
+  ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h \
+  ../Geo/SVector3.h ../Geo/GFace.h ../Geo/GPoint.h ../Geo/GEntity.h \
+  ../Geo/MElement.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
+  ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/MElement.h Solvers.h \
+  ../Common/OS.h ../Geo/GModel.h ../Geo/GVertex.h ../Geo/GEdge.h \
+  ../Geo/GFace.h ../Geo/GRegion.h ../Geo/SBoundingBox3d.h
 # 1 "/Users/geuzaine/.gmsh/Fltk//"
 Opengl.o: Opengl.cpp ../Common/Gmsh.h ../Common/Message.h \
   ../DataStr/Malloc.h ../DataStr/List.h ../DataStr/Tree.h \
diff --git a/Geo/MEdge.h b/Geo/MEdge.h
index 8cb94186acbda2d51c976d0e0d17658899782b8f..a704c106b272c6331e55a12ee3d95ebf49aa1ac8 100644
--- a/Geo/MEdge.h
+++ b/Geo/MEdge.h
@@ -29,22 +29,15 @@ class MEdge {
  private:
   MVertex *_v[2];
   
-  // Storing a pointer to (one of the) originating elements is a
-  // significant overhead, especially since I only use it to get a
-  // crude normal (for graphic purposes) or to know (one of) the
-  // adjacent mesh partitions. I will try to come up with something
-  // better later.
-  MElement *_element;
-  
  public:
   MEdge(MVertex *v0, MVertex *v1, MElement *e) 
-    : _element(e)
   {
     _v[0] = v0; _v[1] = v1;
   }
   inline int getNumVertices() const { return 2; }
   inline MVertex *getVertex(int i) const { return _v[i]; }
-  inline MElement *getElement() const { return _element; }
+  inline MVertex *getMinVertex() const { return std::min(_v[0], _v[1]); }
+  inline MVertex *getMaxVertex() const { return std::max(_v[0], _v[1]); }
   SVector3 tangent()
   {
     SVector3 t(_v[1]->x() - _v[0]->x(), 
diff --git a/Geo/MRep.h b/Geo/MRep.h
index 5b6d0591b1880f48dd3e0a8b48789a8a40c179b1..2497aca4b2e3b35b1a1c6cc50f51b55069f3169b 100644
--- a/Geo/MRep.h
+++ b/Geo/MRep.h
@@ -21,6 +21,7 @@
 // Please report all bugs and problems to <gmsh@geuz.org>.
 
 #include <set>
+#include <map>
 #include <algorithm>
 #include "GEdge.h"
 #include "GFace.h"
@@ -30,30 +31,65 @@
 #include "MElement.h"
 #include "VertexArray.h"
 #include "Message.h"
+#include "OS.h"
 
 class MRep {
+ protected:
+  // containedr for the edge representation (this 2x faster than
+  // std::set<MEdge, MEdgeLessThan>)
+  std::map<std::pair<MVertex*, MVertex*>, MElement*> edges;
+
+  // generates the edges from a bunch of elements
+  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);
+	std::pair<MVertex*, MVertex*> p(e.getMinVertex(), e.getMaxVertex());
+	if(!edges.count(p)) edges[p] = elements[i];
+      }
+    }
+  }
+
  public:
   MRep() : va_lines(0), va_triangles(0), va_quads(0) {}
   virtual ~MRep(){}
-  virtual void generateEdges() = 0;
-  std::set<MEdge, MEdgeLessThan> edges;
+
+  // generates the edge representation
+  virtual void generateEdgeRep() = 0;
+
+  // acces the edge representation
+  typedef std::map<std::pair<MVertex*, MVertex*>, MElement*>::const_iterator eriter;
+  eriter firstEdgeRep() { return edges.begin(); }
+  eriter lastEdgeRep() { return edges.end(); }
+  int getNumEdgeRep() { return edges.size(); }
+
+  // the vertex arrays containing full elements
   VertexArray *va_lines, *va_triangles, *va_quads;
+
+  // destroys all the vertex arrays
+  void resetArrays(){
+    if(va_lines) delete va_lines;
+    va_lines = 0;
+    if(va_triangles) delete va_triangles;
+    va_triangles = 0;
+    if(va_quads) delete va_quads;
+    va_quads = 0;
+  }
 };
 
 class MRepEdge : public MRep {
  private:
   GEdge *_e;
 
-public:
+ public:
   MRepEdge(GEdge *e) : _e(e) {}
   virtual ~MRepEdge(){}
-  virtual void generateEdges()
+  virtual void generateEdgeRep()
   {
-    if(edges.size()) return;
-    for(unsigned int i = 0; i < _e->lines.size(); i++)
-      for(int j = 0; j < _e->lines[i]->getNumEdgesRep(); j++)
-	edges.insert(_e->lines[i]->getEdgeRep(j));
-    Msg(DEBUG, "%d edges in line %d", (int)edges.size(), _e->tag());
+    MRep::generateEdgeRep(_e->lines);
   }
 };
 
@@ -64,16 +100,13 @@ class MRepFace : public MRep {
  public:
   MRepFace(GFace *f) : _f(f) {}
   virtual ~MRepFace(){}
-  virtual void generateEdges()
+  virtual void generateEdgeRep()
   {
-    if(edges.size()) return;
-    for(unsigned int i = 0; i < _f->triangles.size(); i++)
-      for(int j = 0; j < _f->triangles[i]->getNumEdgesRep(); j++)
-	edges.insert(_f->triangles[i]->getEdgeRep(j));
-    for(unsigned int i = 0; i < _f->quadrangles.size(); i++)
-      for(int j = 0; j < _f->quadrangles[i]->getNumEdgesRep(); j++)
-	edges.insert(_f->quadrangles[i]->getEdgeRep(j));
-    Msg(DEBUG, "%d edges in surface %d", (int)edges.size(), _f->tag());
+    double t = Cpu();    
+    MRep::generateEdgeRep(_f->triangles);
+    MRep::generateEdgeRep(_f->quadrangles);
+    Msg(DEBUG, "Created %d edges in surface %d (%gs)",
+	(int)edges.size(), _f->tag(), Cpu()-t);
   }
 };
 
@@ -84,22 +117,15 @@ class MRepRegion : public MRep {
  public:
   MRepRegion(GRegion *r) : _r(r) {}
   virtual ~MRepRegion(){}
-  virtual void generateEdges()
+  virtual void generateEdgeRep()
   {
-    if(edges.size()) return;
-    for(unsigned int i = 0; i < _r->tetrahedra.size(); i++)
-      for(int j = 0; j < _r->tetrahedra[i]->getNumEdgesRep(); j++)
-	edges.insert(_r->tetrahedra[i]->getEdgeRep(j));
-    for(unsigned int i = 0; i < _r->hexahedra.size(); i++)
-      for(int j = 0; j < _r->hexahedra[i]->getNumEdgesRep(); j++)
-	edges.insert(_r->hexahedra[i]->getEdgeRep(j));
-    for(unsigned int i = 0; i < _r->prisms.size(); i++)
-      for(int j = 0; j < _r->prisms[i]->getNumEdgesRep(); j++)
-	edges.insert(_r->prisms[i]->getEdgeRep(j));
-    for(unsigned int i = 0; i < _r->pyramids.size(); i++)
-      for(int j = 0; j < _r->pyramids[i]->getNumEdgesRep(); j++)
-	edges.insert(_r->pyramids[i]->getEdgeRep(j));
-    Msg(DEBUG, "%d edges in volume %d", (int)edges.size(), _r->tag());
+    double t = Cpu();    
+    MRep::generateEdgeRep(_r->tetrahedra);
+    MRep::generateEdgeRep(_r->hexahedra);
+    MRep::generateEdgeRep(_r->prisms);
+    MRep::generateEdgeRep(_r->pyramids);
+    Msg(DEBUG, "Created %d edges in volume %d (%gs)",
+	(int)edges.size(), _r->tag(), Cpu()-t);
   }
 };
 
diff --git a/Geo/Makefile b/Geo/Makefile
index 396ce352730094b1731dcf55feedaba9b7136123..17341776c2ada0bed747b2266ef4530c2da51fc7 100644
--- a/Geo/Makefile
+++ b/Geo/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.93 2006-08-15 02:17:25 geuzaine Exp $
+# $Id: Makefile,v 1.94 2006-08-16 17:14:57 geuzaine Exp $
 #
 # Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 #
@@ -126,7 +126,7 @@ GEntity.o: GEntity.cpp GEntity.h Range.h SPoint3.h SBoundingBox3d.h \
   ../Common/GmshDefines.h MRep.h GEdge.h GVertex.h MVertex.h GPoint.h \
   SVector3.h SPoint2.h MElement.h MEdge.h MFace.h ../Numeric/Numeric.h \
   GFace.h Pair.h GRegion.h ../Common/VertexArray.h ../DataStr/List.h \
-  ../Common/Message.h
+  ../Common/Message.h ../Common/OS.h ../Common/Context.h
 # 1 "/Users/geuzaine/.gmsh/Geo//"
 GVertex.o: GVertex.cpp GVertex.h GEntity.h Range.h SPoint3.h \
   SBoundingBox3d.h ../Common/GmshDefines.h MVertex.h GPoint.h
@@ -166,7 +166,7 @@ GModelIO.o: GModelIO.cpp ../Common/Message.h ../Common/GmshDefines.h \
 MVertex.o: MVertex.cpp MVertex.h SPoint3.h
 # 1 "/Users/geuzaine/.gmsh/Geo//"
 MElement.o: MElement.cpp MElement.h ../Common/GmshDefines.h MVertex.h \
-  SPoint3.h MEdge.h MFace.h SVector3.h ../Numeric/Numeric.h GEntity.h \
+  SPoint3.h MEdge.h SVector3.h MFace.h ../Numeric/Numeric.h GEntity.h \
   Range.h SBoundingBox3d.h
 # 1 "/Users/geuzaine/.gmsh/Geo//"
 gmshModel.o: gmshModel.cpp gmshModel.h GModel.h GVertex.h GEntity.h \
diff --git a/Graphics/Makefile b/Graphics/Makefile
index 00ec0d2793827e931b49def4016fd22d0af828e0..e9df4935011426e5ef8e55dcacb6598c46abcd38 100644
--- a/Graphics/Makefile
+++ b/Graphics/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.96 2006-08-15 02:17:26 geuzaine Exp $
+# $Id: Makefile,v 1.97 2006-08-16 17:14:57 geuzaine Exp $
 #
 # Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 #
@@ -86,11 +86,11 @@ Draw.o: Draw.cpp ../Common/Gmsh.h ../Common/Message.h ../DataStr/Malloc.h \
   ../Geo/SPoint3.h ../Geo/MVertex.h ../Geo/SPoint3.h ../Geo/GPoint.h \
   ../Geo/GEdge.h ../Geo/GEntity.h ../Geo/GVertex.h ../Geo/SVector3.h \
   ../Geo/SPoint3.h ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/MElement.h \
-  ../Geo/MVertex.h ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/MFace.h \
-  ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/GFace.h ../Geo/GPoint.h \
-  ../Geo/GEntity.h ../Geo/MElement.h ../Geo/SPoint2.h ../Geo/SVector3.h \
-  ../Geo/Pair.h ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/MElement.h \
-  ../Geo/SBoundingBox3d.h
+  ../Geo/MVertex.h ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/GFace.h \
+  ../Geo/GPoint.h ../Geo/GEntity.h ../Geo/MElement.h ../Geo/SPoint2.h \
+  ../Geo/SVector3.h ../Geo/Pair.h ../Geo/GRegion.h ../Geo/GEntity.h \
+  ../Geo/MElement.h ../Geo/SBoundingBox3d.h
 # 1 "/Users/geuzaine/.gmsh/Graphics//"
 Mesh.o: Mesh.cpp ../Common/Gmsh.h ../Common/Message.h ../DataStr/Malloc.h \
   ../DataStr/List.h ../DataStr/Tree.h ../DataStr/avl.h ../DataStr/Tools.h \
@@ -100,12 +100,12 @@ Mesh.o: Mesh.cpp ../Common/Gmsh.h ../Common/Message.h ../DataStr/Malloc.h \
   ../Geo/MVertex.h ../Geo/SPoint3.h ../Geo/GPoint.h ../Geo/GEdge.h \
   ../Geo/GEntity.h ../Geo/GVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h \
   ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/MElement.h ../Geo/MVertex.h \
-  ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/MFace.h ../Geo/MVertex.h \
-  ../Geo/SVector3.h ../Numeric/Numeric.h ../Geo/GFace.h ../Geo/GPoint.h \
-  ../Geo/GEntity.h ../Geo/MElement.h ../Geo/SPoint2.h ../Geo/SVector3.h \
-  ../Geo/Pair.h ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/MElement.h \
-  ../Geo/SBoundingBox3d.h ../Common/SmoothNormals.h Draw.h \
-  ../Common/Views.h ../Common/ColorTable.h ../Common/VertexArray.h \
+  ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h \
+  ../Geo/MVertex.h ../Geo/SVector3.h ../Numeric/Numeric.h ../Geo/GFace.h \
+  ../Geo/GPoint.h ../Geo/GEntity.h ../Geo/MElement.h ../Geo/SPoint2.h \
+  ../Geo/SVector3.h ../Geo/Pair.h ../Geo/GRegion.h ../Geo/GEntity.h \
+  ../Geo/MElement.h ../Geo/SBoundingBox3d.h ../Common/SmoothNormals.h \
+  Draw.h ../Common/Views.h ../Common/ColorTable.h ../Common/VertexArray.h \
   ../Common/SmoothNormals.h ../Common/GmshMatrix.h \
   ../Common/AdaptiveViews.h ../Common/GmshMatrix.h ../Common/Context.h \
   ../Geo/MRep.h ../Geo/GEdge.h ../Geo/GFace.h ../Geo/GRegion.h \
@@ -124,10 +124,11 @@ Geom.o: Geom.cpp ../Common/Gmsh.h ../Common/Message.h ../DataStr/Malloc.h \
   ../Geo/SPoint3.h ../Geo/GPoint.h ../Geo/GEdge.h ../Geo/GEntity.h \
   ../Geo/GVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint3.h \
   ../Geo/SPoint2.h ../Geo/MElement.h ../Geo/MVertex.h ../Geo/MEdge.h \
-  ../Geo/MVertex.h ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
-  ../Geo/GFace.h ../Geo/GPoint.h ../Geo/GEntity.h ../Geo/MElement.h \
-  ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h ../Geo/GRegion.h \
-  ../Geo/GEntity.h ../Geo/MElement.h ../Geo/SBoundingBox3d.h
+  ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h \
+  ../Geo/SVector3.h ../Geo/GFace.h ../Geo/GPoint.h ../Geo/GEntity.h \
+  ../Geo/MElement.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
+  ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/MElement.h \
+  ../Geo/SBoundingBox3d.h
 # 1 "/Users/geuzaine/.gmsh/Graphics//"
 Post.o: Post.cpp ../Common/Gmsh.h ../Common/Message.h ../DataStr/Malloc.h \
   ../DataStr/List.h ../DataStr/Tree.h ../DataStr/avl.h ../DataStr/Tools.h \
diff --git a/Graphics/Mesh.cpp b/Graphics/Mesh.cpp
index 0cb0a7cb2a2d636a3758ca834d82961d08cd8b45..b588fb65a478dd293e8619bca2a7207a90d83a99 100644
--- a/Graphics/Mesh.cpp
+++ b/Graphics/Mesh.cpp
@@ -1,4 +1,4 @@
-// $Id: Mesh.cpp,v 1.169 2006-08-16 05:25:22 geuzaine Exp $
+// $Id: Mesh.cpp,v 1.170 2006-08-16 17:14:57 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -245,8 +245,32 @@ static void drawBarycentricDual(std::vector<T*> &elements)
   gl2psDisable(GL2PS_LINE_STIPPLE);
 }
 
+template<class T>
+static bool allElementsVisible(std::vector<T*> &elements)
+{
+  for(unsigned int i = 0; i < elements.size(); i++)
+    if(!elements[i]->getVisibility()) return false;
+  return true;
+}
+
 // Routines for filling and drawing the vertex arrays
 
+static void addEdgesInArrays(GEntity *e, VertexArray *va, MRep *m)
+{
+  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)
+	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)]);
+    }
+  }
+}
+
 template<class T>
 static void addElementsInArrays(GEntity *e, VertexArray *va, std::vector<T*> &elements)
 {
@@ -273,6 +297,7 @@ static void addElementsInArrays(GEntity *e, VertexArray *va, std::vector<T*> &el
     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();
@@ -356,8 +381,7 @@ class drawMeshGVertex {
  public:
   void operator () (GVertex *v)
   {  
-    if(!v->getVisibility())
-      return;
+    if(!v->getVisibility()) return;
     
     if(CTX.render_mode == GMSH_SELECT) {
       glPushName(0);
@@ -380,16 +404,16 @@ class initMeshGEdge {
  public :
   void operator () (GEdge *e)
   {
-    if(!e->getVisibility())
-      return;
+    if(!e->getVisibility()) return;
+
+    if(!e->meshRep) e->meshRep = new MRepEdge(e);
 
-    if(!e->meshRep)
-      e->meshRep = new MRepEdge(e);
+    MRep *m = e->meshRep;
+    m->resetArrays();
 
     if(CTX.mesh.lines){
-      if(e->meshRep->va_lines) delete e->meshRep->va_lines;
-      e->meshRep->va_lines = new VertexArray(2, e->lines.size());
-      addElementsInArrays(e, e->meshRep->va_lines, e->lines);
+      m->va_lines = new VertexArray(2, e->lines.size());
+      addElementsInArrays(e, m->va_lines, e->lines);
     }
   }
 };
@@ -398,8 +422,7 @@ class drawMeshGEdge {
  public:
   void operator () (GEdge *e)
   {  
-    if(!e->getVisibility())
-      return;
+    if(!e->getVisibility()) return;
     
     if(CTX.render_mode == GMSH_SELECT) {
       glPushName(1);
@@ -469,60 +492,37 @@ class initMeshGFace {
  public :
   void operator () (GFace *f)
   {
-    if(!f->getVisibility())
-      return;
+    if(!f->getVisibility()) return;
 
-    if(!f->meshRep)
-      f->meshRep = new MRepFace(f);
+    if(!f->meshRep) f->meshRep = new MRepFace(f);
 
-    //bool useEdges = true;
-    bool useEdges = false;
-
-    if(CTX.mesh.explode != 1. || CTX.mesh.quality_sup || CTX.mesh.radius_sup || 
-       CTX.mesh.use_cut_plane)
-      useEdges = false;
-
-    for(unsigned int i = 0; i < f->triangles.size(); i++){
-      if(!f->triangles[i]->getVisibility()){ useEdges = false; break; }
-    }
-    for(unsigned int i = 0; i < f->quadrangles.size(); i++){
-      if(!f->quadrangles[i]->getVisibility()){ useEdges = false; break; }
-    }
-    
-    if(useEdges) f->meshRep->generateEdges();
+    MRep *m = f->meshRep;
+    m->resetArrays();
 
     // TODO: further optimizations are possible when useEdges is true:
     //
-    // 1) store the unique vertices in the vertex array and
+    // 1) store the unique vertices in the vertex array and use
     //    glDrawElements() instead of glDrawArrays().
-    // 2) we can use tc to stripe the triangles to create strips
-
-    if(useEdges && CTX.mesh.surfaces_edges){
-      if(f->meshRep->va_lines) delete f->meshRep->va_lines;
-      f->meshRep->va_lines = new VertexArray(2, f->meshRep->edges.size());
-      std::set<MEdge>::const_iterator it = f->meshRep->edges.begin();
-      for(; it != f->meshRep->edges.end(); ++it){
-	for(int i = 0; i < 2; i++){
-	  MVertex *v = it->getVertex(i);
-	  MElement *ele = it->getElement();
-	  SVector3 n = ele->getFace(0).normal();
-	  int part = ele->getPartition();
-	  if(CTX.mesh.smooth_normals)
-	    f->model()->normals->get(v->x(), v->y(), v->z(), n[0], n[1], n[2]);
-	  f->meshRep->va_lines->add(v->x(), v->y(), v->z(), n[0], n[1], n[2],
-				    CTX.color.mesh.carousel[abs(part % 20)]);
-	}
-      }
+    // 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))
+      useEdges = false;
+    
+    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);
     }
+    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);
 
-    if((!useEdges && CTX.mesh.surfaces_edges) || CTX.mesh.surfaces_faces){
-      if(f->meshRep->va_triangles) delete f->meshRep->va_triangles;
-      f->meshRep->va_triangles = new VertexArray(3, f->triangles.size());
-      addElementsInArrays(f, f->meshRep->va_triangles, f->triangles);
-
-      if(f->meshRep->va_quads) delete f->meshRep->va_quads;
-      f->meshRep->va_quads = new VertexArray(4, f->quadrangles.size());
-      addElementsInArrays(f, f->meshRep->va_quads, f->quadrangles);
+      m->va_quads = new VertexArray(4, f->quadrangles.size());
+      addElementsInArrays(f, m->va_quads, f->quadrangles);
     }
   }
 };
@@ -531,8 +531,7 @@ class drawMeshGFace {
  public:
   void operator () (GFace *f)
   {  
-    if(!f->getVisibility())
-      return;
+    if(!f->getVisibility()) return;
     
     if(CTX.render_mode == GMSH_SELECT) {
       glPushName(2);
@@ -601,10 +600,41 @@ class initMeshGRegion {
  public :
   void operator () (GRegion *r)
   {  
-    if(!r->meshRep) 
-      r->meshRep = new MRepRegion(r);
-    if(CTX.mesh.volumes_edges)
-      r->meshRep->generateEdges();
+    if(!r->getVisibility()) return;
+
+    if(!r->meshRep) r->meshRep = new MRepRegion(r);
+
+    MRep *m = r->meshRep;
+    m->resetArrays();
+
+    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))
+      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);
+    }
+    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);
+    }
   }
 };
 
@@ -612,24 +642,38 @@ class drawMeshGRegion {
  public :
   void operator () (GRegion *r)
   {  
-    if(!r->getVisibility())
-      return;
+    if(!r->getVisibility()) return;
 
     if(CTX.render_mode == GMSH_SELECT) {
       glPushName(3);
       glPushName(r->tag());
     }
 
+    MRep *m = r->meshRep;
+
     if(CTX.mesh.volumes_edges){
-      glColor4ubv((GLubyte *) & CTX.color.mesh.hexahedron);
-      glBegin(GL_LINES);
-      for(std::set<MEdge>::const_iterator it = r->meshRep->edges.begin(); 
-	  it != r->meshRep->edges.end(); ++it){
-	MVertex *v0 = it->getVertex(0), *v1 = it->getVertex(1);
-	glVertex3d(v0->x(), v0->y(), v0->z());
-	glVertex3d(v1->x(), v1->y(), v1->z());
+      if(m->va_lines && m->va_lines->n()){
+	drawArrays(m->va_lines, GL_LINES, false, 
+		   CTX.mesh.color_carousel == 3, false, 
+		   getColor(r, CTX.mesh.volumes_faces, CTX.color.mesh.line));
       }
-      glEnd();
+      else{
+	drawArrays(m->va_triangles, GL_TRIANGLES, CTX.mesh.light && CTX.mesh.light_lines,
+		   CTX.mesh.color_carousel == 3, false, 
+		   getColor(r, CTX.mesh.volumes_faces, CTX.color.mesh.line), true);
+	drawArrays(m->va_quads, GL_QUADS, CTX.mesh.light && CTX.mesh.light_lines, 
+		   CTX.mesh.color_carousel == 3, false, 
+		   getColor(r, CTX.mesh.volumes_faces, CTX.color.mesh.line), true);
+      }
+    }
+    
+    if(CTX.mesh.volumes_faces){
+      drawArrays(m->va_triangles, GL_TRIANGLES, CTX.mesh.light, 
+		 CTX.mesh.color_carousel == 3, CTX.polygon_offset, 
+		 getColor(r, 0, CTX.color.mesh.tetrahedron));
+      drawArrays(m->va_quads, GL_QUADS, CTX.mesh.light, 
+		 CTX.mesh.color_carousel == 3, CTX.polygon_offset, 
+		 getColor(r, 0, CTX.color.mesh.hexahedron));
     }
 
     if(CTX.mesh.volumes_num) {
diff --git a/Mesh/Makefile b/Mesh/Makefile
index 9128092b78a9ea9ea79e85ce2eb8b24bda0e01c4..af1c1309f46c7e881ed1fb1fa2ac80ddc2887efd 100644
--- a/Mesh/Makefile
+++ b/Mesh/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.119 2006-08-15 02:17:26 geuzaine Exp $
+# $Id: Makefile,v 1.120 2006-08-16 17:14:57 geuzaine Exp $
 #
 # Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 #
@@ -354,10 +354,11 @@ Generator.o: Generator.cpp ../Common/Gmsh.h ../Common/Message.h \
   ../Geo/SPoint3.h ../Geo/GPoint.h ../Geo/GEdge.h ../Geo/GEntity.h \
   ../Geo/GVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint3.h \
   ../Geo/SPoint2.h ../Geo/MElement.h ../Geo/MVertex.h ../Geo/MEdge.h \
-  ../Geo/MVertex.h ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
-  ../Geo/GFace.h ../Geo/GPoint.h ../Geo/GEntity.h ../Geo/MElement.h \
-  ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h ../Geo/GRegion.h \
-  ../Geo/GEntity.h ../Geo/MElement.h ../Geo/SBoundingBox3d.h
+  ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h \
+  ../Geo/SVector3.h ../Geo/GFace.h ../Geo/GPoint.h ../Geo/GEntity.h \
+  ../Geo/MElement.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
+  ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/MElement.h \
+  ../Geo/SBoundingBox3d.h
 # 1 "/Users/geuzaine/.gmsh/Mesh//"
 DiscreteSurface.o: DiscreteSurface.cpp ../Common/Gmsh.h \
   ../Common/Message.h ../DataStr/Malloc.h ../DataStr/List.h \
@@ -408,12 +409,12 @@ meshGEdge.o: meshGEdge.cpp meshGEdge.h ../Geo/GEdge.h ../Geo/GEntity.h \
   ../Geo/GEntity.h ../Geo/MVertex.h ../Geo/SPoint3.h ../Geo/GPoint.h \
   ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint3.h ../Geo/SPoint2.h \
   ../Geo/MElement.h ../Geo/MVertex.h ../Geo/MEdge.h ../Geo/MVertex.h \
-  ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h ../Numeric/Numeric.h \
-  ../Common/Gmsh.h ../Common/Message.h ../DataStr/Malloc.h \
-  ../DataStr/List.h ../DataStr/Tree.h ../DataStr/avl.h ../DataStr/Tools.h \
-  ../DataStr/List.h ../DataStr/Tree.h Utils.h Vertex.h Mesh.h Element.h \
-  Simplex.h Face.h Edge.h ../Geo/ExtrudeParams.h Metric.h Matrix.h \
-  ../Common/Context.h
+  ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Numeric/Numeric.h ../Common/Gmsh.h ../Common/Message.h \
+  ../DataStr/Malloc.h ../DataStr/List.h ../DataStr/Tree.h \
+  ../DataStr/avl.h ../DataStr/Tools.h ../DataStr/List.h ../DataStr/Tree.h \
+  Utils.h Vertex.h Mesh.h Element.h Simplex.h Face.h Edge.h \
+  ../Geo/ExtrudeParams.h Metric.h Matrix.h ../Common/Context.h
 # 1 "/Users/geuzaine/.gmsh/Mesh//"
 meshGFace.o: meshGFace.cpp meshGFace.h ../Geo/SPoint2.h ../Geo/GVertex.h \
   ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
@@ -424,10 +425,10 @@ meshGFace.o: meshGFace.cpp meshGFace.h ../Geo/SPoint2.h ../Geo/GVertex.h \
   Matrix.h ../Geo/GEdge.h ../Geo/GEntity.h ../Geo/GVertex.h \
   ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint3.h ../Geo/SPoint2.h \
   ../Geo/MElement.h ../Geo/MVertex.h ../Geo/MEdge.h ../Geo/MVertex.h \
-  ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h ../Numeric/Numeric.h \
-  ../Geo/GFace.h ../Geo/GPoint.h ../Geo/GEntity.h ../Geo/MElement.h \
-  ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h ../Common/Context.h \
-  Utils.h ../Common/Message.h BDS.h ../Common/Views.h \
+  ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Numeric/Numeric.h ../Geo/GFace.h ../Geo/GPoint.h ../Geo/GEntity.h \
+  ../Geo/MElement.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
+  ../Common/Context.h Utils.h ../Common/Message.h BDS.h ../Common/Views.h \
   ../Common/ColorTable.h ../Common/VertexArray.h \
   ../Common/SmoothNormals.h ../Common/GmshMatrix.h \
   ../Common/AdaptiveViews.h ../Common/GmshMatrix.h
diff --git a/Parser/Makefile b/Parser/Makefile
index 4a530abafc9f75699bc5e6c3fcd248096607c87c..06442544bd218fd00fdede71a930c4b3f1792365 100644
--- a/Parser/Makefile
+++ b/Parser/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.97 2006-08-15 02:17:27 geuzaine Exp $
+# $Id: Makefile,v 1.98 2006-08-16 17:14:57 geuzaine Exp $
 #
 # Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 #
@@ -116,10 +116,10 @@ OpenFile.o: OpenFile.cpp ../Common/Gmsh.h ../Common/Message.h \
   ../Geo/SPoint3.h ../Geo/GPoint.h ../Geo/GEdge.h ../Geo/GEntity.h \
   ../Geo/GVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint3.h \
   ../Geo/SPoint2.h ../Geo/MElement.h ../Geo/MVertex.h ../Geo/MEdge.h \
-  ../Geo/MVertex.h ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
-  ../Numeric/Numeric.h ../Geo/GFace.h ../Geo/GPoint.h ../Geo/GEntity.h \
-  ../Geo/MElement.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
-  ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/MElement.h \
+  ../Geo/MVertex.h ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h \
+  ../Geo/SVector3.h ../Numeric/Numeric.h ../Geo/GFace.h ../Geo/GPoint.h \
+  ../Geo/GEntity.h ../Geo/MElement.h ../Geo/SPoint2.h ../Geo/SVector3.h \
+  ../Geo/Pair.h ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/MElement.h \
   ../Geo/SBoundingBox3d.h ../Common/SmoothNormals.h ../Common/Context.h \
   Parser.h OpenFile.h ../Common/CommandLine.h ../Common/Views.h \
   ../Common/ColorTable.h ../Common/VertexArray.h \
@@ -144,16 +144,16 @@ CreateFile.o: CreateFile.cpp ../Common/Gmsh.h ../Common/Message.h \
   ../Geo/GPoint.h ../Geo/GEdge.h ../Geo/GEntity.h ../Geo/GVertex.h \
   ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint3.h ../Geo/SPoint2.h \
   ../Geo/MElement.h ../Geo/MVertex.h ../Geo/MEdge.h ../Geo/MVertex.h \
-  ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h ../Numeric/Numeric.h \
-  ../Geo/GFace.h ../Geo/GPoint.h ../Geo/GEntity.h ../Geo/MElement.h \
-  ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h ../Geo/GRegion.h \
-  ../Geo/GEntity.h ../Geo/MElement.h ../Geo/SBoundingBox3d.h \
-  ../Common/SmoothNormals.h ../Common/GmshUI.h ../Graphics/gl2ps.h \
-  ../Graphics/gl2gif.h ../Graphics/PixelBuffer.h ../Graphics/Draw.h \
-  ../Common/Views.h ../Common/ColorTable.h ../Common/VertexArray.h \
-  ../Common/SmoothNormals.h ../Common/GmshMatrix.h \
-  ../Common/AdaptiveViews.h ../Common/GmshMatrix.h ../Graphics/gl2jpeg.h \
-  ../Graphics/PixelBuffer.h ../Graphics/gl2png.h \
+  ../Geo/SVector3.h ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Numeric/Numeric.h ../Geo/GFace.h ../Geo/GPoint.h ../Geo/GEntity.h \
+  ../Geo/MElement.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
+  ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/MElement.h \
+  ../Geo/SBoundingBox3d.h ../Common/SmoothNormals.h ../Common/GmshUI.h \
+  ../Graphics/gl2ps.h ../Graphics/gl2gif.h ../Graphics/PixelBuffer.h \
+  ../Graphics/Draw.h ../Common/Views.h ../Common/ColorTable.h \
+  ../Common/VertexArray.h ../Common/SmoothNormals.h \
+  ../Common/GmshMatrix.h ../Common/AdaptiveViews.h ../Common/GmshMatrix.h \
+  ../Graphics/gl2jpeg.h ../Graphics/PixelBuffer.h ../Graphics/gl2png.h \
   ../Graphics/PixelBuffer.h ../Graphics/gl2ppm.h \
   ../Graphics/PixelBuffer.h ../Graphics/gl2yuv.h \
   ../Graphics/PixelBuffer.h