diff --git a/Common/Context.h b/Common/Context.h
index a743612d258e2366347bfb91bcb28ba40c731b47..311baab94c0294dbad11bb8edc9f2350a1935d6d 100644
--- a/Common/Context.h
+++ b/Common/Context.h
@@ -157,7 +157,7 @@ class CTX {
     int autoCoherence, highlightOrphans, clip, useTransform;
     double tolerance, snap[3], transform[3][3], offset[3];
     int occFixSmallEdges, occFixSmallFaces, occSewFaces;
-    int copyMeshingMethod;
+    int copyMeshingMethod, exactExtrusion;
   } geom;
   // mesh options 
   struct {
diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index f100c4e57af99777d47daf7c65c0e447f1cc518b..1bdbf7ac4e4f13f48f375db6be8819a8e5a00c45 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -804,6 +804,8 @@ StringXNumber GeometryOptions_Number[] = {
   { F|O, "CopyMeshingMethod" , opt_geometry_copy_meshing_method, 0. ,
     "Copy meshing method when duplicating geometrical entities?" },
 
+  { F|O, "ExactExtrusion" , opt_geometry_exact_extrusion, 1. ,
+    "Use exact extrusion formula in interpolations (set to 0 to allow geometrical transformations of extruded entities)" },
   { F|O, "ExtrudeReturnLateralEntities" , opt_geometry_extrude_return_lateral, 1. ,
     "Add lateral entities in lists returned by extrusion commands?" },
   { F|O, "ExtrudeSplinePoints" , opt_geometry_extrude_spline_points, 5. ,
diff --git a/Common/Options.cpp b/Common/Options.cpp
index ab2916050485a4cefa7e872120077fa746ff838c..1ba582792f5fd1db80cc01903dd7c7efcbfe9080 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -4684,6 +4684,13 @@ double opt_geometry_copy_meshing_method(OPT_ARGS_NUM)
   return CTX::instance()->geom.copyMeshingMethod;
 }
 
+double opt_geometry_exact_extrusion(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET)
+    CTX::instance()->geom.exactExtrusion = (int)val;
+  return CTX::instance()->geom.exactExtrusion;
+}
+
 double opt_mesh_optimize(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
diff --git a/Common/Options.h b/Common/Options.h
index 9af81170ebbf639525995fa0bd34be46f2640d88..335b7ade4d518e8fe7b1e4d6081c81266972fbca 100644
--- a/Common/Options.h
+++ b/Common/Options.h
@@ -433,6 +433,7 @@ double opt_geometry_snap1(OPT_ARGS_NUM);
 double opt_geometry_snap2(OPT_ARGS_NUM);
 double opt_geometry_clip(OPT_ARGS_NUM);
 double opt_geometry_copy_meshing_method(OPT_ARGS_NUM);
+double opt_geometry_exact_extrusion(OPT_ARGS_NUM);
 double opt_mesh_label_frequency(OPT_ARGS_NUM);
 double opt_mesh_optimize(OPT_ARGS_NUM);
 double opt_mesh_optimize_netgen(OPT_ARGS_NUM);
diff --git a/Geo/GeoInterpolation.cpp b/Geo/GeoInterpolation.cpp
index 427c47fec0a99baa7901bf45c7893406d72df76a..3b7f66ad7cc9c30dc67d8734367f2dc32b6c3da1 100644
--- a/Geo/GeoInterpolation.cpp
+++ b/Geo/GeoInterpolation.cpp
@@ -8,6 +8,7 @@
 #include "GeoInterpolation.h"
 #include "GeoStringInterface.h"
 #include "Numeric.h"
+#include "Context.h"
 
 #define SQU(a)      ((a)*(a))
 
@@ -633,12 +634,12 @@ Vertex InterpolateSurface(Surface *s, double u, double v, int derivee, int u_v)
     return Vertex(p.x(), p.y(), p.z());
   }
 
-  // FIXME: WARNING -- this is a major hack: we use the exact
-  // extrusion formula if the surface is extruded, so that we create
-  // exact surfaces of revolution. But this WILL fail if the extruded
-  // surface is transformed after the extrusion!
-  if(s->Extrude && s->Extrude->geo.Mode == EXTRUDED_ENTITY && 
-     s->Typ != MSH_SURF_PLAN)
+  // Warning: we use the exact extrusion formula so we can create
+  // exact surfaces of revolution. This WILL fail if the surface is
+  // transformed after the extrusion: in that case set the
+  // exactExtrusion option to 0 to use the normal code path
+  if(CTX::instance()->geom.exactExtrusion && s->Extrude && 
+     s->Extrude->geo.Mode == EXTRUDED_ENTITY && s->Typ != MSH_SURF_PLAN)
     return InterpolateExtrudedSurface(s, u, v);
 
   switch (s->Typ) {
diff --git a/Geo/Makefile b/Geo/Makefile
index acc4f2e589eec863a8533096344f60571943373c..33438837597c590354d4661b209464cd5c8947b9 100644
--- a/Geo/Makefile
+++ b/Geo/Makefile
@@ -312,7 +312,8 @@ GeoInterpolation${OBJEXT}: GeoInterpolation.cpp ../Common/GmshMessage.h Geo.h \
   ../Numeric/GmshMatrix.h ../Common/GmshConfig.h ../Common/ListUtils.h \
   ../Common/TreeUtils.h ../Common/avl.h ../Common/ListUtils.h \
   ExtrudeParams.h ../Common/SmoothData.h GeoInterpolation.h \
-  GeoStringInterface.h
+  GeoStringInterface.h ../Common/Context.h ../Geo/CGNSOptions.h \
+  ../Mesh/meshPartitionOptions.h
 findLinks${OBJEXT}: findLinks.cpp ../Common/GmshMessage.h GModel.h GVertex.h \
   GEntity.h Range.h SPoint3.h SBoundingBox3d.h GPoint.h SPoint2.h GEdge.h \
   SVector3.h GFace.h GEdgeLoop.h Pair.h GRegion.h ../Common/TreeUtils.h \
diff --git a/Mesh/meshGFace.cpp b/Mesh/meshGFace.cpp
index 3c0c4055b6147723709f4ed219da2bf125f55ba4..4d53fb9409fc43e0ff9eeb2c8fb432d1c6dcf792 100644
--- a/Mesh/meshGFace.cpp
+++ b/Mesh/meshGFace.cpp
@@ -3,6 +3,7 @@
 // See the LICENSE.txt file for license information. Please report all
 // bugs and problems to <gmsh@geuz.org>.
 
+#include <sstream>
 #include <stdlib.h>
 #include "meshGFace.h"
 #include "meshGFaceBDS.h"
@@ -367,7 +368,8 @@ static bool recover_medge_old(BDS_Mesh *m, GEdge *ge, std::set<EdgeToRecover> *e
 // Builds An initial triangular mesh that respects the boundaries of
 // the domain, including embedded points and surfaces
 
-static bool gmsh2DMeshGenerator(GFace *gf, int RECUR_ITER, bool repairSelfIntersecting1dMesh, bool debug = true)
+static bool gmsh2DMeshGenerator(GFace *gf, int RECUR_ITER, 
+                                bool repairSelfIntersecting1dMesh, bool debug = true)
 {
   BDS_GeomEntity CLASS_F (1, 2);
   typedef std::set<MVertex*> v_container;
@@ -585,10 +587,14 @@ static bool gmsh2DMeshGenerator(GFace *gf, int RECUR_ITER, bool repairSelfInters
     }
     
     if (edgesNotRecovered.size()){
-      Msg::Warning(":-( There are %d intersections in the 1d mesh",
-	  edgesNotRecovered.size());
+      std::ostringstream sstream;
+      for (std::set<EdgeToRecover>::iterator itr = edgesNotRecovered.begin();
+           itr != edgesNotRecovered.end(); ++itr)
+        sstream << " " << itr->ge->tag();
+      Msg::Warning(":-( There are %d intersections in the 1D mesh (curves%s)",
+                   edgesNotRecovered.size(), sstream.str().c_str());
       Msg::Warning("8-| Gmsh splits those edges and tries again");
-
+    
       if (debug){
 	char name[245];
 	sprintf(name, "surface%d-not_yet_recovered-real-%d.msh", gf->tag(),RECUR_ITER);
@@ -623,7 +629,7 @@ static bool gmsh2DMeshGenerator(GFace *gf, int RECUR_ITER, bool repairSelfInters
       return false;
     }
     if(RECUR_ITER > 0)
-      Msg::Warning(":-) Gmsh was able to recover all edges after %d ITERATIONS",
+      Msg::Warning(":-) Gmsh was able to recover all edges after %d iterations",
 		   RECUR_ITER);
     
     //  Msg::Info("Boundary Edges recovered for surface %d", gf->tag());
@@ -917,7 +923,7 @@ static bool buildConsecutiveListOfVertices(GFace *gf, GEdgeLoop  &gel,
          if (seam && seam_the_first){
            coords = ((*it)._sign == 1) ? mesh1d_seam : mesh1d_seam_reversed;
            found = (*it);
-           Msg::Info("This test case would have failed in Previous Gmsh Version ;-)");
+           Msg::Info("This test case would have failed in previous Gmsh versions ;-)");
          }
          else{
            coords = ((*it)._sign == 1) ? mesh1d : mesh1d_reversed;
diff --git a/doc/texinfo/opt_geometry.texi b/doc/texinfo/opt_geometry.texi
index fb62d851d33e92139d585fe721dddea3ee559973..bd6fccf803153a0e016f4402583dccbfe6dad331 100644
--- a/doc/texinfo/opt_geometry.texi
+++ b/doc/texinfo/opt_geometry.texi
@@ -19,6 +19,11 @@ Copy meshing method when duplicating geometrical entities?@*
 Default value: @code{0}@*
 Saved in: @code{General.OptionsFileName}
 
+@item Geometry.ExactExtrusion
+Use exact extrusion formula in interpolations (set to 0 to allow geometrical transformations of extruded entities)@*
+Default value: @code{1}@*
+Saved in: @code{General.OptionsFileName}
+
 @item Geometry.ExtrudeReturnLateralEntities
 Add lateral entities in lists returned by extrusion commands?@*
 Default value: @code{1}@*