diff --git a/Numeric/MetricBasis.cpp b/Numeric/MetricBasis.cpp
index d8155a9d1a1386170d857114f0abfd969a2acdb2..1bc1c72f5c103b842a062c9eef7f247c79325c22 100644
--- a/Numeric/MetricBasis.cpp
+++ b/Numeric/MetricBasis.cpp
@@ -89,87 +89,14 @@ double MetricBasis::minRCorner(MElement *el)
 
   // Metric coefficients
   fullMatrix<double> metCoeffLag;
-
-  switch (el->getDim()) {
-  case 0 :
-    return -1.;
-  case 1 :
-  case 2 :
-    Msg::Fatal("not implemented");
-    break;
-
-  case 3 :
-    {
-      fullMatrix<double> dxyzdX(nSampPnts,3), dxyzdY(nSampPnts,3), dxyzdZ(nSampPnts,3);
-      gradients->getGradientsFromNodes(nodes, &dxyzdX, &dxyzdY, &dxyzdZ);
-
-      metCoeffLag.resize(nSampPnts, 7);
-      for (int i = 0; i < nSampPnts; i++) {
-        const double &dxdX = dxyzdX(i,0), &dydX = dxyzdX(i,1), &dzdX = dxyzdX(i,2);
-        const double &dxdY = dxyzdY(i,0), &dydY = dxyzdY(i,1), &dzdY = dxyzdY(i,2);
-        const double &dxdZ = dxyzdZ(i,0), &dydZ = dxyzdZ(i,1), &dzdZ = dxyzdZ(i,2);
-        const double dvxdX = dxdX*dxdX + dydX*dydX + dzdX*dzdX;
-        const double dvxdY = dxdY*dxdY + dydY*dydY + dzdY*dzdY;
-        const double dvxdZ = dxdZ*dxdZ + dydZ*dydZ + dzdZ*dzdZ;
-        metCoeffLag(i, 0) = (dvxdX + dvxdY + dvxdZ) / 3;
-        metCoeffLag(i, 1) = dvxdX - metCoeffLag(i, 0);
-        metCoeffLag(i, 2) = dvxdY - metCoeffLag(i, 0);
-        metCoeffLag(i, 3) = dvxdZ - metCoeffLag(i, 0);
-        const double fact = std::sqrt(2);
-        metCoeffLag(i, 4) = fact * (dxdX*dxdY + dydX*dydY + dzdX*dzdY);
-        metCoeffLag(i, 5) = fact * (dxdZ*dxdY + dydZ*dydY + dzdZ*dzdY);
-        metCoeffLag(i, 6) = fact * (dxdX*dxdZ + dydX*dydZ + dzdX*dzdZ);
-      }
-    }
-    break;
-  }
+  _fillCoeff(gradients, nodes, metCoeffLag);
 
   // Jacobian coefficients
   fullVector<double> jacLag(jacobian->getNumJacNodes());
   jacobian->getSignedJacobian(nodes, jacLag);
 
   // Compute min_corner(R)
-  double Rmin = 1.;
-
-  for (int i = 0; i < nSampPnts; ++i) {
-    if (jacLag(i) <= 0.) {
-      Rmin = std::min(Rmin, 0.);
-    }
-    else {
-      double q = metCoeffLag(i, 0);
-      double p = 0;
-      for (int k = 1; k < 7; ++k) {
-        p += pow_int(metCoeffLag(i, k), 2);
-      }
-      p = std::sqrt(p/6);
-      const double a = q/p;
-      if (a > 1e4) {
-        Rmin = std::min(Rmin, std::sqrt((a - std::sqrt(3)) / (a + std::sqrt(3))));
-      }
-      else {
-        const double x = .5 * (jacLag(i)/p/p*jacLag(i)/p - a*a*a + 3*a);
-        if (x >  1.1 || x < -1.1) {
-          Msg::Error("x much smaller than -1 or much greater than 1");
-        }
-
-        double tmpR;
-        if (x >=  1)
-          tmpR = (a - 1) / (a + 2);
-        else if (x <= -1)
-          tmpR = (a - 2) / (a + 1);
-        else {
-          const double phi = std::acos(x)/3;
-          tmpR = (a + 2*std::cos(phi + 2*M_PI/3)) / (a + 2*std::cos(phi));
-        }
-        if (tmpR < 0) {
-          if (tmpR < -1e-7) Msg::Error("negative R !!!");
-          else tmpR = 0;
-        }
-        Rmin = std::min(Rmin, std::sqrt(tmpR));
-      }
-    }
-  }
-  return Rmin;
+  return _computeMinlagR(jacLag, metCoeffLag, nSampPnts);
 }
 
 double MetricBasis::minSampledR(MElement *el, int order)
@@ -244,41 +171,7 @@ double MetricBasis::getBoundMinR(MElement *el)
 
   // Metric coefficients
   fullMatrix<double> metCoeffLag;
-
-  switch (el->getDim()) {
-  case 0 :
-    return -1.;
-  case 1 :
-  case 2 :
-    Msg::Fatal("not implemented");
-    break;
-
-  case 3 :
-    {
-      fullMatrix<double> dxyzdX(nSampPnts,3), dxyzdY(nSampPnts,3), dxyzdZ(nSampPnts,3);
-      _gradients->getGradientsFromNodes(nodes, &dxyzdX, &dxyzdY, &dxyzdZ);
-
-      metCoeffLag.resize(nSampPnts, 7);
-      for (int i = 0; i < nSampPnts; i++) {
-        const double &dxdX = dxyzdX(i,0), &dydX = dxyzdX(i,1), &dzdX = dxyzdX(i,2);
-        const double &dxdY = dxyzdY(i,0), &dydY = dxyzdY(i,1), &dzdY = dxyzdY(i,2);
-        const double &dxdZ = dxyzdZ(i,0), &dydZ = dxyzdZ(i,1), &dzdZ = dxyzdZ(i,2);
-        const double dvxdX = dxdX*dxdX + dydX*dydX + dzdX*dzdX;
-        const double dvxdY = dxdY*dxdY + dydY*dydY + dzdY*dzdY;
-        const double dvxdZ = dxdZ*dxdZ + dydZ*dydZ + dzdZ*dzdZ;
-        metCoeffLag(i, 0) = (dvxdX + dvxdY + dvxdZ) / 3;
-        metCoeffLag(i, 1) = dvxdX - metCoeffLag(i, 0);
-        metCoeffLag(i, 2) = dvxdY - metCoeffLag(i, 0);
-        metCoeffLag(i, 3) = dvxdZ - metCoeffLag(i, 0);
-        const double fact = std::sqrt(2);
-        metCoeffLag(i, 4) = fact * (dxdX*dxdY + dydX*dydY + dzdX*dzdY);
-        metCoeffLag(i, 5) = fact * (dxdZ*dxdY + dydZ*dydY + dzdZ*dzdY);
-        metCoeffLag(i, 6) = fact * (dxdX*dxdZ + dydX*dydZ + dzdX*dzdZ);
-      }
-    }
-    break;
-  }
-
+  _fillCoeff(_gradients, nodes, metCoeffLag);
   fullMatrix<double> *metCoeff;
   metCoeff = new fullMatrix<double>(nSampPnts, metCoeffLag.size2());
   _bezier->matrixLag2Bez.mult(metCoeffLag, *metCoeff);
@@ -641,47 +534,14 @@ void MetricBasis::_computeRmin(
     double &RminLag, double &RminBez,
     int depth, bool debug) const
 {
-  RminLag = 1.;
-
-  for (int i = 0; i < _bezier->getNumLagCoeff(); ++i) {
-    if (jac(i) <= 0) {
-        RminLag = 0;
-        RminBez = 0;
-        return;
-    }
-    double q = coeff(i, 0);
-    double p = 0;
-    for (int k = 1; k < 7; ++k) {
-      p += pow_int(coeff(i, k), 2);
-    }
-    p = std::sqrt(p/6);
-    const double a = q/p;
-    if (a > 1e4) {
-      RminLag = std::min(RminLag, std::sqrt((a - std::sqrt(3)) / (a + std::sqrt(3))));
-    }
-    else {
-      const double x = .5 * (jac(i)/p/p*jac(i)/p - a*a*a + 3*a);
-
-      double tmpR;
-      if (x >=  1)
-        tmpR = (a - 1) / (a + 2);
-      else if (x <= -1)
-        tmpR = (a - 2) / (a + 1);
-      else {
-        const double phi = std::acos(x)/3;
-        tmpR = (a + 2*std::cos(phi + 2*M_PI/3)) / (a + 2*std::cos(phi));
-      }
-      if (tmpR <= 0) {
-        RminLag = 0;
-        RminBez = 0;
-        return;
-      }
-      else RminLag = std::min(RminLag, std::sqrt(tmpR));
-    }
+  RminLag = _computeMinlagR(jac, coeff, _bezier->getNumLagCoeff());
+  if (RminLag == 0) {
+    RminBez = 0;
+    return;
   }
 
   double minK;
-  _minJ2P3(coeff, jac, minK);
+  _minK(coeff, jac, minK);
   if (minK < 1e-10) {
     RminBez = 0;
     return;
@@ -810,23 +670,7 @@ void MetricBasis::_computeRmax(
       RmaxLag = std::max(RmaxLag, std::sqrt((a - std::sqrt(3)) / (a + std::sqrt(3))));
     }
     else {
-      const double x = .5 * (jac(i)/p/p*jac(i)/p - a*a*a + 3*a);
-
-      double tmpR;
-      if (x >=  1)
-        tmpR = (a - 1) / (a + 2);
-      else if (x <= -1)
-        tmpR = (a - 2) / (a + 1);
-      else {
-        const double phi = std::acos(x)/3;
-        tmpR = (a + 2*std::cos(phi + 2*M_PI/3)) / (a + 2*std::cos(phi));
-      }
-      if (tmpR < 0) {
-        if (tmpR < -1e-7) Msg::Fatal("3 s normal ? %g (%g, %g, %g) or (%g, %g)",
-            tmpR, p/std::sqrt(6), q, jac(i)*jac(i),
-            q/p*std::sqrt(6), jac(i)*jac(i)/p/p/p*6*std::sqrt(6));
-        else tmpR = 0;
-      }
+      const double tmpR = _Rsafe(a, jac(i)/p/p*jac(i)/p);
       RmaxLag = std::max(RmaxLag, std::sqrt(tmpR));
     }
   }
@@ -932,10 +776,27 @@ void MetricBasis::_getMetricData(MElement *el, MetricData *&md) const
 
   // Metric coefficients
   fullMatrix<double> metCoeffLag;
+  _fillCoeff(_gradients, nodes, metCoeffLag);
+  fullMatrix<double> *metCoeff;
+  metCoeff = new fullMatrix<double>(nSampPnts, metCoeffLag.size2());
+  _bezier->matrixLag2Bez.mult(metCoeffLag, *metCoeff);
 
-  switch (el->getDim()) {
+  // Jacobian coefficients
+  fullVector<double> jacLag(_jacobian->getNumJacNodes());
+  fullVector<double> *jac = new fullVector<double>(_jacobian->getNumJacNodes());
+  _jacobian->getSignedJacobian(nodes, jacLag);
+  _jacobian->lag2Bez(jacLag, *jac);
+
+  md = new MetricData(metCoeff, jac, -1, 0, 0);
+}
+
+void MetricBasis::_fillCoeff(const GradientBasis *gradients,
+    fullMatrix<double> &nodes, fullMatrix<double> &coeff)
+{
+  const int nSampPnts = gradients->getNumSamplingPoints();
+
+  switch (nodes.size2()) {
   case 0 :
-    md = NULL;
     return;
   case 1 :
   case 2 :
@@ -945,9 +806,9 @@ void MetricBasis::_getMetricData(MElement *el, MetricData *&md) const
   case 3 :
     {
       fullMatrix<double> dxyzdX(nSampPnts,3), dxyzdY(nSampPnts,3), dxyzdZ(nSampPnts,3);
-      _gradients->getGradientsFromNodes(nodes, &dxyzdX, &dxyzdY, &dxyzdZ);
+      gradients->getGradientsFromNodes(nodes, &dxyzdX, &dxyzdY, &dxyzdZ);
 
-      metCoeffLag.resize(nSampPnts, 7);
+      coeff.resize(nSampPnts, 7);
       for (int i = 0; i < nSampPnts; i++) {
         const double &dxdX = dxyzdX(i,0), &dydX = dxyzdX(i,1), &dzdX = dxyzdX(i,2);
         const double &dxdY = dxyzdY(i,0), &dydY = dxyzdY(i,1), &dzdY = dxyzdY(i,2);
@@ -955,30 +816,46 @@ void MetricBasis::_getMetricData(MElement *el, MetricData *&md) const
         const double dvxdX = dxdX*dxdX + dydX*dydX + dzdX*dzdX;
         const double dvxdY = dxdY*dxdY + dydY*dydY + dzdY*dzdY;
         const double dvxdZ = dxdZ*dxdZ + dydZ*dydZ + dzdZ*dzdZ;
-        metCoeffLag(i, 0) = (dvxdX + dvxdY + dvxdZ) / 3;
-        metCoeffLag(i, 1) = dvxdX - metCoeffLag(i, 0);
-        metCoeffLag(i, 2) = dvxdY - metCoeffLag(i, 0);
-        metCoeffLag(i, 3) = dvxdZ - metCoeffLag(i, 0);
+        coeff(i, 0) = (dvxdX + dvxdY + dvxdZ) / 3;
+        coeff(i, 1) = dvxdX - coeff(i, 0);
+        coeff(i, 2) = dvxdY - coeff(i, 0);
+        coeff(i, 3) = dvxdZ - coeff(i, 0);
         const double fact = std::sqrt(2);
-        metCoeffLag(i, 4) = fact * (dxdX*dxdY + dydX*dydY + dzdX*dzdY);
-        metCoeffLag(i, 5) = fact * (dxdZ*dxdY + dydZ*dydY + dzdZ*dzdY);
-        metCoeffLag(i, 6) = fact * (dxdX*dxdZ + dydX*dydZ + dzdX*dzdZ);
+        coeff(i, 4) = fact * (dxdX*dxdY + dydX*dydY + dzdX*dzdY);
+        coeff(i, 5) = fact * (dxdZ*dxdY + dydZ*dydY + dzdZ*dzdY);
+        coeff(i, 6) = fact * (dxdX*dxdZ + dydX*dydZ + dzdX*dzdZ);
       }
     }
     break;
   }
+}
 
-  fullMatrix<double> *metCoeff;
-  metCoeff = new fullMatrix<double>(nSampPnts, metCoeffLag.size2());
-  _bezier->matrixLag2Bez.mult(metCoeffLag, *metCoeff);
-
-  // Jacobian coefficients
-  fullVector<double> jacLag(_jacobian->getNumJacNodes());
-  fullVector<double> *jac = new fullVector<double>(_jacobian->getNumJacNodes());
-  _jacobian->getSignedJacobian(nodes, jacLag);
-  _jacobian->lag2Bez(jacLag, *jac);
-
-  md = new MetricData(metCoeff, jac, -1, 0, 0);
+double MetricBasis::_computeMinlagR(const fullVector<double> &jac,
+                                    const fullMatrix<double> &coeff, int num)
+{
+  double Rmin = 1.;
+  for (int i = 0; i < num; ++i) {
+    if (jac(i) <= 0.) {
+      return 0;
+    }
+    else {
+      double q = coeff(i, 0);
+      double p = 0;
+      for (int k = 1; k < 7; ++k) {
+        p += pow_int(coeff(i, k), 2);
+      }
+      p = std::sqrt(p/6);
+      const double a = q/p;
+      if (a > 1e4) {
+        Rmin = std::min(Rmin, std::sqrt((a - std::sqrt(3)) / (a + std::sqrt(3))));
+      }
+      else {
+        const double tmpR = _Rsafe(a, jac(i)/p/p*jac(i)/p);
+        Rmin = std::min(Rmin, std::sqrt(tmpR));
+      }
+    }
+  }
+  return Rmin;
 }
 
 void MetricBasis::_minMaxA(
@@ -1012,7 +889,7 @@ void MetricBasis::_minMaxA(
   max = std::sqrt(max);
 }
 
-void MetricBasis::_minJ2P3(const fullMatrix<double> &coeff,
+void MetricBasis::_minK(const fullMatrix<double> &coeff,
     const fullVector<double> &jac, double &min) const
 {
   fullVector<double> r(coeff.size1());
diff --git a/Numeric/MetricBasis.h b/Numeric/MetricBasis.h
index cfc426f9ee4f77f725ad3fe8e723a77b49e6f478..8bbe4c4aa049a0b6e29e47476649282ca7b78c67 100644
--- a/Numeric/MetricBasis.h
+++ b/Numeric/MetricBasis.h
@@ -78,9 +78,13 @@ private:
   void _getMetricData(MElement*, MetricData*&) const;
 
   double _subdivideForRmin(MetricData*, double RminLag, double tol) const;
+  static void _fillCoeff(const GradientBasis*,
+                  fullMatrix<double> &nodes, fullMatrix<double> &coeff);
+  static double _computeMinlagR(const fullVector<double> &jac,
+                                const fullMatrix<double> &coeff, int num);
 
   void _minMaxA(const fullMatrix<double>&, double &min, double &max) const;
-  void _minJ2P3(const fullMatrix<double>&, const fullVector<double>&, double &min) const;
+  void _minK(const fullMatrix<double>&, const fullVector<double>&, double &min) const;
   void _maxAstKpos(const fullMatrix<double>&, const fullVector<double>&,
                  double minK, double beta, double &maxa) const;
   void _maxAstKneg(const fullMatrix<double>&, const fullVector<double>&,
@@ -90,10 +94,26 @@ private:
   void _maxKstAsharp(const fullMatrix<double>&, const fullVector<double>&,
                  double mina, double beta, double &maxK) const;
 
-  double _Rsafe(double a, double K) const {
+  static double _Rsafe(double a, double K) {
     const double x = .5 * (K - a*a*a + 3*a);
-    const double phi = std::acos(x) / 3;
-    return (a + 2*std::cos(phi + 2*M_PI/3)) / (a + 2*std::cos(phi));
+    if (x > 1+1e-13 || x < -1-1e-13) {
+      Msg::Warning("x = %g (|1+%g|)", x, std::abs(x)-1);
+    }
+
+    double ans;
+    if (x >= 1)       ans = (a - 1) / (a + 2);
+    else if (x <= -1) ans = (a - 2) / (a + 1);
+    else {
+      const double phi = std::acos(x) / 3;
+      ans = (a + 2*std::cos(phi + 2*M_PI/3)) / (a + 2*std::cos(phi));
+    }
+
+    if (ans < 0 || ans > 1) {
+      Msg::Warning("R = %g", ans);
+      if (ans < 0) return 0;
+      else return 1;
+    }
+    return ans;
   }
 
 private: