diff --git a/Geo/closestPoint.cpp b/Geo/closestPoint.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..67d43a41020abc5f179de93cec51073d55de3588
--- /dev/null
+++ b/Geo/closestPoint.cpp
@@ -0,0 +1,69 @@
+#include "closestPoint.h"
+#include "GEntity.h"
+#include "GEdge.h"
+#include "GFace.h"
+#include <vector>
+
+static void oversample (std::vector<SPoint3> &s, double tol){
+  std::vector<SPoint3> t;
+  for (unsigned int i=1;i<s.size();i++){
+    SPoint3 p0 = s[i-1];
+    SPoint3 p1 = s[i];
+    double d = p0.distance(p1);
+    int N = (int) (d / tol);
+    t.push_back(p0);
+    for (int j=1;j<N;j++){
+      const double xi = (double) j/ N;
+      t.push_back(p0 + (p1-p0)*xi);
+    }
+    t.push_back(p1);
+  }
+  s = t;
+}
+
+closestPointFinder :: closestPointFinder (GEntity *ge, double e) : _ge (ge) , _tolerance (e) 
+{
+#if defined(HAVE_ANN)
+  std::vector<SPoint3> pts;
+  if (ge->dim() == 1){
+    GEdge *edge = ge->cast2Edge();
+    if (!edge)Msg::Fatal("in the constructor of closestPoint");
+    std::vector<double> ts;
+    edge->discretize(_tolerance, pts,ts);
+    //    printf("%d points\n",pts.size());
+    oversample (pts, _tolerance);
+    //    printf("%d points after oversampling\n",pts.size());
+  }
+  index = new ANNidx[1];
+  dist = new ANNdist[1];
+  zeronodes = annAllocPts(pts.size(), 3);
+  for (unsigned int k=0;k<pts.size();k++){
+    zeronodes[k][0] = pts[k].x();
+    zeronodes[k][1] = pts[k].y();
+    zeronodes[k][2] = pts[k].z();
+  }
+  kdtree = new ANNkd_tree(zeronodes, pts.size(), 3);
+#else
+  Msg::Fatal("Gmsh should be compiled using ANN");
+#endif
+}
+
+closestPointFinder :: ~closestPointFinder ()
+{
+#if defined(HAVE_ANN)
+  if(kdtree) delete kdtree;
+  if(zeronodes) annDeallocPts(zeronodes);
+  delete[]index;
+  delete[]dist;  
+#endif
+}
+
+SPoint3 closestPointFinder ::operator() (const SPoint3 &p)
+{
+  double xyz[3] = {p.x(),p.y(),p.z()};
+  kdtree->annkSearch(xyz, 1, index, dist);
+  return SPoint3(zeronodes[index[0]][0],
+		 zeronodes[index[0]][1],
+		 zeronodes[index[0]][2]);  
+}
+
diff --git a/Geo/closestPoint.h b/Geo/closestPoint.h
new file mode 100644
index 0000000000000000000000000000000000000000..24ecc73fa4805abf2a2a437048883f6f86f76ee8
--- /dev/null
+++ b/Geo/closestPoint.h
@@ -0,0 +1,26 @@
+#ifndef _CLOSEST_POINT_H_
+#define _CLOSEST_POINT_H_
+#include "GmshConfig.h"
+#if defined(HAVE_ANN)
+#include "ANN/ANN.h"
+#endif
+#include "SPoint3.h"
+class GEntity;
+class closestPointFinder
+{
+#if defined(HAVE_ANN)
+  ANNkd_tree *kdtree;
+  ANNpointArray zeronodes;
+  ANNidxArray index;
+  ANNdistArray dist;
+#endif
+  GEntity* _ge;
+  double _tolerance;
+ public :
+  closestPointFinder (GEntity*, double);
+  ~closestPointFinder ();
+  SPoint3 operator () (const SPoint3 & p);
+  inline double tol() const {return _tolerance;}
+};
+
+#endif
diff --git a/Numeric/hausdorffDistance.cpp b/Numeric/hausdorffDistance.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0c7ba1af3072bf40590bd42fe8d44095edd4c1aa
--- /dev/null
+++ b/Numeric/hausdorffDistance.cpp
@@ -0,0 +1,115 @@
+/*
+compute the hausdorff distance between two polygonal curves 
+in n*m time where n and m are the nb of points of the 
+polygonal curves
+*/
+#include "SVector3.h"
+#include "hausdorffDistance.h"
+
+static double intersect (SPoint3 &q, SVector3 &n, // a plane
+			 SPoint3 &p1, SPoint3 &p2, // a segment
+			 SPoint3 &result)
+{
+  // n * (x-q) = 0
+  // x = p1 + t (p2-p1)
+  // n *(p1 + t (p2-p1) - q) = 0
+  // t = n*(q-p1) / n*(p2-p1)
+
+  const double t = dot(n,q-p1)/dot(n,p2-p1);
+  result = p1 *(1.-t)+ p2*t;
+  return t;
+}
+
+static double projection (SPoint3 &p1, SPoint3 &p2, SPoint3 &q, SPoint3 &result){
+  // x = p1 + t (p2 - p1)
+  // (x - q) * (p2 - p1) = 0
+  // (p1 + t (p2 - p1) - q) (p2 - p1) = 0
+  // t = (q-p1) * (p2-p1) / (p2-p1)^2
+  SVector3 p21 = p2-p1;
+  const double t = dot(q-p1,p21)/dot(p21,p21);
+  result = p1 *(1.-t)+ p2*t;
+  return t;
+}  
+
+static SPoint3 closestPoint (SPoint3 &p1, SPoint3 &p2, SPoint3 &q){
+  double result;
+  const double t = projection (p1,p2,q,result);
+  if (t >= 0.0 && t <= 1.0)return result;
+  if (t < 0)return p1;
+  return p2;
+}  
+
+
+double closestPoint (const std::vector<SPoint3> &P, const SPoint3 &p, SPoint3 & result){
+  double closestDistance = 1.e22;
+  for (unsigned int i=1;i<P.size();i++){
+    SPoint3 q = closestPoint (P[i-1],P[i],p);
+    const double pq = p.distance(q);
+    if (pq < closestDistance){
+      closestDistance = pq;
+      result = q;
+    }   
+  }
+  return closestDistance;
+} 
+
+// we test all points of P plus all points that are the intersections
+// of angle bissectors of Q with P
+double oneSidedHausdorffDistance (const std::vector<SPoint3> &P, 
+				  const std::vector<SPoint3> &Q, 
+				  SPoint3 &p1, SPoint3 &p2){
+  const double hausdorffDistance = 0.0;
+  
+  // first test the points
+  for (unsigned int i=0;i<P.size();i++){
+    SPoint3 result;
+    double d = closestPoint (Q, P[i], result);
+    if (d > hausdorffDistance){
+      hausdorffDistance = d;
+      p1 = P[i];
+      p2 = result;
+    }
+  }
+  // compute angle bissectors intersections
+  std::vector<SPoint3> intersections;
+  for (unsigned int i=1;i<Q.size()-1;i++){
+    SPoint3 a = Q[i-1];
+    SPoint3 b = Q[i];
+    SPoint3 c = Q[i+1];
+    SVector3 ba = b-a;
+    SVector3 ca = c-a;
+    SVector3 bissector = (ba+ca);
+    SVector3 n; // normal to the bissector plane
+    if (bissector.norm == 0){
+      ba.normalize();
+      n = ba;
+    }
+    else{
+      SVector3 b = crossprod (bissector,ba);
+      n = crossprod (b,bissector);
+      n.normalize();
+    }
+    for (unsigned int i=1;i<P.size();i++){
+      SPoint3 result;
+      const double t = intersect (b, n, P[i-1],P[i],result);
+      if (t >=0 && t <=1)intersections.push_back(result);	
+    }
+  }
+
+  for (unsigned int i=0;i<intersections.size();i++){
+    SPoint3 result;
+    double d = closestPoint (Q, intersections[i], result);
+    if (d > hausdorffDistance){
+      hausdorffDistance = d;
+      p1 = P[i];
+      p2 = result;
+    }
+  }
+  return hausdorffDistance;
+}
+
+double hausdorffDistance (const std::vector<SPoint3> &P, 
+			  const std::vector<SPoint3> &Q){
+  return std::max(oneSidedHausdorffDistance (P,Q),
+		  oneSidedHausdorffDistance (Q,P));  
+}
diff --git a/Numeric/hausdorffDistance.h b/Numeric/hausdorffDistance.h
new file mode 100644
index 0000000000000000000000000000000000000000..09f4ef39a213d979bf0dd86aa51a5acbc0bd0b88
--- /dev/null
+++ b/Numeric/hausdorffDistance.h
@@ -0,0 +1,7 @@
+#ifndef _HAUSDORFF_DISTANCE_H_
+#define _HAUSDORFF_DISTANCE_H_
+#include <vector>
+#include "SPoint3.h"
+double hausdorffDistance (const std::vector<SPoint3> &P, 
+			  const std::vector<SPoint3> &Q);
+#endif