diff --git a/Geo/GFace.cpp b/Geo/GFace.cpp
index 82a10bf31fb33cfe208ee1b64fd5c017f4696c8f..e4603f866c7a4a6c3c34dbfef6e182f59d482f0b 100644
--- a/Geo/GFace.cpp
+++ b/Geo/GFace.cpp
@@ -952,6 +952,12 @@ GPoint GFace::closestPoint(const SPoint3 &queryPoint, const double initialGuess[
 
   Range<double> uu = parBounds(0);
   Range<double> vv = parBounds(1);
+  {
+    GPoint pnt = point(initialGuess[0], initialGuess[1]);
+    SPoint3 spnt(pnt.x(), pnt.y(), pnt.z());
+    double dist = queryPoint.distance(spnt);
+    printf("dist = %12.5E\n",dist);
+  }
 
   // FILE *F = fopen ("hop.pos","w");
   // fprintf(F,"View \" \" {\n");
diff --git a/Geo/MQuadrangle.cpp b/Geo/MQuadrangle.cpp
index 92d70237321295ba7ba2100c71892751db477221..d4ad6538c7e63e9023a6ac930c6ad5f850f7090a 100644
--- a/Geo/MQuadrangle.cpp
+++ b/Geo/MQuadrangle.cpp
@@ -233,6 +233,8 @@ void MQuadrangle::getIntegrationPoints(int pOrder, int *npts, IntPt **pts)
 
 double  MQuadrangle::etaShapeMeasure()
 {
+  double AR = 1;//(minEdge()/maxEdge());
+  
   SVector3 v01 (_v[1]->x()-_v[0]->x(),_v[1]->y()-_v[0]->y(),_v[1]->z()-_v[0]->z());
   SVector3 v12 (_v[2]->x()-_v[1]->x(),_v[2]->y()-_v[1]->y(),_v[2]->z()-_v[1]->z());
   SVector3 v23 (_v[3]->x()-_v[2]->x(),_v[3]->y()-_v[2]->y(),_v[3]->z()-_v[2]->z());
@@ -262,7 +264,7 @@ double  MQuadrangle::etaShapeMeasure()
   angle = std::max(fabs(90. - a3),angle);
   angle = std::max(fabs(90. - a4),angle);
 
-  return sign*(1.-angle/90);
+  return sign*(1.-angle/90) * AR;
 }
 
 /// a shape measure for quadrangles
@@ -274,46 +276,6 @@ double  MQuadrangle::etaShapeMeasure()
 ///             1 + xi , 1 - xi ,  -(1-xi), -(1+xi)    
 double MQuadrangle::gammaShapeMeasure(){
   return etaShapeMeasure();
-  /*
-  // xi = -1 eta = -1 
-  const double dsf_corner1 [2][4] = {{0,0,-.5,.5},{0,0.5,-.5,0}};
-  // xi =  1 eta = -1 
-  const double dsf_corner2 [2][4] = {{0,0,-.5,.5},{0.5,0,0,-.5}};
-  // xi =  1 eta =  1 
-  const double dsf_corner3 [2][4] = {{.5,-.5,0,0},{0.5,0,0,-.5}};
-  // xi =  -1 eta =  1 
-  const double dsf_corner4 [2][4] = {{0,0,-.5,.5},{0.5,0,0,-.5}};
-  */
-  double QT[4] = {qmTriangle(_v[0],_v[1],_v[2],QMTRI_RHO),
-		  qmTriangle(_v[1],_v[2],_v[3],QMTRI_RHO), 
-		  qmTriangle(_v[2],_v[3],_v[0],QMTRI_RHO), 
-		  qmTriangle(_v[3],_v[0],_v[1],QMTRI_RHO)} ;
-  std::sort(QT,QT+4);
-  double quality = QT[0]*QT[1] / (QT[2] * QT[3]);
-
-  SVector3 v01 (_v[1]->x()-_v[0]->x(),_v[1]->y()-_v[0]->y(),_v[1]->z()-_v[0]->z());
-  SVector3 v12 (_v[2]->x()-_v[1]->x(),_v[2]->y()-_v[1]->y(),_v[2]->z()-_v[1]->z());
-  SVector3 v23 (_v[3]->x()-_v[2]->x(),_v[3]->y()-_v[2]->y(),_v[3]->z()-_v[2]->z());
-  SVector3 v30 (_v[0]->x()-_v[3]->x(),_v[0]->y()-_v[3]->y(),_v[0]->z()-_v[3]->z());
-
-  SVector3 a = crossprod(v01,v12);
-  SVector3 b = crossprod(v12,v23);
-  SVector3 c = crossprod(v23,v30);
-  SVector3 d = crossprod(v30,v01);
-
-  if (a.z() < 0 || b.z() < 0 || c.z() < 0 || d.z() < 0) return -quality;
-  
-  if (dot(a,b) < 0 || dot(a,c) < 0 || dot(a,d) < 0 )return -quality;
-
-  return quality;
-  /*
-  double J[3][3];
-  double detJ = getJacobian(-1,-1, J);
-  double C[2][2] = {{0,0}{0,0}};
-  for (int i=0;i<2;i++){
-    
-  }*/
-  
 }
 
 
diff --git a/Mesh/BackgroundMesh.cpp b/Mesh/BackgroundMesh.cpp
index a4750c55f927294a1ab3377847b1b2bdb862c445..d72e946bd9bd2f4bd9fa32f09e0bb643b38ab679 100644
--- a/Mesh/BackgroundMesh.cpp
+++ b/Mesh/BackgroundMesh.cpp
@@ -533,8 +533,9 @@ backgroundMesh::backgroundMesh(GFace *_gf, bool cfd)
   _octree = new MElementOctree(_triangles);
 
   // compute the mesh sizes at nodes
-  if (CTX::instance()->mesh.lcFromPoints)
+  if (CTX::instance()->mesh.lcFromPoints){
     propagate1dMesh(_gf);
+  }
   else {
     std::map<MVertex*, MVertex*>::iterator itv2 = _2Dto3D.begin();
     for ( ; itv2 != _2Dto3D.end(); ++itv2){
@@ -623,7 +624,8 @@ static void propagateValuesOnFace(GFace *_gf,
   }
 
   // Solve
-  _lsys->systemSolve();
+  if (myAssembler.sizeOfR())
+    _lsys->systemSolve();
 
   // save solution
   for (std::set<MVertex*>::iterator it = vs.begin(); it != vs.end(); ++it){
diff --git a/Mesh/Generator.cpp b/Mesh/Generator.cpp
index 09dc4721b575b9baac02c16297c0773ff8b7f52b..594c21fa3b8ec3e4690c767a03ca398e01ad372e 100644
--- a/Mesh/Generator.cpp
+++ b/Mesh/Generator.cpp
@@ -599,7 +599,7 @@ static void Mesh3D(GModel *m)
 	f.treat_region(gr);
       }
       //Recombine3D into hex
-      if(CTX::instance()->mesh.recombine3DAll || gr->meshAttributes.recombine3D){
+      if(CTX::instance()->mesh.recombine3DAll || gr->meshAttributes.recombine3D){	
 	Recombinator rec;
 	rec.execute();
 	Supplementary sup;
diff --git a/Mesh/directions3D.cpp b/Mesh/directions3D.cpp
index 0a88eb33496462ab93e0dabe11c01d776399588e..93418da7537eaf8408c2df284514547c27bfeb35 100644
--- a/Mesh/directions3D.cpp
+++ b/Mesh/directions3D.cpp
@@ -573,7 +573,8 @@ void Size_field::solve(GRegion* gr){
   //printf("number of tetrahedra = %d\n",count2);	
   //printf("volume = %f\n",volume);
 
-  system->systemSolve();
+  if (assembler.sizeOfR())
+    system->systemSolve();
 
   for(it=interior.begin();it!=interior.end();it++){
     assembler.getDofValue(*it,0,1,val);
diff --git a/Mesh/meshGFace.cpp b/Mesh/meshGFace.cpp
index e06b660df5518a9644602f4465d214165f4a184b..fd35db21853044bfc25a82b9229ca64fdf01646e 100644
--- a/Mesh/meshGFace.cpp
+++ b/Mesh/meshGFace.cpp
@@ -1737,6 +1737,7 @@ static bool meshGeneratorPeriodic(GFace *gf, bool debug = true)
     outputScalarField(m->triangles, name, 1);
   }
 
+
   // start mesh generation for periodic face
   if(!algoDelaunay2D(gf)){
     // need for a BGM for cross field
@@ -1766,32 +1767,46 @@ static bool meshGeneratorPeriodic(GFace *gf, bool debug = true)
   /// This is a structure that we need only for periodic cases
   /// We will duplicate the vertices (MVertex) that are on seams
   /// 
-  /*
-  {
+  
+  std::map<MVertex*, MVertex*> equivalence;
+  std::map<MVertex*, SPoint2> parametricCoordinates;
+  if(algoDelaunay2D(gf)){
     std::map<MVertex*, BDS_Point*> invertMap;
     std::map<BDS_Point*, MVertex*>::iterator it = recoverMap.begin();
-    std::map<BDS_Point*, MVertex*>::iterator it = recoverMap.begin();
     while(it != recoverMap.end()){
       // we have twice vertex MVertex with 2 different coordinates
-      std::map<MVertex*, BDS_Point*>::iterator invIt = invertMap.find((*it)->second);
+      MVertex  * mv1  =  it->second;
+      BDS_Point* bds = it->first;
+      std::map<MVertex*, BDS_Point*>::iterator invIt = invertMap.find(mv1);
       if (invIt != invertMap.end()){
-	BDS_Point* bds1 = (*invIt)->second; 	
-	BDS_Point* bds2 = (*it)->first;
-	MVertex  * mv1  =  (*it)->second;
 	// create a new "fake" vertex that will be destroyed afterwards
-	double t;
-	mv1->getParameter(0,t);
-	MVertex  * mv2  = new MEdgeVertex (mv1->x(),mv1->y(),mv1->z(),mv1->onWhat(), t);
-	(*it)->second = mv2;
-	std::map<BDS_Point*, MVertex*>::iterator itTemp = it;
-	++it;
-	recoverMap.erase(itTemp);	
+	MVertex  * mv2 ;
+	if (mv1->onWhat()->dim() == 1) {
+	  double t;
+	  mv1->getParameter(0,t);
+	  mv2  = new MEdgeVertex (mv1->x(),mv1->y(),mv1->z(),mv1->onWhat(), t,   ((MEdgeVertex*)mv1)->getLc());
+	}
+	else if (mv1->onWhat()->dim() == 0) {
+	  mv2  = new MVertex (mv1->x(),mv1->y(),mv1->z(),mv1->onWhat());
+	}
+	else
+	  Msg::Error("error in seam reconstruction");
+
+	it->second = mv2;
+	equivalence[mv2] = mv1;
+	parametricCoordinates[mv2] = SPoint2(bds->u,bds->v);
+	//	printf("new vertex created %p that replaces %p %g %g %g\n",mv2,mv1,mv2->x(),mv2->y(),mv2->z());
+	invertMap[mv2] = bds;
+      }
+      else {
+	parametricCoordinates[mv1] = SPoint2(bds->u,bds->v);
+	invertMap[mv1] = bds;
       }
-      else ++it;
-      invertMap[it->second] = it->first;
+      ++it;
     }
+    //    recoverMap.insert(new_relations.begin(), new_relations.end()); 
   }
-  */
+  Msg::Info("%d points that are duplicated for delaunay meshing",equivalence.size());
 
   // fill the small gmsh structures
   {
@@ -1847,17 +1862,29 @@ static bool meshGeneratorPeriodic(GFace *gf, bool debug = true)
     outputScalarField(m->triangles, name, 1);
   }
 
+  bool infty = false;
+  if (gf->getMeshingAlgo() == ALGO_2D_FRONTAL_QUAD || gf->getMeshingAlgo() == ALGO_2D_PACK_PRLGRMS)
+    infty = true;
+  if (infty)
+    buildBackGroundMesh (gf, &equivalence, &parametricCoordinates);
+  // BOUNDARY LAYER
+  modifyInitialMeshForTakingIntoAccountBoundaryLayers(gf);
+  
+
   if(algoDelaunay2D(gf)){
     if(gf->getMeshingAlgo() == ALGO_2D_FRONTAL)
-      bowyerWatsonFrontal(gf);
+      bowyerWatsonFrontal(gf, &equivalence, &parametricCoordinates);
     else if(gf->getMeshingAlgo() == ALGO_2D_FRONTAL_QUAD)
-      bowyerWatsonFrontalLayers(gf,true);
+      bowyerWatsonFrontalLayers(gf,true, &equivalence, &parametricCoordinates);
+    else if(gf->getMeshingAlgo() == ALGO_2D_PACK_PRLGRMS)
+      bowyerWatsonParallelograms(gf,&equivalence, &parametricCoordinates);
     else if(gf->getMeshingAlgo() == ALGO_2D_DELAUNAY ||
             gf->getMeshingAlgo() == ALGO_2D_AUTO)
-      bowyerWatson(gf);
+      bowyerWatson(gf,1000000000, &equivalence, &parametricCoordinates);
     else
       meshGFaceBamg(gf);
-    laplaceSmoothing(gf,CTX::instance()->mesh.nbSmoothing);
+    if (!infty || !(CTX::instance()->mesh.recombineAll || gf->meshAttributes.recombine)) 
+      laplaceSmoothing(gf, CTX::instance()->mesh.nbSmoothing, infty);
   }
 
   // delete the mesh
@@ -1872,6 +1899,7 @@ static bool meshGeneratorPeriodic(GFace *gf, bool debug = true)
                        gf->meshStatistics.best_element_shape,
                        gf->meshStatistics.nbTriangle,
                        gf->meshStatistics.nbGoodQuality);
+  gf->meshStatistics.status = GFace::DONE;
   return true;
 }
 
diff --git a/Mesh/meshGFaceDelaunayInsertion.cpp b/Mesh/meshGFaceDelaunayInsertion.cpp
index 1f066c9b47fa04f46cec22813923d45fd99c2d39..6adf207b67c69b3612265a22159c49481c577899 100644
--- a/Mesh/meshGFaceDelaunayInsertion.cpp
+++ b/Mesh/meshGFaceDelaunayInsertion.cpp
@@ -322,6 +322,7 @@ MTri3::MTri3(MTriangle *t, double lc, SMetric3 *metric, bidimMeshData * data, GF
       const double dy = base->getVertex(0)->y() - center[1];
       const double dz = base->getVertex(0)->z() - center[2];
       circum_radius = sqrt(dx * dx + dy * dy + dz * dz);
+      //      printf("%p %p %p %g %g %g %g %g %g %g %g %g circ %g lc %g\n",base->getVertex(0),base->getVertex(1),base->getVertex(2),pa[0],pa[1],pa[2],pb[0], pb[1],pb[2],pc[0],pc[1],pc[2],circum_radius,lc);
       circum_radius /= lc;
     }
     else {
@@ -867,14 +868,16 @@ static bool insertAPoint(GFace *gf, std::set<MTri3*,compareTri3Ptr>::iterator it
   }
 }
 
-void bowyerWatson(GFace *gf, int MAXPNT)
+void bowyerWatson(GFace *gf, int MAXPNT,
+		  std::map<MVertex* , MVertex*>* equivalence,  
+		  std::map<MVertex*, SPoint2> * parametricCoordinates)
 {
   std::set<MTri3*,compareTri3Ptr> AllTris;
-  bidimMeshData DATA;
+  bidimMeshData DATA(equivalence,parametricCoordinates);
 
   buildMeshGenerationDataStructures(gf, AllTris, DATA);
 
-  // _printTris ("before.pos", AllTris, Us,Vs);
+  //  if (equivalence)_printTris ("before.pos", AllTris.begin(), AllTris.end(), DATA);
   int nbSwaps = edgeSwapPass(gf, AllTris, SWCR_DEL, DATA);
   // _printTris ("after2.pos", AllTris, Us,Vs);
   Msg::Debug("Delaunization of the initial mesh done (%d swaps)", nbSwaps);
@@ -939,7 +942,7 @@ void bowyerWatson(GFace *gf, int MAXPNT)
     }
   }
 #endif
-  transferDataStructure(gf, AllTris, DATA);
+  transferDataStructure(gf, AllTris, DATA);  
 }
 
 /*
@@ -1151,11 +1154,13 @@ void optimalPointFrontalB (GFace *gf,
   }
 }
 
-void bowyerWatsonFrontal(GFace *gf)
+void bowyerWatsonFrontal(GFace *gf,
+		  std::map<MVertex* , MVertex*>* equivalence,  
+		  std::map<MVertex*, SPoint2> * parametricCoordinates)
 {
   std::set<MTri3*,compareTri3Ptr> AllTris;
   std::set<MTri3*,compareTri3Ptr> ActiveTris;
-  bidimMeshData DATA;
+  bidimMeshData DATA(equivalence,parametricCoordinates);
 
   buildMeshGenerationDataStructures(gf, AllTris, DATA);
 
@@ -1324,7 +1329,9 @@ void optimalPointFrontalQuadB (GFace *gf,
   return;
 }
 
-void buildBackGroundMesh (GFace *gf)
+void buildBackGroundMesh (GFace *gf,
+		  std::map<MVertex* , MVertex*>* equivalence,  
+		  std::map<MVertex*, SPoint2> * parametricCoordinates)
 {
   //  printf("build bak mesh\n");
   quadsToTriangles(gf, 100000);
@@ -1351,7 +1358,7 @@ void buildBackGroundMesh (GFace *gf)
     int CurvControl = CTX::instance()->mesh.lcFromCurvature;
     CTX::instance()->mesh.lcFromCurvature = 0;
     //  Do a background mesh
-    bowyerWatson(gf,4000);
+    bowyerWatson(gf,4000, equivalence,parametricCoordinates);
     //  Re-enable curv control if asked
     CTX::instance()->mesh.lcFromCurvature = CurvControl;
     // apply this to the BGM
@@ -1371,12 +1378,14 @@ void buildBackGroundMesh (GFace *gf)
 
 }
 
-void bowyerWatsonFrontalLayers(GFace *gf, bool quad)
+void bowyerWatsonFrontalLayers(GFace *gf, bool quad,
+		  std::map<MVertex* , MVertex*>* equivalence,  
+		  std::map<MVertex*, SPoint2> * parametricCoordinates)
 {
 
   std::set<MTri3*,compareTri3Ptr> AllTris;
   std::set<MTri3*,compareTri3Ptr> ActiveTris;
-  bidimMeshData DATA;
+  bidimMeshData DATA(equivalence, parametricCoordinates);
 
   if (quad){
     LIMIT_ = sqrt(2.) * .99;
@@ -1496,10 +1505,12 @@ void bowyerWatsonFrontalLayers(GFace *gf, bool quad)
   backgroundMesh::unset();
 }
 
-void bowyerWatsonParallelograms(GFace *gf)
+void bowyerWatsonParallelograms(GFace *gf,
+		  std::map<MVertex* , MVertex*>* equivalence,  
+		  std::map<MVertex*, SPoint2> * parametricCoordinates)
 {
   std::set<MTri3*,compareTri3Ptr> AllTris;
-  bidimMeshData DATA;
+  bidimMeshData DATA(equivalence, parametricCoordinates);
   std::vector<MVertex*> packed;
   std::vector<SMetric3> metrics;
 
diff --git a/Mesh/meshGFaceDelaunayInsertion.h b/Mesh/meshGFaceDelaunayInsertion.h
index 449cb68678b953c9c8ad58961e8bc0fdc6ba9d86..00ab44a4c4718799592b711a67a67fbfe9bdb5a3 100644
--- a/Mesh/meshGFaceDelaunayInsertion.h
+++ b/Mesh/meshGFaceDelaunayInsertion.h
@@ -24,10 +24,20 @@ struct bidimMeshData
   std::map<MVertex*,int> indices;
   std::vector<double> Us, Vs, vSizes, vSizesBGM;
   std::vector<SMetric3> vMetricsBGM;
+  std::map<MVertex* , MVertex*>* equivalence;
+  std::map<MVertex*, SPoint2> * parametricCoordinates;
   inline void addVertex (MVertex* mv, double u, double v, double size, double sizeBGM){
     int index = Us.size();
     if (mv->onWhat()->dim() == 2)mv->setIndex(index);
     else indices[mv] = index;
+    if (parametricCoordinates){
+      std::map<MVertex*, SPoint2>::iterator it =  parametricCoordinates->find(mv);
+      if (it != parametricCoordinates->end()){
+	u = it->second.x();
+	v = it->second.y();
+	//	printf("%g %g\n",u,v);
+      }
+    }
     Us.push_back(u);
     Vs.push_back(v);
     vSizes.push_back(size);
@@ -37,6 +47,17 @@ struct bidimMeshData
     if (mv->onWhat()->dim() == 2)return mv->getIndex();
     return indices[mv];
   }
+  inline MVertex * equivalent (MVertex *v1) const {
+    if (equivalence){
+      std::map<MVertex* , MVertex*>::iterator it = equivalence->find(v1);
+      if (it == equivalence->end())return 0;
+      return it->second;
+    }
+    return 0;
+  }
+  bidimMeshData (std::map<MVertex* , MVertex*>* e = 0, std::map<MVertex*, SPoint2> *p = 0) : equivalence(e), parametricCoordinates(p)  
+  {
+  }
 };
 
 
@@ -111,11 +132,21 @@ class compareTri3Ptr
 void connectTriangles(std::list<MTri3*> &);
 void connectTriangles(std::vector<MTri3*> &);
 void connectTriangles(std::set<MTri3*,compareTri3Ptr> &AllTris);
-void bowyerWatson(GFace *gf, int MAXPNT= 1000000000);
-void bowyerWatsonFrontal(GFace *gf);
-void bowyerWatsonFrontalLayers(GFace *gf, bool quad);
-void bowyerWatsonParallelograms(GFace *gf);
-void buildBackGroundMesh (GFace *gf);
+void bowyerWatson(GFace *gf, int MAXPNT= 1000000000,
+		  std::map<MVertex* , MVertex*>* equivalence= 0,  
+		  std::map<MVertex*, SPoint2> * parametricCoordinates= 0);
+void bowyerWatsonFrontal(GFace *gf,
+		  std::map<MVertex* , MVertex*>* equivalence= 0,  
+		  std::map<MVertex*, SPoint2> * parametricCoordinates= 0);
+void bowyerWatsonFrontalLayers(GFace *gf, bool quad,
+		  std::map<MVertex* , MVertex*>* equivalence= 0,  
+		  std::map<MVertex*, SPoint2> * parametricCoordinates= 0);
+void bowyerWatsonParallelograms(GFace *gf,
+		  std::map<MVertex* , MVertex*>* equivalence= 0,  
+		  std::map<MVertex*, SPoint2> * parametricCoordinates= 0);
+void buildBackGroundMesh (GFace *gf,
+		  std::map<MVertex* , MVertex*>* equivalence= 0,  
+		  std::map<MVertex*, SPoint2> * parametricCoordinates= 0);
 
 struct edgeXface
 {
diff --git a/Mesh/meshGFaceOptimize.cpp b/Mesh/meshGFaceOptimize.cpp
index 2e8d0a8410646fedd69dfa0a5e0786b2c0fe2d29..f008d10ff51e5f5adc6627cfcab447c884191ae4 100644
--- a/Mesh/meshGFaceOptimize.cpp
+++ b/Mesh/meshGFaceOptimize.cpp
@@ -23,6 +23,7 @@
 #include "OS.h"
 #include "SVector3.h"
 #include "SPoint3.h"
+#include "robustPredicates.h"
 
 #if defined(HAVE_BFGS)
 #include "stdafx.h"
@@ -53,7 +54,7 @@ static int diff2 (MElement *q1, MElement *q2)
   return 0;
 }
 
-static int SANITY_(GFace *gf,MQuadrangle *q1, MQuadrangle *q2, int count)
+static int SANITY_(GFace *gf,MQuadrangle *q1, MQuadrangle *q2)
 {
   for(unsigned int i = 0; i < gf->quadrangles.size(); i++){
     MQuadrangle *e1 = gf->quadrangles[i];
@@ -118,20 +119,22 @@ static void setLcsInit(MTriangle *t, std::map<MVertex*, double> &vSizes)
   }
 }
 
-static void setLcs(MTriangle *t, std::map<MVertex*, double> &vSizes)
+static void setLcs(MTriangle *t, std::map<MVertex*, double> &vSizes, bidimMeshData & data)
 {
   for(int i = 0; i < 3; i++){
     for(int j = i + 1; j < 3; j++){
       MVertex *vi = t->getVertex(i);
       MVertex *vj = t->getVertex(j);
-      double dx = vi->x() - vj->x();
-      double dy = vi->y() - vj->y();
-      double dz = vi->z() - vj->z();
-      double l = sqrt(dx * dx + dy * dy + dz * dz);
-      std::map<MVertex*,double>::iterator iti = vSizes.find(vi);
-      std::map<MVertex*,double>::iterator itj = vSizes.find(vj);
-      if(iti->second < 0 || iti->second > l) iti->second = l;
-      if(itj->second < 0 || itj->second > l) itj->second = l;
+      if (vi != data.equivalent(vj) && vj != data.equivalent(vi) ){
+	double dx = vi->x() - vj->x();
+	double dy = vi->y() - vj->y();
+	double dz = vi->z() - vj->z();
+	double l = sqrt(dx * dx + dy * dy + dz * dz);
+	std::map<MVertex*,double>::iterator iti = vSizes.find(vi);
+	std::map<MVertex*,double>::iterator itj = vSizes.find(vj);
+	if(iti->second < 0 || iti->second > l) iti->second = l;
+	if(itj->second < 0 || itj->second > l) itj->second = l;
+      }
     }
   }
 }
@@ -147,7 +150,7 @@ void buildMeshGenerationDataStructures(GFace *gf,
     setLcsInit(gf->triangles[i], vSizesMap);
 
   for(unsigned int i = 0;i < gf->triangles.size(); i++)
-    setLcs(gf->triangles[i], vSizesMap);
+    setLcs(gf->triangles[i], vSizesMap, data);
 
   // take care of embedded vertices
   {
@@ -227,6 +230,26 @@ void transferDataStructure(GFace *gf, std::set<MTri3*, compareTri3Ptr> &AllTris,
       if(pp < 0) t->revert();
     }
   }
+
+  if (data.equivalence){
+    std::vector<MTriangle*> newT;
+    for (unsigned int i=0;i<gf->triangles.size();i++){
+      MTriangle *t = gf->triangles[i];
+      MVertex *v[3];
+      for (int j=0;j<3;j++){
+	v[j] = t->getVertex(j);
+	std::map<MVertex* , MVertex*>::iterator it =  data.equivalence->find(v[j]);  
+	if (it != data.equivalence->end()){
+	  v[j] = it->second;
+	}
+      }
+      newT.push_back(new MTriangle (v[0],v[1],v[2]));
+      delete t;
+    } 
+    gf->triangles = newT;
+  }  
+
+
 }
 
 void buildVertexToTriangle(std::vector<MTriangle*> &eles, v2t_cont &adj)
@@ -303,7 +326,7 @@ void parametricCoordinates(MElement *t, GFace *gf, double u[4], double v[4],
   }
 }
 
-double surfaceFaceUV(MElement *t,GFace *gf, bool *concave = 0)
+double surfaceFaceUV(MElement *t,GFace *gf, bool maximal = true)
 {
   double u[4],v[4];
   parametricCoordinates(t,gf,u,v);
@@ -316,8 +339,7 @@ double surfaceFaceUV(MElement *t,GFace *gf, bool *concave = 0)
     const double a2 =
       0.5*fabs((u[2]-u[1])*(v[3]-v[1])-(u[3]-u[1])*(v[2]-v[1])) +
       0.5*fabs((u[0]-u[3])*(v[1]-v[3])-(u[1]-u[3])*(v[0]-v[3])) ;
-    if (concave) *concave = fabs(a2-a1) > 1.e-10*(a2 + a1);
-    return std::min(a2,a1);
+    return maximal ? std::max(a2,a1) : std::min(a2,a1);
   }
 }
 
@@ -469,8 +491,6 @@ static int _removeTwoQuadsNodes(GFace *gf)
       if (q1->getNumVertices() == 4 &&
           q2->getNumVertices() == 4 &&
           touched.find(q1) == touched.end() && touched.find(q2) == touched.end()){
-        touched.insert(q1);
-        touched.insert(q2);
         int comm = 0;
         for (int i=0;i<4;i++){
           if (q1->getVertex(i) == it->first){
@@ -495,8 +515,18 @@ static int _removeTwoQuadsNodes(GFace *gf)
           q2->writePOS(stdout,true,false,false,false,false,false);
           return 0;
         }
-        gf->quadrangles.push_back(new MQuadrangle(v1,v2,v3,v4));
-        vtouched.insert(it->first);
+	MQuadrangle *q = new MQuadrangle(v1,v2,v3,v4);
+	double s1 = surfaceFaceUV(q,gf);
+	double s2 = surfaceFaceUV(q1,gf) + surfaceFaceUV(q2,gf);;
+	if (s1 > s2){
+	  delete q;
+	}
+	else{
+	  touched.insert(q1);
+	  touched.insert(q2);
+	  gf->quadrangles.push_back(q);
+	  vtouched.insert(it->first);
+	}
       }
     }
     it++;
@@ -549,8 +579,8 @@ static bool _isItAGoodIdeaToCollapseThatVertex (GFace *gf,
 {
   double surface_old = surfaceFaceUV(q,gf);
   double surface_new = 0;
-  //  double worst_quality_old = q->etaShapeMeasure();
-  //  double worst_quality_new = 1.0;
+  double worst_quality_old = q->etaShapeMeasure();
+  double worst_quality_new = 1.0;
 
   double x = v->x();
   double y = v->y();
@@ -568,13 +598,13 @@ static bool _isItAGoodIdeaToCollapseThatVertex (GFace *gf,
 
   for (unsigned int j=0;j<e1.size();++j){
     surface_old += surfaceFaceUV(e1[j],gf);
-    //    worst_quality_old = std::min(worst_quality_old,e1[j]-> etaShapeMeasure());
+    worst_quality_old = std::min(worst_quality_old,e1[j]-> etaShapeMeasure());
     for (int k=0;k<e1[j]->getNumVertices();k++){
       if (e1[j]->getVertex(k) == v1 && e1[j] != q)
         e1[j]->setVertex(k,v);
     }
     surface_new += surfaceFaceUV(e1[j],gf);
-    //    worst_quality_new = std::min(worst_quality_new,e1[j]-> etaShapeMeasure());
+    worst_quality_new = std::min(worst_quality_new,e1[j]-> etaShapeMeasure());
     for (int k=0;k<e1[j]->getNumVertices();k++){
       if (e1[j]->getVertex(k) == v && e1[j] != q)
         e1[j]->setVertex(k,v1);
@@ -583,21 +613,21 @@ static bool _isItAGoodIdeaToCollapseThatVertex (GFace *gf,
 
   for (unsigned int j=0;j<e2.size();++j){
     surface_old += surfaceFaceUV(e2[j],gf);
-    //    worst_quality_old = std::min(worst_quality_old,e2[j]-> etaShapeMeasure());
+    worst_quality_old = std::min(worst_quality_old,e2[j]-> etaShapeMeasure());
     for (int k=0;k<e2[j]->getNumVertices();k++){
       if (e2[j]->getVertex(k) == v2 && e2[j] != q)
         e2[j]->setVertex(k,v);
     }
     surface_new += surfaceFaceUV(e2[j],gf);
-    //    worst_quality_new = std::min(worst_quality_new,e2[j]-> etaShapeMeasure());
+    worst_quality_new = std::min(worst_quality_new,e2[j]-> etaShapeMeasure());
     for (int k=0;k<e2[j]->getNumVertices();k++){
       if (e2[j]->getVertex(k) == v && e2[j] != q)
         e2[j]->setVertex(k,v2);
     }
   }
 
-  if ( fabs (surface_old - surface_new ) > 1.e-10 * surface_old) {
-    //    ||       FACT*worst_quality_new <  worst_quality_old ) {
+  if ( fabs (surface_old - surface_new ) > 1.e-10 * surface_old ){
+    //       ||       FACT*worst_quality_new <  worst_quality_old ) {
 
     v->setXYZ(x,y,z);
     v->setParameter(0,uu);
@@ -617,35 +647,31 @@ static bool _isItAGoodIdeaToMoveThatVertex (GFace *gf,
   double surface_old = 0;
   double surface_new = 0;
 
-  double qualityNew[256];
-
   GPoint gp = gf->point(after);
   if (!gp.succeeded())return false;
   SPoint3 pafter  (gp.x(),gp.y(),gp.z());
   SPoint3 pbefore (v1->x(),v1->y(),v1->z());
 
-  for (unsigned int j=0;j<e1.size();++j)
-    surface_old += surfaceFaceUV(e1[j],gf);
-
+  double minq = 1.0;
+  for (unsigned int j=0;j<e1.size();++j){
+    surface_old += surfaceFaceUV(e1[j],gf,false);
+    minq = std::min(e1[j]->etaShapeMeasure(),minq);
+  }
+  
   v1->setParameter(0,after.x());
   v1->setParameter(1,after.y());
   v1->setXYZ(pafter.x(),pafter.y(),pafter.z());
 
-  bool badQuality = false;
+  double minq_new = 1.0;
   for (unsigned int j=0;j<e1.size();++j){
-    surface_new += surfaceFaceUV(e1[j],gf);
-    qualityNew[j] = e1[j]->gammaShapeMeasure();
-    if (qualityNew[j] < 0.01) {
-      badQuality = true;
-      break;
-    }
+    surface_new += surfaceFaceUV(e1[j],gf,false);
+    minq_new = std::min(e1[j]->etaShapeMeasure(),minq_new);
   }
 
   v1->setParameter(0,before.x());
   v1->setParameter(1,before.y());
   v1->setXYZ(pbefore.x(),pbefore.y(),pbefore.z());
-
-  if (badQuality || (surface_new - surface_old)  > 1.e-10 * surface_old) {
+  if ((1.+1.e-10)*surface_old < surface_new|| minq_new < minq) {
     return false;
   }
   return true;
@@ -661,8 +687,21 @@ static bool _isItAGoodIdeaToMoveThoseVertices (GFace *gf,
   double surface_old = 0;
   double surface_new = 0;
 
+  double umin=1.e22,umax=-1.e22,vmin=1.e22,vmax=-1.e22;
+
+  for (unsigned int i=0; i<v.size();++i){
+    umin = std::min(before[i].x(),umin);
+    vmin = std::min(before[i].y(),vmin);
+    umax = std::max(before[i].x(),umax);
+    vmax = std::max(before[i].y(),vmax);
+  }
+
   std::vector<SPoint3> pafter(v.size()), pbefore(v.size());
   for (unsigned int i=0; i<v.size();++i){
+    if (after[i].x() > umax)return false;
+    if (after[i].x() < umin)return false;
+    if (after[i].y() > vmax)return false;
+    if (after[i].y() < vmin)return false;
     GPoint gp = gf->point(after[i]);
     if (!gp.succeeded())return false;
     pafter[i] = SPoint3  (gp.x(),gp.y(),gp.z());
@@ -673,23 +712,27 @@ static bool _isItAGoodIdeaToMoveThoseVertices (GFace *gf,
     surface_old += surfaceFaceUV(e1[j],gf);
 
   for (unsigned int i=0; i<v.size();++i){
-    v[i]->setParameter(0,after[i].x());
-    v[i]->setParameter(1,after[i].y());
-    v[i]->setXYZ(pafter[i].x(),pafter[i].y(),pafter[i].z());
+    if (v[i]->onWhat()->dim() == 2){
+      v[i]->setParameter(0,after[i].x());
+      v[i]->setParameter(1,after[i].y());
+      v[i]->setXYZ(pafter[i].x(),pafter[i].y(),pafter[i].z());
+    }
   }
 
-  bool badQuality = false;
   for (unsigned int j=0;j<e1.size();++j){
     surface_new += surfaceFaceUV(e1[j],gf);
   }
 
   for (unsigned int i=0; i<v.size();++i){
-    v[i]->setParameter(0,before[i].x());
-    v[i]->setParameter(1,before[i].y());
-    v[i]->setXYZ(pbefore[i].x(),pbefore[i].y(),pbefore[i].z());
+    if (v[i]->onWhat()->dim() == 2){
+      v[i]->setParameter(0,before[i].x());
+      v[i]->setParameter(1,before[i].y());
+      v[i]->setXYZ(pbefore[i].x(),pbefore[i].y(),pbefore[i].z());
+    }
   }
 
-  if (badQuality || (surface_new - surface_old)  > 1.e-10 * surface_old) {
+  //  if (fabs(surface_new-surface_old) > 1.e-10 * surface) {
+  if (surface_new > 1.0001*surface_old) {
     return false;
   }
   return true;
@@ -721,26 +764,6 @@ static int _quadWithOneVertexOnBoundary (GFace *gf,
     touched.insert(v2);
     touched.insert(v3);
     touched.insert(v4);
-    /*
-    std::vector<MVertex*> line;
-    for (int j=0;j<e1.size();j++){
-      for (int k=0;k<e1[j]->getNumVertices();k++){
-        if (e1[j]->getVertex(k) != v1 && e1[j] != q &&
-            e1[j]->getVertex(k)->onWhat()->dim() < 2){
-          line.push_back(e1[j]->getVertex(k));
-        }
-      }
-    }
-    // do not collapse if it's a corner
-    if (line.size() == 2){
-      if (fabs(angle3Vertices(line[0],v1,line[1]) - M_PI) > 3*M_PI/8.){
-        //        printf("coucou %g\n",angle3Vertices(line[0],v1,line[1])*180./M_PI);
-        return 0;
-      }
-    }
-    */
-    //    if (line.size() == 2)printf("caca\n");
-    //    else printf("hohcozbucof\n");
     for (unsigned int j=0;j<e2.size();++j){
       for (int k=0;k<e2[j]->getNumVertices();k++){
         if (e2[j]->getVertex(k) == v2 && e2[j] != q)
@@ -1549,7 +1572,7 @@ static int _defectsRemovalBunin(GFace *gf, int maxCavitySize)
 // if a vertex (on boundary) is adjacent to one only quad
 // and if that quad is badly shaped, we split this
 // quad
-static int _splitFlatQuads(GFace *gf, double minQual)
+static int _splitFlatQuads(GFace *gf, double minQual, std::set<MEdge,Less_Edge> &prioritory)
 {
   v2t_cont adj;
   buildVertexToElement(gf->triangles,adj);
@@ -1576,6 +1599,8 @@ static int _splitFlatQuads(GFace *gf, double minQual)
         MVertex *v3 = e->getVertex((k+1)%4);
         MVertex *v2 = e->getVertex((k+2)%4);
         MVertex *v4 = e->getVertex((k+3)%4);
+	prioritory.insert(MEdge(v2,v3)); 
+	prioritory.insert(MEdge(v3,v4)); 
         SPoint2 pv1,pv2,pv3,pv4,pb1,pb2,pb3,pb4;
         reparamMeshEdgeOnFace (v1,v3,gf,pv1,pv3);
         reparamMeshEdgeOnFace (v1,v4,gf,pv1,pv4);
@@ -1778,11 +1803,11 @@ int removeDiamonds(GFace *gf)
   return nbRemove;
 }
 
-int splitFlatQuads(GFace *gf, double q)
+int splitFlatQuads(GFace *gf, double q, std::set<MEdge,Less_Edge> &prioritory)
 {
   int nbRemove = 0;
   while(1){
-    int x = _splitFlatQuads(gf,q);
+    int x = _splitFlatQuads(gf,q, prioritory);
     if (!x)break;
     nbRemove += x;
   }
@@ -1853,7 +1878,7 @@ struct opti_data_vertex_relocation {
     v[2] = _v3;
     v[3] = _v4;
     for (int i=0;i<4;i++){
-      movable[i] = v[0]->onWhat()->dim() == 2;
+      movable[i] = v[i]->onWhat()->dim() == 2;
     }
   }
 
@@ -1872,21 +1897,14 @@ struct opti_data_vertex_relocation {
 
   double f() const
   {
-    /*
-        double minq = 1.0;
-        for (unsigned int i=0;i<e.size();++i){
-          MElement *el = e[i];
-          minq = std::min(el->gammaShapeMeasure(), minq);
-        }
-        if (minq < 0)minq *= 1.1;
-        else minq *= 0.;
-    */
-    double val = 0.0;
+    
+    double val = 1.0;
     for (unsigned int i=0;i<e.size();++i){
       MElement *el = e[i];
       //      double m = log((el->gammaShapeMeasure()-minq)/(1.-minq));
       //      val += m*m;//el->gammaShapeMeasure();
-      val += el->gammaShapeMeasure();
+      //      val =std::min(el->gammaShapeMeasure(),val);
+      val -=  el->gammaShapeMeasure();
     }
 
     return val;
@@ -1899,14 +1917,10 @@ struct opti_data_vertex_relocation {
         for (int j=0;j<nv;j++)dfdu[j] = dfdv[j] = 0;
         return;
       }
-      //      printf("coucou2 %22.15E, %22.15E\n", U[i]+eps,V[i]);
       const double FU = f();
       set_(U[i],V[i]+eps,i);
-      //      printf("coucou3\n");
       const double FV = f();
       set_(U[i],V[i],i);
-      //      printf("coucou4\n");
-      //    printf("%12.5E %12.5E %12.5E\n",F,FU,FV);
       dfdu[i] = movable[i] ? -(F-FU)/eps : 0 ;
       dfdv[i] = movable[i] ? -(F-FV)/eps : 0;
     }
@@ -1915,6 +1929,7 @@ struct opti_data_vertex_relocation {
   {
     //    if (!movable[iv])return;
     //    printf("getting point of surface %d (%22.15E,%22.15E)\n",gf->tag(),U,V);
+    if (!movable[iv])return true;
     GPoint gp = gf->point(U,V);
     if (!gp.succeeded()) return false;//Msg::Error("point not OK");
     v[iv]->x() = gp.x();
@@ -1952,22 +1967,25 @@ void bfgs_callback_vertex_relocation (const alglib::real_1d_array& x,
 static int _untangleQuad (GFace *gf, MQuadrangle *q,v2t_cont & adj)
 {
   std::set<MElement*> all;
+
+  int numU=0;
   for (int i=0;i<4;i++){
     std::vector<MElement*> &adji = adj[q->getVertex(i)];
     all.insert(adji.begin(),adji.end());
     // FIXME
-    if (q->getVertex(i)->onWhat()->dim() != 2)return 0;
+    if (q->getVertex(i)->onWhat()->dim() == 2)numU ++;
   }
+  if (numU == 0)return 0;
   std::vector<MElement*> lt;
   lt.insert(lt.begin(),all.begin(),all.end());
 
   double minq_old = 100.;
   for (unsigned int i = 0; i < lt.size(); i++){
-    const double q = lt[i]->gammaShapeMeasure();
+    const double q = lt[i]->etaShapeMeasure();
     minq_old = std::min(q,minq_old);
   }
   //  printf("-------x--------x------------x-------------------\n");
-  //  printf ("optimizing quadrangle (minq %12.5E) with BFGS %3d\n",minq_old,OPTI_NUMBER);
+  //  printf ("optimizing quadrangle (minq %12.5E) with BFGS\n",minq_old);
 
 
   alglib::ae_int_t dim = 8;
@@ -1983,8 +2001,10 @@ static int _untangleQuad (GFace *gf, MQuadrangle *q,v2t_cont & adj)
 
   double U[4],V[4];
   for (int i=0;i<4;i++){
-    q->getVertex(i)->getParameter(0,U[i]);
-    q->getVertex(i)->getParameter(1,V[i]);
+    SPoint2 p;
+    reparamMeshVertexOnFace(q->getVertex(i),gf, p);
+    U[i] = p.x();
+    V[i] = p.y();
     initial_conditions[2*i] = U[i];
     initial_conditions[2*i+1] = V[i];
   }
@@ -2007,25 +2027,44 @@ static int _untangleQuad (GFace *gf, MQuadrangle *q,v2t_cont & adj)
   //  printf("minq = %12.5E\n",minq);
 
   std::vector<SPoint2> before;for(int i=0;i<4;i++)before.push_back(SPoint2(U[i],V[i]));
-  std::vector<SPoint2> after;for(int i=0;i<4;i++)after.push_back(SPoint2(x[2*i],x[2*i+1]));
+  std::vector<SPoint2> after;
+  for(int i=0;i<4;i++) 
+    if (q->getVertex(i)->onWhat()->dim() == 2)
+      after.push_back(SPoint2(x[2*i],x[2*i+1]));
+    else
+      after.push_back(SPoint2(U[i],V[i]));
   std::vector<MVertex*> vs;for(int i=0;i<4;i++)vs.push_back(q->getVertex(i));
   bool success = _isItAGoodIdeaToMoveThoseVertices (gf,lt,vs,before,after);
+  
+  if (success){
+    for (int i=0;i<4;i++)data.set_(x[2*i],x[2*i+1],i);
+    //    sprintf(NNN,"UNTANGLE_cavity_%d_after.pos",OPTI_NUMBER++);
+    //    data.print_cavity (NNN);
+    return 1;
+  }
+
+  //  double minq_new = 100.;
+  //  for (unsigned int i = 0; i < data.e.size(); i++){
+  //    const double q = data.e[i]->gammaShapeMeasure();
+  //    minq_new = std::min(q,minq_new);
+  //  }
+
+  // if (success) printf("YES %g %g\n",minq,minq_new);
 
-  if (!success || minq < 0.0 || minq <= minq_old/2)   for (int i=0;i<4;i++)data.set_(U[i],V[i],i);
-  else return 1;
+  for (int i=0;i<4;i++)data.set_(U[i],V[i],i);
   return 0;
+  //  return 0;
   //  else printf("OKIDOKI-UNTANGLE\n");
-  //  sprintf(NNN,"UNTANGLE_cavity_%d_after.pos",OPTI_NUMBER++);
-  //  data.print_cavity (NNN);
+  return 1;
 }
 
 
 // use optimization
-static void _relocateVertexOpti(GFace *gf, MVertex *ver,
-                                const std::vector<MElement*> &lt)
+static int _relocateVertexOpti(GFace *gf, MVertex *ver,
+			       const std::vector<MElement*> &lt)
 {
   //  return;
-  if(ver->onWhat()->dim() != 2)return;
+  if(ver->onWhat()->dim() != 2)return 0;
 
   double minq_old = 100.;
   //  printf("------------------------------------------------\n");
@@ -2075,15 +2114,12 @@ static void _relocateVertexOpti(GFace *gf, MVertex *ver,
   bool success = _isItAGoodIdeaToMoveThatVertex (gf,  lt, ver,SPoint2(U,V),SPoint2(x[0],x[1]));
 
   if (!success || minq < 0 || minq <= minq_old/2) data.set_(U,V,0);
-  else {
-//printf("OKIDOKI\n");
-  }
   //  if (rep.terminationtype != 4){
   //    data.set_(U,V);
   //  }
   //  sprintf(NNN,"cavity_%d_after.pos",OPTI_NUMBER++);
   //  data.print_cavity (NNN);
-
+  return success;
 }
 #endif
 
@@ -2146,11 +2182,6 @@ void _relocateVertex(GFace *gf, MVertex *ver,
         ver->z() = pt.z();
       }
     }
-    else{
-#if defined(HAVE_BFGS)
-      // _relocateVertexOpti(gf, ver, lt);
-#endif
-    }
   }
 }
 
@@ -2178,6 +2209,30 @@ void laplaceSmoothing(GFace *gf, int niter, bool infinity_norm)
   }
 }
 
+int optiSmoothing(GFace *gf, int niter, bool infinity_norm)
+{
+  v2t_cont adj;
+  buildVertexToElement(gf->triangles, adj);
+  buildVertexToElement(gf->quadrangles, adj);
+  int N = 0;
+  for(int i = 0; i < niter; i++){
+    v2t_cont::iterator it = adj.begin();
+    while (it != adj.end()){
+      bool doit = false;
+      for (unsigned int j=0;j<it->second.size();j++){
+	if (it->second[j]->gammaShapeMeasure() < .05){
+	  doit = true;
+	}
+      }
+      if (doit){
+	N += _relocateVertexOpti(gf, it->first, it->second);
+      }
+      ++it;
+    }
+  }
+  return N;
+}
+
 
 
 int untangleInvalidQuads(GFace *gf, int niter)
@@ -2190,7 +2245,7 @@ int untangleInvalidQuads(GFace *gf, int niter)
   buildVertexToElement(gf->quadrangles, adj);
   for(int i = 0; i < niter; i++){
     for (unsigned int j=0;j<gf->quadrangles.size();j++){
-      if (gf->quadrangles[j]->gammaShapeMeasure() < 0.1){
+      if (gf->quadrangles[j]->etaShapeMeasure() < 0.1){
         N += _untangleQuad (gf, gf->quadrangles[j], adj);
       }
     }
@@ -2199,8 +2254,34 @@ int untangleInvalidQuads(GFace *gf, int niter)
   return N;
 }
 
+static int orientationOK (GFace *gf, MVertex *v1, MVertex *v2, MVertex *v3){
+  SPoint2 p1,p2,p3;
+  reparamMeshVertexOnFace(v1,gf, p1);
+  reparamMeshVertexOnFace(v2,gf, p2);
+  reparamMeshVertexOnFace(v3,gf, p3);
+  if (robustPredicates::orient2d (p1,p2,p3) < 0)return true;
+  return false;     
+}
 
-int _edgeSwapQuadsForBetterQuality(GFace *gf)
+static int allowSwap (GFace *gf, MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4){
+  SPoint2 p1,p2,p3,p4;
+  reparamMeshVertexOnFace(v1,gf, p1);
+  reparamMeshVertexOnFace(v2,gf, p2);
+  reparamMeshVertexOnFace(v3,gf, p3);
+  reparamMeshVertexOnFace(v4,gf, p4);
+  if (robustPredicates::orient2d (p1,p2,p3) *
+      robustPredicates::orient2d (p1,p2,p4) < 0 &&
+      robustPredicates::orient2d (p3,p4,p1) *
+      robustPredicates::orient2d (p3,p4,p2) > 0)return true;
+  return false;     
+}
+
+static double myShapeMeasure(MElement *e){
+  return e->etaShapeMeasure();
+}
+
+
+int _edgeSwapQuadsForBetterQuality(GFace *gf, double eps, std::set<MEdge,Less_Edge> &prioritory)
 {
   e2t_cont adj;
   //buildEdgeToElement(gf->triangles, adj);
@@ -2219,9 +2300,12 @@ int _edgeSwapQuadsForBetterQuality(GFace *gf)
       MVertex *v2 = it->first.getVertex(1);
       MElement *e1 = it->second.first;
       MElement *e2 = it->second.second;
-      double worst_quality_old = std::min(e1->gammaShapeMeasure(),e2->gammaShapeMeasure());
+      double worst_quality_old = std::min(myShapeMeasure(e1),myShapeMeasure(e2));
+      bool P = prioritory.find(MEdge(v1,v2)) != prioritory.end();
+      if (P)  worst_quality_old = 0.0;
 
-      if (worst_quality_old < .3 && (
+      if ((v1->onWhat()->dim() != 2 || v2->onWhat()->dim() != 2) &&
+	   worst_quality_old < eps && (
           deleted.find(e1) == deleted.end() ||
           deleted.find(e2) == deleted.end())){
         MVertex *v12=0,*v11=0,*v22=0,*v21=0;
@@ -2248,6 +2332,7 @@ int _edgeSwapQuadsForBetterQuality(GFace *gf)
           return 0;
         }
 
+	// edges have to intersect
         MQuadrangle *q1A, *q2A, *q1B, *q2B;
         if (rot1 > 0.0 && rot2 > 0.0){
           q1A = new MQuadrangle (v11,v22,v2,v12);
@@ -2261,40 +2346,49 @@ int _edgeSwapQuadsForBetterQuality(GFace *gf)
           q1B = new MQuadrangle (v11,v12,v21,v1);
           q2B = new MQuadrangle (v21,v12,v2,v22);
         }
-        double worst_quality_A = std::min(q1A->gammaShapeMeasure(),q2A->gammaShapeMeasure());
-        double worst_quality_B = std::min(q1B->gammaShapeMeasure(),q2B->gammaShapeMeasure());
-
-        bool ca1,ca2,cb1,cb2;
-        double old_surface = surfaceFaceUV(e1,gf) + surfaceFaceUV(e2,gf) ;
-        double new_surface_A = surfaceFaceUV(q1A,gf,&ca1) + surfaceFaceUV(q2A,gf,&ca2) ;
-        double new_surface_B = surfaceFaceUV(q1B,gf,&cb1) + surfaceFaceUV(q2B,gf,&cb2) ;
-
-        if (!ca1 && !ca2 &&
-            fabs(old_surface - new_surface_A) < 1.e-10 * old_surface &&
-            0.8*worst_quality_A > worst_quality_old &&
-            0.8*worst_quality_A > worst_quality_B &&
-            SANITY_(gf,q1A,q2A,12121)){
+        double worst_quality_A = std::min(myShapeMeasure(q1A),myShapeMeasure(q2A));
+        double worst_quality_B = std::min(myShapeMeasure(q1B),myShapeMeasure(q2B));
+
+	bool PA = prioritory.find(MEdge(v11,v22)) == prioritory.end();
+	bool PB = prioritory.find(MEdge(v12,v21)) == prioritory.end();
+
+        double old_surface = surfaceFaceUV(e1,gf) + surfaceFaceUV(e2,gf) ; 
+        double new_surface_A = surfaceFaceUV(q1A,gf) + surfaceFaceUV(q2A,gf) ;
+        double new_surface_B = surfaceFaceUV(q1B,gf) + surfaceFaceUV(q2B,gf) ;
+
+	bool doA=false, doB=false;
+	if (old_surface > new_surface_A)doA = true;
+	if (old_surface > new_surface_B)doB = true;
+	if ( worst_quality_A >  worst_quality_B){
+	  if ( worst_quality_A > worst_quality_old && !doB) doA = true;
+	}
+	else{
+	  if ( worst_quality_B > worst_quality_old && !doA) doB = true;
+	}
+
+	if(!allowSwap(gf,v1,v2,v11,v22)) doA = false;
+	if(!allowSwap(gf,v1,v2,v21,v12)) doB = false;
+	
+	if (!PA)doA = false; 
+	if (!PB)doB = false; 
+
+
+        if (doA && SANITY_(gf,q1A,q2A)){
           deleted.insert(e1);
           deleted.insert(e2);
           created.push_back(q1A);
           created.push_back(q2A);
           delete q1B;
           delete q2B;
-          //printf("edge swap performed -- 1\n");
           COUNT++;
         }
-        else if (!cb1 && !cb2 &&
-                 fabs(old_surface - new_surface_B) < 1.e-10 * old_surface  &&
-                 0.8*worst_quality_B > worst_quality_old &&
-                 0.8*worst_quality_B > worst_quality_A &&
-                 SANITY_(gf,q1B,q2B,12121)){
+        else if (doB && SANITY_(gf,q1B,q2B)){
           deleted.insert(e1);
           deleted.insert(e2);
           created.push_back(q1B);
           created.push_back(q2B);
           delete q1A;
           delete q2A;
-          //printf("edge swap performed -- 2\n");
           COUNT++;
         }
         else {
@@ -2320,13 +2414,13 @@ int _edgeSwapQuadsForBetterQuality(GFace *gf)
   return COUNT;
 }
 
-static int  edgeSwapQuadsForBetterQuality (GFace *gf)
+static int  edgeSwapQuadsForBetterQuality (GFace *gf, double eps,  std::set<MEdge,Less_Edge> &prioritory)
 {
   int COUNT = 0;
   while(1){
-    int k = _edgeSwapQuadsForBetterQuality (gf);
+    int k = _edgeSwapQuadsForBetterQuality (gf, eps, prioritory);
     COUNT += k;
-    if (!k || COUNT > 10)break;
+    if (!k || COUNT > 40)break;
   }
   Msg::Debug("%i swap quads performed",COUNT);
   return COUNT;
@@ -2397,6 +2491,41 @@ static std::vector<MVertex*> computeBoundingPoints (const std::vector<MElement*>
   return result;
 }
 
+static MQuadrangle* buildNewQuad(MVertex *first,
+				 MVertex *newV,
+				 MElement *e, 
+				 const std::vector<MElement*> & E){
+  int found[3] = {0,0,0};
+  for (unsigned int i=0;i<E.size();i++){
+    if (E[i] != e){
+      for (int j=0;j<E[i]->getNumVertices();j++){
+	MVertex *v = E[i]->getVertex(j);
+	if (v == e->getVertex(0))found[0]=1;
+	else if (v == e->getVertex(1))found[1]=1;
+	else if (v == e->getVertex(2))found[2]=1;
+      }
+    }
+  }
+  int start = -1;
+  int nextVertex=-1;
+  for (int i=0;i<3;i++){
+    if (e->getVertex(i) == first) start = i;
+    if (!found[i])nextVertex = i ;
+  }
+  if (nextVertex == (start+1)%3){
+    return new MQuadrangle (e->getVertex(start),
+			    e->getVertex((start+1)%3),
+			    e->getVertex((start+2)%3),
+			    newV);
+  }
+  else{
+    return new MQuadrangle (e->getVertex(start),
+			    newV,
+			    e->getVertex((start+1)%3),
+			    e->getVertex((start+2)%3));
+  }      
+}
+
 int postProcessExtraEdges (GFace *gf, std::vector<std::pair<MElement*,MElement*> > &toProcess)
 {
   // some pairs of elements that should be recombined are not neighbor elements (see our paper)
@@ -2454,47 +2583,17 @@ int postProcessExtraEdges (GFace *gf, std::vector<std::pair<MElement*,MElement*>
                                                     p.y());
           gf->mesh_vertices.push_back(newVertex);
           int start1 = 0,start2 = 0;
-          int orientation1=1, orientation2=1;
           for (int k=0;k<3;k++){
             if (t1->getVertex(k) == it->first){
-              //              if (t1->getVertex((k+1)%3)->onWhat()->dim
               start1 = k;
             }
-            if (t2->getVertex(k) == it->first)start2 = k;
+            if (t2->getVertex(k) == it->first){
+	      start2 = k;
+	    }
           }
-          /*
-            FIX THAT !!!!!
-            x--------x--------x
-             \ t1   / \  t2  /
-              \    /   \    /
-               \  /     \  /
-                \/       \/
-
-           */
-          MQuadrangle *q1;
-          if (orientation1)
-            q1 = new MQuadrangle(t1->getVertex(start1),
-                                 newVertex,
-                                 t1->getVertex((start1+1)%3),
-                                 t1->getVertex((start1+2)%3));
-          else
-            q1 = new MQuadrangle(newVertex,
-                                 t1->getVertex((start1+2)%3),
-                                 t1->getVertex((start1+1)%3),
-                                 t1->getVertex(start1));
-
-          MQuadrangle *q2;
-          if (orientation2)
-            q2 = new MQuadrangle(t2->getVertex(start2),
-                                 newVertex,
-                                 t2->getVertex((start2+1)%3),
-                                 t2->getVertex((start2+2)%3));
-          else
-            q2 = new MQuadrangle(newVertex,
-                                 t2->getVertex((start2+2)%3),
-                                 t2->getVertex((start2+1)%3),
-                                 t2->getVertex(start2));
 
+          MQuadrangle *q1 =buildNewQuad(t1->getVertex(start1),newVertex,t1,it->second);
+          MQuadrangle *q2 =buildNewQuad(t2->getVertex(start2),newVertex,t2,it->second);
 
           std::vector<MElement*> newAdj;
           newAdj.push_back(q1);
@@ -2915,7 +3014,7 @@ int recombineWithBlossom(GFace *gf, double dx, double dy,
         elist[2*i]   = t2n[pairs[i].t1];
         elist[2*i+1] = t2n[pairs[i].t2];
         //elen [i] =  (int) pairs[i].angle;
-        elen [i] = (int) pairs[i].total_cost; //addition for class Temporary
+	//        elen [i] = (int) pairs[i].total_cost; //addition for class Temporary
         double angle = atan2(pairs[i].n1->y()-pairs[i].n2->y(),
                              pairs[i].n1->x()-pairs[i].n2->x());
 
@@ -2927,14 +3026,14 @@ int recombineWithBlossom(GFace *gf, double dx, double dy,
           if (angle < 0) angle += M_PI/2;
           if (angle > M_PI/2) angle -= M_PI/2;
         }
-        //elen [i] =  (int) 180. * fabs(angle-M_PI/4)/M_PI;
+        elen [i] =  (int) 180. * fabs(angle-M_PI/4)/M_PI;
 
         int NB = 0;
         if (pairs[i].n1->onWhat()->dim() < 2)NB++;
         if (pairs[i].n2->onWhat()->dim() < 2)NB++;
         if (pairs[i].n3->onWhat()->dim() < 2)NB++;
         if (pairs[i].n4->onWhat()->dim() < 2)NB++;
-        if (elen[i] >  gf->meshAttributes.recombineAngle && NB > 2) {elen[i] = 1000;}
+        if (elen[i] >  180 && NB > 2) {printf("angle %dE\n",elen[i]);elen[i] = 1000;}
       }
 
       if (cubicGraph){
@@ -3121,19 +3220,19 @@ static int _recombineIntoQuads(GFace *gf, int recur_level, bool cubicGraph = 1)
       for (unsigned int i = 0; i < pairs.size(); ++i){
         elist[2*i]   = t2n[pairs[i].t1];
         elist[2*i+1] = t2n[pairs[i].t2];
-        //elen [i] =  (int) pairs[i].angle;
-        elen [i] = (int) pairs[i].total_cost; //addition for class Temporary
-        double angle = atan2(pairs[i].n1->y()-pairs[i].n2->y(),
-                             pairs[i].n1->x()-pairs[i].n2->x());
+        elen [i] =  (int) 1000*exp(-pairs[i].angle);
+        //elen [i] = (int) pairs[i].total_cost; //addition for class Temporary
+	//        double angle = atan2(pairs[i].n1->y()-pairs[i].n2->y(),
+	//                             pairs[i].n1->x()-pairs[i].n2->x());
 
         //double x = .5*(pairs[i].n1->x()+pairs[i].n2->x());
         //double y = .5*(pairs[i].n1->y()+pairs[i].n2->y());
         //double opti = atan2(y,x);
         //angle -= opti;
-        while (angle < 0 || angle > M_PI/2){
-          if (angle < 0) angle += M_PI/2;
-          if (angle > M_PI/2) angle -= M_PI/2;
-        }
+	//        while (angle < 0 || angle > M_PI/2){
+	//          if (angle < 0) angle += M_PI/2;
+	//          if (angle > M_PI/2) angle -= M_PI/2;
+	//        }
         //elen [i] =  (int) 180. * fabs(angle-M_PI/4)/M_PI;
 
         int NB = 0;
@@ -3141,7 +3240,9 @@ static int _recombineIntoQuads(GFace *gf, int recur_level, bool cubicGraph = 1)
         if (pairs[i].n2->onWhat()->dim() < 2)NB++;
         if (pairs[i].n3->onWhat()->dim() < 2)NB++;
         if (pairs[i].n4->onWhat()->dim() < 2)NB++;
-        if (elen[i] >  gf->meshAttributes.recombineAngle && NB > 2) {elen[i] = 1000;}
+	//if (NB > 2)printf("%d %d\n",elen[i],NB);
+	if (elen[i] >  (int)1000*exp(.1) && NB > 2) {elen[i] = 5000;}
+	else if (elen[i] >=  1000 && NB > 2) {elen[i] = 10000;}
       }
 
       if (cubicGraph){
@@ -3228,7 +3329,7 @@ static int _recombineIntoQuads(GFace *gf, int recur_level, bool cubicGraph = 1)
           // FIXME !!
           if (an == 100000 /*|| an == 1000*/){
             toProcess.push_back(std::make_pair(n2t[i1],n2t[i2]));
-            Msg::Debug("Extra edge found in blossom algorithm, optimization will be required");
+            Msg::Warning("Extra edge found in blossom algorithm, optimization will be required");
           }
           else{
             MElement *t1 = n2t[i1];
@@ -3328,6 +3429,22 @@ static int _recombineIntoQuads(GFace *gf, int recur_level, bool cubicGraph = 1)
 }
 
 
+static double printStats(GFace *gf,const char *message){
+  int nbBad=0;
+  int nbInv=0;
+  double Qav=0;
+  double Qmin=1;
+  for (unsigned int i=0;i<gf->quadrangles.size();i++){
+    double Q = gf->quadrangles[i]->etaShapeMeasure() ;
+    if (Q <= 0.0)nbInv ++;
+    if (Q <= 0.1)nbBad ++;
+    Qav += Q;
+    Qmin = std::min(Q,Qmin);
+  }
+  Msg::Info("%s : %5d quads %4d invalid quads %4d quads with Q < 0.1 Avg Q = %12.5E Min %12.5E",message, gf->quadrangles.size(), nbInv, nbBad,Qav/gf->quadrangles.size(),Qmin);
+  return Qmin;
+}
+
 void recombineIntoQuads(GFace *gf,
                         bool topologicalOpti,
                         bool nodeRepositioning)
@@ -3348,81 +3465,62 @@ void recombineIntoQuads(GFace *gf,
   int success = _recombineIntoQuads(gf, 0);
 
   if (saveAll) gf->model()->writeMSH("raw.msh");
-  if(haveParam && nodeRepositioning)
+  printStats (gf, "BEFORE OPTIMIZATION");
+  if(haveParam && nodeRepositioning){
     laplaceSmoothing(gf, CTX::instance()->mesh.nbSmoothing);
-
+  }
   // blossom-quad algo
   if(success && CTX::instance()->mesh.algoRecombine == 1){
     if(topologicalOpti){
       if(haveParam){
         if (saveAll) gf->model()->writeMSH("smoothed.msh");
-        int COUNT = 0, ITER=0;
-        char NAME[256];
-
-        double tFQ=0,tTQ=0,tDI=0,tLA=0,tSW=0,tBU=0;
-        double oldoptistatus[5] = {0,0,0,0,0};
-        double optistatus[5] = {0,0,0,0,0};
+        int ITER=0;
+	int ITERB = 0;
+        int optistatus[6] = {0,0,0,0,0,0};
+	std::set<MEdge,Less_Edge> prioritory;
         while(1){
-          double t6 = Cpu();
           int maxCavitySize = CTX::instance()->mesh.bunin;
-          optistatus[4] = _defectsRemovalBunin(gf,maxCavitySize);
-          if(optistatus[4] && saveAll){
-            sprintf(NAME,"iter%dB.msh",COUNT++); gf->model()->writeMSH(NAME);
-          }
-
-          double t7 = Cpu();
-          double t1 = Cpu();
-          optistatus[0] = splitFlatQuads(gf, .3);
-          if(optistatus[0] && saveAll){
-            sprintf(NAME,"iter%dSF.msh",COUNT++); gf->model()->writeMSH(NAME);
-          }
-          double t2 = Cpu();
+	  optistatus[0] = (ITERB == 1) ?splitFlatQuads(gf, .01, prioritory) : 0;
           optistatus[1] = removeTwoQuadsNodes(gf);
-          if(optistatus[1] && saveAll){
-            sprintf(NAME,"iter%dTQ.msh",COUNT++); gf->model()->writeMSH(NAME);
-          }
-          double t3 = Cpu();
-          optistatus[2] = removeDiamonds(gf);
-          if(optistatus[2] && saveAll){
-            sprintf(NAME,"iter%dD.msh",COUNT++); gf->model()->writeMSH(NAME);
-          }
-
-          double t4 = Cpu();
-          untangleInvalidQuads(gf,CTX::instance()->mesh.nbSmoothing);
-          laplaceSmoothing(gf,CTX::instance()->mesh.nbSmoothing,true);
-          double t5 = Cpu();
-          optistatus[3] = edgeSwapQuadsForBetterQuality(gf);
-
-          if(optistatus[3] && saveAll){
-            sprintf(NAME,"iter%dS.msh",COUNT++); gf->model()->writeMSH(NAME);
-          }
-          double t5b = Cpu();
-          tFQ += (t2-t1);
-          tTQ += (t3-t2);
-          tDI += (t4-t3);
-          tLA += (t5-t4);
-          tSW += (t5b-t5);
-          tBU += (t7-t6);
-          if (!(optistatus[0]+optistatus[1]+optistatus[2]+optistatus[3]+optistatus[4]))
-            break;
-          bool theSame = true;
-          for (int i=0;i<5;i++){
-            if (optistatus[i] != oldoptistatus[i])theSame = false;
-              oldoptistatus[i] = optistatus[i];
-          }
-           if(theSame)break;
-          if (ITER++ >= 20)break;
+          optistatus[4] = _defectsRemovalBunin(gf,maxCavitySize);
+          optistatus[2] = removeDiamonds(gf) ;
+	  laplaceSmoothing(gf,CTX::instance()->mesh.nbSmoothing,true);
+	  optistatus[3] = edgeSwapQuadsForBetterQuality(gf,.01, prioritory);
+	  optistatus[5] = optiSmoothing(gf,CTX::instance()->mesh.nbSmoothing,true);
+	  optistatus[5] = (ITERB == 1) ?untangleInvalidQuads(gf,CTX::instance()->mesh.nbSmoothing) : 0;
+
+	  double bad = printStats (gf, "IN OPTIMIZATION");
+	  if (bad > .1)break;	  
+          if (ITER == 10){
+	    ITERB = 1;
+	  }
+	  if (ITER > 20)break;
+	  int nb = 0;
+	  for (int i=0;i<6;i++)nb += optistatus[i];
+	  if (!nb && ITERB == 0)ITERB = 1;
+	  else if (!nb )break;
+	  //	  printf("%d %d %d %d %d %d\n",optistatus[0],optistatus[1],optistatus[2],optistatus[3],optistatus[4],optistatus[5]);
+	  ITER ++;
         }
-        Msg::Debug("Opti times FQ(%4.3f) tQ(%4.3f) DI(%4.3f) LA(%4.3f) "
-                   "SW(%4.3f) BUN(%4.3f)",tFQ,tTQ,tDI,tLA,tSW,tBU);
       }
 
-      if(haveParam) laplaceSmoothing(gf,CTX::instance()->mesh.nbSmoothing, true);
+      if(haveParam) {
+	laplaceSmoothing(gf,CTX::instance()->mesh.nbSmoothing, true);
+	optiSmoothing(gf,CTX::instance()->mesh.nbSmoothing,true);
+      }
+      //      untangleInvalidQuads(gf,CTX::instance()->mesh.nbSmoothing);
     }
     double t2 = Cpu();
     Msg::Info("Blossom recombination algorithm completed (%g s)", t2 - t1);
-    quadsToTriangles(gf, 0.01);
-    //    if(haveParam) laplaceSmoothing(gf,CTX::instance()->mesh.nbSmoothing);
+    quadsToTriangles(gf, .01);
+    if(haveParam) {
+      laplaceSmoothing(gf,CTX::instance()->mesh.nbSmoothing);
+      //      optiSmoothing(gf,CTX::instance()->mesh.nbSmoothing,true);
+    }
+    //    removeDiamonds(gf);
+    //    removeTwoQuadsNodes(gf);
+    printStats (gf, "AFTER OPTIMIZATION");
+
     return;
   }
 
diff --git a/Mesh/meshGFaceOptimize.h b/Mesh/meshGFaceOptimize.h
index 010607dddb2856a1e029bf057f3ed8e0cde4c89a..04987bff9447d1f0374874cd8d26f1fbdf1efd2b 100644
--- a/Mesh/meshGFaceOptimize.h
+++ b/Mesh/meshGFaceOptimize.h
@@ -158,6 +158,10 @@ struct RecombineTriangle
     else if(t2->getVertex(1) != n1 && t2->getVertex(1) != n2) n4 = t2->getVertex(1);
     else if(t2->getVertex(2) != n1 && t2->getVertex(2) != n2) n4 = t2->getVertex(2);
     
+    MQuadrangle q (n1,n3,n2,n4);
+    angle = q.etaShapeMeasure();
+
+    /*
     double a1 = 180 * angle3Vertices(n1, n4, n2) / M_PI;
     double a2 = 180 * angle3Vertices(n4, n2, n3) / M_PI;
     double a3 = 180 * angle3Vertices(n2, n3, n1) / M_PI;
@@ -166,6 +170,7 @@ struct RecombineTriangle
     angle = std::max(fabs(90. - a2),angle);
     angle = std::max(fabs(90. - a3),angle);
     angle = std::max(fabs(90. - a4),angle);
+    */
     cost_quality = 1.0 - std::max(1.0 - angle/90.0,0.0); //addition for class Temporary
     cost_alignment = Temporary::compute_alignment(me,_t1,_t2); //addition for class Temporary
     total_cost = Temporary::compute_total_cost(cost_quality,cost_alignment); //addition for class Temporary
diff --git a/Mesh/meshGRegionDelaunayInsertion.cpp b/Mesh/meshGRegionDelaunayInsertion.cpp
index 603923906ceb168c3bf0b365afd702b27e2bf4d6..2b33eef5629c330d1c48b6e336af17e77ebf3129 100644
--- a/Mesh/meshGRegionDelaunayInsertion.cpp
+++ b/Mesh/meshGRegionDelaunayInsertion.cpp
@@ -305,6 +305,8 @@ bool insertVertexB(std::list<faceXtet> &shell,
     ++it;
   }
   // OK, the cavity is star shaped
+  if (onePointIsTooClose)printf("One point is too close\n");
+  if (fabs(oldVolume - newVolume) > 1.e-10 * oldVolume)printf("Volume do not match %22.15E %22.15E %22.15E\n",oldVolume,newVolume,fabs(oldVolume-newVolume)/newVolume);
   if (fabs(oldVolume - newVolume) < 1.e-10 * oldVolume &&
       !onePointIsTooClose){
     connectTets_vector(new_cavity.begin(), new_cavity.end());
diff --git a/Mesh/simple3D.cpp b/Mesh/simple3D.cpp
index 6a764903c08aa652c5c2cfc05c440c0f3740f0db..485c2c3ea6f581187c0a719963d0604f1937d2f3 100644
--- a/Mesh/simple3D.cpp
+++ b/Mesh/simple3D.cpp
@@ -345,7 +345,7 @@ void Filler::treat_region(GRegion* gr){
   std::set<MVertex*> temp;
   std::set<MVertex*>::iterator it;
   RTree<Node*,double,3,double> rtree;
-
+  
   Frame_field::init_region(gr);
   Size_field::init_region(gr);
   Size_field::solve(gr);
@@ -704,4 +704,4 @@ void Filler::print_node(Node* node,std::ofstream& file){
 
 /*********static declarations*********/
 
-std::vector<MVertex*> Filler::new_vertices;
\ No newline at end of file
+std::vector<MVertex*> Filler::new_vertices;
diff --git a/Mesh/surfaceFiller.cpp b/Mesh/surfaceFiller.cpp
index f20fcf562d49bd9d83fdfe96b9e1ab18503ff028..4bd812b21ade39184b7419df2bbc0bc92e789597 100644
--- a/Mesh/surfaceFiller.cpp
+++ b/Mesh/surfaceFiller.cpp
@@ -18,7 +18,7 @@
 #include "BackgroundMesh.h"
 #include "intersectCurveSurface.h"
 
-static const double FACTOR = .81;
+static const double FACTOR = .71;
 static const int NUMDIR = 3;
 //static const double DIRS [NUMDIR] = {0.0};
 static const double DIRS [NUMDIR] = {0.0, M_PI/20.,-M_PI/20.};
@@ -133,7 +133,7 @@ bool inExclusionZone (SPoint2 &p,
   if (!backgroundMesh::current()->inDomain(p.x(),p.y(),0)) return true;
 
   my_wrapper w (p);
-  double _min[2] = {p.x()-1.e-8, p.y()-1.e-8},_max[2] = {p.x()+1.e-8,p.y()+1.e-8};
+  double _min[2] = {p.x()-1.e-3, p.y()-1.e-3},_max[2] = {p.x()+1.e-3,p.y()+1.e-3};
   rtree.Search(_min,_max,rtree_callback,&w);
 
   return w._tooclose;
@@ -259,14 +259,15 @@ bool compute4neighbors (GFace *gf,   // the surface
 	   ,covar1[0],covar1[1],covar2[0],covar2[1],l1,l2,size_1,size_2,size_param_1,size_param_2,M,N,E,s1.x(),s1.y(),s2.x(),s2.y());*/
 
     // this is the rectangle in the parameter plane.
-    double r1 = 0*1.e-8*(double)rand() / RAND_MAX;
-    double r2 = 0*1.e-8*(double)rand() / RAND_MAX;
-    double r3 = 0*1.e-8*(double)rand() / RAND_MAX;
-    double r4 = 0*1.e-8*(double)rand() / RAND_MAX;
-    double r5 = 0*1.e-8*(double)rand() / RAND_MAX;
-    double r6 = 0*1.e-8*(double)rand() / RAND_MAX;
-    double r7 = 0*1.e-8* (double)rand() / RAND_MAX;
-    double r8 = 0*1.e-8*(double)rand() / RAND_MAX;
+    const double EPS = 1.e-6;
+    double r1 = EPS*(double)rand() / RAND_MAX;
+    double r2 = EPS*(double)rand() / RAND_MAX;
+    double r3 = EPS*(double)rand() / RAND_MAX;
+    double r4 = EPS*(double)rand() / RAND_MAX;
+    double r5 = EPS*(double)rand() / RAND_MAX;
+    double r6 = EPS*(double)rand() / RAND_MAX;
+    double r7 = EPS* (double)rand() / RAND_MAX;
+    double r8 = EPS*(double)rand() / RAND_MAX;
     double newPoint[4][2] = {{midpoint[0] - covar1[0] * size_param_1 +r1,
 			      midpoint[1] - covar1[1] * size_param_1 +r2},
 			     {midpoint[0] - covar2[0] * size_param_2 +r3,
diff --git a/benchmarks/hex/cube.geo b/benchmarks/hex/cube.geo
index b10cf147f1f6f4c6763913abb91f0f0dcee246aa..5232659f840bedfba0ac988be755ee59919915e6 100644
--- a/benchmarks/hex/cube.geo
+++ b/benchmarks/hex/cube.geo
@@ -4,15 +4,15 @@ Mesh.Recombine3DAll = 1;
 Mesh.Smoothing = 0;
 
 c1 = 0.25; //125;
-c2 = 0.25;
-Point(1) = {1, 1, -1, c1};
+c2 = 0.05;
+Point(1) = {1, 1, -1, c2};
 Point(2) = {-1, 1, -1, c1};
 Point(3) = {-1, -1, -1, c1};
 Point(4) = {1, -1, -1, c1};
-Point(5) = {1, 1, 1, c2};
-Point(6) = {-1, 1, 1, c2};
-Point(7) = {1, -1, 1, c2};
-Point(8) = {-1, -1, 1, c2};
+Point(5) = {1, 1, 1, c1};
+Point(6) = {-1, 1, 1, c1};
+Point(7) = {1, -1, 1, c1};
+Point(8) = {-1, -1, 1, c1};
 Line(1) = {7, 5};
 Line(2) = {5, 6};
 Line(3) = {6, 8};
diff --git a/utils/converters/autocad/dxf2geo.cpp b/utils/converters/autocad/dxf2geo.cpp
index 5794f271eb675faca4fdb8715dd3366ba7861739..a7af2d48728aba43889f8cdae5c22ddbc3cc8727 100644
--- a/utils/converters/autocad/dxf2geo.cpp
+++ b/utils/converters/autocad/dxf2geo.cpp
@@ -292,8 +292,10 @@ void addobj(void)
   else if(strstr(curobj, "TEXT")) {     /* not implemented for now */
   }
   else if(strstr(curobj, "SHAPE")) {    /* these look very hard */
+    printf("SHAPE\n");
   }
   else if(strstr(curobj, "BLOCK")) {    /* these look very hard */
+    printf("BLOCK\n");
   }
   else if(strstr(curobj, "ENDBLK")) {   /* these look very hard */
   }
@@ -304,6 +306,7 @@ void addobj(void)
   else if(strstr(curobj, "ATTRIB")) {   /* not implemented for now */
   }
   else if(strstr(curobj, "POLYLINE")) { /* these look fairly hard */
+    printf("POLYLINE\n");
   }
   else if(strstr(curobj, "VERTEX")) {   /* these look fairly hard */
     if(ints[0] == 192) {
@@ -407,6 +410,9 @@ void addobj(void)
   }
   else if(strstr(curobj, "DIMENSION")) {        /* not implemented for now */
   }
+  else {
+    printf("%s\n",curobj);
+  }
 
 }