1// Created on: 2005-09-08 2// Created by: Alexander GRIGORIEV 3// Copyright (c) 2005-2014 OPEN CASCADE SAS 4// 5// This file is part of Open CASCADE Technology software library. 6// 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 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. 12// 13// Alternatively, this file may be used under the terms of Open CASCADE 14// commercial license or contractual agreement. 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} 351