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