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 | |
16 | inline 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 | |
22 | inline 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 | |
32 | void 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 | |
69 | Standard_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 | |
114 | Bnd_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 | |
151 | Standard_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 | |
200 | Standard_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 | |
262 | Standard_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 | |
281 | Standard_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 | |
312 | Standard_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 | } |