OpenLexocad  27.1
BoundBox.h
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (c) 2005 Imetric 3D GmbH *
3  * *
4  * This file is part of the FreeCAD CAx development system. *
5  * *
6  * This library is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU Library General Public *
8  * License as published by the Free Software Foundation; either *
9  * version 2 of the License, or (at your option) any later version. *
10  * *
11  * This library is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14  * GNU Library General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU Library General Public *
17  * License along with this library; see the file COPYING.LIB. If not, *
18  * write to the Free Software Foundation, Inc., 59 Temple Place, *
19  * Suite 330, Boston, MA 02111-1307, USA *
20  * *
21  ***************************************************************************/
22 
23 
24 #ifndef BASE_BOUNDBOX_H
25 #define BASE_BOUNDBOX_H
26 
27 #include <Base/Vector3D.h>
28 #include <Base/Matrix.h>
29 #include <Base/ViewProj.h>
30 #include <Base/Tools2D.h>
31 #include <limits>
32 
33 namespace Base {
34 
35 class ViewProjMethod;
36 
38 template <class _Precision>
39 class BoundBox3
40 {
41  // helper function
42  static bool isOnRayW(_Precision, _Precision, _Precision);
43  static bool isOnRayS(_Precision, _Precision, _Precision);
44 
45 public:
46  typedef _Precision num_type;
48 
51  _Precision MinX;
52  _Precision MinY;
53  _Precision MinZ;
54  _Precision MaxX;
55  _Precision MaxY;
56  _Precision MaxZ;
58 
60  inline explicit BoundBox3 (_Precision fMinX = std::numeric_limits<_Precision>::max(),
61  _Precision fMinY = std::numeric_limits<_Precision>::max(),
62  _Precision fMinZ = std::numeric_limits<_Precision>::max(),
63  _Precision fMaxX = -std::numeric_limits<_Precision>::max(),
64  _Precision fMaxY = -std::numeric_limits<_Precision>::max(),
65  _Precision fMaxZ = -std::numeric_limits<_Precision>::max());
66  BoundBox3 (const BoundBox3<_Precision> &rcBB) { *this = rcBB; }
68  inline BoundBox3 (const Vector3<_Precision> *pclVect, unsigned long ulCt);
69 
73  BoundBox3 (const Vector3<_Precision> &rcCnt, _Precision fDistance);
74  ~BoundBox3 ();
75 
78 
82  inline bool Intersect (const BoundBox3<_Precision> &rcBB) const;
84  inline bool operator && (const BoundBox3<_Precision> &rcBB) const;
86  inline bool Intersect (const BoundBox2d &rcBB) const;
88  inline bool operator && (const BoundBox2d &rcBB) const;
96  inline void Add (const Vector3<_Precision> &rclVect);
98  inline void Add (const BoundBox3<_Precision> &rcBB);
100 
106  inline bool IsInBox (const Vector3<_Precision> &rcVct) const;
110  inline bool IsInBox (const BoundBox3<_Precision> &rcBB) const;
114  inline bool IsInBox (const BoundBox2d &rcbb) const;
116  bool IsValid (void) const;
118 
121  bool GetOctantFromVector (const Vector3<_Precision> &rclVct, OCTANT &rclOctant) const;
123 
124  enum SIDE { LEFT =0, RIGHT=1, TOP=2, BOTTOM=3, FRONT=4, BACK=5, INVALID=255 };
125 
133  inline Vector3<_Precision> CalcPoint (unsigned short usPoint) const;
135  void CalcPlane (unsigned short usPlane, Vector3<_Precision>& rBase, Vector3<_Precision>& rNormal ) const;
142  bool CalcEdge (unsigned short usEdge, Vector3<_Precision>& rcP0, Vector3<_Precision>& rcP1) const;
147  bool IntersectionPoint (const Vector3<_Precision> &rcVct, const Vector3<_Precision> &rcVctDir, Vector3<_Precision>& cVctRes, _Precision epsilon) const;
149  bool IsCutLine ( const Vector3<_Precision>& rcBase, const Vector3<_Precision>& rcDir, _Precision fTolerance = 0.0f) const;
153  inline bool IsCutPlane (const Vector3<_Precision> &rclBase, const Vector3<_Precision> &rclNormal) const;
155  bool IntersectWithLine (const Vector3<_Precision>& rcBase, const Vector3<_Precision>& rcDir, Vector3<_Precision>& rcP0, Vector3<_Precision>& rcP1) const;
157  bool IntersectPlaneWithLine (unsigned short usSide, const Vector3<_Precision>& rcBase, const Vector3<_Precision>& rcDir,
158  Vector3<_Precision>& rcP0) const;
160  typename BoundBox3<_Precision>::SIDE GetSideFromRay (const Vector3<_Precision> &rclPt, const Vector3<_Precision> &rclDir) const;
163 
169  BoundBox2d ProjectBox(const ViewProjMethod *rclP) const;
173  BoundBox3<_Precision> Transformed(const Matrix4D& mat) const;
174 
176  inline Vector3<_Precision> GetCenter (void) const;
180  inline _Precision CalcDiagonalLength (void) const;
181  void SetVoid (void);
182 
184  inline void Enlarge (_Precision fLen);
186  inline void Shrink (_Precision fLen);
187 
189  inline _Precision LengthX (void) const;
191  inline _Precision LengthY (void) const;
193  inline _Precision LengthZ (void) const;
195  inline void MoveX (_Precision f);
197  inline void MoveY (_Precision f);
199  inline void MoveZ (_Precision f);
201  inline void ScaleX (_Precision f);
203  inline void ScaleY (_Precision f);
205  inline void ScaleZ (_Precision f);
206 
208  void Print (std::ostream&) const;
209 };
210 
211 
212 template <class _Precision>
213 bool BoundBox3<_Precision>::isOnRayW(_Precision A, _Precision B, _Precision K)
214 {
215  // Checks if point K lies on the ray [A,B]
216  return ((A <= K) && (K <= B));
217 }
218 
219 template <class _Precision>
220 bool BoundBox3<_Precision>::isOnRayS(_Precision A, _Precision B, _Precision K)
221 {
222  // Checks if point K lies on the ray [A,B[
223  return ((A <= K) && (K < B));
224 }
225 
226 template <class _Precision>
227 inline BoundBox3<_Precision>::BoundBox3 (_Precision fMinX, _Precision fMinY, _Precision fMinZ,
228  _Precision fMaxX, _Precision fMaxY, _Precision fMaxZ)
229  : MinX(fMinX), MinY(fMinY), MinZ(fMinZ),
230  MaxX(fMaxX), MaxY(fMaxY), MaxZ(fMaxZ)
231 {
232 }
233 
234 template <class _Precision>
235 inline BoundBox3<_Precision>::BoundBox3 (const Vector3<_Precision> *pclVect, unsigned long ulCt)
236  : MinX( std::numeric_limits<_Precision>::max())
237  , MinY( std::numeric_limits<_Precision>::max())
238  , MinZ( std::numeric_limits<_Precision>::max())
239  , MaxX(-std::numeric_limits<_Precision>::max())
240  , MaxY(-std::numeric_limits<_Precision>::max())
241  , MaxZ(-std::numeric_limits<_Precision>::max())
242 {
243  const Vector3<_Precision> *pI, *pEnd = pclVect + ulCt;
244  for (pI = pclVect; pI < pEnd; ++pI) {
245  MinX = std::min<_Precision>(MinX, pI->x);
246  MinY = std::min<_Precision>(MinY, pI->y);
247  MinZ = std::min<_Precision>(MinZ, pI->z);
248  MaxX = std::max<_Precision>(MaxX, pI->x);
249  MaxY = std::max<_Precision>(MaxY, pI->y);
250  MaxZ = std::max<_Precision>(MaxZ, pI->z);
251  }
252 }
253 
254 template <class _Precision>
255 inline BoundBox3<_Precision>::BoundBox3 (const Vector3<_Precision> &rcVector, _Precision fDistance)
256 {
257  MinX = rcVector.x - fDistance;
258  MaxX = rcVector.x + fDistance;
259  MinY = rcVector.y - fDistance;
260  MaxY = rcVector.y + fDistance;
261  MinZ = rcVector.z - fDistance;
262  MaxZ = rcVector.z + fDistance;
263 }
264 
265 template <class _Precision>
267 {
268 }
269 
270 template <class _Precision>
272 {
273  MinX = rcBound.MinX;
274  MinY = rcBound.MinY;
275  MinZ = rcBound.MinZ;
276  MaxX = rcBound.MaxX;
277  MaxY = rcBound.MaxY;
278  MaxZ = rcBound.MaxZ;
279  return *this;
280 }
281 
282 template <class _Precision>
284 {
285  if (rcBB.MaxX < this->MinX || rcBB.MinX > this->MaxX)
286  return false;
287  if (rcBB.MaxY < this->MinY || rcBB.MinY > this->MaxY)
288  return false;
289  if (rcBB.MaxZ < this->MinZ || rcBB.MinZ > this->MaxZ)
290  return false;
291  return true;
292 }
293 
294 template <class _Precision>
296 {
297  return Intersect(rcBB);
298 }
299 
300 template <class _Precision>
301 inline bool BoundBox3<_Precision>::Intersect (const BoundBox2d &rcBB) const
302 {
303  if (rcBB.MaxX < this->MinX || rcBB.MinX > this->MaxX)
304  return false;
305  if (rcBB.MaxY < this->MinY || rcBB.MinY > this->MaxY)
306  return false;
307  return true;
308 }
309 
310 template <class _Precision>
311 inline bool BoundBox3<_Precision>::operator && (const BoundBox2d &rcBB) const
312 {
313  return Intersect(rcBB);
314 }
315 
316 template <class _Precision>
318 {
319  BoundBox3<_Precision> cBBRes;
320 
321  cBBRes.MinX = std::max<_Precision> (MinX, rcBB.MinX);
322  cBBRes.MaxX = std::min<_Precision> (MaxX, rcBB.MaxX);
323  cBBRes.MinY = std::max<_Precision> (MinY, rcBB.MinY);
324  cBBRes.MaxY = std::min<_Precision> (MaxY, rcBB.MaxY);
325  cBBRes.MinZ = std::max<_Precision> (MinZ, rcBB.MinZ);
326  cBBRes.MaxZ = std::min<_Precision> (MaxZ, rcBB.MaxZ);
327 
328  return cBBRes;
329 }
330 
331 template <class _Precision>
333 {
334  BoundBox3<_Precision> cBBRes;
335 
336  cBBRes.MinX = std::min<_Precision> (MinX, rcBB.MinX);
337  cBBRes.MaxX = std::max<_Precision> (MaxX, rcBB.MaxX);
338  cBBRes.MinY = std::min<_Precision> (MinY, rcBB.MinY);
339  cBBRes.MaxY = std::max<_Precision> (MaxY, rcBB.MaxY);
340  cBBRes.MinZ = std::min<_Precision> (MinZ, rcBB.MinZ);
341  cBBRes.MaxZ = std::max<_Precision> (MaxZ, rcBB.MaxZ);
342 
343  return cBBRes;
344 }
345 
346 template <class _Precision>
348 {
349  this->MinX = std::min<_Precision>(this->MinX, rclVect.x);
350  this->MinY = std::min<_Precision>(this->MinY, rclVect.y);
351  this->MinZ = std::min<_Precision>(this->MinZ, rclVect.z);
352  this->MaxX = std::max<_Precision>(this->MaxX, rclVect.x);
353  this->MaxY = std::max<_Precision>(this->MaxY, rclVect.y);
354  this->MaxZ = std::max<_Precision>(this->MaxZ, rclVect.z);
355 }
356 
357 template <class _Precision>
359 {
360  this->MinX = std::min<_Precision> (this->MinX, rcBB.MinX);
361  this->MaxX = std::max<_Precision> (this->MaxX, rcBB.MaxX);
362  this->MinY = std::min<_Precision> (this->MinY, rcBB.MinY);
363  this->MaxY = std::max<_Precision> (this->MaxY, rcBB.MaxY);
364  this->MinZ = std::min<_Precision> (this->MinZ, rcBB.MinZ);
365  this->MaxZ = std::max<_Precision> (this->MaxZ, rcBB.MaxZ);
366 }
367 
368 template <class _Precision>
369 inline bool BoundBox3<_Precision>::IsInBox (const Vector3<_Precision> &rcVct) const
370 {
371  if (rcVct.x < this->MinX || rcVct.x > this->MaxX)
372  return false;
373  if (rcVct.y < this->MinY || rcVct.y > this->MaxY)
374  return false;
375  if (rcVct.z < this->MinZ || rcVct.z > this->MaxZ)
376  return false;
377  return true;
378 }
379 
380 template <class _Precision>
382 {
383  if (rcBB.MinX < this->MinX || rcBB.MaxX > this->MaxX)
384  return false;
385  if (rcBB.MinY < this->MinY || rcBB.MaxY > this->MaxY)
386  return false;
387  if (rcBB.MinZ < this->MinZ || rcBB.MaxZ > this->MaxZ)
388  return false;
389  return true;
390 }
391 
392 template <class _Precision>
393 inline bool BoundBox3<_Precision>::IsInBox (const BoundBox2d &rcBB) const
394 {
395  if (rcBB.MinX < this->MinX || rcBB.MaxX > this->MaxX)
396  return false;
397  if (rcBB.MinY < this->MinY || rcBB.MaxY > this->MaxY)
398  return false;
399  return true;
400 }
401 
402 template <class _Precision>
403 inline bool BoundBox3<_Precision>::IsValid (void) const
404 {
405  return ((MinX <= MaxX) && (MinY <= MaxY) && (MinZ <= MaxZ));
406 }
407 
408 template <class _Precision>
409 inline bool BoundBox3<_Precision>::GetOctantFromVector (const Vector3<_Precision> &rclVct, OCTANT &rclOctant) const
410 {
411  if (!IsInBox (rclVct))
412  return false;
413 
414  unsigned short usNdx = 0;
415  if (isOnRayS ((MinX + MaxX)/2, MaxX, rclVct.x)) // left/RIGHT
416  usNdx |= 1;
417  if (isOnRayS ((MinY + MaxY)/2, MaxY, rclVct.y)) // down/UP
418  usNdx |= 2;
419  if (isOnRayS ((MinZ + MaxZ)/2, MaxZ, rclVct.z)) // back/FRONT
420  usNdx |= 4;
421  rclOctant = static_cast<OCTANT>(usNdx);
422  return true;
423 }
424 
425 template <class _Precision>
427 {
428  BoundBox3<_Precision> cOct (*this);
429 
430  switch (Octant) {
431  case OCT_LDB:
432  cOct.MaxX = (cOct.MinX + cOct.MaxX)/2;
433  cOct.MaxY = (cOct.MinY + cOct.MaxY)/2;
434  cOct.MaxZ = (cOct.MinZ + cOct.MaxZ)/2;
435  break;
436 
437  case OCT_RDB:
438  cOct.MinX = (cOct.MinX + cOct.MaxX)/2;
439  cOct.MaxY = (cOct.MinY + cOct.MaxY)/2;
440  cOct.MaxZ = (cOct.MinZ + cOct.MaxZ)/2;
441  break;
442 
443  case OCT_LUB:
444  cOct.MaxX = (cOct.MinX + cOct.MaxX)/2;
445  cOct.MinY = (cOct.MinY + cOct.MaxY)/2;
446  cOct.MaxZ = (cOct.MinZ + cOct.MaxZ)/2;
447  break;
448 
449  case OCT_RUB:
450  cOct.MinX = (cOct.MinX + cOct.MaxX)/2;
451  cOct.MinY = (cOct.MinY + cOct.MaxY)/2;
452  cOct.MaxZ = (cOct.MinZ + cOct.MaxZ)/2;
453  break;
454 
455  case OCT_LDF:
456  cOct.MaxX = (cOct.MinX + cOct.MaxX)/2;
457  cOct.MaxY = (cOct.MinY + cOct.MaxY)/2;
458  cOct.MinZ = (cOct.MinZ + cOct.MaxZ)/2;
459  break;
460 
461  case OCT_RDF:
462  cOct.MinX = (cOct.MinX + cOct.MaxX)/2;
463  cOct.MaxY = (cOct.MinY + cOct.MaxY)/2;
464  cOct.MinZ = (cOct.MinZ + cOct.MaxZ)/2;
465  break;
466 
467  case OCT_LUF:
468  cOct.MaxX = (cOct.MinX + cOct.MaxX)/2;
469  cOct.MinY = (cOct.MinY + cOct.MaxY)/2;
470  cOct.MinZ = (cOct.MinZ + cOct.MaxZ)/2;
471  break;
472 
473  case OCT_RUF:
474  cOct.MinX = (cOct.MinX + cOct.MaxX)/2;
475  cOct.MinY = (cOct.MinY + cOct.MaxY)/2;
476  cOct.MinZ = (cOct.MinZ + cOct.MaxZ)/2;
477  break;
478  }
479  return cOct;
480 }
481 
482 template <class _Precision>
483 inline Vector3<_Precision> BoundBox3<_Precision>::CalcPoint (unsigned short usPoint) const
484 {
485  switch (usPoint) {
486  case 0: return Vector3<_Precision>(MinX, MinY, MaxZ);
487  case 1: return Vector3<_Precision>(MaxX, MinY, MaxZ);
488  case 2: return Vector3<_Precision>(MaxX, MaxY, MaxZ);
489  case 3: return Vector3<_Precision>(MinX, MaxY, MaxZ);
490  case 4: return Vector3<_Precision>(MinX, MinY, MinZ);
491  case 5: return Vector3<_Precision>(MaxX, MinY, MinZ);
492  case 6: return Vector3<_Precision>(MaxX, MaxY, MinZ);
493  case 7: return Vector3<_Precision>(MinX, MaxY, MinZ);
494  }
495 
496  return Vector3<_Precision>();
497 }
498 
499 template <class _Precision>
500 inline void BoundBox3<_Precision>::CalcPlane (unsigned short usPlane, Vector3<_Precision>& rBase, Vector3<_Precision>& rNormal) const
501 {
502  switch (usPlane) {
503  case LEFT:
504  rBase.Set(MinX, MinY, MaxZ);
505  rNormal.Set(1.0f, 0.0f, 0.0f);
506  break;
507 
508  case RIGHT:
509  rBase.Set(MaxX, MinY, MaxZ);
510  rNormal.Set(1.0f, 0.0f, 0.0f);
511  break;
512 
513  case TOP:
514  rBase.Set(MinX, MaxY, MaxZ);
515  rNormal.Set(0.0f, 1.0f, 0.0f);
516  break;
517 
518  case BOTTOM:
519  rBase.Set(MinX, MinY, MaxZ);
520  rNormal.Set(0.0f, 1.0f, 0.0f);
521  break;
522 
523  case FRONT:
524  rBase.Set(MinX, MinY, MaxZ);
525  rNormal.Set(0.0f, 0.0f, 1.0f);
526  break;
527 
528  case BACK:
529  rBase.Set(MinX, MinY, MinZ);
530  rNormal.Set(0.0f, 0.0f, 1.0f);
531  break;
532  default:
533  break;
534  }
535 }
536 
537 template <class _Precision>
538 inline bool BoundBox3<_Precision>::CalcEdge (unsigned short usEdge, Vector3<_Precision>& rcP0, Vector3<_Precision>& rcP1) const
539 {
540  switch (usEdge) {
541  case 0:
542  rcP0 = CalcPoint(0);
543  rcP1 = CalcPoint(1);
544  break;
545  case 1:
546  rcP0 = CalcPoint(1);
547  rcP1 = CalcPoint(2);
548  break;
549  case 2:
550  rcP0 = CalcPoint(2);
551  rcP1 = CalcPoint(3);
552  break;
553  case 3:
554  rcP0 = CalcPoint(3);
555  rcP1 = CalcPoint(0);
556  break;
557  case 4:
558  rcP0 = CalcPoint(4);
559  rcP1 = CalcPoint(5);
560  break;
561  case 5:
562  rcP0 = CalcPoint(5);
563  rcP1 = CalcPoint(6);
564  break;
565  case 6:
566  rcP0 = CalcPoint(6);
567  rcP1 = CalcPoint(7);
568  break;
569  case 7:
570  rcP0 = CalcPoint(7);
571  rcP1 = CalcPoint(4);
572  break;
573  case 8:
574  rcP0 = CalcPoint(0);
575  rcP1 = CalcPoint(4);
576  break;
577  case 9:
578  rcP0 = CalcPoint(1);
579  rcP1 = CalcPoint(5);
580  break;
581  case 10:
582  rcP0 = CalcPoint(2);
583  rcP1 = CalcPoint(6);
584  break;
585  case 11:
586  rcP0 = CalcPoint(3);
587  rcP1 = CalcPoint(7);
588  break;
589  default:
590  return false; // undefined
591  }
592 
593  return true;
594 }
595 
596 template <class _Precision>
597 inline bool BoundBox3<_Precision>::IntersectionPoint (const Vector3<_Precision> &rcVct, const Vector3<_Precision> &rcVctDir, Vector3<_Precision>& cVctRes, _Precision epsilon) const
598 {
599  bool rc=false;
600  BoundBox3<_Precision> cCmpBound(*this);
601  unsigned short i;
602 
603  // enlarge bounding box by epsilon
604  cCmpBound.Enlarge(epsilon);
605 
606  // Is point inside?
607  if (cCmpBound.IsInBox (rcVct)) {
608  // test sides
609  for (i = 0; (i < 6) && (!rc); i++) {
610  rc = IntersectPlaneWithLine(i, rcVct, rcVctDir, cVctRes);
611  if (!cCmpBound.IsInBox(cVctRes))
612  rc = false;
613  if (rc == true) {
614  // does intersection point lie in desired direction
615  // or was found the opposing side?
616  // -> scalar product of both direction vectors > 0 (angle < 90)
617  rc = ((cVctRes - rcVct) * rcVctDir) >= 0.0;
618  }
619  }
620  }
621 
622  return rc;
623 }
624 
625 template <class _Precision>
626 inline bool BoundBox3<_Precision>::IsCutLine (const Vector3<_Precision>& rcBase, const Vector3<_Precision>& rcDir, _Precision fTolerance) const
627 {
628  _Precision fDist;
629 
630  // zuerst nur grobe und schnelle Pruefung, indem der
631  // Abstand der Linie zum Mittelpunkt der BB berechnet wird
632  // und mit der maximalen Diagonalenlaenge + fTolerance
633  // verglichen wird.
634 
635  // Distanz zwischen Mittelpunkt und Linie
636  fDist = (rcDir % (GetCenter() - rcBase)).Length() / rcDir.Length();
637 
638  if (fDist > (CalcDiagonalLength() + fTolerance)) {
639  return false;
640  }
641  else { // hier genauerer Test
642  unsigned char i;
643  Vector3<_Precision> clVectRes;
644 
645  // schneide jede Seitenflaeche mit der Linie
646  for (i = 0; i < 6; i++) {
647  if (IntersectPlaneWithLine(i, rcBase, rcDir, clVectRes)) {
648  // pruefe, ob Schnittpunkt innerhalb BB-Grenzen + Toleranz
649  switch (i) {
650  case LEFT : // linke und rechte Ebene
651  case RIGHT :
652  if ((isOnRayW (MinY - fTolerance, MaxY + fTolerance, clVectRes.y) &&
653  isOnRayW (MinZ - fTolerance, MaxZ + fTolerance, clVectRes.z)))
654  return true;
655  break;
656  case TOP : // obere und untere Ebene
657  case BOTTOM :
658  if ((isOnRayW (MinX - fTolerance, MaxX + fTolerance, clVectRes.x) &&
659  isOnRayW (MinZ - fTolerance, MaxZ + fTolerance, clVectRes.z)))
660  return true;
661  break;
662  case FRONT : // vordere und hintere Ebene
663  case BACK :
664  if ((isOnRayW (MinX - fTolerance, MaxX + fTolerance, clVectRes.x) &&
665  isOnRayW (MinY - fTolerance, MaxY + fTolerance, clVectRes.y)))
666  return true;
667  break;
668  }
669  }
670  }
671  }
672 
673  return false;
674 }
675 
676 template <class _Precision>
677 inline bool BoundBox3<_Precision>::IsCutPlane (const Vector3<_Precision> &rclBase, const Vector3<_Precision> &rclNormal) const
678 {
679  if (fabs(GetCenter().DistanceToPlane(rclBase, rclNormal)) < CalcDiagonalLength()) {
680  _Precision fD = CalcPoint(0).DistanceToPlane(rclBase, rclNormal);
681  for (unsigned short i = 1; i < 8; i++) {
682  if ((CalcPoint(i).DistanceToPlane(rclBase, rclNormal) * fD) <= 0.0f)
683  return true;
684  }
685  }
686  return false;
687 }
688 
689 template <class _Precision>
691  Vector3<_Precision>& rcP0, Vector3<_Precision>& rcP1) const
692 {
693  Vector3<_Precision> clVectRes, clVect[6];
694 
695  unsigned short numIntersect = 0;
696  // cut each face with the line
697  for (unsigned short i = 0; i < 6; i++) {
698  if (IntersectPlaneWithLine(i, rcBase, rcDir, clVectRes)) {
699  // check if intersection point is inside
700  switch (i) {
701  case LEFT : // left and right plane
702  case RIGHT :
703  if ((isOnRayS(MinY, MaxY, clVectRes.y) &&
704  isOnRayS(MinZ, MaxZ, clVectRes.z))) {
705  clVect[numIntersect] = clVectRes;
706  numIntersect++;
707  } break;
708  case TOP : // top and bottom plane
709  case BOTTOM :
710  if ((isOnRayS(MinX, MaxX, clVectRes.x) &&
711  isOnRayS(MinZ, MaxZ, clVectRes.z))) {
712  clVect[numIntersect] = clVectRes;
713  numIntersect++;
714  } break;
715  case FRONT : // front and back plane
716  case BACK :
717  if ((isOnRayS(MinX, MaxX, clVectRes.x) &&
718  isOnRayS(MinY, MaxY, clVectRes.y))) {
719  clVect[numIntersect] = clVectRes;
720  numIntersect++;
721  } break;
722  }
723  }
724  }
725 
726  if (numIntersect == 2) {
727  rcP0 = clVect[0];
728  rcP1 = clVect[1];
729  return true;
730  }
731  else if (numIntersect > 2) { // search two different intersection points
732  for (unsigned short i = 1; i < numIntersect; i++) {
733  if (clVect[i] != clVect[0]) {
734  rcP0 = clVect[0];
735  rcP1 = clVect[i];
736  return true;
737  }
738  }
739  }
740 
741  return false;
742 }
743 
744 template <class _Precision>
745 inline bool BoundBox3<_Precision>::IntersectPlaneWithLine (unsigned short usSide, const Vector3<_Precision>& rcBase,
746  const Vector3<_Precision>& rcDir, Vector3<_Precision>& rcP0) const
747 {
748  _Precision k;
749  Vector3<_Precision> cBase, cNormal;
750  Vector3<_Precision> cDir(rcDir);
751  CalcPlane(usSide, cBase, cNormal);
752 
753  if ((cNormal * cDir) == 0.0f) {
754  return false; // no point of intersection
755  }
756  else {
757  k = (cNormal * (cBase - rcBase)) / (cNormal * cDir);
758  cDir.Scale(k, k, k);
759  rcP0 = rcBase + cDir;
760  return true;
761  }
762 }
763 
764 template <class _Precision>
766 {
767  Vector3<_Precision> cIntersection;
768  return GetSideFromRay( rclPt, rclDir, cIntersection);
769 }
770 
771 template <class _Precision>
773  Vector3<_Precision>& rcInt) const
774 {
775  Vector3<_Precision> cP0, cP1;
776  if (IntersectWithLine(rclPt, rclDir, cP0, cP1) == false)
777  return INVALID;
778 
779  Vector3<_Precision> cOut;
780  // same orientation
781  if ((cP1-cP0)*rclDir > 0)
782  cOut = cP1;
783  else
784  cOut = cP0;
785 
786  rcInt = cOut;
787 
788  _Precision fMax = 1.0e-3f;
789  SIDE tSide = INVALID;
790 
791  if (fabs(cOut.x - MinX) < fMax) { // left plane
792  fMax = _Precision(fabs(cOut.x - MinX));
793  tSide = LEFT;
794  }
795 
796  if (fabs(cOut.x - MaxX) < fMax) { // right plane
797  fMax = _Precision(fabs(cOut.x - MaxX));
798  tSide = RIGHT;
799  }
800 
801  if (fabs(cOut.y - MinY) < fMax) { // bottom plane
802  fMax = _Precision(fabs(cOut.y - MinY));
803  tSide = BOTTOM;
804  }
805 
806  if (fabs(cOut.y - MaxY) < fMax) { // top plane
807  fMax = _Precision(fabs(cOut.y - MaxY));
808  tSide = TOP;
809  }
810 
811  if (fabs(cOut.z - MinZ) < fMax) { // front plane
812  fMax = _Precision(fabs(cOut.z - MinZ));
813  tSide = FRONT;
814  }
815 
816  if (fabs(cOut.z - MaxZ) < fMax) { // back plane
817  fMax = _Precision(fabs(cOut.z - MaxZ));
818  tSide = BACK;
819  }
820 
821  return tSide;
822 }
823 
824 template <class _Precision>
826 {
827 #if 0
828  // Get the nearest point of the bb, point MUST be inside the bb!
829  _Precision fMinDist = std::numeric_limits<_Precision>::max();
830  Vector3<_Precision> cBase, cNormal, clRet;
831 
832  for (int i = 0; i < 6; i++) {
833  Vector3<_Precision> clTemp = rclPt;
834  CalcPlane(i, cBase, cNormal);
835  clTemp.ProjectToPlane(cBase, cNormal);
836  _Precision fDist = (clTemp - rclPt).Length();
837  if (fDist < fMinDist) {
838  fMinDist = fDist;
839  clRet = clTemp;
840  }
841  }
842 
843  return clRet;
844 #else
845  Vector3<_Precision> closest = rclPt;
846 
847  Vector3<_Precision> center = GetCenter();
848  _Precision devx = closest.x - center.x;
849  _Precision devy = closest.y - center.y;
850  _Precision devz = closest.z - center.z;
851 
852  _Precision halfwidth = (MaxX - MinX) / 2;
853  _Precision halfheight = (MaxY - MinY) / 2;
854  _Precision halfdepth = (MaxZ - MinZ) / 2;
855 
856  // Move point to be on the nearest plane of the box.
857  if ((fabs(devx) > fabs(devy)) && (fabs(devx) > fabs(devz)))
858  closest.x = center.x + halfwidth * ((devx < 0.0) ? -1.0 : 1.0);
859  else if (fabs(devy) > fabs(devz))
860  closest.y = center.y + halfheight * ((devy < 0.0) ? -1.0 : 1.0);
861  else
862  closest.z = center.z + halfdepth * ((devz < 0.0) ? -1.0 : 1.0);
863 
864  // Clamp to be inside box.
865  closest.x = std::min<_Precision>(std::max<_Precision>(closest.x, MinX), MaxX);
866  closest.y = std::min<_Precision>(std::max<_Precision>(closest.y, MinY), MaxY);
867  closest.z = std::min<_Precision>(std::max<_Precision>(closest.z, MinZ), MaxZ);
868 
869  return closest;
870 #endif
871 }
872 
873 template <class _Precision>
875 {
876  BoundBox2d clBB2D;
877  clBB2D.SetVoid();
878 
879  for (int i = 0; i < 8; i++) {
880  Vector3<_Precision> clTrsPt = (*pclP)(CalcPoint(i));
881  clBB2D.Add(Vector2d(clTrsPt.x, clTrsPt.y));
882  }
883 
884  return clBB2D;
885 }
886 
887 template <class _Precision>
889 {
891  for (int i=0; i<8; i++)
892  bbox.Add(mat * CalcPoint(i));
893  return bbox;
894 }
895 
896 template <class _Precision>
898 {
899  return Vector3<_Precision>((MaxX + MinX) / 2,
900  (MaxY + MinY) / 2,
901  (MaxZ + MinZ) / 2);
902 }
903 
904 template <class _Precision>
905 inline _Precision BoundBox3<_Precision>::CalcDiagonalLength (void) const
906 {
907  return static_cast<_Precision>(sqrt (((MaxX - MinX) * (MaxX - MinX)) +
908  ((MaxY - MinY) * (MaxY - MinY)) +
909  ((MaxZ - MinZ) * (MaxZ - MinZ))));
910 }
911 
912 template <class _Precision>
914 {
915  MinX = MinY = MinZ = std::numeric_limits<_Precision>::max();
916  MaxX = MaxY = MaxZ = -std::numeric_limits<_Precision>::max();
917 }
918 
919 template <class _Precision>
920 inline void BoundBox3<_Precision>::Enlarge (_Precision fLen)
921 {
922  MinX -= fLen; MinY -= fLen; MinZ -= fLen;
923  MaxX += fLen; MaxY += fLen; MaxZ += fLen;
924 }
925 
926 template <class _Precision>
927 inline void BoundBox3<_Precision>::Shrink (_Precision fLen)
928 {
929  MinX += fLen; MinY += fLen; MinZ += fLen;
930  MaxX -= fLen; MaxY -= fLen; MaxZ -= fLen;
931 }
932 
933 template <class _Precision>
934 inline _Precision BoundBox3<_Precision>::LengthX (void) const
935 {
936  return MaxX - MinX;
937 }
938 
939 template <class _Precision>
940 inline _Precision BoundBox3<_Precision>::LengthY (void) const
941 {
942  return MaxY - MinY;
943 }
944 
945 template <class _Precision>
946 inline _Precision BoundBox3<_Precision>::LengthZ (void) const
947 {
948  return MaxZ - MinZ;
949 }
950 
951 template <class _Precision>
952 inline void BoundBox3<_Precision>::MoveX (_Precision f)
953 {
954  MinX += f; MaxX += f;
955 }
956 
957 template <class _Precision>
958 inline void BoundBox3<_Precision>::MoveY (_Precision f)
959 {
960  MinY += f; MaxY += f;
961 }
962 
963 template <class _Precision>
964 inline void BoundBox3<_Precision>::MoveZ (_Precision f)
965 {
966  MinZ += f; MaxZ += f;
967 }
968 
969 template <class _Precision>
970 inline void BoundBox3<_Precision>::ScaleX (_Precision f)
971 {
972  MinX *= f; MaxX *= f;
973 }
974 
975 template <class _Precision>
976 inline void BoundBox3<_Precision>::ScaleY (_Precision f)
977 {
978  MinY *= f; MaxY *= f;
979 }
980 
981 template <class _Precision>
982 inline void BoundBox3<_Precision>::ScaleZ (_Precision f)
983 {
984  MinZ *= f; MaxZ *= f;
985 }
986 
989 
990 } // namespace Base
991 
992 #endif // BASE_BOUNDBOX_H
993 
_Precision z
Definition: Vector3D.h:89
Definition: ViewProj.h:36
Definition: BoundBox.h:120
_Precision CalcDiagonalLength(void) const
Definition: BoundBox.h:905
bool IsCutPlane(const Vector3< _Precision > &rclBase, const Vector3< _Precision > &rclNormal) const
Definition: BoundBox.h:677
Definition: BoundBox.h:119
Definition: BoundBox.h:119
BoundBox3< float > BoundBox3f
Definition: BoundBox.h:987
Definition: BoundBox.h:124
_Precision y
Definition: Vector3D.h:88
bool IntersectionPoint(const Vector3< _Precision > &rcVct, const Vector3< _Precision > &rcVctDir, Vector3< _Precision > &cVctRes, _Precision epsilon) const
Definition: BoundBox.h:597
bool operator &&(const BoundBox3< _Precision > &rcBB) const
Definition: BoundBox.h:295
Definition: BoundBox.h:120
Definition: BoundBox.h:119
Definition: Tools2D.h:45
_Precision MinZ
Definition: BoundBox.h:53
Definition: BoundBox.h:124
Definition: GlobalId.h:61
_Precision LengthY(void) const
Definition: BoundBox.h:940
bool GetOctantFromVector(const Vector3< _Precision > &rclVct, OCTANT &rclOctant) const
Definition: BoundBox.h:409
BoundBox3< _Precision > Intersected(const BoundBox3< _Precision > &rcBB) const
Definition: BoundBox.h:317
bool IsValid(void) const
Definition: BoundBox.h:403
void SetVoid(void)
Definition: Tools2D.h:536
BoundBox3(_Precision fMinX=std::numeric_limits< _Precision >::max(), _Precision fMinY=std::numeric_limits< _Precision >::max(), _Precision fMinZ=std::numeric_limits< _Precision >::max(), _Precision fMaxX=-std::numeric_limits< _Precision >::max(), _Precision fMaxY=-std::numeric_limits< _Precision >::max(), _Precision fMaxZ=-std::numeric_limits< _Precision >::max())
Definition: BoundBox.h:227
_Precision MaxY
Definition: BoundBox.h:55
_Precision x
Definition: Vector3D.h:87
Definition: BoundBox.h:124
_Precision MaxZ
Definition: BoundBox.h:56
bool IsInBox(const Vector3< _Precision > &rcVct) const
Definition: BoundBox.h:369
_Precision LengthX(void) const
Definition: BoundBox.h:934
void ScaleZ(_Precision f)
Definition: BoundBox.h:982
Vector3 & ProjectToPlane(const Vector3 &rclBase, const Vector3 &rclNorm)
Projects this point onto the plane given by the base rclBase and the normal rclNorm.
void ScaleY(_Precision f)
Definition: BoundBox.h:976
Definition: BoundBox.h:120
double MaxY
Definition: Tools2D.h:100
bool CalcEdge(unsigned short usEdge, Vector3< _Precision > &rcP0, Vector3< _Precision > &rcP1) const
Definition: BoundBox.h:538
_Precision MaxX
Definition: BoundBox.h:54
bool IntersectPlaneWithLine(unsigned short usSide, const Vector3< _Precision > &rcBase, const Vector3< _Precision > &rcDir, Vector3< _Precision > &rcP0) const
Definition: BoundBox.h:745
SIDE
Definition: BoundBox.h:124
BoundBox3< _Precision >::SIDE GetSideFromRay(const Vector3< _Precision > &rclPt, const Vector3< _Precision > &rclDir) const
Definition: BoundBox.h:765
bool IsCutLine(const Vector3< _Precision > &rcBase, const Vector3< _Precision > &rcDir, _Precision fTolerance=0.0f) const
Definition: BoundBox.h:626
BoundBox3(const BoundBox3< _Precision > &rcBB)
Definition: BoundBox.h:66
BoundBox3< _Precision > & operator=(const BoundBox3< _Precision > &rcBound)
Assignment operator.
Definition: BoundBox.h:271
double MinX
Definition: Tools2D.h:100
OCTANT
Definition: BoundBox.h:119
void ScaleX(_Precision f)
Definition: BoundBox.h:970
BoundBox3< _Precision > CalcOctant(typename BoundBox3< _Precision >::OCTANT Octant) const
Definition: BoundBox.h:426
Vector3< _Precision > GetCenter(void) const
Definition: BoundBox.h:897
Vector3< _Precision > ClosestPoint(const Vector3< _Precision > &rclPt) const
Definition: BoundBox.h:825
void MoveZ(_Precision f)
Definition: BoundBox.h:964
BoundBox3< _Precision > Transformed(const Matrix4D &mat) const
Definition: BoundBox.h:888
Definition: BoundBox.h:124
Vector3< _Precision > CalcPoint(unsigned short usPoint) const
Definition: BoundBox.h:483
void MoveX(_Precision f)
Definition: BoundBox.h:952
void Add(const Vector3< _Precision > &rclVect)
Definition: BoundBox.h:347
BoundBox3< _Precision > United(const BoundBox3< _Precision > &rcBB) const
Definition: BoundBox.h:332
BoundBox2d ProjectBox(const ViewProjMethod *rclP) const
Definition: BoundBox.h:874
Definition: BoundBox.h:124
BoundBox3< double > BoundBox3d
Definition: BoundBox.h:988
Definition: BoundBox.h:124
~BoundBox3()
Definition: BoundBox.h:266
Definition: BoundBox.h:119
_Precision MinY
Definition: BoundBox.h:52
_Precision MinX
Definition: BoundBox.h:51
void Enlarge(_Precision fLen)
Definition: BoundBox.h:920
void Print(std::ostream &) const
Definition: Matrix.h:38
Definition: BoundBox.h:120
Definition: BoundBox.h:124
Definition: AbstractXMLReader.h:5
Definition: Vector3D.h:78
void Set(_Precision fX, _Precision fY, _Precision fZ)
double MaxX
Definition: Tools2D.h:100
_Precision LengthZ(void) const
Definition: BoundBox.h:946
void Shrink(_Precision fLen)
Definition: BoundBox.h:927
void CalcPlane(unsigned short usPlane, Vector3< _Precision > &rBase, Vector3< _Precision > &rNormal) const
Definition: BoundBox.h:500
void SetVoid(void)
Definition: BoundBox.h:913
_Precision num_type
Definition: BoundBox.h:46
bool IntersectWithLine(const Vector3< _Precision > &rcBase, const Vector3< _Precision > &rcDir, Vector3< _Precision > &rcP0, Vector3< _Precision > &rcP1) const
Definition: BoundBox.h:690
_Precision Length(void) const
Length of the vector.
float_traits< num_type > traits_type
Definition: BoundBox.h:47
bool Intersect(const BoundBox3< _Precision > &rcBB) const
Definition: BoundBox.h:283
Definition: Vector3D.h:58
Definition: BoundBox.h:39
Definition: Tools2D.h:97
double MinY
Definition: Tools2D.h:100
void MoveY(_Precision f)
Definition: BoundBox.h:958
void Add(const Vector2d &v)
Definition: Tools2D.h:542