fc5ac30ae5ea211cc453fcc2397e804b848ed34d
[occt.git] / src / GProp / GProp_UFunction.gxx
1 // Created on: 2005-12-09
2 // Created by: Sergey KHROMOV
3 // Copyright (c) 2005-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 //=======================================================================
17 //function : Constructor.
18 //purpose  : 
19 //=======================================================================
20
21 GProp_UFunction::GProp_UFunction(const Face             &theSurface,
22                                  const gp_Pnt           &theVertex,
23                                  const Standard_Boolean  IsByPoint,
24                                  const Standard_Address  theCoeffs)
25      : mySurface(theSurface),
26        myVertex(theVertex),
27        myCoeffs(theCoeffs),
28        myVParam(0.),
29        myValueType(GProp_Unknown),
30        myIsByPoint(IsByPoint)
31 {
32 }
33
34 //=======================================================================
35 //function : Value
36 //purpose  : Returns a value of the function.
37 //=======================================================================
38
39 Standard_Boolean GProp_UFunction::Value(const Standard_Real  X,
40                                               Standard_Real &F)
41 {
42   // Volume computation
43   if (myValueType == GProp_Mass) {
44     gp_XYZ        aPMP0;
45     Standard_Real aTmpPar1;
46     Standard_Real aTmpPar2;
47
48     F = VolumeValue(X, aPMP0, aTmpPar1, aTmpPar2);
49
50     return Standard_True;
51   }
52
53   // Center of mass computation
54   if (myValueType == GProp_CenterMassX ||
55       myValueType == GProp_CenterMassY ||
56       myValueType == GProp_CenterMassZ)
57     return CenterMassValue(X, F);
58
59   // Inertia computation
60   if (myValueType == GProp_InertiaXX ||
61       myValueType == GProp_InertiaYY ||
62       myValueType == GProp_InertiaZZ ||
63       myValueType == GProp_InertiaXY ||
64       myValueType == GProp_InertiaXZ ||
65       myValueType == GProp_InertiaYZ)
66     return InertiaValue(X, F);
67
68   return Standard_False;
69 }
70
71 //=======================================================================
72 //function : VolumeValue
73 //purpose  : Returns the value for volume computation.
74 //=======================================================================
75
76 Standard_Real GProp_UFunction::VolumeValue(const Standard_Real  X,
77                                                  gp_XYZ        &thePMP0,
78                                                  Standard_Real &theS,
79                                                  Standard_Real &theD1)
80 {
81   gp_Pnt aPnt;
82   gp_Vec aNorm;
83
84   mySurface.Normal(X, myVParam, aPnt, aNorm);
85
86   thePMP0 = aPnt.XYZ().Subtracted(myVertex.XYZ());
87
88   // Volume computation for ByPoint mode.
89   if (myIsByPoint)
90     return thePMP0.Dot(aNorm.XYZ());
91
92   // Volume and additional coefficients computation for ByPlane mode.
93   Standard_Real *aCoeff = (Standard_Real *)myCoeffs;
94
95   theS  =   aNorm.X()*aCoeff[0] + aNorm.Y()*aCoeff[1] + aNorm.Z()*aCoeff[2];
96   theD1 =   thePMP0.X()*aCoeff[0] + thePMP0.Y()*aCoeff[1]
97           + thePMP0.Z()*aCoeff[2] - aCoeff[3];
98
99   return theS*theD1;
100 }
101
102 //=======================================================================
103 //function : CenterMassValue
104 //purpose  : Returns a value for the center of mass computation.
105 //=======================================================================
106
107 Standard_Boolean GProp_UFunction::CenterMassValue(const Standard_Real  X,
108                                                         Standard_Real &F)
109 {
110   gp_XYZ        aPmP0;
111   Standard_Real aS;
112   Standard_Real aD1;
113
114   F = VolumeValue(X, aPmP0, aS, aD1);
115
116   // Center of mass computation for ByPoint mode.
117   if (myIsByPoint) {
118     switch (myValueType) {
119     case GProp_CenterMassX:   F *= aPmP0.X(); break;
120     case GProp_CenterMassY:   F *= aPmP0.Y(); break;
121     case GProp_CenterMassZ:   F *= aPmP0.Z(); break;
122     default:
123       return Standard_False;
124     }
125
126     return Standard_True;
127   }
128
129   // Center of mass computation for ByPlane mode.
130   Standard_Real *aCoeff = (Standard_Real *)myCoeffs;
131
132   switch (myValueType) {
133   case GProp_CenterMassX:   F *= (aPmP0.X() - 0.5*aCoeff[0]*aD1); break;
134   case GProp_CenterMassY:   F *= (aPmP0.Y() - 0.5*aCoeff[1]*aD1); break;
135   case GProp_CenterMassZ:   F *= (aPmP0.Z() - 0.5*aCoeff[2]*aD1); break;
136   default:
137     return Standard_False;
138   }
139
140   return Standard_True;
141 }
142
143 //=======================================================================
144 //function : InertiaValue
145 //purpose  : Compute the value of intertia.
146 //=======================================================================
147
148 Standard_Boolean GProp_UFunction::InertiaValue(const Standard_Real  X,
149                                                      Standard_Real &F)
150 {
151   gp_XYZ        aPmP0;
152   Standard_Real aS;
153   Standard_Real aD1;
154   Standard_Real aParam1;
155   Standard_Real aParam2;
156   Standard_Real *aCoeffs = (Standard_Real *)myCoeffs;
157
158   F = VolumeValue(X, aPmP0, aS, aD1);
159
160   // Inertia computation for ByPoint mode.
161   if (myIsByPoint) {
162     switch(myValueType) {
163     case GProp_InertiaXX:
164     case GProp_InertiaYZ:
165       aParam1 = aPmP0.Y() - aCoeffs[1];
166       aParam2 = aPmP0.Z() - aCoeffs[2];
167       break;
168     case GProp_InertiaYY:
169     case GProp_InertiaXZ:
170       aParam1 = aPmP0.X() - aCoeffs[0];
171       aParam2 = aPmP0.Z() - aCoeffs[2];
172       break;
173     case GProp_InertiaZZ:
174     case GProp_InertiaXY:
175       aParam1 = aPmP0.X() - aCoeffs[0];
176       aParam2 = aPmP0.Y() - aCoeffs[1];
177       break;
178     default:
179       return Standard_False;
180     }
181
182     if (myValueType == GProp_InertiaXX ||
183         myValueType == GProp_InertiaYY ||
184         myValueType == GProp_InertiaZZ)
185       F *=  aParam1*aParam1 + aParam2*aParam2;
186     else
187       F *= -aParam1*aParam2;
188
189     return Standard_True;
190   }
191
192   // Inertia computation for ByPlane mode.
193   Standard_Real aD2 = aD1*aD1;
194   Standard_Real aD3 = aD1*aD2/3.;
195   Standard_Real aPPar1;
196   Standard_Real aPPar2;
197   Standard_Real aCoeff1;
198   Standard_Real aCoeff2;
199
200   // Inertia computation for XX, YY and ZZ.
201   if (myValueType == GProp_InertiaXX ||
202       myValueType == GProp_InertiaYY ||
203       myValueType == GProp_InertiaZZ) {
204
205     if (myValueType == GProp_InertiaXX) {
206       aPPar1  = aPmP0.Y();
207       aPPar2  = aPmP0.Z();
208       aCoeff1 = aCoeffs[1];
209       aCoeff2 = aCoeffs[2];
210     } else if (myValueType == GProp_InertiaYY) {
211       aPPar1  = aPmP0.X();
212       aPPar2  = aPmP0.Z();
213       aCoeff1 = aCoeffs[0];
214       aCoeff2 = aCoeffs[2];
215     } else { // myValueType == GProp_InertiaZZ
216       aPPar1  = aPmP0.X();
217       aPPar2  = aPmP0.Y();
218       aCoeff1 = aCoeffs[0];
219       aCoeff2 = aCoeffs[1];
220     }
221
222     aPPar1  -= aCoeff1*aD1;
223     aPPar2  -= aCoeff2*aD1;
224     aParam1  = aPPar1*aPPar1*aD1 + aPPar1*aCoeff1*aD2 + aCoeff1*aCoeff1*aD3;
225     aParam2  = aPPar2*aPPar2*aD1 + aPPar2*aCoeff2*aD2 + aCoeff2*aCoeff2*aD3;
226
227     F = (aParam1 + aParam2)*aS;
228
229     return Standard_True;
230   }
231
232   // Inertia computation for XY, YZ and XZ.
233   if (myValueType == GProp_InertiaXY ||
234       myValueType == GProp_InertiaYZ ||
235       myValueType == GProp_InertiaXZ) {
236
237     if (myValueType == GProp_InertiaXY) {
238       aPPar1  = aPmP0.X();
239       aPPar2  = aPmP0.Y();
240       aCoeff1 = aCoeffs[0];
241       aCoeff2 = aCoeffs[1];
242     } else if (myValueType == GProp_InertiaYZ) {
243       aPPar1  = aPmP0.Y();
244       aPPar2  = aPmP0.Z();
245       aCoeff1 = aCoeffs[1];
246       aCoeff2 = aCoeffs[2];
247     } else { // myValueType == GProp_InertiaXZ
248       aPPar1  = aPmP0.X();
249       aPPar2  = aPmP0.Z();
250       aCoeff1 = aCoeffs[0];
251       aCoeff2 = aCoeffs[2];
252     }
253
254     aD2     *=   0.5;
255     aPPar1  -=   aCoeff1*aD1;
256     aPPar2  -=   aCoeff2*aD1;
257     aParam1  =   aPPar1*aPPar2*aD1
258                + (aPPar1*aCoeff2 + aPPar2*aCoeff1)*aD2 + aCoeff1*aCoeff2*aD3;
259
260     F = -aParam1*aS;
261
262     return Standard_True;
263   }
264
265   return Standard_False;
266 }