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[3], 17 const RealType aDist [3]) 18{ 19 return (Abs(aDist[0]) > aHSize[0] || 20 Abs(aDist[1]) > aHSize[1] || 21 Abs(aDist[2]) > aHSize[2]); 22} 23 24inline Standard_Boolean _compareDistD (const gp_XYZ& aHSize,const gp_XYZ& aDist) 25{ 26 return (Abs(aDist.X()) > aHSize.X() || 27 Abs(aDist.Y()) > aHSize.Y() || 28 Abs(aDist.Z()) > aHSize.Z()); 29} 30 31//======================================================================= 32//function : Add 33//purpose : Update the box by a point 34//======================================================================= 35 36void Bnd_B3x::Add (const gp_XYZ& thePnt) { 37 if (IsVoid()) { 38 myCenter[0] = RealType(thePnt.X()); 39 myCenter[1] = RealType(thePnt.Y()); 40 myCenter[2] = RealType(thePnt.Z()); 41 myHSize [0] = 0.; 42 myHSize [1] = 0.; 43 myHSize [2] = 0.; 44 } else { 45 const RealType aDiff[3] = { 46 RealType(thePnt.X()) - myCenter[0], 47 RealType(thePnt.Y()) - myCenter[1], 48 RealType(thePnt.Z()) - myCenter[2] 49 }; 50 if (aDiff[0] > myHSize[0]) { 51 const RealType aShift = (aDiff[0] - myHSize[0]) / 2; 52 myCenter[0] += aShift; 53 myHSize [0] += aShift; 54 } else if (aDiff[0] < -myHSize[0]) { 55 const RealType aShift = (aDiff[0] + myHSize[0]) / 2; 56 myCenter[0] += aShift; 57 myHSize [0] -= aShift; 58 } 59 if (aDiff[1] > myHSize[1]) { 60 const RealType aShift = (aDiff[1] - myHSize[1]) / 2; 61 myCenter[1] +=aShift; 62 myHSize [1] +=aShift; 63 } else if (aDiff[1] < -myHSize[1]) { 64 const RealType aShift = (aDiff[1] + myHSize[1]) / 2; 65 myCenter[1] += aShift; 66 myHSize [1] -= aShift; 67 } 68 if (aDiff[2] > myHSize[2]) { 69 const RealType aShift = (aDiff[2] - myHSize[2]) / 2; 70 myCenter[2] +=aShift; 71 myHSize [2] +=aShift; 72 } else if (aDiff[2] < -myHSize[2]) { 73 const RealType aShift = (aDiff[2] + myHSize[2]) / 2; 74 myCenter[2] += aShift; 75 myHSize [2] -= aShift; 76 } 77 } 78} 79 80//======================================================================= 81//function : Limit 82//purpose : limit the current box with the internals of theBox 83//======================================================================= 84 85Standard_Boolean Bnd_B3x::Limit (const Bnd_B3x& theBox) 86{ 87 Standard_Boolean aResult (Standard_False); 88 const RealType diffC[3] = { 89 theBox.myCenter[0] - myCenter[0], 90 theBox.myCenter[1] - myCenter[1], 91 theBox.myCenter[2] - myCenter[2] 92 }; 93 const RealType sumH[3] = { 94 theBox.myHSize[0] + myHSize[0], 95 theBox.myHSize[1] + myHSize[1], 96 theBox.myHSize[2] + myHSize[2] 97 }; 98 // check the condition IsOut 99 if (_compareDist (sumH, diffC) == Standard_False) { 100 const RealType diffH[3] = { 101 theBox.myHSize[0] - myHSize[0], 102 theBox.myHSize[1] - myHSize[1], 103 theBox.myHSize[2] - myHSize[2] 104 }; 105 if (diffC[0] - diffH[0] > 0.) { 106 const RealType aShift = (diffC[0] - diffH[0]) / 2; // positive 107 myCenter[0] += aShift; 108 myHSize [0] -= aShift; 109 } else if (diffC[0] + diffH[0] < 0.) { 110 const RealType aShift = (diffC[0] + diffH[0]) / 2; // negative 111 myCenter[0] += aShift; 112 myHSize [0] += aShift; 113 } 114 if (diffC[1] - diffH[1] > 0.) { 115 const RealType aShift = (diffC[1] - diffH[1]) / 2; // positive 116 myCenter[1] += aShift; 117 myHSize [1] -= aShift; 118 } else if (diffC[1] + diffH[1] < 0.) { 119 const RealType aShift = (diffC[1] + diffH[1]) / 2; // negative 120 myCenter[1] += aShift; 121 myHSize [1] += aShift; 122 } 123 if (diffC[2] - diffH[2] > 0.) { 124 const RealType aShift = (diffC[2] - diffH[2]) / 2; // positive 125 myCenter[2] += aShift; 126 myHSize [2] -= aShift; 127 } else if (diffC[2] + diffH[2] < 0.) { 128 const RealType aShift = (diffC[2] + diffH[2]) / 2; // negative 129 myCenter[2] += aShift; 130 myHSize [2] += aShift; 131 } 132 aResult = Standard_True; 133 } 134 return aResult; 135} 136 137//======================================================================= 138//function : Transformed 139//purpose : 140//======================================================================= 141 142Bnd_B3x Bnd_B3x::Transformed (const gp_Trsf& theTrsf) const 143{ 144 Bnd_B3x aResult; 145 const gp_TrsfForm aForm = theTrsf.Form(); 146 const Standard_Real aScale = theTrsf.ScaleFactor(); 147 const Standard_Real aScaleAbs = Abs(aScale); 148 if (aForm == gp_Identity) 149 aResult = * this; 150 else if (aForm== gp_Translation || aForm== gp_PntMirror || aForm== gp_Scale) 151 { 152 aResult.myCenter[0] = 153 (RealType)(myCenter[0] * aScale + theTrsf.TranslationPart().X()); 154 aResult.myCenter[1] = 155 (RealType)(myCenter[1] * aScale + theTrsf.TranslationPart().Y()); 156 aResult.myCenter[2] = 157 (RealType)(myCenter[2] * aScale + theTrsf.TranslationPart().Z()); 158 aResult.myHSize[0] = (RealType)(myHSize[0] * aScaleAbs); 159 aResult.myHSize[1] = (RealType)(myHSize[1] * aScaleAbs); 160 aResult.myHSize[2] = (RealType)(myHSize[2] * aScaleAbs); 161 } else { 162 gp_XYZ aCenter ((Standard_Real)myCenter[0], 163 (Standard_Real)myCenter[1], 164 (Standard_Real)myCenter[2]); 165 theTrsf.Transforms (aCenter); 166 aResult.myCenter[0] = (RealType)aCenter.X(); 167 aResult.myCenter[1] = (RealType)aCenter.Y(); 168 aResult.myCenter[2] = (RealType)aCenter.Z(); 169 170 const Standard_Real * aMat = &theTrsf.HVectorialPart().Value(1,1); 171 aResult.myHSize[0] = (RealType)(aScaleAbs * (Abs(aMat[0]) * myHSize[0]+ 172 Abs(aMat[1]) * myHSize[1]+ 173 Abs(aMat[2]) * myHSize[2])); 174 aResult.myHSize[1] = (RealType)(aScaleAbs * (Abs(aMat[3]) * myHSize[0]+ 175 Abs(aMat[4]) * myHSize[1]+ 176 Abs(aMat[5]) * myHSize[2])); 177 aResult.myHSize[2] = (RealType)(aScaleAbs * (Abs(aMat[6]) * myHSize[0]+ 178 Abs(aMat[7]) * myHSize[1]+ 179 Abs(aMat[8]) * myHSize[2])); 180 } 181 return aResult; 182} 183 184//======================================================================= 185//function : IsOut 186//purpose : Intersection Box - Sphere 187//======================================================================= 188 189Standard_Boolean Bnd_B3x::IsOut (const gp_XYZ& theCenter, 190 const Standard_Real theRadius, 191 const Standard_Boolean isSphereHollow) const 192{ 193 Standard_Boolean aResult (Standard_True); 194 if (isSphereHollow == Standard_False) { 195 // vector from the center of the sphere to the nearest box face 196 const Standard_Real aDist[3] = { 197 Abs(theCenter.X()-Standard_Real(myCenter[0])) - Standard_Real(myHSize[0]), 198 Abs(theCenter.Y()-Standard_Real(myCenter[1])) - Standard_Real(myHSize[1]), 199 Abs(theCenter.Z()-Standard_Real(myCenter[2])) - Standard_Real(myHSize[2]) 200 }; 201 Standard_Real aD (0.); 202 if (aDist[0] > 0.) 203 aD = aDist[0]*aDist[0]; 204 if (aDist[1] > 0.) 205 aD += aDist[1]*aDist[1]; 206 if (aDist[2] > 0.) 207 aD += aDist[2]*aDist[2]; 208 aResult = (aD > theRadius*theRadius); 209 } else { 210 const Standard_Real aDistC[3] = { 211 Abs(theCenter.X()-Standard_Real(myCenter[0])), 212 Abs(theCenter.Y()-Standard_Real(myCenter[1])), 213 Abs(theCenter.Z()-Standard_Real(myCenter[2])) 214 }; 215 // vector from the center of the sphere to the nearest box face 216 Standard_Real aDist[3] = { 217 aDistC[0] - Standard_Real(myHSize[0]), 218 aDistC[1] - Standard_Real(myHSize[1]), 219 aDistC[2] - Standard_Real(myHSize[2]) 220 }; 221 Standard_Real aD (0.); 222 if (aDist[0] > 0.) 223 aD = aDist[0]*aDist[0]; 224 if (aDist[1] > 0.) 225 aD += aDist[1]*aDist[1]; 226 if (aDist[2] > 0.) 227 aD += aDist[2]*aDist[2]; 228 if (aD < theRadius*theRadius) { 229 // the box intersects the solid sphere; check if it is completely 230 // inside the circle (in such case return isOut==True) 231 aDist[0] = aDistC[0] + Standard_Real(myHSize[0]); 232 aDist[1] = aDistC[1] + Standard_Real(myHSize[1]); 233 aDist[2] = aDistC[2] + Standard_Real(myHSize[2]); 234 if (aDist[0]*aDist[0]+aDist[1]*aDist[1]+aDist[2]*aDist[2] 235 > theRadius*theRadius) 236 aResult = Standard_False; 237 } 238 } 239 return aResult; 240} 241 242//======================================================================= 243//function : IsOut 244//purpose : Intersection Box - transformed Box 245//======================================================================= 246 247Standard_Boolean Bnd_B3x::IsOut (const Bnd_B3x& theBox, 248 const gp_Trsf& theTrsf) const 249{ 250 Standard_Boolean aResult (Standard_False); 251 const gp_TrsfForm aForm = theTrsf.Form(); 252 const Standard_Real aScale = theTrsf.ScaleFactor(); 253 const Standard_Real aScaleAbs = Abs(aScale); 254 if (aForm == gp_Translation || aForm == gp_Identity || 255 aForm == gp_PntMirror || aForm == gp_Scale) 256 { 257 aResult = 258 (Abs (RealType(theBox.myCenter[0]*aScale + theTrsf.TranslationPart().X()) 259 - myCenter[0]) 260 > RealType (theBox.myHSize[0]*aScaleAbs) + myHSize[0] || 261 Abs (RealType(theBox.myCenter[1]*aScale + theTrsf.TranslationPart().Y()) 262 - myCenter[1]) 263 > RealType (theBox.myHSize[1]*aScaleAbs) + myHSize[1] || 264 Abs (RealType(theBox.myCenter[2]*aScale + theTrsf.TranslationPart().Y()) 265 - myCenter[2]) 266 > RealType (theBox.myHSize[2]*aScaleAbs) + myHSize[2]); 267 268 } 269 else { 270 // theBox is transformed and we check the resulting (enlarged) box against 271 // 'this' box. 272 const Standard_Real * aMat = &theTrsf.HVectorialPart().Value(1,1); 273 274 gp_XYZ aCenter ((Standard_Real)theBox.myCenter[0], 275 (Standard_Real)theBox.myCenter[1], 276 (Standard_Real)theBox.myCenter[2]); 277 theTrsf.Transforms (aCenter); 278 const Standard_Real aDist[3] = { 279 aCenter.X() - (Standard_Real)myCenter[0], 280 aCenter.Y() - (Standard_Real)myCenter[1], 281 aCenter.Z() - (Standard_Real)myCenter[2] 282 }; 283 const Standard_Real aMatAbs[9] = { 284 Abs(aMat[0]), Abs(aMat[1]), Abs(aMat[2]), Abs(aMat[3]), Abs(aMat[4]), 285 Abs(aMat[5]), Abs(aMat[6]), Abs(aMat[7]), Abs(aMat[8]) 286 }; 287 if (Abs(aDist[0]) > (aScaleAbs*(aMatAbs[0]*theBox.myHSize[0]+ 288 aMatAbs[1]*theBox.myHSize[1]+ 289 aMatAbs[2]*theBox.myHSize[2]) + 290 (Standard_Real)myHSize[0]) || 291 Abs(aDist[1]) > (aScaleAbs*(aMatAbs[3]*theBox.myHSize[0]+ 292 aMatAbs[4]*theBox.myHSize[1]+ 293 aMatAbs[5]*theBox.myHSize[2]) + 294 (Standard_Real)myHSize[1]) || 295 Abs(aDist[2]) > (aScaleAbs*(aMatAbs[6]*theBox.myHSize[0]+ 296 aMatAbs[7]*theBox.myHSize[1]+ 297 aMatAbs[8]*theBox.myHSize[2]) + 298 (Standard_Real)myHSize[2])) 299 aResult = Standard_True; 300 301 else { 302 // theBox is rotated, scaled and translated. We apply the reverse 303 // translation and scaling then check against the rotated box 'this' 304 if ((Abs(aMat[0]*aDist[0]+aMat[3]*aDist[1]+aMat[6]*aDist[2]) 305 > theBox.myHSize[0]*aScaleAbs + (aMatAbs[0]*myHSize[0] + 306 aMatAbs[3]*myHSize[1] + 307 aMatAbs[6]*myHSize[2])) || 308 (Abs(aMat[1]*aDist[0]+aMat[4]*aDist[1]+aMat[7]*aDist[2]) 309 > theBox.myHSize[1]*aScaleAbs + (aMatAbs[1]*myHSize[0] + 310 aMatAbs[4]*myHSize[1] + 311 aMatAbs[7]*myHSize[2])) || 312 (Abs(aMat[2]*aDist[0]+aMat[5]*aDist[1]+aMat[8]*aDist[2]) 313 > theBox.myHSize[2]*aScaleAbs + (aMatAbs[2]*myHSize[0] + 314 aMatAbs[5]*myHSize[1] + 315 aMatAbs[8]*myHSize[2]))) 316 aResult = Standard_True; 317 } 318 } 319 return aResult; 320} 321 322//======================================================================= 323//function : IsOut 324//purpose : 325//======================================================================= 326 327Standard_Boolean Bnd_B3x::IsOut (const gp_Ax3& thePlane) const 328{ 329 if (IsVoid()) 330 return Standard_True; 331 const gp_XYZ& anOrigin = thePlane.Location().XYZ(); 332 const gp_XYZ& aDir = thePlane.Direction().XYZ(); 333 const gp_XYZ aBoxCenter ((Standard_Real)myCenter[0], 334 (Standard_Real)myCenter[1], 335 (Standard_Real)myCenter[2]); 336 const Standard_Real aDist0 = (aBoxCenter - anOrigin) * aDir; 337 // Find the signed distances from two opposite corners of the box to the plane 338 // If the distances are not the same sign, then the plane crosses the box 339 const Standard_Real aDist1 = // proj of HSize on aDir 340 Standard_Real(myHSize[0]) * Abs(aDir.X()) + 341 Standard_Real(myHSize[1]) * Abs(aDir.Y()) + 342 Standard_Real(myHSize[2]) * Abs(aDir.Z()); 343 return ((aDist0 + aDist1) * (aDist0 - aDist1) > 0.); 344} 345 346//======================================================================= 347//function : IsOut 348//purpose : 349//======================================================================= 350 351Standard_Boolean Bnd_B3x::IsOut (const gp_Ax1& theLine, 352 const Standard_Boolean isRay, 353 const Standard_Real theOverthickness) const 354{ 355 const Standard_Real aRes = gp::Resolution() * 100.; 356 if (IsVoid()) 357 return Standard_True; 358 Standard_Real 359 anInter0[2] = {-RealLast(), RealLast()}, 360 anInter1[2] = {-RealLast(), RealLast()}; 361 const gp_XYZ& aDir = theLine.Direction().XYZ(); 362 const gp_XYZ aDiff ((Standard_Real)myCenter[0] - theLine.Location().X(), 363 (Standard_Real)myCenter[1] - theLine.Location().Y(), 364 (Standard_Real)myCenter[2] - theLine.Location().Z()); 365 366 // Find the parameter interval in X dimension 367 Standard_Real aHSize = (Standard_Real)myHSize[0]+theOverthickness; 368 if (aDir.X() > aRes) { 369 anInter0[0]= (aDiff.X() - aHSize) / aDir.X(); 370 anInter0[1]= (aDiff.X() + aHSize) / aDir.X(); 371 } else if (aDir.X() < -aRes) { 372 anInter0[0]= (aDiff.X() + aHSize) / aDir.X(); 373 anInter0[1]= (aDiff.X() - aHSize) / aDir.X(); 374 } else 375 // the line is orthogonal to OX axis. Test for inclusion in box limits 376 if (Abs(aDiff.X()) > aHSize) 377 return Standard_True; 378 379 // Find the parameter interval in Y dimension 380 aHSize = (Standard_Real)myHSize[1]+theOverthickness; 381 if (aDir.Y() > aRes) { 382 anInter1[0]= (aDiff.Y() - aHSize) / aDir.Y(); 383 anInter1[1]= (aDiff.Y() + aHSize) / aDir.Y(); 384 } else if (aDir.Y() < -aRes) { 385 anInter1[0]= (aDiff.Y() + aHSize) / aDir.Y(); 386 anInter1[1]= (aDiff.Y() - aHSize) / aDir.Y(); 387 } else 388 // the line is orthogonal to OY axis. Test for inclusion in box limits 389 if (Abs(aDiff.Y()) > aHSize) 390 return Standard_True; 391 392 // Intersect Y-interval with X-interval 393 if (anInter0[0] > (anInter1[1] + aRes) || anInter0[1] < (anInter1[0] - aRes)) 394 return Standard_True; 395 if (anInter1[0] > anInter0[0]) 396 anInter0[0] = anInter1[0]; 397 if (anInter1[1] < anInter0[1]) 398 anInter0[1] = anInter1[1]; 399 if (isRay && anInter0[1] < -aRes) 400 return Standard_True; 401 402 // Find the parameter interval in Z dimension 403 aHSize = (Standard_Real)myHSize[2]+theOverthickness; 404 if (aDir.Z() > aRes) { 405 anInter1[0]= (aDiff.Z() - aHSize) / aDir.Z(); 406 anInter1[1]= (aDiff.Z() + aHSize) / aDir.Z(); 407 } else if (aDir.Z() < -aRes) { 408 anInter1[0]= (aDiff.Z() + aHSize) / aDir.Z(); 409 anInter1[1]= (aDiff.Z() - aHSize) / aDir.Z(); 410 } else 411 // the line is orthogonal to OZ axis. Test for inclusion in box limits 412 return (Abs(aDiff.Z()) > aHSize); 413 if (isRay && anInter1[1] < -aRes) 414 return Standard_True; 415 416 return (anInter0[0] > (anInter1[1]+aRes) || anInter0[1] < (anInter1[0]-aRes)); 417} 418 419//======================================================================= 420//function : IsIn 421//purpose : Test the complete inclusion of this box in transformed theOtherBox 422//======================================================================= 423 424Standard_Boolean Bnd_B3x::IsIn (const Bnd_B3x& theBox, 425 const gp_Trsf& theTrsf) const 426{ 427 Standard_Boolean aResult (Standard_False); 428 const gp_TrsfForm aForm = theTrsf.Form(); 429 const Standard_Real aScale = theTrsf.ScaleFactor(); 430 const Standard_Real aScaleAbs = Abs(aScale); 431 if (aForm == gp_Translation || aForm == gp_Identity || 432 aForm == gp_PntMirror || aForm == gp_Scale) 433 { 434 aResult = 435 (Abs (RealType(theBox.myCenter[0]*aScale + theTrsf.TranslationPart().X()) 436 - myCenter[0]) 437 < RealType (theBox.myHSize[0]*aScaleAbs) - myHSize[0] && 438 Abs (RealType(theBox.myCenter[1]*aScale + theTrsf.TranslationPart().Y()) 439 - myCenter[1]) 440 < RealType (theBox.myHSize[1]*aScaleAbs) - myHSize[1] && 441 Abs (RealType(theBox.myCenter[2]*aScale + theTrsf.TranslationPart().Y()) 442 - myCenter[2]) 443 < RealType (theBox.myHSize[2]*aScaleAbs) - myHSize[2]); 444 445 } else { 446 // theBox is rotated, scaled and translated. We apply the reverse 447 // translation and scaling then check against the rotated box 'this' 448 const Standard_Real * aMat = &theTrsf.HVectorialPart().Value(1,1); 449 gp_XYZ aCenter ((Standard_Real)theBox.myCenter[0], 450 (Standard_Real)theBox.myCenter[1], 451 (Standard_Real)theBox.myCenter[2]); 452 theTrsf.Transforms (aCenter); 453 const Standard_Real aDist[3] = { 454 aCenter.X() - (Standard_Real)myCenter[0], 455 aCenter.Y() - (Standard_Real)myCenter[1], 456 aCenter.Z() - (Standard_Real)myCenter[2] 457 }; 458 if ((Abs(aMat[0]*aDist[0]+aMat[3]*aDist[1]+aMat[6]*aDist[2]) 459 < theBox.myHSize[0]*aScaleAbs - (Abs(aMat[0])*myHSize[0] + 460 Abs(aMat[3])*myHSize[1] + 461 Abs(aMat[6])*myHSize[2])) && 462 (Abs(aMat[1]*aDist[0]+aMat[4]*aDist[1]+aMat[7]*aDist[2]) 463 < theBox.myHSize[1]*aScaleAbs - (Abs(aMat[1])*myHSize[0] + 464 Abs(aMat[4])*myHSize[1] + 465 Abs(aMat[7])*myHSize[2])) && 466 (Abs(aMat[2]*aDist[0]+aMat[5]*aDist[1]+aMat[8]*aDist[2]) 467 < theBox.myHSize[2]*aScaleAbs - (Abs(aMat[2])*myHSize[0] + 468 Abs(aMat[5])*myHSize[1] + 469 Abs(aMat[8])*myHSize[2]))) 470 aResult = Standard_True; 471 } 472 return aResult; 473} 474 475