0025630: Possible memory leaks in BRepGProp_Vinert and BRepGProp_Sinert
[occt.git] / src / BRepGProp / BRepGProp_Gauss.cxx
diff --git a/src/BRepGProp/BRepGProp_Gauss.cxx b/src/BRepGProp/BRepGProp_Gauss.cxx
new file mode 100644 (file)
index 0000000..d905f75
--- /dev/null
@@ -0,0 +1,1380 @@
+// Copyright (c) 2008-2015 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <math.hxx>
+#include <Precision.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <Standard_Assert.hxx>
+#include <BRepGProp_Face.hxx>
+#include <BRepGProp_Domain.hxx>
+#include <BRepGProp_Gauss.hxx>
+
+// If the following is defined the error of algorithm is calculated by static moments
+#define IS_MIN_DIM
+
+namespace
+{
+  // Minimal value of interval's range for computation | minimal value of "dim" | ... 
+  static const Standard_Real EPS_PARAM          = 1.e-12;
+  static const Standard_Real EPS_DIM            = 1.e-30;
+  static const Standard_Real ERROR_ALGEBR_RATIO = 2.0 / 3.0;
+
+  // Maximum of GaussPoints on a subinterval and maximum of subintervals
+  static const Standard_Integer GPM        = math::GaussPointsMax();
+  static const Standard_Integer SUBS_POWER = 32;
+  static const Standard_Integer SM         = SUBS_POWER * GPM + 1;
+
+  // Auxiliary inner functions to perform arithmetic operations.
+  static Standard_Real Add(const Standard_Real theA, const Standard_Real theB)
+  {
+    return theA + theB;
+  }
+
+  static Standard_Real AddInf(const Standard_Real theA, const Standard_Real theB)
+  {
+    if (Precision::IsPositiveInfinite(theA))
+    {
+      if (Precision::IsNegativeInfinite(theB))
+        return 0.0;
+      else
+        return Precision::Infinite();
+    }
+
+    if (Precision::IsPositiveInfinite(theB))
+    {
+      if (Precision::IsNegativeInfinite(theA))
+        return 0.0;
+      else
+        return Precision::Infinite();
+    }
+
+    if (Precision::IsNegativeInfinite(theA))
+    {
+      if (Precision::IsPositiveInfinite(theB))
+        return 0.0;
+      else
+        return -Precision::Infinite();
+    }
+
+    if (Precision::IsNegativeInfinite(theB))
+    {
+      if (Precision::IsPositiveInfinite(theA))
+        return 0.0;
+      else
+        return -Precision::Infinite();
+    }
+
+    return theA + theB;
+  }
+
+  static Standard_Real Mult(const Standard_Real theA, const Standard_Real theB)
+  {
+    return theA * theB;
+  }
+
+  static Standard_Real MultInf(const Standard_Real theA, const Standard_Real theB)
+  {
+    if ((theA == 0.0) || (theB == 0.0))  //strictly zerro (without any tolerances)
+      return 0.0;
+
+    if (Precision::IsPositiveInfinite(theA))
+    {
+      if (theB < 0.0)
+        return -Precision::Infinite();
+      else
+        return Precision::Infinite();
+    }
+
+    if (Precision::IsPositiveInfinite(theB))
+    {
+      if (theA < 0.0)
+        return -Precision::Infinite();
+      else
+        return Precision::Infinite();
+    }
+
+    if (Precision::IsNegativeInfinite(theA))
+    {
+      if (theB < 0.0)
+        return +Precision::Infinite();
+      else
+        return -Precision::Infinite();
+    }
+
+    if (Precision::IsNegativeInfinite(theB))
+    {
+      if (theA < 0.0)
+        return +Precision::Infinite();
+      else
+        return -Precision::Infinite();
+    }
+
+    return theA * theB;
+  }
+}
+
+//=======================================================================
+//function : BRepGProp_Gauss::Inert::Inert
+//purpose  : Constructor
+//=======================================================================
+BRepGProp_Gauss::Inertia::Inertia()
+: Mass(0.0),
+  Ix  (0.0),
+  Iy  (0.0),
+  Iz  (0.0),
+  Ixx (0.0),
+  Iyy (0.0),
+  Izz (0.0),
+  Ixy (0.0),
+  Ixz (0.0),
+  Iyz (0.0)
+{
+}
+
+//=======================================================================
+//function : Inertia::Reset
+//purpose  : Zeroes all values.
+//=======================================================================
+void BRepGProp_Gauss::Inertia::Reset()
+{
+  memset(reinterpret_cast<void*>(this), 0, sizeof(BRepGProp_Gauss::Inertia));
+}
+
+//=======================================================================
+//function : BRepGProp_Gauss
+//purpose  : Constructor
+//=======================================================================
+BRepGProp_Gauss::BRepGProp_Gauss(const BRepGProp_GaussType theType)
+: myType(theType)
+{
+  add  = (::Add );
+  mult = (::Mult);
+}
+
+//=======================================================================
+//function : MaxSubs
+//purpose  : 
+//=======================================================================
+Standard_Integer BRepGProp_Gauss::MaxSubs(const Standard_Integer theN,
+                                          const Standard_Integer theCoeff)
+{
+  return IntegerLast() / theCoeff < theN ?
+         IntegerLast() : theN * theCoeff + 1;
+}
+
+//=======================================================================
+//function : Init
+//purpose  : 
+//=======================================================================
+void BRepGProp_Gauss::Init(Handle_Vector&         theOutVec,
+                           const Standard_Real    theValue,
+                           const Standard_Integer theFirst,
+                           const Standard_Integer theLast)
+{
+  if(theLast - theFirst == 0)
+  {
+    theOutVec->Init(theValue);
+  }
+  else
+  {
+    for (Standard_Integer i = theFirst; i <= theLast; ++i)
+      theOutVec->Value(i) = theValue;
+  }
+}
+
+//=======================================================================
+//function : InitMass
+//purpose  : 
+//=======================================================================
+void BRepGProp_Gauss::InitMass(const Standard_Real    theValue,
+                               const Standard_Integer theFirst,
+                               const Standard_Integer theLast,
+                               InertiaArray&          theArray)
+{
+  if (theArray.IsNull())
+    return;
+
+  Standard_Integer aFirst = theFirst;
+  Standard_Integer aLast  = theLast;
+
+  if (theLast - theFirst == 0)
+  {
+    aFirst = theArray->Lower();
+    aLast  = theArray->Upper();
+  }
+
+  for (Standard_Integer i = aFirst; i <= aLast; ++i)
+      theArray->ChangeValue(i).Mass = theValue;
+}
+
+//=======================================================================
+//function : FillIntervalBounds
+//purpose  : 
+//=======================================================================
+Standard_Integer BRepGProp_Gauss::FillIntervalBounds(
+  const Standard_Real         theA,
+  const Standard_Real         theB,
+  const TColStd_Array1OfReal& theKnots,
+  const Standard_Integer      theNumSubs,
+  InertiaArray&               theInerts,
+  Handle_Vector&              theParam1,
+  Handle_Vector&              theParam2,
+  Handle_Vector&              theError,
+  Handle_Vector&              theCommonError)
+{
+  const Standard_Integer aSize =
+    Max(theKnots.Upper(), MaxSubs(theKnots.Upper() - 1, theNumSubs));
+
+  if (aSize - 1 > theParam1->Upper())
+  {
+    theInerts = new NCollection_Array1<Inertia>(1, aSize);
+    theParam1 = new math_Vector(1, aSize);
+    theParam2 = new math_Vector(1, aSize);
+    theError  = new math_Vector(1, aSize, 0.0);
+
+    if (theCommonError.IsNull() == Standard_False)
+      theCommonError = new math_Vector(1, aSize, 0.0);
+  }
+
+  Standard_Integer j = 1, k = 1;
+  theParam1->Value(j++) = theA;
+
+  const Standard_Integer aLength = theKnots.Upper();
+  for (Standard_Integer i = 1; i <= aLength; ++i)
+  {
+    const Standard_Real kn = theKnots(i);
+    if (theA < kn)
+    {
+      if (kn < theB) 
+      {
+        theParam1->Value(j++) = kn;
+        theParam2->Value(k++) = kn; 
+      }
+      else
+        break;
+    }
+  }
+
+  theParam2->Value(k) = theB;
+  return k;
+}
+
+
+
+//=======================================================================
+//function : computeVInertiaOfElementaryPart
+//purpose  : 
+//=======================================================================
+void BRepGProp_Gauss::computeVInertiaOfElementaryPart(
+  const gp_Pnt&             thePoint,
+  const gp_Vec&             theNormal,
+  const gp_Pnt&             theLocation,
+  const Standard_Real       theWeight,
+  const Standard_Real       theCoeff[],
+  const Standard_Boolean    theIsByPoint,
+  BRepGProp_Gauss::Inertia& theOutInertia)
+{
+  Standard_Real x = thePoint.X() - theLocation.X();
+  Standard_Real y = thePoint.Y() - theLocation.Y();
+  Standard_Real z = thePoint.Z() - theLocation.Z();
+
+  const Standard_Real xn = theNormal.X() * theWeight;
+  const Standard_Real yn = theNormal.Y() * theWeight;
+  const Standard_Real zn = theNormal.Z() * theWeight;
+
+  if (theIsByPoint)
+  {
+    /////////////////////                        ///////////////////////
+    //    OFV code     //                        //    Initial code   //
+    /////////////////////                        ///////////////////////
+    // modified by APO
+
+    Standard_Real dv = x * xn + y * yn + z * zn; //xyz  = x * y * z;
+    theOutInertia.Mass += dv / 3.0;              //Ixyi += zn * xyz; 
+    theOutInertia.Ix   += 0.25 * x * dv;         //Iyzi += xn * xyz;
+    theOutInertia.Iy   += 0.25 * y * dv;         //Ixzi += yn * xyz; 
+    theOutInertia.Iz   += 0.25 * z * dv;         //xi = x * x * x * xn / 3.0;
+    x -= theCoeff[0];                            //yi = y * y * y * yn / 3.0;
+    y -= theCoeff[1];                            //zi = z * z * z * zn / 3.0;
+    z -= theCoeff[2];                            //Ixxi += (yi + zi);
+    dv *= 0.2;                                   //Iyyi += (xi + zi);
+    theOutInertia.Ixy -= x * y * dv;             //Izzi += (xi + yi);
+    theOutInertia.Iyz -= y * z * dv;             //x -= Coeff[0];
+    theOutInertia.Ixz -= x * z * dv;             //y -= Coeff[1];
+    x *= x;                                      //z -= Coeff[2];
+    y *= y;                                      //dv = x * xn + y * yn + z * zn;
+    z *= z;                                      //dvi +=  dv; 
+    theOutInertia.Ixx += (y + z) * dv;           //Ixi += x * dv;
+    theOutInertia.Iyy += (x + z) * dv;           //Iyi += y * dv;
+    theOutInertia.Izz += (x + y) * dv;           //Izi += z * dv;
+  }
+  else
+  { // By plane
+    const Standard_Real s = xn * theCoeff[0] + yn * theCoeff[1] + zn * theCoeff[2];
+
+    Standard_Real d1  = theCoeff[0] * x + theCoeff[1] * y + theCoeff[2] * z - theCoeff[3];
+    Standard_Real d2  = d1 * d1;
+    Standard_Real d3  = d1 * d2 / 3.0;
+    Standard_Real dv  = s  * d1;
+
+    theOutInertia.Mass += dv;
+    theOutInertia.Ix   += (x - (theCoeff[0] * d1 * 0.5)) * dv;
+    theOutInertia.Iy   += (y - (theCoeff[1] * d1 * 0.5)) * dv;
+    theOutInertia.Iz   += (z - (theCoeff[2] * d1 * 0.5)) * dv;
+
+    const Standard_Real px = x - theCoeff[0] * d1;
+    const Standard_Real py = y - theCoeff[1] * d1;
+    const Standard_Real pz = z - theCoeff[2] * d1;
+
+    x = px * px * d1 + px * theCoeff[0] * d2 + theCoeff[0] * theCoeff[0] * d3;
+    y = py * py * d1 + py * theCoeff[1] * d2 + theCoeff[1] * theCoeff[1] * d3;
+    z = pz * pz * d1 + pz * theCoeff[2] * d2 + theCoeff[2] * theCoeff[2] * d3;
+
+    theOutInertia.Ixx += (y + z) * s;
+    theOutInertia.Iyy += (x + z) * s;
+    theOutInertia.Izz += (x + y) * s;
+
+    d2 *= 0.5;
+    x = (py * pz * d1) + (py * theCoeff[2] * d2) + (pz * theCoeff[1] * d2) + (theCoeff[1] * theCoeff[2] * d3);
+    y = (px * pz * d1) + (pz * theCoeff[0] * d2) + (px * theCoeff[2] * d2) + (theCoeff[0] * theCoeff[2] * d3);
+    z = (px * py * d1) + (px * theCoeff[1] * d2) + (py * theCoeff[0] * d2) + (theCoeff[0] * theCoeff[1] * d3);
+
+    theOutInertia.Ixy -= z * s;
+    theOutInertia.Iyz -= x * s;
+    theOutInertia.Ixz -= y * s;
+  }
+}
+
+//=======================================================================
+//function : computeSInertiaOfElementaryPart
+//purpose  : 
+//=======================================================================
+void BRepGProp_Gauss::computeSInertiaOfElementaryPart(
+  const gp_Pnt&             thePoint,
+  const gp_Vec&             theNormal,
+  const gp_Pnt&             theLocation,
+  const Standard_Real       theWeight,
+  BRepGProp_Gauss::Inertia& theOutInertia)
+{
+  // ds - Jacobien (x, y, z) -> (u, v) = ||n||
+  const Standard_Real ds = mult(theNormal.Magnitude(), theWeight);
+  const Standard_Real x = add(thePoint.X(), -theLocation.X());
+  const Standard_Real y = add(thePoint.Y(), -theLocation.Y());
+  const Standard_Real z = add(thePoint.Z(), -theLocation.Z());
+
+  theOutInertia.Mass = add(theOutInertia.Mass, ds);
+
+  const Standard_Real XdS = mult(x, ds);
+  const Standard_Real YdS = mult(y, ds);
+  const Standard_Real ZdS = mult(z, ds);
+
+  theOutInertia.Ix  = add(theOutInertia.Ix,  XdS);
+  theOutInertia.Iy  = add(theOutInertia.Iy,  YdS);
+  theOutInertia.Iz  = add(theOutInertia.Iz,  ZdS);
+  theOutInertia.Ixy = add(theOutInertia.Ixy, mult(x, YdS));
+  theOutInertia.Iyz = add(theOutInertia.Iyz, mult(y, ZdS));
+  theOutInertia.Ixz = add(theOutInertia.Ixz, mult(x, ZdS));
+
+  const Standard_Real XXdS = mult(x, XdS);
+  const Standard_Real YYdS = mult(y, YdS);
+  const Standard_Real ZZdS = mult(z, ZdS);
+
+  theOutInertia.Ixx = add(theOutInertia.Ixx, add(YYdS, ZZdS));
+  theOutInertia.Iyy = add(theOutInertia.Iyy, add(XXdS, ZZdS));
+  theOutInertia.Izz = add(theOutInertia.Izz, add(XXdS, YYdS));
+}
+
+//=======================================================================
+//function : checkBounds
+//purpose  : 
+//=======================================================================
+void BRepGProp_Gauss::checkBounds(const Standard_Real theU1,
+                                  const Standard_Real theU2,
+                                  const Standard_Real theV1,
+                                  const Standard_Real theV2)
+{
+  if (Precision::IsInfinite(theU1) || Precision::IsInfinite(theU2) ||
+      Precision::IsInfinite(theV1) || Precision::IsInfinite(theV2))
+  {
+    add  = (::AddInf);
+    mult = (::MultInf);
+  }
+}
+
+//=======================================================================
+//function : addAndRestoreInertia
+//purpose  : 
+//=======================================================================
+void BRepGProp_Gauss::addAndRestoreInertia(
+  const BRepGProp_Gauss::Inertia& theInInertia,
+  BRepGProp_Gauss::Inertia&       theOutInertia)
+{
+  theOutInertia.Mass = add(theOutInertia.Mass, theInInertia.Mass);
+  theOutInertia.Ix   = add(theOutInertia.Ix,   theInInertia.Ix);
+  theOutInertia.Iy   = add(theOutInertia.Iy,   theInInertia.Iy);
+  theOutInertia.Iz   = add(theOutInertia.Iz,   theInInertia.Iz);
+  theOutInertia.Ixx  = add(theOutInertia.Ixx,  theInInertia.Ixx);
+  theOutInertia.Iyy  = add(theOutInertia.Iyy,  theInInertia.Iyy);
+  theOutInertia.Izz  = add(theOutInertia.Izz,  theInInertia.Izz);
+  theOutInertia.Ixy  = add(theOutInertia.Ixy,  theInInertia.Ixy);
+  theOutInertia.Ixz  = add(theOutInertia.Ixz,  theInInertia.Ixz);
+  theOutInertia.Iyz  = add(theOutInertia.Iyz,  theInInertia.Iyz);
+}
+
+//=======================================================================
+//function : multAndRestoreInertia
+//purpose  : 
+//=======================================================================
+void BRepGProp_Gauss::multAndRestoreInertia(
+  const Standard_Real       theValue,
+  BRepGProp_Gauss::Inertia& theInOutInertia)
+{
+  theInOutInertia.Mass = mult(theInOutInertia.Mass, theValue);
+  theInOutInertia.Ix   = mult(theInOutInertia.Ix,   theValue);
+  theInOutInertia.Iy   = mult(theInOutInertia.Iy,   theValue);
+  theInOutInertia.Iz   = mult(theInOutInertia.Iz,   theValue);
+  theInOutInertia.Ixx  = mult(theInOutInertia.Ixx,  theValue);
+  theInOutInertia.Iyy  = mult(theInOutInertia.Iyy,  theValue);
+  theInOutInertia.Izz  = mult(theInOutInertia.Izz,  theValue);
+  theInOutInertia.Ixy  = mult(theInOutInertia.Ixy,  theValue);
+  theInOutInertia.Ixz  = mult(theInOutInertia.Ixz,  theValue);
+  theInOutInertia.Iyz  = mult(theInOutInertia.Iyz,  theValue);
+}
+
+//=======================================================================
+//function : convert
+//purpose  : 
+//=======================================================================
+void BRepGProp_Gauss::convert(const BRepGProp_Gauss::Inertia& theInertia,
+                              gp_Pnt&                         theOutGravityCenter,
+                              gp_Mat&                         theOutMatrixOfInertia,
+                              Standard_Real&                  theOutMass)
+{
+  if (Abs(theInertia.Mass) >= EPS_DIM)
+  {
+    const Standard_Real anInvMass = 1.0 / theInertia.Mass;
+    theOutGravityCenter.SetX(theInertia.Ix * anInvMass);
+    theOutGravityCenter.SetY(theInertia.Iy * anInvMass);
+    theOutGravityCenter.SetZ(theInertia.Iz * anInvMass);
+
+    theOutMass = theInertia.Mass;
+  }
+  else
+  {
+    theOutMass = 0.0;
+    theOutGravityCenter.SetCoord(0.0, 0.0, 0.0);
+  }
+
+  theOutMatrixOfInertia = gp_Mat(
+    gp_XYZ ( theInertia.Ixx, -theInertia.Ixy, -theInertia.Ixz),
+    gp_XYZ (-theInertia.Ixy,  theInertia.Iyy, -theInertia.Iyz),
+    gp_XYZ (-theInertia.Ixz, -theInertia.Iyz,  theInertia.Izz));
+}
+
+//=======================================================================
+//function : convert
+//purpose  : 
+//=======================================================================
+void BRepGProp_Gauss::convert(const BRepGProp_Gauss::Inertia& theInertia,
+                              const Standard_Real             theCoeff[],
+                              const Standard_Boolean          theIsByPoint,
+                              gp_Pnt&                         theOutGravityCenter,
+                              gp_Mat&                         theOutMatrixOfInertia,
+                              Standard_Real&                  theOutMass)
+{
+  convert(theInertia, theOutGravityCenter, theOutMatrixOfInertia, theOutMass);
+  if (Abs(theInertia.Mass) >= EPS_DIM && theIsByPoint)
+  {
+    const Standard_Real anInvMass = 1.0 / theInertia.Mass;
+    if (theIsByPoint == Standard_True)
+    {
+      theOutGravityCenter.SetX(theCoeff[0] + theInertia.Ix * anInvMass);
+      theOutGravityCenter.SetY(theCoeff[1] + theInertia.Iy * anInvMass);
+      theOutGravityCenter.SetZ(theCoeff[2] + theInertia.Iz * anInvMass);
+    }
+    else
+    {
+      theOutGravityCenter.SetX(theInertia.Ix * anInvMass);
+      theOutGravityCenter.SetY(theInertia.Iy * anInvMass);
+      theOutGravityCenter.SetZ(theInertia.Iz * anInvMass);
+    }
+
+    theOutMass = theInertia.Mass;
+  }
+  else
+  {
+    theOutMass = 0.0;
+    theOutGravityCenter.SetCoord(0.0, 0.0, 0.0);
+  }
+
+  theOutMatrixOfInertia = gp_Mat(
+    gp_XYZ (theInertia.Ixx, theInertia.Ixy, theInertia.Ixz),
+    gp_XYZ (theInertia.Ixy, theInertia.Iyy, theInertia.Iyz),
+    gp_XYZ (theInertia.Ixz, theInertia.Iyz, theInertia.Izz));
+}
+
+//=======================================================================
+//function : Compute
+//purpose  : 
+//=======================================================================
+Standard_Real BRepGProp_Gauss::Compute(
+  BRepGProp_Face&        theSurface,
+  BRepGProp_Domain&      theDomain,
+  const gp_Pnt&          theLocation,
+  const Standard_Real    theEps,
+  const Standard_Real    theCoeff[],
+  const Standard_Boolean theIsByPoint,
+  Standard_Real&         theOutMass,
+  gp_Pnt&                theOutGravityCenter,
+  gp_Mat&                theOutInertia)
+{
+  const Standard_Boolean isErrorCalculation  =
+    ( 0.0 > theEps || theEps < 0.001 ) ? Standard_True : Standard_False;
+  const Standard_Boolean isVerifyComputation =
+    ( 0.0 < theEps && theEps < 0.001 ) ? Standard_True : Standard_False;
+
+  Standard_Real anEpsilon= Abs(theEps);
+
+  BRepGProp_Gauss::Inertia anInertia;
+  InertiaArray anInertiaL = new NCollection_Array1<Inertia>(1, SM);
+  InertiaArray anInertiaU = new NCollection_Array1<Inertia>(1, SM);
+
+  // Prepare Gauss points and weights
+  Handle_Vector LGaussP[2];
+  Handle_Vector LGaussW[2];
+  Handle_Vector UGaussP[2];
+  Handle_Vector UGaussW[2];
+
+  const Standard_Integer aNbGaussPoint =
+    RealToInt(Ceiling(ERROR_ALGEBR_RATIO * GPM));
+
+  LGaussP[0] = new math_Vector(1, GPM);
+  LGaussP[1] = new math_Vector(1, aNbGaussPoint);
+  LGaussW[0] = new math_Vector(1, GPM);
+  LGaussW[1] = new math_Vector(1, aNbGaussPoint);
+
+  UGaussP[0] = new math_Vector(1, GPM);
+  UGaussP[1] = new math_Vector(1, aNbGaussPoint);
+  UGaussW[0] = new math_Vector(1, GPM);
+  UGaussW[1] = new math_Vector(1, aNbGaussPoint);
+
+  Handle_Vector L1 = new math_Vector(1, SM);
+  Handle_Vector L2 = new math_Vector(1, SM);
+  Handle_Vector U1 = new math_Vector(1, SM);
+  Handle_Vector U2 = new math_Vector(1, SM);
+
+  Handle_Vector ErrL  = new math_Vector(1, SM, 0.0);
+  Handle_Vector ErrU  = new math_Vector(1, SM, 0.0);
+  Handle_Vector ErrUL = new math_Vector(1, SM, 0.0);
+
+  // Face parametrization in U and V direction
+  Standard_Real BV1, BV2, BU1, BU2;
+  theSurface.Bounds(BU1, BU2, BV1, BV2);
+  checkBounds(BU1, BU2, BV1, BV2);
+
+  //
+  const Standard_Integer NumSubs = SUBS_POWER;
+  const Standard_Boolean isNaturalRestriction = theSurface.NaturalRestriction();
+
+  Standard_Real CIx, CIy, CIz, CIxy, CIxz, CIyz;
+  Standard_Real CDim[2], CIxx[2], CIyy[2], CIzz[2];
+
+  // Boundary curve parametrization
+  Standard_Real u1 = BU1, u2, l1, l2, lm, lr, l, v;
+
+  // On the boundary curve u-v
+  gp_Pnt2d Puv;
+  gp_Vec2d Vuv;
+  Standard_Real Dul;  // Dul = Du / Dl
+
+  Standard_Integer iLS, iLSubEnd, iGL, iGLEnd, NbLGaussP[2], LRange[2], iL, kL, kLEnd, IL, JL;
+  Standard_Integer i, iUSubEnd, NbUGaussP[2], URange[2], kU, kUEnd, IU, JU;
+  Standard_Integer UMaxSubs, LMaxSubs;
+
+  Standard_Real ErrorU, ErrorL, ErrorLMax = 0.0, Eps = 0.0, EpsL = 0.0, EpsU = 0.0;
+  iGLEnd = isErrorCalculation ? 2 : 1;
+
+  NbUGaussP[0] = theSurface.SIntOrder(anEpsilon);
+  NbUGaussP[1] = RealToInt( Ceiling(ERROR_ALGEBR_RATIO * NbUGaussP[0]) );
+
+  math::GaussPoints (NbUGaussP[0], *UGaussP[0]);
+  math::GaussWeights(NbUGaussP[0], *UGaussW[0]);
+  math::GaussPoints (NbUGaussP[1], *UGaussP[1]);
+  math::GaussWeights(NbUGaussP[1], *UGaussW[1]);
+
+  const Standard_Integer aNbUSubs = theSurface.SUIntSubs();
+  TColStd_Array1OfReal UKnots(1, aNbUSubs + 1);
+  theSurface.UKnots(UKnots);
+
+  while (isNaturalRestriction || theDomain.More())
+  {
+    if (isNaturalRestriction)
+    { 
+      NbLGaussP[0] = Min(2 * NbUGaussP[0], math::GaussPointsMax());
+    }
+    else
+    {
+      theSurface.Load(theDomain.Value());
+      NbLGaussP[0] = theSurface.LIntOrder(anEpsilon);
+    }
+
+    NbLGaussP[1] = RealToInt( Ceiling(ERROR_ALGEBR_RATIO * NbLGaussP[0]) );
+
+    math::GaussPoints (NbLGaussP[0], *LGaussP[0]);
+    math::GaussWeights(NbLGaussP[0], *LGaussW[0]);
+    math::GaussPoints (NbLGaussP[1], *LGaussP[1]);
+    math::GaussWeights(NbLGaussP[1], *LGaussW[1]);
+
+    const Standard_Integer aNbLSubs =
+      isNaturalRestriction ? theSurface.SVIntSubs(): theSurface.LIntSubs();
+    TColStd_Array1OfReal LKnots(1, aNbLSubs + 1);
+
+    if (isNaturalRestriction)
+    {
+      theSurface.VKnots(LKnots);
+      l1 = BV1;
+      l2 = BV2;
+    }
+    else
+    {
+      theSurface.LKnots(LKnots);
+      l1 = theSurface.FirstParameter();
+      l2 = theSurface.LastParameter();
+    }
+    ErrorL = 0.0;
+    kLEnd = 1; JL = 0;
+
+    if (Abs(l2 - l1) > EPS_PARAM)
+    {
+      iLSubEnd = FillIntervalBounds(l1, l2, LKnots, NumSubs, anInertiaL, L1, L2, ErrL, ErrUL);
+      LMaxSubs = BRepGProp_Gauss::MaxSubs(iLSubEnd);
+
+      if (LMaxSubs > SM)
+        LMaxSubs = SM;
+
+      BRepGProp_Gauss::InitMass(0.0, 1, LMaxSubs, anInertiaL);
+      BRepGProp_Gauss::Init(ErrL,  0.0, 1, LMaxSubs);
+      BRepGProp_Gauss::Init(ErrUL, 0.0, 1, LMaxSubs);
+
+      do // while: L
+      {
+        if (++JL > iLSubEnd)
+        {
+          LRange[0] = IL = ErrL->Max();
+          LRange[1] = JL;
+          L1->Value(JL) = (L1->Value(IL) + L2->Value(IL)) * 0.5;
+          L2->Value(JL) = L2->Value(IL);
+          L2->Value(IL) = L1->Value(JL);
+        }
+        else
+          LRange[0] = IL = JL;
+
+        if (JL == LMaxSubs || Abs(L2->Value(JL) - L1->Value(JL)) < EPS_PARAM)
+        {
+          if (kLEnd == 1)
+          {
+            anInertiaL->ChangeValue(JL).Reset();
+            ErrL->Value(JL) = 0.0;
+          }
+          else
+          {
+            --JL;
+            EpsL = ErrorL;
+            Eps = EpsL / 0.9;
+            break;
+          }
+        }
+        else
+          for (kL = 0; kL < kLEnd; kL++)
+          {
+            iLS = LRange[kL];
+            lm = 0.5 * (L2->Value(iLS) + L1->Value(iLS));
+            lr = 0.5 * (L2->Value(iLS) - L1->Value(iLS));
+
+            CIx = CIy = CIz = CIxy = CIxz = CIyz = 0.0;
+
+            for (iGL = 0; iGL < iGLEnd; ++iGL)
+            {
+              CDim[iGL] = CIxx[iGL] = CIyy[iGL] = CIzz[iGL] = 0.0;
+
+              for (iL = 1; iL <= NbLGaussP[iGL]; iL++)
+              {
+                l = lm + lr * LGaussP[iGL]->Value(iL);
+                if (isNaturalRestriction)
+                { 
+                  v = l;
+                  u2 = BU2;
+                  Dul = LGaussW[iGL]->Value(iL);
+                }
+                else
+                {
+                  theSurface.D12d (l, Puv, Vuv);
+                  Dul = Vuv.Y() * LGaussW[iGL]->Value(iL);  // Dul = Du / Dl
+
+                  if (Abs(Dul) < EPS_PARAM)
+                    continue;
+
+                  v  = Puv.Y();
+                  u2 = Puv.X();
+
+                  // Check on cause out off bounds of value current parameter
+                  if (v < BV1)
+                    v = BV1;
+                  else if (v > BV2)
+                    v = BV2;
+
+                  if (u2 < BU1)
+                    u2 = BU1;
+                  else if (u2 > BU2)
+                    u2 = BU2; 
+                }
+
+                ErrUL->Value(iLS) = 0.0;
+                kUEnd = 1;
+                JU = 0;
+
+                if (Abs(u2 - u1) < EPS_PARAM)
+                  continue;
+
+                Handle_Vector aDummy;
+                iUSubEnd = FillIntervalBounds(u1, u2, UKnots, NumSubs, anInertiaU, U1, U2, ErrU, aDummy);
+                UMaxSubs = BRepGProp_Gauss::MaxSubs(iUSubEnd);
+
+                if (UMaxSubs > SM)
+                  UMaxSubs = SM;
+
+                BRepGProp_Gauss::InitMass(0.0, 1, UMaxSubs, anInertiaU);
+                BRepGProp_Gauss::Init(ErrU, 0.0, 1, UMaxSubs);
+                ErrorU = 0.0;
+
+                do
+                {//while: U
+                  if (++JU > iUSubEnd)
+                  {
+                    URange[0] = IU = ErrU->Max();
+                    URange[1] = JU;
+
+                    U1->Value(JU) = (U1->Value(IU) + U2->Value(IU)) * 0.5;
+                    U2->Value(JU) = U2->Value(IU);
+                    U2->Value(IU) = U1->Value(JU);
+                  }
+                  else
+                    URange[0] = IU = JU;
+
+                  if (JU == UMaxSubs || Abs(U2->Value(JU) - U1->Value(JU)) < EPS_PARAM)
+                    if (kUEnd == 1)
+                    {
+                      ErrU->Value(JU) = 0.0;
+                      anInertiaU->ChangeValue(JU).Reset();
+                    }
+                    else
+                    {
+                      --JU;
+                      EpsU = ErrorU;
+                      Eps  = 10. * EpsU * Abs((u2 - u1) * Dul);
+                      EpsL = 0.9 * Eps;
+                      break;
+                    }
+                  else
+                  {
+                    gp_Pnt aPoint;
+                    gp_Vec aNormal;
+
+                    for (kU = 0; kU < kUEnd; ++kU)
+                    {
+                      BRepGProp_Gauss::Inertia aLocal[2];
+
+                      Standard_Integer iUS = URange[kU];
+                      const Standard_Integer aLength = iGLEnd - iGL;
+
+                      const Standard_Real um = 0.5 * (U2->Value(iUS) + U1->Value(iUS));
+                      const Standard_Real ur = 0.5 * (U2->Value(iUS) - U1->Value(iUS));
+
+                      for (Standard_Integer iGU = 0; iGU < aLength; ++iGU)
+                      {
+                        for (Standard_Integer iU = 1; iU <= NbUGaussP[iGU]; ++iU)
+                        {
+                          Standard_Real w = UGaussW[iGU]->Value(iU);
+                          const Standard_Real u = um + ur * UGaussP[iGU]->Value(iU);
+
+                          theSurface.Normal(u, v, aPoint, aNormal);
+
+                          if (myType == Vinert)
+                          {
+                            computeVInertiaOfElementaryPart(
+                              aPoint, aNormal, theLocation, w, theCoeff, theIsByPoint, aLocal[iGU]);
+                          }
+                          else
+                          {
+                            if (iGU > 0)
+                              aLocal[iGU].Mass += (w * aNormal.Magnitude());
+                            else
+                            {
+                              computeSInertiaOfElementaryPart(
+                                aPoint, aNormal, theLocation, w, aLocal[iGU]);
+                            }
+                          }
+                        }
+                      }
+
+                      BRepGProp_Gauss::Inertia& anUI =
+                        anInertiaU->ChangeValue(iUS);
+
+                      anUI.Mass = mult(aLocal[0].Mass, ur);
+
+                      if (myType == Vinert)
+                      {
+                        anUI.Ixx = mult(aLocal[0].Ixx, ur);
+                        anUI.Iyy = mult(aLocal[0].Iyy, ur);
+                        anUI.Izz = mult(aLocal[0].Izz, ur);
+                      }
+
+                      if (iGL > 0)
+                        continue;
+
+                      Standard_Real aDMass = Abs(aLocal[1].Mass - aLocal[0].Mass);
+
+                      if (myType == Vinert)
+                      {
+                        aLocal[1].Ixx = Abs(aLocal[1].Ixx - aLocal[0].Ixx);
+                        aLocal[1].Iyy = Abs(aLocal[1].Iyy - aLocal[0].Iyy);
+                        aLocal[1].Izz = Abs(aLocal[1].Izz - aLocal[0].Izz);
+
+                        anUI.Ix = mult(aLocal[0].Ix, ur);
+                        anUI.Iy = mult(aLocal[0].Iy, ur);
+                        anUI.Iz = mult(aLocal[0].Iz, ur);
+
+                        anUI.Ixy = mult(aLocal[0].Ixy, ur);
+                        anUI.Ixz = mult(aLocal[0].Ixz, ur);
+                        anUI.Iyz = mult(aLocal[0].Iyz, ur);
+
+                        #ifndef IS_MIN_DIM
+                        aDMass = aLocal[1].Ixx + aLocal[1].Iyy + aLocal[1].Izz;
+                        #endif
+
+                        ErrU->Value(iUS) = mult(aDMass, ur);
+                      }
+                      else
+                      {
+                        anUI.Ix  = mult(aLocal[0].Ix,  ur);
+                        anUI.Iy  = mult(aLocal[0].Iy,  ur);
+                        anUI.Iz  = mult(aLocal[0].Iz,  ur);
+                        anUI.Ixx = mult(aLocal[0].Ixx, ur);
+                        anUI.Iyy = mult(aLocal[0].Iyy, ur);
+                        anUI.Izz = mult(aLocal[0].Izz, ur);
+                        anUI.Ixy = mult(aLocal[0].Ixy, ur);
+                        anUI.Ixz = mult(aLocal[0].Ixz, ur);
+                        anUI.Iyz = mult(aLocal[0].Iyz, ur);
+
+                        ErrU->Value(iUS) = mult(aDMass, ur);
+                      }
+                    }
+                  }
+
+                  if (JU == iUSubEnd)
+                  {
+                    kUEnd = 2;
+                    ErrorU = ErrU->Value(ErrU->Max());
+                  }
+                } while ( (ErrorU - EpsU > 0.0 && EpsU != 0.0) || kUEnd == 1 );
+
+                for (i = 1; i <= JU; ++i)
+                {
+                  const BRepGProp_Gauss::Inertia& anIU =
+                    anInertiaU->Value(i);
+
+                  CDim[iGL] = add(CDim[iGL], mult(anIU.Mass, Dul));
+                  CIxx[iGL] = add(CIxx[iGL], mult(anIU.Ixx,  Dul));
+                  CIyy[iGL] = add(CIyy[iGL], mult(anIU.Iyy,  Dul));
+                  CIzz[iGL] = add(CIzz[iGL], mult(anIU.Izz,  Dul));
+                }
+
+                if (iGL > 0)
+                  continue;
+
+                ErrUL->Value(iLS) = ErrorU * Abs((u2 - u1) * Dul);
+
+                for (i = 1; i <= JU; ++i)
+                {
+                  const BRepGProp_Gauss::Inertia& anIU =
+                    anInertiaU->Value(i);
+
+                  CIx = add(CIx, mult(anIU.Ix, Dul));
+                  CIy = add(CIy, mult(anIU.Iy, Dul));
+                  CIz = add(CIz, mult(anIU.Iz, Dul));
+
+                  CIxy = add(CIxy, mult(anIU.Ixy, Dul));
+                  CIxz = add(CIxz, mult(anIU.Ixz, Dul));
+                  CIyz = add(CIyz, mult(anIU.Iyz, Dul));
+                }
+              }//for: iL 
+            }//for: iGL
+
+            BRepGProp_Gauss::Inertia& aLI = anInertiaL->ChangeValue(iLS);
+
+            aLI.Mass = mult(CDim[0], lr);
+            aLI.Ixx  = mult(CIxx[0], lr);
+            aLI.Iyy  = mult(CIyy[0], lr);
+            aLI.Izz  = mult(CIzz[0], lr);
+
+            if (iGLEnd == 2)
+            {
+              Standard_Real aSubDim = Abs(CDim[1] - CDim[0]);
+
+              if (myType == Vinert)
+              {
+                ErrorU = ErrUL->Value(iLS);
+
+                CIxx[1] = Abs(CIxx[1] - CIxx[0]);
+                CIyy[1] = Abs(CIyy[1] - CIyy[0]);
+                CIzz[1] = Abs(CIzz[1] - CIzz[0]);
+
+                #ifndef IS_MIN_DIM
+                aSubDim = CIxx[1] + CIyy[1] + CIzz[1];
+                #endif
+
+                ErrL->Value(iLS) = add(mult(aSubDim, lr), ErrorU);
+              }
+              else
+              {
+                ErrL->Value(iLS) = add(mult(aSubDim, lr), ErrUL->Value(iLS));
+              }
+            }
+
+            aLI.Ix = mult(CIx, lr);
+            aLI.Iy = mult(CIy, lr);
+            aLI.Iz = mult(CIz, lr);
+
+            aLI.Ixy = mult(CIxy, lr);
+            aLI.Ixz = mult(CIxz, lr);
+            aLI.Iyz = mult(CIyz, lr);
+          }//for: (kL)iLS
+
+          // Calculate/correct epsilon of computation by current value of dim
+          // That is need for not spend time for 
+          if (JL == iLSubEnd)
+          {
+            kLEnd = 2;
+
+            Standard_Real DDim = 0.0;
+            for (i = 1; i <= JL; ++i)
+              DDim += anInertiaL->Value(i).Mass;
+
+            #ifndef IS_MIN_DIM
+            {
+              if (myType == Vinert)
+              {
+                Standard_Real DIxx = 0.0, DIyy = 0.0, DIzz = 0.0;
+                for (i = 1; i <= JL; ++i)
+                {
+                  const BRepGProp_Gauss::Inertia& aLocalL =
+                    anInertiaL->Value(i);
+
+                  DIxx += aLocalL.Ixx;
+                  DIyy += aLocalL.Iyy;
+                  DIzz += aLocalL.Izz;
+                }
+
+                DDim = Abs(DIxx) + Abs(DIyy) + Abs(DIzz);
+              }
+            }
+            #endif
+
+            DDim = Abs(DDim * anEpsilon);
+
+            if (DDim > Eps)
+            {
+              Eps  = DDim;
+              EpsL = 0.9 * Eps;
+            }
+          }
+          if (kLEnd == 2)
+          {
+            ErrorL = ErrL->Value(ErrL->Max());
+          }
+      } while ( (ErrorL - EpsL > 0.0 && isVerifyComputation) || kLEnd == 1 );
+
+      for ( i = 1; i <= JL; i++ )
+        addAndRestoreInertia(anInertiaL->Value(i), anInertia);
+
+      ErrorLMax = Max(ErrorLMax, ErrorL);
+    }
+
+    if (isNaturalRestriction)
+      break;
+
+    theDomain.Next();
+  }
+
+  if (myType == Vinert)
+    convert(anInertia, theCoeff, theIsByPoint, theOutGravityCenter, theOutInertia, theOutMass);
+  else
+    convert(anInertia, theOutGravityCenter, theOutInertia, theOutMass);
+
+  if (iGLEnd == 2)
+  {
+    if (theOutMass != 0.0)
+    {
+      Eps = ErrorLMax / Abs(theOutMass);
+
+      #ifndef IS_MIN_DIM
+      {
+        if (myType == Vinert)
+          Eps = ErrorLMax / (Abs(anInertia.Ixx) +
+                             Abs(anInertia.Iyy) +
+                             Abs(anInertia.Izz));
+      }
+      #endif
+    }
+    else
+    {
+      Eps = 0.0;
+    }
+  }
+  else
+  {
+    Eps = anEpsilon;
+  }
+
+  return Eps;
+}
+
+//=======================================================================
+//function : Compute
+//purpose  : 
+//=======================================================================
+Standard_Real BRepGProp_Gauss::Compute(BRepGProp_Face&     theSurface,
+                                       BRepGProp_Domain&   theDomain,
+                                       const gp_Pnt&       theLocation,
+                                       const Standard_Real theEps,
+                                       Standard_Real&      theOutMass,
+                                       gp_Pnt&             theOutGravityCenter,
+                                       gp_Mat&             theOutInertia)
+{
+  Standard_ASSERT_RAISE(myType == Sinert, "BRepGProp_Gauss: Incorrect type");
+
+  return Compute(theSurface,
+                 theDomain,
+                 theLocation,
+                 theEps,
+                 NULL,
+                 Standard_True,
+                 theOutMass,
+                 theOutGravityCenter,
+                 theOutInertia);
+}
+
+//=======================================================================
+//function : Compute
+//purpose  : 
+//=======================================================================
+void BRepGProp_Gauss::Compute(BRepGProp_Face&   theSurface,
+                              BRepGProp_Domain& theDomain,
+                              const gp_Pnt&     theLocation,
+                              Standard_Real&    theOutMass,
+                              gp_Pnt&           theOutGravityCenter,
+                              gp_Mat&           theOutInertia)
+{
+  Standard_ASSERT_RAISE(myType == Sinert, "BRepGProp_Gauss: Incorrect type");
+
+  Standard_Real u1, u2, v1, v2;
+  theSurface.Bounds (u1, u2, v1, v2);
+  checkBounds(u1, u2, v1, v2);
+
+  const Standard_Integer NbUGaussgp_Pnts =
+    Min(theSurface.UIntegrationOrder(), math::GaussPointsMax());
+
+  const Standard_Integer NbVGaussgp_Pnts =
+    Min(theSurface.VIntegrationOrder(), math::GaussPointsMax());
+
+  const Standard_Integer NbGaussgp_Pnts =
+    Max(NbUGaussgp_Pnts, NbVGaussgp_Pnts);
+
+  // Number of Gauss points for the integration on the face
+  math_Vector GaussSPV (1, NbGaussgp_Pnts);
+  math_Vector GaussSWV (1, NbGaussgp_Pnts);
+  math::GaussPoints (NbGaussgp_Pnts, GaussSPV);
+  math::GaussWeights(NbGaussgp_Pnts, GaussSWV);
+
+  BRepGProp_Gauss::Inertia anInertia;
+  while (theDomain.More())
+  {
+    theSurface.Load(theDomain.Value());
+
+    const Standard_Integer NbCGaussgp_Pnts =
+      Min(theSurface.IntegrationOrder(), math::GaussPointsMax());
+
+    math_Vector GaussCP(1, NbCGaussgp_Pnts);
+    math_Vector GaussCW(1, NbCGaussgp_Pnts);
+    math::GaussPoints (NbCGaussgp_Pnts, GaussCP);
+    math::GaussWeights(NbCGaussgp_Pnts, GaussCW);
+
+    
+    const Standard_Real l1 = theSurface.FirstParameter();
+    const Standard_Real l2 = theSurface.LastParameter ();
+    const Standard_Real lm = 0.5 * (l2 + l1);
+    const Standard_Real lr = 0.5 * (l2 - l1);
+
+    BRepGProp_Gauss::Inertia aCInertia;
+    for (Standard_Integer i = 1; i <= NbCGaussgp_Pnts; ++i)
+    {
+      const Standard_Real l = lm + lr * GaussCP(i);
+
+      gp_Pnt2d Puv;
+      gp_Vec2d Vuv;
+      theSurface.D12d(l, Puv, Vuv);
+
+      const Standard_Real v = Puv.Y();
+      u2  = Puv.X();
+
+      const Standard_Real Dul = Vuv.Y() * GaussCW(i);
+      const Standard_Real um  = 0.5 * (u2 + u1);
+      const Standard_Real ur  = 0.5 * (u2 - u1);
+
+      BRepGProp_Gauss::Inertia aLocalInertia;
+      for (Standard_Integer j = 1; j <= NbGaussgp_Pnts; ++j)
+      {
+        const Standard_Real u = add(um, mult(ur, GaussSPV(j)));
+        const Standard_Real aWeight = Dul * GaussSWV(j);
+
+        gp_Pnt aPoint;
+        gp_Vec aNormal;
+        theSurface.Normal (u, v, aPoint, aNormal);
+
+        computeSInertiaOfElementaryPart(aPoint, aNormal, theLocation, aWeight, aLocalInertia);
+      }
+
+      multAndRestoreInertia(ur, aLocalInertia);
+      addAndRestoreInertia (aLocalInertia, aCInertia);
+    }
+
+    multAndRestoreInertia(lr, aCInertia);
+    addAndRestoreInertia (aCInertia, anInertia);
+
+    theDomain.Next();
+  }
+
+  convert(anInertia, theOutGravityCenter, theOutInertia, theOutMass);
+}
+
+//=======================================================================
+//function : Compute
+//purpose  : 
+//=======================================================================
+void BRepGProp_Gauss::Compute(BRepGProp_Face&         theSurface,
+                              BRepGProp_Domain&       theDomain,
+                              const gp_Pnt&           theLocation,
+                              const Standard_Real     theCoeff[],
+                              const Standard_Boolean  theIsByPoint,
+                              Standard_Real&          theOutMass,
+                              gp_Pnt&                 theOutGravityCenter,
+                              gp_Mat&                 theOutInertia)
+{
+  Standard_ASSERT_RAISE(myType == Vinert, "BRepGProp_Gauss: Incorrect type");
+
+  Standard_Real u1, v1, u2, v2;
+  theSurface.Bounds (u1, u2, v1, v2);
+  checkBounds(u1, u2, v1, v2);
+
+  Standard_Real _u2 = u2;  //OCC104
+
+  BRepGProp_Gauss::Inertia anInertia;
+  while (theDomain.More())
+  {
+    theSurface.Load(theDomain.Value());
+
+    const Standard_Integer aVNbCGaussgp_Pnts =
+      theSurface.VIntegrationOrder();
+
+    const Standard_Integer aNbGaussgp_Pnts =
+      Min( Max(theSurface.IntegrationOrder(), aVNbCGaussgp_Pnts), math::GaussPointsMax() );
+
+    math_Vector GaussP(1, aNbGaussgp_Pnts);
+    math_Vector GaussW(1, aNbGaussgp_Pnts);
+    math::GaussPoints (aNbGaussgp_Pnts, GaussP);
+    math::GaussWeights(aNbGaussgp_Pnts, GaussW);
+
+    const Standard_Real l1 = theSurface.FirstParameter();
+    const Standard_Real l2 = theSurface.LastParameter();
+    const Standard_Real lm = 0.5 * (l2 + l1);
+    const Standard_Real lr = 0.5 * (l2 - l1);
+
+    BRepGProp_Gauss::Inertia aCInertia;
+    for (Standard_Integer i = 1; i <= aNbGaussgp_Pnts; ++i)
+    {
+      const Standard_Real l = lm + lr * GaussP(i);
+
+      gp_Pnt2d Puv;
+      gp_Vec2d Vuv;
+
+      theSurface.D12d(l, Puv, Vuv);
+
+      u2  = Puv.X();
+      u2 = Min( Max(u1, u2), _u2 ); // OCC104
+      const Standard_Real v = Min(Max(Puv.Y(), v1), v2);
+
+      const Standard_Real Dul = Vuv.Y() * GaussW(i);
+      const Standard_Real um  = 0.5 * (u2 + u1);
+      const Standard_Real ur  = 0.5 * (u2 - u1);
+
+      BRepGProp_Gauss::Inertia aLocalInertia;
+      for (Standard_Integer j = 1; j <= aNbGaussgp_Pnts; ++j)
+      {
+        const Standard_Real u = um + ur * GaussP(j);
+        const Standard_Real aWeight = Dul * GaussW(j);
+
+        gp_Pnt aPoint;
+        gp_Vec aNormal;
+
+        theSurface.Normal(u, v, aPoint, aNormal);
+
+        computeVInertiaOfElementaryPart(
+          aPoint,
+          aNormal,
+          theLocation,
+          aWeight,
+          theCoeff,
+          theIsByPoint,
+          aLocalInertia);
+      }
+
+      multAndRestoreInertia(ur, aLocalInertia);
+      addAndRestoreInertia (aLocalInertia, aCInertia);
+    }
+
+    multAndRestoreInertia(lr,        aCInertia);
+    addAndRestoreInertia (aCInertia, anInertia);
+
+    theDomain.Next();
+  }
+
+  convert(anInertia, theCoeff, theIsByPoint, theOutGravityCenter, theOutInertia, theOutMass);
+}
+
+//=======================================================================
+//function : Compute
+//purpose  : 
+//=======================================================================
+void BRepGProp_Gauss::Compute(const BRepGProp_Face&  theSurface,
+                              const gp_Pnt&          theLocation,
+                              const Standard_Real    theCoeff[],
+                              const Standard_Boolean theIsByPoint,
+                              Standard_Real&         theOutMass,
+                              gp_Pnt&                theOutGravityCenter,
+                              gp_Mat&                theOutInertia)
+{
+  Standard_Real LowerU, UpperU, LowerV, UpperV;
+  theSurface.Bounds(LowerU, UpperU, LowerV, UpperV);
+  checkBounds(LowerU, UpperU, LowerV, UpperV);
+
+  const Standard_Integer UOrder =
+    Min(theSurface.UIntegrationOrder(), math::GaussPointsMax());
+  const Standard_Integer VOrder =
+    Min(theSurface.VIntegrationOrder(), math::GaussPointsMax());
+
+  // Gauss points and weights
+  math_Vector GaussPU(1, UOrder);
+  math_Vector GaussWU(1, UOrder);
+  math_Vector GaussPV(1, VOrder);
+  math_Vector GaussWV(1, VOrder);
+
+  math::GaussPoints (UOrder, GaussPU);
+  math::GaussWeights(UOrder, GaussWU);
+  math::GaussPoints (VOrder, GaussPV);
+  math::GaussWeights(VOrder, GaussWV);
+
+  const Standard_Real um = 0.5 * add(UpperU,  LowerU);
+  const Standard_Real vm = 0.5 * add(UpperV,  LowerV);
+  Standard_Real ur = 0.5 * add(UpperU, -LowerU);
+  Standard_Real vr = 0.5 * add(UpperV, -LowerV);
+
+  gp_Pnt aPoint;
+  gp_Vec aNormal;
+
+  BRepGProp_Gauss::Inertia anInertia;
+  for (Standard_Integer j = 1; j <= VOrder; ++j)
+  {
+    BRepGProp_Gauss::Inertia anInertiaOfElementaryPart;
+    const Standard_Real v = add(vm, mult(vr, GaussPV(j)));
+
+    for (Standard_Integer i = 1; i <= UOrder; ++i)
+    {
+      const Standard_Real aWeight = GaussWU(i);
+      const Standard_Real u = add(um, mult(ur, GaussPU (i)));
+      theSurface.Normal(u, v, aPoint, aNormal);
+
+      if (myType == Vinert)
+      {
+        computeVInertiaOfElementaryPart(
+          aPoint,
+          aNormal,
+          theLocation,
+          aWeight,
+          theCoeff,
+          theIsByPoint,
+          anInertiaOfElementaryPart);
+      }
+      else // Sinert
+      {
+        computeSInertiaOfElementaryPart(
+          aPoint,
+          aNormal,
+          theLocation,
+          aWeight,
+          anInertiaOfElementaryPart);
+      }
+    }
+
+    multAndRestoreInertia(GaussWV(j), anInertiaOfElementaryPart);
+    addAndRestoreInertia (anInertiaOfElementaryPart,  anInertia);
+  }
+  vr            = mult(vr, ur);
+  anInertia.Ixx = mult(vr, anInertia.Ixx);
+  anInertia.Iyy = mult(vr, anInertia.Iyy);
+  anInertia.Izz = mult(vr, anInertia.Izz);
+  anInertia.Ixy = mult(vr, anInertia.Ixy);
+  anInertia.Ixz = mult(vr, anInertia.Ixz);
+  anInertia.Iyz = mult(vr, anInertia.Iyz);
+
+  if (myType == Vinert)
+  {
+    convert(anInertia, theCoeff, theIsByPoint, theOutGravityCenter, theOutInertia, theOutMass);
+  }
+  else // Sinert
+  {
+    convert(anInertia, theOutGravityCenter, theOutInertia, theOutMass);
+  }
+
+  theOutMass *= vr;
+}
+
+//=======================================================================
+//function : Compute
+//purpose  : 
+//=======================================================================
+void BRepGProp_Gauss::Compute(const BRepGProp_Face& theSurface,
+                              const gp_Pnt&         theLocation,
+                              Standard_Real&        theOutMass,
+                              gp_Pnt&               theOutGravityCenter,
+                              gp_Mat&               theOutInertia)
+{
+  Standard_ASSERT_RAISE(myType == Sinert, "BRepGProp_Gauss: Incorrect type");
+
+  Compute(theSurface,
+          theLocation,
+          NULL,
+          Standard_True,
+          theOutMass,
+          theOutGravityCenter,
+          theOutInertia);
+}