diff --git a/Geo/GModelIO_Fourier.cpp b/Geo/GModelIO_Fourier.cpp
index 7ff9057d92f9f8aac541f5888cb78c25e04acf14..733785858d610e3fdc7408b5fa49200ed68e61db 100644
--- a/Geo/GModelIO_Fourier.cpp
+++ b/Geo/GModelIO_Fourier.cpp
@@ -85,10 +85,27 @@ public:
   void operator() (GFace *gf)
   {  
     int M = (int)(30. / CTX.mesh.lc_factor), N = (int)(30. / CTX.mesh.lc_factor);
+
+    //if(gf->tag() == 2){
+    //M = 9;
+    //N = 15;
+    //}
+
     for(int i = 0; i < M; i++){
       for(int j = 0; j < N; j++){
 	double u = i/(double)(M - 1);
 	double v = j/(double)(N - 1);
+
+	//if(gf->tag() == 2){
+	  // hack for sttr report 2 (ship model, top right patch)
+	  // XYZ_values_ship_Top(u,v=0) = 
+	  // XYZ_values_ship_Med(u*matching_const1_+matching_const2_,v=1)
+	  // where 0=<u=<1, 
+	  //       matching_const1_=0.523540136032613,
+	  //       matching_const2_=0.475747890863610. 
+	//u = u * 0.5268 + 0.475;
+	//}
+
 	GPoint p = gf->point(u, v);
 	double pou=1;
 	//FM->GetPou(gf->tag(), u, v, pou);
@@ -109,6 +126,21 @@ public:
   }
 };
 
+class meshGmsh{
+public:
+  void operator() (GFace *gf)
+  {  
+    fourierFace *ff = dynamic_cast<fourierFace*>(gf);
+    if(!ff) {
+      Msg(GERROR, "face %d is not Fourier", gf->tag());
+      return;
+    }
+    ff->meshBoundary();
+    meshGFace mesh; 
+    mesh(ff);
+  }
+};
+
 class computePartitionOfUnity{
 public:
   void operator() (GFace *gf)
@@ -586,6 +618,87 @@ fourierFace::~fourierFace()
   }
 }
 
+void fourierFace::meshBoundary()
+{
+  _discrete = 0;
+
+  int nu=0, nv=0;
+  FM->GetNum(tag(), nu, nv);
+
+  std::vector<double> u, v;
+  FM->GetBoundary_Points(tag(), u, v);
+
+  if(2*nu+2*nv != u.size()){
+    Msg(INFO, "Special patch from youngae: %d", tag());
+    GPoint p0 = point(u[0], v[0]);
+    GPoint p1 = point(u[1], v[1]);
+    MVertex *v0 = new MFaceVertex(p0.x(), p0.y(), p0.z(), this, u[0], v[0]);
+    MVertex *v1 = new MFaceVertex(p1.x(), p1.y(), p1.z(), this, u[1], v[1]);
+    _v[0] = new fourierVertex(model(), v0);
+    _v[1] = new fourierVertex(model(), v1);
+    _e[0] = new fourierEdge(model(), 1, _v[0], _v[1]);
+    _e[0]->addFace(this);
+    _e[1] = new fourierEdge(model(), 2, _v[1], _v[0]);
+    _e[1]->addFace(this);
+    for(unsigned int i = 2; i < u.size() - 1; i++){
+      if(u[i] != u[i-1] || v[i] != v[i-1]){
+	GPoint p = point(u[i], v[i]);
+	MVertex *vv = new MFaceVertex(p.x(), p.y(), p.z(), this, u[i], v[i]);
+	_e[1]->mesh_vertices.push_back(vv);
+      }
+    }
+    l_edges.push_back(_e[0]); l_dirs.push_back(1);
+    l_edges.push_back(_e[1]); l_dirs.push_back(1);
+    return;
+  }
+  
+  int corners[4] = {0, nu, nu + nv, 2 * nu + nv};
+  for(int i = 0; i < 4; i++){
+    double uu = u[corners[i]], vv = v[corners[i]];
+    GPoint p = point(uu, vv);
+    MVertex *newv = new MFaceVertex(p.x(), p.y(), p.z(), this, uu, vv);
+    _v[i] = new fourierVertex(model(), newv);
+  }
+  
+  meshAttributes.Method = TRANSFINI;
+  meshAttributes.recombine = 1;
+  meshAttributes.transfiniteArrangement = 1;
+  meshAttributes.corners.clear();
+  for(int i = 0; i < 4; i++)
+    meshAttributes.corners.push_back(_v[i]);
+      
+  _e[0] = new fourierEdge(model(), 1, _v[0], _v[1]);
+  _e[0]->addFace(this);
+  _e[1] = new fourierEdge(model(), 2, _v[1], _v[2]);
+  _e[1]->addFace(this);
+  _e[2] = new fourierEdge(model(), 3, _v[2], _v[3]);
+  _e[2]->addFace(this);
+  _e[3] = new fourierEdge(model(), 4, _v[3], _v[0]);
+  _e[3]->addFace(this);
+
+  for(unsigned int i = corners[0] + 1; i < corners[1] - 1; i++){
+    GPoint p = point(u[i], v[i]);
+    _e[0]->mesh_vertices.push_back(new MFaceVertex(p.x(), p.y(), p.z(), this, u[i], v[i]));
+  }
+  for(unsigned int i = corners[1] + 1; i < corners[2] - 1; i++){
+    GPoint p = point(u[i], v[i]);
+    _e[1]->mesh_vertices.push_back(new MFaceVertex(p.x(), p.y(), p.z(), this, u[i], v[i]));
+  }
+  for(unsigned int i = corners[2] + 1; i < corners[3] - 1; i++){
+    GPoint p = point(u[i], v[i]);
+    _e[2]->mesh_vertices.push_back(new MFaceVertex(p.x(), p.y(), p.z(), this, u[i], v[i]));
+  }
+  for(unsigned int i = corners[3] + 1; i < u.size() - 1; i++){
+    GPoint p = point(u[i], v[i]);
+    _e[3]->mesh_vertices.push_back(new MFaceVertex(p.x(), p.y(), p.z(), this, u[i], v[i]));
+  }
+
+  l_edges.push_back(_e[0]); l_dirs.push_back(1);
+  l_edges.push_back(_e[1]); l_dirs.push_back(1);
+  l_edges.push_back(_e[2]); l_dirs.push_back(1);
+  l_edges.push_back(_e[3]); l_dirs.push_back(1);
+}
+
 Range<double> fourierFace::parBounds(int i) const
 {
   double min, max;
@@ -656,8 +769,12 @@ int GModel::readFourier(const std::string &name)
     add(new fourierFace(this, i));
 
   // mesh each face with quads
-  std::for_each(firstFace(), lastFace(), meshCartesian());
+  //std::for_each(firstFace(), lastFace(), meshCartesian());
+  //return 1;
 
+  // mesh each face using the standard gmsh algorithms
+  setMeshSize(0.1);
+  std::for_each(firstFace(), lastFace(), meshGmsh());
   return 1;
 
   // compute partition of unity
diff --git a/Geo/Makefile b/Geo/Makefile
index e304a138a0c72aee1a81e7b6bd96afeb924828c3..a4b8193d30bd45d948fcb3a29a64bbf434eada40 100644
--- a/Geo/Makefile
+++ b/Geo/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.122 2006-12-20 15:50:57 remacle Exp $
+# $Id: Makefile,v 1.123 2006-12-21 17:10:15 geuzaine Exp $
 #
 # Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 #
@@ -104,12 +104,18 @@ GRegion.o: GRegion.cpp GModel.h GVertex.h GEntity.h Range.h SPoint3.h \
   ../Numeric/Numeric.h ../Common/Context.h ../DataStr/List.h \
   ExtrudeParams.h GFace.h GEdgeLoop.h Pair.h GRegion.h \
   ../Common/SmoothNormals.h
-gmshEdge.o: gmshEdge.cpp gmshEdge.h Geo.h ../Common/GmshDefines.h \
-  ../DataStr/List.h ../DataStr/Tree.h ../DataStr/avl.h ExtrudeParams.h \
-  GEdge.h GEntity.h Range.h SPoint3.h SBoundingBox3d.h GVertex.h \
-  MVertex.h GPoint.h SPoint2.h SVector3.h MElement.h MEdge.h \
-  ../Common/Hash.h MFace.h ../Numeric/Numeric.h ../Common/Context.h \
-  gmshVertex.h GeoInterpolation.h
+gmshVertex.o: gmshVertex.cpp GFace.h GPoint.h GEntity.h Range.h SPoint3.h \
+  SBoundingBox3d.h ../Common/GmshDefines.h GEdgeLoop.h GEdge.h GVertex.h \
+  MVertex.h SPoint2.h SVector3.h MElement.h MEdge.h ../Common/Hash.h \
+  MFace.h ../Numeric/Numeric.h ../Common/Context.h ../DataStr/List.h \
+  ExtrudeParams.h Pair.h gmshVertex.h Geo.h ../DataStr/Tree.h \
+  ../DataStr/avl.h GeoInterpolation.h
+gmshEdge.o: gmshEdge.cpp GFace.h GPoint.h GEntity.h Range.h SPoint3.h \
+  SBoundingBox3d.h ../Common/GmshDefines.h GEdgeLoop.h GEdge.h GVertex.h \
+  MVertex.h SPoint2.h SVector3.h MElement.h MEdge.h ../Common/Hash.h \
+  MFace.h ../Numeric/Numeric.h ../Common/Context.h ../DataStr/List.h \
+  ExtrudeParams.h Pair.h gmshEdge.h Geo.h ../DataStr/Tree.h \
+  ../DataStr/avl.h gmshVertex.h GeoInterpolation.h
 gmshFace.o: gmshFace.cpp GModel.h GVertex.h GEntity.h Range.h SPoint3.h \
   SBoundingBox3d.h ../Common/GmshDefines.h MVertex.h GPoint.h SPoint2.h \
   GEdge.h SVector3.h MElement.h MEdge.h ../Common/Hash.h MFace.h \
@@ -239,7 +245,7 @@ MVertex.o: MVertex.cpp MVertex.h SPoint3.h
 MElement.o: MElement.cpp MElement.h ../Common/GmshDefines.h MVertex.h \
   SPoint3.h MEdge.h SVector3.h ../Common/Hash.h MFace.h \
   ../Numeric/Numeric.h ../Common/Context.h ../DataStr/List.h GEntity.h \
-  Range.h SBoundingBox3d.h
+  Range.h SBoundingBox3d.h ../Common/Message.h
 SVector3.o: SVector3.cpp SVector3.h SPoint3.h
 projectionFace.o: projectionFace.cpp projectionFace.h GFace.h GPoint.h \
   GEntity.h Range.h SPoint3.h SBoundingBox3d.h ../Common/GmshDefines.h \
diff --git a/Geo/fourierFace.h b/Geo/fourierFace.h
index 4e1069fa79c5f9822cbeaa2d5bc3d56957b14007..9a9ecb57524fb929dd280f4fffc1e567cfef250f 100644
--- a/Geo/fourierFace.h
+++ b/Geo/fourierFace.h
@@ -60,6 +60,9 @@ class fourierFace : public GFace {
   fourierFace(GModel *m, int num);
   fourierFace(GFace *f, std::vector<MVertex*> &loop, std::vector<MVertex*> &hole);
   virtual ~fourierFace();
+
+  void meshBoundary();
+
   Range<double> parBounds(int i) const; 
   virtual int paramDegeneracies(int dir, double *par) { return 0; }
   
diff --git a/Mesh/Makefile b/Mesh/Makefile
index 521ae19c41683747028768429b3d568b18e33e18..3e62ac0a87b54a467770b76a6474a89a5fc62edc 100644
--- a/Mesh/Makefile
+++ b/Mesh/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.157 2006-12-20 15:50:57 remacle Exp $
+# $Id: Makefile,v 1.158 2006-12-21 17:10:15 geuzaine Exp $
 #
 # Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 #
@@ -38,7 +38,6 @@ SRC = Generator.cpp \
         meshGFaceExtruded.cpp \
         meshGRegion.cpp \
         meshGRegionDelaunayInsertion.cpp \
-        meshGFaceDelaunayInsertion.cpp \
         meshGRegionTransfinite.cpp \
         meshGRegionExtruded.cpp \
         DivideAndConquer.cpp \
diff --git a/Mesh/meshGFace.cpp b/Mesh/meshGFace.cpp
index fdb226e9a4dd33869b766a5a5bd5cf19ba34a91b..2cdc22bdee303c899aed43a62f81b52a1fa606cd 100644
--- a/Mesh/meshGFace.cpp
+++ b/Mesh/meshGFace.cpp
@@ -1,4 +1,4 @@
-// $Id: meshGFace.cpp,v 1.44 2006-12-21 09:33:41 remacle Exp $
+// $Id: meshGFace.cpp,v 1.45 2006-12-21 17:10:15 geuzaine Exp $
 //
 // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 //
@@ -580,37 +580,38 @@ bool gmsh2DMeshGenerator ( GFace *gf )
   //  fprintf(fdeb,"surface %d\n" ,gf->tag());
   int count = 0;
   SBoundingBox3d bbox;
-  while(itv != all_vertices.end())
-    {
-      MVertex *here     = *itv;
-      SPoint2 param;
-      if (here->onWhat()->dim() == 0)
-	{
-	  GVertex *gv = (GVertex*)here->onWhat();
-	  param=gv->reparamOnFace (gf,1);
-	}
-      else if (here->onWhat()->dim() == 1)
-	{
-	  GEdge *ge = (GEdge*)here->onWhat();
-	  double UU;
-	  here->getParameter(0,UU);
-	  param=ge->reparamOnFace (gf,UU,1);
-	}
+  while(itv != all_vertices.end()){
+    MVertex *here = *itv;
+    SPoint2 param;
+    if(here->onWhat()->dim() == 0){
+      GVertex *gv = (GVertex*)here->onWhat();
+      param = gv->reparamOnFace(gf,1);
+    }
+    else if(here->onWhat()->dim() == 1){
+      GEdge *ge = (GEdge*)here->onWhat();
+      double UU;
+      here->getParameter(0, UU);
+      param = ge->reparamOnFace(gf, UU, 1);
+    }
+    else{
+      double UU, VV;
+      if(here->onWhat() == gf && here->getParameter(0, UU) && here->getParameter(1, VV))
+	param = SPoint2(UU, VV);
       else
-	param =  gf->parFromPoint (SPoint3(here->x(),here->y(),here->z()));
-       //    fprintf(fdeb,"%d %g %g %g\n" ,here->getNum(),here->x(),here->y(),here->z());
-      U_[count] = param.x();
-      V_[count] = param.y();
-      (*itv)->setNum(count);
-      numbered_vertices[(*itv)->getNum()] = *itv;
-      bbox += SPoint3 ( param.x(), param.y() , 0);      
-      count ++;
-      ++itv;
+	param = gf->parFromPoint(SPoint3(here->x(), here->y(), here->z()));
     }
-
+    // fprintf(fdeb,"%d %g %g %g\n" ,here->getNum(),here->x(),here->y(),here->z());
+    U_[count] = param.x();
+    V_[count] = param.y();
+    (*itv)->setNum(count);
+    numbered_vertices[(*itv)->getNum()] = *itv;
+    bbox += SPoint3 ( param.x(), param.y() , 0);      
+    count ++;
+    ++itv;
+  }
+  
   //  fclose (fdeb);
 
-
   // compute the bounding box in parametric space
   // I do not have SBoundingBox, so I use a 3D one...
   // At the same time, number the vertices locally
@@ -719,7 +720,7 @@ bool gmsh2DMeshGenerator ( GFace *gf )
     {
       if (!recover_medge ( m, *it))
 	{
-	  Msg(WARNING,"Face not meshed");
+	  Msg(GERROR,"Face not meshed");
 	  return false;
 	}
       ++it;
diff --git a/Mesh/meshGFaceTransfinite.cpp b/Mesh/meshGFaceTransfinite.cpp
index d250c8e2e8aeca03c5697dbfd78c0866e00a19b5..7e4e213af2ce4e19317d378562ebeaa54d71fc51 100644
--- a/Mesh/meshGFaceTransfinite.cpp
+++ b/Mesh/meshGFaceTransfinite.cpp
@@ -1,4 +1,4 @@
-// $Id: meshGFaceTransfinite.cpp,v 1.14 2006-12-21 09:33:41 remacle Exp $
+// $Id: meshGFaceTransfinite.cpp,v 1.15 2006-12-21 17:10:15 geuzaine Exp $
 //
 // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 //
@@ -103,23 +103,24 @@ int MeshTransfiniteSurface( GFace *gf)
 	return 0;
       }
     }
-
     SPoint2 param;
-    if (v->onWhat()->dim() == 0)
-      {
-	GVertex *gv = (GVertex*)v->onWhat();
-	param=gv->reparamOnFace (gf,1);
-      }
-    else if (v->onWhat()->dim() == 1)
-	{
-	  GEdge *ge = (GEdge*)v->onWhat();
-	  double UU;
-	  v->getParameter(0,UU);
-	  param=ge->reparamOnFace (gf,UU,1);
-	}
-    else
-      param =  gf->parFromPoint (SPoint3(v->x(),v->y(),v->z()));
-
+    if(v->onWhat()->dim() == 0){
+      GVertex *gv = (GVertex*)v->onWhat();
+      param = gv->reparamOnFace(gf, 1);
+    }
+    else if(v->onWhat()->dim() == 1){
+      GEdge *ge = (GEdge*)v->onWhat();
+      double UU;
+      v->getParameter(0, UU);
+      param = ge->reparamOnFace(gf, UU, 1);
+    }
+    else{
+      double UU, VV;
+      if(v->onWhat() == gf && v->getParameter(0, UU) && v->getParameter(1, VV))
+	param = SPoint2(UU, VV);
+      else
+	param = gf->parFromPoint(SPoint3(v->x(), v->y(), v->z()));
+    }
     U.push_back(param.x());
     V.push_back(param.y());
   }
@@ -248,29 +249,8 @@ int MeshTransfiniteSurface( GFace *gf)
 	int iP1 = N1 + i;
 	int iP2 = N2 + j;
 	int iP3 = ((N3 + N2) - i) % m_vertices.size();
-#if 0 // FIXME: this is buggy, so let's just do it in real space instead for now
 	double Up = TRAN_TRI(U[iP1], U[iP2], U[iP3], UC1, UC2, UC3, u, v);
 	double Vp = TRAN_TRI(V[iP1], V[iP2], V[iP3], VC1, VC2, VC3, u, v);
-#else
-	double xp = TRAN_TRI(m_vertices[iP1]->x(), m_vertices[iP2]->x(), 
-			     m_vertices[iP3]->x(), m_vertices[N1]->x(),
-			     m_vertices[N2]->x(), m_vertices[N3]->x(), u, v);
-	double yp = TRAN_TRI(m_vertices[iP1]->y(), m_vertices[iP2]->y(), 
-			     m_vertices[iP3]->y(), m_vertices[N1]->y(),
-			     m_vertices[N2]->y(), m_vertices[N3]->y(), u, v);
-	double zp = TRAN_TRI(m_vertices[iP1]->z(), m_vertices[iP2]->z(), 
-			     m_vertices[iP3]->z(), m_vertices[N1]->z(),
-			     m_vertices[N2]->z(), m_vertices[N3]->z(), u, v);
-	double Up, Vp;
-	if(gf->geomType() == GEntity::Plane){
-	  SPoint2 param = gf->parFromPoint(SPoint3(xp, yp, zp));
-	  Up = param.x();
-	  Vp = param.y();
-	}
-	else{ // xp, yp, zp is usually not on the surface
-	  gf->XYZtoUV(xp, yp, zp, Up, Vp, 1.0, false);
-	}
-#endif
 	GPoint gp = gf->point(SPoint2(Up, Vp));
 	MFaceVertex *newv = new MFaceVertex(gp.x(), gp.y(), gp.z(), gf, Up, Vp);
 	gf->mesh_vertices.push_back(newv);
diff --git a/Parser/OpenFile.cpp b/Parser/OpenFile.cpp
index 5f6ba17acb37518d69cb789ee7a0085027d1ed9e..a6cd9e74616962c4e49367c206197af274722c24 100644
--- a/Parser/OpenFile.cpp
+++ b/Parser/OpenFile.cpp
@@ -1,4 +1,4 @@
-// $Id: OpenFile.cpp,v 1.135 2006-12-16 18:38:52 geuzaine Exp $
+// $Id: OpenFile.cpp,v 1.136 2006-12-21 17:10:15 geuzaine Exp $
 //
 // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 //
@@ -248,7 +248,7 @@ void SetProjectName(char *name)
 int MergeFile(char *name, int warn_if_missing)
 {
 #if defined(HAVE_FOURIER_MODEL)
-  if(!strcmp(name, "falcon")){
+  if(!strcmp(name, "falcon") || !strcmp(name, "ship")){
     GMODEL->readFourier(name);
     SetBoundingBox();
     CTX.mesh.changed = ENT_ALL;
diff --git a/benchmarks/2d/transfinite_tri_ugly_fix.geo b/benchmarks/2d/transfinite_tri_ugly_fix.geo
index d10c640a424d8c0c64e5c4ebe07a8bccfee1b097..a511ae153a244c2895d191e897686e5fbdf2a32f 100644
--- a/benchmarks/2d/transfinite_tri_ugly_fix.geo
+++ b/benchmarks/2d/transfinite_tri_ugly_fix.geo
@@ -10,6 +10,7 @@ Line Loop(4) = {1,-3,-2};
 Plane Surface(5) = {4};
 
 Transfinite Line{1,2,3} = 20;
+//Transfinite Surface{5} = {3,1,2};
 //Transfinite Surface{5} = {2,1,3};
 Transfinite Surface{5} = {1,2,3};
 
diff --git a/doc/texinfo/gmsh.texi b/doc/texinfo/gmsh.texi
index 1a74f5b5d9203336f30421bdebfd95c8d21a2979..7d5382934c264262b7aa4a6f9e6ebade86a63558 100644
--- a/doc/texinfo/gmsh.texi
+++ b/doc/texinfo/gmsh.texi
@@ -1,5 +1,5 @@
 \input texinfo.tex @c -*-texinfo-*-
-@c $Id: gmsh.texi,v 1.223 2006-12-03 20:41:46 geuzaine Exp $
+@c $Id: gmsh.texi,v 1.224 2006-12-21 17:10:15 geuzaine Exp $
 @c
 @c Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 @c
@@ -314,12 +314,14 @@ modules is given hereafter.
 @node Geometry, Mesh, Overview, Overview
 @section Geometry: geometrical entity definition
 
-Geometries are created in a bottom-up flow by successively defining points,
+Gmsh uses a boundary representation (``b-rep'') to describe geometries.
+Models are created in a bottom-up flow by successively defining points,
 oriented lines (line segments, circles, ellipses, splines, @dots{}),
-oriented surfaces (plane surfaces, ruled surfaces, triangulated surfaces,
-@dots{}) and volumes. Compound groups of geometrical entities can be
-defined, based on these elementary geometric entities. Gmsh's scripting
-language allows all geometrical entities to be fully parameterized.
+oriented surfaces (plane surfaces, ruled surfaces, triangulated
+surfaces, @dots{}) and volumes. Compound groups of geometrical entities
+(called ``physical groups'') can also be defined, based on these
+elementary geometric entities. Gmsh's scripting language allows all
+geometrical entities to be fully parameterized.
 
 @c -------------------------------------------------------------------------
 @c Mesh: finite element mesh generation
@@ -329,74 +331,54 @@ language allows all geometrical entities to be fully parameterized.
 @section Mesh: finite element mesh generation
 
 A finite element mesh is a tessellation of a given subset of the
-three-dimensional space by elementary geometrical elements of various shapes
-(in Gmsh's case: lines, triangles, quadrangles, tetrahedra, prisms,
-hexahedra and pyramids), arranged in such a way that if two of them
-intersect, they do so along a face, an edge or a node, and never
-otherwise. All the finite element meshes produced by Gmsh are considered as
-``unstructured'', even if they were generated in a ``structured'' way
-(e.g., by extrusion). This implies that the elementary geometrical elements
-are defined only by an ordered list of their nodes but that no predefined
-order relation is assumed between any two elements.
-
-The mesh generation is performed in the same bottom-up flow as the geometry
-creation: lines are discretized first; the mesh of the lines is then used to
-mesh the surfaces; then the mesh of the surfaces is used to mesh the
-volumes. In this process, the mesh of an entity is only constrained by the
-mesh of its boundary@footnote{For example, in three dimensions:
+three-dimensional space by elementary geometrical elements of various
+shapes (in Gmsh's case: lines, triangles, quadrangles, tetrahedra,
+prisms, hexahedra and pyramids), arranged in such a way that if two of
+them intersect, they do so along a face, an edge or a node, and never
+otherwise. All the finite element meshes produced by Gmsh are considered
+as ``unstructured'', even if they were generated in a ``structured'' way
+(e.g., by extrusion). This implies that the elementary geometrical
+elements are defined only by an ordered list of their nodes but that no
+predefined order relation is assumed between any two elements.
+
+The mesh generation is performed in the same bottom-up flow as the
+geometry creation: lines are discretized first; the mesh of the lines is
+then used to mesh the surfaces; then the mesh of the surfaces is used to
+mesh the volumes. In this process, the mesh of an entity is only
+constrained by the mesh of its boundary@footnote{For example, in three
+dimensions:
 
 @itemize @bullet
 @item
 the triangles discretizing a surface will be forced to be faces of
-tetrahedra in the final 3D mesh only if the surface is part of the boundary
-of a volume;
+tetrahedra in the final 3D mesh only if the surface is part of the
+boundary of a volume;
 @item
 the line elements discretizing a curve will be forced to be edges of
-tetrahedra in the final 3D mesh only if the curve is part of the boundary of
-a surface, itself part of the boundary of a volume;
+tetrahedra in the final 3D mesh only if the curve is part of the
+boundary of a surface, itself part of the boundary of a volume;
 @item
-a single node discretizing a point in the middle of a volume will be forced
-to be a vertex of one of the tetrahedra in the final 3D mesh only if this
-point is connected to a curve, itself part of the boundary of a surface,
-itself part of the boundary of a volume...
+a single node discretizing a point in the middle of a volume will be
+forced to be a vertex of one of the tetrahedra in the final 3D mesh only
+if this point is connected to a curve, itself part of the boundary of a
+surface, itself part of the boundary of a volume...
 @end itemize
-}. This automatically assures the conformity of the mesh when, for example,
-two surfaces share a common line. But this also implies that the
-discretization of an ``isolated'' (@var{n}-1)-th dimensional entity inside
-an @var{n}-th dimensional entity does @emph{not} constrain the @var{n}-th
-dimensional mesh.  Every meshing step is constrained by the characteristic
-length field, which can be uniform, specified by characteristic lengths
-associated with elementary geometrical entities, or associated with another
-mesh (the background mesh).
+}. This automatically assures the conformity of the mesh when, for
+example, two surfaces share a common line. But this also implies that
+the discretization of an ``isolated'' (@var{n}-1)-th dimensional entity
+inside an @var{n}-th dimensional entity does @emph{not} constrain the
+@var{n}-th dimensional mesh.  Every meshing step is constrained by the
+characteristic length field, which can be uniform, specified by
+characteristic lengths associated with elementary geometrical entities,
+or associated with another mesh (the ``background mesh'').
 
 For each meshing step, all structured mesh directives are executed
 first, and serve as additional constraints for the unstructured parts
 @footnote{Note that mixing structured volume grids with unstructured
 volume grids generated with the default 3D isotropic Delaunay algorithm
 can result, in certain cases, to non-conform surface meshes on their
-shared boudary. If this happens, you may consider using the Netgen
-algorithm for the unstructured part.}. The implemented Delaunay
-algorithm is subdivided in the following five steps for surface/volume
-discretization:
-
-@enumerate
-@item
-trivial meshing of a box including the convex polygon/polyhedron defined by
-the boundary nodes resulting from the discretization of the lines/surfaces;
-@item
-creation of the initial mesh by insertion of all the nodes on the
-lines/surfaces thanks to the Bowyer algorithm;
-@item
-boundary restoration to force all the edges/faces of the lines/surfaces to
-be present in the initial mesh;
-@item
-suppression of all the unwanted triangles/tetrahedra (in particular those
-containing the nodes of the initial box);
-@item
-insertion of new nodes by the Bowyer algorithm until the characteristic size
-of each simplex is lower or equal to the characteristic length field
-evaluated at the center of its circumscribed circle/sphere.
-@end enumerate
+shared boundary. If this happens, you may consider using the Netgen
+algorithm for the unstructured part.}.
 
 @c -------------------------------------------------------------------------
 @c Solver: external solver interface
@@ -405,13 +387,13 @@ evaluated at the center of its circumscribed circle/sphere.
 @node Solver, Post-processing, Mesh, Overview
 @section Solver: external solver interface
 
-External solvers can be interfaced with Gmsh through Unix or TCP/IP sockets,
-which permits to easily launch external computations and to collect and
-exploit the simulation results within Gmsh's post-processing module. The
-default solver interfaced with Gmsh is GetDP
-(@uref{http://www.geuz.org/getdp/}). Small examples of solvers written in C,
-C++, Perl and Python are available in the source distribution (in the
-@file{utils/solvers/} directory).
+External solvers can be interfaced with Gmsh through Unix or TCP/IP
+sockets, which permits to launch external computations and to collect
+and process the results directly from within Gmsh's post-processing
+module. The default solver interfaced with Gmsh is GetDP
+(@uref{http://www.geuz.org/getdp/}). Examples on how to interface
+solvers written in C, C++, Perl and Python are available in the source
+distribution (in the @file{utils/solvers/} directory).
 
 @c -------------------------------------------------------------------------
 @c Post-processing: scalar, vector and tensor field visualization
@@ -420,17 +402,18 @@ C++, Perl and Python are available in the source distribution (in the
 @node Post-processing, What Gmsh is pretty good at, Solver, Overview
 @section Post-processing: scalar, vector and tensor field visualization
 
-Multiple post-processing scalar, vector or tensor maps can be loaded and
-manipulated (globally or individually) along with the geometry and the
-mesh. Scalar fields are represented by iso-value lines/surfaces or color
-maps, while vector fields are represented by three-dimensional arrows or
-displacement maps. Post-processing functions include section computation,
-offset, elevation, boundary and component extraction, color map and range
-modification, animation, vector graphic output, etc. All post-processing
-options can be accessed either interactively or through the input ASCII text
-files. Scripting permits to automate all post-processing operations, e.g.,
-for the creation of animations. User-defined operations can also be
-performed on post-processing views through dynamically loadable plugins.
+Gmsh can load and manipulate multiple post-processing scalar, vector or
+tensor maps along with the geometry and the mesh. Scalar fields are
+represented by iso-value lines/surfaces or color maps, while vector
+fields are represented by three-dimensional arrows or displacement
+maps. Post-processing functions include section computation, offset,
+elevation, boundary and component extraction, color map and range
+modification, animation, vector graphic output, etc. All the
+post-processing options can be accessed either interactively or through
+the input ASCII text files. Scripting permits to automate all
+post-processing operations, as for example to create
+animations. User-defined operations can also be performed on
+post-processing views through dynamically loadable plugins.
 
 @c -------------------------------------------------------------------------
 @c What Gmsh is pretty good at...
@@ -455,6 +438,8 @@ parameterize these geometries. Gmsh's scripting language enables all
 commands and command arguments to depend on previous calculations (see
 @ref{Expressions}, and @ref{Geometry commands});
 @item
+import complex models in industry-standard formats like STEP or IGES;
+@item
 generate 1D, 2D and 3D simplicial (i.e., using line segments, triangles and
 tetrahedra) finite element meshes. The performance of the 1D and 2D
 algorithms is pretty good; the 3D algorithm is still experimental and slow
@@ -480,10 +465,10 @@ PostScript, LaTeX, PNG, JPEG, @dots{} (@pxref{General options});
 @item
 generate complex animations (see @ref{General tools}, and @ref{t8.geo});
 @item
-run on low end machines and/or machines with no graphic system. Gmsh can be
-compiled with or without the graphical user interface, and all versions can
-be used either interactively or not, directly from the command line
-(@pxref{Running Gmsh});
+run on low end machines and/or machines with no graphical
+interface. Gmsh can be compiled with or without the GUI, and all
+versions can be used either interactively or directly from the command
+line (@pxref{Running Gmsh});
 @item
 configure your preferred options. Gmsh has a large number of configuration
 options that can be set interactively using the GUI, scattered inside
@@ -509,11 +494,12 @@ also some (a lot of?) weaknesses:
 
 @itemize @bullet
 @item
-the bottom-up approach for describing geometries can become inconvenient for
+the b-rep approach for describing geometries can become inconvenient for
 complex models;
 @item
-there is no support for NURBS and only very limited support for trimmed
-surfaces;
+there is no support for Nurbs and only very limited support for trimmed
+surfaces in Gmsh's scripting language (however you can import STEP or
+IGES models with such features);
 @item
 Gmsh is not primarily a structured mesh generator: no automatic
 quadrilateral or hexahedral meshing algorithm is provided. If you want