From 43433727451fff6d7b3b19dace07bbcd4593c511 Mon Sep 17 00:00:00 2001
From: Tristan Carrier Baudouin <tristan.carrier@uclouvain.be>
Date: Fri, 4 Mar 2011 10:33:31 +0000
Subject: [PATCH] lpcvt

---
 CMakeLists.txt               |    5 +-
 Common/LuaBindings.cpp       |    3 +
 Common/gmshpy.i              |    2 +
 Geo/GModel.h                 |    2 +-
 Mesh/meshGFaceLloyd.cpp      | 1385 +++++++++++++++++++++++++---------
 Mesh/meshGFaceLloyd.h        |   92 ++-
 Mesh/meshGFaceOptimize.cpp   |  182 ++++-
 Mesh/meshGFaceOptimize.h     |   18 +
 Numeric/DivideAndConquer.cpp |   36 +-
 Numeric/DivideAndConquer.h   |   14 +-
 10 files changed, 1366 insertions(+), 373 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7ed51dcdaa..78372cafba 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -43,7 +43,7 @@ option(ENABLE_OCC "Enable Open CASCADE geometrical models" ON)
 option(ENABLE_ACIS "Enable ACIS geometrical models" ON)
 option(ENABLE_OSMESA "Use OSMesa for offscreen rendering" OFF)
 option(ENABLE_PARSER "Build the GEO file parser" ON)
-option(ENABLE_PETSC "Enable PETSc linear algebra solvers" ON)
+option(ENABLE_PETSC "Enable PETSc linear algebra solvers" OFF)
 option(ENABLE_POST "Build the post-processing module" ON)
 option(ENABLE_PLUGINS "Build the post-processing plugins" ON)
 option(ENABLE_QT "Build QT GUI" OFF)
@@ -439,6 +439,9 @@ if(ENABLE_CHACO)
   set_config_option(HAVE_CHACO "Chaco")
 endif(ENABLE_CHACO)
 
+add_subdirectory(contrib/lbfgs)
+include_directories(contrib/lbfgs)
+
 if(ENABLE_DINTEGRATION)
   add_subdirectory(contrib/DiscreteIntegration)
   include_directories(contrib/DiscreteIntegration)
diff --git a/Common/LuaBindings.cpp b/Common/LuaBindings.cpp
index 6b033c9c9b..6d6c4fe586 100644
--- a/Common/LuaBindings.cpp
+++ b/Common/LuaBindings.cpp
@@ -33,6 +33,8 @@
 #include "polynomialBasis.h"
 #include "Gauss.h"
 #include "meshPartitionOptions.h"
+#include "meshGFaceOptimize.h"
+#include "meshGFaceLloyd.h"
 
 #if defined(HAVE_OPENGL)
 #include "drawContext.h"
@@ -418,6 +420,7 @@ binding::binding()
   polynomialBasis::registerBindings(this);
   gaussIntegration::registerBindings(this);
   meshPartitionOptions::registerBindings(this);
+  Temporary::registerBindings(this);
 #if defined(HAVE_SOLVER)
   function::registerBindings(this);
   linearSystem<double>::registerBindings(this);
diff --git a/Common/gmshpy.i b/Common/gmshpy.i
index 1136a7fc06..c225e6672e 100644
--- a/Common/gmshpy.i
+++ b/Common/gmshpy.i
@@ -31,6 +31,7 @@
   #include "meshPartitionOptions.h"
   #include "linearSystemCSR.h"
   #include "elasticitySolver.h"
+  #include "meshGFaceLloyd.h"
   #include "PView.h"
   #include "PViewData.h"
   #include "PViewFactory.h"
@@ -125,5 +126,6 @@ namespace std {
 %include "SPoint2.h"
 %include "GPoint.h"  
 %include "functionPython.h"
+%include "meshGFaceLloyd.h"
 %include "DefaultOptions.h"
 
diff --git a/Geo/GModel.h b/Geo/GModel.h
index 7297e5beca..4595ab2ff5 100644
--- a/Geo/GModel.h
+++ b/Geo/GModel.h
@@ -404,7 +404,7 @@ class GModel
                    double angle);
   GEntity *extrude(GEntity *e, std::vector<double> p1, std::vector<double> p2);
   GEntity *addPipe(GEntity *e, std::vector<GEdge *>  edges);
-  
+
   void addRuledFaces(std::vector<std::vector<GEdge *> > edges);
   GFace *addFace(std::vector<GEdge *> edges, std::vector< std::vector<double > > points);
   GFace *addPlanarFace(std::vector<std::vector<GEdge *> > edges);
diff --git a/Mesh/meshGFaceLloyd.cpp b/Mesh/meshGFaceLloyd.cpp
index 4f3a57b818..9e865247ae 100644
--- a/Mesh/meshGFaceLloyd.cpp
+++ b/Mesh/meshGFaceLloyd.cpp
@@ -8,38 +8,89 @@
 #include "Context.h"
 #include "meshGFace.h"
 #include "BackgroundMesh.h"
+#include <fstream>
+#include "ap.h"
+#include "alglibinternal.h"
+#include "alglibmisc.h"
+#include "linalg.h"
+#include "optimization.h"
 
-/*List of parameters to modify*/ 
-//Line 76 : the variable "number" contains the number of points to remove.
-//Line 165 : the variable "test" is printed by the script.
-//Line 190 : the variable "angle" specifies the orientation of the mesh.
-//Line 287 : the variable "num" contains the number of iteration of the bisection method
-//used to find the fixed point.
-//Line 447 : it is the function "optimize" that needs to be called by the script.
-//Line 455 : put "lloyd(face)" in commentary to avoid calling the l1 lloyds method.
-//Line 456 : put "recombineIntoQuads(face,1,1)" in commentary to avoid calling the quad 
-//meshing method.
-//Line 461 : the code below line 461 refers to Lua and might need to be removed.
-
-void lloydAlgorithm::operator () (GFace *gf) 
+
+
+/****************fonction callback****************/
+/*************************************************/
+
+void function1_grad(const alglib::real_1d_array& x,double& func,alglib::real_1d_array& grad,void* ptr){
+  int i;
+  int p;
+  int num;
+  int index;
+  int dimension;
+  int identificator;
+  GFace* gf;
+  DocRecord* pointer;
+  	
+  pointer = static_cast<DocRecord*>(ptr);	
+  p = pointer->get_p();
+  dimension = pointer->get_dimension();
+  gf = pointer->get_face();
+  num = pointer->numPoints;
+
+  std::vector<SVector3> gradients(num);
+  std::vector<double> energies(num);
+  std::vector<SVector3> area_centroids(num);
+  std::vector<double> areas(num);	
+	
+  index = 0;
+  for(i=0;i<num;i++){
+    PointRecord &pt = pointer->points[i];
+	MVertex *v = (MVertex*)pt.data;
+	if(v->onWhat()==gf && !pointer->onHull(i)){
+	  pointer->points[i].where.h = x[index];
+	  pointer->points[i].where.v = x[index + dimension/2];
+	  pointer->points[i].identificator = index;
+	  index++;
+	}
+  }
+  
+  pointer->Voronoi();
+	
+  lloydAlgorithm lloyd;
+  lloyd.eval(*pointer,gf,gradients,energies,area_centroids,areas,p);
+  func = lloyd.total_energy(energies);
+  printf("%f\n",1E18*func);
+	
+  for(i=0;i<num;i++){
+    PointRecord &pt = pointer->points[i];
+	MVertex *v = (MVertex*)pt.data;
+	if(v->onWhat()==gf && !pointer->onHull(i)){
+	  identificator = pointer->points[i].identificator;
+	  grad[identificator] = gradients[i].x();
+	  grad[identificator + dimension/2] = gradients[i].y();
+	}
+  }	
+}
+
+void topology(const alglib::real_1d_array &x,double func,void *ptr){
+}
+
+
+
+/****************fonctions principales****************/
+/*****************************************************/
+
+void lloydAlgorithm::operator () (GFace *gf)
 {
   std::set<MVertex*> all;
 
-  // get all the points of the face ...
   for (unsigned int i = 0; i < gf->getNumMeshElements(); i++){
     MElement *e = gf->getMeshElement(i);
     for (int j = 0;j<e->getNumVertices(); j++){
       MVertex *v = e->getVertex(j);
-      //if (v->onWhat()->dim() < 2){
-	all.insert(v);
-	//}
+	  all.insert(v);
     }
   }
 
-  backgroundMesh::set(gf);
-  backgroundMesh::current()->print("bgm.pos", 0);
-
-  // Create a triangulator
   DocRecord triangulator(all.size());
   
   Range<double> du = gf->parBounds(0) ;
@@ -48,9 +99,6 @@ void lloydAlgorithm::operator () (GFace *gf)
   const double LC2D = sqrt((du.high()-du.low())*(du.high()-du.low()) +
                            (dv.high()-dv.low())*(dv.high()-dv.low()));  
 
-  //printf("Lloyd on face %d %d elements %d nodes LC %g\n", gf->tag(),
-  //       gf->getNumMeshElements(), (int)all.size(), LC2D);
-
   int i = 0;
   for (std::set<MVertex*>::iterator it = all.begin(); it != all.end(); ++it){
     SPoint2 p;
@@ -72,10 +120,10 @@ void lloydAlgorithm::operator () (GFace *gf)
   triangulator.Voronoi();
   triangulator.initialize();
   int index,number,count,max;
-  bool recent;
-  number = 0; //This variable contains the number of points to remove.
+  bool flag;
+  number = 0;
   count = 0;
-  max = 100000;
+  max = 1000;
   for(int i=0;i<max;i++)
   {
     if(count>=number) break;
@@ -83,389 +131,1020 @@ void lloydAlgorithm::operator () (GFace *gf)
 	PointRecord& pt = triangulator.points[index];
 	MVertex* v = (MVertex*)pt.data;
 	if(v->onWhat()==gf && !triangulator.onHull(index)){
-	  recent = triangulator.remove_point(index);
-	  if(recent) count++;
+	  flag = triangulator.remove_point(index);
+	  if(flag) count++;
 	}
   }
-  triangulator.remove_all();
+  triangulator.remove_all();	
+	
+  /*triangulator.Voronoi();
+  double delta;
+  delta = 0.2;
+  for(int i=0;i<triangulator.numPoints;i++){
+    PointRecord& pt = triangulator.points[i];
+	MVertex* v = (MVertex*)pt.data;
+	if(v->onWhat()==gf && !triangulator.onHull(i)){
+	  triangulator.points[i].where.h = delta + (1.0-2.0*delta)*((double)rand()/(double)RAND_MAX);
+	  triangulator.points[i].where.v = delta + (1.0-2.0*delta)*((double)rand()/(double)RAND_MAX);
+	}
+  }*/	
+
+  int exponent = 8;	
 	
-  // compute the Voronoi diagram
   triangulator.Voronoi();
-  //printf("hullSize = %d\n",triangulator.hullSize());
   triangulator.makePosView("LloydInit.pos");
-  //triangulator.printMedialAxis("medialAxis.pos");
+  	
+  int num_interior;
+  double initial_conditions[2*triangulator.numPoints];
+  num_interior = 0;
+  for(int i=0;i<triangulator.numPoints;i++){
+    PointRecord& pt = triangulator.points[i];
+	MVertex* v = (MVertex*)pt.data;
+	if(v->onWhat()==gf && !triangulator.onHull(i)){
+	  num_interior++;
+	}
+  }
+  index = 0;
+  for(int i=0;i<triangulator.numPoints;i++){
+    PointRecord& pt = triangulator.points[i];
+	MVertex* v = (MVertex*)pt.data;
+	if(v->onWhat()==gf && !triangulator.onHull(i)){
+	  initial_conditions[index] = triangulator.points[i].where.h;
+	  initial_conditions[index+num_interior] = triangulator.points[i].where.v;
+	  index++;
+	}
+  }
+  alglib::real_1d_array x;
+  x.setcontent(2*num_interior,initial_conditions);
   
-  // now do the Lloyd iterations
-  int ITER = 0;
-  while (1){
-    // store the new coordinates there
-    fullMatrix<double> cgs(triangulator.numPoints,2);
-    // now iterate on internal vertices
-    double ENERGY = 0.0;
-    double criteria = 0.0;
-    for (int i=0; i<triangulator.numPoints;i++){
-      // get the ith vertex
-      PointRecord &pt = triangulator.points[i];
-      MVertex *v = (MVertex*)pt.data;
-      if (v->onWhat() == gf && !triangulator.onHull(i)){
-        // get the voronoi corners
-        std::vector<SPoint2> pts;
-        triangulator.voronoiCell (i,pts); 
-        double E, A;
-        SPoint2 p(pt.where.h,pt.where.v);
-		for(int k=0;k<pts.size();k++){
-		  rotate(p,pts[k]);
-		}
-		SPoint2 point = fixed_point(pts); //Fixed point for quad mesh generation
-		unrotate(p,point);
-		cgs(i,0) = point.x();
-		cgs(i,1) = point.y();
-        ENERGY += E;
-	double d = sqrt((p.x()-cgs(i,0))*(p.x()-cgs(i,0))+
-			(p.y()-cgs(i,1))*(p.y()-cgs(i,1)));
-	criteria += d/A;
-      }// if (v->onWhat() == gf)
-      else {
-      }
-    }// for all points
-
-    for(PointNumero i = 0; i < triangulator.numPoints; i++) {
-      MVertex *v = (MVertex*)triangulator.points[i].data;
-      if (v->onWhat() == gf && !triangulator.onHull(i)){
-        triangulator.points[i].where.h = cgs(i,0);
-        triangulator.points[i].where.v = cgs(i,1);
-      }
-    }
-
-    Msg::Debug("GFace %d Lloyd-iter %d Inertia=%g Convergence=%g ", gf->tag(), 
-               ITER++, ENERGY, criteria);
-    if (ITER > ITER_MAX)break;
-
-    // compute the Voronoi diagram
-    triangulator.Voronoi();
-
-    if (ITER % 10 == 0){
-      char name[234];
-      sprintf(name,"LloydIter%d.pos",ITER);
-      triangulator.makePosView(name);
-    }
+  triangulator.set_p(exponent);
+  triangulator.set_dimension(2*num_interior);
+  triangulator.set_face(gf);	
+  
+  double epsg = 0;
+  double epsf = 0;
+  double epsx = 0;
+  alglib::ae_int_t maxits = 0;
+  alglib::minlbfgsstate state;
+  alglib::minlbfgsreport rep;
+	
+  minlbfgscreate(2*num_interior,4,x,state);
+  minlbfgssetcond(state,epsg,epsf,epsx,maxits);
+  minlbfgsoptimize(state,function1_grad,NULL,&triangulator);
+  minlbfgsresults(state,x,rep);
+	
+  index = 0;
+  for(i=0;i<triangulator.numPoints;i++){
+    PointRecord &pt = triangulator.points[i];
+	MVertex *v = (MVertex*)pt.data;
+	if(v->onWhat()==gf && !triangulator.onHull(i)){
+	  triangulator.points[i].where.h = x[index];
+	  triangulator.points[i].where.v = x[index + num_interior];
+	  index++;
+	}
   }
+  triangulator.Voronoi();	
 	
-  // now create the vertices
   test = 0;
   std::vector<MVertex*> mesh_vertices;
   for (int i=0; i<triangulator.numPoints;i++){
-    // get the ith vertex
     PointRecord &pt = triangulator.points[i];
     MVertex *v = (MVertex*)pt.data;
     if (v->onWhat() == gf && !triangulator.onHull(i)){
       GPoint gp = gf->point (pt.where.h,pt.where.v);
       MFaceVertex *v = new MFaceVertex(gp.x(),gp.y(),gp.z(),gf,gp.u(),gp.v());
-	  mesh_vertices.push_back(v);
+      mesh_vertices.push_back(v);
 	  test++;
     }
   }
 
-  // destroy the mesh
   deMeshGFace killer;
   killer(gf);
   
-  // put all additional vertices in the list of
-  // vertices
   gf->_additional_vertices = mesh_vertices;
-  // remesh the face with all those vertices in
   Msg::Info("Lloyd remeshing of face %d ", gf->tag());
   meshGFace mesher;
   mesher(gf);
-  // assign those vertices to the face internal vertices
   gf->mesh_vertices.insert(gf->mesh_vertices.begin(),
                            gf->_additional_vertices.begin(),  
                            gf->_additional_vertices.end());  
-  // clear the list of additional vertices
-  gf->_additional_vertices.clear();
-}
-
-double lloydAlgorithm::get_angle(double x,double y){
-  double angle;
-  angle = M_PI/4.0; //This variable specifies the orientation of the mesh.
-  return angle;
-}
-
-//This function returns the a, b, c and d components of the rotation matrix.
-void lloydAlgorithm::get_rotation(double x,double y,double& a,double& b,double& c,double& d){
-  double angle;
-  angle = get_angle(x,y);
-  a = cos(angle);
-  b = -sin(angle);
-  c = sin(angle);
-  d = cos(angle);
-}
-
-//This function returns the a, b, c and d components of the inverse rotation matrix.
-void lloydAlgorithm::get_unrotation(double x,double y,double& _a,double& _b,double& _c,double& _d){
-  double a,b,c,d;
-  double det;
-  get_rotation(x,y,a,b,c,d);
-  det = 1.0/(a*d-b*c);
-  _a = d/det;
-  _b = -b/det;
-  _c = -c/det;
-  _d = a/det;
-}
-
-//This function rotates a vertice (point) belonging to a Voronoi cell.
-//The angle is specified by the location of the generator, because we want all vertices
-//of the Voronoi cell to be rotated by the same amount in case the orientation of the
-//mesh is not constant.
-//The generator itself is not rotated.
-void lloydAlgorithm::rotate(SPoint2 generator,SPoint2& point){
-  double x,y;
-  double new_x,new_y;
-  double a,b,c,d;
-  get_rotation(generator.x(),generator.y(),a,b,c,d);
-  x = point.x();
-  y = point.y();
-  new_x = a*x + b*y;
-  new_y = c*x + d*y;
-  point.setPosition(new_x,new_y);
-}
-
-//This function rotates a vertice (point) belonging to a Voronoi cell in the reverse direction.
-//The angle is specified by the location of the generator, because we want all vertices
-//of the Voronoi cell to be rotated by the same amount in case the orientation of the
-//mesh is not constant.
-//The generator itself is not rotated.
-void lloydAlgorithm::unrotate(SPoint2 generator,SPoint2& point){
-  double x,y;
-  double new_x,new_y;
-  double a,b,c,d;
-  get_unrotation(generator.x(),generator.y(),a,b,c,d);
-  x = point.x();
-  y = point.y();
-  new_x = a*x + b*y;
-  new_y = c*x + d*y;
-  point.setPosition(new_x,new_y);
-}
-
-//This function returns the fixed point of the voronoi cell specified in argument (polygon).
-//It finds the bounding box of the voronoi cell and then it calls the function range in x and y.
-SPoint2 lloydAlgorithm::fixed_point(const std::vector<SPoint2>& polygon){
-  int i,num;
-  double x,y;
-  double x_min,y_min;
-  double x_max,y_max;
-  double solution_x,solution_y;
-  SPoint2 point;
-  x_min = 100000000.0;
-  y_min = 100000000.0;
-  x_max = -100000000.0;
-  y_max = -100000000.0;
-  num = polygon.size();
-  for(i=0;i<num;i++){
-	point = polygon[i];
-    x = point.x();
-	y = point.y();
-	if(x < x_min) x_min = x;
-	if(y < y_min) y_min = y;
-	if(x > x_max) x_max = x;
-	if(y > y_max) y_max = y;
-  }
-  solution_x = range(polygon,x_min,x_max,1);
-  solution_y = range(polygon,y_min,y_max,0);
-  return SPoint2(solution_x,solution_y);
-}
-
-//This function returns the x or y median of the Voronoi cell specified in argument (polygon).
-//If direction = 1, the function will return the x median.
-//If direction = 0, the function will return the y median.
-//The variables u1 and u2 should be respectively equal to the minimum and the maximum of x or y,
-//depending of the value of direction.
-//This function uses the bisection method.
-double lloydAlgorithm::range(const std::vector<SPoint2>& polygon,double u1,double u2,bool direction){
-  int i,num;
-  double mid,val;
-  num = 16; //This variable specifies the number of iteration of the bisection method.
-  for(i=0;i<num;i++){
-	mid = 0.5*(u1 + u2);
-	val = gradient(polygon,mid,direction);
-	if(val >= 0) u2 = mid;
-	else u1 = mid;
-  }
-  return 0.5*(u1 + u2);
-}
-
-//This function returns the x or y component of the l1 gradient of the voronoi cell
-//specified in argument (polygon).
-//If direction = 1, it will return the x component.
-//If direction = 0, it will return the y component.
-//The variable generator should be equal to the x or y component of the point to which the 
-//voronoi cell belongs.
-//x component = A1-A2, A1 : area of the left part, A2 : area of the right part
-//y component = A3-A4, A3 : area of the lower part, A4 : area of the higher part
-double lloydAlgorithm::gradient(const std::vector<SPoint2>& polygon,double generator,bool direction){
-  int i,num,index1,index2;
-  bool intersection,side;
-  double areaA,areaB;
-  SPoint2 p1,p2,solution;
-  std::vector<bool> category;
-  std::vector<SPoint2> new_polygon;
-  std::vector<SPoint2> polygonA;
-  std::vector<SPoint2> polygonB;
-  num = polygon.size();
-  for(i=0;i<num;i++){
-	index1 = i;
-	index2 = (i+1)%num;
-	p1 = polygon[index1];
-	p2 = polygon[index2];
-	solution = line_intersection(p1,p2,generator,direction,intersection);
-	if(intersection){
-	  new_polygon.push_back(p1);
-	  new_polygon.push_back(solution);
-	  category.push_back(1);
-	  category.push_back(0);	
-	}
-	else{
-	  new_polygon.push_back(p1);
-	  category.push_back(1);	
+  gf->_additional_vertices.clear();  
+}
+
+double lloydAlgorithm::optimize(int max,int flag){
+  GFace*face;
+  GModel*model = GModel::current();
+  GModel::fiter iterator;
+  lloydAlgorithm lloyd(max,flag);
+  for(iterator = model->firstFace();iterator != model->lastFace();iterator++)
+  {
+    face = *iterator;
+	if(face->getNumMeshElements() > 0){
+	  lloyd(face);
+	  recombineIntoQuads(face,1,1);
 	}
   }
-  num = new_polygon.size();
-  for(i=0;i<num;i++){
-	if(category[i]){
-	  side = point_side(new_polygon[i],generator,direction);
-	  if(side){
-	    polygonA.push_back(new_polygon[i]);
+  return lloyd.test;
+}
+
+
+
+/****************Calcul du gradient****************/
+/**************************************************/
+
+void lloydAlgorithm::eval(DocRecord& triangulator,GFace* gf,std::vector<SVector3>& gradients,std::vector<double>& energies,std::vector<SVector3>& area_centroids,std::vector<double>& areas,int p){
+  int i;
+  
+  for(i=0;i<triangulator.numPoints;i++){
+    gradients[i] = SVector3(0.0,0.0,0.0);
+	energies[i] = 0.0;
+    area_centroids[i] = SVector3(0.0,0.0,0.0);
+	areas[i] = 0.0;
+  }
+	
+  for(i=0;i<triangulator.numPoints;i++){
+    PointRecord &pt = triangulator.points[i];
+	MVertex *v = (MVertex*)pt.data;
+	if(v->onWhat()==gf && !triangulator.onHull(i)){
+	  bool is_inside1;
+	  bool is_inside2;
+	  bool flag;
+	  int num = triangulator._adjacencies[i].t_length;
+	  for(int j=0;j<num;j++){
+	    int index3 = triangulator._adjacencies[i].t[j];
+		int index2 = triangulator._adjacencies[i].t[(j+1)%num];
+		int index1 = triangulator._adjacencies[i].t[(j+2)%num];
+		double _x0[2] = {triangulator.points[i].where.h,triangulator.points[i].where.v};
+		double _x1[2] = {triangulator.points[index1].where.h,triangulator.points[index1].where.v};
+	    double _x2[2] = {triangulator.points[index2].where.h,triangulator.points[index2].where.v};
+		double _x3[2] = {triangulator.points[index3].where.h,triangulator.points[index3].where.v};
+		SPoint2 x0(_x0[0],_x0[1]);
+		SPoint2 x1(_x1[0],_x1[1]);
+		SPoint2 x2(_x2[0],_x2[1]);
+		SPoint2 x3(_x3[0],_x3[1]);
+		double _C1[2];
+		double _C2[2];
+		circumCenterXY(_x0,_x1,_x2,_C1);
+		circumCenterXY(_x0,_x2,_x3,_C2);
+		SPoint2 C1(_C1[0],_C1[1]);
+		SPoint2 C2(_C2[0],_C2[1]);
+		is_inside1 = inside_domain(C1.x(),C1.y());
+		is_inside2 = inside_domain(C2.x(),C2.y());
+		if(is_inside1 && is_inside2){
+		  energies[i] = energies[i] + F(x0,C1,C2,p);
+		  gradients[i] = gradients[i] + simple(x0,C1,C2,p);
+		  area_centroids[i] = area_centroids[i] + area_centroid(x0,C1,C2);
+		  areas[i] = areas[i] + triangle_area(x0,C1,C2);
+		  SVector3 grad1 = dF_dC1(x0,C1,C2,p);
+		  SVector3 grad2 = dF_dC2(x0,C1,C2,p);
+		  gradients[i] = gradients[i] + inner_dFdx0(grad1,C1,x0,x1,x2);
+		  gradients[index1] = gradients[index1] + inner_dFdx0(grad1,C1,x1,x0,x2);
+		  gradients[index2] = gradients[index2] + inner_dFdx0(grad1,C1,x2,x0,x1);
+		  gradients[i] = gradients[i] + inner_dFdx0(grad2,C2,x0,x2,x3);
+		  gradients[index2] = gradients[index2] + inner_dFdx0(grad2,C2,x2,x0,x3);
+		  gradients[index3] = gradients[index3] + inner_dFdx0(grad2,C2,x3,x0,x2);
+		}
+		else if(is_inside1){
+		  SPoint2 first;
+		  SPoint2 second;
+		  SVector3 vecA;
+		  SVector3 vecB;
+		  first = boundary_intersection(C1,C2,flag,vecA);
+		  second = boundary_intersection(x0,C2,flag,vecB);
+		  energies[i] = energies[i] + F(x0,C1,first,p);
+		  energies[i] = energies[i] + F(x0,first,second,p);
+		  gradients[i] = gradients[i] + simple(x0,C1,first,p);
+		  gradients[i] = gradients[i] + simple(x0,first,second,p);
+		  area_centroids[i] = area_centroids[i] + area_centroid(x0,C1,first);
+		  area_centroids[i] = area_centroids[i] + area_centroid(x0,first,second);
+		  areas[i] = areas[i] + triangle_area(x0,C1,first);
+		  areas[i] = areas[i] + triangle_area(x0,first,second);
+		  SVector3 grad1 = dF_dC1(x0,C1,first,p);
+		  SVector3 grad2 = dF_dC2(x0,C1,first,p);
+		  SVector3 grad3 = dF_dC1(x0,first,second,p);
+		  gradients[i] = gradients[i] + inner_dFdx0(grad1,C1,x0,x1,x2);
+		  gradients[index1] = gradients[index1] + inner_dFdx0(grad1,C1,x1,x0,x2);
+		  gradients[index2] = gradients[index2] + inner_dFdx0(grad1,C1,x2,x0,x1);
+		  gradients[i] = gradients[i] + boundary_dFdx0(grad2,first,x0,x2,vecA);
+		  gradients[index2] = gradients[index2] + boundary_dFdx0(grad2,first,x2,x0,vecA);
+		  gradients[i] = gradients[i] + boundary_dFdx0(grad3,first,x0,x2,vecA);
+		  gradients[index2] = gradients[index2] + boundary_dFdx0(grad3,first,x2,x0,vecA);
+		}
+		else if(is_inside2){
+		  SPoint2 first;
+		  SPoint2 second;
+		  SVector3 vecA;
+		  SVector3 vecB;
+		  first = boundary_intersection(C1,C2,flag,vecA);
+		  second = boundary_intersection(x0,C1,flag,vecB);
+		  energies[i] = energies[i] + F(x0,second,first,p);
+		  energies[i] = energies[i] + F(x0,first,C2,p);
+		  gradients[i] = gradients[i] + simple(x0,second,first,p);
+		  gradients[i] = gradients[i] + simple(x0,first,C2,p);
+		  area_centroids[i] = area_centroids[i] + area_centroid(x0,second,first);
+		  area_centroids[i] = area_centroids[i] + area_centroid(x0,first,C2);
+		  areas[i] = areas[i] + triangle_area(x0,second,first);
+		  areas[i] = areas[i] + triangle_area(x0,first,C2);
+		  SVector3 grad1 = dF_dC2(x0,second,first,p);
+		  SVector3 grad2 = dF_dC1(x0,first,C2,p);
+		  SVector3 grad3 = dF_dC2(x0,first,C2,p);
+		  gradients[i] = gradients[i] + inner_dFdx0(grad3,C2,x0,x2,x3);
+		  gradients[index2] = gradients[index2] + inner_dFdx0(grad3,C2,x2,x0,x3);
+		  gradients[index3] = gradients[index3] + inner_dFdx0(grad3,C2,x3,x0,x2);
+		  gradients[i] = gradients[i] + boundary_dFdx0(grad2,first,x0,x2,vecA);
+		  gradients[index2] = gradients[index2] + boundary_dFdx0(grad2,first,x2,x0,vecA);
+		  gradients[i] = gradients[i] + boundary_dFdx0(grad1,first,x0,x2,vecA);
+		  gradients[index2] = gradients[index2] + boundary_dFdx0(grad1,first,x2,x0,vecA);
+		}
+		else{
+		  SPoint2 first;
+		  SPoint2 second;
+		  SPoint2 third;
+		  SPoint2 fourth;
+		  SPoint2 median;
+		  SPoint2 any;
+		  SVector3 vecA;
+		  SVector3 vecB;
+		  SVector3 vec;
+		  any = boundary_intersection(C1,C2,flag,vec);
+		  if(flag){
+		    median = mid(x0,x2);
+			first = boundary_intersection(median,C1,flag,vecA);
+			second = boundary_intersection(median,C2,flag,vecB);
+			third = boundary_intersection(x0,C1,flag,vec);
+			fourth = boundary_intersection(x0,C2,flag,vec);
+			energies[i] = energies[i] + F(x0,first,second,p);
+			energies[i] = energies[i] + F(x0,third,first,p);
+			energies[i] = energies[i] + F(x0,second,fourth,p);
+			gradients[i] = gradients[i] + simple(x0,first,second,p);
+			gradients[i] = gradients[i] + simple(x0,third,first,p);
+			gradients[i] = gradients[i] + simple(x0,second,fourth,p);
+			area_centroids[i] = area_centroids[i] + area_centroid(x0,first,second);
+			area_centroids[i] = area_centroids[i] + area_centroid(x0,third,first);
+			area_centroids[i] = area_centroids[i] + area_centroid(x0,second,fourth);
+			areas[i] = areas[i] + triangle_area(x0,first,second);
+			areas[i] = areas[i] + triangle_area(x0,third,first);
+			areas[i] = areas[i] + triangle_area(x0,second,fourth);
+			SVector3 grad1 = dF_dC1(x0,first,second,p);
+			SVector3 grad2 = dF_dC2(x0,first,second,p);  
+			SVector3 grad3 = dF_dC2(x0,third,first,p);  
+			SVector3 grad4 = dF_dC1(x0,second,fourth,p);  
+			gradients[i] = gradients[i] + boundary_dFdx0(grad1,first,x0,x2,vecA);
+			gradients[index2] = gradients[index2] + boundary_dFdx0(grad1,first,x2,x0,vecA);  
+			gradients[i] = gradients[i] + boundary_dFdx0(grad2,second,x0,x2,vecB);
+			gradients[index2] = gradients[index2] + boundary_dFdx0(grad2,second,x2,x0,vecB);
+			gradients[i] = gradients[i] + boundary_dFdx0(grad3,first,x0,x2,vecA);
+			gradients[index2] = gradients[index2] + boundary_dFdx0(grad3,first,x2,x0,vecA);  
+			gradients[i] = gradients[i] + boundary_dFdx0(grad4,second,x0,x2,vecB);
+			gradients[index2] = gradients[index2] + boundary_dFdx0(grad4,second,x2,x0,vecB);
+		  }
+		  else{
+		    first = boundary_intersection(x0,C1,flag,vec);
+			second = boundary_intersection(x0,C2,flag,vec);
+			energies[i] = energies[i] + F(x0,first,second,p);
+			gradients[i] = gradients[i] + simple(x0,first,second,p);
+			area_centroids[i] = area_centroids[i] + area_centroid(x0,first,second);
+			areas[i] = areas[i] + triangle_area(x0,first,second);
+		  }
+	    }
 	  }
-	  else{
-	    polygonB.push_back(new_polygon[i]);
+	}
+	else {
+      double e = 0.00000001;
+	  bool ok_triangle1;
+	  bool ok_triangle2;
+	  bool is_inside1;
+	  bool is_inside2;
+	  bool is_inside;
+	  bool flag;
+	  int num = triangulator._adjacencies[i].t_length;
+	  for(int j=0;j<num;j++){
+	    int index3 = triangulator._adjacencies[i].t[j];
+		int index2 = triangulator._adjacencies[i].t[(j+1)%num];
+		int index1 = triangulator._adjacencies[i].t[(j+2)%num];
+		if(index1!=index2 && index1!=index3 && index2!=index3 && i!=index1 && i!=index2 && i!=index3){
+		  double _x0[2] = {triangulator.points[i].where.h,triangulator.points[i].where.v};
+		  double _x1[2] = {triangulator.points[index1].where.h,triangulator.points[index1].where.v};
+		  double _x2[2] = {triangulator.points[index2].where.h,triangulator.points[index2].where.v};
+		  double _x3[2] = {triangulator.points[index3].where.h,triangulator.points[index3].where.v};
+		  SPoint2 x0(_x0[0],_x0[1]);
+		  SPoint2 x1(_x1[0],_x1[1]);
+		  SPoint2 x2(_x2[0],_x2[1]);
+		  SPoint2 x3(_x3[0],_x3[1]);
+		  ok_triangle1 = adjacent(triangulator,index1,index2) && triangle_area(x0,x1,x2)>e;
+		  ok_triangle2 = adjacent(triangulator,index2,index3) && triangle_area(x0,x2,x3)>e;
+		  if(ok_triangle1 && ok_triangle2){
+		    double _C1[2];
+			double _C2[2];
+			circumCenterXY(_x0,_x1,_x2,_C1);
+			circumCenterXY(_x0,_x2,_x3,_C2);
+			SPoint2 C1(_C1[0],_C1[1]);
+			SPoint2 C2(_C2[0],_C2[1]);
+			is_inside1 = inside_domain(C1.x(),C1.y());
+			is_inside2 = inside_domain(C2.x(),C2.y());
+		    if(is_inside1 && is_inside2){
+			  energies[i] = energies[i] + F(x0,C1,C2,p);
+			  SVector3 grad1 = dF_dC1(x0,C1,C2,p);
+			  SVector3 grad2 = dF_dC2(x0,C1,C2,p);
+			  gradients[index1] = gradients[index1] + inner_dFdx0(grad1,C1,x1,x0,x2);
+			  gradients[index2] = gradients[index2] + inner_dFdx0(grad1,C1,x2,x0,x1);
+			  gradients[index2] = gradients[index2] + inner_dFdx0(grad2,C2,x2,x0,x3);
+			  gradients[index3] = gradients[index3] + inner_dFdx0(grad2,C2,x3,x0,x2);
+		    }
+		    else if(is_inside1){
+		      SPoint2 val;
+			  SVector3 vec;
+			  val = boundary_intersection(C1,C2,flag,vec);
+			  energies[i] = energies[i] + F(x0,C1,val,p);
+			  SVector3 grad1 = dF_dC1(x0,C1,val,p);
+			  SVector3 grad2 = dF_dC2(x0,C1,val,p);
+			  gradients[index1] = gradients[index1] + inner_dFdx0(grad1,C1,x1,x0,x2);
+			  gradients[index2] = gradients[index2] + inner_dFdx0(grad1,C1,x2,x0,x1);
+			  gradients[index2] = gradients[index2] + boundary_dFdx0(grad2,val,x2,x0,vec);
+		    }
+		    else if(is_inside2){
+		      SPoint2 val;
+			  SVector3 vec;
+			  val = boundary_intersection(C1,C2,flag,vec);
+			  energies[i] = energies[i] + F(x0,val,C2,p);
+			  SVector3 grad1 = dF_dC1(x0,val,C2,p);
+			  SVector3 grad2 = dF_dC2(x0,val,C2,p);
+			  gradients[index2] = gradients[index2] + inner_dFdx0(grad2,C2,x2,x0,x3);
+			  gradients[index3] = gradients[index3] + inner_dFdx0(grad2,C2,x3,x0,x2);
+			  gradients[index2] = gradients[index2] + boundary_dFdx0(grad1,val,x2,x0,vec);
+		    }
+			else{
+			  SPoint2 first;
+			  SPoint2 second;
+			  SPoint2 median;
+			  SPoint2 any;
+			  SVector3 vecA;
+			  SVector3 vecB;
+			  SVector3 vec;
+			  any = boundary_intersection(C1,C2,flag,vec);
+			  if(flag){
+			    median = mid(x0,x2);
+				first = boundary_intersection(median,C1,flag,vecA);
+				second = boundary_intersection(median,C2,flag,vecB);
+				energies[i] = energies[i] + F(x0,first,second,p);
+				SVector3 grad1 = dF_dC1(x0,first,second,p);
+				SVector3 grad2 = dF_dC2(x0,first,second,p);
+				gradients[index2] = gradients[index2] + boundary_dFdx0(grad1,first,x2,x0,vecA);
+				gradients[index2] = gradients[index2] + boundary_dFdx0(grad2,second,x2,x0,vecB);
+			  }
+			}
+		  }
+		  else if(ok_triangle1){
+		    double _C[2];
+		    circumCenterXY(_x0,_x1,_x2,_C);
+			SPoint2 C(_C[0],_C[1]);
+			is_inside = inside_domain(C.x(),C.y());
+			if(is_inside){
+			  SPoint2 val;
+			  val = mid(x0,x2);
+			  energies[i] = energies[i] + F(x0,C,val,p);
+			  SVector3 grad1 = dF_dC1(x0,C,val,p);
+			  gradients[index1] = gradients[index1] + inner_dFdx0(grad1,C,x1,x0,x2);
+			}	  
+		  }
+		  else if(ok_triangle2){
+		    double _C[2];
+			circumCenterXY(_x0,_x2,_x3,_C);
+			SPoint2 C(_C[0],_C[1]);
+			is_inside = inside_domain(C.x(),C.y());
+			if(is_inside){
+			  SPoint2 val;
+			  val = mid(x0,x2);
+			  energies[i] = energies[i] + F(x0,val,C,p);
+			  SVector3 grad1 = dF_dC2(x0,val,C,p);
+			  gradients[index3] = gradients[index3] + inner_dFdx0(grad1,C,x3,x0,x2);
+		    }
+		  }
+	    }
 	  }
+    }
+  }
+}
+
+double lloydAlgorithm::total_energy(std::vector<double> energies){
+  int i;
+  double total;
+  total = 0.0;
+  for(i=0;i<energies.size();i++){
+    total = total + energies[i];
+  }
+  return total;
+}
+
+SVector3 lloydAlgorithm::numerical(DocRecord& triangulator,GFace* gf,int index,int p){
+  double x_original;
+  double y_original;
+  double energy_right;
+  double energy_left;
+  double energy_up;
+  double energy_down;
+  double comp_x;
+  double comp_y;
+  double e;
+  std::vector<double> energies(triangulator.numPoints);
+  std::vector<SVector3> gradients(triangulator.numPoints);
+  std::vector<SVector3> area_centroids(triangulator.numPoints);
+  std::vector<double> areas(triangulator.numPoints);
+  e = 0.00001;
+  x_original = triangulator.points[index].where.h;
+  y_original = triangulator.points[index].where.v;
+  
+  triangulator.points[index].where.h = x_original + e;
+  triangulator.points[index].where.v = y_original;
+  eval(triangulator,gf,gradients,energies,area_centroids,areas,p);
+  energy_right = total_energy(energies);
+
+  triangulator.points[index].where.h = x_original - e;
+  triangulator.points[index].where.v = y_original;
+  eval(triangulator,gf,gradients,energies,area_centroids,areas,p);
+  energy_left = total_energy(energies);
+	
+  triangulator.points[index].where.h = x_original;
+  triangulator.points[index].where.v = y_original + e;
+  eval(triangulator,gf,gradients,energies,area_centroids,areas,p);
+  energy_up = total_energy(energies);
+	
+  triangulator.points[index].where.h = x_original;
+  triangulator.points[index].where.v = y_original - e;
+  eval(triangulator,gf,gradients,energies,area_centroids,areas,p);
+  energy_down = total_energy(energies);
+  
+  comp_x = (energy_right - energy_left)/(2*e);	
+  comp_y = (energy_up - energy_down)/(2*e);		
+  
+  triangulator.points[index].where.h = x_original;
+  triangulator.points[index].where.v = y_original;	
+	
+  return SVector3(comp_x,comp_y,0.0);
+}
+
+void lloydAlgorithm::write(DocRecord& triangulator,GFace* gf,int p){
+  int i;
+  SVector3 grad1;
+  SVector3 grad2;
+  SVector3 ecart;
+  std::vector<SVector3> gradients(triangulator.numPoints);
+  std::vector<double> energies(triangulator.numPoints);
+  std::vector<SVector3> area_centroids(triangulator.numPoints);
+  std::vector<double> areas(triangulator.numPoints);
+	
+  eval(triangulator,gf,gradients,energies,area_centroids,areas,p);
+  
+  std::ofstream file("gradient");
+  
+  for(i=0;i<triangulator.numPoints;i++){
+    PointRecord& pt = triangulator.points[i];
+	MVertex* v = (MVertex*)pt.data;
+	if(v->onWhat()==gf && !triangulator.onHull(i)){
+	  grad1 = numerical(triangulator,gf,i,p);
+	  grad2 = gradients[i];
+	  ecart = grad1-grad2;
+	  file << grad1.x() << "  ";
+	  file << grad2.x() << "      ";
+	  file << grad1.y() << "  ";
+	  file << grad2.y() << "      ";
+	  file << 100.0*ecart.norm()/grad1.norm() << " ";
+	  file << "\n";
 	}
-	else{
-	  polygonA.push_back(new_polygon[i]);
-	  polygonB.push_back(new_polygon[i]);
+  }
+}
+
+void lloydAlgorithm::write2(DocRecord& triangulator,GFace* gf){
+  int i;
+  SPoint2 generator;
+  SVector3 grad1;
+  SVector3 grad2;
+  SVector3 ecart;
+  std::vector<SVector3> gradients(triangulator.numPoints);
+  std::vector<double> energies(triangulator.numPoints);
+  std::vector<SVector3> area_centroids(triangulator.numPoints);
+  std::vector<double> areas(triangulator.numPoints);
+	
+  eval(triangulator,gf,gradients,energies,area_centroids,areas,2);
+	
+  std::ofstream file("gradient2");
+	
+  for(i=0;i<triangulator.numPoints;i++){
+    PointRecord& pt = triangulator.points[i];
+	MVertex* v = (MVertex*)pt.data;
+	if(v->onWhat()==gf && !triangulator.onHull(i)){
+	  generator = SPoint2(triangulator.points[i].where.h,triangulator.points[i].where.v);
+	  grad1 = analytical(generator,area_centroids[i],areas[i]);
+	  grad2 = gradients[i];
+	  ecart = grad1-grad2;
+	  file << grad1.x() << "  ";
+	  file << grad2.x() << "      ";
+	  file << grad1.y() << "  ";
+	  file << grad2.y() << "      ";
+	  file << 100.0*ecart.norm()/grad1.norm() << " ";
+	  file << "\n";
 	}
   }
-  areaA = polygon_area(polygonA);
-  areaB = polygon_area(polygonB);
-  return areaA-areaB;
-}
-
-//The point p is a vertice of a Voronoi cell.
-//The variable generator contains the x or y component of the point to which
-//the Voronoi cell belongs. If direction = 1, it will contain the x component,
-//if direction = 0, it will contain the y component.
-//If direction = 1, this function will return 1 if p is at the left of the generator
-//and it will return 0 if p is at the right of the generator.
-//If direction = 0, this function will return 1 if p is below the generator
-//and it will return 0 if p is higher than the generator.
-bool lloydAlgorithm::point_side(SPoint2 p,double generator,bool direction){
-  if(direction){
-    if(p.x()<=generator) return 1;
-	else return 0;
+}
+
+SVector3 lloydAlgorithm::analytical(SPoint2 generator,SVector3 area_centroid,double area){
+  SVector3 _generator;
+  SVector3 val;
+  _generator = SVector3(generator.x(),generator.y(),0.0);
+  val = 2.0*area*(_generator - (1.0/area)*area_centroid);
+  return val;
+}
+
+SVector3 lloydAlgorithm::area_centroid(SPoint2 p1,SPoint2 p2,SPoint2 p3){
+  double x;
+  double y;
+  double area;
+  area = triangle_area(p1,p2,p3);
+  x = (1.0/3.0)*(p1.x() + p2.x() + p3.x());
+  y = (1.0/3.0)*(p1.y() + p2.y() + p3.y());
+  return SVector3(area*x,area*y,0.0);
+}
+
+
+
+/****************Fonctions pour le calcul du gradient****************/
+/********************************************************************/
+
+double lloydAlgorithm::F(SPoint2 generator,SPoint2 C1,SPoint2 C2,int p){
+  int i;
+  int num;
+  int order;
+  double x;
+  double y;
+  double energy;
+  SPoint2 point;
+  fullMatrix<double> pts;
+  fullMatrix<double> weights;
+  order = 8;
+  gaussIntegration::getTriangle(order,pts,weights);
+  num = pts.size1();
+  energy = 0.0;
+  for(i=0;i<num;i++){
+    x = Tx(pts(i,0),pts(i,1),generator,C1,C2);
+	y = Ty(pts(i,0),pts(i,1),generator,C1,C2);
+	point = SPoint2(x,y);
+	energy = energy + weights(i,0)*f(generator,point,p);
   }
-  else{
-    if(p.y()<=generator) return 1;
-	else return 0;
+  energy = J(generator,C1,C2)*energy;
+  return energy;
+}
+
+SVector3 lloydAlgorithm::simple(SPoint2 generator,SPoint2 C1,SPoint2 C2,int p){
+  int i;
+  int num;
+  int order;
+  double x;
+  double y;
+  double comp_x;
+  double comp_y;
+  SPoint2 point;
+  fullMatrix<double> pts;
+  fullMatrix<double> weights;
+  order = 8;
+  gaussIntegration::getTriangle(order,pts,weights);
+  num = pts.size1();
+  comp_x = 0.0;
+  comp_y = 0.0;
+  for(i=0;i<num;i++){
+    x = Tx(pts(i,0),pts(i,1),generator,C1,C2);
+	y = Ty(pts(i,0),pts(i,1),generator,C1,C2);
+	point = SPoint2(x,y);
+	comp_x = comp_x + weights(i,0)*df_dx(generator,point,p);
+	comp_y = comp_y + weights(i,0)*df_dy(generator,point,p);
   }
+  comp_x = J(generator,C1,C2)*comp_x;
+  comp_y = J(generator,C1,C2)*comp_y; 
+  return SVector3(comp_x,comp_y,0.0);
 }
 
-//This function uses the Surveyors Formula to calculate the area of the Voronoi cell
-//specified in argument (polygon).
-double lloydAlgorithm::polygon_area(const std::vector<SPoint2>& polygon){
+SVector3 lloydAlgorithm::dF_dC1(SPoint2 generator,SPoint2 C1,SPoint2 C2,int p){
   int i;
   int num;
+  int order;
+  double x;
+  double y;
+  double comp_x;
+  double comp_y;
+  SPoint2 point;
+  fullMatrix<double> pts;
+  fullMatrix<double> weights;
+  order = 8;
+  gaussIntegration::getTriangle(order,pts,weights);
+  num = pts.size1();
+  comp_x = 0.0;
+  comp_y = 0.0;
+  for(i=0;i<num;i++){
+    x = Tx(pts(i,0),pts(i,1),generator,C1,C2);
+	y = Ty(pts(i,0),pts(i,1),generator,C1,C2);
+	point = SPoint2(x,y);
+	comp_x = comp_x + weights(i,0)*df_dx(point,generator,p)*dTx_dp2x(pts(i,0),pts(i,1))*J(generator,C1,C2);
+	comp_x = comp_x + weights(i,0)*f(point,generator,p)*dJ_dp2x(generator,C1,C2);
+	comp_y = comp_y + weights(i,0)*df_dy(point,generator,p)*dTy_dp2y(pts(i,0),pts(i,1))*J(generator,C1,C2);
+	comp_y = comp_y + weights(i,0)*f(point,generator,p)*dJ_dp2y(generator,C1,C2);
+  }		
+  return SVector3(comp_x,comp_y,0.0);
+}
+
+SVector3 lloydAlgorithm::dF_dC2(SPoint2 generator,SPoint2 C1,SPoint2 C2,int p){
+  int i;
+  int num;
+  int order;
+  double x;
+  double y;
+  double comp_x;
+  double comp_y;
+  SPoint2 point;
+  fullMatrix<double> pts;
+  fullMatrix<double> weights;
+  order = 8;
+  gaussIntegration::getTriangle(order,pts,weights);
+  num = pts.size1();
+  comp_x = 0.0;
+  comp_y = 0.0;
+  for(i=0;i<num;i++){
+    x = Tx(pts(i,0),pts(i,1),generator,C1,C2);
+	y = Ty(pts(i,0),pts(i,1),generator,C1,C2);
+	point = SPoint2(x,y);
+	comp_x = comp_x + weights(i,0)*df_dx(point,generator,p)*dTx_dp3x(pts(i,0),pts(i,1))*J(generator,C1,C2);
+	comp_x = comp_x + weights(i,0)*f(point,generator,p)*dJ_dp3x(generator,C1,C2);
+	comp_y = comp_y + weights(i,0)*df_dy(point,generator,p)*dTy_dp3y(pts(i,0),pts(i,1))*J(generator,C1,C2);
+	comp_y = comp_y + weights(i,0)*f(point,generator,p)*dJ_dp3y(generator,C1,C2);
+  }		
+  return SVector3(comp_x,comp_y,0.0);
+}
+
+double lloydAlgorithm::f(SPoint2 p1,SPoint2 p2,int p){
+  double val;
+  val = exp(p1.x()-p2.x(),p) + exp(p1.y()-p2.y(),p);
+  return val;
+}
+
+double lloydAlgorithm::df_dx(SPoint2 p1,SPoint2 p2,int p){
+  double val;
+  val = ((double)p)*exp(p1.x()-p2.x(),p-1);
+  return val;
+}
+
+double lloydAlgorithm::df_dy(SPoint2 p1,SPoint2 p2,int p){
+  double val;
+  val = ((double)p)*exp(p1.y()-p2.y(),p-1);
+  return val;
+}
+
+double lloydAlgorithm::L1(double u,double v){
+  double val;
+  val = 1.0-u-v;
+  return val;
+}
+
+double lloydAlgorithm::dL1_du(){
+  return -1.0;
+}
+
+double lloydAlgorithm::dL1_dv(){
+  return -1.0;
+}
+
+double lloydAlgorithm::L2(double u,double v){
+  double val;
+  val = u;
+  return val;
+}
+
+double lloydAlgorithm::dL2_du(){
+  return 1.0;
+}
+
+double lloydAlgorithm::dL2_dv(){
+  return 0.0;
+}
+
+double lloydAlgorithm::L3(double u,double v){
+  double val;
+  val = v;
+  return val;
+}
+
+double lloydAlgorithm::dL3_du(){
+  return 0.0;
+}
+
+double lloydAlgorithm::dL3_dv(){
+  return 1.0;
+}
+
+double lloydAlgorithm::Tx(double u,double v,SPoint2 p1,SPoint2 p2,SPoint2 p3){
+  double val;
+  val = L1(u,v)*p1.x() + L2(u,v)*p2.x() + L3(u,v)*p3.x();
+  return val;
+}
+
+double lloydAlgorithm::dTx_dp1x(double u,double v){
+  return L1(u,v);
+}
+
+double lloydAlgorithm::dTx_dp2x(double u,double v){
+  return L2(u,v);
+}
+
+double lloydAlgorithm::dTx_dp3x(double u,double v){
+  return L3(u,v);
+}
+
+double lloydAlgorithm::dTx_du(SPoint2 p1,SPoint2 p2,SPoint2 p3){
+  double val;
+  val = dL1_du()*p1.x() + dL2_du()*p2.x() + dL3_du()*p3.x();
+  return val;
+}
+
+double lloydAlgorithm::dTx_dv(SPoint2 p1,SPoint2 p2,SPoint2 p3){
+  double val;
+  val = dL1_dv()*p1.x() + dL2_dv()*p2.x() + dL3_dv()*p3.x();
+  return val;
+}
+
+double lloydAlgorithm::Ty(double u,double v,SPoint2 p1,SPoint2 p2,SPoint2 p3){
+  double val;
+  val = L1(u,v)*p1.y() + L2(u,v)*p2.y() + L3(u,v)*p3.y();
+  return val;
+}
+
+double lloydAlgorithm::dTy_dp1y(double u,double v){
+  return L1(u,v);
+}
+
+double lloydAlgorithm::dTy_dp2y(double u,double v){
+  return L2(u,v);
+}
+
+double lloydAlgorithm::dTy_dp3y(double u,double v){
+  return L3(u,v);
+}
+
+double lloydAlgorithm::dTy_du(SPoint2 p1,SPoint2 p2,SPoint2 p3){
+  double val;
+  val = dL1_du()*p1.y() + dL2_du()*p2.y() + dL3_du()*p3.y();
+  return val;
+}
+
+double lloydAlgorithm::dTy_dv(SPoint2 p1,SPoint2 p2,SPoint2 p3){
+  double val;
+  val = dL1_dv()*p1.y() + dL2_dv()*p2.y() + dL3_dv()*p3.y();
+  return val;
+}
+
+double lloydAlgorithm::J(SPoint2 p1,SPoint2 p2,SPoint2 p3){
+  double val;
+  val = dTx_du(p1,p2,p3)*dTy_dv(p1,p2,p3) - dTx_dv(p1,p2,p3)*dTy_du(p1,p2,p3);
+  return val;
+}
+
+double lloydAlgorithm::dJ_dp1x(SPoint2 p1,SPoint2 p2,SPoint2 p3){
+  double val;
+  val = dL1_du()*dTy_dv(p1,p2,p3) - dL1_dv()*dTy_du(p1,p2,p3);
+  return val;
+}
+
+double lloydAlgorithm::dJ_dp2x(SPoint2 p1,SPoint2 p2,SPoint2 p3){
+  double val;
+  val = dL2_du()*dTy_dv(p1,p2,p3) - dL2_dv()*dTy_du(p1,p2,p3);
+  return val;
+}
+
+double lloydAlgorithm::dJ_dp3x(SPoint2 p1,SPoint2 p2,SPoint2 p3){
+  double val;
+  val = dL3_du()*dTy_dv(p1,p2,p3) - dL3_dv()*dTy_du(p1,p2,p3);
+  return val;
+}
+
+double lloydAlgorithm::dJ_dp1y(SPoint2 p1,SPoint2 p2,SPoint2 p3){
+  double val;
+  val = dTx_du(p1,p2,p3)*dL1_dv() - dTx_dv(p1,p2,p3)*dL1_du();
+  return val;
+}
+
+double lloydAlgorithm::dJ_dp2y(SPoint2 p1,SPoint2 p2,SPoint2 p3){
+  double val;
+  val = dTx_du(p1,p2,p3)*dL2_dv() - dTx_dv(p1,p2,p3)*dL2_du();
+  return val;
+}
+
+double lloydAlgorithm::dJ_dp3y(SPoint2 p1,SPoint2 p2,SPoint2 p3){
+  double val;
+  val = dTx_du(p1,p2,p3)*dL3_dv() - dTx_dv(p1,p2,p3)*dL3_du();
+  return val;
+}
+
+SVector3 lloydAlgorithm::inner_dFdx0(SVector3 dFdC,SPoint2 C,SPoint2 x0,SPoint2 x1,SPoint2 x2){
+  fullMatrix<double> A(2,2);
+  fullMatrix<double> B(2,2);
+  fullMatrix<double> M(2,2);
+  fullMatrix<double> _dFdC(1,2);
+  fullMatrix<double> _val(1,2);
+  A(0,0) = x1.x() - x0.x(); 
+  A(0,1) = x1.y() - x0.y();
+  A(1,0) = x2.x() - x0.x(); 
+  A(1,1) = x2.y() - x0.y();
+  A.invertInPlace();
+  B(0,0) = C.x() - x0.x();
+  B(0,1) = C.y() - x0.y();
+  B(1,0) = C.x() - x0.x();
+  B(1,1) = C.y() - x0.y();
+  A.mult_naive(B,M);
+  _dFdC(0,0) = dFdC.x();
+  _dFdC(0,1) = dFdC.y();
+  _dFdC.mult_naive(M,_val);
+  return SVector3(_val(0,0),_val(0,1),0.0);	
+}
+
+SVector3 lloydAlgorithm::boundary_dFdx0(SVector3 dFdC,SPoint2 C,SPoint2 x0,SPoint2 x1,SVector3 normal){
+  fullMatrix<double> A(2,2);
+  fullMatrix<double> B(2,2);
+  fullMatrix<double> M(2,2);
+  fullMatrix<double> _dFdC(1,2);
+  fullMatrix<double> _val(1,2);
+  A(0,0) = x1.x() - x0.x(); 
+  A(0,1) = x1.y() - x0.y();
+  A(1,0) = normal.x(); 
+  A(1,1) = normal.y();
+  A.invertInPlace();
+  B(0,0) = C.x() - x0.x();
+  B(0,1) = C.y() - x0.y();
+  B(1,0) = 0.0;
+  B(1,1) = 0.0;
+  A.mult_naive(B,M);
+  _dFdC(0,0) = dFdC.x();
+  _dFdC(0,1) = dFdC.y();
+  _dFdC.mult_naive(M,_val);
+  return SVector3(_val(0,0),_val(0,1),0.0);	
+}
+
+double lloydAlgorithm::exp(double a,int b)
+{
+  int i;
+  double val = 1.0;
+  for(i=0;i<b;i++){
+    val = val*a;	
+  }
+  return val;
+}
+
+
+
+/****************Calcul des intersections****************/
+/********************************************************/
+
+SVector3 lloydAlgorithm::normal(SPoint2 p1,SPoint2 p2){
+  double x;
+  double y;
+  SVector3 val;
+  x = p2.x() - p1.x();
+  y = p2.y() - p1.y();
+  val = SVector3(-y,x,0.0);
+  return val;
+}
+
+SPoint2 lloydAlgorithm::mid(SPoint2 p1,SPoint2 p2){
+  double x;
+  double y;
+  x = 0.5*(p1.x() + p2.x());
+  y = 0.5*(p1.y() + p2.y());
+  return SPoint2(x,y);
+}
+
+void lloydAlgorithm::print_segment(SPoint2 p1,SPoint2 p2,std::ofstream& file){
+  file << "SL (" << p1.x() << ", "
+	             << p1.y() << ", 0, "
+	             << p2.x() << ", "
+	             << p2.y() << ", 0){" << "10, 20};\n";	
+}
+
+bool lloydAlgorithm::adjacent(const DocRecord& triangulator,int index1,int index2){
+  int num = triangulator._adjacencies[index1].t_length;
+  for(int i=0;i<num;i++){
+    if(triangulator._adjacencies[index1].t[i] == index2){
+	  return 1;
+	}
+  }
+  return 0;
+}
+
+double lloydAlgorithm::triangle_area(SPoint2 p1,SPoint2 p2,SPoint2 p3){
   double area;
-  num = polygon.size();
-  if(num<3) return 0.0;
+  double x1,y1;
+  double x2,y2;
+  x1 = p2.x() - p1.x();
+  y1 = p2.y() - p1.y();
+  x2 = p3.x() - p1.x();
+  y2 = p3.y() - p1.y();
+  area = 0.5*fabs(x1*y2 - x2*y1);
+  return area;
+}
+
+SPoint2 lloydAlgorithm::boundary_intersection(SPoint2 p1,SPoint2 p2,bool& flag,SVector3& vec){
+  int i;
+  int num;
+  bool flag2;
+  SPoint2 p3;
+  SPoint2 p4;
+  SPoint2 val;
+  boundary_edge edge;	
+  num = get_number_boundary_edges();
+  for(i=0;i<num;i++){
+    edge = get_boundary_edge(i);
+	p3 = edge.get_p1();
+	p4 = edge.get_p2();
+	val = intersection(p1,p2,p3,p4,flag2);
+	if(flag2){
+	  flag = 1;
+	  vec = normal(p3,p4);
+	  return val;
+	}
+  }
+  flag = 0;
+  vec = SVector3(0.0,0.0,0.0);
+  return SPoint2(0.0,0.0);
+}
+
+bool lloydAlgorithm::inside_domain(double x,double y){
+  if(x<=1.0 && x>=0.0 && y<=1.0 && y>=0.0){
+    return 1;
+  }
   else{
-    area = 0.0;
-    for(i=0;i<num-1;i++){
-	  area = area + 0.5*(polygon[i].x()*polygon[i+1].y() - polygon[i+1].x()*polygon[i].y());
-    }
-    area = area + 0.5*(polygon[num-1].x()*polygon[0].y() - polygon[0].x()*polygon[num-1].y());
-    return fabs(area);
+    return 0;
   }
 }
 
-//This function determines if there is an intersection between the segment p1-p2 and the
-//infinite line passing through the generator, which is the point to which the Voronoi cell
-//belongs.
-//If there is an intersection, then the variable intersection will contain 1, otherwise it will
-//contain 0. In that case, the point that the function returns is not imporant.
-//If direction = 1, the variable generator will contain the x component, in that case,
-//the infinite line will be vertical.
-//If direction = 0, the variable generator will contain the y component, in that case,
-//the infinite line will be horizontal. 
-SPoint2 lloydAlgorithm::line_intersection(SPoint2 p1,SPoint2 p2,double generator,bool direction,bool& intersection){
-  double x1,x2,solution_x;
-  double y1,y2,solution_y;
-  double u,e;
+int lloydAlgorithm::get_number_boundary_edges(){
+  return 4;
+}
+
+boundary_edge lloydAlgorithm::get_boundary_edge(int i){
+  if(i==0) return boundary_edge(SPoint2(0.0,0.0),SPoint2(1.0,0.0));
+  else if(i==1) return boundary_edge(SPoint2(1.0,0.0),SPoint2(1.0,1.0));
+  else if(i==2) return boundary_edge(SPoint2(1.0,1.0),SPoint2(0.0,1.0));
+  else if(i==3) return boundary_edge(SPoint2(0.0,1.0),SPoint2(0.0,0.0));
+}
+
+SPoint2 lloydAlgorithm::intersection(SPoint2 p1,SPoint2 p2,SPoint2 p3,SPoint2 p4,bool& flag){
+  double x1,y1;
+  double x2,y2;
+  double x3,y3;
+  double x4,y4;
+  double ua,ub;
+  double num_ua;
+  double num_ub;
+  double denom;
+  double e;
   x1 = p1.x();
   y1 = p1.y();
   x2 = p2.x();
   y2 = p2.y();
-  e = 0.0000001;
-  intersection = 0;
-  if(direction){
-	if(fabs(x1 - generator)<e){
-	  intersection = 1;
-	  return SPoint2(x1,y1);
-	}
-	else if(fabs(x2 - generator)<e){
-	  intersection = 1;
-	  return SPoint2(x2,y2);
-	}
-	else if((x1<generator && x2>generator)||(x1>generator && x2<generator)){
-	  intersection = 1;
-	  u = (generator-x1)/(x2-x1);
-	  solution_x = generator;
-	  solution_y = y1 + u*(y2-y1);
-	  return SPoint2(solution_x,solution_y);
-	}
+  x3 = p3.x();
+  y3 = p3.y();
+  x4 = p4.x();
+  y4 = p4.y();
+  e = 0.000001;
+  denom = (y4-y3)*(x2-x1) - (x4-x3)*(y2-y1);
+  if(fabs(denom)<e){
+    flag = 0;
+	return SPoint2(0.0,0.0);
+  }
+  num_ua = (x4-x3)*(y1-y3) - (y4-y3)*(x1-x3);
+  num_ub = (x2-x1)*(y1-y3) - (y2-y1)*(x1-x3);
+  ua = num_ua/denom;
+  ub = num_ub/denom;
+  if(ua<=1.0 && ua>=0.0 && ub<=1.0 && ub>=0.0){
+    flag = 1;
+	return SPoint2(x1+ua*(x2-x1),y1+ua*(y2-y1));
   }
   else{
-	if(fabs(y1 - generator)<e){
-	  intersection = 1;
-	  return SPoint2(x1,y1);
-	}
-	else if(fabs(y2 - generator)<e){
-	  intersection = 1;
-	  return SPoint2(x2,y2);
-	}
-	else if((y1<generator && y2>generator)||(y1>generator && y2<generator)){
-	  intersection = 1;
-	  u = (generator-y1)/(y2-y1);
-	  solution_x = x1 + u*(x2-x1);
-	  solution_y = generator;
-	  return SPoint2(solution_x,solution_y);
-	}
+    flag = 0;
+	return SPoint2(0.0,0.0);
   }
-  return SPoint2(0.0,0.0);
 }
 
-//This is the function called by the script.
-double lloydAlgorithm::optimize(int max,int flag){
-  GFace*face;
-  GModel*model = GModel::current();
-  GModel::fiter iterator;
-  lloydAlgorithm lloyd(max,flag);
-  for(iterator = model->firstFace();iterator != model->lastFace();iterator++)
-  {
-    face = *iterator;
-	lloyd(face);
-	recombineIntoQuads(face,1,1);
-  }
-  return lloyd.test;
+/****************Class boundary_edge****************/
+boundary_edge::boundary_edge(SPoint2 new_p1,SPoint2 new_p2){
+  p1 = new_p1;
+  p2 = new_p2;
+}
+
+boundary_edge::boundary_edge(){}
+
+boundary_edge::~boundary_edge(){}
+
+SPoint2 boundary_edge::get_p1(){
+  return p1;
 }
 
-#include "Bindings.h"
-void lloydAlgorithm::registerBindings(binding *b){
-  classBinding*cb = b->addClass<lloydAlgorithm>("lloydAlgorithm");
-  cb->setDescription("This class is used to move the points according to lloyd algorithm.");
-  methodBinding*cm;
-  cm = cb->setConstructor<lloydAlgorithm>();
-  cm->setDescription("This is the constructor.");
-  cm = cb->addMethod("optimize",&lloydAlgorithm::optimize);
-  cm->setDescription("This function moves the points.");
-  cm->setArgNames("max","flag",NULL);
+SPoint2 boundary_edge::get_p2(){
+  return p2;
 }
+
+
diff --git a/Mesh/meshGFaceLloyd.h b/Mesh/meshGFaceLloyd.h
index b86fd54b2a..1f2462771f 100644
--- a/Mesh/meshGFaceLloyd.h
+++ b/Mesh/meshGFaceLloyd.h
@@ -7,9 +7,17 @@
 #define _MESH_GFACE_LLOYD_H_
 #include "fullMatrix.h"
 #include "DivideAndConquer.h"
-#include "Bindings.h"
+#include "ap.h"
+#include "alglibinternal.h"
+#include "alglibmisc.h"
+#include "linalg.h"
+#include "optimization.h"
 
 class GFace;
+class boundary_edge;
+
+void function1_grad(const alglib::real_1d_array&,double&,alglib::real_1d_array&,void*);
+void topology(const alglib::real_1d_array &,double,void*);
 
 class lloydAlgorithm {
   int ITER_MAX;
@@ -20,19 +28,77 @@ class lloydAlgorithm {
   : ITER_MAX(itermax), infiniteNorm(infnorm) {}
   lloydAlgorithm() {}
   void operator () (GFace *);
-  double get_angle(double,double);
-  void get_rotation(double,double,double&,double&,double&,double&);
-  void get_unrotation(double,double,double&,double&,double&,double&);
-  void rotate(SPoint2,SPoint2&);
-  void unrotate(SPoint2,SPoint2&);
-  SPoint2 fixed_point(const std::vector<SPoint2>&);
-  double range(const std::vector<SPoint2>&,double,double,bool);
-  double gradient(const std::vector<SPoint2>&,double,bool);
-  bool point_side(SPoint2,double,bool);
-  double polygon_area(const std::vector<SPoint2>&);
-  SPoint2 line_intersection(SPoint2,SPoint2,double,bool,bool&);
   double optimize(int,int);
-  static void registerBindings(binding *b);
+  
+  void eval(DocRecord&,GFace*,std::vector<SVector3>&,std::vector<double>&,std::vector<SVector3>&,std::vector<double>&,int);
+  double total_energy(std::vector<double>);	
+  SVector3 numerical(DocRecord&,GFace*,int,int);
+  void write(DocRecord&,GFace*,int);
+  void write2(DocRecord&,GFace*);
+  SVector3 analytical(SPoint2,SVector3,double);
+  SVector3 area_centroid(SPoint2,SPoint2,SPoint2);
+	
+  double F(SPoint2,SPoint2,SPoint2,int);
+  SVector3 simple(SPoint2,SPoint2,SPoint2,int);
+  SVector3 dF_dC1(SPoint2,SPoint2,SPoint2,int);
+  SVector3 dF_dC2(SPoint2,SPoint2,SPoint2,int);
+  double f(SPoint2,SPoint2,int);
+  double df_dx(SPoint2,SPoint2,int);
+  double df_dy(SPoint2,SPoint2,int);
+  double L1(double,double);
+  double dL1_du();
+  double dL1_dv();
+  double L2(double,double);
+  double dL2_du();
+  double dL2_dv();
+  double L3(double,double);
+  double dL3_du();
+  double dL3_dv();
+  double Tx(double,double,SPoint2,SPoint2,SPoint2);
+  double dTx_dp1x(double,double);
+  double dTx_dp2x(double,double);
+  double dTx_dp3x(double,double);
+  double dTx_du(SPoint2,SPoint2,SPoint2);
+  double dTx_dv(SPoint2,SPoint2,SPoint2);
+  double Ty(double,double,SPoint2,SPoint2,SPoint2);
+  double dTy_dp1y(double,double);
+  double dTy_dp2y(double,double);
+  double dTy_dp3y(double,double);
+  double dTy_du(SPoint2,SPoint2,SPoint2);
+  double dTy_dv(SPoint2,SPoint2,SPoint2);
+  double J(SPoint2,SPoint2,SPoint2);
+  double dJ_dp1x(SPoint2,SPoint2,SPoint2);
+  double dJ_dp2x(SPoint2,SPoint2,SPoint2);
+  double dJ_dp3x(SPoint2,SPoint2,SPoint2);
+  double dJ_dp1y(SPoint2,SPoint2,SPoint2);
+  double dJ_dp2y(SPoint2,SPoint2,SPoint2);
+  double dJ_dp3y(SPoint2,SPoint2,SPoint2);
+  SVector3 inner_dFdx0(SVector3,SPoint2,SPoint2,SPoint2,SPoint2);
+  SVector3 boundary_dFdx0(SVector3,SPoint2,SPoint2,SPoint2,SVector3);
+  double exp(double,int);
+  
+  SVector3 normal(SPoint2,SPoint2);
+  SPoint2 mid(SPoint2,SPoint2);
+  void print_segment(SPoint2,SPoint2,std::ofstream&);
+  bool adjacent(const DocRecord&,int,int);
+  double triangle_area(SPoint2,SPoint2,SPoint2);
+  SPoint2 boundary_intersection(SPoint2,SPoint2,bool&,SVector3&);
+  bool inside_domain(double,double);
+  int get_number_boundary_edges();
+  boundary_edge get_boundary_edge(int);
+  SPoint2 intersection(SPoint2,SPoint2,SPoint2,SPoint2,bool&);
+};
+
+class boundary_edge{
+ private :
+  SPoint2 p1;
+  SPoint2 p2;
+ public :
+  boundary_edge(SPoint2,SPoint2);
+  boundary_edge();
+  ~boundary_edge();
+  SPoint2 get_p1();
+  SPoint2 get_p2();
 };
 
 #endif
diff --git a/Mesh/meshGFaceOptimize.cpp b/Mesh/meshGFaceOptimize.cpp
index 20794238d7..07956971eb 100644
--- a/Mesh/meshGFaceOptimize.cpp
+++ b/Mesh/meshGFaceOptimize.cpp
@@ -19,6 +19,10 @@
 #include "Generator.h"
 #include "Context.h"
 #include "OS.h"
+#include "PView.h"
+#include "PViewData.h"
+#include "SVector3.h"
+#include "SPoint3.h"
 
 #ifdef HAVE_MATCH
 extern "C" int FAILED_NODE;
@@ -1512,6 +1516,9 @@ struct RecombineTriangle
 {
   MElement *t1, *t2;
   double angle;
+  double cost_quality; //addition for class Temporary
+  double cost_alignment; //addition for class Temporary
+  double total_cost; //addition for class Temporary
   MVertex *n1, *n2, *n3, *n4;
   RecombineTriangle(const MEdge &me, MElement *_t1, MElement *_t2)
     : t1(_t1), t2(_t2)
@@ -1533,11 +1540,16 @@ struct RecombineTriangle
     angle = fabs(90. - a1);
     angle = std::max(fabs(90. - a2),angle);
     angle = std::max(fabs(90. - a3),angle);
-    angle = std::max(fabs(90. - a4),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
+	total_cost = 100.0*cost_quality; //addition for class Temporary
   }
   bool operator < (const RecombineTriangle &other) const
   {
-    return angle < other.angle;
+    //return angle < other.angle;
+	return total_cost < other.total_cost; //addition for class Temporary
   }
 };
 
@@ -1640,7 +1652,8 @@ static int _recombineIntoQuads(GFace *gf, int recur_level, bool cubicGraph = 1)
       for (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].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());
 
@@ -2055,3 +2068,166 @@ void recombineIntoQuadsIterative(GFace *gf)
     if (COUNT == 5)break;
   }
 }
+
+
+
+#include "Bindings.h"
+
+double Temporary::w1,Temporary::w2,Temporary::w3;
+std::vector<SVector3> Temporary::gradients;
+
+Temporary::Temporary(){}
+
+Temporary::~Temporary(){}
+
+SVector3 Temporary::compute_gradient(MElement*element){
+  double x1,y1,z1;
+  double x2,y2,z2;
+  double x3,y3,z3;
+  double x,y,z;
+  MVertex*vertex1 = element->getVertex(0);
+  MVertex*vertex2 = element->getVertex(1);
+  MVertex*vertex3 = element->getVertex(2);
+  x1 = vertex1->x();
+  y1 = vertex1->y();
+  z1 = vertex1->z();
+  x2 = vertex2->x();
+  y2 = vertex2->y();
+  z2 = vertex2->z();
+  x3 = vertex3->x();
+  y3 = vertex3->y();
+  z3 = vertex3->z();
+  x = (x1+x2+x3)/3.0;
+  y = (y1+y2+y3)/3.0;
+  z = (z1+z2+z3)/3.0;
+  return SVector3(0.0,1.0,0.0);
+}
+
+void Temporary::select_weights(double new_w1,double new_w2,double new_w3){
+  w1 = new_w1;
+  w2 = new_w2;
+  w3 = new_w3;
+}
+
+double Temporary::compute_total_cost(double f1,double f2){
+  double cost;
+  cost = w1*f1 + w2*f2 + w3*f1*f2;
+  return cost;
+}
+
+SVector3 Temporary::compute_normal(MElement*element){
+  double x1,y1,z1;
+  double x2,y2,z2;
+  double x3,y3,z3;
+  double length;
+  SVector3 vectorA;
+  SVector3 vectorB;
+  SVector3 normal;
+  MVertex*vertex1 = element->getVertex(0);
+  MVertex*vertex2 = element->getVertex(1);
+  MVertex*vertex3 = element->getVertex(2);
+  x1 = vertex1->x();
+  y1 = vertex1->y();
+  z1 = vertex1->z();
+  x2 = vertex2->x();
+  y2 = vertex2->y();
+  z2 = vertex2->z();
+  x3 = vertex3->x();
+  y3 = vertex3->y();
+  z3 = vertex3->z();
+  vectorA = SVector3(x2-x1,y2-y1,z2-z1);
+  vectorB = SVector3(x3-x1,y3-y1,z3-z1);
+  normal = crossprod(vectorA,vectorB);
+  length = norm(normal);
+  return SVector3(normal.x()/length,normal.y()/length,normal.z()/length);
+}
+
+SVector3 Temporary::compute_other_vector(MElement*element){
+  int number;
+  double length;
+  SVector3 normal;
+  SVector3 gradient;
+  SVector3 other_vector;
+  number = element->getNum();
+  normal = Temporary::compute_normal(element);
+  gradient = Temporary::compute_gradient(element);//gradients[number];
+  other_vector = crossprod(gradient,normal);
+  length = norm(other_vector);
+  return SVector3(other_vector.x()/length,other_vector.y()/length,other_vector.z()/length);
+}
+
+double Temporary::compute_alignment(const MEdge&_edge, MElement*element1, MElement*element2){
+  int number;
+  double scalar_productA,scalar_productB;
+  double alignment;
+  SVector3 gradient;
+  SVector3 other_vector;
+  SVector3 edge;
+  MVertex*vertexA;
+  MVertex*vertexB;
+  number = element1->getNum();
+  gradient = Temporary::compute_gradient(element1);//gradients[number];
+  other_vector = Temporary::compute_other_vector(element1);
+  vertexA = _edge.getVertex(0);
+  vertexB = _edge.getVertex(1);
+  edge = SVector3(vertexB->x()-vertexA->x(),vertexB->y()-vertexA->y(),vertexB->z()-vertexA->z());
+  scalar_productA = fabs(dot(gradient,edge));
+  scalar_productB = fabs(dot(other_vector,edge));
+  alignment = std::max(scalar_productA,scalar_productB) - sqrt(2.0)/2.0;
+  alignment = alignment/(1.0-sqrt(2.0)/2.0);	
+  return alignment;
+}
+
+void Temporary::read_data(std::string file_name){
+  int i,j,number;
+  double x,y,z;
+  MElement*element;
+  PView*view;
+  PViewData*data;	
+  PView::readMSH(file_name,-1);
+  std::vector<PView*> list = PView::list;
+  data = list[0]->getData();
+  for(i = 0;i < data->getNumEntities(0);i++)
+  {
+    if(data->skipEntity(0,i)) continue;
+    for(j = 0;j < data->getNumElements(0,i);j++)
+	{
+	  if(data->skipElement(0,i,j)) continue;
+	  element = data->getElement(0,i,j);
+	  number = element->getNum();
+	  data->getValue(0,i,j,0,x);
+	  data->getValue(0,i,j,1,y);
+	  data->getValue(0,i,j,2,z);
+	  gradients[number] = SVector3(x,y,z);
+	}
+  }
+}
+
+void Temporary::quadrilaterize(std::string file_name,double _w1,double _w2,double _w3){
+  GFace*face;
+  GModel*model = GModel::current();
+  GModel::fiter iterator;
+  gradients.resize(model->getNumMeshElements() + 1);
+  w1 = _w1;
+  w2 = _w2;
+  w3 = _w3;
+  Temporary::read_data(file_name);
+  for(iterator = model->firstFace();iterator != model->lastFace();iterator++)
+  {
+    face = *iterator;
+	_recombineIntoQuads(face,1,1);
+  }
+}
+
+void Temporary::registerBindings(binding *b){
+  classBinding*cb = b->addClass<Temporary>("Temporary");
+  cb->setDescription("This class is used to create quad meshes from a script.");
+  methodBinding*cm;
+  cm = cb->setConstructor<Temporary>();
+  cm->setDescription("This is the constructor.");
+  cm = cb->addMethod("quadrilaterize",&Temporary::quadrilaterize);
+  cm->setDescription("This function creates the quad mesh.");
+  cm->setArgNames("file_name","w1","w2","w3",NULL);
+}
+	
+
diff --git a/Mesh/meshGFaceOptimize.h b/Mesh/meshGFaceOptimize.h
index a94db547f4..d4f01d47be 100644
--- a/Mesh/meshGFaceOptimize.h
+++ b/Mesh/meshGFaceOptimize.h
@@ -126,4 +126,22 @@ struct swapquad{
   }
 };
 
+class Temporary{
+  private :
+	static double w1,w2,w3;
+	static std::vector<SVector3> gradients;
+	void read_data(std::string);
+	static SVector3 compute_normal(MElement*);
+	static SVector3 compute_other_vector(MElement*);
+	static SVector3 compute_gradient(MElement*);
+  public :
+	Temporary();
+	~Temporary();
+	void quadrilaterize(std::string,double,double,double);
+	static double compute_total_cost(double,double);
+	static void select_weights(double,double,double);
+	static double compute_alignment(const MEdge&,MElement*,MElement*);
+	static void registerBindings(binding *b);
+};
+
 #endif
diff --git a/Numeric/DivideAndConquer.cpp b/Numeric/DivideAndConquer.cpp
index 978e4937e2..f0c29562c8 100644
--- a/Numeric/DivideAndConquer.cpp
+++ b/Numeric/DivideAndConquer.cpp
@@ -28,6 +28,30 @@
 #define Pred(x) ((x)->prev)
 #define Succ(x) ((x)->next)
 
+int DocRecord::get_p(){
+  return p;
+}
+
+void DocRecord::set_p(int new_p){
+  p = new_p;
+}
+
+int DocRecord::get_dimension(){
+  return dimension;
+}
+
+void DocRecord::set_dimension(int new_dimension){
+  dimension = new_dimension;
+}
+
+GFace* DocRecord::get_face(){
+  return gf;
+}
+
+void DocRecord::set_face(GFace* new_gf){
+  gf = new_gf;
+}
+
 PointNumero DocRecord::Predecessor(PointNumero a, PointNumero b)
 {
   DListPeek p = points[a].adjacent;
@@ -824,7 +848,7 @@ DocRecord::DocRecord(int n)
     numPoints(n), points(NULL), numTriangles(0), triangles(NULL)
 {
   if(numPoints)
-    points = new PointRecord[numPoints+1000];
+    points = new PointRecord[numPoints+3000];
 }
 
 DocRecord::~DocRecord()
@@ -898,6 +922,7 @@ void DocRecord::remove_all(){
 	  points2[index].where.v = points[i].where.v;
 	  points2[index].data = points[i].data;
 	  points2[index].flag = points[i].flag;
+	  points2[index].identificator = points[i].identificator;
 	  index++;
 	}
   }
@@ -906,6 +931,15 @@ void DocRecord::remove_all(){
   numPoints = numPoints2;
 }
 
+void DocRecord::add_point(double x,double y,GFace*face){
+  PointRecord point;
+  point.where.h = x;
+  point.where.v = y; 
+  point.data = new MVertex(x,y,0.0,(GEntity*)face,2);
+  points[numPoints] = point;
+  numPoints = numPoints+1;
+}
+
 #include "Bindings.h"
 
 void DocRecord::registerBindings(binding *b)
diff --git a/Numeric/DivideAndConquer.h b/Numeric/DivideAndConquer.h
index da5f4d7322..aa5f646cfd 100644
--- a/Numeric/DivideAndConquer.h
+++ b/Numeric/DivideAndConquer.h
@@ -30,6 +30,7 @@ struct PointRecord {
   DListPeek adjacent;
   void *data;
   int flag; //0:to be kept, 1:to be removed
+  int identificator;
   PointRecord() : adjacent(0), data (0) {}
 };
 
@@ -59,6 +60,9 @@ typedef struct{
 
 class DocRecord{
  private:
+  int p;
+  int dimension;
+  GFace* gf;
   int _hullSize;
   PointNumero *_hull;
   PointNumero Predecessor(PointNumero a, PointNumero b);
@@ -76,15 +80,22 @@ class DocRecord{
   int Insert(PointNumero a, PointNumero b);
   int DListDelete(DListPeek *dlist, PointNumero oldPoint);
   int Delete(PointNumero a, PointNumero b);
-  int ConvertDListToTriangles();
   void ConvertDListToVoronoiData();
+  int ConvertDListToTriangles();
   void RemoveAllDList();
   int BuildDelaunay();
   int CountPointsOnHull();
   void ConvexHull();
  public:
+  int get_p();
+  void set_p(int);
+  int get_dimension();
+  void set_dimension(int);
+  GFace* get_face();
+  void set_face(GFace*);
   STriangle *_adjacencies;
   int numPoints;        // number of points
+  int size_points;
   PointRecord *points;  // points to triangulate
   int numTriangles;     // number of triangles
   Triangle *triangles;  // 2D results
@@ -105,6 +116,7 @@ class DocRecord{
   void initialize();
   bool remove_point(int);
   void remove_all();
+  void add_point(double,double,GFace*);
   PointNumero *ConvertDlistToArray(DListPeek *dlist, int *n);
   static void registerBindings(binding *b);
 };
-- 
GitLab