diff --git a/Common/Context.h b/Common/Context.h
index 2f71d3b91d7fdec07c3ed1d67359ef9d22816a2b..6dd1b25d6f4e462ada948468a670d4ef6acce62c 100644
--- a/Common/Context.h
+++ b/Common/Context.h
@@ -86,7 +86,6 @@ public :
   double min[3];              // x, y and z min for the current geometry 
   double max[3];              // x, y and z max for the current geometry 
   double cg[3];               // "center of mass" of the current geometry
-  double range[3];            // maximum range in the three directions 
   double lc;                  // characteristic length for the whole problem (never
                               // used in mesh generation ->only for geo/post) 
 
diff --git a/Common/Makefile b/Common/Makefile
index 8c3794da9b652a52b5c93bd2f3406f017d6fa1d8..378bea08cbe8a26caadcda03553a6f2d02cd1eee 100644
--- a/Common/Makefile
+++ b/Common/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.97 2006-08-06 22:58:47 geuzaine Exp $
+# $Id: Makefile,v 1.98 2006-08-07 19:08:11 geuzaine Exp $
 #
 # Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 #
@@ -141,7 +141,8 @@ CommandLine.o: CommandLine.cpp Gmsh.h Message.h ../DataStr/Malloc.h \
   ../Geo/SPoint3.h ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/MElement.h \
   ../Geo/MVertex.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 OS.h
+  ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/MElement.h \
+  ../Geo/SBoundingBox3d.h OS.h
 # 1 "/Users/geuzaine/.gmsh/Common//"
 OS.o: OS.cpp Message.h
 # 1 "/Users/geuzaine/.gmsh/Common//"
diff --git a/Common/Options.cpp b/Common/Options.cpp
index a6f2c9a18bececee17a3fd3ddeed8b773f2acf70..a2fe6ece0a3fa0b09e9a4938a0fac4b015001b8b 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -1,4 +1,4 @@
-// $Id: Options.cpp,v 1.284 2006-08-07 00:08:07 geuzaine Exp $
+// $Id: Options.cpp,v 1.285 2006-08-07 19:08:11 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -130,7 +130,6 @@ void Init_Options(int num)
   CTX.min[0] = CTX.min[1] = CTX.min[2] = 0.0;
   CTX.max[0] = CTX.max[1] = CTX.max[2] = 1.0;
   CTX.cg[0] = CTX.cg[1] = CTX.cg[2] = 0.0;
-  CTX.range[0] = CTX.range[1] = CTX.range[2] = 1.0;
   CTX.vxmin = CTX.vymin = CTX.vxmax = CTX.vymax = 0.;
   CTX.render_mode = GMSH_RENDER;
   CTX.pixel_equiv_x = CTX.pixel_equiv_y = 0.;
diff --git a/Common/Views.h b/Common/Views.h
index c22da3ef99204a09bd4e25ef2b9afeee52caebd7..d67b2bc2f359174bf6fa65257c15820cb681c336 100644
--- a/Common/Views.h
+++ b/Common/Views.h
@@ -212,7 +212,7 @@ void AliasView(int num, int withoptions);
 void FreeView(Post_View *v);
 bool RemoveViewByIndex(int index);
 bool RemoveViewByNumber(int num);
-void ReadView(FILE *file, char *filename);
+int ReadView(char *filename);
 void WriteView(Post_View *v, char *filename, int format, int append);
 void CopyViewOptions(Post_View *src, Post_View *dest);
 void CombineViews(int time, int how, int remove);
diff --git a/Common/ViewsIO.cpp b/Common/ViewsIO.cpp
index c7508d33f0c5162d012ada66c30371cd72103ef3..c0910bd3e87a81254c334d62db0b0169eac2ea85 100644
--- a/Common/ViewsIO.cpp
+++ b/Common/ViewsIO.cpp
@@ -1,4 +1,4 @@
-// $Id: ViewsIO.cpp,v 1.5 2006-08-07 13:57:13 geuzaine Exp $
+// $Id: ViewsIO.cpp,v 1.6 2006-08-07 19:08:11 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -33,8 +33,14 @@ void UpdateViewsInGUI();
 
 // Read view from file
 
-void ReadView(FILE *file, char *filename)
+int ReadView(char *filename)
 {
+  FILE *fp = fopen(filename, "r");
+  if(!fp){
+    Msg(GERROR, "Unable to open file '%s'", filename);
+    return 0;
+  }
+
   char str[256], name[256];
   int i, nb, format, size, testone, swap, t2l, t3l;
   double version;
@@ -43,22 +49,22 @@ void ReadView(FILE *file, char *filename)
   while(1) {
 
     do {
-      if(!fgets(str, 256, file) || feof(file))
+      if(!fgets(str, 256, fp) || feof(fp))
         break;
     } while(str[0] != '$');
 
-    if(feof(file))
+    if(feof(fp))
       break;
 
     if(!strncmp(&str[1], "PostFormat", 10)) {
-      if(!fscanf(file, "%lf %d %d\n", &version, &format, &size)){
+      if(!fscanf(fp, "%lf %d %d\n", &version, &format, &size)){
         Msg(GERROR, "Read error");
-        return;
+        return 0;
       }
       if(version < 1.0) {
         Msg(GERROR, "This post-processing file is too old (version %g < 1.0)",
             version);
-        return;
+        return 0;
       }
       if(size == sizeof(double))
         Msg(DEBUG, "Data is in double precision format (size==%d)", size);
@@ -66,7 +72,7 @@ void ReadView(FILE *file, char *filename)
         Msg(DEBUG, "Data is in single precision format (size==%d)", size);
       else {
         Msg(GERROR, "Unknown data size (%d) in post-processing file", size);
-        return;
+        return 0;
       }
       if(format == 0)
         format = LIST_FORMAT_ASCII;
@@ -74,38 +80,37 @@ void ReadView(FILE *file, char *filename)
         format = LIST_FORMAT_BINARY;
       else {
         Msg(GERROR, "Unknown format for view");
-        return;
+        return 0;
       }
     }
 
-
     if(!strncmp(&str[1], "View", 4)) {
       v = BeginView(0);
       if(version <= 1.0) {
         Msg(DEBUG, "Detected post-processing view format <= 1.0");
-        if(!fscanf(file, "%s %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
+        if(!fscanf(fp, "%s %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
 		   name, &v->NbTimeStep,
 		   &v->NbSP, &v->NbVP, &v->NbTP, &v->NbSL, &v->NbVL, &v->NbTL,
 		   &v->NbST, &v->NbVT, &v->NbTT, &v->NbSS, &v->NbVS, &v->NbTS)){
 	  Msg(GERROR, "Read error");
-	  return;
+	  return 0;
 	}
         v->NbT2 = t2l = v->NbT3 = t3l = 0;
       }
       else if(version == 1.1) {
         Msg(DEBUG, "Detected post-processing view format 1.1");
-        if(!fscanf(file,
+        if(!fscanf(fp,
 		   "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
 		   name, &v->NbTimeStep, &v->NbSP, &v->NbVP, &v->NbTP, &v->NbSL,
 		   &v->NbVL, &v->NbTL, &v->NbST, &v->NbVT, &v->NbTT, &v->NbSS,
 		   &v->NbVS, &v->NbTS, &v->NbT2, &t2l, &v->NbT3, &t3l)){
 	  Msg(GERROR, "Read error");
-	  return;
+	  return 0;
 	}
       }
       else if(version == 1.2 || version == 1.3) {
         Msg(DEBUG, "Detected post-processing view format %g", version);
-        if(!fscanf(file, "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d "
+        if(!fscanf(fp, "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d "
 		   "%d %d %d %d %d %d %d %d %d %d %d %d %d\n",
 		   name, &v->NbTimeStep,
 		   &v->NbSP, &v->NbVP, &v->NbTP, &v->NbSL, &v->NbVL, &v->NbTL,
@@ -114,12 +119,12 @@ void ReadView(FILE *file, char *filename)
 		   &v->NbSI, &v->NbVI, &v->NbTI, &v->NbSY, &v->NbVY, &v->NbTY,
 		   &v->NbT2, &t2l, &v->NbT3, &t3l)){
 	  Msg(GERROR, "Read error");
-	  return;
+	  return 0;
 	}
       }
       else if(version == 1.4) {
         Msg(DEBUG, "Detected post-processing view format 1.4");
-        if(!fscanf(file, "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d "
+        if(!fscanf(fp, "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d "
 		   "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d "
 		   "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
 		   name, &v->NbTimeStep,
@@ -132,13 +137,13 @@ void ReadView(FILE *file, char *filename)
 		   &v->NbSH2, &v->NbVH2, &v->NbTH2, &v->NbSI2, &v->NbVI2, &v->NbTI2,
 		   &v->NbSY2, &v->NbVY2, &v->NbTY2, &v->NbT2, &t2l, &v->NbT3, &t3l)){
 	  Msg(GERROR, "Read error");
-	  return;
+	  return 0;
 	}
       }
       else {
         Msg(GERROR, "Unknown post-processing file format (version %g)",
             version);
-        return;
+        return 0;
       }
 
       for(i = 0; i < (int)strlen(name); i++)
@@ -147,9 +152,9 @@ void ReadView(FILE *file, char *filename)
 
       swap = 0;
       if(format == LIST_FORMAT_BINARY) {
-        if(!fread(&testone, sizeof(int), 1, file)){
+        if(!fread(&testone, sizeof(int), 1, fp)){
 	  Msg(GERROR, "Read error");
-	  return;
+	  return 0;
 	}
         if(testone != 1) {
           Msg(INFO, "Swapping bytes from binary file");
@@ -160,12 +165,12 @@ void ReadView(FILE *file, char *filename)
       v->DataSize = size;
 
       // Time values
-      v->Time = List_CreateFromFile(v->NbTimeStep, 100, size, file, format, swap);
+      v->Time = List_CreateFromFile(v->NbTimeStep, 100, size, fp, format, swap);
 
       // Note: if nb==0, we still allocates the lists (so that they
       // are ready to be filled later, e.g. in plugins)
 
-#define LCD List_CreateFromFile(nb, 1000, size, file, format, swap)
+#define LCD List_CreateFromFile(nb, 1000, size, fp, format, swap)
 
       // Points
       nb = v->NbSP ? v->NbSP * (v->NbTimeStep * 1 + 3) : 0; v->SP = LCD;
@@ -246,19 +251,19 @@ void ReadView(FILE *file, char *filename)
 
       // 2D strings
       nb = v->NbT2 ? v->NbT2 * 4 : 0;
-      v->T2D = List_CreateFromFile(nb, 100, size, file, format, swap);
+      v->T2D = List_CreateFromFile(nb, 100, size, fp, format, swap);
       if(version <= 1.2)
-	v->T2C = List_CreateFromFileOld(t2l, 100, sizeof(char), file, format, swap);
+	v->T2C = List_CreateFromFileOld(t2l, 100, sizeof(char), fp, format, swap);
       else
-	v->T2C = List_CreateFromFile(t2l, 100, sizeof(char), file, format, swap);
+	v->T2C = List_CreateFromFile(t2l, 100, sizeof(char), fp, format, swap);
 
       // 3D strings
       nb = v->NbT3 ? v->NbT3 * 5 : 0;
-      v->T3D = List_CreateFromFile(nb, 100, size, file, format, swap);
+      v->T3D = List_CreateFromFile(nb, 100, size, fp, format, swap);
       if(version <= 1.2)
-	v->T3C = List_CreateFromFileOld(t3l, 100, sizeof(char), file, format, swap);
+	v->T3C = List_CreateFromFileOld(t3l, 100, sizeof(char), fp, format, swap);
       else
-	v->T3C = List_CreateFromFile(t3l, 100, sizeof(char), file, format, swap);
+	v->T3C = List_CreateFromFile(t3l, 100, sizeof(char), fp, format, swap);
 
       Msg(DEBUG,
           "Read View '%s' (%d TimeSteps): "
@@ -302,15 +307,17 @@ void ReadView(FILE *file, char *filename)
     }
 
     do {
-      if(!fgets(str, 256, file) || feof(file))
+      if(!fgets(str, 256, fp) || feof(fp))
         Msg(GERROR, "Prematured end of file");
     } while(str[0] != '$');
 
-  }     /* while 1 ... */
+  }
 
 #if defined(HAVE_FLTK)
   UpdateViewsInGUI();
 #endif
+
+  return 1;
 }
 
 // Write view to file in Parsed, ASCII or Binary format
diff --git a/Fltk/Makefile b/Fltk/Makefile
index 70d4643740516735034a6b690a00b8467abb4eb7..85cca8035d65608296c70ff2eac49c155157aeb8 100644
--- a/Fltk/Makefile
+++ b/Fltk/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.93 2006-08-04 14:28:01 geuzaine Exp $
+# $Id: Makefile,v 1.94 2006-08-07 19:08:11 geuzaine Exp $
 #
 # Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 #
@@ -89,7 +89,8 @@ Main.o: Main.cpp GUI.h Opengl_Window.h ../Mesh/Mesh.h ../DataStr/List.h \
   ../Geo/SPoint3.h ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/MElement.h \
   ../Geo/MVertex.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/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 \
@@ -163,7 +164,7 @@ Callbacks.o: Callbacks.cpp ../Mesh/BDS.h ../Common/Views.h \
   ../Geo/SPoint2.h ../Geo/MElement.h ../Geo/MVertex.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/MElement.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/GModel.cpp b/Geo/GModel.cpp
index 5b891496c70d8c817f39f02647922f13195d1f31..576c87e32fbe05c5533fd8227510ba26846025a3 100644
--- a/Geo/GModel.cpp
+++ b/Geo/GModel.cpp
@@ -115,3 +115,20 @@ void GModel::getPhysicalGroups(std::map<int, std::vector<GEntity*> > groups[4])
   for(riter it = firstRegion(); it != lastRegion(); ++it)
     addInGroup(*it, groups[3]);
 }
+
+SBoundingBox3d GModel::recomputeBounds()
+{
+  SBoundingBox3d bb;
+  for(viter it = firstVertex(); it != lastVertex(); ++it)
+    bb += (*it)->bounds();
+  /*
+  for(eiter it = firstEdge(); it != lastEdge(); ++it)
+    bb += (*it)->bounds();
+  for(fiter it = firstFace(); it != lastFace(); ++it)
+    bb += (*it)->bounds();
+  for(riter it = firstRegion(); it != lastRegion(); ++it)
+    bb += (*it)->bounds();
+  */
+  boundingBox = bb;
+  return bounds();
+}
diff --git a/Geo/GModel.h b/Geo/GModel.h
index 1d98c17bcd3057bbbfdbf347c0e4f50a9f3a91f3..1793db774a185831c3fe02ddd16397534ea568e8 100644
--- a/Geo/GModel.h
+++ b/Geo/GModel.h
@@ -8,12 +8,23 @@
 #include "GEdge.h"
 #include "GFace.h"
 #include "GRegion.h"
+#include "SBoundingBox3d.h"
 
 // A geometric model. The model is a non-manifold B-Rep.
 
 class GModel  
 {
-public:
+ protected:
+  std::string modelName;
+  std::set<GRegion*, EntityLessThan> regions;
+  std::set<GFace*, EntityLessThan> faces;
+  std::set<GEdge*, EntityLessThan> edges;
+  std::set<GVertex*, EntityLessThan> vertices;
+  // stored bounding box
+  SBoundingBox3d boundingBox;
+
+ public:
+  GModel(const std::string &name) : modelName(name){}
   virtual ~GModel() {}
 
   typedef std::set<GRegion*, EntityLessThan>::iterator riter;
@@ -65,22 +76,19 @@ public:
   // Returns all physical groups (one map per dimension: 0-D to 3-D)
   void getPhysicalGroups(std::map<int, std::vector<GEntity*> > groups[4]);
 
+  // The bounding box
+  virtual SBoundingBox3d bounds(){ return boundingBox; }
+  virtual SBoundingBox3d recomputeBounds();
+
   // IO routines
   int readMSH(const std::string &name);
   int writeMSH(const std::string &name, double version=1.0, bool saveAll=false,
 	       double scalingFactor=1.0);
   int writePOS(const std::string &name, double scalingFactor=1.0);
+  int readSTL(const std::string &name, double tolerance=1.e-3);
   int writeSTL(const std::string &name, double scalingFactor=1.0);
   int writeVRML(const std::string &name, double scalingFactor=1.0);
   int writeUNV(const std::string &name, double scalingFactor=1.0);
-
-protected:
-  std::string modelName;
-  GModel(const std::string &name):modelName(name){}
-  std::set<GRegion*, EntityLessThan> regions;
-  std::set<GFace*, EntityLessThan> faces;
-  std::set<GEdge*, EntityLessThan> edges;
-  std::set<GVertex*, EntityLessThan> vertices;
 };
 
 #endif
diff --git a/Geo/GModelIO.cpp b/Geo/GModelIO.cpp
index 9ba813951a29ce761be2e40e91dfb80e38e8bebf..96b66bc155dc42113f6d47ed0238fd0d1723cf0e 100644
--- a/Geo/GModelIO.cpp
+++ b/Geo/GModelIO.cpp
@@ -7,6 +7,7 @@
 #include "gmshFace.h"
 #include "gmshEdge.h"
 #include "MElement.h"
+#include "SBoundingBox3d.h"
 
 static int getNumVerticesForElementTypeMSH(int type)
 {
@@ -123,6 +124,7 @@ int GModel::readMSH(const std::string &name)
   int elementTypes[7] = {LGN1, TRI1, QUA1, TET1, HEX1, PRI1, PYR1};
   double version = 1.0;
   char str[256];
+  SBoundingBox3d bbox;
   std::map<int, MVertex*> vertices;
   std::map<int, std::vector<MVertex*> > points;
   std::map<int, std::vector<MElement*> > elements[7];
@@ -155,6 +157,7 @@ int GModel::readMSH(const std::string &name)
 	int num;
 	double x, y, z;
         fscanf(fp, "%d %lf %lf %lf", &num, &x, &y, &z);
+	bbox += SPoint3(x, y, z);
 	if(vertices.count(num))
 	  Msg(WARNING, "Skipping duplicate vertex %d", num);
 	else
@@ -337,6 +340,8 @@ int GModel::readMSH(const std::string &name)
   for(int i = 0; i < 4; i++)  
     storePhysicalTagsInEntities(this, i, physicals[i]);
 
+  boundingBox += bbox;
+
   fclose(fp);
   return 1;
 }
@@ -509,6 +514,133 @@ int GModel::writePOS(const std::string &name, double scalingFactor)
   return 1;
 }
 
+static void swapBytes(char *array, int size, int n)
+{
+  char *x = new char[size];
+  for(int i = 0; i < n; i++) {
+    char *a = &array[i * size];
+    memcpy(x, a, size);
+    for(int c = 0; c < size; c++)
+      a[size - 1 - c] = x[c];
+  }
+  delete [] x;
+}
+
+int GModel::readSTL(const std::string &name, double tolerance)
+{
+  FILE *fp = fopen(name.c_str(), "rb");
+  if(!fp){
+    Msg(GERROR, "Unable to open file '%s'", name.c_str());
+    return 0;
+  }
+
+  // read all facets and store triplets of points
+  std::vector<SPoint3> points;
+  SBoundingBox3d bbox;
+
+  // "solid" or binary data header
+  char buffer[256];
+  fgets(buffer, sizeof(buffer), fp);
+
+  if(!strncmp(buffer, "solid", 5)) { 
+    // ASCII STL
+    while(!feof(fp)) {
+      // "facet normal x y z" or "endsolid"
+      if(!fgets(buffer, sizeof(buffer), fp)) break;
+      if(!strncmp(buffer, "endsolid", 8)) break;
+      char s1[256], s2[256];
+      float x, y, z;
+      sscanf(buffer, "%s %s %f %f %f", s1, s2, &x, &y, &z);
+      // "outer loop"
+      if(!fgets(buffer, sizeof(buffer), fp)) break;
+      // "vertex x y z"
+      for(int i = 0; i < 3; i++){
+	if(!fgets(buffer, sizeof(buffer), fp)) break;
+	sscanf(buffer, "%s %f %f %f", s1, &x, &y, &z);
+	SPoint3 p(x, y, z);
+	points.push_back(p);
+	bbox += p;
+      }
+      // "endloop"
+      if(!fgets(buffer, sizeof(buffer), fp)) break;
+      // "endfacet"
+      if(!fgets(buffer, sizeof(buffer), fp)) break;
+    }
+  }
+  else{
+    // Binary STL
+    rewind(fp);
+    char header[80];
+    if(fread(header, sizeof(char), 80, fp)){
+      unsigned int nfacets = 0;
+      size_t ret = fread(&nfacets, sizeof(unsigned int), 1, fp);
+      bool swap = false;
+      if(nfacets > 10000000){
+	Msg(INFO, "Swapping bytes from binary file");
+	swap = true;
+	swapBytes((char*)&nfacets, sizeof(unsigned int), 1);
+      }
+      if(ret && nfacets){
+	char *data = new char[nfacets * 50 * sizeof(char)];
+	ret = fread(data, sizeof(char), nfacets * 50, fp);
+	if(ret == nfacets * 50){
+	  for(unsigned int i = 0; i < nfacets; i++) {
+	    float *xyz = (float *)&data[i * 50 * sizeof(char)];
+	    if(swap) swapBytes((char*)xyz, sizeof(float), 12);
+	    for(int j = 0; j < 3; j++){
+	      SPoint3 p(xyz[3 + 3 * j], xyz[3 + 3 * j + 1], xyz[3 + 3 * j + 2]);
+	      points.push_back(p);
+	      bbox += p;
+	    }
+	  }
+	}
+	delete data;
+      }
+    }
+  }
+
+  if(!points.size() || points.size() % 3){
+    Msg(GERROR, "Wrong number of points in STL");
+    return 0;
+  }
+
+  Msg(INFO, "%d facets", points.size() / 3);
+
+  // create face
+  GFace *face = new gmshFace(this, numFace() + 1);
+  add(face);
+
+  // create (unique) vertices and triangles
+  SPoint3 min = bbox.min();
+  SPoint3 max = bbox.max();
+  double dx = max.x() - min.x(), dy = max.y() - min.y(), dz = max.z() - min.z();
+  double lc = sqrt(dx * dx + dy * dy + dz * dz);
+  MVertexLessThanLexicographic::tolerance = lc * tolerance;
+  std::set<MVertex*, MVertexLessThanLexicographic> vertices;
+  for(unsigned int i = 0; i < points.size(); i += 3){
+    MVertex *v[3];
+    for(int j = 0; j < 3; j++){
+      double x = points[i + j].x(), y = points[i + j].y(), z = points[i + j].z();
+      MVertex w(x, y, z);
+      std::set<MVertex*, MVertexLessThanLexicographic>::iterator it = vertices.find(&w);
+      if(it != vertices.end()) {
+        v[j] = *it;
+      }
+      else {
+        v[j] = new MVertex(x, y, z);
+	vertices.insert(v[j]);
+	face->mesh_vertices.push_back(v[j]);
+      }
+    }
+    face->triangles.push_back(new MTriangle(v[0], v[1], v[2]));
+  }
+
+  boundingBox += bbox;
+
+  fclose(fp);
+  return 1;
+}
+
 int GModel::writeSTL(const std::string &name, double scalingFactor)
 {
   FILE *fp = fopen(name.c_str(), "w");
diff --git a/Geo/GVertex.h b/Geo/GVertex.h
index 80d87875541fd28f8a446f7883ca232ee87556bd..79c5d14559ce9878cc3928fae3b68984b83f6065 100644
--- a/Geo/GVertex.h
+++ b/Geo/GVertex.h
@@ -26,6 +26,7 @@ public:
   virtual int dim() const {return 0;}
   virtual GeomType geomType() const {return Point;}
   virtual double prescribedMeshSizeAtVertex() const {return 0;}
+  virtual SBoundingBox3d bounds(){ return SBoundingBox3d(SPoint3(x(), y(), z())); }
   virtual std::string getAdditionalInfoString()
   {
     char str[256];
diff --git a/Geo/MVertex.cpp b/Geo/MVertex.cpp
index 32a44fed3f58b05647ec85f387f178de2eb030e8..d900baf5879d57edd7a77dfa65bb9bf8ab41cf98 100644
--- a/Geo/MVertex.cpp
+++ b/Geo/MVertex.cpp
@@ -2,6 +2,7 @@
 #include "MVertex.h"
 
 int MVertex::_globalNum = 0;
+double MVertexLessThanLexicographic::tolerance = 1.e-6;
 
 void MVertex::writeMSH(FILE *fp, double scalingFactor)
 {
diff --git a/Geo/MVertex.h b/Geo/MVertex.h
index 4510bad51ef1e6253d0e7ea9b45f1ed97371a34f..b732f779a1ebaa4904185b518afd132d2a50f3a7 100644
--- a/Geo/MVertex.h
+++ b/Geo/MVertex.h
@@ -65,4 +65,18 @@ class MFaceVertex : public MVertex{
   ~MFaceVertex(){}
 };
 
+class MVertexLessThanLexicographic{
+ public:
+  static double tolerance;
+  bool operator()(const MVertex *v1, const MVertex *v2) const
+  {
+    if(v1->x() - v2->x() >  tolerance) return true;
+    if(v1->x() - v2->x() < -tolerance) return false;
+    if(v1->y() - v2->y() >  tolerance) return true;
+    if(v1->y() - v2->y() < -tolerance) return false;
+    if(v1->z() - v2->z() >  tolerance) return true;
+    return false;
+  }
+};
+
 #endif
diff --git a/Geo/Makefile b/Geo/Makefile
index 078d396bf595c9a7e0c5adbc0e7dedb363e3adc5..1d477dfe6bd3807fb2aedfb35b40c7480f850ec8 100644
--- a/Geo/Makefile
+++ b/Geo/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.83 2006-08-07 00:08:08 geuzaine Exp $
+# $Id: Makefile,v 1.84 2006-08-07 19:08:11 geuzaine Exp $
 #
 # Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 #
@@ -34,7 +34,6 @@ endif
 
 
 SRC = CAD.cpp \
-      MinMax.cpp \
       ExtrudeParams.cpp \
       Geo.cpp \
       GeoUtils.cpp \
@@ -92,11 +91,6 @@ CAD.o: CAD.cpp ../Common/Gmsh.h ../Common/Message.h ../DataStr/Malloc.h \
   ../Mesh/Create.h ../Mesh/Vertex.h ../Mesh/Mesh.h CAD.h ExtrudeParams.h \
   ../Common/Visibility.h ../Common/Context.h
 # 1 "/Users/geuzaine/.gmsh/Geo//"
-MinMax.o: MinMax.cpp ../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 \
-  ../Numeric/Numeric.h ../Mesh/Vertex.h ../Common/Context.h
-# 1 "/Users/geuzaine/.gmsh/Geo//"
 ExtrudeParams.o: ExtrudeParams.cpp ../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 \
@@ -196,7 +190,8 @@ gmshEdge.o: gmshEdge.cpp gmshModel.h GModel.h GVertex.h GEntity.h Range.h \
   ../Common/SmoothNormals.h ../Mesh/Metric.h ../Mesh/Vertex.h \
   ../Mesh/Simplex.h ../Mesh/Mesh.h ../Mesh/Matrix.h \
   ../Mesh/Interpolation.h ../Mesh/Vertex.h ../Mesh/Mesh.h CAD.h \
-  ExtrudeParams.h Geo.h ../Common/Context.h
+  ExtrudeParams.h Geo.h ../Mesh/Create.h ../Mesh/Vertex.h ../Mesh/Mesh.h \
+  ../Common/Context.h
 # 1 "/Users/geuzaine/.gmsh/Geo//"
 gmshFace.o: gmshFace.cpp gmshModel.h GModel.h GVertex.h GEntity.h Range.h \
   SPoint3.h SBoundingBox3d.h MVertex.h ../Common/GmshDefines.h GPoint.h \
@@ -210,7 +205,8 @@ gmshFace.o: gmshFace.cpp gmshModel.h GModel.h GVertex.h GEntity.h Range.h \
   ../Common/SmoothNormals.h ../Mesh/Metric.h ../Mesh/Vertex.h \
   ../Mesh/Simplex.h ../Mesh/Mesh.h ../Mesh/Matrix.h gmshFace.h \
   ../Mesh/Interpolation.h ../Mesh/Vertex.h ../Mesh/Mesh.h CAD.h \
-  ExtrudeParams.h Geo.h ../Mesh/Utils.h ../Mesh/Vertex.h ../Mesh/Mesh.h
+  ExtrudeParams.h Geo.h ../Mesh/Create.h ../Mesh/Vertex.h ../Mesh/Mesh.h \
+  ../Mesh/Utils.h ../Mesh/Vertex.h ../Mesh/Mesh.h
 # 1 "/Users/geuzaine/.gmsh/Geo//"
 gmshRegion.o: gmshRegion.cpp gmshModel.h GModel.h GVertex.h GEntity.h \
   Range.h SPoint3.h SBoundingBox3d.h MVertex.h ../Common/GmshDefines.h \
@@ -224,7 +220,8 @@ gmshRegion.o: gmshRegion.cpp gmshModel.h GModel.h GVertex.h GEntity.h \
   ../Common/SmoothNormals.h ../Mesh/Metric.h ../Mesh/Vertex.h \
   ../Mesh/Simplex.h ../Mesh/Mesh.h ../Mesh/Matrix.h gmshFace.h \
   gmshRegion.h ../Mesh/Interpolation.h ../Mesh/Vertex.h ../Mesh/Mesh.h \
-  CAD.h ExtrudeParams.h Geo.h
+  CAD.h ExtrudeParams.h Geo.h ../Mesh/Create.h ../Mesh/Vertex.h \
+  ../Mesh/Mesh.h ../Mesh/Utils.h ../Mesh/Vertex.h ../Mesh/Mesh.h
 # 1 "/Users/geuzaine/.gmsh/Geo//"
 SVector3.o: SVector3.cpp SVector3.h SPoint3.h
 # 1 "/Users/geuzaine/.gmsh/Geo//"
diff --git a/Geo/MinMax.cpp b/Geo/MinMax.cpp
deleted file mode 100644
index 5207250a8fd0d62b59e684bc1f420d51c80232b4..0000000000000000000000000000000000000000
--- a/Geo/MinMax.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-// $Id: MinMax.cpp,v 1.21 2006-01-06 00:34:24 geuzaine Exp $
-//
-// Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-// USA.
-// 
-// Please report all bugs and problems to <gmsh@geuz.org>.
-
-#include "Gmsh.h"
-#include "Numeric.h"
-#include "Vertex.h"
-#include "Context.h"
-
-extern Context_T CTX;
-
-static void minmax(void *a, void *b)
-{
-  Vertex *v = *(Vertex **) a;
-  CTX.min[0] = (CTX.min[0] < v->Pos.X) ? CTX.min[0] : v->Pos.X;
-  CTX.max[0] = (CTX.max[0] > v->Pos.X) ? CTX.max[0] : v->Pos.X;
-  CTX.min[1] = (CTX.min[1] < v->Pos.Y) ? CTX.min[1] : v->Pos.Y;
-  CTX.max[1] = (CTX.max[1] > v->Pos.Y) ? CTX.max[1] : v->Pos.Y;
-  CTX.min[2] = (CTX.min[2] < v->Pos.Z) ? CTX.min[2] : v->Pos.Z;
-  CTX.max[2] = (CTX.max[2] > v->Pos.Z) ? CTX.max[2] : v->Pos.Z;
-
-  CTX.cg[0] += v->Pos.X;
-  CTX.cg[1] += v->Pos.Y;
-  CTX.cg[2] += v->Pos.Z;
-}
-
-void CalculateMinMax(Tree_T * t, double *bbox)
-{
-  CTX.cg[0] = 0.0;
-  CTX.cg[1] = 0.0;
-  CTX.cg[2] = 0.0;
-
-  if(!Tree_Nbr(t)) {
-    if(!bbox || (bbox[0] > bbox[1])) {  //the bbox is wrong
-      CTX.min[0] = CTX.min[1] = CTX.min[2] = -1.;
-      CTX.max[0] = CTX.max[1] = CTX.max[2] = 1.;
-      CTX.range[0] = CTX.range[1] = CTX.range[2] = 0.;
-      CTX.lc = 1.;
-      return;
-    }
-    else {
-      CTX.min[0] = bbox[0];
-      CTX.max[0] = bbox[1];
-      CTX.min[1] = bbox[2];
-      CTX.max[1] = bbox[3];
-      CTX.min[2] = bbox[4];
-      CTX.max[2] = bbox[5];
-
-      CTX.cg[0] = (CTX.min[0] + CTX.max[0])/2.;
-      CTX.cg[1] = (CTX.min[1] + CTX.max[1])/2.;
-      CTX.cg[2] = (CTX.min[2] + CTX.max[2])/2.;
-    }
-  }
-  else {
-    Vertex *v;
-    Tree_Right(t, &v);
-    CTX.min[0] = CTX.max[0] = v->Pos.X;
-    CTX.min[1] = CTX.max[1] = v->Pos.Y;
-    CTX.min[2] = CTX.max[2] = v->Pos.Z;
-    Tree_Action(t, minmax);
-    int nb = Tree_Nbr(t);
-    CTX.cg[0] /= nb;
-    CTX.cg[1] /= nb;
-    CTX.cg[2] /= nb;
-  }
-
-  CTX.range[0] = CTX.max[0] - CTX.min[0];
-  CTX.range[1] = CTX.max[1] - CTX.min[1];
-  CTX.range[2] = CTX.max[2] - CTX.min[2];
-
-  if(CTX.range[0] == 0. && CTX.range[1] == 0. && CTX.range[2] == 0.) {
-    CTX.min[0] -= 1.;
-    CTX.min[1] -= 1.;
-    CTX.max[0] += 1.;
-    CTX.max[1] += 1.;
-    CTX.lc = 1.;
-  }
-  else if(CTX.range[0] == 0. && CTX.range[1] == 0.) {
-    CTX.lc = CTX.range[2];
-    CTX.min[0] -= CTX.lc;
-    CTX.min[1] -= CTX.lc;
-    CTX.max[0] += CTX.lc;
-    CTX.max[1] += CTX.lc;
-  }
-  else if(CTX.range[0] == 0. && CTX.range[2] == 0.) {
-    CTX.lc = CTX.range[1];
-    CTX.min[0] -= CTX.lc;
-    CTX.max[0] += CTX.lc;
-  }
-  else if(CTX.range[1] == 0. && CTX.range[2] == 0.) {
-    CTX.lc = CTX.range[0];
-    CTX.min[1] -= CTX.lc;
-    CTX.max[1] += CTX.lc;
-  }
-  else if(CTX.range[0] == 0.) {
-    CTX.lc = sqrt(DSQR(CTX.range[1]) + DSQR(CTX.range[2]));
-    CTX.min[0] -= CTX.lc;
-    CTX.max[0] += CTX.lc;
-  }
-  else if(CTX.range[1] == 0.) {
-    CTX.lc = sqrt(DSQR(CTX.range[0]) + DSQR(CTX.range[2]));
-    CTX.min[1] -= CTX.lc;
-    CTX.max[1] += CTX.lc;
-  }
-  else if(CTX.range[2] == 0.) {
-    CTX.lc = sqrt(DSQR(CTX.range[0]) + DSQR(CTX.range[1]));
-  }
-  else {
-    CTX.lc = sqrt(DSQR(CTX.range[0]) + DSQR(CTX.range[1]) + DSQR(CTX.range[2]));
-  }
-
-}
diff --git a/Geo/MinMax.h b/Geo/MinMax.h
deleted file mode 100644
index b0bfd63b00fbbcc89c1d51cf6e89675d0542ecde..0000000000000000000000000000000000000000
--- a/Geo/MinMax.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef _MINMAX_H_
-#define _MINMAX_H_
-
-// Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-// USA.
-// 
-// Please report all bugs and problems to <gmsh@geuz.org>.
-
-#include "Tree.h"
-
-void CalculateMinMax (Tree_T *t, double *bbox);
-
-#endif
diff --git a/Geo/SBoundingBox3d.cpp b/Geo/SBoundingBox3d.cpp
index 9b24a972d5e691b040c5fed3a11ce5d3a68be50a..9dbbb116ed8efba65692cb84859c516d992f2e19 100644
--- a/Geo/SBoundingBox3d.cpp
+++ b/Geo/SBoundingBox3d.cpp
@@ -8,6 +8,15 @@ SBoundingBox3d::SBoundingBox3d()
 SBoundingBox3d::SBoundingBox3d(const SPoint3 & pt)
 : MinPt(pt), MaxPt(pt)
 {}
+
+bool SBoundingBox3d::empty()
+{
+  if(MinPt.x() == DBL_MAX || MinPt.y() == DBL_MAX || MinPt.z() == DBL_MAX ||
+     MaxPt.x() == -DBL_MAX || MaxPt.y() == -DBL_MAX || MaxPt.z() == -DBL_MAX) 
+    return true;
+  return false;
+}
+
 void SBoundingBox3d::operator+=(const SPoint3 &pt)
 // note: it is possible for pt[i] to be both > MaxPt[i] and < MinPt[i]
 // the first point always will be both
@@ -26,7 +35,6 @@ void SBoundingBox3d::operator+=(const SPoint3 &pt)
     MinPt[2] = pt[2];
   if (pt[2] > MaxPt[2])
     MaxPt[2] = pt[2];
-
 }
 
 void SBoundingBox3d::operator+=(const SBoundingBox3d &box)
@@ -53,7 +61,6 @@ void SBoundingBox3d::operator*=(double scale)
   MinPt *= scale;
   MaxPt += center;
   MinPt += center;
-
 }
 
 void SBoundingBox3d::scale(double sx, double sy, double sz)
@@ -80,5 +87,4 @@ void SBoundingBox3d::makeCube()
     scales[j] = max/len[j];
 
   scale(scales[0],scales[1],scales[2]);
-  
 }
diff --git a/Geo/SBoundingBox3d.h b/Geo/SBoundingBox3d.h
index 43cf47177c6e3e8b57dd5edadbe75a32c80e5cc4..44b96bcd10810bd623201287174ecd8ebef3a2e2 100644
--- a/Geo/SBoundingBox3d.h
+++ b/Geo/SBoundingBox3d.h
@@ -9,6 +9,7 @@ class SBoundingBox3d {
  public:
   SBoundingBox3d();
   SBoundingBox3d(const SPoint3 &);
+  bool empty();
   void operator+=(const SPoint3 &pt);
   void operator+=(const SBoundingBox3d &pt);
   void operator*=(double scale);
diff --git a/Graphics/Makefile b/Graphics/Makefile
index 7b6d0f7b9bc1f68d820a66abafaa24ac1f800158..cfdb4b01e31c2f4397bdd1ad43805e147bba1e1c 100644
--- a/Graphics/Makefile
+++ b/Graphics/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.87 2006-08-07 00:08:08 geuzaine Exp $
+# $Id: Makefile,v 1.88 2006-08-07 19:08:12 geuzaine Exp $
 #
 # Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 #
@@ -90,7 +90,8 @@ Draw.o: Draw.cpp ../Common/Gmsh.h ../Common/Message.h ../DataStr/Malloc.h \
   ../Geo/SPoint3.h ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/MElement.h \
   ../Geo/MVertex.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/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 \
@@ -102,11 +103,11 @@ Mesh.o: Mesh.cpp ../Common/Gmsh.h ../Common/Message.h ../DataStr/Malloc.h \
   ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/MElement.h ../Geo/MVertex.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 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 \
-  gl2ps.h
+  ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/MElement.h \
+  ../Geo/SBoundingBox3d.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 gl2ps.h
 # 1 "/Users/geuzaine/.gmsh/Graphics//"
 Geom.o: Geom.cpp ../Common/Gmsh.h ../Common/Message.h ../DataStr/Malloc.h \
   ../DataStr/List.h ../DataStr/Tree.h ../DataStr/avl.h ../DataStr/Tools.h \
@@ -123,7 +124,7 @@ Geom.o: Geom.cpp ../Common/Gmsh.h ../Common/Message.h ../DataStr/Malloc.h \
   ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/MElement.h ../Geo/MVertex.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/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 \
@@ -238,11 +239,11 @@ CreateFile.o: CreateFile.cpp ../Common/Gmsh.h ../Common/Message.h \
   ../Geo/SPoint2.h ../Geo/MElement.h ../Geo/MVertex.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 gl2ps.h gl2gif.h PixelBuffer.h Draw.h \
-  ../Common/Views.h ../Common/ColorTable.h ../Common/VertexArray.h \
-  ../Common/SmoothNormals.h ../Common/GmshMatrix.h \
-  ../Common/AdaptiveViews.h ../Common/GmshMatrix.h gl2jpeg.h gl2png.h \
-  gl2ppm.h gl2yuv.h
+  ../Geo/MElement.h ../Geo/SBoundingBox3d.h gl2ps.h gl2gif.h \
+  PixelBuffer.h Draw.h ../Common/Views.h ../Common/ColorTable.h \
+  ../Common/VertexArray.h ../Common/SmoothNormals.h \
+  ../Common/GmshMatrix.h ../Common/AdaptiveViews.h ../Common/GmshMatrix.h \
+  gl2jpeg.h gl2png.h gl2ppm.h gl2yuv.h
 # 1 "/Users/geuzaine/.gmsh/Graphics//"
 gl2ps.o: gl2ps.cpp gl2ps.h
 # 1 "/Users/geuzaine/.gmsh/Graphics//"
diff --git a/Graphics/ReadImg.cpp b/Graphics/ReadImg.cpp
index 9ec28628d3d95d054517cc87ba9afb4c9f5caf01..edb531ca6e24827554bf4f4c3cdf23e5df94961f 100644
--- a/Graphics/ReadImg.cpp
+++ b/Graphics/ReadImg.cpp
@@ -1,4 +1,4 @@
-// $Id: ReadImg.cpp,v 1.15 2006-01-28 23:01:15 geuzaine Exp $
+// $Id: ReadImg.cpp,v 1.16 2006-08-07 19:08:12 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -97,9 +97,9 @@ static Post_View *Img2Pos(Fl_RGB_Image & img_init, int quads=1,
   return v;
 }
 
-static void EndPos(char *name, Post_View *v)
+static int EndPos(char *name, Post_View *v)
 {
-  if(!v) return;
+  if(!v) return 0;
   char name_pos[256], title[256];
   strcpy(name_pos, name);
   strcat(name_pos, ".pos");
@@ -113,34 +113,29 @@ static void EndPos(char *name, Post_View *v)
   else
     strcpy(title, &name[i+1]);
   EndView(v, 1, name_pos, title);
-  Msg(INFO, "Read file '%s'", name);
-  Msg(STATUS2N, "Read '%s'", name);
+  return 1;
 }
 
-void read_pnm(char *name) 
+int read_pnm(char *name) 
 {
-  Msg(INFO, "Reading PNM file '%s'", name);
   Fl_PNM_Image img(name);
-  EndPos(name, Img2Pos(img));
+  return EndPos(name, Img2Pos(img));
 }
 
-void read_jpeg(char *name) 
+int read_jpeg(char *name) 
 {
-  Msg(INFO, "Reading JPEG file '%s'", name);
   Fl_JPEG_Image img(name);
-  EndPos(name, Img2Pos(img));
+  return EndPos(name, Img2Pos(img));
 }
 
-void read_png(char *name) 
+int read_png(char *name) 
 {
-  Msg(INFO, "Reading PNG file '%s'", name);
   Fl_PNG_Image img(name);
-  EndPos(name, Img2Pos(img));
+  return EndPos(name, Img2Pos(img));
 }
 
-void read_bmp(char *name) 
+int read_bmp(char *name) 
 {
-  Msg(INFO, "Reading BMP file '%s'", name);
   Fl_BMP_Image img(name);
-  EndPos(name, Img2Pos(img));
+  return EndPos(name, Img2Pos(img));
 }
diff --git a/Graphics/ReadImg.h b/Graphics/ReadImg.h
index e7635e744cf9e1e346685e3eda79ca0f38cf6c7a..c5d8769891144b2acafab11ee0a5006602c88b0a 100644
--- a/Graphics/ReadImg.h
+++ b/Graphics/ReadImg.h
@@ -20,9 +20,9 @@
 // 
 // Please report all bugs and problems to <gmsh@geuz.org>.
 
-void read_pnm(char *name);
-void read_jpeg(char *name);
-void read_png(char *name);
-void read_bmp(char *name);
+int read_pnm(char *name);
+int read_jpeg(char *name);
+int read_png(char *name);
+int read_bmp(char *name);
 
 #endif
diff --git a/Mesh/Makefile b/Mesh/Makefile
index 5a859f62d25fd313e60b3781a6d0740693e95481..815fea0e2cd02c2047c13518725e0c95db63b6dc 100644
--- a/Mesh/Makefile
+++ b/Mesh/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.113 2006-08-07 00:08:08 geuzaine Exp $
+# $Id: Makefile,v 1.114 2006-08-07 19:08:12 geuzaine Exp $
 #
 # Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 #
@@ -390,7 +390,7 @@ Generator.o: Generator.cpp BDS.h ../Common/Views.h ../Common/ColorTable.h \
   ../Geo/SPoint2.h ../Geo/MElement.h ../Geo/MVertex.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/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 \
diff --git a/Parser/Gmsh.tab.cpp b/Parser/Gmsh.tab.cpp
index 8826bed89888690212434ad50948d877c2697aac..39ebf5f1736211a599b5774796540b428f1e7b06 100644
--- a/Parser/Gmsh.tab.cpp
+++ b/Parser/Gmsh.tab.cpp
@@ -126,7 +126,7 @@
 
 #line 1 "Gmsh.y"
 
-// $Id: Gmsh.tab.cpp,v 1.270 2006-08-07 13:57:14 geuzaine Exp $
+// $Id: Gmsh.tab.cpp,v 1.271 2006-08-07 19:08:12 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -523,27 +523,27 @@ static const short yyrline[] = { 0,
   1477,  1493,  1513,  1530,  1547,  1567,  1573,  1578,  1583,  1590,
   1592,  1593,  1596,  1601,  1605,  1621,  1637,  1653,  1673,  1688,
   1694,  1700,  1711,  1721,  1731,  1745,  1763,  1777,  1786,  1792,
-  1803,  1816,  1861,  1876,  1887,  1906,  1916,  1938,  1942,  1947,
-  1952,  1962,  1979,  1995,  2021,  2048,  2080,  2087,  2092,  2098,
-  2102,  2110,  2119,  2127,  2135,  2140,  2148,  2153,  2161,  2166,
-  2176,  2183,  2190,  2197,  2204,  2211,  2218,  2225,  2232,  2239,
-  2244,  2251,  2256,  2263,  2268,  2275,  2280,  2287,  2292,  2299,
-  2304,  2311,  2316,  2323,  2328,  2335,  2340,  2350,  2354,  2359,
-  2386,  2410,  2418,  2437,  2455,  2473,  2502,  2537,  2564,  2591,
-  2605,  2623,  2628,  2637,  2639,  2640,  2641,  2642,  2643,  2644,
-  2645,  2646,  2653,  2654,  2655,  2656,  2657,  2658,  2659,  2660,
-  2661,  2662,  2663,  2664,  2665,  2666,  2667,  2668,  2669,  2670,
-  2671,  2672,  2673,  2674,  2675,  2676,  2677,  2678,  2679,  2680,
-  2681,  2682,  2683,  2684,  2686,  2687,  2688,  2689,  2690,  2691,
-  2692,  2693,  2694,  2695,  2696,  2697,  2698,  2699,  2700,  2701,
-  2702,  2703,  2704,  2705,  2706,  2711,  2716,  2717,  2718,  2719,
-  2720,  2721,  2725,  2741,  2756,  2776,  2790,  2803,  2826,  2844,
-  2862,  2880,  2898,  2905,  2910,  2914,  2918,  2922,  2928,  2933,
-  2937,  2941,  2947,  2951,  2955,  2961,  2967,  2974,  2980,  2984,
-  2989,  2993,  3004,  3011,  3022,  3042,  3052,  3062,  3072,  3089,
-  3108,  3132,  3160,  3166,  3170,  3174,  3186,  3191,  3203,  3210,
-  3231,  3236,  3250,  3256,  3262,  3267,  3275,  3283,  3297,  3311,
-  3315,  3334,  3356
+  1803,  1816,  1862,  1877,  1888,  1907,  1917,  1939,  1943,  1948,
+  1953,  1963,  1980,  1996,  2022,  2049,  2081,  2088,  2093,  2099,
+  2103,  2111,  2120,  2128,  2136,  2141,  2149,  2154,  2162,  2167,
+  2177,  2184,  2191,  2198,  2205,  2212,  2219,  2226,  2233,  2240,
+  2245,  2252,  2257,  2264,  2269,  2276,  2281,  2288,  2293,  2300,
+  2305,  2312,  2317,  2324,  2329,  2336,  2341,  2351,  2355,  2360,
+  2387,  2411,  2419,  2438,  2456,  2474,  2503,  2538,  2565,  2592,
+  2606,  2624,  2629,  2638,  2640,  2641,  2642,  2643,  2644,  2645,
+  2646,  2647,  2654,  2655,  2656,  2657,  2658,  2659,  2660,  2661,
+  2662,  2663,  2664,  2665,  2666,  2667,  2668,  2669,  2670,  2671,
+  2672,  2673,  2674,  2675,  2676,  2677,  2678,  2679,  2680,  2681,
+  2682,  2683,  2684,  2685,  2687,  2688,  2689,  2690,  2691,  2692,
+  2693,  2694,  2695,  2696,  2697,  2698,  2699,  2700,  2701,  2702,
+  2703,  2704,  2705,  2706,  2707,  2712,  2717,  2718,  2719,  2720,
+  2721,  2722,  2726,  2742,  2757,  2777,  2791,  2804,  2827,  2845,
+  2863,  2881,  2899,  2906,  2911,  2915,  2919,  2923,  2929,  2934,
+  2938,  2942,  2948,  2952,  2956,  2962,  2968,  2975,  2981,  2985,
+  2990,  2994,  3005,  3012,  3023,  3043,  3053,  3063,  3073,  3090,
+  3109,  3133,  3161,  3167,  3171,  3175,  3187,  3192,  3204,  3211,
+  3232,  3237,  3251,  3257,  3263,  3268,  3276,  3284,  3298,  3312,
+  3316,  3335,  3357
 };
 #endif
 
@@ -4511,6 +4511,7 @@ case 132:
 	// using the FILE pointer, but hey, I'm lazy...
 	Msg(STATUS2, "Reading '%s'", tmpstring);
 	ParseFile(tmpstring, 0, 1);
+	SetBoundingBox();
 	Msg(STATUS2, "Read '%s'", tmpstring);
       }
       else if(!strcmp(yyvsp[-2].c, "Print")){
@@ -4543,7 +4544,7 @@ case 132:
     ;
     break;}
 case 133:
-#line 1862 "Gmsh.y"
+#line 1863 "Gmsh.y"
 {
       if(!strcmp(yyvsp[-6].c, "Save") && !strcmp(yyvsp[-5].c, "View")){
 	Post_View **vv = (Post_View **)List_Pointer_Test(CTX.post.list, (int)yyvsp[-3].d);
@@ -4560,7 +4561,7 @@ case 133:
     ;
     break;}
 case 134:
-#line 1877 "Gmsh.y"
+#line 1878 "Gmsh.y"
 {
       if(!strcmp(yyvsp[-6].c, "Background") && !strcmp(yyvsp[-5].c, "Mesh")  && !strcmp(yyvsp[-4].c, "View")){
 	Post_View **vv = (Post_View **)List_Pointer_Test(CTX.post.list, (int)yyvsp[-2].d);
@@ -4573,7 +4574,7 @@ case 134:
     ;
     break;}
 case 135:
-#line 1888 "Gmsh.y"
+#line 1889 "Gmsh.y"
 {
       if(!strcmp(yyvsp[-2].c, "Sleep")){
 	SleepInSeconds(yyvsp[-1].d);
@@ -4594,7 +4595,7 @@ case 135:
     ;
     break;}
 case 136:
-#line 1907 "Gmsh.y"
+#line 1908 "Gmsh.y"
 {
        try {
 	 GMSH_PluginManager::instance()->action(yyvsp[-4].c, yyvsp[-1].c, 0);
@@ -4606,7 +4607,7 @@ case 136:
      ;
     break;}
 case 137:
-#line 1917 "Gmsh.y"
+#line 1918 "Gmsh.y"
 {
       if(!strcmp(yyvsp[-1].c, "ElementsFromAllViews"))
 	CombineViews(0, 1, CTX.post.combine_remove_orig);
@@ -4630,27 +4631,27 @@ case 137:
     ;
     break;}
 case 138:
-#line 1939 "Gmsh.y"
+#line 1940 "Gmsh.y"
 {
       exit(0);
     ;
     break;}
 case 139:
-#line 1943 "Gmsh.y"
+#line 1944 "Gmsh.y"
 {
       CTX.forced_bbox = 0;
       SetBoundingBox();
     ;
     break;}
 case 140:
-#line 1948 "Gmsh.y"
+#line 1949 "Gmsh.y"
 {
       CTX.forced_bbox = 1;
       SetBoundingBox(yyvsp[-12].d, yyvsp[-10].d, yyvsp[-8].d, yyvsp[-6].d, yyvsp[-4].d, yyvsp[-2].d);
     ;
     break;}
 case 141:
-#line 1953 "Gmsh.y"
+#line 1954 "Gmsh.y"
 {
 #if defined(HAVE_FLTK)
       Draw();
@@ -4658,7 +4659,7 @@ case 141:
     ;
     break;}
 case 142:
-#line 1965 "Gmsh.y"
+#line 1966 "Gmsh.y"
 {
       LoopControlVariablesTab[ImbricatedLoop][0] = yyvsp[-3].d;
       LoopControlVariablesTab[ImbricatedLoop][1] = yyvsp[-1].d;
@@ -4675,7 +4676,7 @@ case 142:
     ;
     break;}
 case 143:
-#line 1980 "Gmsh.y"
+#line 1981 "Gmsh.y"
 {
       LoopControlVariablesTab[ImbricatedLoop][0] = yyvsp[-5].d;
       LoopControlVariablesTab[ImbricatedLoop][1] = yyvsp[-3].d;
@@ -4693,7 +4694,7 @@ case 143:
     ;
     break;}
 case 144:
-#line 1996 "Gmsh.y"
+#line 1997 "Gmsh.y"
 {
       LoopControlVariablesTab[ImbricatedLoop][0] = yyvsp[-3].d;
       LoopControlVariablesTab[ImbricatedLoop][1] = yyvsp[-1].d;
@@ -4721,7 +4722,7 @@ case 144:
     ;
     break;}
 case 145:
-#line 2022 "Gmsh.y"
+#line 2023 "Gmsh.y"
 {
       LoopControlVariablesTab[ImbricatedLoop][0] = yyvsp[-5].d;
       LoopControlVariablesTab[ImbricatedLoop][1] = yyvsp[-3].d;
@@ -4750,7 +4751,7 @@ case 145:
     ;
     break;}
 case 146:
-#line 2049 "Gmsh.y"
+#line 2050 "Gmsh.y"
 {
       if(ImbricatedLoop <= 0){
 	yymsg(GERROR, "Invalid For/EndFor loop");
@@ -4784,7 +4785,7 @@ case 146:
     ;
     break;}
 case 147:
-#line 2081 "Gmsh.y"
+#line 2082 "Gmsh.y"
 {
       if(!FunctionManager::Instance()->createFunction(yyvsp[0].c, yyin, yyname, yylineno))
 	yymsg(GERROR, "Redefinition of function %s", yyvsp[0].c);
@@ -4793,14 +4794,14 @@ case 147:
     ;
     break;}
 case 148:
-#line 2088 "Gmsh.y"
+#line 2089 "Gmsh.y"
 {
       if(!FunctionManager::Instance()->leaveFunction(&yyin, yyname, yylineno))
 	yymsg(GERROR, "Error while exiting function");
     ;
     break;}
 case 149:
-#line 2093 "Gmsh.y"
+#line 2094 "Gmsh.y"
 {
       if(!FunctionManager::Instance()->enterFunction(yyvsp[-1].c, &yyin, yyname, yylineno))
 	yymsg(GERROR, "Unknown function %s", yyvsp[-1].c);
@@ -4808,18 +4809,18 @@ case 149:
     ;
     break;}
 case 150:
-#line 2099 "Gmsh.y"
+#line 2100 "Gmsh.y"
 {
       if(!yyvsp[-1].d) skip_until("If", "EndIf");
     ;
     break;}
 case 151:
-#line 2103 "Gmsh.y"
+#line 2104 "Gmsh.y"
 {
     ;
     break;}
 case 152:
-#line 2112 "Gmsh.y"
+#line 2113 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShapes(TRANSLATE, yyvsp[-1].l, 
@@ -4829,7 +4830,7 @@ case 152:
     ;
     break;}
 case 153:
-#line 2120 "Gmsh.y"
+#line 2121 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShapes(ROTATE, yyvsp[-1].l, 
@@ -4839,7 +4840,7 @@ case 153:
     ;
     break;}
 case 154:
-#line 2128 "Gmsh.y"
+#line 2129 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShapes(TRANSLATE_ROTATE, yyvsp[-1].l, 
@@ -4849,14 +4850,14 @@ case 154:
     ;
     break;}
 case 155:
-#line 2136 "Gmsh.y"
+#line 2137 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 156:
-#line 2141 "Gmsh.y"
+#line 2142 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShapes(TRANSLATE, yyvsp[-3].l, 
@@ -4866,14 +4867,14 @@ case 156:
     ;
     break;}
 case 157:
-#line 2149 "Gmsh.y"
+#line 2150 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 158:
-#line 2154 "Gmsh.y"
+#line 2155 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShapes(ROTATE, yyvsp[-3].l, 
@@ -4883,14 +4884,14 @@ case 158:
     ;
     break;}
 case 159:
-#line 2162 "Gmsh.y"
+#line 2163 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 160:
-#line 2167 "Gmsh.y"
+#line 2168 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShapes(TRANSLATE_ROTATE, yyvsp[-3].l, 
@@ -4900,7 +4901,7 @@ case 160:
     ;
     break;}
 case 161:
-#line 2177 "Gmsh.y"
+#line 2178 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE, MSH_POINT, (int)yyvsp[-4].d, 
@@ -4909,7 +4910,7 @@ case 161:
     ;
     break;}
 case 162:
-#line 2184 "Gmsh.y"
+#line 2185 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE, MSH_SEGM_LINE, (int)yyvsp[-4].d, 
@@ -4918,7 +4919,7 @@ case 162:
     ;
     break;}
 case 163:
-#line 2191 "Gmsh.y"
+#line 2192 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE, MSH_SURF_PLAN, (int)yyvsp[-4].d, 
@@ -4927,7 +4928,7 @@ case 163:
     ;
     break;}
 case 164:
-#line 2198 "Gmsh.y"
+#line 2199 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(ROTATE, MSH_POINT, (int)yyvsp[-8].d, 
@@ -4936,7 +4937,7 @@ case 164:
     ;
     break;}
 case 165:
-#line 2205 "Gmsh.y"
+#line 2206 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(ROTATE, MSH_SEGM_LINE, (int)yyvsp[-8].d, 
@@ -4945,7 +4946,7 @@ case 165:
     ;
     break;}
 case 166:
-#line 2212 "Gmsh.y"
+#line 2213 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(ROTATE, MSH_SURF_PLAN, (int)yyvsp[-8].d, 
@@ -4954,7 +4955,7 @@ case 166:
     ;
     break;}
 case 167:
-#line 2219 "Gmsh.y"
+#line 2220 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE_ROTATE, MSH_POINT, (int)yyvsp[-10].d, 
@@ -4963,7 +4964,7 @@ case 167:
     ;
     break;}
 case 168:
-#line 2226 "Gmsh.y"
+#line 2227 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE_ROTATE, MSH_SEGM_LINE, (int)yyvsp[-10].d, 
@@ -4972,7 +4973,7 @@ case 168:
     ;
     break;}
 case 169:
-#line 2233 "Gmsh.y"
+#line 2234 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE_ROTATE, MSH_SURF_PLAN, (int)yyvsp[-10].d, 
@@ -4981,14 +4982,14 @@ case 169:
     ;
     break;}
 case 170:
-#line 2240 "Gmsh.y"
+#line 2241 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 171:
-#line 2245 "Gmsh.y"
+#line 2246 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE, MSH_POINT, (int)yyvsp[-8].d, 
@@ -4997,14 +4998,14 @@ case 171:
     ;
     break;}
 case 172:
-#line 2252 "Gmsh.y"
+#line 2253 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 173:
-#line 2257 "Gmsh.y"
+#line 2258 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE, MSH_SEGM_LINE, (int)yyvsp[-8].d, 
@@ -5013,14 +5014,14 @@ case 173:
     ;
     break;}
 case 174:
-#line 2264 "Gmsh.y"
+#line 2265 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 175:
-#line 2269 "Gmsh.y"
+#line 2270 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE, MSH_SURF_PLAN, (int)yyvsp[-8].d, 
@@ -5029,14 +5030,14 @@ case 175:
     ;
     break;}
 case 176:
-#line 2276 "Gmsh.y"
+#line 2277 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 177:
-#line 2281 "Gmsh.y"
+#line 2282 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(ROTATE, MSH_POINT, (int)yyvsp[-12].d, 
@@ -5045,14 +5046,14 @@ case 177:
     ;
     break;}
 case 178:
-#line 2288 "Gmsh.y"
+#line 2289 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 179:
-#line 2293 "Gmsh.y"
+#line 2294 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(ROTATE, MSH_SEGM_LINE, (int)yyvsp[-12].d, 
@@ -5061,14 +5062,14 @@ case 179:
     ;
     break;}
 case 180:
-#line 2300 "Gmsh.y"
+#line 2301 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 181:
-#line 2305 "Gmsh.y"
+#line 2306 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(ROTATE, MSH_SURF_PLAN, (int)yyvsp[-12].d, 
@@ -5077,14 +5078,14 @@ case 181:
     ;
     break;}
 case 182:
-#line 2312 "Gmsh.y"
+#line 2313 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 183:
-#line 2317 "Gmsh.y"
+#line 2318 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE_ROTATE, MSH_POINT, (int)yyvsp[-14].d, 
@@ -5093,14 +5094,14 @@ case 183:
     ;
     break;}
 case 184:
-#line 2324 "Gmsh.y"
+#line 2325 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 185:
-#line 2329 "Gmsh.y"
+#line 2330 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE_ROTATE, MSH_SEGM_LINE, (int)yyvsp[-14].d, 
@@ -5109,14 +5110,14 @@ case 185:
     ;
     break;}
 case 186:
-#line 2336 "Gmsh.y"
+#line 2337 "Gmsh.y"
 {
       extr.mesh.ExtrudeMesh = false;
       extr.mesh.Recombine = false;
     ;
     break;}
 case 187:
-#line 2341 "Gmsh.y"
+#line 2342 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(Shape));
       ExtrudeShape(TRANSLATE_ROTATE, MSH_SURF_PLAN, (int)yyvsp[-14].d, 
@@ -5125,17 +5126,17 @@ case 187:
     ;
     break;}
 case 188:
-#line 2352 "Gmsh.y"
+#line 2353 "Gmsh.y"
 {
     ;
     break;}
 case 189:
-#line 2355 "Gmsh.y"
+#line 2356 "Gmsh.y"
 {
     ;
     break;}
 case 190:
-#line 2361 "Gmsh.y"
+#line 2362 "Gmsh.y"
 {
       double d;
       extr.mesh.ExtrudeMesh = true;
@@ -5163,7 +5164,7 @@ case 190:
     ;
     break;}
 case 191:
-#line 2387 "Gmsh.y"
+#line 2388 "Gmsh.y"
 {
       double d;
       extr.mesh.ExtrudeMesh = true;
@@ -5189,13 +5190,13 @@ case 191:
     ;
     break;}
 case 192:
-#line 2411 "Gmsh.y"
+#line 2412 "Gmsh.y"
 {
       extr.mesh.Recombine = true;
     ;
     break;}
 case 193:
-#line 2420 "Gmsh.y"
+#line 2421 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[-3].l); i++){
 	double d;
@@ -5215,7 +5216,7 @@ case 193:
     ;
     break;}
 case 194:
-#line 2438 "Gmsh.y"
+#line 2439 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[-6].l); i++){
 	double d;
@@ -5235,7 +5236,7 @@ case 194:
     ;
     break;}
 case 195:
-#line 2456 "Gmsh.y"
+#line 2457 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[-6].l); i++){
 	double d;
@@ -5255,7 +5256,7 @@ case 195:
     ;
     break;}
 case 196:
-#line 2474 "Gmsh.y"
+#line 2475 "Gmsh.y"
 {
       Surface *s = FindSurface((int)yyvsp[-4].d, THEM);
       if(!s)
@@ -5286,7 +5287,7 @@ case 196:
     ;
     break;}
 case 197:
-#line 2503 "Gmsh.y"
+#line 2504 "Gmsh.y"
 {
       Surface *s = FindSurface((int)yyvsp[-5].d, THEM);
       if(!s)
@@ -5323,7 +5324,7 @@ case 197:
     ;
     break;}
 case 198:
-#line 2538 "Gmsh.y"
+#line 2539 "Gmsh.y"
 {
       Surface *s = FindSurface((int)yyvsp[-4].d, THEM);
       if(!s)
@@ -5352,7 +5353,7 @@ case 198:
     ;
     break;}
 case 199:
-#line 2565 "Gmsh.y"
+#line 2566 "Gmsh.y"
 {
       Volume *v = FindVolume((int)yyvsp[-4].d, THEM);
       if(!v)
@@ -5381,7 +5382,7 @@ case 199:
     ;
     break;}
 case 200:
-#line 2592 "Gmsh.y"
+#line 2593 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[-3].l); i++){
 	double d;
@@ -5397,7 +5398,7 @@ case 200:
     ;
     break;}
 case 201:
-#line 2606 "Gmsh.y"
+#line 2607 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[-1].l); i++){
 	double d;
@@ -5412,51 +5413,51 @@ case 201:
     ;
     break;}
 case 202:
-#line 2625 "Gmsh.y"
+#line 2626 "Gmsh.y"
 { 
       ReplaceAllDuplicates(THEM);
     ;
     break;}
 case 203:
-#line 2629 "Gmsh.y"
+#line 2630 "Gmsh.y"
 { 
       IntersectAllSegmentsTogether();
     ;
     break;}
 case 204:
-#line 2638 "Gmsh.y"
+#line 2639 "Gmsh.y"
 { yyval.d = yyvsp[0].d;           ;
     break;}
 case 205:
-#line 2639 "Gmsh.y"
+#line 2640 "Gmsh.y"
 { yyval.d = yyvsp[-1].d;           ;
     break;}
 case 206:
-#line 2640 "Gmsh.y"
+#line 2641 "Gmsh.y"
 { yyval.d = -yyvsp[0].d;          ;
     break;}
 case 207:
-#line 2641 "Gmsh.y"
+#line 2642 "Gmsh.y"
 { yyval.d = yyvsp[0].d;           ;
     break;}
 case 208:
-#line 2642 "Gmsh.y"
+#line 2643 "Gmsh.y"
 { yyval.d = !yyvsp[0].d;          ;
     break;}
 case 209:
-#line 2643 "Gmsh.y"
+#line 2644 "Gmsh.y"
 { yyval.d = yyvsp[-2].d - yyvsp[0].d;      ;
     break;}
 case 210:
-#line 2644 "Gmsh.y"
+#line 2645 "Gmsh.y"
 { yyval.d = yyvsp[-2].d + yyvsp[0].d;      ;
     break;}
 case 211:
-#line 2645 "Gmsh.y"
+#line 2646 "Gmsh.y"
 { yyval.d = yyvsp[-2].d * yyvsp[0].d;      ;
     break;}
 case 212:
-#line 2647 "Gmsh.y"
+#line 2648 "Gmsh.y"
 { 
       if(!yyvsp[0].d)
 	yymsg(GERROR, "Division by zero in '%g / %g'", yyvsp[-2].d, yyvsp[0].d);
@@ -5465,247 +5466,247 @@ case 212:
     ;
     break;}
 case 213:
-#line 2653 "Gmsh.y"
+#line 2654 "Gmsh.y"
 { yyval.d = (int)yyvsp[-2].d % (int)yyvsp[0].d;  ;
     break;}
 case 214:
-#line 2654 "Gmsh.y"
+#line 2655 "Gmsh.y"
 { yyval.d = pow(yyvsp[-2].d, yyvsp[0].d);  ;
     break;}
 case 215:
-#line 2655 "Gmsh.y"
+#line 2656 "Gmsh.y"
 { yyval.d = yyvsp[-2].d < yyvsp[0].d;      ;
     break;}
 case 216:
-#line 2656 "Gmsh.y"
+#line 2657 "Gmsh.y"
 { yyval.d = yyvsp[-2].d > yyvsp[0].d;      ;
     break;}
 case 217:
-#line 2657 "Gmsh.y"
+#line 2658 "Gmsh.y"
 { yyval.d = yyvsp[-2].d <= yyvsp[0].d;     ;
     break;}
 case 218:
-#line 2658 "Gmsh.y"
+#line 2659 "Gmsh.y"
 { yyval.d = yyvsp[-2].d >= yyvsp[0].d;     ;
     break;}
 case 219:
-#line 2659 "Gmsh.y"
+#line 2660 "Gmsh.y"
 { yyval.d = yyvsp[-2].d == yyvsp[0].d;     ;
     break;}
 case 220:
-#line 2660 "Gmsh.y"
+#line 2661 "Gmsh.y"
 { yyval.d = yyvsp[-2].d != yyvsp[0].d;     ;
     break;}
 case 221:
-#line 2661 "Gmsh.y"
+#line 2662 "Gmsh.y"
 { yyval.d = yyvsp[-2].d && yyvsp[0].d;     ;
     break;}
 case 222:
-#line 2662 "Gmsh.y"
+#line 2663 "Gmsh.y"
 { yyval.d = yyvsp[-2].d || yyvsp[0].d;     ;
     break;}
 case 223:
-#line 2663 "Gmsh.y"
+#line 2664 "Gmsh.y"
 { yyval.d = yyvsp[-4].d? yyvsp[-2].d : yyvsp[0].d;  ;
     break;}
 case 224:
-#line 2664 "Gmsh.y"
+#line 2665 "Gmsh.y"
 { yyval.d = exp(yyvsp[-1].d);      ;
     break;}
 case 225:
-#line 2665 "Gmsh.y"
+#line 2666 "Gmsh.y"
 { yyval.d = log(yyvsp[-1].d);      ;
     break;}
 case 226:
-#line 2666 "Gmsh.y"
+#line 2667 "Gmsh.y"
 { yyval.d = log10(yyvsp[-1].d);    ;
     break;}
 case 227:
-#line 2667 "Gmsh.y"
+#line 2668 "Gmsh.y"
 { yyval.d = sqrt(yyvsp[-1].d);     ;
     break;}
 case 228:
-#line 2668 "Gmsh.y"
+#line 2669 "Gmsh.y"
 { yyval.d = sin(yyvsp[-1].d);      ;
     break;}
 case 229:
-#line 2669 "Gmsh.y"
+#line 2670 "Gmsh.y"
 { yyval.d = asin(yyvsp[-1].d);     ;
     break;}
 case 230:
-#line 2670 "Gmsh.y"
+#line 2671 "Gmsh.y"
 { yyval.d = cos(yyvsp[-1].d);      ;
     break;}
 case 231:
-#line 2671 "Gmsh.y"
+#line 2672 "Gmsh.y"
 { yyval.d = acos(yyvsp[-1].d);     ;
     break;}
 case 232:
-#line 2672 "Gmsh.y"
+#line 2673 "Gmsh.y"
 { yyval.d = tan(yyvsp[-1].d);      ;
     break;}
 case 233:
-#line 2673 "Gmsh.y"
+#line 2674 "Gmsh.y"
 { yyval.d = atan(yyvsp[-1].d);     ;
     break;}
 case 234:
-#line 2674 "Gmsh.y"
+#line 2675 "Gmsh.y"
 { yyval.d = atan2(yyvsp[-3].d, yyvsp[-1].d);;
     break;}
 case 235:
-#line 2675 "Gmsh.y"
+#line 2676 "Gmsh.y"
 { yyval.d = sinh(yyvsp[-1].d);     ;
     break;}
 case 236:
-#line 2676 "Gmsh.y"
+#line 2677 "Gmsh.y"
 { yyval.d = cosh(yyvsp[-1].d);     ;
     break;}
 case 237:
-#line 2677 "Gmsh.y"
+#line 2678 "Gmsh.y"
 { yyval.d = tanh(yyvsp[-1].d);     ;
     break;}
 case 238:
-#line 2678 "Gmsh.y"
+#line 2679 "Gmsh.y"
 { yyval.d = fabs(yyvsp[-1].d);     ;
     break;}
 case 239:
-#line 2679 "Gmsh.y"
+#line 2680 "Gmsh.y"
 { yyval.d = floor(yyvsp[-1].d);    ;
     break;}
 case 240:
-#line 2680 "Gmsh.y"
+#line 2681 "Gmsh.y"
 { yyval.d = ceil(yyvsp[-1].d);     ;
     break;}
 case 241:
-#line 2681 "Gmsh.y"
+#line 2682 "Gmsh.y"
 { yyval.d = fmod(yyvsp[-3].d, yyvsp[-1].d); ;
     break;}
 case 242:
-#line 2682 "Gmsh.y"
+#line 2683 "Gmsh.y"
 { yyval.d = fmod(yyvsp[-3].d, yyvsp[-1].d); ;
     break;}
 case 243:
-#line 2683 "Gmsh.y"
+#line 2684 "Gmsh.y"
 { yyval.d = sqrt(yyvsp[-3].d*yyvsp[-3].d+yyvsp[-1].d*yyvsp[-1].d); ;
     break;}
 case 244:
-#line 2684 "Gmsh.y"
+#line 2685 "Gmsh.y"
 { yyval.d = yyvsp[-1].d*(double)rand()/(double)RAND_MAX; ;
     break;}
 case 245:
-#line 2686 "Gmsh.y"
+#line 2687 "Gmsh.y"
 { yyval.d = exp(yyvsp[-1].d);      ;
     break;}
 case 246:
-#line 2687 "Gmsh.y"
+#line 2688 "Gmsh.y"
 { yyval.d = log(yyvsp[-1].d);      ;
     break;}
 case 247:
-#line 2688 "Gmsh.y"
+#line 2689 "Gmsh.y"
 { yyval.d = log10(yyvsp[-1].d);    ;
     break;}
 case 248:
-#line 2689 "Gmsh.y"
+#line 2690 "Gmsh.y"
 { yyval.d = sqrt(yyvsp[-1].d);     ;
     break;}
 case 249:
-#line 2690 "Gmsh.y"
+#line 2691 "Gmsh.y"
 { yyval.d = sin(yyvsp[-1].d);      ;
     break;}
 case 250:
-#line 2691 "Gmsh.y"
+#line 2692 "Gmsh.y"
 { yyval.d = asin(yyvsp[-1].d);     ;
     break;}
 case 251:
-#line 2692 "Gmsh.y"
+#line 2693 "Gmsh.y"
 { yyval.d = cos(yyvsp[-1].d);      ;
     break;}
 case 252:
-#line 2693 "Gmsh.y"
+#line 2694 "Gmsh.y"
 { yyval.d = acos(yyvsp[-1].d);     ;
     break;}
 case 253:
-#line 2694 "Gmsh.y"
+#line 2695 "Gmsh.y"
 { yyval.d = tan(yyvsp[-1].d);      ;
     break;}
 case 254:
-#line 2695 "Gmsh.y"
+#line 2696 "Gmsh.y"
 { yyval.d = atan(yyvsp[-1].d);     ;
     break;}
 case 255:
-#line 2696 "Gmsh.y"
+#line 2697 "Gmsh.y"
 { yyval.d = atan2(yyvsp[-3].d, yyvsp[-1].d);;
     break;}
 case 256:
-#line 2697 "Gmsh.y"
+#line 2698 "Gmsh.y"
 { yyval.d = sinh(yyvsp[-1].d);     ;
     break;}
 case 257:
-#line 2698 "Gmsh.y"
+#line 2699 "Gmsh.y"
 { yyval.d = cosh(yyvsp[-1].d);     ;
     break;}
 case 258:
-#line 2699 "Gmsh.y"
+#line 2700 "Gmsh.y"
 { yyval.d = tanh(yyvsp[-1].d);     ;
     break;}
 case 259:
-#line 2700 "Gmsh.y"
+#line 2701 "Gmsh.y"
 { yyval.d = fabs(yyvsp[-1].d);     ;
     break;}
 case 260:
-#line 2701 "Gmsh.y"
+#line 2702 "Gmsh.y"
 { yyval.d = floor(yyvsp[-1].d);    ;
     break;}
 case 261:
-#line 2702 "Gmsh.y"
+#line 2703 "Gmsh.y"
 { yyval.d = ceil(yyvsp[-1].d);     ;
     break;}
 case 262:
-#line 2703 "Gmsh.y"
+#line 2704 "Gmsh.y"
 { yyval.d = fmod(yyvsp[-3].d, yyvsp[-1].d); ;
     break;}
 case 263:
-#line 2704 "Gmsh.y"
+#line 2705 "Gmsh.y"
 { yyval.d = fmod(yyvsp[-3].d, yyvsp[-1].d); ;
     break;}
 case 264:
-#line 2705 "Gmsh.y"
+#line 2706 "Gmsh.y"
 { yyval.d = sqrt(yyvsp[-3].d*yyvsp[-3].d+yyvsp[-1].d*yyvsp[-1].d); ;
     break;}
 case 265:
-#line 2706 "Gmsh.y"
+#line 2707 "Gmsh.y"
 { yyval.d = yyvsp[-1].d*(double)rand()/(double)RAND_MAX; ;
     break;}
 case 266:
-#line 2715 "Gmsh.y"
+#line 2716 "Gmsh.y"
 { yyval.d = yyvsp[0].d; ;
     break;}
 case 267:
-#line 2716 "Gmsh.y"
+#line 2717 "Gmsh.y"
 { yyval.d = 3.141592653589793; ;
     break;}
 case 268:
-#line 2717 "Gmsh.y"
+#line 2718 "Gmsh.y"
 { yyval.d = ParUtil::Instance()->rank(); ;
     break;}
 case 269:
-#line 2718 "Gmsh.y"
+#line 2719 "Gmsh.y"
 { yyval.d = ParUtil::Instance()->size(); ;
     break;}
 case 270:
-#line 2719 "Gmsh.y"
+#line 2720 "Gmsh.y"
 { yyval.d = Get_GmshMajorVersion(); ;
     break;}
 case 271:
-#line 2720 "Gmsh.y"
+#line 2721 "Gmsh.y"
 { yyval.d = Get_GmshMinorVersion(); ;
     break;}
 case 272:
-#line 2721 "Gmsh.y"
+#line 2722 "Gmsh.y"
 { yyval.d = Get_GmshPatchVersion(); ;
     break;}
 case 273:
-#line 2726 "Gmsh.y"
+#line 2727 "Gmsh.y"
 {
       Symbol TheSymbol;
       TheSymbol.Name = yyvsp[0].c;
@@ -5720,7 +5721,7 @@ case 273:
     ;
     break;}
 case 274:
-#line 2742 "Gmsh.y"
+#line 2743 "Gmsh.y"
 {
       char tmpstring[1024];
       sprintf(tmpstring, "%s_%d", yyvsp[-4].c, (int)yyvsp[-1].d) ;
@@ -5737,7 +5738,7 @@ case 274:
     ;
     break;}
 case 275:
-#line 2757 "Gmsh.y"
+#line 2758 "Gmsh.y"
 {
       Symbol TheSymbol;
       TheSymbol.Name = yyvsp[-3].c;
@@ -5759,7 +5760,7 @@ case 275:
     ;
     break;}
 case 276:
-#line 2777 "Gmsh.y"
+#line 2778 "Gmsh.y"
 {
       Symbol TheSymbol;
       TheSymbol.Name = yyvsp[-2].c;
@@ -5775,7 +5776,7 @@ case 276:
     ;
     break;}
 case 277:
-#line 2791 "Gmsh.y"
+#line 2792 "Gmsh.y"
 {
       Symbol TheSymbol;
       TheSymbol.Name = yyvsp[-1].c;
@@ -5790,7 +5791,7 @@ case 277:
     ;
     break;}
 case 278:
-#line 2804 "Gmsh.y"
+#line 2805 "Gmsh.y"
 {
       Symbol TheSymbol;
       TheSymbol.Name = yyvsp[-4].c;
@@ -5812,7 +5813,7 @@ case 278:
     ;
     break;}
 case 279:
-#line 2827 "Gmsh.y"
+#line 2828 "Gmsh.y"
 {
       double (*pNumOpt)(int num, int action, double value);
       StringXNumber *pNumCat;
@@ -5832,7 +5833,7 @@ case 279:
     ;
     break;}
 case 280:
-#line 2845 "Gmsh.y"
+#line 2846 "Gmsh.y"
 {
       double (*pNumOpt)(int num, int action, double value);
       StringXNumber *pNumCat;
@@ -5852,7 +5853,7 @@ case 280:
     ;
     break;}
 case 281:
-#line 2863 "Gmsh.y"
+#line 2864 "Gmsh.y"
 {
       double (*pNumOpt)(int num, int action, double value);
       StringXNumber *pNumCat;
@@ -5872,7 +5873,7 @@ case 281:
     ;
     break;}
 case 282:
-#line 2881 "Gmsh.y"
+#line 2882 "Gmsh.y"
 {
       double (*pNumOpt)(int num, int action, double value);
       StringXNumber *pNumCat;
@@ -5892,124 +5893,124 @@ case 282:
     ;
     break;}
 case 283:
-#line 2899 "Gmsh.y"
+#line 2900 "Gmsh.y"
 { 
       yyval.d = GetValue(yyvsp[-3].c, yyvsp[-1].d);
       Free(yyvsp[-3].c);
     ;
     break;}
 case 284:
-#line 2907 "Gmsh.y"
+#line 2908 "Gmsh.y"
 {
       memcpy(yyval.v, yyvsp[0].v, 5*sizeof(double));
     ;
     break;}
 case 285:
-#line 2911 "Gmsh.y"
+#line 2912 "Gmsh.y"
 {
       for(int i = 0; i < 5; i++) yyval.v[i] = -yyvsp[0].v[i];
     ;
     break;}
 case 286:
-#line 2915 "Gmsh.y"
+#line 2916 "Gmsh.y"
 { 
       for(int i = 0; i < 5; i++) yyval.v[i] = yyvsp[0].v[i];
     ;
     break;}
 case 287:
-#line 2919 "Gmsh.y"
+#line 2920 "Gmsh.y"
 { 
       for(int i = 0; i < 5; i++) yyval.v[i] = yyvsp[-2].v[i] - yyvsp[0].v[i];
     ;
     break;}
 case 288:
-#line 2923 "Gmsh.y"
+#line 2924 "Gmsh.y"
 {
       for(int i = 0; i < 5; i++) yyval.v[i] = yyvsp[-2].v[i] + yyvsp[0].v[i];
     ;
     break;}
 case 289:
-#line 2930 "Gmsh.y"
+#line 2931 "Gmsh.y"
 { 
       yyval.v[0] = yyvsp[-9].d;  yyval.v[1] = yyvsp[-7].d;  yyval.v[2] = yyvsp[-5].d;  yyval.v[3] = yyvsp[-3].d; yyval.v[4] = yyvsp[-1].d;
     ;
     break;}
 case 290:
-#line 2934 "Gmsh.y"
+#line 2935 "Gmsh.y"
 { 
       yyval.v[0] = yyvsp[-7].d;  yyval.v[1] = yyvsp[-5].d;  yyval.v[2] = yyvsp[-3].d;  yyval.v[3] = yyvsp[-1].d; yyval.v[4] = 1.0;
     ;
     break;}
 case 291:
-#line 2938 "Gmsh.y"
+#line 2939 "Gmsh.y"
 {
       yyval.v[0] = yyvsp[-5].d;  yyval.v[1] = yyvsp[-3].d;  yyval.v[2] = yyvsp[-1].d;  yyval.v[3] = 0.0; yyval.v[4] = 1.0;
     ;
     break;}
 case 292:
-#line 2942 "Gmsh.y"
+#line 2943 "Gmsh.y"
 {
       yyval.v[0] = yyvsp[-5].d;  yyval.v[1] = yyvsp[-3].d;  yyval.v[2] = yyvsp[-1].d;  yyval.v[3] = 0.0; yyval.v[4] = 1.0;
     ;
     break;}
 case 293:
-#line 2949 "Gmsh.y"
+#line 2950 "Gmsh.y"
 {
     ;
     break;}
 case 294:
-#line 2952 "Gmsh.y"
+#line 2953 "Gmsh.y"
 {
        yyval.l = yyvsp[-1].l;
     ;
     break;}
 case 295:
-#line 2956 "Gmsh.y"
+#line 2957 "Gmsh.y"
 {
        yyval.l = yyvsp[-1].l;
     ;
     break;}
 case 296:
-#line 2963 "Gmsh.y"
+#line 2964 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(List_T*));
       List_Add(yyval.l, &(yyvsp[0].l));
     ;
     break;}
 case 297:
-#line 2968 "Gmsh.y"
+#line 2969 "Gmsh.y"
 {
       List_Add(yyval.l, &(yyvsp[0].l));
     ;
     break;}
 case 298:
-#line 2976 "Gmsh.y"
+#line 2977 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(double));
       List_Add(yyval.l, &(yyvsp[0].d));
     ;
     break;}
 case 299:
-#line 2981 "Gmsh.y"
+#line 2982 "Gmsh.y"
 {
       yyval.l = yyvsp[0].l;
     ;
     break;}
 case 300:
-#line 2985 "Gmsh.y"
+#line 2986 "Gmsh.y"
 {
       // creates an empty list
       yyval.l = List_Create(2, 1, sizeof(double));
     ;
     break;}
 case 301:
-#line 2990 "Gmsh.y"
+#line 2991 "Gmsh.y"
 {
       yyval.l = yyvsp[-1].l;
     ;
     break;}
 case 302:
-#line 2994 "Gmsh.y"
+#line 2995 "Gmsh.y"
 {
       yyval.l = yyvsp[-1].l;
       double *pd;
@@ -6020,7 +6021,7 @@ case 302:
     ;
     break;}
 case 303:
-#line 3006 "Gmsh.y"
+#line 3007 "Gmsh.y"
 { 
       yyval.l = List_Create(2, 1, sizeof(double)); 
       for(double d = yyvsp[-2].d; (yyvsp[-2].d < yyvsp[0].d) ? (d <= yyvsp[0].d) : (d >= yyvsp[0].d); (yyvsp[-2].d < yyvsp[0].d) ? (d += 1.) : (d -= 1.)) 
@@ -6028,7 +6029,7 @@ case 303:
     ;
     break;}
 case 304:
-#line 3012 "Gmsh.y"
+#line 3013 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(double)); 
       if(!yyvsp[0].d || (yyvsp[-4].d < yyvsp[-2].d && yyvsp[0].d < 0) || (yyvsp[-4].d > yyvsp[-2].d && yyvsp[0].d > 0)){
@@ -6041,7 +6042,7 @@ case 304:
    ;
     break;}
 case 305:
-#line 3023 "Gmsh.y"
+#line 3024 "Gmsh.y"
 {
       // Returns the coordinates of a point and fills a list with it.
       // This allows to ensure e.g. that relative point positions are
@@ -6063,7 +6064,7 @@ case 305:
     ;
     break;}
 case 306:
-#line 3043 "Gmsh.y"
+#line 3044 "Gmsh.y"
 {
       yyval.l = List_Create(List_Nbr(yyvsp[0].l), 1, sizeof(double));
       for(int i = 0; i < List_Nbr(yyvsp[0].l); i++){
@@ -6075,7 +6076,7 @@ case 306:
     ;
     break;}
 case 307:
-#line 3053 "Gmsh.y"
+#line 3054 "Gmsh.y"
 {
       yyval.l = List_Create(List_Nbr(yyvsp[0].l), 1, sizeof(double));
       for(int i = 0; i < List_Nbr(yyvsp[0].l); i++){
@@ -6087,7 +6088,7 @@ case 307:
     ;
     break;}
 case 308:
-#line 3063 "Gmsh.y"
+#line 3064 "Gmsh.y"
 {
       yyval.l = List_Create(List_Nbr(yyvsp[0].l), 1, sizeof(double));
       for(int i = 0; i < List_Nbr(yyvsp[0].l); i++){
@@ -6099,7 +6100,7 @@ case 308:
     ;
     break;}
 case 309:
-#line 3073 "Gmsh.y"
+#line 3074 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(double));
       Symbol TheSymbol;
@@ -6118,7 +6119,7 @@ case 309:
     ;
     break;}
 case 310:
-#line 3090 "Gmsh.y"
+#line 3091 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(double));
       Symbol TheSymbol;
@@ -6139,7 +6140,7 @@ case 310:
     ;
     break;}
 case 311:
-#line 3109 "Gmsh.y"
+#line 3110 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(double));
       Symbol TheSymbol;
@@ -6165,7 +6166,7 @@ case 311:
     ;
     break;}
 case 312:
-#line 3133 "Gmsh.y"
+#line 3134 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(double));
       Symbol TheSymbol;
@@ -6193,26 +6194,26 @@ case 312:
     ;
     break;}
 case 313:
-#line 3162 "Gmsh.y"
+#line 3163 "Gmsh.y"
 {
       yyval.l = List_Create(2, 1, sizeof(double));
       List_Add(yyval.l, &(yyvsp[0].d));
     ;
     break;}
 case 314:
-#line 3167 "Gmsh.y"
+#line 3168 "Gmsh.y"
 {
       yyval.l = yyvsp[0].l;
     ;
     break;}
 case 315:
-#line 3171 "Gmsh.y"
+#line 3172 "Gmsh.y"
 {
       List_Add(yyval.l, &(yyvsp[0].d));
     ;
     break;}
 case 316:
-#line 3175 "Gmsh.y"
+#line 3176 "Gmsh.y"
 {
       for(int i = 0; i < List_Nbr(yyvsp[0].l); i++){
 	double d;
@@ -6223,19 +6224,19 @@ case 316:
     ;
     break;}
 case 317:
-#line 3188 "Gmsh.y"
+#line 3189 "Gmsh.y"
 {
       yyval.u = CTX.PACK_COLOR((int)yyvsp[-7].d, (int)yyvsp[-5].d, (int)yyvsp[-3].d, (int)yyvsp[-1].d);
     ;
     break;}
 case 318:
-#line 3192 "Gmsh.y"
+#line 3193 "Gmsh.y"
 {
       yyval.u = CTX.PACK_COLOR((int)yyvsp[-5].d, (int)yyvsp[-3].d, (int)yyvsp[-1].d, 255);
     ;
     break;}
 case 319:
-#line 3204 "Gmsh.y"
+#line 3205 "Gmsh.y"
 {
       int flag;
       yyval.u = Get_ColorForString(ColorString, -1, yyvsp[0].c, &flag);
@@ -6244,7 +6245,7 @@ case 319:
     ;
     break;}
 case 320:
-#line 3211 "Gmsh.y"
+#line 3212 "Gmsh.y"
 {
       unsigned int (*pColOpt)(int num, int action, unsigned int value);
       StringXColor *pColCat;
@@ -6265,13 +6266,13 @@ case 320:
     ;
     break;}
 case 321:
-#line 3233 "Gmsh.y"
+#line 3234 "Gmsh.y"
 {
       yyval.l = yyvsp[-1].l;
     ;
     break;}
 case 322:
-#line 3237 "Gmsh.y"
+#line 3238 "Gmsh.y"
 {
       yyval.l = List_Create(256, 10, sizeof(unsigned int));
       GmshColorTable *ct = Get_ColorTable((int)yyvsp[-3].d);
@@ -6285,26 +6286,26 @@ case 322:
     ;
     break;}
 case 323:
-#line 3252 "Gmsh.y"
+#line 3253 "Gmsh.y"
 {
       yyval.l = List_Create(256, 10, sizeof(unsigned int));
       List_Add(yyval.l, &(yyvsp[0].u));
     ;
     break;}
 case 324:
-#line 3257 "Gmsh.y"
+#line 3258 "Gmsh.y"
 {
       List_Add(yyval.l, &(yyvsp[0].u));
     ;
     break;}
 case 325:
-#line 3264 "Gmsh.y"
+#line 3265 "Gmsh.y"
 {
       yyval.c = yyvsp[0].c;
     ;
     break;}
 case 326:
-#line 3268 "Gmsh.y"
+#line 3269 "Gmsh.y"
 {
       yyval.c = (char *)Malloc(32*sizeof(char));
       time_t now;
@@ -6314,7 +6315,7 @@ case 326:
     ;
     break;}
 case 327:
-#line 3276 "Gmsh.y"
+#line 3277 "Gmsh.y"
 {
       yyval.c = (char *)Malloc((strlen(yyvsp[-3].c)+strlen(yyvsp[-1].c)+1)*sizeof(char));
       strcpy(yyval.c, yyvsp[-3].c);
@@ -6324,7 +6325,7 @@ case 327:
     ;
     break;}
 case 328:
-#line 3284 "Gmsh.y"
+#line 3285 "Gmsh.y"
 {
       yyval.c = (char *)Malloc((strlen(yyvsp[-1].c)+1)*sizeof(char));
       int i;
@@ -6340,7 +6341,7 @@ case 328:
     ;
     break;}
 case 329:
-#line 3298 "Gmsh.y"
+#line 3299 "Gmsh.y"
 {
       yyval.c = (char *)Malloc((strlen(yyvsp[-1].c)+1)*sizeof(char));
       int i;
@@ -6356,13 +6357,13 @@ case 329:
     ;
     break;}
 case 330:
-#line 3312 "Gmsh.y"
+#line 3313 "Gmsh.y"
 {
       yyval.c = yyvsp[-1].c;
     ;
     break;}
 case 331:
-#line 3316 "Gmsh.y"
+#line 3317 "Gmsh.y"
 {
       char tmpstring[1024];
       int i = PrintListOfDouble(yyvsp[-3].c, yyvsp[-1].l, tmpstring);
@@ -6383,7 +6384,7 @@ case 331:
     ;
     break;}
 case 332:
-#line 3335 "Gmsh.y"
+#line 3336 "Gmsh.y"
 { 
       char* (*pStrOpt)(int num, int action, char *value);
       StringXString *pStrCat;
@@ -6407,7 +6408,7 @@ case 332:
     ;
     break;}
 case 333:
-#line 3357 "Gmsh.y"
+#line 3358 "Gmsh.y"
 { 
       char* (*pStrOpt)(int num, int action, char *value);
       StringXString *pStrCat;
@@ -6652,7 +6653,7 @@ yyerrhandle:
     }
   return 1;
 }
-#line 3380 "Gmsh.y"
+#line 3381 "Gmsh.y"
 
 
 void DeleteSymbol(void *a, void *b){
diff --git a/Parser/Gmsh.y b/Parser/Gmsh.y
index fb9bc23e1d9622e051263a3709084406f7477762..db1724ddd76098d827fe371a6045e51b0139c7a5 100644
--- a/Parser/Gmsh.y
+++ b/Parser/Gmsh.y
@@ -1,5 +1,5 @@
 %{
-// $Id: Gmsh.y,v 1.231 2006-08-07 13:57:17 geuzaine Exp $
+// $Id: Gmsh.y,v 1.232 2006-08-07 19:08:13 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -1828,6 +1828,7 @@ Command :
 	// using the FILE pointer, but hey, I'm lazy...
 	Msg(STATUS2, "Reading '%s'", tmpstring);
 	ParseFile(tmpstring, 0, 1);
+	SetBoundingBox();
 	Msg(STATUS2, "Read '%s'", tmpstring);
       }
       else if(!strcmp($1, "Print")){
diff --git a/Parser/Gmsh.yy.cpp b/Parser/Gmsh.yy.cpp
index ba3f43c3c8adbda9451758e1b9065149eca1f63c..2be60e3187997f1acc63368195a258df98f27dd7 100644
--- a/Parser/Gmsh.yy.cpp
+++ b/Parser/Gmsh.yy.cpp
@@ -2,7 +2,7 @@
 /* A lexical scanner generated by flex */
 
 /* Scanner skeleton version:
- * $Header: /cvsroot/gmsh/Parser/Gmsh.yy.cpp,v 1.269 2006-08-07 13:57:17 geuzaine Exp $
+ * $Header: /cvsroot/gmsh/Parser/Gmsh.yy.cpp,v 1.270 2006-08-07 19:08:13 geuzaine Exp $
  */
 
 #define FLEX_SCANNER
@@ -727,7 +727,7 @@ char *yytext;
 #line 1 "Gmsh.l"
 #define INITIAL 0
 #line 2 "Gmsh.l"
-// $Id: Gmsh.yy.cpp,v 1.269 2006-08-07 13:57:17 geuzaine Exp $
+// $Id: Gmsh.yy.cpp,v 1.270 2006-08-07 19:08:13 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
diff --git a/Parser/Makefile b/Parser/Makefile
index 2fb5ebf13cacb37c3b0f7b4de89f9a546e5bf54e..450cdcf13e9404a9a58935598ae083edfeb4da6d 100644
--- a/Parser/Makefile
+++ b/Parser/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.91 2006-08-04 14:28:03 geuzaine Exp $
+# $Id: Makefile,v 1.92 2006-08-07 19:08:13 geuzaine Exp $
 #
 # Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 #
@@ -107,28 +107,28 @@ Gmsh.yy.o: Gmsh.yy.cpp ../Common/Gmsh.h ../Common/Message.h \
   ../Mesh/Vertex.h ../Mesh/Simplex.h ../Mesh/Mesh.h ../Mesh/Matrix.h \
   ../Geo/ExtrudeParams.h Gmsh.tab.hpp
 # 1 "/Users/geuzaine/.gmsh/Parser//"
-OpenFile.o: OpenFile.cpp ../Mesh/BDS.h ../Common/Views.h \
-  ../Common/ColorTable.h ../DataStr/List.h ../Common/VertexArray.h \
-  ../Common/SmoothNormals.h ../Numeric/Numeric.h ../Common/GmshMatrix.h \
-  ../Common/AdaptiveViews.h ../Common/GmshMatrix.h ../Common/Gmsh.h \
-  ../Common/Message.h ../DataStr/Malloc.h ../DataStr/Tree.h \
+OpenFile.o: OpenFile.cpp ../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 \
   ../Geo/gmshModel.h ../Geo/GModel.h ../Geo/GVertex.h ../Geo/GEntity.h \
   ../Geo/Range.h ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h \
   ../Geo/SPoint3.h ../Geo/MVertex.h ../Common/GmshDefines.h \
   ../Geo/MVertex.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/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 ../Common/Context.h Parser.h OpenFile.h \
+  ../Geo/SPoint2.h ../Geo/MElement.h ../Geo/MVertex.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/Context.h Parser.h OpenFile.h \
   ../Common/CommandLine.h ../Plugin/PluginManager.h ../Plugin/Plugin.h \
-  ../Common/Options.h ../Geo/Geo.h ../Mesh/Mesh.h ../Mesh/Vertex.h \
-  ../Mesh/Element.h ../Mesh/Vertex.h ../Mesh/Simplex.h ../Mesh/Vertex.h \
-  ../Mesh/Element.h ../Mesh/Face.h ../Mesh/Vertex.h ../Mesh/Element.h \
-  ../Mesh/Edge.h ../Mesh/Vertex.h ../Mesh/Simplex.h \
-  ../Geo/ExtrudeParams.h ../Mesh/Metric.h ../Mesh/Vertex.h \
-  ../Mesh/Simplex.h ../Mesh/Mesh.h ../Mesh/Matrix.h ../Geo/MinMax.h \
+  ../Common/Options.h ../Common/Views.h ../Common/ColorTable.h \
+  ../Common/VertexArray.h ../Common/SmoothNormals.h \
+  ../Common/GmshMatrix.h ../Common/AdaptiveViews.h ../Common/GmshMatrix.h \
+  ../Mesh/Mesh.h ../Mesh/Vertex.h ../Mesh/Element.h ../Mesh/Vertex.h \
+  ../Mesh/Simplex.h ../Mesh/Vertex.h ../Mesh/Element.h ../Mesh/Face.h \
+  ../Mesh/Vertex.h ../Mesh/Element.h ../Mesh/Edge.h ../Mesh/Vertex.h \
+  ../Mesh/Simplex.h ../Geo/ExtrudeParams.h ../Mesh/Metric.h \
+  ../Mesh/Vertex.h ../Mesh/Simplex.h ../Mesh/Mesh.h ../Mesh/Matrix.h \
   ../Common/Visibility.h ../Graphics/ReadImg.h ../Common/OS.h \
   ../Common/GmshUI.h ../Graphics/Draw.h ../Fltk/GUI.h \
   ../Fltk/Opengl_Window.h ../Fltk/Colorbar_Window.h \
diff --git a/Parser/OpenFile.cpp b/Parser/OpenFile.cpp
index 0d6bf469b6b7d21ff5d8050c23605c754bde5e61..c012e09b0382f7b4c2c75c486aa1eb0974440626 100644
--- a/Parser/OpenFile.cpp
+++ b/Parser/OpenFile.cpp
@@ -1,4 +1,4 @@
-// $Id: OpenFile.cpp,v 1.101 2006-08-07 13:57:17 geuzaine Exp $
+// $Id: OpenFile.cpp,v 1.102 2006-08-07 19:08:13 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -23,7 +23,6 @@
 #include <sys/cygwin.h>
 #endif
 
-#include "BDS.h"
 #include "Gmsh.h"
 #include "gmshModel.h"
 #include "Numeric.h"
@@ -32,10 +31,8 @@
 #include "OpenFile.h"
 #include "CommandLine.h"
 #include "PluginManager.h"
-#include "Geo.h"
-#include "Mesh.h"
 #include "Views.h"
-#include "MinMax.h"
+#include "Mesh.h"
 #include "Visibility.h"
 #include "ReadImg.h"
 #include "OS.h"
@@ -48,13 +45,9 @@ extern GUI *WID;
 void UpdateViewsInGUI();
 #endif
 
-extern Mesh *THEM;
 extern GModel *GMODEL;
 extern Context_T CTX;
 
-extern  void BDS_To_Mesh(Mesh *m);
-extern  void BDS_To_Mesh_2(Mesh *m);
-
 void FixRelativePath(char *in, char *out){
   if(in[0] == '/' || in[0] == '\\' || (strlen(in)>2 && in[1] == ':')){
     // do nothing: 'in' is an absolute path
@@ -91,58 +84,95 @@ void SplitFileName(char *name, char *base, char *ext)
   }
 }
 
+static void FinishUpBoundingBox()
+{
+  double range[3];
+
+  for(int i = 0; i < 3; i++){
+    CTX.cg[i] = 0.5 * (CTX.min[i] + CTX.max[i]);
+    range[i] = CTX.max[i] - CTX.min[i];
+  }
+
+  if(range[0] == 0. && range[1] == 0. && range[2] == 0.) {
+    CTX.min[0] -= 1.; CTX.min[1] -= 1.;
+    CTX.max[0] += 1.; CTX.max[1] += 1.;
+    CTX.lc = 1.;
+  }
+  else if(range[0] == 0. && range[1] == 0.) {
+    CTX.lc = range[2];
+    CTX.min[0] -= CTX.lc; CTX.min[1] -= CTX.lc;
+    CTX.max[0] += CTX.lc; CTX.max[1] += CTX.lc;
+  }
+  else if(range[0] == 0. && range[2] == 0.) {
+    CTX.lc = range[1];
+    CTX.min[0] -= CTX.lc; CTX.max[0] += CTX.lc;
+  }
+  else if(range[1] == 0. && range[2] == 0.) {
+    CTX.lc = range[0];
+    CTX.min[1] -= CTX.lc; CTX.max[1] += CTX.lc;
+  }
+  else if(range[0] == 0.) {
+    CTX.lc = sqrt(DSQR(range[1]) + DSQR(range[2]));
+    CTX.min[0] -= CTX.lc; CTX.max[0] += CTX.lc;
+  }
+  else if(range[1] == 0.) {
+    CTX.lc = sqrt(DSQR(range[0]) + DSQR(range[2]));
+    CTX.min[1] -= CTX.lc; CTX.max[1] += CTX.lc;
+  }
+  else if(range[2] == 0.) {
+    CTX.lc = sqrt(DSQR(range[0]) + DSQR(range[1]));
+  }
+  else {
+    CTX.lc = sqrt(DSQR(range[0]) + DSQR(range[1]) + DSQR(range[2]));
+  }
+}
+
 void SetBoundingBox(double xmin, double xmax,
 		    double ymin, double ymax, 
 		    double zmin, double zmax)
 {
-  double bbox[6] = {xmin, xmax, ymin, ymax, zmin, zmax};
-  CalculateMinMax(NULL, bbox);
+  CTX.min[0] = xmin; CTX.max[0] = xmax;
+  CTX.min[1] = ymin; CTX.max[1] = ymax;
+  CTX.min[2] = zmin; CTX.max[2] = zmax;
+  FinishUpBoundingBox();
 }
 
 void SetBoundingBox(void)
 {
-  if(!THEM || CTX.forced_bbox) 
-    return;
-  if (THEM->bds) {
-    double bbox[6] = {THEM->bds->Min[0],THEM->bds->Max[0],THEM->bds->Min[1],
-		      THEM->bds->Max[1],THEM->bds->Min[2],THEM->bds->Max[2]};
-    CalculateMinMax(NULL, bbox);
-  }
-  else if(Tree_Nbr(THEM->Vertices)) {
-    // if we have mesh vertices, use them
-    CalculateMinMax(THEM->Vertices, NULL);
-  }
-  else if(Tree_Nbr(THEM->Points)) { 
-    // else, if we have geometry points, use them
-    CalculateMinMax(THEM->Points, NULL);
-  }
-  else if(List_Nbr(CTX.post.list)) {
-    // else, if we have views, use the max bb of all the views
-    double bbox[6];
-    Post_View *v = *(Post_View **)List_Pointer(CTX.post.list, 0);
-    for(int i = 0; i < 6; i++) bbox[i] = v->BBox[i];
-    for(int i = 1; i < List_Nbr(CTX.post.list); i++){
-      v = *(Post_View **)List_Pointer(CTX.post.list, i);
-      if(v->BBox[0] < bbox[0]) bbox[0] = v->BBox[0];
-      if(v->BBox[1] > bbox[1]) bbox[1] = v->BBox[1];
-      if(v->BBox[2] < bbox[2]) bbox[2] = v->BBox[2];
-      if(v->BBox[3] > bbox[3]) bbox[3] = v->BBox[3];
-      if(v->BBox[4] < bbox[4]) bbox[4] = v->BBox[4];
-      if(v->BBox[5] > bbox[5]) bbox[5] = v->BBox[5];
+  if(CTX.forced_bbox) return;
+
+  SBoundingBox3d bb;
+
+  if(GMODEL)
+    bb = GMODEL->bounds();
+
+  if(bb.empty() && GMODEL)
+    bb = GMODEL->recomputeBounds();
+  
+  if(List_Nbr(CTX.post.list)) {
+    for(int i = 0; i < List_Nbr(CTX.post.list); i++){
+      Post_View *v = *(Post_View **)List_Pointer(CTX.post.list, i);
+      bb += SPoint3(v->BBox[0], v->BBox[2], v->BBox[4]);
+      bb += SPoint3(v->BBox[1], v->BBox[3], v->BBox[5]);
     }
-    CalculateMinMax(NULL, bbox);
   }
-  else {
-    // else, use a default bbox
-    CalculateMinMax(NULL, NULL);
+  
+  if(bb.empty()){
+    bb += SPoint3(-1., -1., -1.);
+    bb += SPoint3(1., 1., 1.);
   }
+  
+  CTX.min[0] = bb.min().x(); CTX.max[0] = bb.max().x();
+  CTX.min[1] = bb.min().y(); CTX.max[1] = bb.max().y();
+  CTX.min[2] = bb.min().z(); CTX.max[2] = bb.max().z();
+  FinishUpBoundingBox();
 }
 
 int ParseFile(char *f, int close, int warn_if_missing)
 {
   char yyname_old[256], tmp[256];
   FILE *yyin_old, *fp;
-  int yylineno_old, yyerrorstate_old, numviews_old, status;
+  int yylineno_old, yyerrorstate_old, numviews_old;
 
   // add 'b' for pure Windows programs: opening in text mode messes up
   // fsetpos/fgetpos (used e.g. for user-defined functions)
@@ -175,10 +205,6 @@ int ParseFile(char *f, int close, int warn_if_missing)
       break;
     }
   }
-  if(THEM)
-    status = THEM->status;
-  else
-    status = 0;
 
   if(close)
     fclose(yyin);
@@ -186,8 +212,6 @@ int ParseFile(char *f, int close, int warn_if_missing)
   if(GMODEL) delete GMODEL;
   GMODEL = new gmshModel;
 
-  SetBoundingBox();
-
   strncpy(yyname, yyname_old, 255);
   yyin = yyin_old;
   yyerrorstate = yyerrorstate_old;
@@ -200,18 +224,15 @@ int ParseFile(char *f, int close, int warn_if_missing)
   }
   
   GMSH_Solve_Plugin *sp = GMSH_PluginManager::instance()->findSolverPlugin();
-  if(sp) {
-    sp->readSolverFile(f);
-  }
+  if(sp) sp->readSolverFile(f);
 
-  return status;
+  return 1;
 }
 
 void ParseString(char *str)
 {
+  if(!str) return;
   FILE *fp;
-  if(!str)
-    return;
   if((fp = fopen(CTX.tmp_filename_fullpath, "w"))) {
     fprintf(fp, str);
     fprintf(fp, "\n");
@@ -227,30 +248,25 @@ void SetProjectName(char *name)
 
   strncpy(CTX.filename, name, 255);
   strncpy(CTX.base_filename, base, 255);
-  strncpy(THEM->name, CTX.base_filename, 255);
 
 #if defined(HAVE_FLTK)
-  if(!CTX.batch)
-    WID->set_title(CTX.filename);
+  if(!CTX.batch) WID->set_title(CTX.filename);
 #endif
 }
 
 int MergeProblem(char *name, int warn_if_missing)
 {
-  char ext[256], base[256], tmp[256];
-  int status;
-  FILE *fp;
-
   // added 'b' for pure Windows programs, since some of these files
   // contain binary data
+  FILE *fp;
   if(!(fp = fopen(name, "rb"))){
-    if(warn_if_missing)
-      Msg(WARNING, "Unable to open file '%s'", name);
+    if(warn_if_missing) Msg(WARNING, "Unable to open file '%s'", name);
     return 0;
   }
 
   Msg(STATUS2, "Reading '%s'", name);
 
+  char ext[256], base[256];
   SplitFileName(name, base, ext);
 
 #if defined(HAVE_FLTK)
@@ -261,6 +277,7 @@ int MergeProblem(char *name, int warn_if_missing)
       if(fl_choice("File '%s' is in gzip format.\n\nDo you want to uncompress it?", 
 		   "Cancel", "Uncompress", NULL, name)){
 	fclose(fp);
+	char tmp[256];
 	sprintf(tmp, "gunzip -c %s > %s", name, base);
 	SystemCall(tmp);
 	if(!strcmp(CTX.filename, name)) // this is the project file
@@ -270,88 +287,57 @@ int MergeProblem(char *name, int warn_if_missing)
     }
   }
 #endif
-  
-  if(!strcmp(ext, ".stl") || !strcmp(ext, ".STL") || !strcmp(ext, ".mesh")) {
-    if(THEM->bds) delete THEM->bds;
-    THEM->bds = new BDS_Mesh;
-    if(!strcmp(ext, ".mesh"))
-      THEM->bds->read_mesh(name);
-    else
-      THEM->bds->read_stl(name, CTX.mesh.stl_distance_tol);
-    THEM->bds->classify(CTX.mesh.dihedral_angle_tol * M_PI / 180);
-    BDS_To_Mesh(THEM);
-    THEM->bds_mesh = new BDS_Mesh(*THEM->bds);
-    BDS_To_Mesh_2(THEM);
-    THEM->status = 2;
-    SetBoundingBox();
-    status = THEM->status;
+
+  int status = 0;
+  if(!strcmp(ext, ".stl") || !strcmp(ext, ".STL")){
+    if(!GMODEL) GMODEL = new gmshModel;
+    status = GMODEL->readSTL(name, CTX.mesh.stl_distance_tol);
   }
 #if defined(HAVE_FLTK)
   else if(!strcmp(ext, ".pnm") || !strcmp(ext, ".PNM") ||
 	  !strcmp(ext, ".pbm") || !strcmp(ext, ".PBM") ||
 	  !strcmp(ext, ".pgm") || !strcmp(ext, ".PGM") ||
 	  !strcmp(ext, ".ppm") || !strcmp(ext, ".PPM")) {
-    read_pnm(name);
-    SetBoundingBox();
-    status = 0;
+    status = read_pnm(name);
   }
   else if(!strcmp(ext, ".bmp") || !strcmp(ext, ".BMP")) {
-    read_bmp(name);
-    SetBoundingBox();
-    status = 0;
+    status = read_bmp(name);
   }
 #if defined(HAVE_LIBJPEG)
   else if(!strcmp(ext, ".jpg") || !strcmp(ext, ".JPG") ||
 	  !strcmp(ext, ".jpeg") || !strcmp(ext, ".JPEG")) {
-    read_jpeg(name);
-    SetBoundingBox();
-    status = 0;
+    status = read_jpeg(name);
   }
 #endif
 #if defined(HAVE_LIBPNG)
   else if(!strcmp(ext, ".png") || !strcmp(ext, ".PNG")) {
-    read_png(name);
-    SetBoundingBox();
-    status = 0;
+    status = read_png(name);
   }
 #endif
 #endif
   else {
     fpos_t position;
     fgetpos(fp, &position);
+    char tmp[256];
     fgets(tmp, sizeof(tmp), fp);
     fsetpos(fp, &position);
-
-    if(!strncmp(tmp, "$PTS", 4) || 
-       !strncmp(tmp, "$NO", 3) || 
-       !strncmp(tmp, "$PARA", 5) || 
-       !strncmp(tmp, "$ELM", 4) ||
-       !strncmp(tmp, "$MeshFormat", 4)) {
-      if(THEM->status < 0)
-	mai3d(0);
-
-      if(!GMODEL) 
-	GMODEL = new gmshModel;
-      GMODEL->readMSH(name);
-
-      SetBoundingBox();
-      status = THEM->status;
+    if(!strncmp(tmp, "$PTS", 4) || !strncmp(tmp, "$NO", 3) || 
+       !strncmp(tmp, "$PARA", 5) || !strncmp(tmp, "$ELM", 4) ||
+       !strncmp(tmp, "$MeshFormat", 11)) {
+      if(!GMODEL) GMODEL = new gmshModel;
+      status = GMODEL->readMSH(name);
     }
-    else if(!strncmp(tmp, "$PostFormat", 11) ||
-	    !strncmp(tmp, "$View", 5)) {
-      ReadView(fp, name);
-      SetBoundingBox();
-      status = 0;
+    else if(!strncmp(tmp, "$PostFormat", 11) || !strncmp(tmp, "$View", 5)) {
+      status = ReadView(name);
     }
     else {
       status = ParseFile(name, 1);
     }
   }
 
+  SetBoundingBox();
   Msg(STATUS2, "Read '%s'", name);
-
   fclose(fp);
-
   return status;
 }
 
@@ -369,19 +355,13 @@ void OpenProblem(char *name)
   srand(1);
 
   SetProjectName(name);
-
-  int status = MergeProblem(name);
-
+  MergeProblem(name);
   ApplyLcFactor();
 
   CTX.threads_lock = 0;
 
-  if(!status)
-    mai3d(0);
-
 #if defined(HAVE_FLTK)
-  if(!CTX.batch)
-    WID->reset_visibility();
+  if(!CTX.batch) WID->reset_visibility();
   ZeroHighlight();
 #endif
 }