1 // Created on: 2005-09-08
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2005-2012 OPEN CASCADE SAS
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.
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.
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.
21 inline Standard_Boolean _compareDist (const RealType aHSize[2],
22 const RealType aDist[2])
24 return (Abs(aDist[0]) > aHSize[0] || Abs(aDist[1]) > aHSize[1]);
27 inline Standard_Boolean _compareDistD (const gp_XY& aHSize, const gp_XY& aDist)
29 return (Abs(aDist.X()) > aHSize.X() || Abs(aDist.Y()) > aHSize.Y());
32 //=======================================================================
34 //purpose : Update the box by a point
35 //=======================================================================
37 void Bnd_B2x::Add (const gp_XY& thePnt) {
39 myCenter[0] = RealType(thePnt.X());
40 myCenter[1] = RealType(thePnt.Y());
44 const RealType aDiff[2] = {
45 RealType(thePnt.X()) - myCenter[0],
46 RealType(thePnt.Y()) - myCenter[1]
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;
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;
69 //=======================================================================
71 //purpose : limit the current box with the internals of theBox
72 //=======================================================================
74 Standard_Boolean Bnd_B2x::Limit (const Bnd_B2x& theBox)
76 Standard_Boolean aResult (Standard_False);
77 const RealType diffC[2] = {
78 theBox.myCenter[0] - myCenter[0],
79 theBox.myCenter[1] - myCenter[1]
81 const RealType sumH[2] = {
82 theBox.myHSize[0] + myHSize[0],
83 theBox.myHSize[1] + myHSize[1]
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]
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;
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;
109 aResult = Standard_True;
114 //=======================================================================
115 //function : Transformed
117 //=======================================================================
119 Bnd_B2x Bnd_B2x::Transformed (const gp_Trsf2d& theTrsf) const
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)
127 else if (aForm== gp_Translation || aForm== gp_PntMirror || aForm== gp_Scale)
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);
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();
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]));
151 //=======================================================================
153 //purpose : Intersection Box - Circle
154 //=======================================================================
156 Standard_Boolean Bnd_B2x::IsOut (const gp_XY& theCenter,
157 const Standard_Real theRadius,
158 const Standard_Boolean isCircleHollow) const
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])
167 Standard_Real aD (0.);
169 aD = aDist[0]*aDist[0];
171 aD += aDist[1]*aDist[1];
172 aResult = (aD > theRadius*theRadius);
174 const Standard_Real aDistC[2] = {
175 Abs(theCenter.X()-Standard_Real(myCenter[0])),
176 Abs(theCenter.Y()-Standard_Real(myCenter[1]))
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])
183 Standard_Real aD (0.);
185 aD = aDist[0]*aDist[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;
200 //=======================================================================
202 //purpose : Intersection Box - transformed Box
203 //=======================================================================
205 Standard_Boolean Bnd_B2x::IsOut (const Bnd_B2x& theBox,
206 const gp_Trsf2d& theTrsf) const
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)
216 (Abs (RealType(theBox.myCenter[0]*aScale + theTrsf.TranslationPart().X())
218 > RealType (theBox.myHSize[0]*aScaleAbs) + myHSize[0] ||
219 Abs (RealType(theBox.myCenter[1]*aScale + theTrsf.TranslationPart().Y())
221 > RealType (theBox.myHSize[1]*aScaleAbs) + myHSize[1]);
225 // theBox is transformed and we check the resulting (enlarged) box against
227 const Standard_Real * aMat = &theTrsf.HVectorialPart().Value(1,1);
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]
236 const Standard_Real aMatAbs[4] = {
237 Abs(aMat[0]), Abs(aMat[1]), Abs(aMat[2]), Abs(aMat[3])
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;
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;
262 //=======================================================================
264 //purpose : Intersection Box - Line
265 //=======================================================================
267 Standard_Boolean Bnd_B2x::IsOut (const gp_Ax2d& theLine) const
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])
278 return (Abs(aProd[0]) > (Abs(aProd[1]) + Abs(aProd[2])));
281 //=======================================================================
283 //purpose : Intersection Box - Segment
284 //=======================================================================
286 Standard_Boolean Bnd_B2x::IsOut (const gp_XY& theP0, const gp_XY& theP1) const
288 Standard_Boolean aResult (Standard_True);
289 if (IsVoid() == Standard_False)
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])
298 if (Abs(aProd[0]) < (Abs(aProd[1]) + Abs(aProd[2])))
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]));
312 //=======================================================================
314 //purpose : Test the complete inclusion of this box in transformed theOtherBox
315 //=======================================================================
317 Standard_Boolean Bnd_B2x::IsIn (const Bnd_B2x& theBox,
318 const gp_Trsf2d& theTrsf) const
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)
328 (Abs (RealType(theBox.myCenter[0]*aScale + theTrsf.TranslationPart().X())
330 < RealType (theBox.myHSize[0]*aScaleAbs) - myHSize[0] &&
331 Abs (RealType(theBox.myCenter[1]*aScale + theTrsf.TranslationPart().Y())
333 < RealType (theBox.myHSize[1]*aScaleAbs) - myHSize[1]);
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]
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;