diff --git a/Mesh/meshGFaceDelaunayInsertion.cpp b/Mesh/meshGFaceDelaunayInsertion.cpp
index 2a4298869dfb550b0a7430a04541b4d27006854d..102b11fe5d4a87ff43bb3c8d41bcbf1582f81af9 100644
--- a/Mesh/meshGFaceDelaunayInsertion.cpp
+++ b/Mesh/meshGFaceDelaunayInsertion.cpp
@@ -646,7 +646,8 @@ void gmshBowyerWatson(GFace *gf)
                        Vs[base->getVertex(2)->getNum()]) / 3.};
       buildMetric(gf, pa, metric);
       circumCenterMetric(worst->tri(), metric, Us, Vs, center, r2);       
-      insertAPoint(gf,AllTris.begin(),center,metric,Us,Vs,vSizes,vSizesBGM,AllTris);
+      insertAPoint(gf, AllTris.begin(), center, metric, Us, Vs, vSizes, vSizesBGM, 
+                   AllTris);
     }
     //     if(ITER % 10== 0){
     //       char name[245];
@@ -654,7 +655,7 @@ void gmshBowyerWatson(GFace *gf)
     //       _printTris (name, AllTris, Us,Vs,false);
     //     }
   }    
-  transferDataStructure(gf, AllTris); 
+  transferDataStructure(gf, AllTris, Us, Vs); 
 }
 
 /*
@@ -791,6 +792,6 @@ void gmshBowyerWatsonFrontal(GFace *gf)
 
   // char name[245];
   // sprintf(name,"frontal%d.pos", gf->tag());
-  // _printTris (name, AllTris, Us,Vs);
-  transferDataStructure(gf, AllTris); 
+  // _printTris (name, AllTris, Us, Vs);
+  transferDataStructure(gf, AllTris, Us, Vs); 
 } 
diff --git a/Mesh/meshGFaceOptimize.cpp b/Mesh/meshGFaceOptimize.cpp
index 9317b2dac3035b85175645778f7c2a05c27bb43c..7bd6005778bebc20019ca5caf0a55774a8884e55 100644
--- a/Mesh/meshGFaceOptimize.cpp
+++ b/Mesh/meshGFaceOptimize.cpp
@@ -93,10 +93,11 @@ void buildMeshGenerationDataStructures(GFace *gf,
   connectTriangles(AllTris);
 }
 
-void transferDataStructure(GFace *gf, std::set<MTri3*, compareTri3Ptr> &AllTris)
+void transferDataStructure(GFace *gf, std::set<MTri3*, compareTri3Ptr> &AllTris,
+                           std::vector<double> &Us, std::vector<double> &Vs)
 {
   while (1) {
-    if (AllTris.begin() == AllTris.end() ) break;
+    if (AllTris.begin() == AllTris.end()) break;
     MTri3 *worst = *AllTris.begin();
     if (worst->isDeleted())
       delete worst->tri();
@@ -106,26 +107,23 @@ void transferDataStructure(GFace *gf, std::set<MTri3*, compareTri3Ptr> &AllTris)
     AllTris.erase(AllTris.begin());      
   }
 
-  // make sure all the triangles are oriented in the same way (in
-  // parameter space). FIXME: this is really ugly and slow. JF: we
-  // need to change the actual algorithm to ensure that we create
-  // correctly oriented triangles in the first place
+  // make sure all the triangles are oriented in the same way in
+  // parameter space (it would be nicer to change the actual algorithm
+  // to ensure that we create correctly-oriented triangles in the
+  // first place)
   if(gf->triangles.size() > 1){
-    double u[3], v[3], n1[3], n2[3];
+    double n1[3], n2[3];
     MTriangle *t = gf->triangles[0];
-    SPoint2 uv[3];
-    for(int i = 0; i < 3; i++)
-      reparamMeshVertexOnFace(t->getVertex(i), gf, uv[i]);
-    normal3points(uv[0].x(), uv[0].y(), 0., 
-                  uv[1].x(), uv[1].y(), 0., 
-                  uv[2].x(), uv[2].y(), 0., n1);
+    MVertex *v0 = t->getVertex(0), *v1 = t->getVertex(1), *v2 = t->getVertex(2);
+    normal3points(Us[v0->getNum()], Vs[v0->getNum()], 0.,
+                  Us[v1->getNum()], Vs[v1->getNum()], 0.,
+                  Us[v2->getNum()], Vs[v2->getNum()], 0., n1);
     for(unsigned int j = 1; j < gf->triangles.size(); j++){
       t = gf->triangles[j];
-      for(int i = 0; i < 3; i++)
-        reparamMeshVertexOnFace(t->getVertex(i), gf, uv[i]);
-      normal3points(uv[0].x(), uv[0].y(), 0., 
-                    uv[1].x(), uv[1].y(), 0., 
-                    uv[2].x(), uv[2].y(), 0., n2);
+      v0 = t->getVertex(0); v1 = t->getVertex(1); v2 = t->getVertex(2);
+      normal3points(Us[v0->getNum()], Vs[v0->getNum()], 0.,
+                    Us[v1->getNum()], Vs[v1->getNum()], 0.,
+                    Us[v2->getNum()], Vs[v2->getNum()], 0., n2);
       double pp; prosca(n1, n2, &pp);
       if(pp < 0) t->revert();
     }
diff --git a/Mesh/meshGFaceOptimize.h b/Mesh/meshGFaceOptimize.h
index fb96c8ea83b86cd654ca35033fbdf6fd0c99af3b..729740391d7a3c260ff27da7cb8dd0f882ab39c9 100644
--- a/Mesh/meshGFaceOptimize.h
+++ b/Mesh/meshGFaceOptimize.h
@@ -52,7 +52,8 @@ void buildMeshGenerationDataStructures(GFace *gf,
                                        std::vector<double> &vSizesBGM,
                                        std::vector<double> &Us,
                                        std::vector<double> &Vs);
-void transferDataStructure (GFace *gf, std::set<MTri3*, compareTri3Ptr> &AllTris);
+void transferDataStructure(GFace *gf, std::set<MTri3*, compareTri3Ptr> &AllTris,
+                           std::vector<double> &Us, std::vector<double> &Vs);
 void gmshRecombineIntoQuads(GFace *gf);
 
 struct swapquad{
diff --git a/doc/VERSIONS.txt b/doc/VERSIONS.txt
index 79b58b29adc9f9bcaffa125259cb98ff725f54d3..ea83933b2742a501e992c967cffaaebc95e0a643 100644
--- a/doc/VERSIONS.txt
+++ b/doc/VERSIONS.txt
@@ -1,9 +1,10 @@
-$Id: VERSIONS.txt,v 1.39 2009-03-15 10:36:40 geuzaine Exp $
+$Id: VERSIONS.txt,v 1.40 2009-03-16 07:23:48 geuzaine Exp $
 
 (?): removed GSL dependency (Gmsh now simply requires Blas and
 Lapack); new per-window visibility; added support for composite window
 printing and background images; fixes for string options in parser;
-fixed surface mesh orientation for Open Cascade models.
+fixed surface mesh orientation for Open Cascade models; fixed triangle
+orientations in Delaunay and Frontal algorithms.
 
 2.3.0 (Jan 23, 2009): major graphics and GUI code refactoring; new
 full-quad/hexa subdivision algorithm (removed Mesh.RecombineAlgo);