0024177: Eliminate CLang compiler warning -Wlogical-op-parentheses (&& within ||)
[occt.git] / src / Bnd / Bnd_B2x.gxx
1 // Created on: 2005-09-08
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2005-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21 inline Standard_Boolean _compareDist  (const RealType aHSize[2],
22                                        const RealType aDist[2])
23 {
24   return (Abs(aDist[0]) > aHSize[0] || Abs(aDist[1]) > aHSize[1]);
25 }
26
27 inline Standard_Boolean _compareDistD (const gp_XY& aHSize, const gp_XY& aDist)
28 {
29   return (Abs(aDist.X()) > aHSize.X() || Abs(aDist.Y()) > aHSize.Y());
30 }
31
32 //=======================================================================
33 //function : Add
34 //purpose  : Update the box by a point
35 //=======================================================================
36
37 void Bnd_B2x::Add (const gp_XY& thePnt) {
38   if (IsVoid()) {
39     myCenter[0] = RealType(thePnt.X());
40     myCenter[1] = RealType(thePnt.Y());
41     myHSize [0] = 0.;
42     myHSize [1] = 0.;
43   } else {
44     const RealType aDiff[2] = {
45       RealType(thePnt.X()) - myCenter[0],
46       RealType(thePnt.Y()) - myCenter[1]
47     };
48     if (aDiff[0] > myHSize[0]) {
49       const RealType aShift = (aDiff[0] - myHSize[0]) / 2;
50       myCenter[0] += aShift;
51       myHSize [0] += aShift;
52     } else if (aDiff[0] < -myHSize[0]) {
53       const RealType aShift = (aDiff[0] + myHSize[0]) / 2;
54       myCenter[0] += aShift;
55       myHSize [0] -= aShift;
56     }
57     if (aDiff[1] > myHSize[1]) {
58       const RealType aShift = (aDiff[1] - myHSize[1]) / 2;
59       myCenter[1] += aShift;
60       myHSize [1] += aShift;
61     } else if (aDiff[1] < -myHSize[1]) {
62       const RealType aShift = (aDiff[1] + myHSize[1]) / 2;
63       myCenter[1] += aShift;
64       myHSize [1] -= aShift;
65     }
66   }
67 }
68
69 //=======================================================================
70 //function : Limit
71 //purpose  : limit the current box with the internals of theBox
72 //=======================================================================
73
74 Standard_Boolean Bnd_B2x::Limit (const Bnd_B2x& theBox)
75 {
76   Standard_Boolean aResult (Standard_False);
77   const RealType diffC[2] = {
78     theBox.myCenter[0] - myCenter[0],
79     theBox.myCenter[1] - myCenter[1]
80   };
81   const RealType sumH[2] = {
82     theBox.myHSize[0] + myHSize[0],
83     theBox.myHSize[1] + myHSize[1]
84   };
85   // check the condition IsOut
86   if (_compareDist (sumH, diffC) == Standard_False) {
87     const RealType diffH[2] = {
88       theBox.myHSize[0] - myHSize[0],
89       theBox.myHSize[1] - myHSize[1]
90     };
91     if (diffC[0] - diffH[0] > 0.) {
92       const RealType aShift = (diffC[0] - diffH[0]) / 2; // positive
93       myCenter[0] += aShift;
94       myHSize [0] -= aShift;
95     } else if (diffC[0] + diffH[0] < 0.) {
96       const RealType aShift = (diffC[0] + diffH[0]) / 2; // negative
97       myCenter[0] += aShift;
98       myHSize [0] += aShift;
99     }
100     if (diffC[1] - diffH[1] > 0.) {
101       const RealType aShift = (diffC[1] - diffH[1]) / 2; // positive
102       myCenter[1] += aShift;
103       myHSize [1] -= aShift;
104     } else if (diffC[1] + diffH[1] < 0.) {
105       const RealType aShift = (diffC[1] + diffH[1]) / 2; // negative
106       myCenter[1] += aShift;
107       myHSize [1] += aShift;
108     }
109     aResult = Standard_True;
110   }
111   return aResult;
112 }
113
114 //=======================================================================
115 //function : Transformed
116 //purpose  : 
117 //=======================================================================
118
119 Bnd_B2x Bnd_B2x::Transformed (const gp_Trsf2d& theTrsf) const
120 {
121   Bnd_B2x aResult;
122   const gp_TrsfForm aForm = theTrsf.Form();
123   const Standard_Real aScale = theTrsf.ScaleFactor();
124   const Standard_Real aScaleAbs = Abs(aScale);
125   if (aForm == gp_Identity)
126     aResult = * this;
127   else if (aForm== gp_Translation || aForm== gp_PntMirror || aForm== gp_Scale)
128   {
129     aResult.myCenter[0] =
130       (RealType)(myCenter[0] * aScale + theTrsf.TranslationPart().X());
131     aResult.myCenter[1] =
132       (RealType)(myCenter[1] * aScale + theTrsf.TranslationPart().Y());
133     aResult.myHSize[0] = (RealType)(myHSize[0] * aScaleAbs);
134     aResult.myHSize[1] = (RealType)(myHSize[1] * aScaleAbs);
135   } else {
136     gp_XY aCenter ((Standard_Real)myCenter[0],
137                    (Standard_Real)myCenter[1]);
138     theTrsf.Transforms (aCenter);
139     aResult.myCenter[0] = (RealType)aCenter.X();
140     aResult.myCenter[1] = (RealType)aCenter.Y();
141
142     const Standard_Real * aMat = &theTrsf.HVectorialPart().Value(1,1);
143     aResult.myHSize[0] = (RealType)(aScaleAbs * (Abs(aMat[0]) * myHSize[0]+
144                                                  Abs(aMat[1]) * myHSize[1]));
145     aResult.myHSize[1] = (RealType)(aScaleAbs * (Abs(aMat[2]) * myHSize[0]+
146                                                  Abs(aMat[3]) * myHSize[1]));
147   }
148   return aResult;
149 }
150
151 //=======================================================================
152 //function : IsOut
153 //purpose  : Intersection Box - Circle
154 //=======================================================================
155
156 Standard_Boolean Bnd_B2x::IsOut (const gp_XY&           theCenter,
157                                  const Standard_Real    theRadius,
158                                  const Standard_Boolean isCircleHollow) const
159 {
160   Standard_Boolean aResult (Standard_True);
161   if (isCircleHollow == Standard_False) {
162     // vector from the center of the circle to the nearest box face
163     const Standard_Real aDist[2] = {
164       Abs(theCenter.X()-Standard_Real(myCenter[0])) - Standard_Real(myHSize[0]),
165       Abs(theCenter.Y()-Standard_Real(myCenter[1])) - Standard_Real(myHSize[1])
166     };
167     Standard_Real aD (0.);
168     if (aDist[0] > 0.)
169       aD  = aDist[0]*aDist[0];
170     if (aDist[1] > 0.)
171       aD += aDist[1]*aDist[1];
172     aResult = (aD > theRadius*theRadius);
173   } else {
174     const Standard_Real aDistC[2] = {
175       Abs(theCenter.X()-Standard_Real(myCenter[0])),
176       Abs(theCenter.Y()-Standard_Real(myCenter[1]))
177     };
178     // vector from the center of the circle to the nearest box face
179     Standard_Real aDist[2] = {
180       aDistC[0] - Standard_Real(myHSize[0]),
181       aDistC[1] - Standard_Real(myHSize[1])
182     };
183     Standard_Real aD (0.);
184     if (aDist[0] > 0.)
185       aD  = aDist[0]*aDist[0];
186     if (aDist[1] > 0.)
187       aD += aDist[1]*aDist[1];
188     if (aD < theRadius*theRadius) {
189       // the box intersects the solid circle; check if it is completely
190       // inside the circle (in such case return isOut==True)
191       aDist[0] = aDistC[0] + Standard_Real(myHSize[0]);
192       aDist[1] = aDistC[1] + Standard_Real(myHSize[1]);
193       if (aDist[0]*aDist[0]+aDist[1]*aDist[1] > theRadius*theRadius)
194         aResult = Standard_False;
195     }
196   }
197   return aResult;
198 }
199
200 //=======================================================================
201 //function : IsOut
202 //purpose  : Intersection Box - transformed Box
203 //=======================================================================
204
205 Standard_Boolean Bnd_B2x::IsOut (const Bnd_B2x&   theBox,
206                                  const gp_Trsf2d& theTrsf) const
207 {
208   Standard_Boolean aResult (Standard_False);
209   const gp_TrsfForm aForm = theTrsf.Form();
210   const Standard_Real aScale = theTrsf.ScaleFactor();
211   const Standard_Real aScaleAbs = Abs(aScale);
212   if (aForm == gp_Translation || aForm == gp_Identity ||
213       aForm == gp_PntMirror   || aForm == gp_Scale)
214   {
215     aResult =
216       (Abs (RealType(theBox.myCenter[0]*aScale + theTrsf.TranslationPart().X())
217             - myCenter[0])
218          > RealType (theBox.myHSize[0]*aScaleAbs) + myHSize[0] ||
219        Abs (RealType(theBox.myCenter[1]*aScale + theTrsf.TranslationPart().Y())
220             - myCenter[1])
221          > RealType (theBox.myHSize[1]*aScaleAbs) + myHSize[1]);
222
223   }
224   else {
225     // theBox is transformed and we check the resulting (enlarged) box against
226     // 'this' box.
227     const Standard_Real * aMat = &theTrsf.HVectorialPart().Value(1,1);
228
229     gp_XY aCenter ((Standard_Real)theBox.myCenter[0],
230                    (Standard_Real)theBox.myCenter[1]);
231     theTrsf.Transforms (aCenter);
232     const Standard_Real aDist[2] = {
233       aCenter.X() - (Standard_Real)myCenter[0],
234       aCenter.Y() - (Standard_Real)myCenter[1]
235     };
236     const Standard_Real aMatAbs[4] = {
237       Abs(aMat[0]), Abs(aMat[1]), Abs(aMat[2]), Abs(aMat[3])
238     };
239     if (Abs(aDist[0]) > (aScaleAbs * (aMatAbs[0]*theBox.myHSize[0]+
240                                       aMatAbs[1]*theBox.myHSize[1]) +
241                          (Standard_Real)myHSize[0])    ||
242         Abs(aDist[1]) > (aScaleAbs * (aMatAbs[2]*theBox.myHSize[0]+
243                                       aMatAbs[3]*theBox.myHSize[1]) +
244                          (Standard_Real)myHSize[1]))
245       aResult = Standard_True;
246
247     else {
248     // theBox is rotated, scaled and translated. We apply the reverse
249     // translation and scaling then check against the rotated box 'this'
250       if ((Abs(aMat[0]*aDist[0]+aMat[2]*aDist[1])
251            > theBox.myHSize[0]*aScaleAbs + (aMatAbs[0]*myHSize[0] +
252                                             aMatAbs[2]*myHSize[1])) ||
253           (Abs(aMat[1]*aDist[0]+aMat[3]*aDist[1])
254            > theBox.myHSize[1]*aScaleAbs + (aMatAbs[1]*myHSize[0] +
255                                             aMatAbs[3]*myHSize[1])))
256         aResult = Standard_True;
257     }
258   }
259   return aResult;
260 }
261
262 //=======================================================================
263 //function : IsOut
264 //purpose  : Intersection Box - Line
265 //=======================================================================
266
267 Standard_Boolean Bnd_B2x::IsOut (const gp_Ax2d& theLine) const
268 {
269   if (IsVoid())
270     return Standard_True;
271   // Intersect the line containing the segment.
272   const Standard_Real aProd[3] = {
273     theLine.Direction().XY() ^ (gp_XY (myCenter[0] - theLine.Location().X(),
274                                        myCenter[1] - theLine.Location().Y())),
275     theLine.Direction().X() * Standard_Real(myHSize[1]),
276     theLine.Direction().Y() * Standard_Real(myHSize[0])
277   };
278   return (Abs(aProd[0]) > (Abs(aProd[1]) + Abs(aProd[2])));
279 }
280
281 //=======================================================================
282 //function : IsOut
283 //purpose  : Intersection Box - Segment
284 //=======================================================================
285
286 Standard_Boolean Bnd_B2x::IsOut (const gp_XY& theP0, const gp_XY& theP1) const
287 {
288   Standard_Boolean aResult (Standard_True);
289   if (IsVoid() == Standard_False)
290   {
291     // Intersect the line containing the segment.
292     const gp_XY aSegDelta (theP1 - theP0);
293     const Standard_Real aProd[3] = {
294       aSegDelta ^ (gp_XY (myCenter[0], myCenter[1]) - theP0),
295       aSegDelta.X() * Standard_Real(myHSize[1]),
296       aSegDelta.Y() * Standard_Real(myHSize[0])
297     };
298     if (Abs(aProd[0]) < (Abs(aProd[1]) + Abs(aProd[2])))
299     {
300       // Intersection with line detected; check the segment as bounding box
301       const gp_XY aHSeg    (0.5 * aSegDelta.X(), 0.5 * aSegDelta.Y());
302       const gp_XY aHSegAbs (Abs(aHSeg.X()), Abs(aHSeg.Y()));
303       aResult = _compareDistD (gp_XY((Standard_Real)myHSize[0],
304                                      (Standard_Real)myHSize[1]) + aHSegAbs,
305                                theP0 + aHSeg-gp_XY((Standard_Real)myCenter[0],
306                                                    (Standard_Real)myCenter[1]));
307     }
308   }
309   return aResult;
310 }
311
312 //=======================================================================
313 //function : IsIn
314 //purpose  : Test the complete inclusion of this box in transformed theOtherBox
315 //=======================================================================
316
317 Standard_Boolean Bnd_B2x::IsIn (const Bnd_B2x&   theBox,
318                                 const gp_Trsf2d& theTrsf) const
319 {
320   Standard_Boolean aResult (Standard_False);
321   const gp_TrsfForm aForm = theTrsf.Form();
322   const Standard_Real aScale = theTrsf.ScaleFactor();
323   const Standard_Real aScaleAbs = Abs(aScale);
324   if (aForm == gp_Translation || aForm == gp_Identity ||
325       aForm == gp_PntMirror   || aForm == gp_Scale)
326   {
327     aResult =
328       (Abs (RealType(theBox.myCenter[0]*aScale + theTrsf.TranslationPart().X())
329             - myCenter[0])
330          < RealType (theBox.myHSize[0]*aScaleAbs) - myHSize[0] &&
331        Abs (RealType(theBox.myCenter[1]*aScale + theTrsf.TranslationPart().Y())
332             - myCenter[1])
333          < RealType (theBox.myHSize[1]*aScaleAbs) - myHSize[1]);
334
335   } else {
336     // theBox is rotated, scaled and translated. We apply the reverse
337     // translation and scaling then check against the rotated box 'this'
338     const Standard_Real * aMat = &theTrsf.HVectorialPart().Value(1,1);
339     gp_XY aCenter ((Standard_Real)theBox.myCenter[0],
340                    (Standard_Real)theBox.myCenter[1]);
341     theTrsf.Transforms (aCenter);
342     const Standard_Real aDist[2] = {
343       aCenter.X() - (Standard_Real)myCenter[0],
344       aCenter.Y() - (Standard_Real)myCenter[1]
345     };
346     if ((Abs(aMat[0]*aDist[0]+aMat[2]*aDist[1])
347          < theBox.myHSize[0]*aScaleAbs - (Abs(aMat[0])*myHSize[0] +
348                                           Abs(aMat[2])*myHSize[1])) &&
349         (Abs(aMat[1]*aDist[0]+aMat[3]*aDist[1])
350          < theBox.myHSize[1]*aScaleAbs - (Abs(aMat[1])*myHSize[0] +
351                                           Abs(aMat[3])*myHSize[1])))
352       aResult = Standard_True;
353   }
354   return aResult;
355 }