7fd59977 |
1 | // File: GProp_VGPropsGK.gxx |
2 | // Created: Fri Dec 9 14:00:04 2005 |
3 | // Author: Sergey KHROMOV |
4 | // <skv@dimox> |
5 | |
6 | |
7 | #include <TColStd_HArray1OfReal.hxx> |
8 | #include <TColStd_Array1OfBoolean.hxx> |
9 | #include <math_KronrodSingleIntegration.hxx> |
10 | #include <math_Vector.hxx> |
11 | #include <math.hxx> |
12 | |
13 | //========================================================================== |
14 | //function : Constructor |
15 | // |
16 | //========================================================================== |
17 | |
18 | GProp_VGPropsGK::GProp_VGPropsGK( Face &theSurface, |
19 | const gp_Pnt &theLocation, |
20 | const Standard_Real theTolerance, |
21 | const Standard_Boolean theCGFlag, |
22 | const Standard_Boolean theIFlag) |
23 | : myErrorReached(0.) |
24 | { |
25 | SetLocation(theLocation); |
26 | Perform(theSurface, theTolerance, theCGFlag, theIFlag); |
27 | } |
28 | |
29 | //========================================================================== |
30 | //function : Constructor |
31 | // |
32 | //========================================================================== |
33 | |
34 | GProp_VGPropsGK::GProp_VGPropsGK( Face &theSurface, |
35 | const gp_Pnt &thePoint, |
36 | const gp_Pnt &theLocation, |
37 | const Standard_Real theTolerance, |
38 | const Standard_Boolean theCGFlag, |
39 | const Standard_Boolean theIFlag) |
40 | |
41 | : myErrorReached(0.) |
42 | { |
43 | SetLocation(theLocation); |
44 | Perform(theSurface, thePoint, theTolerance, theCGFlag, theIFlag); |
45 | } |
46 | |
47 | //========================================================================== |
48 | //function : Constructor |
49 | // |
50 | //========================================================================== |
51 | |
52 | GProp_VGPropsGK::GProp_VGPropsGK( Face &theSurface, |
53 | Domain &theDomain, |
54 | const gp_Pnt &theLocation, |
55 | const Standard_Real theTolerance, |
56 | const Standard_Boolean theCGFlag, |
57 | const Standard_Boolean theIFlag) |
58 | |
59 | : myErrorReached(0.) |
60 | { |
61 | SetLocation(theLocation); |
62 | Perform(theSurface, theDomain, theTolerance, theCGFlag, theIFlag); |
63 | } |
64 | |
65 | //========================================================================== |
66 | //function : Constructor |
67 | // |
68 | //========================================================================== |
69 | |
70 | GProp_VGPropsGK::GProp_VGPropsGK( Face &theSurface, |
71 | Domain &theDomain, |
72 | const gp_Pnt &thePoint, |
73 | const gp_Pnt &theLocation, |
74 | const Standard_Real theTolerance, |
75 | const Standard_Boolean theCGFlag, |
76 | const Standard_Boolean theIFlag) |
77 | |
78 | : myErrorReached(0.) |
79 | { |
80 | SetLocation(theLocation); |
81 | Perform(theSurface, theDomain, thePoint, theTolerance, theCGFlag, theIFlag); |
82 | } |
83 | |
84 | //========================================================================== |
85 | //function : Constructor |
86 | // |
87 | //========================================================================== |
88 | |
89 | GProp_VGPropsGK::GProp_VGPropsGK( Face &theSurface, |
90 | const gp_Pln &thePlane, |
91 | const gp_Pnt &theLocation, |
92 | const Standard_Real theTolerance, |
93 | const Standard_Boolean theCGFlag, |
94 | const Standard_Boolean theIFlag) |
95 | |
96 | : myErrorReached(0.) |
97 | { |
98 | SetLocation(theLocation); |
99 | Perform(theSurface, thePlane, theTolerance, theCGFlag, theIFlag); |
100 | } |
101 | |
102 | //========================================================================== |
103 | //function : Constructor |
104 | // |
105 | //========================================================================== |
106 | |
107 | GProp_VGPropsGK::GProp_VGPropsGK( Face &theSurface, |
108 | Domain &theDomain, |
109 | const gp_Pln &thePlane, |
110 | const gp_Pnt &theLocation, |
111 | const Standard_Real theTolerance, |
112 | const Standard_Boolean theCGFlag, |
113 | const Standard_Boolean theIFlag) |
114 | |
115 | : myErrorReached(0.) |
116 | { |
117 | SetLocation(theLocation); |
118 | Perform(theSurface, theDomain, thePlane, theTolerance, theCGFlag, theIFlag); |
119 | } |
120 | |
121 | //========================================================================== |
122 | //function : Perform |
123 | // Compute the properties. |
124 | //========================================================================== |
125 | |
126 | Standard_Real GProp_VGPropsGK::Perform( Face &theSurface, |
127 | const Standard_Real theTolerance, |
128 | const Standard_Boolean theCGFlag, |
129 | const Standard_Boolean theIFlag) |
130 | |
131 | { |
132 | Standard_Real aShift[] = { 0., 0., 0. }; |
133 | |
134 | return PrivatePerform(theSurface, NULL, Standard_True, &aShift, theTolerance, |
135 | theCGFlag, theIFlag); |
136 | } |
137 | |
138 | //========================================================================== |
139 | //function : Perform |
140 | // Compute the properties. |
141 | //========================================================================== |
142 | |
143 | Standard_Real GProp_VGPropsGK::Perform( Face &theSurface, |
144 | const gp_Pnt &thePoint, |
145 | const Standard_Real theTolerance, |
146 | const Standard_Boolean theCGFlag, |
147 | const Standard_Boolean theIFlag) |
148 | |
149 | { |
150 | gp_XYZ aXYZ(thePoint.XYZ().Subtracted(loc.XYZ())); |
151 | Standard_Real aShift[3]; |
152 | |
153 | aXYZ.Coord(aShift[0], aShift[1], aShift[2]); |
154 | |
155 | return PrivatePerform(theSurface, NULL, Standard_True, &aShift, theTolerance, |
156 | theCGFlag, theIFlag); |
157 | } |
158 | |
159 | //========================================================================== |
160 | //function : Perform |
161 | // Compute the properties. |
162 | //========================================================================== |
163 | |
164 | Standard_Real GProp_VGPropsGK::Perform( Face &theSurface, |
165 | Domain &theDomain, |
166 | const Standard_Real theTolerance, |
167 | const Standard_Boolean theCGFlag, |
168 | const Standard_Boolean theIFlag) |
169 | |
170 | { |
171 | Standard_Real aShift[] = { 0., 0., 0. }; |
172 | |
173 | return PrivatePerform(theSurface, &theDomain, |
174 | Standard_True, &aShift, theTolerance, |
175 | theCGFlag, theIFlag); |
176 | } |
177 | |
178 | //========================================================================== |
179 | //function : Perform |
180 | // Compute the properties. |
181 | //========================================================================== |
182 | |
183 | Standard_Real GProp_VGPropsGK::Perform( Face &theSurface, |
184 | Domain &theDomain, |
185 | const gp_Pnt &thePoint, |
186 | const Standard_Real theTolerance, |
187 | const Standard_Boolean theCGFlag, |
188 | const Standard_Boolean theIFlag) |
189 | |
190 | { |
191 | gp_XYZ aXYZ(thePoint.XYZ().Subtracted(loc.XYZ())); |
192 | Standard_Real aShift[3]; |
193 | |
194 | aXYZ.Coord(aShift[0], aShift[1], aShift[2]); |
195 | |
196 | return PrivatePerform(theSurface, &theDomain, |
197 | Standard_True, &aShift, theTolerance, |
198 | theCGFlag, theIFlag); |
199 | } |
200 | |
201 | //========================================================================== |
202 | //function : Perform |
203 | // Compute the properties. |
204 | //========================================================================== |
205 | |
206 | Standard_Real GProp_VGPropsGK::Perform( Face &theSurface, |
207 | const gp_Pln &thePlane, |
208 | const Standard_Real theTolerance, |
209 | const Standard_Boolean theCGFlag, |
210 | const Standard_Boolean theIFlag) |
211 | |
212 | { |
213 | Standard_Real aCoeff[4]; |
214 | Standard_Real aXLoc; |
215 | Standard_Real aYLoc; |
216 | Standard_Real aZLoc; |
217 | |
218 | loc.Coord(aXLoc, aYLoc, aZLoc); |
219 | thePlane.Coefficients (aCoeff[0], aCoeff[1], aCoeff[2], aCoeff[3]); |
220 | aCoeff[3] = aCoeff[3] - aCoeff[0]*aXLoc - aCoeff[1]*aYLoc - aCoeff[2]*aZLoc; |
221 | |
222 | return PrivatePerform(theSurface, NULL, |
223 | Standard_False, &aCoeff, theTolerance, |
224 | theCGFlag, theIFlag); |
225 | } |
226 | |
227 | //========================================================================== |
228 | //function : Perform |
229 | // Compute the properties. |
230 | //========================================================================== |
231 | |
232 | Standard_Real GProp_VGPropsGK::Perform( Face &theSurface, |
233 | Domain &theDomain, |
234 | const gp_Pln &thePlane, |
235 | const Standard_Real theTolerance, |
236 | const Standard_Boolean theCGFlag, |
237 | const Standard_Boolean theIFlag) |
238 | |
239 | { |
240 | Standard_Real aCoeff[4]; |
241 | Standard_Real aXLoc; |
242 | Standard_Real aYLoc; |
243 | Standard_Real aZLoc; |
244 | |
245 | loc.Coord(aXLoc, aYLoc, aZLoc); |
246 | thePlane.Coefficients (aCoeff[0], aCoeff[1], aCoeff[2], aCoeff[3]); |
247 | aCoeff[3] = aCoeff[3] - aCoeff[0]*aXLoc - aCoeff[1]*aYLoc - aCoeff[2]*aZLoc; |
248 | |
249 | return PrivatePerform(theSurface, &theDomain, |
250 | Standard_False, &aCoeff, theTolerance, |
251 | theCGFlag, theIFlag); |
252 | } |
253 | |
254 | //========================================================================== |
255 | //function : PrivatePerform |
256 | // Compute the properties. |
257 | //========================================================================== |
258 | |
259 | Standard_Real GProp_VGPropsGK::PrivatePerform |
260 | ( Face &theSurface, |
261 | const Standard_Address thePtrDomain, |
262 | const Standard_Boolean IsByPoint, |
263 | const Standard_Address theCoeffs, |
264 | const Standard_Real theTolerance, |
265 | const Standard_Boolean theCGFlag, |
266 | const Standard_Boolean theIFlag) |
267 | |
268 | { |
269 | |
270 | const Standard_Real aTTol = 1.e-9; |
271 | Standard_Real *aCoeffs = (Standard_Real *)theCoeffs; |
272 | |
273 | // Compute the number of 2d bounding curves of the face. |
274 | Domain *aPDomain = NULL; |
275 | Standard_Integer aNbCurves = 0; |
276 | |
277 | // If the pointer to the domain is NULL, there is only one curve to treat: |
278 | // U isoline with the UMax parameter. |
279 | if (thePtrDomain == NULL) |
280 | aNbCurves = 1; |
281 | else { |
282 | aPDomain = (Domain *)thePtrDomain; |
283 | |
284 | for (aPDomain->Init(); aPDomain->More(); aPDomain->Next()) |
285 | aNbCurves++; |
286 | } |
287 | |
288 | if (aNbCurves == 0) { |
289 | myErrorReached = -1.; |
290 | |
291 | return myErrorReached; |
292 | } |
293 | |
294 | //Standard_Real aCrvTol = 0.5*theTolerance/aNbCurves; |
295 | Standard_Real aCrvTol = 0.1*theTolerance; |
296 | Standard_Real aUMin; |
297 | Standard_Real aUMax; |
298 | Standard_Real aTMin; |
299 | Standard_Real aTMax; |
300 | Standard_Integer aNbPnts; |
301 | Standard_Integer aNbMaxIter = 1000; |
302 | Standard_Integer aNbVal = 10; |
303 | Standard_Integer k; |
304 | math_Vector aLocalValue(1, aNbVal); |
305 | math_Vector aLocalTolReached(1, aNbVal); |
306 | math_Vector aValue(1, aNbVal); |
307 | math_Vector aTolReached(1, aNbVal); |
308 | TColStd_Array1OfBoolean CFlags(1, aNbVal); |
309 | CFlags.Init(Standard_False); |
310 | Standard_Boolean isMore; |
311 | |
312 | //aNbVal = 1; |
313 | aValue.Init(0.); |
314 | aTolReached.Init(0.); |
315 | |
316 | CFlags.Init(Standard_False); |
317 | CFlags(1) = Standard_True; |
318 | |
319 | if(theCGFlag || theIFlag) { |
320 | Standard_Integer i; |
321 | for(i = 2; i <= 4; ++i) {CFlags(i) = Standard_True;} |
322 | } |
323 | |
324 | if(theIFlag) { |
325 | Standard_Integer i; |
326 | for(i = 5; i <= 10; ++i) {CFlags(i) = Standard_True;} |
327 | } |
328 | |
329 | theSurface.Bounds(aUMin, aUMax, aTMin, aTMax); |
330 | |
331 | if (thePtrDomain == NULL) |
332 | isMore = Standard_True; |
333 | else { |
334 | aPDomain->Init(); |
335 | isMore = aPDomain->More(); |
336 | } |
337 | |
338 | while(isMore) { |
339 | // If the pointer to the domain is NULL, there is only one curve to treat: |
340 | // U isoline with the UMax parameter. |
341 | |
342 | if (thePtrDomain == NULL) |
343 | theSurface.Load(Standard_False, GeomAbs_IsoU); |
344 | else |
345 | theSurface.Load(aPDomain->Value()); |
346 | |
347 | aTMin = theSurface.FirstParameter(); |
348 | aTMax = theSurface.LastParameter(); |
349 | |
350 | |
351 | // Get the spans on the curve. |
352 | Handle(TColStd_HArray1OfReal) aTKnots; |
353 | GProp_TFunction aTFunc(theSurface, loc, IsByPoint, theCoeffs, |
354 | aUMin, aCrvTol); |
355 | |
356 | theSurface.GetTKnots(aTMin, aTMax, aTKnots); |
357 | |
358 | Standard_Integer iU = aTKnots->Upper(); |
359 | Standard_Integer aNbTIntervals = aTKnots->Length() - 1; |
360 | //Standard_Real aTolSpan = aCrvTol/aNbTIntervals; |
361 | Standard_Real aTolSpan = 0.9*theTolerance; //Relative error |
362 | math_KronrodSingleIntegration anIntegral; |
363 | GProp_ValueType aValueType; |
364 | |
365 | |
366 | // Empirical criterion. |
367 | aNbPnts = Min(15, theSurface.IntegrationOrder()/aNbTIntervals + 1); |
368 | aNbPnts = Max(5, aNbPnts); |
369 | // aNbPnts = theSurface.IntegrationOrder(); |
370 | |
371 | aLocalValue.Init(0.); |
372 | aLocalTolReached.Init(0.); |
373 | |
374 | for (k = 1; k <= aNbVal; k++) { |
375 | |
376 | if(!CFlags(k)) continue; |
377 | |
378 | Standard_Integer i = aTKnots->Lower(); |
379 | |
380 | switch (k) { |
381 | case 1: aValueType = GProp_Mass; break; |
382 | case 2: aValueType = GProp_CenterMassX; break; |
383 | case 3: aValueType = GProp_CenterMassY; break; |
384 | case 4: aValueType = GProp_CenterMassZ; break; |
385 | case 5: aValueType = GProp_InertiaXX; break; |
386 | case 6: aValueType = GProp_InertiaYY; break; |
387 | case 7: aValueType = GProp_InertiaZZ; break; |
388 | case 8: aValueType = GProp_InertiaXY; break; |
389 | case 9: aValueType = GProp_InertiaXZ; break; |
390 | case 10: aValueType = GProp_InertiaYZ; break; |
391 | |
392 | default: myErrorReached = -1.; return myErrorReached; |
393 | } |
394 | aTFunc.SetValueType(aValueType); |
395 | |
396 | Standard_Real err1 = 0.; |
397 | while (i < iU) { |
398 | |
399 | //cout << "-------------- Span " << i << " nbp: " << aNbPnts << endl; |
400 | Standard_Real aT1 = aTKnots->Value(i++); |
401 | Standard_Real aT2 = aTKnots->Value(i); |
402 | |
403 | if(aT2 - aT1 < aTTol) continue; |
404 | |
405 | aTFunc.SetNbKronrodPoints(aNbPnts); |
406 | aTFunc.Init(); |
407 | aTFunc.SetTolerance(aCrvTol/(aT2-aT1)); |
408 | anIntegral.Perform(aTFunc, aT1, aT2, aNbPnts, aTolSpan, aNbMaxIter); |
409 | |
410 | if (!anIntegral.IsDone()) { |
411 | myErrorReached = -1.; |
412 | |
413 | return myErrorReached; |
414 | } |
415 | |
416 | aLocalValue(k) += anIntegral.Value(); |
417 | err1 = aTFunc.AbsolutError()*(aT2 - aT1); |
418 | //cout << "Errors: " << anIntegral.NbIterReached() << " " << anIntegral.AbsolutError() << " " << err1 << endl; |
419 | aLocalTolReached(k) += anIntegral.AbsolutError() + err1; |
420 | //cout << "--- Errors: " << anIntegral.NbIterReached() << " " << anIntegral.AbsolutError() << " " << err1 << endl; |
421 | } |
422 | |
423 | aValue(k) += aLocalValue(k); |
424 | aTolReached(k) += aLocalTolReached(k); |
425 | } |
426 | |
427 | // If the pointer to the domain is NULL, there is only one curve to treat: |
428 | // U isoline with the UMax parameter. |
429 | if (thePtrDomain == NULL) |
430 | isMore = Standard_False; |
431 | else { |
432 | aPDomain->Next(); |
433 | isMore = aPDomain->More(); |
434 | } |
435 | } |
436 | |
437 | // Get volume value. |
438 | dim = aValue(1); |
439 | myErrorReached = aTolReached(1); |
440 | myAbsolutError = myErrorReached; |
441 | Standard_Real anAbsDim = Abs(dim); |
442 | Standard_Real aVolTol = Epsilon(myAbsolutError); |
443 | if(anAbsDim >= aVolTol) myErrorReached /= anAbsDim; |
444 | |
445 | if(theCGFlag || theIFlag) { |
446 | // Compute values of center of mass. |
447 | if(anAbsDim >= aVolTol) { |
448 | if (IsByPoint) { |
449 | aValue(2) = aCoeffs[0] + aValue(2)/dim; |
450 | aValue(3) = aCoeffs[1] + aValue(3)/dim; |
451 | aValue(4) = aCoeffs[2] + aValue(4)/dim; |
452 | } else { |
453 | aValue(2) /= dim; |
454 | aValue(3) /= dim; |
455 | aValue(4) /= dim; |
456 | } |
457 | } else { |
458 | aValue(2) = 0.; |
459 | aValue(3) = 0.; |
460 | aValue(4) = 0.; |
461 | dim = 0.; |
462 | } |
463 | g.SetCoord(aValue(2), aValue(3), aValue(4)); |
464 | } |
465 | |
466 | if(theIFlag) { |
467 | // Fill the matrix of inertia. |
468 | inertia.SetCols (gp_XYZ (aValue(5), aValue(8), aValue(9)), |
469 | gp_XYZ (aValue(8), aValue(6), aValue(10)), |
470 | gp_XYZ (aValue(9), aValue(10), aValue(7))); |
471 | } |
472 | //return myErrorReached; |
473 | return myAbsolutError; |
474 | } |
475 | |