diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index 62d046b4590d66a7e0b02cdb22ed3019a892f256..3b659a7ef9a2660769aad6d1157fc22ec8c2d5e2 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -975,7 +975,7 @@ StringXNumber MeshOptions_Number[] = {
     "Only display elements whose longest edge is greater than RadiusInf" },
   { F|O, "RadiusSup" , opt_mesh_radius_sup , 0.0 , 
     "Only display elements whose longest edge is smaller than RadiusSup" },
-  { F|O, "RandomFactor" , opt_mesh_rand_factor , 1.e-4 ,
+  { F|O, "RandomFactor" , opt_mesh_rand_factor , 1.e-10 ,
     "Random factor used in 2D and 3D meshing algorithm (test other values when the algorithm fails)" },
   { F|O, "RecombineAlgo" , opt_mesh_recombine_algo , 1 ,
     "Recombine algorithm (1=mixed triangles-quadrangles, 2=all quadrangles)" }, 
diff --git a/Geo/GRegion.cpp b/Geo/GRegion.cpp
index a5cd03c822920e6697401797f83415529705878a..9273ded37ee46d2ce1d2532ffd3203e8f4330905 100644
--- a/Geo/GRegion.cpp
+++ b/Geo/GRegion.cpp
@@ -1,4 +1,4 @@
-// $Id: GRegion.cpp,v 1.10 2006-08-26 13:34:46 geuzaine Exp $
+// $Id: GRegion.cpp,v 1.11 2006-09-11 15:23:54 remacle Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -110,3 +110,22 @@ void GRegion::deleteMeshPartitions()
   for(unsigned int i = 0; i < pyramids.size(); i++)
     pyramids[i]->setPartition(0);
 }
+std::list<GEdge*>  GRegion::edges() const
+{
+  std::list<GEdge*> e;
+  std::list<GFace *>::const_iterator it =  l_faces.begin();
+  while (it != l_faces.end())
+    {
+      std::list<GEdge*> e2;
+      e2 = (*it)->edges();
+      std::list<GEdge*>::const_iterator it2 = e2.begin();
+      while (it2 != e2.end())
+	{
+	  if (std::find(e.begin(),e.end(),*it2) == e.end())
+	    e.push_back(*it2);
+	  ++it2;
+	}
+      ++it;
+    }
+  return e;
+}
diff --git a/Geo/GRegion.h b/Geo/GRegion.h
index ebc66decf3c11c7c1d036d49b6bc95c2315d6e3c..2e0fe1d484d3db13d7172c7fdc991d835b2a7ef2 100644
--- a/Geo/GRegion.h
+++ b/Geo/GRegion.h
@@ -36,6 +36,9 @@ class GRegion : public GEntity {
   virtual int dim() const {return 3;}
   virtual void setVisibility(char val, bool recursive=false);
   virtual std::list<GFace*> faces() const{return l_faces;}
+  virtual std::list<GEdge*> edges() const;
+  void set(std::list<GFace*> &f) {l_faces= f;}
+  
 
   // The bounding box
   virtual SBoundingBox3d bounds() const; 
diff --git a/Geo/MElement.h b/Geo/MElement.h
index 38d5d31157c30da7f3690d3a7ea99b25f17222b2..4cea2e14deba5fa83882cb8f2e20f8d0a4bda995 100644
--- a/Geo/MElement.h
+++ b/Geo/MElement.h
@@ -995,4 +995,5 @@ class MPyramid14 : public MPyramid {
   }
 };
 
+  
 #endif
diff --git a/Mesh/2D_DivAndConq.cpp b/Mesh/2D_DivAndConq.cpp
index bdb0131b99b0b87e1b0f381f178bc34dd708c8be..26b55470a4f4988ecbbdf1257be5e7edc5dc6344 100644
--- a/Mesh/2D_DivAndConq.cpp
+++ b/Mesh/2D_DivAndConq.cpp
@@ -1,4 +1,4 @@
-// $Id: 2D_DivAndConq.cpp,v 1.21 2006-01-06 00:34:25 geuzaine Exp $
+// $Id: 2D_DivAndConq.cpp,v 1.22 2006-09-11 15:23:54 remacle Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -183,7 +183,7 @@ Segment UpperCommonTangent(DT vl, DT vr)
 
 /* return 1 if the point k is NOT in the circumcircle of
    triangle hij */
-
+#ifndef HAVE_TETGEN
 int Qtest(PointNumero h, PointNumero i, PointNumero j, PointNumero k)
 {
   double xc, yc, rcarre, distca;
@@ -209,6 +209,28 @@ int Qtest(PointNumero h, PointNumero i, PointNumero j, PointNumero k)
   else
     return (0); /* point not in circle, because no circle !     */
 }
+#else 
+#include "tetgen.h"
+int Qtest(PointNumero h, PointNumero i, PointNumero j, PointNumero k)
+{
+  exactinit() ;
+  if((h == i) && (h == j) && (h == k)) {
+    Msg(GERROR, "3 identical points in Qtest");
+    return (0); /* returning 1 will cause looping for ever */
+  }
+  
+  REAL pa[2] = {(REAL)pPointArray[h].where.h,(REAL)pPointArray[h].where.v};
+  REAL pb[2] = {(REAL)pPointArray[i].where.h,(REAL)pPointArray[i].where.v};
+  REAL pc[2] = {(REAL)pPointArray[j].where.h,(REAL)pPointArray[j].where.v};
+  REAL pd[2] = {(REAL)pPointArray[k].where.h,(REAL)pPointArray[k].where.v};
+  
+  REAL result = incircle ( pa, pb, pc, pd ) * orient2d (pa,pb,pc);
+  //  Msg(INFO, "Qtest %12.5E",result);
+  
+  return (result < 0)?1:0;
+}
+#endif
+
 
 int merge(DT vl, DT vr)
 {
diff --git a/Mesh/Makefile b/Mesh/Makefile
index 78b0288b0e6140d0417641fff53df7bf1d28973e..229ed8216404e6c66f00d52cc8941acbf0e288d1 100644
--- a/Mesh/Makefile
+++ b/Mesh/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.130 2006-09-07 04:54:55 geuzaine Exp $
+# $Id: Makefile,v 1.131 2006-09-11 15:23:54 remacle Exp $
 #
 # Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 #
@@ -66,6 +66,7 @@ SRC = 1D_Mesh.cpp \
       meshGEdge.cpp \
       meshGFace.cpp \
       meshGFaceTransfinite.cpp \
+      meshGFaceDelaunayInstertion.cpp \
       meshGRegion.cpp \
       Nurbs.cpp \
       Interpolation.cpp \
diff --git a/Mesh/meshGFace.cpp b/Mesh/meshGFace.cpp
index dcbc2c7585363f423802fe8c045bcda67bc7a414..8c1067414dfc0a7e65685bf877ac5c0c45a882d4 100644
--- a/Mesh/meshGFace.cpp
+++ b/Mesh/meshGFace.cpp
@@ -1,4 +1,4 @@
-// $Id: meshGFace.cpp,v 1.12 2006-09-08 02:39:43 geuzaine Exp $
+// $Id: meshGFace.cpp,v 1.13 2006-09-11 15:23:54 remacle Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -443,7 +443,7 @@ void RefineMesh ( GFace *gf, BDS_Mesh &m , const int NIT)
 	    }
 	}
 	IT++;
-	//	Msg(INFO," %d split %d swap %d collapse %d smooth",nb_split,nb_swap,nb_collaps,nb_smooth);
+	Msg(INFO," iter %d minL %g maxL %g %d split %d swap %d collapse %d smooth",IT,minL,maxL,nb_split,nb_swap,nb_collaps,nb_smooth);
 	m.cleanup();  
     }  
 }
@@ -895,7 +895,7 @@ void gmsh2DMeshGenerator ( GFace *gf )
   // goto hhh;
    // start mesh generation
 
-  RefineMesh (gf,*m,20);
+  RefineMesh (gf,*m,15);
   //  OptimizeMesh (gf,*m,2);
 
 
diff --git a/Mesh/meshGRegion.cpp b/Mesh/meshGRegion.cpp
index 92d678ffe16a262866f3eb4f1203a3235af5e1b2..72023179e2fb97ff6563dc80cec2d7500ad23ee3 100644
--- a/Mesh/meshGRegion.cpp
+++ b/Mesh/meshGRegion.cpp
@@ -1,10 +1,15 @@
 #include "meshGRegion.h"
+#include "GModel.h"
 #include "GRegion.h"
 #include "GFace.h"
+#include "GEdge.h"
 #include "BDS.h"
 #include "Message.h"
 #include <vector>
 
+
+
+
 void getAllBoundingVertices (GRegion *gr, int importVolumeMesh, std::set<MVertex*> &allBoundingVertices )
 {
   std::list<GFace*> faces = gr->faces();
@@ -19,9 +24,9 @@ void getAllBoundingVertices (GRegion *gr, int importVolumeMesh, std::set<MVertex
       for (unsigned int i = 0; i< gf->triangles.size(); i++)
 	{
 	  MTriangle *t = gf->triangles[i];
-	  allBoundingVertices.insert (t->getVertex(0));
-	  allBoundingVertices.insert (t->getVertex(1));
-	  allBoundingVertices.insert (t->getVertex(2));
+	  for (int k=0;k<3;k++)
+	    if (allBoundingVertices.find(t->getVertex(k)) ==  allBoundingVertices.end())
+	      allBoundingVertices.insert (t->getVertex(k));
 	}
       ++it;
     }
@@ -66,8 +71,6 @@ void buildTetgenStructure (  GRegion *gr, tetgenio &in, std::vector<MVertex*> &
       ++it;
     }
 
-  Msg(INFO,"%d model faces -- NumFaces = %d",nbFace,faces.size());
-
   in.numberoffacets = nbFace;
   in.facetlist = new tetgenio::facet[in.numberoffacets];
   in.facetmarkerlist = new int[in.numberoffacets];
@@ -84,7 +87,8 @@ void buildTetgenStructure (  GRegion *gr, tetgenio &in, std::vector<MVertex*> &
 	  tetgenio::init(f);    
 	  f->numberofholes = 0;
 	  f->numberofpolygons = 1;
-	  tetgenio::polygon *p = f->polygonlist = new tetgenio::polygon[f->numberofpolygons];
+	  f->polygonlist = new tetgenio::polygon[f->numberofpolygons];
+          tetgenio::polygon *p = &f->polygonlist[0];
 	  tetgenio::init(p);    
 	  p->numberofvertices = 3;
 	  p->vertexlist = new int[p->numberofvertices];
@@ -97,17 +101,75 @@ void buildTetgenStructure (  GRegion *gr, tetgenio &in, std::vector<MVertex*> &
 	}
       ++it;
     }   
+
+
 }
 
 void TransferTetgenMesh(GRegion *gr, tetgenio &in, tetgenio &out, std::vector<MVertex*> & numberedV)
 {
-  for (int i = 0; i < out.numberofpoints; i++) 
+  int I = numberedV.size() + 1;
+  for (int i = numberedV.size(); i < out.numberofpoints; i++) 
     {
-      MVertex *v = new MVertex (out.pointlist[i * 3 + 0],out.pointlist[i * 3 + 1],out.pointlist[i * 3 + 2]); 
+      MVertex *v = new MVertex (out.pointlist[i * 3 + 0],
+				out.pointlist[i * 3 + 1],
+				out.pointlist[i * 3 + 2], gr); 
       gr->mesh_vertices.push_back(v);
       numberedV.push_back(v);
     }
  
+  Msg(INFO,"%d points %d edges and %d faces in the final mesh",out.numberofpoints,out.numberofedges,out.numberoftrifaces);
+  // Tetgen modifies both surface & edge mesh. So, we recreate all mes
+
+  {
+    std::list<GFace*> faces = gr->faces();
+    std::list<GFace*>::iterator it = faces.begin();
+    while (it != faces.end())
+      {
+	GFace *gf = (*it); 
+	for (int i=0;i<gf->triangles.size();i++)
+	  {
+	    delete gf->triangles[i];
+	  }
+	gf->triangles.clear();
+	++it;
+      }    
+  }    
+  
+  // re create 1D mesh 
+  // 2 be done ...
+  for (int i = 0; i < out.numberofedges; i++) 
+    {
+      MVertex *v[2];
+      v[0] = numberedV[out.edgelist[i * 2 + 0] -1];
+      v[1] = numberedV[out.edgelist[i * 2 + 1] -1];
+    }
+
+  // re-create the triangular meshes
+  for (int i = 0; i < out.numberoftrifaces; i++) 
+    {
+      MVertex *v[3];
+      v[0] = numberedV[out.trifacelist[i * 3 + 0] -1];
+      v[1] = numberedV[out.trifacelist[i * 3 + 1] -1];
+      v[2] = numberedV[out.trifacelist[i * 3 + 2] -1];
+      GFace *gf = gr->model()->faceByTag ( out.trifacemarkerlist[i] );
+      for (int j=0;j<3;j++)
+	{	  
+	  if ( v[j]->onWhat()->dim() == 3 )
+	    {
+	      v[j]->onWhat()->mesh_vertices.erase(std::find(v[j]->onWhat()->mesh_vertices.begin(),
+							    v[j]->onWhat()->mesh_vertices.end(),
+							    v[j]));
+	      //	      SPoint2 pp = gf->parFromPoint(SPoint3 (v[j]->x(),v[j]->y(),v[j]->z()));
+	      SPoint2 pp (0,0);
+	      MFaceVertex *v1b = new MFaceVertex (v[j]->x(),v[j]->y(),v[j]->z(),gf,pp.x(),pp.y() );
+	      numberedV[out.trifacelist[i * 3 + j] -1] = v1b;
+	      delete v[j];
+	      v[j] = v1b;
+	    }
+	}
+      MTriangle *t = new  MTriangle(v[0],v[1],v[2]);
+      gf->triangles.push_back(t);	  
+    }
   for (int i = 0; i < out.numberoftetrahedra; i++) {
     MVertex *v1 = numberedV[out.tetrahedronlist[i * 4 + 0] -1];
     MVertex *v2 = numberedV[out.tetrahedronlist[i * 4 + 1] -1];
@@ -116,10 +178,10 @@ void TransferTetgenMesh(GRegion *gr, tetgenio &in, tetgenio &out, std::vector<MV
     MTetrahedron *t = new  MTetrahedron(v1,v2,v3,v4);
     gr->tetrahedra.push_back(t);
   }
-
- 
-}
   
+  
+}
+
 
 #endif
 
@@ -200,7 +262,7 @@ void TransferVolumeMesh(GRegion *gr, Ng_Mesh * _ngmesh, std::vector<MVertex*> &n
     {
       double tmp[3];
       Ng_GetPoint(_ngmesh, i+1, tmp);
-      MVertex *v = new MVertex (tmp[0],tmp[1],tmp[2]);
+      MVertex *v = new MVertex (tmp[0],tmp[1],tmp[2],gr);
       numberedV.push_back(v);
       gr->mesh_vertices.push_back(v);
     }
@@ -243,7 +305,7 @@ int intersect_line_triangle ( double X[3],
 {
   double mat[3][3], det;
   double b[3], res[3];
-  const double eps_prec = 1.e-5;
+  const double eps_prec = 1.e-9;
 
   mat[0][0] = X[1] - X[0];
   mat[0][1] = X[2] - X[0];
@@ -362,23 +424,35 @@ void meshGRegion :: operator() (GRegion *gr)
   // Send a messsage to the GMSH environment
   Msg(STATUS2, "Meshing volume %d", gr->tag());
 
-  // orient the triangles of with respect to this region
-  meshNormalsPointOutOfTheRegion (gr); 
-  
   if(CTX.mesh.algo3d == DELAUNAY_TETGEN)
     {
 #if !defined(HAVE_TETGEN)
     Msg(GERROR, "Tetgen is not compiled in this version of Gmsh");
 #else
+    // put all the faces in the same model
+    GModel::riter rit = gr->model()->firstRegion() ;
+    if (gr != *rit)return;    
+    std::list<GFace*> faces = gr->faces();
+    std::list<GFace*> allFaces;
+    GModel::fiter fit = gr->model()->firstFace() ;
+    while (fit != gr->model()->lastFace())
+      {
+	allFaces.push_back(*fit);
+	++fit;
+      }
+    gr->set ( allFaces );
+    // mesh with tetgen, possibly changing the mesh on boundaries
     tetgenio in, out;
     std::vector<MVertex*> numberedV;
     char opts[128];
     buildTetgenStructure (  gr, in, numberedV);
-    sprintf(opts, "pqa%f%c", (float)CTX.mesh.quality,
+    sprintf(opts, "pe%c",
 	    (CTX.verbosity < 3)? 'Q': (CTX.verbosity > 6)? 'V': '\0');
-    Msg(STATUS2, "Meshing with volume constraint %f", (float)CTX.mesh.quality);
     tetrahedralize(opts, &in, &out);
     TransferTetgenMesh(gr, in, out, numberedV);
+    // restore the initial set of faces
+    gr->set ( faces );
+
 #endif
     }
 
@@ -387,6 +461,8 @@ void meshGRegion :: operator() (GRegion *gr)
 #if !defined(HAVE_NETGEN)
     Msg(GERROR, "Netgen is not compiled in this version of Gmsh");
 #else
+    // orient the triangles of with respect to this region
+    meshNormalsPointOutOfTheRegion (gr);     
     std::vector<MVertex*> numberedV;
     Ng_Mesh * _ngmesh = buildNetgenStructure (gr, 0, numberedV);
     Ng_Meshing_Parameters mp;
diff --git a/contrib/Tetgen/tetgen.h b/contrib/Tetgen/tetgen.h
index e67f87d14a42fc09d7447a7f529cba6e981bd2e9..896c3f2279614d83acf0ac35c4d489734ed599ad 100644
--- a/contrib/Tetgen/tetgen.h
+++ b/contrib/Tetgen/tetgen.h
@@ -520,7 +520,9 @@ class tetgenbehavior {
 ///////////////////////////////////////////////////////////////////////////////
 
 REAL exactinit();
+REAL incircle(REAL *pa, REAL *pb, REAL *pc, REAL *pd);
 REAL orient3d(REAL *pa, REAL *pb, REAL *pc, REAL *pd);
+REAL orient2d(REAL *pa, REAL *pb, REAL *pc);
 REAL insphere(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe);
 
 ///////////////////////////////////////////////////////////////////////////////