diff --git a/Mesh/meshGFaceDelaunayInsertion.cpp b/Mesh/meshGFaceDelaunayInsertion.cpp
index 27c522151cb49e56cba4badf13c16d78f8dac617..fe3b64f0aea6575933ba44d0278210d999c3349d 100644
--- a/Mesh/meshGFaceDelaunayInsertion.cpp
+++ b/Mesh/meshGFaceDelaunayInsertion.cpp
@@ -1,4 +1,4 @@
-// $Id: meshGFaceDelaunayInsertion.cpp,v 1.22 2008-03-30 13:10:16 remacle Exp $
+// $Id: meshGFaceDelaunayInsertion.cpp,v 1.23 2008-03-30 18:39:32 remacle Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -34,6 +34,18 @@
 #include "Context.h"
 extern Context_T CTX;
 
+const double LIMIT_ = 0.5 * sqrt(2.0);
+
+static bool isActive ( MTri3 *t , double limit_, int &active){
+  if (t->isDeleted()) return false;
+  for (active=0;active<3;active++){
+    MTri3 *neigh = t->getNeigh(active);
+    if (!neigh || neigh->getRadius() < limit_)return true;
+  }
+  return false;
+}
+
+
 void circumCenterXY(double *p1, double *p2, double *p3, double *res)
 {
   double d, a1, a2, a3;
@@ -387,6 +399,7 @@ double getSurfUV(MTriangle *t, std::vector<double> &Us, std::vector<double> &Vs)
 
 bool insertVertex(GFace *gf, MVertex *v, double *param , MTri3 *t,
                   std::set<MTri3*, compareTri3Ptr> &allTets,
+                  std::set<MTri3*, compareTri3Ptr> *activeTets,
                   std::vector<double> &vSizes, std::vector<double> &vSizesBGM,
                   std::vector<double> &Us, std::vector<double> &Vs,
                   double *metric = 0)
@@ -440,9 +453,17 @@ bool insertVertex(GFace *gf, MVertex *v, double *param , MTri3 *t,
     newVolume += ss;
     ++it;
   }
-  if (fabs(oldVolume - newVolume) < 1.e-12 * oldVolume){      
+  if (fabs(oldVolume - newVolume) < 1.e-12 * oldVolume && shell.size() > 3){      
     connectTris(new_cavity.begin(),new_cavity.end());      
     allTets.insert(newTris,newTris+shell.size());
+    if (activeTets){
+      for (std::list<MTri3*>::iterator i = new_cavity.begin();i!=new_cavity.end();++i){
+	int active_edge;
+	if(isActive(*i,LIMIT_,active_edge)){
+	  (*activeTets).insert(*i);
+	}
+      }
+    }
     delete [] newTris;
     return true;
   }
@@ -503,11 +524,23 @@ void _printTris(char *name, std::set<MTri3*, compareTri3Ptr> &AllTris,
 }
 
 
-static void insertAPoint(GFace *gf, std::set<MTri3*,compareTri3Ptr>::iterator it, double center[2],double metric[3], 
-			 std::vector<double> &Us, std::vector<double> &Vs,
-			 std::vector<double> &vSizes, std::vector<double> &vSizesBGM,
-			 std::set<MTri3*,compareTri3Ptr> &AllTris){
-  MTri3 *worst = *it;
+static void insertAPoint(GFace *gf, 			 
+			 std::set<MTri3*,compareTri3Ptr>::iterator it, 
+			 double center[2],
+			 double metric[3], 
+			 std::vector<double> &Us, 
+			 std::vector<double> &Vs,
+			 std::vector<double> &vSizes, 
+			 std::vector<double> &vSizesBGM,
+			 std::set<MTri3*,compareTri3Ptr> &AllTris,
+			 std::set<MTri3*,compareTri3Ptr> * ActiveTris = 0,
+			 MTri3 *worst = 0){
+  if (worst){
+    it = AllTris.find(worst);
+    if (worst != *it)throw;
+  }
+  else worst = *it;
+
   MTri3 *ptin = 0;
   double uv[2];
   MTriangle *base = worst->tri();
@@ -543,12 +576,12 @@ static void insertAPoint(GFace *gf, std::set<MTri3*,compareTri3Ptr>::iterator it
     Us.push_back(center[0]);
     Vs.push_back(center[1]);
     
-    if (!insertVertex(gf, v, center, worst, AllTris, vSizes, vSizesBGM, 
+    if (!insertVertex(gf, v, center, worst, AllTris,ActiveTris, vSizes, vSizesBGM, 
 		      Us, Vs, metric)) {
       Msg(DEBUG2,"2D Delaunay : a cavity is not star shaped");
       AllTris.erase(it);
       worst->forceRadius(-1);
-      AllTris.insert(worst);		  
+      AllTris.insert(worst);		        
       delete v;
     }
     else 
@@ -625,15 +658,6 @@ void gmshBowyerWatson(GFace *gf)
   
 */
 
-static bool isActive ( MTri3 *t , double limit_, int &active){
-  if (t->isDeleted()) return false;
-  for (active=0;active<3;active++){
-    MTri3 *neigh = t->getNeigh(active);
-    if (!neigh || neigh->getRadius() < limit_)return true;
-  }
-  return false;
-}
-
 static double length_metric ( const double p[2], const double q[2], const double metric[3])
 {
   return sqrt (   (p[0]-q[0]) * metric [0] * (p[0]-q[0]) +
@@ -667,7 +691,6 @@ static double length_metric ( const double p[2], const double q[2], const double
 
 
 void gmshBowyerWatsonFrontal(GFace *gf){
-//void gmshFrontalDelaunay (GFace *gf){
   std::set<MTri3*,compareTri3Ptr> AllTris;
   std::vector<double> vSizes, vSizesBGM, Us, Vs;
   buidMeshGenerationDataStructures(gf, AllTris, vSizes, vSizesBGM, Us, Vs);
@@ -676,8 +699,6 @@ void gmshBowyerWatsonFrontal(GFace *gf){
   int nbSwaps = edgeSwapPass(gf, AllTris, SWCR_DEL, Us, Vs, vSizes, vSizesBGM);
   Msg(DEBUG2,"Delaunization of the initial mesh done (%d swaps)", nbSwaps);
   
-  const double LIMIT_ = 0.5 * sqrt(2.0);
-
   // insert points
   int ITER = 0, active_edge;
   while (1){
@@ -747,7 +768,10 @@ void gmshBowyerWatsonFrontal(GFace *gf){
     const double p    = 0.5*length_metric (P,Q,metric);// / RATIO;
     //    const double p    = 0.5*sqrt(DSQR(P[0]-Q[0])+DSQR(P[1]-Q[1]));//length_metric (P,Q,metric);
     const double q    = length_metric (center,midpoint,metric);
-    const double rhoM = 0.5 * (vSizes[base->getVertex(ip1)->getNum()] + vSizes[base->getVertex(ip2)->getNum()] ) / sqrt(3.);// * RATIO;
+    const double rhoM1 = 0.5 * (vSizes[base->getVertex(ip1)->getNum()] + vSizes[base->getVertex(ip2)->getNum()] ) / sqrt(3.);// * RATIO;
+    const double rhoM2 = 0.5 * (vSizesBGM[base->getVertex(ip1)->getNum()] + vSizesBGM[base->getVertex(ip2)->getNum()] ) / sqrt(3.);// * RATIO;
+    const double rhoM  = Extend1dMeshIn2dSurfaces() ? std::min(rhoM1, rhoM2) : rhoM2;
+    
 
     double ps = dir[0]*(P[0]-Q[0]) + dir[1]*(P[1]-Q[1]) ;
     //    printf("ratio = %12.5E dir %g %g m %g %g %g %g ps = %12.5E\n",RATIO,dir[0],dir[1],metric[0],metric[1],metric[2],rhoM*sqrt(3.),ps); 
@@ -772,6 +796,93 @@ void gmshBowyerWatsonFrontal(GFace *gf){
     insertAPoint(gf,it,newPoint,metric,Us,Vs,vSizes,vSizesBGM,AllTris);
     //    if (ITER++ == 5)break;
   } 
-  //  _printTris ("frontal.pos", AllTris, Us,Vs);
+  _printTris ("frontal.pos", AllTris, Us,Vs);
+  transferDataStructure(gf, AllTris); 
+} 
+
+void gmshBowyerWatsonFrontal2(GFace *gf){
+  std::set<MTri3*,compareTri3Ptr> AllTris;
+  std::set<MTri3*,compareTri3Ptr> ActiveTris;
+  std::vector<double> vSizes, vSizesBGM, Us, Vs;
+  buidMeshGenerationDataStructures(gf, AllTris, vSizes, vSizesBGM, Us, Vs);
+
+  // delaunise the initial mesh
+  int nbSwaps = edgeSwapPass(gf, AllTris, SWCR_DEL, Us, Vs, vSizes, vSizesBGM);
+  Msg(DEBUG2,"Delaunization of the initial mesh done (%d swaps)", nbSwaps);
+  
+  int ITER = 0, active_edge;
+  // compute active triangle
+  std::set<MTri3*,compareTri3Ptr>::iterator it = AllTris.begin();
+  for ( ; it!=AllTris.end();++it){
+    if(isActive(*it,LIMIT_,active_edge))
+      ActiveTris.insert(*it);
+    else if ((*it)->getRadius() < LIMIT_)break;
+  }
+  
+  // insert points
+  while (1){
+    if (!ActiveTris.size() || ActiveTris.size() > 1000)break;
+    MTri3 *worst = (*ActiveTris.begin());
+    ActiveTris.erase(ActiveTris.begin());
+    printf("active_tris.size = %d\n",ActiveTris.size());
+
+    if (!worst->isDeleted() && isActive(worst,LIMIT_,active_edge)){      
+      if(ITER++ % 5000 == 0)
+	Msg(DEBUG1,"%7d points created -- Worst tri radius is %8.3f",
+	    vSizes.size(), worst->getRadius());
+      // compute circum center of that guy
+      double center[2],uv[2],metric[3],r2;
+      MTriangle *base = worst->tri();
+      circUV(base, Us, Vs, center, gf);
+      double pa[2] = {(Us[base->getVertex(0)->getNum()] + 
+		       Us[base->getVertex(1)->getNum()] + 
+		       Us[base->getVertex(2)->getNum()]) / 3.,
+		      (Vs[base->getVertex(0)->getNum()] + 
+		       Vs[base->getVertex(1)->getNum()] + 
+		       Vs[base->getVertex(2)->getNum()]) / 3.};
+      buildMetric(gf, pa, metric);
+      circumCenterMetric(worst->tri(), metric, Us, Vs, center, r2); 
+      // compute the middle point of the edge
+      int ip1 = active_edge - 1 < 0 ? 2 : active_edge - 1;
+      int ip2 = active_edge;
+      //     printf("the active edge is %d : %g %g -> %g %g\n",active_edge,base->getVertex(ip1)->x(),base->getVertex(ip1)->y(),
+      // 	   base->getVertex(ip2)->x(),base->getVertex(ip2)->y());
+      double P[2] =  {Us[base->getVertex(ip1)->getNum()],  
+		      Vs[base->getVertex(ip1)->getNum()]};
+      double Q[2] =  {Us[base->getVertex(ip2)->getNum()], 
+		      Vs[base->getVertex(ip2)->getNum()]};
+      double midpoint[2] =  {0.5*(P[0]+Q[0]),0.5*(P[1]+Q[1])};
+      
+      // now we have the edge center and the center of the circumcircle, 
+      // we try to find a point that would produce a perfect triangle while
+      // connecting the 2 points of the active edge
+      
+      double dir[2] = {center[0]-midpoint[0],center[1]-midpoint[1]};
+      double norm = sqrt(dir[0]*dir[0]+dir[1]*dir[1]);
+      dir[0]/=norm;
+      dir[1]/=norm;
+      const double RATIO = sqrt(  dir[0]*dir[0]*metric[0]+
+				  2*dir[1]*dir[0]*metric[1]+
+				  dir[1]*dir[1]*metric[2]);    
+      
+      
+      const double p    = 0.5*length_metric (P,Q,metric);// / RATIO;
+      const double q    = length_metric (center,midpoint,metric);
+      const double rhoM = 0.5 * (vSizes[base->getVertex(ip1)->getNum()] + vSizes[base->getVertex(ip2)->getNum()] ) / sqrt(3.);// * RATIO;
+      
+      const double rhoM_hat = std::min(std::max(rhoM,p),(p*p+q*q)/(2*q));
+      const double d = (rhoM_hat + sqrt (rhoM_hat*rhoM_hat - p*p))/RATIO;
+      
+      double newPoint[2] = 
+	{
+	  midpoint[0] + d * dir[0],
+	  midpoint[1] + d * dir[1]
+	};
+      insertAPoint(gf,AllTris.end(),newPoint,metric,Us,Vs,vSizes,vSizesBGM,AllTris,&ActiveTris,worst);
+    } 
+  }
+
+  _printTris ("frontal.pos", AllTris, Us,Vs);
   transferDataStructure(gf, AllTris); 
 } 
+