0028643: Coding rules - eliminate GCC compiler warnings -Wmisleading-indentation
[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   TopoDS_Iterator aWIter(aF);
589   const Standard_Boolean isNaturalRestriction = !aWIter.More(); //theSurface.NaturalRestriction();
590
591   Standard_Real CIx, CIy, CIz, CIxy, CIxz, CIyz;
592   Standard_Real CDim[2], CIxx[2], CIyy[2], CIzz[2];
593
594   // Boundary curve parametrization
595   Standard_Real u1 = BU1, u2, l1, l2, lm, lr, l, v;
596
597   // On the boundary curve u-v
598   gp_Pnt2d Puv;
599   gp_Vec2d Vuv;
600   Standard_Real Dul;  // Dul = Du / Dl
601
602   Standard_Integer iLS, iLSubEnd, iGL, iGLEnd, NbLGaussP[2], LRange[2], iL, kL, kLEnd, IL, JL;
603   Standard_Integer i, iUSubEnd, NbUGaussP[2], URange[2], kU, kUEnd, IU, JU;
604   Standard_Integer UMaxSubs, LMaxSubs;
605
606   Standard_Real ErrorU, ErrorL, ErrorLMax = 0.0, Eps = 0.0, EpsL = 0.0, EpsU = 0.0;
607   iGLEnd = isErrorCalculation ? 2 : 1;
608
609   NbUGaussP[0] = theSurface.SIntOrder(anEpsilon);
610   NbUGaussP[1] = RealToInt( Ceiling(ERROR_ALGEBR_RATIO * NbUGaussP[0]) );
611
612   math::GaussPoints (NbUGaussP[0], *UGaussP[0]);
613   math::GaussWeights(NbUGaussP[0], *UGaussW[0]);
614   math::GaussPoints (NbUGaussP[1], *UGaussP[1]);
615   math::GaussWeights(NbUGaussP[1], *UGaussW[1]);
616
617   const Standard_Integer aNbUSubs = theSurface.SUIntSubs();
618   TColStd_Array1OfReal UKnots(1, aNbUSubs + 1);
619   theSurface.UKnots(UKnots);
620
621   while (isNaturalRestriction || theDomain.More())
622   {
623     if (isNaturalRestriction)
624     {
625       NbLGaussP[0] = Min(2 * NbUGaussP[0], math::GaussPointsMax());
626     }
627     else
628     {
629       theSurface.Load(theDomain.Value());
630       NbLGaussP[0] = theSurface.LIntOrder(anEpsilon);
631     }
632
633     NbLGaussP[1] = RealToInt( Ceiling(ERROR_ALGEBR_RATIO * NbLGaussP[0]) );
634
635     math::GaussPoints (NbLGaussP[0], *LGaussP[0]);
636     math::GaussWeights(NbLGaussP[0], *LGaussW[0]);
637     math::GaussPoints (NbLGaussP[1], *LGaussP[1]);
638     math::GaussWeights(NbLGaussP[1], *LGaussW[1]);
639
640     const Standard_Integer aNbLSubs =
641       isNaturalRestriction ? theSurface.SVIntSubs(): theSurface.LIntSubs();
642     TColStd_Array1OfReal LKnots(1, aNbLSubs + 1);
643
644     if (isNaturalRestriction)
645     {
646       theSurface.VKnots(LKnots);
647       l1 = BV1;
648       l2 = BV2;
649     }
650     else
651     {
652       theSurface.LKnots(LKnots);
653       l1 = theSurface.FirstParameter();
654       l2 = theSurface.LastParameter();
655     }
656     ErrorL = 0.0;
657     kLEnd = 1; JL = 0;
658
659     if (Abs(l2 - l1) > EPS_PARAM)
660     {
661       iLSubEnd = FillIntervalBounds(l1, l2, LKnots, NumSubs, anInertiaL, L1, L2, ErrL, ErrUL);
662       LMaxSubs = BRepGProp_Gauss::MaxSubs(iLSubEnd);
663
664       if (LMaxSubs > SM)
665       {
666         LMaxSubs = SM;
667       }
668
669       BRepGProp_Gauss::InitMass(0.0, 1, LMaxSubs, anInertiaL);
670       BRepGProp_Gauss::Init(ErrL,  0.0, 1, LMaxSubs);
671       BRepGProp_Gauss::Init(ErrUL, 0.0, 1, LMaxSubs);
672
673       do // while: L
674       {
675         if (++JL > iLSubEnd)
676         {
677           LRange[0] = IL = ErrL->Max();
678           LRange[1] = JL;
679           L1->Value(JL) = (L1->Value(IL) + L2->Value(IL)) * 0.5;
680           L2->Value(JL) = L2->Value(IL);
681           L2->Value(IL) = L1->Value(JL);
682         }
683         else
684         {
685           LRange[0] = IL = JL;
686         }
687
688         if (JL == LMaxSubs || Abs(L2->Value(JL) - L1->Value(JL)) < EPS_PARAM)
689         {
690           if (kLEnd == 1)
691           {
692             anInertiaL->ChangeValue(JL).Reset();
693             ErrL->Value(JL) = 0.0;
694           }
695           else
696           {
697             --JL;
698             EpsL = ErrorL;
699             Eps = EpsL / 0.9;
700             break;
701           }
702         }
703         else
704         {
705           for (kL = 0; kL < kLEnd; kL++)
706           {
707             iLS = LRange[kL];
708             lm = 0.5 * (L2->Value(iLS) + L1->Value(iLS));
709             lr = 0.5 * (L2->Value(iLS) - L1->Value(iLS));
710
711             CIx = CIy = CIz = CIxy = CIxz = CIyz = 0.0;
712
713             for (iGL = 0; iGL < iGLEnd; ++iGL)
714             {
715               CDim[iGL] = CIxx[iGL] = CIyy[iGL] = CIzz[iGL] = 0.0;
716
717               for (iL = 1; iL <= NbLGaussP[iGL]; iL++)
718               {
719                 l = lm + lr * LGaussP[iGL]->Value(iL);
720                 if (isNaturalRestriction)
721                 {
722                   v = l;
723                   u2 = BU2;
724                   Dul = LGaussW[iGL]->Value(iL);
725                 }
726                 else
727                 {
728                   theSurface.D12d (l, Puv, Vuv);
729                   Dul = Vuv.Y() * LGaussW[iGL]->Value(iL);  // Dul = Du / Dl
730
731                   if (Abs(Dul) < EPS_PARAM)
732                     continue;
733
734                   v  = Puv.Y();
735                   u2 = Puv.X();
736
737                   // Check on cause out off bounds of value current parameter
738                   if (v < BV1)
739                     v = BV1;
740                   else if (v > BV2)
741                     v = BV2;
742
743                   if (u2 < BU1)
744                     u2 = BU1;
745                   else if (u2 > BU2)
746                     u2 = BU2;
747                 }
748
749                 ErrUL->Value(iLS) = 0.0;
750                 kUEnd = 1;
751                 JU = 0;
752
753                 if (Abs(u2 - u1) < EPS_PARAM)
754                   continue;
755
756                 NCollection_Handle<math_Vector> aDummy;
757                 iUSubEnd = FillIntervalBounds(u1, u2, UKnots, NumSubs, anInertiaU, U1, U2, ErrU, aDummy);
758                 UMaxSubs = BRepGProp_Gauss::MaxSubs(iUSubEnd);
759
760                 if (UMaxSubs > SM)
761                   UMaxSubs = SM;
762
763                 BRepGProp_Gauss::InitMass(0.0, 1, UMaxSubs, anInertiaU);
764                 BRepGProp_Gauss::Init(ErrU, 0.0, 1, UMaxSubs);
765                 ErrorU = 0.0;
766
767                 do
768                 {//while: U
769                   if (++JU > iUSubEnd)
770                   {
771                     URange[0] = IU = ErrU->Max();
772                     URange[1] = JU;
773
774                     U1->Value(JU) = (U1->Value(IU) + U2->Value(IU)) * 0.5;
775                     U2->Value(JU) = U2->Value(IU);
776                     U2->Value(IU) = U1->Value(JU);
777                   }
778                   else
779                     URange[0] = IU = JU;
780
781                   if (JU == UMaxSubs || Abs(U2->Value(JU) - U1->Value(JU)) < EPS_PARAM)
782                     if (kUEnd == 1)
783                     {
784                       ErrU->Value(JU) = 0.0;
785                       anInertiaU->ChangeValue(JU).Reset();
786                     }
787                     else
788                     {
789                       --JU;
790                       EpsU = ErrorU;
791                       Eps  = 10. * EpsU * Abs((u2 - u1) * Dul);
792                       EpsL = 0.9 * Eps;
793                       break;
794                     }
795                   else
796                   {
797                     gp_Pnt aPoint;
798                     gp_Vec aNormal;
799
800                     for (kU = 0; kU < kUEnd; ++kU)
801                     {
802                       BRepGProp_Gauss::Inertia aLocal[2];
803
804                       Standard_Integer iUS = URange[kU];
805                       const Standard_Integer aLength = iGLEnd - iGL;
806
807                       const Standard_Real um = 0.5 * (U2->Value(iUS) + U1->Value(iUS));
808                       const Standard_Real ur = 0.5 * (U2->Value(iUS) - U1->Value(iUS));
809
810                       for (Standard_Integer iGU = 0; iGU < aLength; ++iGU)
811                       {
812                         for (Standard_Integer iU = 1; iU <= NbUGaussP[iGU]; ++iU)
813                         {
814                           Standard_Real w = UGaussW[iGU]->Value(iU);
815                           const Standard_Real u = um + ur * UGaussP[iGU]->Value(iU);
816
817                           theSurface.Normal(u, v, aPoint, aNormal);
818
819                           if (myType == Vinert)
820                           {
821                             computeVInertiaOfElementaryPart(
822                               aPoint, aNormal, theLocation, w, theCoeff, theIsByPoint, aLocal[iGU]);
823                           }
824                           else
825                           {
826                             if (iGU > 0)
827                               aLocal[iGU].Mass += (w * aNormal.Magnitude());
828                             else
829                             {
830                               computeSInertiaOfElementaryPart(
831                                 aPoint, aNormal, theLocation, w, aLocal[iGU]);
832                             }
833                           }
834                         }
835                       }
836
837                       BRepGProp_Gauss::Inertia& anUI =
838                         anInertiaU->ChangeValue(iUS);
839
840                       anUI.Mass = mult(aLocal[0].Mass, ur);
841
842                       if (myType == Vinert)
843                       {
844                         anUI.Ixx = mult(aLocal[0].Ixx, ur);
845                         anUI.Iyy = mult(aLocal[0].Iyy, ur);
846                         anUI.Izz = mult(aLocal[0].Izz, ur);
847                       }
848
849                       if (iGL > 0)
850                         continue;
851
852                       Standard_Real aDMass = Abs(aLocal[1].Mass - aLocal[0].Mass);
853
854                       if (myType == Vinert)
855                       {
856                         aLocal[1].Ixx = Abs(aLocal[1].Ixx - aLocal[0].Ixx);
857                         aLocal[1].Iyy = Abs(aLocal[1].Iyy - aLocal[0].Iyy);
858                         aLocal[1].Izz = Abs(aLocal[1].Izz - aLocal[0].Izz);
859
860                         anUI.Ix = mult(aLocal[0].Ix, ur);
861                         anUI.Iy = mult(aLocal[0].Iy, ur);
862                         anUI.Iz = mult(aLocal[0].Iz, ur);
863
864                         anUI.Ixy = mult(aLocal[0].Ixy, ur);
865                         anUI.Ixz = mult(aLocal[0].Ixz, ur);
866                         anUI.Iyz = mult(aLocal[0].Iyz, ur);
867
868                         #ifndef IS_MIN_DIM
869                         aDMass = aLocal[1].Ixx + aLocal[1].Iyy + aLocal[1].Izz;
870                         #endif
871
872                         ErrU->Value(iUS) = mult(aDMass, ur);
873                       }
874                       else
875                       {
876                         anUI.Ix  = mult(aLocal[0].Ix,  ur);
877                         anUI.Iy  = mult(aLocal[0].Iy,  ur);
878                         anUI.Iz  = mult(aLocal[0].Iz,  ur);
879                         anUI.Ixx = mult(aLocal[0].Ixx, ur);
880                         anUI.Iyy = mult(aLocal[0].Iyy, ur);
881                         anUI.Izz = mult(aLocal[0].Izz, ur);
882                         anUI.Ixy = mult(aLocal[0].Ixy, ur);
883                         anUI.Ixz = mult(aLocal[0].Ixz, ur);
884                         anUI.Iyz = mult(aLocal[0].Iyz, ur);
885
886                         ErrU->Value(iUS) = mult(aDMass, ur);
887                       }
888                     }
889                   }
890
891                   if (JU == iUSubEnd)
892                   {
893                     kUEnd = 2;
894                     ErrorU = ErrU->Value(ErrU->Max());
895                   }
896                 } while ( (ErrorU - EpsU > 0.0 && EpsU != 0.0) || kUEnd == 1 );
897
898                 for (i = 1; i <= JU; ++i)
899                 {
900                   const BRepGProp_Gauss::Inertia& anIU =
901                     anInertiaU->Value(i);
902
903                   CDim[iGL] = add(CDim[iGL], mult(anIU.Mass, Dul));
904                   CIxx[iGL] = add(CIxx[iGL], mult(anIU.Ixx,  Dul));
905                   CIyy[iGL] = add(CIyy[iGL], mult(anIU.Iyy,  Dul));
906                   CIzz[iGL] = add(CIzz[iGL], mult(anIU.Izz,  Dul));
907                 }
908
909                 if (iGL > 0)
910                   continue;
911
912                 ErrUL->Value(iLS) = ErrorU * Abs((u2 - u1) * Dul);
913
914                 for (i = 1; i <= JU; ++i)
915                 {
916                   const BRepGProp_Gauss::Inertia& anIU =
917                     anInertiaU->Value(i);
918
919                   CIx = add(CIx, mult(anIU.Ix, Dul));
920                   CIy = add(CIy, mult(anIU.Iy, Dul));
921                   CIz = add(CIz, mult(anIU.Iz, Dul));
922
923                   CIxy = add(CIxy, mult(anIU.Ixy, Dul));
924                   CIxz = add(CIxz, mult(anIU.Ixz, Dul));
925                   CIyz = add(CIyz, mult(anIU.Iyz, Dul));
926                 }
927               }//for: iL
928             }//for: iGL
929
930             BRepGProp_Gauss::Inertia& aLI = anInertiaL->ChangeValue(iLS);
931
932             aLI.Mass = mult(CDim[0], lr);
933             aLI.Ixx  = mult(CIxx[0], lr);
934             aLI.Iyy  = mult(CIyy[0], lr);
935             aLI.Izz  = mult(CIzz[0], lr);
936
937             if (iGLEnd == 2)
938             {
939               Standard_Real aSubDim = Abs(CDim[1] - CDim[0]);
940
941               if (myType == Vinert)
942               {
943                 ErrorU = ErrUL->Value(iLS);
944
945                 CIxx[1] = Abs(CIxx[1] - CIxx[0]);
946                 CIyy[1] = Abs(CIyy[1] - CIyy[0]);
947                 CIzz[1] = Abs(CIzz[1] - CIzz[0]);
948
949                 #ifndef IS_MIN_DIM
950                 aSubDim = CIxx[1] + CIyy[1] + CIzz[1];
951                 #endif
952
953                 ErrL->Value(iLS) = add(mult(aSubDim, lr), ErrorU);
954               }
955               else
956               {
957                 ErrL->Value(iLS) = add(mult(aSubDim, lr), ErrUL->Value(iLS));
958               }
959             }
960
961             aLI.Ix = mult(CIx, lr);
962             aLI.Iy = mult(CIy, lr);
963             aLI.Iz = mult(CIz, lr);
964
965             aLI.Ixy = mult(CIxy, lr);
966             aLI.Ixz = mult(CIxz, lr);
967             aLI.Iyz = mult(CIyz, lr);
968           }//for: (kL)iLS
969         }
970
971         // Calculate/correct epsilon of computation by current value of dim
972         // That is need for not spend time for
973         if (JL == iLSubEnd)
974         {
975           kLEnd = 2;
976
977           Standard_Real DDim = 0.0;
978           for (i = 1; i <= JL; ++i)
979             DDim += anInertiaL->Value(i).Mass;
980
981           #ifndef IS_MIN_DIM
982           {
983             if (myType == Vinert)
984             {
985               Standard_Real DIxx = 0.0, DIyy = 0.0, DIzz = 0.0;
986               for (i = 1; i <= JL; ++i)
987               {
988                 const BRepGProp_Gauss::Inertia& aLocalL =
989                   anInertiaL->Value(i);
990
991                 DIxx += aLocalL.Ixx;
992                 DIyy += aLocalL.Iyy;
993                 DIzz += aLocalL.Izz;
994               }
995
996               DDim = Abs(DIxx) + Abs(DIyy) + Abs(DIzz);
997             }
998           }
999           #endif
1000
1001           DDim = Abs(DDim * anEpsilon);
1002
1003           if (DDim > Eps)
1004           {
1005             Eps  = DDim;
1006             EpsL = 0.9 * Eps;
1007           }
1008         }
1009         if (kLEnd == 2)
1010         {
1011           ErrorL = ErrL->Value(ErrL->Max());
1012         }
1013       } while ( (ErrorL - EpsL > 0.0 && isVerifyComputation) || kLEnd == 1 );
1014
1015       for ( i = 1; i <= JL; i++ )
1016       {
1017         addAndRestoreInertia(anInertiaL->Value(i), anInertia);
1018       }
1019
1020       ErrorLMax = Max(ErrorLMax, ErrorL);
1021     }
1022
1023     if (isNaturalRestriction)
1024       break;
1025
1026     theDomain.Next();
1027   }
1028
1029   if (myType == Vinert)
1030     convert(anInertia, theCoeff, theIsByPoint, theOutGravityCenter, theOutInertia, theOutMass);
1031   else
1032     convert(anInertia, theOutGravityCenter, theOutInertia, theOutMass);
1033
1034   if (iGLEnd == 2)
1035   {
1036     if (theOutMass != 0.0)
1037     {
1038       Eps = ErrorLMax / Abs(theOutMass);
1039
1040       #ifndef IS_MIN_DIM
1041       {
1042         if (myType == Vinert)
1043           Eps = ErrorLMax / (Abs(anInertia.Ixx) +
1044                              Abs(anInertia.Iyy) +
1045                              Abs(anInertia.Izz));
1046       }
1047       #endif
1048     }
1049     else
1050     {
1051       Eps = 0.0;
1052     }
1053   }
1054   else
1055   {
1056     Eps = anEpsilon;
1057   }
1058
1059   return Eps;
1060 }
1061
1062 //=======================================================================
1063 //function : Compute
1064 //purpose  : 
1065 //=======================================================================
1066 Standard_Real BRepGProp_Gauss::Compute(BRepGProp_Face&     theSurface,
1067                                        BRepGProp_Domain&   theDomain,
1068                                        const gp_Pnt&       theLocation,
1069                                        const Standard_Real theEps,
1070                                        Standard_Real&      theOutMass,
1071                                        gp_Pnt&             theOutGravityCenter,
1072                                        gp_Mat&             theOutInertia)
1073 {
1074   Standard_ASSERT_RAISE(myType == Sinert, "BRepGProp_Gauss: Incorrect type");
1075
1076   return Compute(theSurface,
1077                  theDomain,
1078                  theLocation,
1079                  theEps,
1080                  NULL,
1081                  Standard_True,
1082                  theOutMass,
1083                  theOutGravityCenter,
1084                  theOutInertia);
1085 }
1086
1087 //=======================================================================
1088 //function : Compute
1089 //purpose  : 
1090 //=======================================================================
1091 void BRepGProp_Gauss::Compute(BRepGProp_Face&   theSurface,
1092                               BRepGProp_Domain& theDomain,
1093                               const gp_Pnt&     theLocation,
1094                               Standard_Real&    theOutMass,
1095                               gp_Pnt&           theOutGravityCenter,
1096                               gp_Mat&           theOutInertia)
1097 {
1098   Standard_ASSERT_RAISE(myType == Sinert, "BRepGProp_Gauss: Incorrect type");
1099
1100   Standard_Real u1, u2, v1, v2;
1101   theSurface.Bounds (u1, u2, v1, v2);
1102   checkBounds(u1, u2, v1, v2);
1103
1104   const Standard_Integer NbUGaussgp_Pnts =
1105     Min(theSurface.UIntegrationOrder(), math::GaussPointsMax());
1106
1107   const Standard_Integer NbVGaussgp_Pnts =
1108     Min(theSurface.VIntegrationOrder(), math::GaussPointsMax());
1109
1110   const Standard_Integer NbGaussgp_Pnts =
1111     Max(NbUGaussgp_Pnts, NbVGaussgp_Pnts);
1112
1113   // Number of Gauss points for the integration on the face
1114   math_Vector GaussSPV (1, NbGaussgp_Pnts);
1115   math_Vector GaussSWV (1, NbGaussgp_Pnts);
1116   math::GaussPoints (NbGaussgp_Pnts, GaussSPV);
1117   math::GaussWeights(NbGaussgp_Pnts, GaussSWV);
1118
1119   BRepGProp_Gauss::Inertia anInertia;
1120   while (theDomain.More())
1121   {
1122     theSurface.Load(theDomain.Value());
1123
1124     Standard_Integer NbCGaussgp_Pnts =
1125       Min(theSurface.IntegrationOrder(), math::GaussPointsMax());
1126
1127     NbCGaussgp_Pnts = Max(NbCGaussgp_Pnts, NbGaussgp_Pnts);
1128
1129     math_Vector GaussCP(1, NbCGaussgp_Pnts);
1130     math_Vector GaussCW(1, NbCGaussgp_Pnts);
1131     math::GaussPoints (NbCGaussgp_Pnts, GaussCP);
1132     math::GaussWeights(NbCGaussgp_Pnts, GaussCW);
1133
1134     
1135     const Standard_Real l1 = theSurface.FirstParameter();
1136     const Standard_Real l2 = theSurface.LastParameter ();
1137     const Standard_Real lm = 0.5 * (l2 + l1);
1138     const Standard_Real lr = 0.5 * (l2 - l1);
1139
1140     BRepGProp_Gauss::Inertia aCInertia;
1141     for (Standard_Integer i = 1; i <= NbCGaussgp_Pnts; ++i)
1142     {
1143       const Standard_Real l = lm + lr * GaussCP(i);
1144
1145       gp_Pnt2d Puv;
1146       gp_Vec2d Vuv;
1147       theSurface.D12d(l, Puv, Vuv);
1148
1149       const Standard_Real v = Puv.Y();
1150       u2  = Puv.X();
1151
1152       const Standard_Real Dul = Vuv.Y() * GaussCW(i);
1153       const Standard_Real um  = 0.5 * (u2 + u1);
1154       const Standard_Real ur  = 0.5 * (u2 - u1);
1155
1156       BRepGProp_Gauss::Inertia aLocalInertia;
1157       for (Standard_Integer j = 1; j <= NbGaussgp_Pnts; ++j)
1158       {
1159         const Standard_Real u = add(um, mult(ur, GaussSPV(j)));
1160         const Standard_Real aWeight = Dul * GaussSWV(j);
1161
1162         gp_Pnt aPoint;
1163         gp_Vec aNormal;
1164         theSurface.Normal (u, v, aPoint, aNormal);
1165
1166         computeSInertiaOfElementaryPart(aPoint, aNormal, theLocation, aWeight, aLocalInertia);
1167       }
1168
1169       multAndRestoreInertia(ur, aLocalInertia);
1170       addAndRestoreInertia (aLocalInertia, aCInertia);
1171     }
1172
1173     multAndRestoreInertia(lr, aCInertia);
1174     addAndRestoreInertia (aCInertia, anInertia);
1175
1176     theDomain.Next();
1177   }
1178
1179   convert(anInertia, theOutGravityCenter, theOutInertia, theOutMass);
1180 }
1181
1182 //=======================================================================
1183 //function : Compute
1184 //purpose  : 
1185 //=======================================================================
1186 void BRepGProp_Gauss::Compute(BRepGProp_Face&         theSurface,
1187                               BRepGProp_Domain&       theDomain,
1188                               const gp_Pnt&           theLocation,
1189                               const Standard_Real     theCoeff[],
1190                               const Standard_Boolean  theIsByPoint,
1191                               Standard_Real&          theOutMass,
1192                               gp_Pnt&                 theOutGravityCenter,
1193                               gp_Mat&                 theOutInertia)
1194 {
1195   Standard_ASSERT_RAISE(myType == Vinert, "BRepGProp_Gauss: Incorrect type");
1196
1197   Standard_Real u1, v1, u2, v2;
1198   theSurface.Bounds (u1, u2, v1, v2);
1199   checkBounds(u1, u2, v1, v2);
1200
1201   Standard_Real _u2 = u2;  //OCC104
1202
1203   BRepGProp_Gauss::Inertia anInertia;
1204   while (theDomain.More())
1205   {
1206     theSurface.Load(theDomain.Value());
1207
1208     const Standard_Integer aVNbCGaussgp_Pnts =
1209       theSurface.VIntegrationOrder();
1210
1211     const Standard_Integer aNbGaussgp_Pnts =
1212       Min( Max(theSurface.IntegrationOrder(), aVNbCGaussgp_Pnts), math::GaussPointsMax() );
1213
1214     math_Vector GaussP(1, aNbGaussgp_Pnts);
1215     math_Vector GaussW(1, aNbGaussgp_Pnts);
1216     math::GaussPoints (aNbGaussgp_Pnts, GaussP);
1217     math::GaussWeights(aNbGaussgp_Pnts, GaussW);
1218
1219     const Standard_Real l1 = theSurface.FirstParameter();
1220     const Standard_Real l2 = theSurface.LastParameter();
1221     const Standard_Real lm = 0.5 * (l2 + l1);
1222     const Standard_Real lr = 0.5 * (l2 - l1);
1223
1224     BRepGProp_Gauss::Inertia aCInertia;
1225     for (Standard_Integer i = 1; i <= aNbGaussgp_Pnts; ++i)
1226     {
1227       const Standard_Real l = lm + lr * GaussP(i);
1228
1229       gp_Pnt2d Puv;
1230       gp_Vec2d Vuv;
1231
1232       theSurface.D12d(l, Puv, Vuv);
1233
1234       u2  = Puv.X();
1235       u2 = Min( Max(u1, u2), _u2 ); // OCC104
1236       const Standard_Real v = Min(Max(Puv.Y(), v1), v2);
1237
1238       const Standard_Real Dul = Vuv.Y() * GaussW(i);
1239       const Standard_Real um  = 0.5 * (u2 + u1);
1240       const Standard_Real ur  = 0.5 * (u2 - u1);
1241
1242       BRepGProp_Gauss::Inertia aLocalInertia;
1243       for (Standard_Integer j = 1; j <= aNbGaussgp_Pnts; ++j)
1244       {
1245         const Standard_Real u = um + ur * GaussP(j);
1246         const Standard_Real aWeight = Dul * GaussW(j);
1247
1248         gp_Pnt aPoint;
1249         gp_Vec aNormal;
1250
1251         theSurface.Normal(u, v, aPoint, aNormal);
1252
1253         computeVInertiaOfElementaryPart(
1254           aPoint,
1255           aNormal,
1256           theLocation,
1257           aWeight,
1258           theCoeff,
1259           theIsByPoint,
1260           aLocalInertia);
1261       }
1262
1263       multAndRestoreInertia(ur, aLocalInertia);
1264       addAndRestoreInertia (aLocalInertia, aCInertia);
1265     }
1266
1267     multAndRestoreInertia(lr,        aCInertia);
1268     addAndRestoreInertia (aCInertia, anInertia);
1269
1270     theDomain.Next();
1271   }
1272
1273   convert(anInertia, theCoeff, theIsByPoint, theOutGravityCenter, theOutInertia, theOutMass);
1274 }
1275
1276 //=======================================================================
1277 //function : Compute
1278 //purpose  : 
1279 //=======================================================================
1280 void BRepGProp_Gauss::Compute(const BRepGProp_Face&  theSurface,
1281                               const gp_Pnt&          theLocation,
1282                               const Standard_Real    theCoeff[],
1283                               const Standard_Boolean theIsByPoint,
1284                               Standard_Real&         theOutMass,
1285                               gp_Pnt&                theOutGravityCenter,
1286                               gp_Mat&                theOutInertia)
1287 {
1288   Standard_Real LowerU, UpperU, LowerV, UpperV;
1289   theSurface.Bounds(LowerU, UpperU, LowerV, UpperV);
1290   checkBounds(LowerU, UpperU, LowerV, UpperV);
1291
1292   const Standard_Integer UOrder =
1293     Min(theSurface.UIntegrationOrder(), math::GaussPointsMax());
1294   const Standard_Integer VOrder =
1295     Min(theSurface.VIntegrationOrder(), math::GaussPointsMax());
1296
1297   // Gauss points and weights
1298   math_Vector GaussPU(1, UOrder);
1299   math_Vector GaussWU(1, UOrder);
1300   math_Vector GaussPV(1, VOrder);
1301   math_Vector GaussWV(1, VOrder);
1302
1303   math::GaussPoints (UOrder, GaussPU);
1304   math::GaussWeights(UOrder, GaussWU);
1305   math::GaussPoints (VOrder, GaussPV);
1306   math::GaussWeights(VOrder, GaussWV);
1307
1308   const Standard_Real um = 0.5 * add(UpperU,  LowerU);
1309   const Standard_Real vm = 0.5 * add(UpperV,  LowerV);
1310   Standard_Real ur = 0.5 * add(UpperU, -LowerU);
1311   Standard_Real vr = 0.5 * add(UpperV, -LowerV);
1312
1313   gp_Pnt aPoint;
1314   gp_Vec aNormal;
1315
1316   BRepGProp_Gauss::Inertia anInertia;
1317   for (Standard_Integer j = 1; j <= VOrder; ++j)
1318   {
1319     BRepGProp_Gauss::Inertia anInertiaOfElementaryPart;
1320     const Standard_Real v = add(vm, mult(vr, GaussPV(j)));
1321
1322     for (Standard_Integer i = 1; i <= UOrder; ++i)
1323     {
1324       const Standard_Real aWeight = GaussWU(i);
1325       const Standard_Real u = add(um, mult(ur, GaussPU (i)));
1326       theSurface.Normal(u, v, aPoint, aNormal);
1327
1328       if (myType == Vinert)
1329       {
1330         computeVInertiaOfElementaryPart(
1331           aPoint,
1332           aNormal,
1333           theLocation,
1334           aWeight,
1335           theCoeff,
1336           theIsByPoint,
1337           anInertiaOfElementaryPart);
1338       }
1339       else // Sinert
1340       {
1341         computeSInertiaOfElementaryPart(
1342           aPoint,
1343           aNormal,
1344           theLocation,
1345           aWeight,
1346           anInertiaOfElementaryPart);
1347       }
1348     }
1349
1350     multAndRestoreInertia(GaussWV(j), anInertiaOfElementaryPart);
1351     addAndRestoreInertia (anInertiaOfElementaryPart,  anInertia);
1352   }
1353   vr            = mult(vr, ur);
1354   anInertia.Ixx = mult(vr, anInertia.Ixx);
1355   anInertia.Iyy = mult(vr, anInertia.Iyy);
1356   anInertia.Izz = mult(vr, anInertia.Izz);
1357   anInertia.Ixy = mult(vr, anInertia.Ixy);
1358   anInertia.Ixz = mult(vr, anInertia.Ixz);
1359   anInertia.Iyz = mult(vr, anInertia.Iyz);
1360
1361   if (myType == Vinert)
1362   {
1363     convert(anInertia, theCoeff, theIsByPoint, theOutGravityCenter, theOutInertia, theOutMass);
1364   }
1365   else // Sinert
1366   {
1367     convert(anInertia, theOutGravityCenter, theOutInertia, theOutMass);
1368   }
1369
1370   theOutMass *= vr;
1371 }
1372
1373 //=======================================================================
1374 //function : Compute
1375 //purpose  : 
1376 //=======================================================================
1377 void BRepGProp_Gauss::Compute(const BRepGProp_Face& theSurface,
1378                               const gp_Pnt&         theLocation,
1379                               Standard_Real&        theOutMass,
1380                               gp_Pnt&               theOutGravityCenter,
1381                               gp_Mat&               theOutInertia)
1382 {
1383   Standard_ASSERT_RAISE(myType == Sinert, "BRepGProp_Gauss: Incorrect type");
1384
1385   Compute(theSurface,
1386           theLocation,
1387           NULL,
1388           Standard_True,
1389           theOutMass,
1390           theOutGravityCenter,
1391           theOutInertia);
1392 }