7fd59977 |
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 | } |