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