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