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