e8d70b1713bfba9076bb9e7d6f7212c3ff3c360f
[occt.git] / src / BRepGProp / BRepGProp_Gauss.cxx
1 // Copyright (c) 2008-2015 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <math.hxx>
15 #include <Precision.hxx>
16 #include <TColStd_Array1OfReal.hxx>
17 #include <Standard_Assert.hxx>
18 #include <BRepGProp_Face.hxx>
19 #include <BRepGProp_Domain.hxx>
20 #include <BRepGProp_Gauss.hxx>
21
22 // If the following is defined the error of algorithm is calculated by static moments
23 #define IS_MIN_DIM
24
25 namespace
26 {
27   // Minimal value of interval's range for computation | minimal value of "dim" | ... 
28   static const Standard_Real EPS_PARAM          = 1.e-12;
29   static const Standard_Real EPS_DIM            = 1.e-30;
30   static const Standard_Real ERROR_ALGEBR_RATIO = 2.0 / 3.0;
31
32   // Maximum of GaussPoints on a subinterval and maximum of subintervals
33   static const Standard_Integer GPM        = math::GaussPointsMax();
34   static const Standard_Integer SUBS_POWER = 32;
35   static const Standard_Integer SM         = SUBS_POWER * GPM + 1;
36
37   // Auxiliary inner functions to perform arithmetic operations.
38   static Standard_Real Add(const Standard_Real theA, const Standard_Real theB)
39   {
40     return theA + theB;
41   }
42
43   static Standard_Real AddInf(const Standard_Real theA, const Standard_Real theB)
44   {
45     if (Precision::IsPositiveInfinite(theA))
46     {
47       if (Precision::IsNegativeInfinite(theB))
48         return 0.0;
49       else
50         return Precision::Infinite();
51     }
52
53     if (Precision::IsPositiveInfinite(theB))
54     {
55       if (Precision::IsNegativeInfinite(theA))
56         return 0.0;
57       else
58         return Precision::Infinite();
59     }
60
61     if (Precision::IsNegativeInfinite(theA))
62     {
63       if (Precision::IsPositiveInfinite(theB))
64         return 0.0;
65       else
66         return -Precision::Infinite();
67     }
68
69     if (Precision::IsNegativeInfinite(theB))
70     {
71       if (Precision::IsPositiveInfinite(theA))
72         return 0.0;
73       else
74         return -Precision::Infinite();
75     }
76
77     return theA + theB;
78   }
79
80   static Standard_Real Mult(const Standard_Real theA, const Standard_Real theB)
81   {
82     return theA * theB;
83   }
84
85   static Standard_Real MultInf(const Standard_Real theA, const Standard_Real theB)
86   {
87     if ((theA == 0.0) || (theB == 0.0))  //strictly zerro (without any tolerances)
88       return 0.0;
89
90     if (Precision::IsPositiveInfinite(theA))
91     {
92       if (theB < 0.0)
93         return -Precision::Infinite();
94       else
95         return Precision::Infinite();
96     }
97
98     if (Precision::IsPositiveInfinite(theB))
99     {
100       if (theA < 0.0)
101         return -Precision::Infinite();
102       else
103         return Precision::Infinite();
104     }
105
106     if (Precision::IsNegativeInfinite(theA))
107     {
108       if (theB < 0.0)
109         return +Precision::Infinite();
110       else
111         return -Precision::Infinite();
112     }
113
114     if (Precision::IsNegativeInfinite(theB))
115     {
116       if (theA < 0.0)
117         return +Precision::Infinite();
118       else
119         return -Precision::Infinite();
120     }
121
122     return theA * theB;
123   }
124 }
125
126 //=======================================================================
127 //function : BRepGProp_Gauss::Inert::Inert
128 //purpose  : Constructor
129 //=======================================================================
130 BRepGProp_Gauss::Inertia::Inertia()
131 : Mass(0.0),
132   Ix  (0.0),
133   Iy  (0.0),
134   Iz  (0.0),
135   Ixx (0.0),
136   Iyy (0.0),
137   Izz (0.0),
138   Ixy (0.0),
139   Ixz (0.0),
140   Iyz (0.0)
141 {
142 }
143
144 //=======================================================================
145 //function : Inertia::Reset
146 //purpose  : Zeroes all values.
147 //=======================================================================
148 void BRepGProp_Gauss::Inertia::Reset()
149 {
150   memset(reinterpret_cast<void*>(this), 0, sizeof(BRepGProp_Gauss::Inertia));
151 }
152
153 //=======================================================================
154 //function : BRepGProp_Gauss
155 //purpose  : Constructor
156 //=======================================================================
157 BRepGProp_Gauss::BRepGProp_Gauss(const BRepGProp_GaussType theType)
158 : myType(theType)
159 {
160   add  = (::Add );
161   mult = (::Mult);
162 }
163
164 //=======================================================================
165 //function : MaxSubs
166 //purpose  : 
167 //=======================================================================
168 Standard_Integer BRepGProp_Gauss::MaxSubs(const Standard_Integer theN,
169                                           const Standard_Integer theCoeff)
170 {
171   return IntegerLast() / theCoeff < theN ?
172          IntegerLast() : theN * theCoeff + 1;
173 }
174
175 //=======================================================================
176 //function : Init
177 //purpose  : 
178 //=======================================================================
179 void BRepGProp_Gauss::Init(NCollection_Handle<math_Vector>&         theOutVec,
180                            const Standard_Real    theValue,
181                            const Standard_Integer theFirst,
182                            const Standard_Integer theLast)
183 {
184   if(theLast - theFirst == 0)
185   {
186     theOutVec->Init(theValue);
187   }
188   else
189   {
190     for (Standard_Integer i = theFirst; i <= theLast; ++i)
191       theOutVec->Value(i) = theValue;
192   }
193 }
194
195 //=======================================================================
196 //function : InitMass
197 //purpose  : 
198 //=======================================================================
199 void BRepGProp_Gauss::InitMass(const Standard_Real    theValue,
200                                const Standard_Integer theFirst,
201                                const Standard_Integer theLast,
202                                InertiaArray&          theArray)
203 {
204   if (theArray.IsNull())
205     return;
206
207   Standard_Integer aFirst = theFirst;
208   Standard_Integer aLast  = theLast;
209
210   if (theLast - theFirst == 0)
211   {
212     aFirst = theArray->Lower();
213     aLast  = theArray->Upper();
214   }
215
216   for (Standard_Integer i = aFirst; i <= aLast; ++i)
217       theArray->ChangeValue(i).Mass = theValue;
218 }
219
220 //=======================================================================
221 //function : FillIntervalBounds
222 //purpose  : 
223 //=======================================================================
224 Standard_Integer BRepGProp_Gauss::FillIntervalBounds(
225   const Standard_Real         theA,
226   const Standard_Real         theB,
227   const TColStd_Array1OfReal& theKnots,
228   const Standard_Integer      theNumSubs,
229   InertiaArray&               theInerts,
230   NCollection_Handle<math_Vector>&              theParam1,
231   NCollection_Handle<math_Vector>&              theParam2,
232   NCollection_Handle<math_Vector>&              theError,
233   NCollection_Handle<math_Vector>&              theCommonError)
234 {
235   const Standard_Integer aSize =
236     Max(theKnots.Upper(), MaxSubs(theKnots.Upper() - 1, theNumSubs));
237
238   if (aSize - 1 > theParam1->Upper())
239   {
240     theInerts = new NCollection_Array1<Inertia>(1, aSize);
241     theParam1 = new math_Vector(1, aSize);
242     theParam2 = new math_Vector(1, aSize);
243     theError  = new math_Vector(1, aSize, 0.0);
244
245     if (theCommonError.IsNull() == Standard_False)
246       theCommonError = new math_Vector(1, aSize, 0.0);
247   }
248
249   Standard_Integer j = 1, k = 1;
250   theParam1->Value(j++) = theA;
251
252   const Standard_Integer aLength = theKnots.Upper();
253   for (Standard_Integer i = 1; i <= aLength; ++i)
254   {
255     const Standard_Real kn = theKnots(i);
256     if (theA < kn)
257     {
258       if (kn < theB) 
259       {
260         theParam1->Value(j++) = kn;
261         theParam2->Value(k++) = kn; 
262       }
263       else
264         break;
265     }
266   }
267
268   theParam2->Value(k) = theB;
269   return k;
270 }
271
272
273
274 //=======================================================================
275 //function : computeVInertiaOfElementaryPart
276 //purpose  : 
277 //=======================================================================
278 void BRepGProp_Gauss::computeVInertiaOfElementaryPart(
279   const gp_Pnt&             thePoint,
280   const gp_Vec&             theNormal,
281   const gp_Pnt&             theLocation,
282   const Standard_Real       theWeight,
283   const Standard_Real       theCoeff[],
284   const Standard_Boolean    theIsByPoint,
285   BRepGProp_Gauss::Inertia& theOutInertia)
286 {
287   Standard_Real x = thePoint.X() - theLocation.X();
288   Standard_Real y = thePoint.Y() - theLocation.Y();
289   Standard_Real z = thePoint.Z() - theLocation.Z();
290
291   const Standard_Real xn = theNormal.X() * theWeight;
292   const Standard_Real yn = theNormal.Y() * theWeight;
293   const Standard_Real zn = theNormal.Z() * theWeight;
294
295   if (theIsByPoint)
296   {
297     /////////////////////                        ///////////////////////
298     //    OFV code     //                        //    Initial code   //
299     /////////////////////                        ///////////////////////
300     // modified by APO
301
302     Standard_Real dv = x * xn + y * yn + z * zn; //xyz  = x * y * z;
303     theOutInertia.Mass += dv / 3.0;              //Ixyi += zn * xyz; 
304     theOutInertia.Ix   += 0.25 * x * dv;         //Iyzi += xn * xyz;
305     theOutInertia.Iy   += 0.25 * y * dv;         //Ixzi += yn * xyz; 
306     theOutInertia.Iz   += 0.25 * z * dv;         //xi = x * x * x * xn / 3.0;
307     x -= theCoeff[0];                            //yi = y * y * y * yn / 3.0;
308     y -= theCoeff[1];                            //zi = z * z * z * zn / 3.0;
309     z -= theCoeff[2];                            //Ixxi += (yi + zi);
310     dv *= 0.2;                                   //Iyyi += (xi + zi);
311     theOutInertia.Ixy -= x * y * dv;             //Izzi += (xi + yi);
312     theOutInertia.Iyz -= y * z * dv;             //x -= Coeff[0];
313     theOutInertia.Ixz -= x * z * dv;             //y -= Coeff[1];
314     x *= x;                                      //z -= Coeff[2];
315     y *= y;                                      //dv = x * xn + y * yn + z * zn;
316     z *= z;                                      //dvi +=  dv; 
317     theOutInertia.Ixx += (y + z) * dv;           //Ixi += x * dv;
318     theOutInertia.Iyy += (x + z) * dv;           //Iyi += y * dv;
319     theOutInertia.Izz += (x + y) * dv;           //Izi += z * dv;
320   }
321   else
322   { // By plane
323     const Standard_Real s = xn * theCoeff[0] + yn * theCoeff[1] + zn * theCoeff[2];
324
325     Standard_Real d1  = theCoeff[0] * x + theCoeff[1] * y + theCoeff[2] * z - theCoeff[3];
326     Standard_Real d2  = d1 * d1;
327     Standard_Real d3  = d1 * d2 / 3.0;
328     Standard_Real dv  = s  * d1;
329
330     theOutInertia.Mass += dv;
331     theOutInertia.Ix   += (x - (theCoeff[0] * d1 * 0.5)) * dv;
332     theOutInertia.Iy   += (y - (theCoeff[1] * d1 * 0.5)) * dv;
333     theOutInertia.Iz   += (z - (theCoeff[2] * d1 * 0.5)) * dv;
334
335     const Standard_Real px = x - theCoeff[0] * d1;
336     const Standard_Real py = y - theCoeff[1] * d1;
337     const Standard_Real pz = z - theCoeff[2] * d1;
338
339     x = px * px * d1 + px * theCoeff[0] * d2 + theCoeff[0] * theCoeff[0] * d3;
340     y = py * py * d1 + py * theCoeff[1] * d2 + theCoeff[1] * theCoeff[1] * d3;
341     z = pz * pz * d1 + pz * theCoeff[2] * d2 + theCoeff[2] * theCoeff[2] * d3;
342
343     theOutInertia.Ixx += (y + z) * s;
344     theOutInertia.Iyy += (x + z) * s;
345     theOutInertia.Izz += (x + y) * s;
346
347     d2 *= 0.5;
348     x = (py * pz * d1) + (py * theCoeff[2] * d2) + (pz * theCoeff[1] * d2) + (theCoeff[1] * theCoeff[2] * d3);
349     y = (px * pz * d1) + (pz * theCoeff[0] * d2) + (px * theCoeff[2] * d2) + (theCoeff[0] * theCoeff[2] * d3);
350     z = (px * py * d1) + (px * theCoeff[1] * d2) + (py * theCoeff[0] * d2) + (theCoeff[0] * theCoeff[1] * d3);
351
352     theOutInertia.Ixy -= z * s;
353     theOutInertia.Iyz -= x * s;
354     theOutInertia.Ixz -= y * s;
355   }
356 }
357
358 //=======================================================================
359 //function : computeSInertiaOfElementaryPart
360 //purpose  : 
361 //=======================================================================
362 void BRepGProp_Gauss::computeSInertiaOfElementaryPart(
363   const gp_Pnt&             thePoint,
364   const gp_Vec&             theNormal,
365   const gp_Pnt&             theLocation,
366   const Standard_Real       theWeight,
367   BRepGProp_Gauss::Inertia& theOutInertia)
368 {
369   // ds - Jacobien (x, y, z) -> (u, v) = ||n||
370   const Standard_Real ds = mult(theNormal.Magnitude(), theWeight);
371   const Standard_Real x = add(thePoint.X(), -theLocation.X());
372   const Standard_Real y = add(thePoint.Y(), -theLocation.Y());
373   const Standard_Real z = add(thePoint.Z(), -theLocation.Z());
374
375   theOutInertia.Mass = add(theOutInertia.Mass, ds);
376
377   const Standard_Real XdS = mult(x, ds);
378   const Standard_Real YdS = mult(y, ds);
379   const Standard_Real ZdS = mult(z, ds);
380
381   theOutInertia.Ix  = add(theOutInertia.Ix,  XdS);
382   theOutInertia.Iy  = add(theOutInertia.Iy,  YdS);
383   theOutInertia.Iz  = add(theOutInertia.Iz,  ZdS);
384   theOutInertia.Ixy = add(theOutInertia.Ixy, mult(x, YdS));
385   theOutInertia.Iyz = add(theOutInertia.Iyz, mult(y, ZdS));
386   theOutInertia.Ixz = add(theOutInertia.Ixz, mult(x, ZdS));
387
388   const Standard_Real XXdS = mult(x, XdS);
389   const Standard_Real YYdS = mult(y, YdS);
390   const Standard_Real ZZdS = mult(z, ZdS);
391
392   theOutInertia.Ixx = add(theOutInertia.Ixx, add(YYdS, ZZdS));
393   theOutInertia.Iyy = add(theOutInertia.Iyy, add(XXdS, ZZdS));
394   theOutInertia.Izz = add(theOutInertia.Izz, add(XXdS, YYdS));
395 }
396
397 //=======================================================================
398 //function : checkBounds
399 //purpose  : 
400 //=======================================================================
401 void BRepGProp_Gauss::checkBounds(const Standard_Real theU1,
402                                   const Standard_Real theU2,
403                                   const Standard_Real theV1,
404                                   const Standard_Real theV2)
405 {
406   if (Precision::IsInfinite(theU1) || Precision::IsInfinite(theU2) ||
407       Precision::IsInfinite(theV1) || Precision::IsInfinite(theV2))
408   {
409     add  = (::AddInf);
410     mult = (::MultInf);
411   }
412 }
413
414 //=======================================================================
415 //function : addAndRestoreInertia
416 //purpose  : 
417 //=======================================================================
418 void BRepGProp_Gauss::addAndRestoreInertia(
419   const BRepGProp_Gauss::Inertia& theInInertia,
420   BRepGProp_Gauss::Inertia&       theOutInertia)
421 {
422   theOutInertia.Mass = add(theOutInertia.Mass, theInInertia.Mass);
423   theOutInertia.Ix   = add(theOutInertia.Ix,   theInInertia.Ix);
424   theOutInertia.Iy   = add(theOutInertia.Iy,   theInInertia.Iy);
425   theOutInertia.Iz   = add(theOutInertia.Iz,   theInInertia.Iz);
426   theOutInertia.Ixx  = add(theOutInertia.Ixx,  theInInertia.Ixx);
427   theOutInertia.Iyy  = add(theOutInertia.Iyy,  theInInertia.Iyy);
428   theOutInertia.Izz  = add(theOutInertia.Izz,  theInInertia.Izz);
429   theOutInertia.Ixy  = add(theOutInertia.Ixy,  theInInertia.Ixy);
430   theOutInertia.Ixz  = add(theOutInertia.Ixz,  theInInertia.Ixz);
431   theOutInertia.Iyz  = add(theOutInertia.Iyz,  theInInertia.Iyz);
432 }
433
434 //=======================================================================
435 //function : multAndRestoreInertia
436 //purpose  : 
437 //=======================================================================
438 void BRepGProp_Gauss::multAndRestoreInertia(
439   const Standard_Real       theValue,
440   BRepGProp_Gauss::Inertia& theInOutInertia)
441 {
442   theInOutInertia.Mass = mult(theInOutInertia.Mass, theValue);
443   theInOutInertia.Ix   = mult(theInOutInertia.Ix,   theValue);
444   theInOutInertia.Iy   = mult(theInOutInertia.Iy,   theValue);
445   theInOutInertia.Iz   = mult(theInOutInertia.Iz,   theValue);
446   theInOutInertia.Ixx  = mult(theInOutInertia.Ixx,  theValue);
447   theInOutInertia.Iyy  = mult(theInOutInertia.Iyy,  theValue);
448   theInOutInertia.Izz  = mult(theInOutInertia.Izz,  theValue);
449   theInOutInertia.Ixy  = mult(theInOutInertia.Ixy,  theValue);
450   theInOutInertia.Ixz  = mult(theInOutInertia.Ixz,  theValue);
451   theInOutInertia.Iyz  = mult(theInOutInertia.Iyz,  theValue);
452 }
453
454 //=======================================================================
455 //function : convert
456 //purpose  : 
457 //=======================================================================
458 void BRepGProp_Gauss::convert(const BRepGProp_Gauss::Inertia& theInertia,
459                               gp_Pnt&                         theOutGravityCenter,
460                               gp_Mat&                         theOutMatrixOfInertia,
461                               Standard_Real&                  theOutMass)
462 {
463   if (Abs(theInertia.Mass) >= EPS_DIM)
464   {
465     const Standard_Real anInvMass = 1.0 / theInertia.Mass;
466     theOutGravityCenter.SetX(theInertia.Ix * anInvMass);
467     theOutGravityCenter.SetY(theInertia.Iy * anInvMass);
468     theOutGravityCenter.SetZ(theInertia.Iz * anInvMass);
469
470     theOutMass = theInertia.Mass;
471   }
472   else
473   {
474     theOutMass = 0.0;
475     theOutGravityCenter.SetCoord(0.0, 0.0, 0.0);
476   }
477
478   theOutMatrixOfInertia = gp_Mat(
479     gp_XYZ ( theInertia.Ixx, -theInertia.Ixy, -theInertia.Ixz),
480     gp_XYZ (-theInertia.Ixy,  theInertia.Iyy, -theInertia.Iyz),
481     gp_XYZ (-theInertia.Ixz, -theInertia.Iyz,  theInertia.Izz));
482 }
483
484 //=======================================================================
485 //function : convert
486 //purpose  : 
487 //=======================================================================
488 void BRepGProp_Gauss::convert(const BRepGProp_Gauss::Inertia& theInertia,
489                               const Standard_Real             theCoeff[],
490                               const Standard_Boolean          theIsByPoint,
491                               gp_Pnt&                         theOutGravityCenter,
492                               gp_Mat&                         theOutMatrixOfInertia,
493                               Standard_Real&                  theOutMass)
494 {
495   convert(theInertia, theOutGravityCenter, theOutMatrixOfInertia, theOutMass);
496   if (Abs(theInertia.Mass) >= EPS_DIM && theIsByPoint)
497   {
498     const Standard_Real anInvMass = 1.0 / theInertia.Mass;
499     if (theIsByPoint == Standard_True)
500     {
501       theOutGravityCenter.SetX(theCoeff[0] + theInertia.Ix * anInvMass);
502       theOutGravityCenter.SetY(theCoeff[1] + theInertia.Iy * anInvMass);
503       theOutGravityCenter.SetZ(theCoeff[2] + theInertia.Iz * anInvMass);
504     }
505     else
506     {
507       theOutGravityCenter.SetX(theInertia.Ix * anInvMass);
508       theOutGravityCenter.SetY(theInertia.Iy * anInvMass);
509       theOutGravityCenter.SetZ(theInertia.Iz * anInvMass);
510     }
511
512     theOutMass = theInertia.Mass;
513   }
514   else
515   {
516     theOutMass = 0.0;
517     theOutGravityCenter.SetCoord(0.0, 0.0, 0.0);
518   }
519
520   theOutMatrixOfInertia = gp_Mat(
521     gp_XYZ (theInertia.Ixx, theInertia.Ixy, theInertia.Ixz),
522     gp_XYZ (theInertia.Ixy, theInertia.Iyy, theInertia.Iyz),
523     gp_XYZ (theInertia.Ixz, theInertia.Iyz, theInertia.Izz));
524 }
525
526 //=======================================================================
527 //function : Compute
528 //purpose  : 
529 //=======================================================================
530 Standard_Real BRepGProp_Gauss::Compute(
531   BRepGProp_Face&        theSurface,
532   BRepGProp_Domain&      theDomain,
533   const gp_Pnt&          theLocation,
534   const Standard_Real    theEps,
535   const Standard_Real    theCoeff[],
536   const Standard_Boolean theIsByPoint,
537   Standard_Real&         theOutMass,
538   gp_Pnt&                theOutGravityCenter,
539   gp_Mat&                theOutInertia)
540 {
541   const Standard_Boolean isErrorCalculation  =
542     ( 0.0 > theEps || theEps < 0.001 ) ? Standard_True : Standard_False;
543   const Standard_Boolean isVerifyComputation =
544     ( 0.0 < theEps && theEps < 0.001 ) ? Standard_True : Standard_False;
545
546   Standard_Real anEpsilon= Abs(theEps);
547
548   BRepGProp_Gauss::Inertia anInertia;
549   InertiaArray anInertiaL = new NCollection_Array1<Inertia>(1, SM);
550   InertiaArray anInertiaU = new NCollection_Array1<Inertia>(1, SM);
551
552   // Prepare Gauss points and weights
553   NCollection_Handle<math_Vector> LGaussP[2];
554   NCollection_Handle<math_Vector> LGaussW[2];
555   NCollection_Handle<math_Vector> UGaussP[2];
556   NCollection_Handle<math_Vector> UGaussW[2];
557
558   const Standard_Integer aNbGaussPoint =
559     RealToInt(Ceiling(ERROR_ALGEBR_RATIO * GPM));
560
561   LGaussP[0] = new math_Vector(1, GPM);
562   LGaussP[1] = new math_Vector(1, aNbGaussPoint);
563   LGaussW[0] = new math_Vector(1, GPM);
564   LGaussW[1] = new math_Vector(1, aNbGaussPoint);
565
566   UGaussP[0] = new math_Vector(1, GPM);
567   UGaussP[1] = new math_Vector(1, aNbGaussPoint);
568   UGaussW[0] = new math_Vector(1, GPM);
569   UGaussW[1] = new math_Vector(1, aNbGaussPoint);
570
571   NCollection_Handle<math_Vector> L1 = new math_Vector(1, SM);
572   NCollection_Handle<math_Vector> L2 = new math_Vector(1, SM);
573   NCollection_Handle<math_Vector> U1 = new math_Vector(1, SM);
574   NCollection_Handle<math_Vector> U2 = new math_Vector(1, SM);
575
576   NCollection_Handle<math_Vector> ErrL  = new math_Vector(1, SM, 0.0);
577   NCollection_Handle<math_Vector> ErrU  = new math_Vector(1, SM, 0.0);
578   NCollection_Handle<math_Vector> ErrUL = new math_Vector(1, SM, 0.0);
579
580   // Face parametrization in U and V direction
581   Standard_Real BV1, BV2, BU1, BU2;
582   theSurface.Bounds(BU1, BU2, BV1, BV2);
583   checkBounds(BU1, BU2, BV1, BV2);
584
585   //
586   const Standard_Integer NumSubs = SUBS_POWER;
587   const TopoDS_Face& aF = theSurface.GetFace(); 
588   const Standard_Boolean isNaturalRestriction = (aF.NbChildren () == 0); //theSurface.NaturalRestriction();
589
590   Standard_Real CIx, CIy, CIz, CIxy, CIxz, CIyz;
591   Standard_Real CDim[2], CIxx[2], CIyy[2], CIzz[2];
592
593   // Boundary curve parametrization
594   Standard_Real u1 = BU1, u2, l1, l2, lm, lr, l, v;
595
596   // On the boundary curve u-v
597   gp_Pnt2d Puv;
598   gp_Vec2d Vuv;
599   Standard_Real Dul;  // Dul = Du / Dl
600
601   Standard_Integer iLS, iLSubEnd, iGL, iGLEnd, NbLGaussP[2], LRange[2], iL, kL, kLEnd, IL, JL;
602   Standard_Integer i, iUSubEnd, NbUGaussP[2], URange[2], kU, kUEnd, IU, JU;
603   Standard_Integer UMaxSubs, LMaxSubs;
604
605   Standard_Real ErrorU, ErrorL, ErrorLMax = 0.0, Eps = 0.0, EpsL = 0.0, EpsU = 0.0;
606   iGLEnd = isErrorCalculation ? 2 : 1;
607
608   NbUGaussP[0] = theSurface.SIntOrder(anEpsilon);
609   NbUGaussP[1] = RealToInt( Ceiling(ERROR_ALGEBR_RATIO * NbUGaussP[0]) );
610
611   math::GaussPoints (NbUGaussP[0], *UGaussP[0]);
612   math::GaussWeights(NbUGaussP[0], *UGaussW[0]);
613   math::GaussPoints (NbUGaussP[1], *UGaussP[1]);
614   math::GaussWeights(NbUGaussP[1], *UGaussW[1]);
615
616   const Standard_Integer aNbUSubs = theSurface.SUIntSubs();
617   TColStd_Array1OfReal UKnots(1, aNbUSubs + 1);
618   theSurface.UKnots(UKnots);
619
620   while (isNaturalRestriction || theDomain.More())
621   {
622     if (isNaturalRestriction)
623     {
624       NbLGaussP[0] = Min(2 * NbUGaussP[0], math::GaussPointsMax());
625     }
626     else
627     {
628       theSurface.Load(theDomain.Value());
629       NbLGaussP[0] = theSurface.LIntOrder(anEpsilon);
630     }
631
632     NbLGaussP[1] = RealToInt( Ceiling(ERROR_ALGEBR_RATIO * NbLGaussP[0]) );
633
634     math::GaussPoints (NbLGaussP[0], *LGaussP[0]);
635     math::GaussWeights(NbLGaussP[0], *LGaussW[0]);
636     math::GaussPoints (NbLGaussP[1], *LGaussP[1]);
637     math::GaussWeights(NbLGaussP[1], *LGaussW[1]);
638
639     const Standard_Integer aNbLSubs =
640       isNaturalRestriction ? theSurface.SVIntSubs(): theSurface.LIntSubs();
641     TColStd_Array1OfReal LKnots(1, aNbLSubs + 1);
642
643     if (isNaturalRestriction)
644     {
645       theSurface.VKnots(LKnots);
646       l1 = BV1;
647       l2 = BV2;
648     }
649     else
650     {
651       theSurface.LKnots(LKnots);
652       l1 = theSurface.FirstParameter();
653       l2 = theSurface.LastParameter();
654     }
655     ErrorL = 0.0;
656     kLEnd = 1; JL = 0;
657
658     if (Abs(l2 - l1) > EPS_PARAM)
659     {
660       iLSubEnd = FillIntervalBounds(l1, l2, LKnots, NumSubs, anInertiaL, L1, L2, ErrL, ErrUL);
661       LMaxSubs = BRepGProp_Gauss::MaxSubs(iLSubEnd);
662
663       if (LMaxSubs > SM)
664       {
665         LMaxSubs = SM;
666       }
667
668       BRepGProp_Gauss::InitMass(0.0, 1, LMaxSubs, anInertiaL);
669       BRepGProp_Gauss::Init(ErrL,  0.0, 1, LMaxSubs);
670       BRepGProp_Gauss::Init(ErrUL, 0.0, 1, LMaxSubs);
671
672       do // while: L
673       {
674         if (++JL > iLSubEnd)
675         {
676           LRange[0] = IL = ErrL->Max();
677           LRange[1] = JL;
678           L1->Value(JL) = (L1->Value(IL) + L2->Value(IL)) * 0.5;
679           L2->Value(JL) = L2->Value(IL);
680           L2->Value(IL) = L1->Value(JL);
681         }
682         else
683         {
684           LRange[0] = IL = JL;
685         }
686
687         if (JL == LMaxSubs || Abs(L2->Value(JL) - L1->Value(JL)) < EPS_PARAM)
688         {
689           if (kLEnd == 1)
690           {
691             anInertiaL->ChangeValue(JL).Reset();
692             ErrL->Value(JL) = 0.0;
693           }
694           else
695           {
696             --JL;
697             EpsL = ErrorL;
698             Eps = EpsL / 0.9;
699             break;
700           }
701         }
702         else
703         {
704           for (kL = 0; kL < kLEnd; kL++)
705           {
706             iLS = LRange[kL];
707             lm = 0.5 * (L2->Value(iLS) + L1->Value(iLS));
708             lr = 0.5 * (L2->Value(iLS) - L1->Value(iLS));
709
710             CIx = CIy = CIz = CIxy = CIxz = CIyz = 0.0;
711
712             for (iGL = 0; iGL < iGLEnd; ++iGL)
713             {
714               CDim[iGL] = CIxx[iGL] = CIyy[iGL] = CIzz[iGL] = 0.0;
715
716               for (iL = 1; iL <= NbLGaussP[iGL]; iL++)
717               {
718                 l = lm + lr * LGaussP[iGL]->Value(iL);
719                 if (isNaturalRestriction)
720                 {
721                   v = l;
722                   u2 = BU2;
723                   Dul = LGaussW[iGL]->Value(iL);
724                 }
725                 else
726                 {
727                   theSurface.D12d (l, Puv, Vuv);
728                   Dul = Vuv.Y() * LGaussW[iGL]->Value(iL);  // Dul = Du / Dl
729
730                   if (Abs(Dul) < EPS_PARAM)
731                     continue;
732
733                   v  = Puv.Y();
734                   u2 = Puv.X();
735
736                   // Check on cause out off bounds of value current parameter
737                   if (v < BV1)
738                     v = BV1;
739                   else if (v > BV2)
740                     v = BV2;
741
742                   if (u2 < BU1)
743                     u2 = BU1;
744                   else if (u2 > BU2)
745                     u2 = BU2;
746                 }
747
748                 ErrUL->Value(iLS) = 0.0;
749                 kUEnd = 1;
750                 JU = 0;
751
752                 if (Abs(u2 - u1) < EPS_PARAM)
753                   continue;
754
755                 NCollection_Handle<math_Vector> aDummy;
756                 iUSubEnd = FillIntervalBounds(u1, u2, UKnots, NumSubs, anInertiaU, U1, U2, ErrU, aDummy);
757                 UMaxSubs = BRepGProp_Gauss::MaxSubs(iUSubEnd);
758
759                 if (UMaxSubs > SM)
760                   UMaxSubs = SM;
761
762                 BRepGProp_Gauss::InitMass(0.0, 1, UMaxSubs, anInertiaU);
763                 BRepGProp_Gauss::Init(ErrU, 0.0, 1, UMaxSubs);
764                 ErrorU = 0.0;
765
766                 do
767                 {//while: U
768                   if (++JU > iUSubEnd)
769                   {
770                     URange[0] = IU = ErrU->Max();
771                     URange[1] = JU;
772
773                     U1->Value(JU) = (U1->Value(IU) + U2->Value(IU)) * 0.5;
774                     U2->Value(JU) = U2->Value(IU);
775                     U2->Value(IU) = U1->Value(JU);
776                   }
777                   else
778                     URange[0] = IU = JU;
779
780                   if (JU == UMaxSubs || Abs(U2->Value(JU) - U1->Value(JU)) < EPS_PARAM)
781                     if (kUEnd == 1)
782                     {
783                       ErrU->Value(JU) = 0.0;
784                       anInertiaU->ChangeValue(JU).Reset();
785                     }
786                     else
787                     {
788                       --JU;
789                       EpsU = ErrorU;
790                       Eps  = 10. * EpsU * Abs((u2 - u1) * Dul);
791                       EpsL = 0.9 * Eps;
792                       break;
793                     }
794                   else
795                   {
796                     gp_Pnt aPoint;
797                     gp_Vec aNormal;
798
799                     for (kU = 0; kU < kUEnd; ++kU)
800                     {
801                       BRepGProp_Gauss::Inertia aLocal[2];
802
803                       Standard_Integer iUS = URange[kU];
804                       const Standard_Integer aLength = iGLEnd - iGL;
805
806                       const Standard_Real um = 0.5 * (U2->Value(iUS) + U1->Value(iUS));
807                       const Standard_Real ur = 0.5 * (U2->Value(iUS) - U1->Value(iUS));
808
809                       for (Standard_Integer iGU = 0; iGU < aLength; ++iGU)
810                       {
811                         for (Standard_Integer iU = 1; iU <= NbUGaussP[iGU]; ++iU)
812                         {
813                           Standard_Real w = UGaussW[iGU]->Value(iU);
814                           const Standard_Real u = um + ur * UGaussP[iGU]->Value(iU);
815
816                           theSurface.Normal(u, v, aPoint, aNormal);
817
818                           if (myType == Vinert)
819                           {
820                             computeVInertiaOfElementaryPart(
821                               aPoint, aNormal, theLocation, w, theCoeff, theIsByPoint, aLocal[iGU]);
822                           }
823                           else
824                           {
825                             if (iGU > 0)
826                               aLocal[iGU].Mass += (w * aNormal.Magnitude());
827                             else
828                             {
829                               computeSInertiaOfElementaryPart(
830                                 aPoint, aNormal, theLocation, w, aLocal[iGU]);
831                             }
832                           }
833                         }
834                       }
835
836                       BRepGProp_Gauss::Inertia& anUI =
837                         anInertiaU->ChangeValue(iUS);
838
839                       anUI.Mass = mult(aLocal[0].Mass, ur);
840
841                       if (myType == Vinert)
842                       {
843                         anUI.Ixx = mult(aLocal[0].Ixx, ur);
844                         anUI.Iyy = mult(aLocal[0].Iyy, ur);
845                         anUI.Izz = mult(aLocal[0].Izz, ur);
846                       }
847
848                       if (iGL > 0)
849                         continue;
850
851                       Standard_Real aDMass = Abs(aLocal[1].Mass - aLocal[0].Mass);
852
853                       if (myType == Vinert)
854                       {
855                         aLocal[1].Ixx = Abs(aLocal[1].Ixx - aLocal[0].Ixx);
856                         aLocal[1].Iyy = Abs(aLocal[1].Iyy - aLocal[0].Iyy);
857                         aLocal[1].Izz = Abs(aLocal[1].Izz - aLocal[0].Izz);
858
859                         anUI.Ix = mult(aLocal[0].Ix, ur);
860                         anUI.Iy = mult(aLocal[0].Iy, ur);
861                         anUI.Iz = mult(aLocal[0].Iz, ur);
862
863                         anUI.Ixy = mult(aLocal[0].Ixy, ur);
864                         anUI.Ixz = mult(aLocal[0].Ixz, ur);
865                         anUI.Iyz = mult(aLocal[0].Iyz, ur);
866
867                         #ifndef IS_MIN_DIM
868                         aDMass = aLocal[1].Ixx + aLocal[1].Iyy + aLocal[1].Izz;
869                         #endif
870
871                         ErrU->Value(iUS) = mult(aDMass, ur);
872                       }
873                       else
874                       {
875                         anUI.Ix  = mult(aLocal[0].Ix,  ur);
876                         anUI.Iy  = mult(aLocal[0].Iy,  ur);
877                         anUI.Iz  = mult(aLocal[0].Iz,  ur);
878                         anUI.Ixx = mult(aLocal[0].Ixx, ur);
879                         anUI.Iyy = mult(aLocal[0].Iyy, ur);
880                         anUI.Izz = mult(aLocal[0].Izz, ur);
881                         anUI.Ixy = mult(aLocal[0].Ixy, ur);
882                         anUI.Ixz = mult(aLocal[0].Ixz, ur);
883                         anUI.Iyz = mult(aLocal[0].Iyz, ur);
884
885                         ErrU->Value(iUS) = mult(aDMass, ur);
886                       }
887                     }
888                   }
889
890                   if (JU == iUSubEnd)
891                   {
892                     kUEnd = 2;
893                     ErrorU = ErrU->Value(ErrU->Max());
894                   }
895                 } while ( (ErrorU - EpsU > 0.0 && EpsU != 0.0) || kUEnd == 1 );
896
897                 for (i = 1; i <= JU; ++i)
898                 {
899                   const BRepGProp_Gauss::Inertia& anIU =
900                     anInertiaU->Value(i);
901
902                   CDim[iGL] = add(CDim[iGL], mult(anIU.Mass, Dul));
903                   CIxx[iGL] = add(CIxx[iGL], mult(anIU.Ixx,  Dul));
904                   CIyy[iGL] = add(CIyy[iGL], mult(anIU.Iyy,  Dul));
905                   CIzz[iGL] = add(CIzz[iGL], mult(anIU.Izz,  Dul));
906                 }
907
908                 if (iGL > 0)
909                   continue;
910
911                 ErrUL->Value(iLS) = ErrorU * Abs((u2 - u1) * Dul);
912
913                 for (i = 1; i <= JU; ++i)
914                 {
915                   const BRepGProp_Gauss::Inertia& anIU =
916                     anInertiaU->Value(i);
917
918                   CIx = add(CIx, mult(anIU.Ix, Dul));
919                   CIy = add(CIy, mult(anIU.Iy, Dul));
920                   CIz = add(CIz, mult(anIU.Iz, Dul));
921
922                   CIxy = add(CIxy, mult(anIU.Ixy, Dul));
923                   CIxz = add(CIxz, mult(anIU.Ixz, Dul));
924                   CIyz = add(CIyz, mult(anIU.Iyz, Dul));
925                 }
926               }//for: iL
927             }//for: iGL
928
929             BRepGProp_Gauss::Inertia& aLI = anInertiaL->ChangeValue(iLS);
930
931             aLI.Mass = mult(CDim[0], lr);
932             aLI.Ixx  = mult(CIxx[0], lr);
933             aLI.Iyy  = mult(CIyy[0], lr);
934             aLI.Izz  = mult(CIzz[0], lr);
935
936             if (iGLEnd == 2)
937             {
938               Standard_Real aSubDim = Abs(CDim[1] - CDim[0]);
939
940               if (myType == Vinert)
941               {
942                 ErrorU = ErrUL->Value(iLS);
943
944                 CIxx[1] = Abs(CIxx[1] - CIxx[0]);
945                 CIyy[1] = Abs(CIyy[1] - CIyy[0]);
946                 CIzz[1] = Abs(CIzz[1] - CIzz[0]);
947
948                 #ifndef IS_MIN_DIM
949                 aSubDim = CIxx[1] + CIyy[1] + CIzz[1];
950                 #endif
951
952                 ErrL->Value(iLS) = add(mult(aSubDim, lr), ErrorU);
953               }
954               else
955               {
956                 ErrL->Value(iLS) = add(mult(aSubDim, lr), ErrUL->Value(iLS));
957               }
958             }
959
960             aLI.Ix = mult(CIx, lr);
961             aLI.Iy = mult(CIy, lr);
962             aLI.Iz = mult(CIz, lr);
963
964             aLI.Ixy = mult(CIxy, lr);
965             aLI.Ixz = mult(CIxz, lr);
966             aLI.Iyz = mult(CIyz, lr);
967           }//for: (kL)iLS
968         }
969
970         // Calculate/correct epsilon of computation by current value of dim
971         // That is need for not spend time for
972         if (JL == iLSubEnd)
973         {
974           kLEnd = 2;
975
976           Standard_Real DDim = 0.0;
977           for (i = 1; i <= JL; ++i)
978             DDim += anInertiaL->Value(i).Mass;
979
980           #ifndef IS_MIN_DIM
981           {
982             if (myType == Vinert)
983             {
984               Standard_Real DIxx = 0.0, DIyy = 0.0, DIzz = 0.0;
985               for (i = 1; i <= JL; ++i)
986               {
987                 const BRepGProp_Gauss::Inertia& aLocalL =
988                   anInertiaL->Value(i);
989
990                 DIxx += aLocalL.Ixx;
991                 DIyy += aLocalL.Iyy;
992                 DIzz += aLocalL.Izz;
993               }
994
995               DDim = Abs(DIxx) + Abs(DIyy) + Abs(DIzz);
996             }
997           }
998           #endif
999
1000           DDim = Abs(DDim * anEpsilon);
1001
1002           if (DDim > Eps)
1003           {
1004             Eps  = DDim;
1005             EpsL = 0.9 * Eps;
1006           }
1007         }
1008         if (kLEnd == 2)
1009         {
1010           ErrorL = ErrL->Value(ErrL->Max());
1011         }
1012       } while ( (ErrorL - EpsL > 0.0 && isVerifyComputation) || kLEnd == 1 );
1013
1014       for ( i = 1; i <= JL; i++ )
1015       {
1016         addAndRestoreInertia(anInertiaL->Value(i), anInertia);
1017       }
1018
1019       ErrorLMax = Max(ErrorLMax, ErrorL);
1020     }
1021
1022     if (isNaturalRestriction)
1023       break;
1024
1025     theDomain.Next();
1026   }
1027
1028   if (myType == Vinert)
1029     convert(anInertia, theCoeff, theIsByPoint, theOutGravityCenter, theOutInertia, theOutMass);
1030   else
1031     convert(anInertia, theOutGravityCenter, theOutInertia, theOutMass);
1032
1033   if (iGLEnd == 2)
1034   {
1035     if (theOutMass != 0.0)
1036     {
1037       Eps = ErrorLMax / Abs(theOutMass);
1038
1039       #ifndef IS_MIN_DIM
1040       {
1041         if (myType == Vinert)
1042           Eps = ErrorLMax / (Abs(anInertia.Ixx) +
1043                              Abs(anInertia.Iyy) +
1044                              Abs(anInertia.Izz));
1045       }
1046       #endif
1047     }
1048     else
1049     {
1050       Eps = 0.0;
1051     }
1052   }
1053   else
1054   {
1055     Eps = anEpsilon;
1056   }
1057
1058   return Eps;
1059 }
1060
1061 //=======================================================================
1062 //function : Compute
1063 //purpose  : 
1064 //=======================================================================
1065 Standard_Real BRepGProp_Gauss::Compute(BRepGProp_Face&     theSurface,
1066                                        BRepGProp_Domain&   theDomain,
1067                                        const gp_Pnt&       theLocation,
1068                                        const Standard_Real theEps,
1069                                        Standard_Real&      theOutMass,
1070                                        gp_Pnt&             theOutGravityCenter,
1071                                        gp_Mat&             theOutInertia)
1072 {
1073   Standard_ASSERT_RAISE(myType == Sinert, "BRepGProp_Gauss: Incorrect type");
1074
1075   return Compute(theSurface,
1076                  theDomain,
1077                  theLocation,
1078                  theEps,
1079                  NULL,
1080                  Standard_True,
1081                  theOutMass,
1082                  theOutGravityCenter,
1083                  theOutInertia);
1084 }
1085
1086 //=======================================================================
1087 //function : Compute
1088 //purpose  : 
1089 //=======================================================================
1090 void BRepGProp_Gauss::Compute(BRepGProp_Face&   theSurface,
1091                               BRepGProp_Domain& theDomain,
1092                               const gp_Pnt&     theLocation,
1093                               Standard_Real&    theOutMass,
1094                               gp_Pnt&           theOutGravityCenter,
1095                               gp_Mat&           theOutInertia)
1096 {
1097   Standard_ASSERT_RAISE(myType == Sinert, "BRepGProp_Gauss: Incorrect type");
1098
1099   Standard_Real u1, u2, v1, v2;
1100   theSurface.Bounds (u1, u2, v1, v2);
1101   checkBounds(u1, u2, v1, v2);
1102
1103   const Standard_Integer NbUGaussgp_Pnts =
1104     Min(theSurface.UIntegrationOrder(), math::GaussPointsMax());
1105
1106   const Standard_Integer NbVGaussgp_Pnts =
1107     Min(theSurface.VIntegrationOrder(), math::GaussPointsMax());
1108
1109   const Standard_Integer NbGaussgp_Pnts =
1110     Max(NbUGaussgp_Pnts, NbVGaussgp_Pnts);
1111
1112   // Number of Gauss points for the integration on the face
1113   math_Vector GaussSPV (1, NbGaussgp_Pnts);
1114   math_Vector GaussSWV (1, NbGaussgp_Pnts);
1115   math::GaussPoints (NbGaussgp_Pnts, GaussSPV);
1116   math::GaussWeights(NbGaussgp_Pnts, GaussSWV);
1117
1118   BRepGProp_Gauss::Inertia anInertia;
1119   while (theDomain.More())
1120   {
1121     theSurface.Load(theDomain.Value());
1122
1123     Standard_Integer NbCGaussgp_Pnts =
1124       Min(theSurface.IntegrationOrder(), math::GaussPointsMax());
1125
1126     NbCGaussgp_Pnts = Max(NbCGaussgp_Pnts, NbGaussgp_Pnts);
1127
1128     math_Vector GaussCP(1, NbCGaussgp_Pnts);
1129     math_Vector GaussCW(1, NbCGaussgp_Pnts);
1130     math::GaussPoints (NbCGaussgp_Pnts, GaussCP);
1131     math::GaussWeights(NbCGaussgp_Pnts, GaussCW);
1132
1133     
1134     const Standard_Real l1 = theSurface.FirstParameter();
1135     const Standard_Real l2 = theSurface.LastParameter ();
1136     const Standard_Real lm = 0.5 * (l2 + l1);
1137     const Standard_Real lr = 0.5 * (l2 - l1);
1138
1139     BRepGProp_Gauss::Inertia aCInertia;
1140     for (Standard_Integer i = 1; i <= NbCGaussgp_Pnts; ++i)
1141     {
1142       const Standard_Real l = lm + lr * GaussCP(i);
1143
1144       gp_Pnt2d Puv;
1145       gp_Vec2d Vuv;
1146       theSurface.D12d(l, Puv, Vuv);
1147
1148       const Standard_Real v = Puv.Y();
1149       u2  = Puv.X();
1150
1151       const Standard_Real Dul = Vuv.Y() * GaussCW(i);
1152       const Standard_Real um  = 0.5 * (u2 + u1);
1153       const Standard_Real ur  = 0.5 * (u2 - u1);
1154
1155       BRepGProp_Gauss::Inertia aLocalInertia;
1156       for (Standard_Integer j = 1; j <= NbGaussgp_Pnts; ++j)
1157       {
1158         const Standard_Real u = add(um, mult(ur, GaussSPV(j)));
1159         const Standard_Real aWeight = Dul * GaussSWV(j);
1160
1161         gp_Pnt aPoint;
1162         gp_Vec aNormal;
1163         theSurface.Normal (u, v, aPoint, aNormal);
1164
1165         computeSInertiaOfElementaryPart(aPoint, aNormal, theLocation, aWeight, aLocalInertia);
1166       }
1167
1168       multAndRestoreInertia(ur, aLocalInertia);
1169       addAndRestoreInertia (aLocalInertia, aCInertia);
1170     }
1171
1172     multAndRestoreInertia(lr, aCInertia);
1173     addAndRestoreInertia (aCInertia, anInertia);
1174
1175     theDomain.Next();
1176   }
1177
1178   convert(anInertia, theOutGravityCenter, theOutInertia, theOutMass);
1179 }
1180
1181 //=======================================================================
1182 //function : Compute
1183 //purpose  : 
1184 //=======================================================================
1185 void BRepGProp_Gauss::Compute(BRepGProp_Face&         theSurface,
1186                               BRepGProp_Domain&       theDomain,
1187                               const gp_Pnt&           theLocation,
1188                               const Standard_Real     theCoeff[],
1189                               const Standard_Boolean  theIsByPoint,
1190                               Standard_Real&          theOutMass,
1191                               gp_Pnt&                 theOutGravityCenter,
1192                               gp_Mat&                 theOutInertia)
1193 {
1194   Standard_ASSERT_RAISE(myType == Vinert, "BRepGProp_Gauss: Incorrect type");
1195
1196   Standard_Real u1, v1, u2, v2;
1197   theSurface.Bounds (u1, u2, v1, v2);
1198   checkBounds(u1, u2, v1, v2);
1199
1200   Standard_Real _u2 = u2;  //OCC104
1201
1202   BRepGProp_Gauss::Inertia anInertia;
1203   while (theDomain.More())
1204   {
1205     theSurface.Load(theDomain.Value());
1206
1207     const Standard_Integer aVNbCGaussgp_Pnts =
1208       theSurface.VIntegrationOrder();
1209
1210     const Standard_Integer aNbGaussgp_Pnts =
1211       Min( Max(theSurface.IntegrationOrder(), aVNbCGaussgp_Pnts), math::GaussPointsMax() );
1212
1213     math_Vector GaussP(1, aNbGaussgp_Pnts);
1214     math_Vector GaussW(1, aNbGaussgp_Pnts);
1215     math::GaussPoints (aNbGaussgp_Pnts, GaussP);
1216     math::GaussWeights(aNbGaussgp_Pnts, GaussW);
1217
1218     const Standard_Real l1 = theSurface.FirstParameter();
1219     const Standard_Real l2 = theSurface.LastParameter();
1220     const Standard_Real lm = 0.5 * (l2 + l1);
1221     const Standard_Real lr = 0.5 * (l2 - l1);
1222
1223     BRepGProp_Gauss::Inertia aCInertia;
1224     for (Standard_Integer i = 1; i <= aNbGaussgp_Pnts; ++i)
1225     {
1226       const Standard_Real l = lm + lr * GaussP(i);
1227
1228       gp_Pnt2d Puv;
1229       gp_Vec2d Vuv;
1230
1231       theSurface.D12d(l, Puv, Vuv);
1232
1233       u2  = Puv.X();
1234       u2 = Min( Max(u1, u2), _u2 ); // OCC104
1235       const Standard_Real v = Min(Max(Puv.Y(), v1), v2);
1236
1237       const Standard_Real Dul = Vuv.Y() * GaussW(i);
1238       const Standard_Real um  = 0.5 * (u2 + u1);
1239       const Standard_Real ur  = 0.5 * (u2 - u1);
1240
1241       BRepGProp_Gauss::Inertia aLocalInertia;
1242       for (Standard_Integer j = 1; j <= aNbGaussgp_Pnts; ++j)
1243       {
1244         const Standard_Real u = um + ur * GaussP(j);
1245         const Standard_Real aWeight = Dul * GaussW(j);
1246
1247         gp_Pnt aPoint;
1248         gp_Vec aNormal;
1249
1250         theSurface.Normal(u, v, aPoint, aNormal);
1251
1252         computeVInertiaOfElementaryPart(
1253           aPoint,
1254           aNormal,
1255           theLocation,
1256           aWeight,
1257           theCoeff,
1258           theIsByPoint,
1259           aLocalInertia);
1260       }
1261
1262       multAndRestoreInertia(ur, aLocalInertia);
1263       addAndRestoreInertia (aLocalInertia, aCInertia);
1264     }
1265
1266     multAndRestoreInertia(lr,        aCInertia);
1267     addAndRestoreInertia (aCInertia, anInertia);
1268
1269     theDomain.Next();
1270   }
1271
1272   convert(anInertia, theCoeff, theIsByPoint, theOutGravityCenter, theOutInertia, theOutMass);
1273 }
1274
1275 //=======================================================================
1276 //function : Compute
1277 //purpose  : 
1278 //=======================================================================
1279 void BRepGProp_Gauss::Compute(const BRepGProp_Face&  theSurface,
1280                               const gp_Pnt&          theLocation,
1281                               const Standard_Real    theCoeff[],
1282                               const Standard_Boolean theIsByPoint,
1283                               Standard_Real&         theOutMass,
1284                               gp_Pnt&                theOutGravityCenter,
1285                               gp_Mat&                theOutInertia)
1286 {
1287   Standard_Real LowerU, UpperU, LowerV, UpperV;
1288   theSurface.Bounds(LowerU, UpperU, LowerV, UpperV);
1289   checkBounds(LowerU, UpperU, LowerV, UpperV);
1290
1291   const Standard_Integer UOrder =
1292     Min(theSurface.UIntegrationOrder(), math::GaussPointsMax());
1293   const Standard_Integer VOrder =
1294     Min(theSurface.VIntegrationOrder(), math::GaussPointsMax());
1295
1296   // Gauss points and weights
1297   math_Vector GaussPU(1, UOrder);
1298   math_Vector GaussWU(1, UOrder);
1299   math_Vector GaussPV(1, VOrder);
1300   math_Vector GaussWV(1, VOrder);
1301
1302   math::GaussPoints (UOrder, GaussPU);
1303   math::GaussWeights(UOrder, GaussWU);
1304   math::GaussPoints (VOrder, GaussPV);
1305   math::GaussWeights(VOrder, GaussWV);
1306
1307   const Standard_Real um = 0.5 * add(UpperU,  LowerU);
1308   const Standard_Real vm = 0.5 * add(UpperV,  LowerV);
1309   Standard_Real ur = 0.5 * add(UpperU, -LowerU);
1310   Standard_Real vr = 0.5 * add(UpperV, -LowerV);
1311
1312   gp_Pnt aPoint;
1313   gp_Vec aNormal;
1314
1315   BRepGProp_Gauss::Inertia anInertia;
1316   for (Standard_Integer j = 1; j <= VOrder; ++j)
1317   {
1318     BRepGProp_Gauss::Inertia anInertiaOfElementaryPart;
1319     const Standard_Real v = add(vm, mult(vr, GaussPV(j)));
1320
1321     for (Standard_Integer i = 1; i <= UOrder; ++i)
1322     {
1323       const Standard_Real aWeight = GaussWU(i);
1324       const Standard_Real u = add(um, mult(ur, GaussPU (i)));
1325       theSurface.Normal(u, v, aPoint, aNormal);
1326
1327       if (myType == Vinert)
1328       {
1329         computeVInertiaOfElementaryPart(
1330           aPoint,
1331           aNormal,
1332           theLocation,
1333           aWeight,
1334           theCoeff,
1335           theIsByPoint,
1336           anInertiaOfElementaryPart);
1337       }
1338       else // Sinert
1339       {
1340         computeSInertiaOfElementaryPart(
1341           aPoint,
1342           aNormal,
1343           theLocation,
1344           aWeight,
1345           anInertiaOfElementaryPart);
1346       }
1347     }
1348
1349     multAndRestoreInertia(GaussWV(j), anInertiaOfElementaryPart);
1350     addAndRestoreInertia (anInertiaOfElementaryPart,  anInertia);
1351   }
1352   vr            = mult(vr, ur);
1353   anInertia.Ixx = mult(vr, anInertia.Ixx);
1354   anInertia.Iyy = mult(vr, anInertia.Iyy);
1355   anInertia.Izz = mult(vr, anInertia.Izz);
1356   anInertia.Ixy = mult(vr, anInertia.Ixy);
1357   anInertia.Ixz = mult(vr, anInertia.Ixz);
1358   anInertia.Iyz = mult(vr, anInertia.Iyz);
1359
1360   if (myType == Vinert)
1361   {
1362     convert(anInertia, theCoeff, theIsByPoint, theOutGravityCenter, theOutInertia, theOutMass);
1363   }
1364   else // Sinert
1365   {
1366     convert(anInertia, theOutGravityCenter, theOutInertia, theOutMass);
1367   }
1368
1369   theOutMass *= vr;
1370 }
1371
1372 //=======================================================================
1373 //function : Compute
1374 //purpose  : 
1375 //=======================================================================
1376 void BRepGProp_Gauss::Compute(const BRepGProp_Face& theSurface,
1377                               const gp_Pnt&         theLocation,
1378                               Standard_Real&        theOutMass,
1379                               gp_Pnt&               theOutGravityCenter,
1380                               gp_Mat&               theOutInertia)
1381 {
1382   Standard_ASSERT_RAISE(myType == Sinert, "BRepGProp_Gauss: Incorrect type");
1383
1384   Compute(theSurface,
1385           theLocation,
1386           NULL,
1387           Standard_True,
1388           theOutMass,
1389           theOutGravityCenter,
1390           theOutInertia);
1391 }