1 // Created on: 2005-12-09
2 // Created by: Sergey KHROMOV
3 // Copyright (c) 2005-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
17 #include <BRepGProp_Domain.hxx>
18 #include <BRepGProp_TFunction.hxx>
19 #include <BRepGProp_VinertGK.hxx>
22 #include <math_KronrodSingleIntegration.hxx>
23 #include <TColStd_Array1OfBoolean.hxx>
24 #include <TColStd_HArray1OfReal.hxx>
26 //==========================================================================
27 //function : Constructor
28 //==========================================================================
29 BRepGProp_VinertGK::BRepGProp_VinertGK(BRepGProp_Face &theSurface,
30 const gp_Pnt &theLocation,
31 const Standard_Real theTolerance,
32 const Standard_Boolean theCGFlag,
33 const Standard_Boolean theIFlag):
36 SetLocation(theLocation);
37 Perform(theSurface, theTolerance, theCGFlag, theIFlag);
40 //==========================================================================
41 //function : Constructor
43 //==========================================================================
45 BRepGProp_VinertGK::BRepGProp_VinertGK( BRepGProp_Face &theSurface,
46 const gp_Pnt &thePoint,
47 const gp_Pnt &theLocation,
48 const Standard_Real theTolerance,
49 const Standard_Boolean theCGFlag,
50 const Standard_Boolean theIFlag):
53 SetLocation(theLocation);
54 Perform(theSurface, thePoint, theTolerance, theCGFlag, theIFlag);
57 //==========================================================================
58 //function : Constructor
60 //==========================================================================
62 BRepGProp_VinertGK::BRepGProp_VinertGK(BRepGProp_Face &theSurface,
63 BRepGProp_Domain &theDomain,
64 const gp_Pnt &theLocation,
65 const Standard_Real theTolerance,
66 const Standard_Boolean theCGFlag,
67 const Standard_Boolean theIFlag):
70 SetLocation(theLocation);
71 Perform(theSurface, theDomain, theTolerance, theCGFlag, theIFlag);
74 //==========================================================================
75 //function : Constructor
77 //==========================================================================
79 BRepGProp_VinertGK::BRepGProp_VinertGK(BRepGProp_Face &theSurface,
80 BRepGProp_Domain &theDomain,
81 const gp_Pnt &thePoint,
82 const gp_Pnt &theLocation,
83 const Standard_Real theTolerance,
84 const Standard_Boolean theCGFlag,
85 const Standard_Boolean theIFlag):
88 SetLocation(theLocation);
89 Perform(theSurface, theDomain, thePoint, theTolerance, theCGFlag, theIFlag);
92 //==========================================================================
93 //function : Constructor
95 //==========================================================================
97 BRepGProp_VinertGK::BRepGProp_VinertGK(BRepGProp_Face &theSurface,
98 const gp_Pln &thePlane,
99 const gp_Pnt &theLocation,
100 const Standard_Real theTolerance,
101 const Standard_Boolean theCGFlag,
102 const Standard_Boolean theIFlag):
105 SetLocation(theLocation);
106 Perform(theSurface, thePlane, theTolerance, theCGFlag, theIFlag);
109 //==========================================================================
110 //function : Constructor
112 //==========================================================================
114 BRepGProp_VinertGK::BRepGProp_VinertGK(BRepGProp_Face &theSurface,
115 BRepGProp_Domain &theDomain,
116 const gp_Pln &thePlane,
117 const gp_Pnt &theLocation,
118 const Standard_Real theTolerance,
119 const Standard_Boolean theCGFlag,
120 const Standard_Boolean theIFlag):
123 SetLocation(theLocation);
124 Perform(theSurface, theDomain, thePlane, theTolerance, theCGFlag, theIFlag);
127 //==========================================================================
129 // Compute the properties.
130 //==========================================================================
132 Standard_Real BRepGProp_VinertGK::Perform(BRepGProp_Face &theSurface,
133 const Standard_Real theTolerance,
134 const Standard_Boolean theCGFlag,
135 const Standard_Boolean theIFlag)
138 Standard_Real aShift[] = { 0., 0., 0. };
140 return PrivatePerform(theSurface, NULL, Standard_True, aShift, theTolerance,
141 theCGFlag, theIFlag);
144 //==========================================================================
146 // Compute the properties.
147 //==========================================================================
149 Standard_Real BRepGProp_VinertGK::Perform(BRepGProp_Face &theSurface,
150 const gp_Pnt &thePoint,
151 const Standard_Real theTolerance,
152 const Standard_Boolean theCGFlag,
153 const Standard_Boolean theIFlag)
156 gp_XYZ aXYZ(thePoint.XYZ().Subtracted(loc.XYZ()));
157 Standard_Real aShift[3];
159 aXYZ.Coord(aShift[0], aShift[1], aShift[2]);
161 return PrivatePerform(theSurface, NULL, Standard_True, aShift, theTolerance,
162 theCGFlag, theIFlag);
165 //==========================================================================
167 // Compute the properties.
168 //==========================================================================
170 Standard_Real BRepGProp_VinertGK::Perform(BRepGProp_Face &theSurface,
171 BRepGProp_Domain &theDomain,
172 const Standard_Real theTolerance,
173 const Standard_Boolean theCGFlag,
174 const Standard_Boolean theIFlag)
177 Standard_Real aShift[] = { 0., 0., 0. };
179 return PrivatePerform(theSurface, &theDomain,
180 Standard_True, aShift, theTolerance,
181 theCGFlag, theIFlag);
184 //==========================================================================
186 // Compute the properties.
187 //==========================================================================
189 Standard_Real BRepGProp_VinertGK::Perform(BRepGProp_Face &theSurface,
190 BRepGProp_Domain &theDomain,
191 const gp_Pnt &thePoint,
192 const Standard_Real theTolerance,
193 const Standard_Boolean theCGFlag,
194 const Standard_Boolean theIFlag)
197 gp_XYZ aXYZ(thePoint.XYZ().Subtracted(loc.XYZ()));
198 Standard_Real aShift[3];
200 aXYZ.Coord(aShift[0], aShift[1], aShift[2]);
202 return PrivatePerform(theSurface, &theDomain,
203 Standard_True, aShift, theTolerance,
204 theCGFlag, theIFlag);
207 //==========================================================================
209 // Compute the properties.
210 //==========================================================================
212 Standard_Real BRepGProp_VinertGK::Perform(BRepGProp_Face &theSurface,
213 const gp_Pln &thePlane,
214 const Standard_Real theTolerance,
215 const Standard_Boolean theCGFlag,
216 const Standard_Boolean theIFlag)
219 Standard_Real aCoeff[4];
224 loc.Coord(aXLoc, aYLoc, aZLoc);
225 thePlane.Coefficients (aCoeff[0], aCoeff[1], aCoeff[2], aCoeff[3]);
226 aCoeff[3] = aCoeff[3] - aCoeff[0]*aXLoc - aCoeff[1]*aYLoc - aCoeff[2]*aZLoc;
228 return PrivatePerform(theSurface, NULL,
229 Standard_False, aCoeff, theTolerance,
230 theCGFlag, theIFlag);
233 //==========================================================================
235 // Compute the properties.
236 //==========================================================================
238 Standard_Real BRepGProp_VinertGK::Perform(BRepGProp_Face &theSurface,
239 BRepGProp_Domain &theDomain,
240 const gp_Pln &thePlane,
241 const Standard_Real theTolerance,
242 const Standard_Boolean theCGFlag,
243 const Standard_Boolean theIFlag)
246 Standard_Real aCoeff[4];
251 loc.Coord(aXLoc, aYLoc, aZLoc);
252 thePlane.Coefficients (aCoeff[0], aCoeff[1], aCoeff[2], aCoeff[3]);
253 aCoeff[3] = aCoeff[3] - aCoeff[0]*aXLoc - aCoeff[1]*aYLoc - aCoeff[2]*aZLoc;
255 return PrivatePerform(theSurface, &theDomain,
256 Standard_False, aCoeff, theTolerance,
257 theCGFlag, theIFlag);
260 //==========================================================================
261 //function : PrivatePerform
262 // Compute the properties.
263 //==========================================================================
265 Standard_Real BRepGProp_VinertGK::PrivatePerform
266 (BRepGProp_Face &theSurface,
267 const Standard_Address thePtrDomain,
268 const Standard_Boolean IsByPoint,
269 const Standard_Real* theCoeffs,
270 const Standard_Real theTolerance,
271 const Standard_Boolean theCGFlag,
272 const Standard_Boolean theIFlag)
276 const Standard_Real aTTol = 1.e-9;
277 const Standard_Real* aCoeffs = theCoeffs;
279 // Compute the number of 2d bounding curves of the face.
280 BRepGProp_Domain *aPDomain = NULL;
281 Standard_Integer aNbCurves = 0;
283 // If the pointer to the domain is NULL, there is only one curve to treat:
284 // U isoline with the UMax parameter.
285 if (thePtrDomain == NULL)
288 aPDomain = (BRepGProp_Domain *)thePtrDomain;
290 for (aPDomain->Init(); aPDomain->More(); aPDomain->Next())
294 if (aNbCurves == 0) {
295 myErrorReached = -1.;
297 return myErrorReached;
300 //Standard_Real aCrvTol = 0.5*theTolerance/aNbCurves;
301 Standard_Real aCrvTol = 0.1*theTolerance;
306 Standard_Integer aNbPnts;
307 Standard_Integer aNbMaxIter = 1000;
308 Standard_Integer aNbVal = 10;
310 math_Vector aLocalValue(1, aNbVal);
311 math_Vector aLocalTolReached(1, aNbVal);
312 math_Vector aValue(1, aNbVal);
313 math_Vector aTolReached(1, aNbVal);
314 TColStd_Array1OfBoolean CFlags(1, aNbVal);
315 CFlags.Init(Standard_False);
316 Standard_Boolean isMore;
320 aTolReached.Init(0.);
322 CFlags.Init(Standard_False);
323 CFlags(1) = Standard_True;
325 if(theCGFlag || theIFlag) {
327 for(i = 2; i <= 4; ++i) {CFlags(i) = Standard_True;}
332 for(i = 5; i <= 10; ++i) {CFlags(i) = Standard_True;}
335 theSurface.Bounds(aUMin, aUMax, aTMin, aTMax);
337 if (thePtrDomain == NULL)
338 isMore = Standard_True;
341 isMore = aPDomain->More();
345 // If the pointer to the domain is NULL, there is only one curve to treat:
346 // U isoline with the UMax parameter.
348 if (thePtrDomain == NULL)
349 theSurface.Load(Standard_False, GeomAbs_IsoU);
351 theSurface.Load(aPDomain->Value());
353 aTMin = theSurface.FirstParameter();
354 aTMax = theSurface.LastParameter();
357 // Get the spans on the curve.
358 Handle(TColStd_HArray1OfReal) aTKnots;
359 BRepGProp_TFunction aTFunc (theSurface, loc, IsByPoint, theCoeffs, aUMin, aCrvTol);
361 theSurface.GetTKnots(aTMin, aTMax, aTKnots);
363 Standard_Integer iU = aTKnots->Upper();
364 Standard_Integer aNbTIntervals = aTKnots->Length() - 1;
365 //Standard_Real aTolSpan = aCrvTol/aNbTIntervals;
366 Standard_Real aTolSpan = 0.9*theTolerance; //Relative error
367 math_KronrodSingleIntegration anIntegral;
368 GProp_ValueType aValueType;
371 // Empirical criterion.
372 aNbPnts = Min(15, theSurface.IntegrationOrder()/aNbTIntervals + 1);
373 aNbPnts = Max(5, aNbPnts);
374 // aNbPnts = theSurface.IntegrationOrder();
376 aLocalValue.Init(0.);
377 aLocalTolReached.Init(0.);
379 for (k = 1; k <= aNbVal; k++) {
381 if(!CFlags(k)) continue;
383 Standard_Integer i = aTKnots->Lower();
386 case 1: aValueType = GProp_Mass; break;
387 case 2: aValueType = GProp_CenterMassX; break;
388 case 3: aValueType = GProp_CenterMassY; break;
389 case 4: aValueType = GProp_CenterMassZ; break;
390 case 5: aValueType = GProp_InertiaXX; break;
391 case 6: aValueType = GProp_InertiaYY; break;
392 case 7: aValueType = GProp_InertiaZZ; break;
393 case 8: aValueType = GProp_InertiaXY; break;
394 case 9: aValueType = GProp_InertiaXZ; break;
395 case 10: aValueType = GProp_InertiaYZ; break;
397 default: myErrorReached = -1.; return myErrorReached;
399 aTFunc.SetValueType(aValueType);
401 Standard_Real err1 = 0.;
404 //std::cout << "-------------- Span " << i << " nbp: " << aNbPnts << std::endl;
405 Standard_Real aT1 = aTKnots->Value(i++);
406 Standard_Real aT2 = aTKnots->Value(i);
408 if(aT2 - aT1 < aTTol) continue;
410 aTFunc.SetNbKronrodPoints(aNbPnts);
412 aTFunc.SetTolerance(aCrvTol/(aT2-aT1));
413 anIntegral.Perform(aTFunc, aT1, aT2, aNbPnts, aTolSpan, aNbMaxIter);
415 if (!anIntegral.IsDone()) {
416 myErrorReached = -1.;
418 return myErrorReached;
421 aLocalValue(k) += anIntegral.Value();
422 err1 = aTFunc.AbsolutError()*(aT2 - aT1);
423 //std::cout << "Errors: " << anIntegral.NbIterReached() << " " << anIntegral.AbsolutError() << " " << err1 << std::endl;
424 aLocalTolReached(k) += anIntegral.AbsolutError() + err1;
425 //std::cout << "--- Errors: " << anIntegral.NbIterReached() << " " << anIntegral.AbsolutError() << " " << err1 << std::endl;
428 aValue(k) += aLocalValue(k);
429 aTolReached(k) += aLocalTolReached(k);
432 // If the pointer to the domain is NULL, there is only one curve to treat:
433 // U isoline with the UMax parameter.
434 if (thePtrDomain == NULL)
435 isMore = Standard_False;
438 isMore = aPDomain->More();
444 myErrorReached = aTolReached(1);
445 myAbsolutError = myErrorReached;
446 Standard_Real anAbsDim = Abs(dim);
447 Standard_Real aVolTol = Epsilon(myAbsolutError);
448 if(anAbsDim >= aVolTol) myErrorReached /= anAbsDim;
450 if(theCGFlag || theIFlag) {
451 // Compute values of center of mass.
452 if(anAbsDim >= aVolTol) {
454 aValue(2) = aCoeffs[0] + aValue(2)/dim;
455 aValue(3) = aCoeffs[1] + aValue(3)/dim;
456 aValue(4) = aCoeffs[2] + aValue(4)/dim;
468 g.SetCoord(aValue(2), aValue(3), aValue(4));
472 // Fill the matrix of inertia.
473 inertia.SetCols (gp_XYZ (aValue(5), aValue(8), aValue(9)),
474 gp_XYZ (aValue(8), aValue(6), aValue(10)),
475 gp_XYZ (aValue(9), aValue(10), aValue(7)));
477 //return myErrorReached;
478 return myAbsolutError;