diff --git a/Common/Context.cpp b/Common/Context.cpp
index a4fc1b82ae98a0692bd07091964a27fa939a2c61..234aee965b89f31a4e971417d9806fad0f500a9c 100644
--- a/Common/Context.cpp
+++ b/Common/Context.cpp
@@ -81,7 +81,7 @@ CTX::CTX()
   mesh.numSubEdges = 0;
   mesh.colorCarousel = 0;
   mesh.ignorePartBound = 0;
-  mesh.saveTri = 1;
+  mesh.saveTri = 0;
   color.mesh.tangents = color.mesh.tetrahedron = color.mesh.triangle = 0;
   color.mesh.prism = color.mesh.pyramid = color.mesh.hexahedron = 0;
   color.mesh.tangents = color.mesh.line = color.mesh.quadrangle = 0;
diff --git a/Plugin/CutParametric.cpp b/Plugin/CutParametric.cpp
index defd7182e6ec6b6411f0019cfc5ab073cc2f985d..709c3d0c45c6acbd35754d7314fc850e5e1aeebd 100644
--- a/Plugin/CutParametric.cpp
+++ b/Plugin/CutParametric.cpp
@@ -17,15 +17,18 @@
 StringXNumber CutParametricOptions_Number[] = {
   {GMSH_FULLRC, "MinU", GMSH_CutParametricPlugin::callbackMinU, 0.},
   {GMSH_FULLRC, "MaxU", GMSH_CutParametricPlugin::callbackMaxU, 2 * 3.1416},
-  {GMSH_FULLRC, "NumPointsU", GMSH_CutParametricPlugin::callbackN, 360.},
+  {GMSH_FULLRC, "NumPointsU", GMSH_CutParametricPlugin::callbackNU, 180.},
+  {GMSH_FULLRC, "MinV", GMSH_CutParametricPlugin::callbackMinV, 0.},
+  {GMSH_FULLRC, "MaxV", GMSH_CutParametricPlugin::callbackMaxV, 2 * 3.1416},
+  {GMSH_FULLRC, "NumPointsV", GMSH_CutParametricPlugin::callbackNV, 180.},
   {GMSH_FULLRC, "ConnectPoints", GMSH_CutParametricPlugin::callbackConnect, 0.},
   {GMSH_FULLRC, "View", NULL, -1.}
 };
 
 StringXString CutParametricOptions_String[] = {
-  {GMSH_FULLRC, "X", GMSH_CutParametricPlugin::callbackX, "0.1 + 0.5 * Cos(u)"},
-  {GMSH_FULLRC, "Y", GMSH_CutParametricPlugin::callbackY, "0.1 + 0.5 * Sin(u)"},
-  {GMSH_FULLRC, "Z", GMSH_CutParametricPlugin::callbackZ, "0"},
+  {GMSH_FULLRC, "X", GMSH_CutParametricPlugin::callbackX, "2 * Cos(u) * Sin(v)"},
+  {GMSH_FULLRC, "Y", GMSH_CutParametricPlugin::callbackY, "4 * Sin(u) * Sin(v)"},
+  {GMSH_FULLRC, "Z", GMSH_CutParametricPlugin::callbackZ, "0.1 + 0.5 * Cos(v)"}
 };
 
 extern "C"
@@ -48,6 +51,18 @@ static double getU(int i)
     return minU + (double)(i)/(double)(nbU-1) * (maxU - minU);
 }
 
+static double getV(int i)
+{
+  double minV = CutParametricOptions_Number[3].def;
+  double maxV = CutParametricOptions_Number[4].def;
+  int nbV = (int)CutParametricOptions_Number[5].def;
+  
+  if(nbV == 1)
+    return minV;
+  else
+    return minV + (double)(i)/(double)(nbV-1) * (maxV - minV);
+}
+
 int GMSH_CutParametricPlugin::recompute = 1;
 std::vector<double> GMSH_CutParametricPlugin::x;
 std::vector<double> GMSH_CutParametricPlugin::y;
@@ -55,24 +70,29 @@ std::vector<double> GMSH_CutParametricPlugin::z;
 
 int GMSH_CutParametricPlugin::fillXYZ()
 {
-  std::vector<std::string> expressions(3), variables(1);
+  std::vector<std::string> expressions(3), variables(2);
   for(int i = 0; i < 3; i++) 
     expressions[i] = CutParametricOptions_String[i].def;
   variables[0] = "u";
+  variables[1] = "v";
   mathEvaluator f(expressions, variables);
   if(expressions.empty()) return 0;
 
   int nbU = (int)CutParametricOptions_Number[2].def;
-  x.resize(nbU);
-  y.resize(nbU);
-  z.resize(nbU);
-  std::vector<double> val(1), res(3);
+  int nbV = (int)CutParametricOptions_Number[5].def;
+  x.resize(nbU * nbV);
+  y.resize(nbU * nbV);
+  z.resize(nbU * nbV);
+  std::vector<double> val(2), res(3);
   for(int i = 0; i < nbU; ++i){
     val[0] = getU(i);
-    if(f.eval(val, res)){
-      x[i] = res[0];
-      y[i] = res[1];
-      z[i] = res[2];
+    for(int j = 0; j < nbV; ++j){
+      val[1] = getV(j);
+      if(f.eval(val, res)){
+        x[i * nbV + j] = res[0];
+        y[i * nbV + j] = res[1];
+        z[i * nbV + j] = res[2];
+      }
     }
   }
   return 1;
@@ -86,13 +106,33 @@ void GMSH_CutParametricPlugin::draw(void *context)
     recompute = 0;
   }
   glColor4ubv((GLubyte *) & CTX::instance()->color.fg);
-  if(CutParametricOptions_Number[3].def && x.size() > 1){
-    glBegin(GL_LINES);
-    for(unsigned int i = 1; i < x.size(); ++i){
-      glVertex3d(x[i-1], y[i-1], z[i-1]);
-      glVertex3d(x[i], y[i], z[i]);
+  int nbU = CutParametricOptions_Number[2].def;
+  int nbV = CutParametricOptions_Number[5].def;
+  if(CutParametricOptions_Number[6].def && x.size() > 1){
+    if(nbU == 1 || nbV == 1){
+      glBegin(GL_LINES);
+      for(unsigned int i = 1; i < x.size(); ++i){
+        glVertex3d(x[i-1], y[i-1], z[i-1]);
+        glVertex3d(x[i], y[i], z[i]);
+      }
+      glEnd();
+    }
+    else{
+      glBegin(GL_TRIANGLES);
+      for(unsigned int i = 0; i < nbU - 1; ++i){
+        for(unsigned int j = 0; j < nbV - 1; ++j){
+          int v = i * nbV + j;
+          glVertex3d(x[v], y[v], z[v]);
+          glVertex3d(x[v+1], y[v+1], z[v+1]);
+          glVertex3d(x[v+1+nbV], y[v+1+nbV], z[v+1+nbV]);
+
+          glVertex3d(x[v], y[v], z[v]);
+          glVertex3d(x[v+nbV], y[v+nbV], z[v+nbV]);
+          glVertex3d(x[v+1+nbV], y[v+1+nbV], z[v+1+nbV]);
+        }
+      }
+      glEnd();
     }
-    glEnd();
   }
   else{
     drawContext *ctx = (drawContext*)context;
@@ -138,15 +178,33 @@ double GMSH_CutParametricPlugin::callbackMaxU(int num, int action, double value)
                   0.01, 0., 10.);
 }
 
-double GMSH_CutParametricPlugin::callbackN(int num, int action, double value)
+double GMSH_CutParametricPlugin::callbackNU(int num, int action, double value)
 {
   return callback(num, action, value, &CutParametricOptions_Number[2].def,
                   1, 1, 1000);
 }
 
-double GMSH_CutParametricPlugin::callbackConnect(int num, int action, double value)
+double GMSH_CutParametricPlugin::callbackMinV(int num, int action, double value)
 {
   return callback(num, action, value, &CutParametricOptions_Number[3].def,
+                  0.01, 0., 10.);
+}
+
+double GMSH_CutParametricPlugin::callbackMaxV(int num, int action, double value)
+{
+  return callback(num, action, value, &CutParametricOptions_Number[4].def,
+                  0.01, 0., 10.);
+}
+
+double GMSH_CutParametricPlugin::callbackNV(int num, int action, double value)
+{
+  return callback(num, action, value, &CutParametricOptions_Number[5].def,
+                  1, 1, 1000);
+}
+
+double GMSH_CutParametricPlugin::callbackConnect(int num, int action, double value)
+{
+  return callback(num, action, value, &CutParametricOptions_Number[6].def,
                   1, 0, 1);
 }
 
@@ -168,10 +226,11 @@ std::string GMSH_CutParametricPlugin::callbackZ(int num, int action, std::string
 std::string GMSH_CutParametricPlugin::getHelp() const
 {
   return "Plugin(CutParametric) cuts the view `View' with "
-    "the parametric function (`X'(u), `Y'(u), `Z'(u)), "
+    "the parametric function (`X'(u,v), `Y'(u,v), `Z'(u,v)), "
     "using `NumPointsU' values of the parameter u in "
-    "[`MinU', `MaxU'].\n\n"
-    "If `ConnectPoints' is set, the plugin creates line "
+    "[`MinU', `MaxU'] and `NumPointsV' values of the parameter v in "
+    "[`MinV', `MaxV'].\n\n"
+    "If `ConnectPoints' is set, the plugin creates surface or line "
     "elements; otherwise, the plugin generates points.\n\n"
     "If `View' < 0, the plugin is run on the current view.\n\n"
     "Plugin(CutParametric) creates one new view.";
@@ -210,7 +269,7 @@ static void addInView(int connect, int i, int nbcomp, int nbtime,
       L.push_back(z0); L.push_back(z);
       for(int k = 0; k < nbtime; ++k){
         for(int l = 0; l < nbcomp; ++l)
-          L.push_back(res0[nbcomp * k + l]); 
+          L.push_back(res0[nbcomp * k + l]);
         for(int l = 0; l < nbcomp; ++l)
           L.push_back(res[nbcomp * k + l]);
       }
@@ -228,9 +287,32 @@ static void addInView(int connect, int i, int nbcomp, int nbtime,
   }
 }
 
+static void addInView(int nbcomp, int nbtime,
+                      double x0, double y0, double z0, double *res0,
+                      double x1, double y1, double z1, double *res1,
+                      double x2, double y2, double z2, double *res2,
+                      double x3, double y3, double z3, double *res3,
+                      std::vector<double> &Q, int *nQ)
+{
+  Q.push_back(x0); Q.push_back(x1); Q.push_back(x2); Q.push_back(x3);
+  Q.push_back(y0); Q.push_back(y1); Q.push_back(y2); Q.push_back(y3);
+  Q.push_back(z0); Q.push_back(z1); Q.push_back(z2); Q.push_back(z3);
+  for(int k = 0; k < nbtime; ++k){
+    for(int l = 0; l < nbcomp; ++l)
+      Q.push_back(res0[nbcomp * k + l]);
+    for(int l = 0; l < nbcomp; ++l)
+      Q.push_back(res1[nbcomp * k + l]);
+    for(int l = 0; l < nbcomp; ++l)
+      Q.push_back(res2[nbcomp * k + l]);
+    for(int l = 0; l < nbcomp; ++l)
+      Q.push_back(res3[nbcomp * k + l]);
+  }
+  (*nQ)++;
+}
+
 PView *GMSH_CutParametricPlugin::execute(PView *v)
 {
-  int iView = (int)CutParametricOptions_Number[4].def;
+  int iView = (int)CutParametricOptions_Number[7].def;
 
   PView *v1 = getView(iView, v);
   if(!v1) return v;
@@ -241,8 +323,9 @@ PView *GMSH_CutParametricPlugin::execute(PView *v)
 
   int numSteps = data1->getNumTimeSteps();
   int nbU = (int)CutParametricOptions_Number[2].def;
-  int connect = (int)CutParametricOptions_Number[3].def;
-  if(nbU < 2) connect = 0;
+  int nbV = (int)CutParametricOptions_Number[5].def;
+  int connect = (int)CutParametricOptions_Number[6].def;
+  if(nbU < 2 && nbV < 2) connect = 0;
 
   OctreePost o(v1);
 
@@ -251,41 +334,95 @@ PView *GMSH_CutParametricPlugin::execute(PView *v)
 
   double *res0 = new double[9 * numSteps];
   double *res1 = new double[9 * numSteps];
+  double *res2 = new double[9 * numSteps];
+  double *res3 = new double[9 * numSteps];
   double x0 = 0., y0 = 0., z0 = 0., x1 = 0., y1 = 0., z1 = 0.;
+  double x2 = 0., y2 = 0., z2 = 0., x3 = 0., y3 = 0., z3 = 0.;
 
   for(int k = 0; k < 9 * numSteps; ++k) res0[k] = res1[k] = 0.;
 
-  for(int i = 0; i < nbU; ++i){
-    if(i && connect){
-      x0 = x1;
-      y0 = y1;
-      z0 = z1;
-      for(int k = 0; k < 9 * numSteps; ++k) res0[k] = res1[k];
-    }
+  if(nbU == 1 || nbV == 1 || !connect){
+    for(int i = 0; i < x.size(); ++i){
+      if(i && connect){
+        x0 = x1;
+        y0 = y1;
+        z0 = z1;
+        for(int k = 0; k < 9 * numSteps; ++k) res0[k] = res1[k];
+      }
 
-    x1 = x[i];
-    y1 = y[i];
-    z1 = z[i];
+      x1 = x[i];
+      y1 = y[i];
+      z1 = z[i];
 
-    if(data1->getNumScalars()){
-      o.searchScalar(x1, y1, z1, res1);
-      addInView(connect, i, 1, numSteps, x0, y0, z0, res0, x1, y1, z1, res1,
-                data2->SP, &data2->NbSP, data2->SL, &data2->NbSL);
-    }
-    if(data1->getNumVectors()){
-      o.searchVector(x1, y1, z1, res1);
-      addInView(connect, i, 3, numSteps, x0, y0, z0, res0, x1, y1, z1, res1,
-                data2->VP, &data2->NbVP, data2->VL, &data2->NbVL);
+      if(data1->getNumScalars()){
+        o.searchScalar(x1, y1, z1, res1);
+        addInView(connect, i, 1, numSteps, x0, y0, z0, res0, x1, y1, z1, res1,
+                  data2->SP, &data2->NbSP, data2->SL, &data2->NbSL);
+      }
+      if(data1->getNumVectors()){
+        o.searchVector(x1, y1, z1, res1);
+        addInView(connect, i, 3, numSteps, x0, y0, z0, res0, x1, y1, z1, res1,
+                  data2->VP, &data2->NbVP, data2->VL, &data2->NbVL);
+      }
+      if(data1->getNumTensors()){
+        o.searchTensor(x1, y1, z1, res1);
+        addInView(connect, i, 9, numSteps, x0, y0, z0, res0, x1, y1, z1, res1,
+                  data2->TP, &data2->NbTP, data2->TL, &data2->NbTL);
+      }
     }
-    if(data1->getNumTensors()){
-      o.searchTensor(x1, y1, z1, res1);
-      addInView(connect, i, 9, numSteps, x0, y0, z0, res0, x1, y1, z1, res1,
-                data2->TP, &data2->NbTP, data2->TL, &data2->NbTL);
+  }
+  else{
+    for(int i = 0; i < nbU - 1; ++i){
+      for(int j = 0; j < nbV - 1; ++j){
+        int v = i * nbV + j;
+        x0 = x[v];
+        y0 = y[v];
+        z0 = z[v];
+        x1 = x[v+1];
+        y1 = y[v+1];
+        z1 = z[v+1];
+        x2 = x[v+nbV+1];
+        y2 = y[v+nbV+1];
+        z2 = z[v+nbV+1];
+        x3 = x[v+nbV];
+        y3 = y[v+nbV];
+        z3 = z[v+nbV];
+
+        if(data1->getNumScalars()){
+          o.searchScalar(x0, y0, z0, res0);
+          o.searchScalar(x1, y1, z1, res1);
+          o.searchScalar(x2, y2, z2, res2);
+          o.searchScalar(x3, y3, z3, res3);
+          addInView(1, numSteps, x0, y0, z0, res0, x1, y1, z1, res1,
+                    x2, y2, z2, res2, x3, y3, z3, res3,
+                    data2->SQ, &data2->NbSQ);
+        }
+        if(data1->getNumVectors()){
+          o.searchVector(x0, y0, z0, res0);
+          o.searchVector(x1, y1, z1, res1);
+          o.searchVector(x2, y2, z2, res2);
+          o.searchVector(x3, y3, z3, res3);
+          addInView(3, numSteps, x0, y0, z0, res0, x1, y1, z1, res1,
+                    x2, y2, z2, res2, x3, y3, z3, res3,
+                    data2->VQ, &data2->NbVQ);
+        }
+        if(data1->getNumTensors()){
+          o.searchTensor(x0, y0, z0, res0);
+          o.searchTensor(x1, y1, z1, res1);
+          o.searchTensor(x2, y2, z2, res2);
+          o.searchTensor(x3, y3, z3, res3);
+          addInView(9, numSteps, x0, y0, z0, res0, x1, y1, z1, res1,
+                    x2, y2, z2, res2, x3, y3, z3, res3,
+                    data2->TQ, &data2->NbTQ);
+        }
+      }
     }
   }
-    
+
   delete [] res0;
   delete [] res1;
+  delete [] res2;
+  delete [] res3;
 
   data2->setName(data1->getName() + "_CutParametric");
   data2->setFileName(data1->getName() + "_CutParametric.pos");
diff --git a/Plugin/CutParametric.h b/Plugin/CutParametric.h
index 448e06b0cd5f60c5331133c804fe2b270bf199f8..12495014a41a9fabd137c679c773983f9fd9998c 100644
--- a/Plugin/CutParametric.h
+++ b/Plugin/CutParametric.h
@@ -30,7 +30,7 @@ class GMSH_CutParametricPlugin : public GMSH_PostPlugin
   std::string getName() const { return "CutParametric"; }
   std::string getShortHelp() const
   {
-    return "Cut with the parametric curve (X(u), Y(u), Z(u))";
+    return "Cut with the parametric curve (X(u,v), Y(u,v), Z(u,v))";
   }
   std::string getHelp() const;
   int getNbOptions() const;
@@ -41,7 +41,10 @@ class GMSH_CutParametricPlugin : public GMSH_PostPlugin
 
   static double callbackMinU(int, int, double);
   static double callbackMaxU(int, int, double);
-  static double callbackN(int, int, double);
+  static double callbackNU(int, int, double);
+  static double callbackMinV(int, int, double);
+  static double callbackMaxV(int, int, double);
+  static double callbackNV(int, int, double);
   static double callbackConnect(int, int, double);
   static std::string callbackX(int, int, std::string);
   static std::string callbackY(int, int, std::string);