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