BoundBox.h

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2005 Imetric 3D GmbH                                    *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  is distributed in the hope that it will be useful,      *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 
00024 #ifndef BASE_BOUNDBOX_H
00025 #define BASE_BOUNDBOX_H
00026 
00027 #include "Vector3D.h"
00028 #include "Matrix.h"
00029 #include "ViewProj.h"
00030 #include "Tools2D.h"
00031 
00032 // Checks if point K lies on the ray [A,B[
00033 #define IS_ON_RAY(A,B,K)  (((A) <= (K)) && ((B) > (K)))
00034 
00035 namespace Base {
00036 
00037 class ViewProjMethod;
00038 
00040 template <class _Precision>
00041 class BoundBox3
00042 {
00043 public:
00044   typedef _Precision num_type;
00045   typedef float_traits<num_type> traits_type;
00046 
00049   _Precision MinX;
00050   _Precision MinY;
00051   _Precision MinZ;
00052   _Precision MaxX;
00053   _Precision MaxY;
00054   _Precision MaxZ;
00056   
00058   inline explicit BoundBox3 ( _Precision fMinX =  FLOAT_MAX, _Precision fMinY =  FLOAT_MAX,
00059                               _Precision fMinZ =  FLOAT_MAX, _Precision fMaxX = -FLOAT_MAX,
00060                               _Precision fMaxY = -FLOAT_MAX, _Precision fMaxZ = -FLOAT_MAX );
00061   BoundBox3 (const BoundBox3<_Precision> &rcBB) { *this = rcBB; }
00063   inline BoundBox3 (const Vector3<_Precision> *pclVect, unsigned long ulCt);
00064 
00068   BoundBox3 (const Vector3<_Precision> &rcCnt, _Precision fDistance);
00069   ~BoundBox3 ();
00070  
00072   inline  BoundBox3<_Precision>& operator = (const BoundBox3<_Precision> &rcBound);
00073  
00077   inline bool operator && (const BoundBox3<_Precision> &rcBB) const;
00079   inline bool operator && (const BoundBox2D &rcBB) const;
00083   BoundBox3<_Precision> operator & (const BoundBox3<_Precision> &rcBB) const;
00085   inline  BoundBox3<_Precision>& operator &= (const Vector3<_Precision> &rclVect);
00087   BoundBox3<_Precision> operator | (const BoundBox3<_Precision> &rcBB) const;
00091   inline  void Add (const Vector3<_Precision> &rclVect);
00093   inline  void Add (const BoundBox3<_Precision> &rcBB);
00095  
00099   inline bool IsInBox (const Vector3<_Precision> &rcVct) const;
00101   inline bool IsInBox (const BoundBox3<_Precision> &rcBB) const;
00103   inline bool IsInBox (const BoundBox2D &rcbb) const;
00105   bool IsValid (void) const;
00107 
00108   enum OCTANT {OCT_LDB = 0, OCT_RDB, OCT_LUB, OCT_RUB,
00109                OCT_LDF,     OCT_RDF, OCT_LUF, OCT_RUF};
00110   bool GetOctantFromVector (const Vector3<_Precision> &rclVct, OCTANT &rclOctant) const;
00111   BoundBox3<_Precision> CalcOctant (typename BoundBox3<_Precision>::OCTANT Octant) const;
00112 
00113   enum SIDE { LEFT =0, RIGHT=1, TOP=2, BOTTOM=3, FRONT=4, BACK=5, INVALID=255 };
00114 
00122   inline Vector3<_Precision> CalcPoint (unsigned short usPoint) const;
00124   void CalcPlane (unsigned short usPlane, Vector3<_Precision>& rBase, Vector3<_Precision>& rNormal ) const;
00131   bool  CalcDistance (unsigned short usEdge, Vector3<_Precision>& rcP0, Vector3<_Precision>& rcP1) const;
00136   bool IntersectionPoint (const Vector3<_Precision> &rcVct, const Vector3<_Precision> &rcVctDir, Vector3<_Precision>& cVctRes, _Precision epsilon) const;
00138   bool IsCutLine ( const Vector3<_Precision>& rcBase, const Vector3<_Precision>& rcDir, _Precision fTolerance = 0.0f) const;
00140   inline bool IsCutPlane (const Vector3<_Precision> &rclBase, const Vector3<_Precision> &rclNormal) const;
00142   bool IntersectWithLine (const Vector3<_Precision>& rcBase, const Vector3<_Precision>& rcDir, Vector3<_Precision>& rcP0, Vector3<_Precision>& rcP1) const;
00144   bool IntersectPlaneWithLine (unsigned short usSide, const Vector3<_Precision>& rcBase, const Vector3<_Precision>& rcDir, 
00145                                Vector3<_Precision>& rcP0) const;
00147   typename BoundBox3<_Precision>::SIDE GetSideFromRay (const Vector3<_Precision> &rclPt, const Vector3<_Precision> &rclDir) const;
00149   typename BoundBox3<_Precision>::SIDE GetSideFromRay (const Vector3<_Precision> &rclPt, const Vector3<_Precision> &rclDir, Vector3<_Precision>& rcInt) const;
00150   
00155   Vector3<_Precision> NearestPoint (const Vector3<_Precision> &rclPt) const;
00157   BoundBox2D ProjectBox(const ViewProjMethod *rclP) const;
00158   BoundBox3<_Precision> Transformed(const Matrix4D& mat) const;
00159 
00161   inline Vector3<_Precision> CalcCenter (void) const;
00162   inline _Precision CalcDiagonalLength (void) const;
00163   void Flush (void);
00164   
00166   inline void Enlarge (_Precision fLen);   
00168   inline void Shrink  (_Precision fLen);   
00169 
00171   inline _Precision LengthX (void) const;
00173   inline _Precision LengthY (void) const;
00175   inline _Precision LengthZ (void) const;
00177   inline void MoveX (_Precision f);
00179   inline void MoveY (_Precision f);
00181   inline void MoveZ (_Precision f);
00183   inline void ScaleX (_Precision f);
00185   inline void ScaleY (_Precision f);
00187   inline void ScaleZ (_Precision f);
00188  
00190   void Print (void);
00191 };
00192 
00193 
00194 template <class _Precision>
00195 inline BoundBox3<_Precision>::BoundBox3 (const Vector3<_Precision> &rcVector, _Precision fDistance)
00196 {
00197   MinX = rcVector.x - fDistance; 
00198   MaxX = rcVector.x + fDistance;
00199   MinY = rcVector.y - fDistance; 
00200   MaxY = rcVector.y + fDistance;
00201   MinZ = rcVector.z - fDistance; 
00202   MaxZ = rcVector.z + fDistance;
00203 }
00204 
00205 template <class _Precision>
00206 inline BoundBox3<_Precision>::~BoundBox3 ()
00207 {
00208 }
00209 
00210 template <class _Precision>
00211 inline BoundBox3<_Precision> BoundBox3<_Precision>::operator & (const BoundBox3<_Precision> &rcBB) const
00212 {
00213   BoundBox3<_Precision> cBBRes;
00214 
00215   cBBRes.MinX = std::max<_Precision> (MinX, rcBB.MinX);
00216   cBBRes.MaxX = std::min<_Precision> (MaxX, rcBB.MaxX);
00217   cBBRes.MinY = std::max<_Precision> (MinY, rcBB.MinY);
00218   cBBRes.MaxY = std::min<_Precision> (MaxY, rcBB.MaxY);
00219   cBBRes.MinZ = std::max<_Precision> (MinZ, rcBB.MinZ);
00220   cBBRes.MaxZ = std::min<_Precision> (MaxZ, rcBB.MaxZ);
00221 
00222   return cBBRes;
00223 }
00224 
00225 template <class _Precision>
00226 inline BoundBox3<_Precision> BoundBox3<_Precision>::operator | (const BoundBox3<_Precision> &rcBB) const
00227 {
00228   BoundBox3<_Precision> cBBRes;
00229 
00230   cBBRes.MinX = std::min<_Precision> (MinX, rcBB.MinX);
00231   cBBRes.MaxX = std::max<_Precision> (MaxX, rcBB.MaxX);
00232   cBBRes.MinY = std::min<_Precision> (MinY, rcBB.MinY);
00233   cBBRes.MaxY = std::max<_Precision> (MaxY, rcBB.MaxY);
00234   cBBRes.MinZ = std::min<_Precision> (MinZ, rcBB.MinZ);
00235   cBBRes.MaxZ = std::max<_Precision> (MaxZ, rcBB.MaxZ);
00236 
00237   return cBBRes;
00238 }
00239 
00240 template <class _Precision>
00241 inline  void BoundBox3<_Precision>::Add (const Vector3<_Precision> &rclVect)
00242 {
00243   this->MinX = std::min<_Precision>(this->MinX, rclVect.x);
00244   this->MinY = std::min<_Precision>(this->MinY, rclVect.y);
00245   this->MinZ = std::min<_Precision>(this->MinZ, rclVect.z);
00246   this->MaxX = std::max<_Precision>(this->MaxX, rclVect.x);
00247   this->MaxY = std::max<_Precision>(this->MaxY, rclVect.y);
00248   this->MaxZ = std::max<_Precision>(this->MaxZ, rclVect.z);
00249 }
00250 
00251 template <class _Precision>
00252 inline  void BoundBox3<_Precision>::Add (const BoundBox3<_Precision> &rcBB)
00253 {
00254   this->MinX = std::min<_Precision> (this->MinX, rcBB.MinX);
00255   this->MaxX = std::max<_Precision> (this->MaxX, rcBB.MaxX);
00256   this->MinY = std::min<_Precision> (this->MinY, rcBB.MinY);
00257   this->MaxY = std::max<_Precision> (this->MaxY, rcBB.MaxY);
00258   this->MinZ = std::min<_Precision> (this->MinZ, rcBB.MinZ);
00259   this->MaxZ = std::max<_Precision> (this->MaxZ, rcBB.MaxZ);
00260 }
00261 
00262 template <class _Precision>
00263 inline bool BoundBox3<_Precision>::IsCutLine ( const Vector3<_Precision>& rcBase, const Vector3<_Precision>& rcDir, _Precision fTolerance) const
00264 {
00265   _Precision fDist; 
00266  
00267   // zuerst nur grobe und schnelle Pruefung, indem der
00268   // Abstand der Linie zum Mittelpunkt der BB berechnet wird
00269   // und mit der maximalen Diagonalenlaenge + fTolerance
00270   // verglichen wird.
00271  
00272   // Distanz zwischen Mittelpunkt und Linie
00273   fDist = (rcDir % (CalcCenter() - rcBase)).Length() / rcDir.Length();
00274 
00275   if (fDist > (CalcDiagonalLength() + fTolerance))
00276     return false;
00277   else // hier genauerer Test
00278   {
00279     unsigned char i;
00280     Vector3<_Precision>  clVectRes;
00281    
00282     // schneide jede Seitenflaeche mit der Linie
00283     for (i = 0; i < 6; i++)
00284     {
00285      
00286       if (IntersectPlaneWithLine(i, rcBase, rcDir, clVectRes) == true)
00287       {
00288         // pruefe, ob Schnittpunkt innerhalb BB-Grenzen + Toleranz
00289         switch (i)
00290         {
00291           case 0 :  // linke und rechte Ebene
00292           case 1 :
00293             if ((IS_ON_RAY (MinY - fTolerance, MaxY + fTolerance, clVectRes.y) &&
00294                  IS_ON_RAY (MinZ - fTolerance, MaxZ + fTolerance, clVectRes.z)) == true) 
00295               return true;                     
00296             break;                    
00297           case 2 :  // obere und untere Ebene
00298           case 3 :
00299             if ((IS_ON_RAY (MinX - fTolerance, MaxX + fTolerance, clVectRes.x) &&
00300                  IS_ON_RAY (MinZ - fTolerance, MaxZ + fTolerance, clVectRes.z))== true) 
00301               return true;                     
00302             break;                    
00303           case 4 :  // vordere und hintere Ebene
00304           case 5 :
00305             if ((IS_ON_RAY (MinX - fTolerance, MaxX + fTolerance, clVectRes.x) &&
00306                  IS_ON_RAY (MinY - fTolerance, MaxY + fTolerance, clVectRes.y)) == true) 
00307               return true;                     
00308             break;                    
00309         }
00310       }
00311     }    
00312   }
00313   
00314   return false;
00315 } 
00316 
00317 template <class _Precision>
00318 inline bool BoundBox3<_Precision>::IsValid (void) const
00319 {
00320   return ((MinX <= MaxX) && (MinY <= MaxY) && (MinZ <= MaxZ));
00321 }
00322 
00323 #define HALF(A,B)  ((A)+((B-A)/2))
00324 
00325 template <class _Precision>
00326 inline bool BoundBox3<_Precision>::GetOctantFromVector (const Vector3<_Precision> &rclVct, OCTANT &rclOctant) const
00327 {
00328   if (!IsInBox (rclVct))
00329     return false;
00330     
00331   unsigned short usNdx = 0;
00332   if (IS_ON_RAY (HALF (MinX, MaxX), MaxX, rclVct.x))  // left/RIGHT
00333     usNdx |= 1;
00334   if (IS_ON_RAY (HALF (MinY, MaxY), MaxY, rclVct.y))  // down/UP
00335     usNdx |= 2;
00336   if (IS_ON_RAY (HALF (MinZ, MaxZ), MaxZ, rclVct.z))  // back/FRONT
00337     usNdx |= 4;
00338   rclOctant = (OCTANT) usNdx;
00339   return true;
00340 }
00341 
00342 template <class _Precision>
00343 inline BoundBox3<_Precision> BoundBox3<_Precision>::CalcOctant (typename BoundBox3< _Precision >::OCTANT Octant) const
00344 {
00345   BoundBox3<_Precision> cOct (*this);
00346 
00347   switch (Octant)
00348   {
00349     case OCT_LDB:
00350       cOct.MaxX = HALF (cOct.MinX, cOct.MaxX);
00351       cOct.MaxY = HALF (cOct.MinY, cOct.MaxY);
00352       cOct.MaxZ = HALF (cOct.MinZ, cOct.MaxZ);
00353       break;
00354 
00355     case OCT_RDB:
00356       cOct.MinX = HALF (cOct.MinX, cOct.MaxX);
00357       cOct.MaxY = HALF (cOct.MinY, cOct.MaxY);
00358       cOct.MaxZ = HALF (cOct.MinZ, cOct.MaxZ);
00359       break;
00360 
00361     case OCT_LUB:
00362       cOct.MaxX = HALF (cOct.MinX, cOct.MaxX);
00363       cOct.MinY = HALF (cOct.MinY, cOct.MaxY);
00364       cOct.MaxZ = HALF (cOct.MinZ, cOct.MaxZ);
00365       break;
00366 
00367     case OCT_RUB:
00368       cOct.MinX = HALF (cOct.MinX, cOct.MaxX);
00369       cOct.MinY = HALF (cOct.MinY, cOct.MaxY);
00370       cOct.MaxZ = HALF (cOct.MinZ, cOct.MaxZ);
00371       break;
00372 
00373     case OCT_LDF:
00374       cOct.MaxX = HALF (cOct.MinX, cOct.MaxX);
00375       cOct.MaxY = HALF (cOct.MinY, cOct.MaxY);
00376       cOct.MinZ = HALF (cOct.MinZ, cOct.MaxZ);
00377       break;
00378 
00379     case OCT_RDF:
00380       cOct.MinX = HALF (cOct.MinX, cOct.MaxX);
00381       cOct.MaxY = HALF (cOct.MinY, cOct.MaxY);
00382       cOct.MinZ = HALF (cOct.MinZ, cOct.MaxZ);
00383       break;
00384 
00385     case OCT_LUF:
00386       cOct.MaxX = HALF (cOct.MinX, cOct.MaxX);
00387       cOct.MinY = HALF (cOct.MinY, cOct.MaxY);
00388       cOct.MinZ = HALF (cOct.MinZ, cOct.MaxZ);
00389       break;
00390 
00391     case OCT_RUF:
00392       cOct.MinX = HALF (cOct.MinX, cOct.MaxX);
00393       cOct.MinY = HALF (cOct.MinY, cOct.MaxY);
00394       cOct.MinZ = HALF (cOct.MinZ, cOct.MaxZ);
00395       break;
00396   }
00397   return cOct;
00398 }
00399 
00400 #undef HALF
00401 
00402 template <class _Precision>
00403 inline void BoundBox3<_Precision>::CalcPlane (unsigned short usPlane, Vector3<_Precision>& rBase, Vector3<_Precision>& rNormal ) const
00404 {
00405   switch (usPlane)
00406   { 
00407   //links
00408   case 0:
00409     rBase.Set(MinX, MinY, MaxZ);
00410     rNormal.Set(1.0f, 0.0f, 0.0f);
00411     break;
00412 
00413   // rechts
00414   case 1:                                   
00415     rBase.Set(MaxX, MinY, MaxZ);
00416     rNormal.Set(1.0f, 0.0f, 0.0f);
00417     break;
00418 
00419   // oben
00420   case 2:
00421     rBase.Set(MinX, MaxY, MaxZ);
00422     rNormal.Set(0.0f, 1.0f, 0.0f);
00423     break;
00424 
00425   // unten
00426   case 3:
00427     rBase.Set(MinX, MinY, MaxZ);
00428     rNormal.Set(0.0f, 1.0f, 0.0f);
00429     break;
00430 
00431   // vorne
00432   case 4:
00433     rBase.Set(MinX, MinY, MaxZ);
00434     rNormal.Set(0.0f, 0.0f, 1.0f);
00435     break;
00436 
00437   // hinten
00438   default:
00439     rBase.Set(MinX, MinY, MinZ);
00440     rNormal.Set(0.0f, 0.0f, 1.0f);
00441     break;
00442   }
00443 }
00444 
00445 template <class _Precision>
00446 inline bool BoundBox3<_Precision>::CalcDistance (unsigned short usEdge, Vector3<_Precision>& rcP0, Vector3<_Precision>& rcP1) const
00447 {
00448   switch (usEdge)
00449   {
00450   case  0: 
00451     rcP0 = CalcPoint(0);
00452     rcP1 = CalcPoint(1);
00453     break;
00454   case  1: 
00455     rcP0 = CalcPoint(1);
00456     rcP1 = CalcPoint(2);
00457     break;
00458   case  2: 
00459     rcP0 = CalcPoint(2);
00460     rcP1 = CalcPoint(3);
00461     break;
00462   case  3: 
00463     rcP0 = CalcPoint(3);
00464     rcP1 = CalcPoint(0);
00465     break;
00466   case  4: 
00467     rcP0 = CalcPoint(4);
00468     rcP1 = CalcPoint(5);
00469     break;
00470   case  5: 
00471     rcP0 = CalcPoint(5);
00472     rcP1 = CalcPoint(6);
00473     break;
00474   case  6: 
00475     rcP0 = CalcPoint(6);
00476     rcP1 = CalcPoint(7);
00477     break;
00478   case  7: 
00479     rcP0 = CalcPoint(7);
00480     rcP1 = CalcPoint(4);
00481     break;
00482   case  8: 
00483     rcP0 = CalcPoint(0);
00484     rcP1 = CalcPoint(4);
00485     break;
00486   case  9: 
00487     rcP0 = CalcPoint(1);
00488     rcP1 = CalcPoint(5);
00489     break;
00490   case 10: 
00491     rcP0 = CalcPoint(2);
00492     rcP1 = CalcPoint(6);
00493     break;
00494   case 11: 
00495     rcP0 = CalcPoint(3);
00496     rcP1 = CalcPoint(7);
00497     break;
00498   default: 
00499     return false; // undefined
00500   }
00501 
00502   return true;
00503 }
00504 
00505 template <class _Precision>
00506 inline bool BoundBox3<_Precision>::IntersectionPoint (const Vector3<_Precision> &rcVct, const Vector3<_Precision> &rcVctDir, Vector3<_Precision>& cVctRes, _Precision epsilon) const
00507 {
00508     bool rc=false;
00509     BoundBox3<_Precision> cCmpBound(*this);
00510     unsigned short i;
00511 
00512     // enlarge bounding box by epsilon
00513     cCmpBound.Enlarge(epsilon);
00514 
00515     // Is point inside?
00516     if (cCmpBound.IsInBox (rcVct)) {
00517         // test sides
00518         for (i = 0; (i < 6) && (!rc); i++) {
00519             rc = IntersectPlaneWithLine(i, rcVct, rcVctDir, cVctRes);
00520             if (!cCmpBound.IsInBox(cVctRes)) 
00521                 rc = false;
00522             if (rc == true) {
00523                 // does intersection point lie in desired direction
00524                 // or was found the opposing side?
00525                 // -> scalar product of both direction vectors > 0 (angle < 90)
00526                 rc = ((cVctRes - rcVct) * rcVctDir) >= (_Precision)0.0;
00527             }
00528         }
00529     }
00530 
00531     return rc;
00532 }
00533 
00534 template <class _Precision>
00535 inline bool BoundBox3<_Precision>::IntersectPlaneWithLine (unsigned short usSide, const Vector3<_Precision>& rcBase,
00536                                          const Vector3<_Precision>& rcDir, Vector3<_Precision>& rcP0) const
00537 {
00538   _Precision k;
00539   Vector3<_Precision> cBase, cNormal;
00540   Vector3<_Precision>  cDir(rcDir);
00541   CalcPlane(usSide, cBase, cNormal);
00542 
00543   if ((cNormal * cDir) == 0.0f) 
00544     return false;  // no point of intersection
00545   else
00546   {
00547     k = (cNormal * (cBase - rcBase)) / (cNormal * cDir);
00548     cDir.Scale(k, k, k);
00549     rcP0 = rcBase + cDir;
00550 
00551     return true;
00552   }
00553 }
00554 
00555 template <class _Precision>
00556 inline bool BoundBox3<_Precision>::IntersectWithLine ( const Vector3<_Precision> & rcBase, const Vector3<_Precision>& rcDir,
00557                                      Vector3<_Precision>& rcP0, Vector3<_Precision>& rcP1 ) const
00558 {
00559   Vector3<_Precision>  clVectRes, clVect[6];
00560   unsigned short i, j;
00561   
00562   j = 0;
00563   // schneide jede Seitenflaeche mit der Linie
00564   for (i = 0; i < 6; i++)
00565   {
00566 
00567     if ( IntersectPlaneWithLine(i, rcBase, rcDir, clVectRes ) )
00568     {
00569       // pruefe, ob Schnittpunkt innerhalb BB-Grenzen
00570       switch (i)
00571       {
00572         case 0 :  // linke und rechte Ebene
00573         case 1 :
00574           if ((IS_ON_RAY(MinY, MaxY, clVectRes.y) &&
00575                IS_ON_RAY(MinZ, MaxZ, clVectRes.z)) == true)
00576           {
00577             clVect[j] = clVectRes;
00578             j++;
00579           }                                 
00580           break;                    
00581         case 2 :  // obere und untere Ebene
00582         case 3 :
00583           if ((IS_ON_RAY(MinX, MaxX, clVectRes.x) &&
00584                IS_ON_RAY(MinZ, MaxZ, clVectRes.z))== true)
00585           {
00586             clVect[j] = clVectRes;
00587             j++;                     
00588           }
00589           break;                    
00590         case 4 :  // vordere und hintere Ebene
00591         case 5 :
00592           if ((IS_ON_RAY(MinX, MaxX, clVectRes.x) &&
00593                IS_ON_RAY(MinY, MaxY, clVectRes.y)) == true) 
00594           {
00595             clVect[j] = clVectRes;
00596             j++;
00597           }        
00598           break;                    
00599       }
00600     }
00601   }
00602   
00603   if (j == 2)  
00604   {
00605     rcP0 = clVect[0];
00606     rcP1 = clVect[1];
00607     return true;
00608   }
00609   else if (j > 2)  // suche 2 unterschiedliche Schnittpunkte
00610   {
00611     for (i = 1; i < j; i++)
00612     {
00613       if (clVect[i] != clVect[0])
00614       {
00615         rcP0 = clVect[0];
00616         rcP1 = clVect[i];
00617         return true;
00618       }
00619     }
00620   }
00621   
00622   return false; 
00623 }
00624 
00625 template <class _Precision>
00626 inline typename BoundBox3<_Precision>::SIDE BoundBox3<_Precision>::GetSideFromRay (const Vector3<_Precision> &rclPt, const Vector3<_Precision> &rclDir) const
00627 {
00628   Vector3<_Precision> cIntersection;
00629   return GetSideFromRay( rclPt, rclDir, cIntersection);
00630 }
00631 
00632 template <class _Precision>
00633 inline typename BoundBox3<_Precision>::SIDE BoundBox3<_Precision>::GetSideFromRay (const Vector3<_Precision> &rclPt, const Vector3<_Precision> &rclDir,
00634                                                                                    Vector3<_Precision>& rcInt) const
00635 {
00636   Vector3<_Precision> cP0, cP1;
00637   if ( IntersectWithLine(rclPt, rclDir, cP0, cP1) == false )
00638     return INVALID;
00639 
00640   Vector3<_Precision>  cOut;
00641   // same orientation
00642   if ( (cP1-cP0)*rclDir > 0.0f )
00643     cOut = cP1;
00644   else
00645     cOut = cP0;
00646 
00647   rcInt = cOut;
00648 
00649   _Precision fMax = 1.0e-3f;
00650   SIDE  tSide = INVALID;
00651 
00652   if (fabs(cOut.x - MinX) < fMax)      // linke Ebene
00653   {
00654     fMax = _Precision(fabs(cOut.x - MinX));
00655     tSide = LEFT;
00656   }
00657 
00658   if (fabs(cOut.x - MaxX) < fMax) // rechte Ebene
00659   {
00660     fMax = _Precision(fabs(cOut.x - MaxX));
00661     tSide = RIGHT;
00662   }
00663 
00664   if (fabs(cOut.y - MinY) < fMax) // untere Ebene
00665   {
00666     fMax = _Precision(fabs(cOut.y - MinY));
00667     tSide = BOTTOM;
00668   }
00669 
00670   if (fabs(cOut.y - MaxY) < fMax) // obere Ebene
00671   {
00672     fMax = _Precision(fabs(cOut.y - MaxY));
00673     tSide = TOP;
00674   }
00675 
00676   if (fabs(cOut.z - MinZ) < fMax) // vordere Ebene
00677   { 
00678     fMax = _Precision(fabs(cOut.z - MinZ));
00679     tSide = FRONT;
00680   }
00681 
00682   if (fabs(cOut.z - MaxZ) < fMax) // hintere Ebene
00683   {
00684     fMax = _Precision(fabs(cOut.z - MaxZ));
00685     tSide = BACK;
00686   }
00687 
00688   return tSide;
00689 }
00690 
00691 template <class _Precision>
00692 inline void BoundBox3<_Precision>::Flush (void)
00693 {
00694   MinX = MinY = MinZ =  FLOAT_MAX;
00695   MaxX = MaxY = MaxZ = -FLOAT_MAX;
00696 }
00697 
00698 template <class _Precision>
00699 inline void BoundBox3<_Precision>::Print (void)
00700 {
00701   printf ("X1 : %5.2f   Y1 : %5.2f   Z1 : %5.2f\n", MinX, MinY, MinZ);
00702   printf ("X2 : %5.2f   Y2 : %5.2f   Z2 : %5.2f\n", MaxX, MaxY, MaxZ);
00703 }
00704 
00705 template <class _Precision>
00706 inline BoundBox2D BoundBox3<_Precision>::ProjectBox(const ViewProjMethod *pclP) const
00707 {
00708   BoundBox2D  clBB2D;
00709 
00710   clBB2D.SetVoid();
00711 
00712   for (int i = 0; i < 8; i++)
00713   {
00714     Vector3<_Precision> clTrsPt = (*pclP)(CalcPoint(i));
00715     clBB2D &= Vector2D(clTrsPt.x, clTrsPt.y);
00716   }
00717 
00718   return clBB2D;
00719 }
00720 
00721 template <class _Precision>
00722 inline BoundBox3<_Precision> BoundBox3<_Precision>::Transformed(const Matrix4D& mat) const
00723 {
00724   BoundBox3<_Precision> bbox;
00725   for (int i=0; i<8; i++)
00726       bbox.Add(mat * CalcPoint(i));
00727   return bbox;
00728 }
00729 
00730 template <class _Precision>
00731 inline Vector3<_Precision> BoundBox3<_Precision>::NearestPoint (const Vector3<_Precision> &rclPt) const
00732 {
00733   // Suche naechsten Punkt auf der BB, !!! Punkt MUSS innerhalb BB liegen !!!
00734   _Precision fMinDist = FLOAT_MAX;
00735   Vector3<_Precision> cBase, cNormal, clRet;
00736 
00737   for (int i = 0; i < 6; i++)
00738   {
00739     Vector3<_Precision> clTemp = rclPt;
00740     CalcPlane(i, cBase, cNormal);
00741     clTemp.ProjToPlane(cBase, cNormal);
00742     _Precision fDist = (clTemp - rclPt).Length();
00743     if (fDist < fMinDist)
00744     {
00745       fMinDist = fDist;
00746       clRet = clTemp; 
00747     }
00748   }
00749 
00750   return clRet;
00751 }
00752 
00753 
00754 template <class _Precision>
00755 inline BoundBox3<_Precision>::BoundBox3 (_Precision fMinX, _Precision fMinY, _Precision fMinZ,
00756                                  _Precision fMaxX, _Precision fMaxY, _Precision fMaxZ)
00757 : MinX(fMinX), MinY(fMinY), MinZ(fMinZ),
00758   MaxX(fMaxX), MaxY(fMaxY), MaxZ(fMaxZ)
00759 {
00760 }
00761 
00762 template <class _Precision>
00763 inline BoundBox3<_Precision>::BoundBox3 (const Vector3<_Precision> *pclVect, unsigned long ulCt)
00764 : MinX(FLOAT_MAX),  MinY(FLOAT_MAX),  MinZ(FLOAT_MAX),
00765   MaxX(-FLOAT_MAX), MaxY(-FLOAT_MAX), MaxZ(-FLOAT_MAX)
00766 {
00767   const Vector3<_Precision>  *pI, *pEnd = pclVect + ulCt;
00768   for (pI = pclVect; pI < pEnd; pI++)
00769   {
00770     MinX = std::min<_Precision>(MinX, pI->x);
00771     MinY = std::min<_Precision>(MinY, pI->y);
00772     MinZ = std::min<_Precision>(MinZ, pI->z);
00773     MaxX = std::max<_Precision>(MaxX, pI->x);
00774     MaxY = std::max<_Precision>(MaxY, pI->y);
00775     MaxZ = std::max<_Precision>(MaxZ, pI->z);
00776   }
00777 }
00778 
00779 template <class _Precision>
00780 inline  BoundBox3<_Precision>& BoundBox3<_Precision>::operator = (const BoundBox3<_Precision> &rcBound)
00781 {
00782   MinX = rcBound.MinX;
00783   MinY = rcBound.MinY;
00784   MinZ = rcBound.MinZ;
00785   MaxX = rcBound.MaxX;
00786   MaxY = rcBound.MaxY;
00787   MaxZ = rcBound.MaxZ;
00788   return *this;
00789 }
00790 
00791 template <class _Precision>
00792 inline  BoundBox3<_Precision>& BoundBox3<_Precision>::operator &= (const Vector3<_Precision> &rclVect)
00793 {
00794   MinX = std::min<_Precision>(MinX, rclVect.x);
00795   MinY = std::min<_Precision>(MinY, rclVect.y);
00796   MinZ = std::min<_Precision>(MinZ, rclVect.z);
00797   MaxX = std::max<_Precision>(MaxX, rclVect.x);
00798   MaxY = std::max<_Precision>(MaxY, rclVect.y);
00799   MaxZ = std::max<_Precision>(MaxZ, rclVect.z);
00800   return *this;
00801 }
00802 
00803 template <class _Precision>
00804 inline bool BoundBox3<_Precision>::operator && (const BoundBox3<_Precision> &rcBB) const
00805 {
00806   return  (IS_ON_RAY (MinX, MaxX, rcBB.MinX)        ||
00807            IS_ON_RAY (MinX, MaxX, rcBB.MaxX)        ||
00808            IS_ON_RAY (rcBB.MinX,  rcBB.MaxX, MinX)  ||
00809            IS_ON_RAY (rcBB.MinX,  rcBB.MaxX, MaxX)) &&
00810           (IS_ON_RAY (MinY, MaxY, rcBB.MinY)        ||
00811            IS_ON_RAY (MinY, MaxY, rcBB.MaxY)        ||
00812            IS_ON_RAY (rcBB.MinY,  rcBB.MaxY, MinY)  ||
00813            IS_ON_RAY (rcBB.MinY,  rcBB.MaxY, MaxY)) &&
00814           (IS_ON_RAY (MinZ, MaxZ, rcBB.MinZ)        ||
00815            IS_ON_RAY (MinZ, MaxZ, rcBB.MaxZ)        ||
00816            IS_ON_RAY (rcBB.MinZ,  rcBB.MaxZ, MinZ)  ||
00817            IS_ON_RAY (rcBB.MinZ,  rcBB.MaxZ, MaxZ));
00818 }
00819 
00820 template <class _Precision>
00821 inline bool BoundBox3<_Precision>::operator && (const BoundBox2D &rcBB) const
00822 {
00823   return  (IS_ON_RAY (MinX, MaxX, rcBB.fMinX)         ||
00824            IS_ON_RAY (MinX, MaxX, rcBB.fMaxX)         ||
00825            IS_ON_RAY (rcBB.fMinX,  rcBB.fMaxX, MinX)  ||
00826            IS_ON_RAY (rcBB.fMinX,  rcBB.fMaxX, MaxX)) &&
00827           (IS_ON_RAY (MinY, MaxY, rcBB.fMinY)         ||
00828            IS_ON_RAY (MinY, MaxY, rcBB.fMaxY)         ||
00829            IS_ON_RAY (rcBB.fMinY,  rcBB.fMaxY, MinY)  ||
00830            IS_ON_RAY (rcBB.fMinY,  rcBB.fMaxY, MaxY) );
00831 }
00832 
00833 template <class _Precision>
00834 inline Vector3<_Precision> BoundBox3<_Precision>::CalcPoint (unsigned short usPoint) const
00835 {
00836   switch (usPoint)
00837   {
00838     case 0: return Vector3<_Precision>(MinX, MinY, MaxZ);
00839     case 1: return Vector3<_Precision>(MaxX, MinY, MaxZ);
00840     case 2: return Vector3<_Precision>(MaxX, MaxY, MaxZ);
00841     case 3: return Vector3<_Precision>(MinX, MaxY, MaxZ);
00842     case 4: return Vector3<_Precision>(MinX, MinY, MinZ);
00843     case 5: return Vector3<_Precision>(MaxX, MinY, MinZ);
00844     case 6: return Vector3<_Precision>(MaxX, MaxY, MinZ);
00845     case 7: return Vector3<_Precision>(MinX, MaxY, MinZ);
00846   }
00847 
00848   return Vector3<_Precision>();
00849 }
00850 
00851 template <class _Precision>
00852 inline Vector3<_Precision> BoundBox3<_Precision>::CalcCenter (void) const
00853 {
00854   return Vector3<_Precision>(MinX + (MaxX - MinX) / 2.0f,
00855                   MinY + (MaxY - MinY) / 2.0f,
00856                   MinZ + (MaxZ - MinZ) / 2.0f);
00857 }
00858 
00859 template <class _Precision>
00860 inline _Precision BoundBox3<_Precision>::CalcDiagonalLength (void) const
00861 {
00862   return (_Precision)sqrt (((MaxX - MinX) * (MaxX - MinX)) +
00863                       ((MaxY - MinY) * (MaxY - MinY)) +
00864                       ((MaxZ - MinZ) * (MaxZ - MinZ)));
00865 }
00866 
00867 template <class _Precision>
00868 inline bool BoundBox3<_Precision>::IsCutPlane (const Vector3<_Precision> &rclBase, const Vector3<_Precision> &rclNormal) const
00869 {
00870   if (fabs(CalcCenter().DistanceToPlane(rclBase, rclNormal)) < CalcDiagonalLength())
00871   {
00872     _Precision fD = CalcPoint(0).DistanceToPlane(rclBase, rclNormal);
00873     for (unsigned short i = 1; i < 8; i++)
00874     {
00875       if ((CalcPoint(i).DistanceToPlane(rclBase, rclNormal) * fD) < 0.0f)
00876         return true;
00877     }
00878   }
00879   return false;
00880 }
00881 
00882 template <class _Precision>
00883 inline void BoundBox3<_Precision>::Enlarge (_Precision fLen)
00884 {
00885   MinX -= fLen; MinY -= fLen; MinZ -= fLen;
00886   MaxX += fLen; MaxY += fLen; MaxZ += fLen;
00887 }
00888 
00889 template <class _Precision>
00890 inline void BoundBox3<_Precision>::Shrink (_Precision fLen)
00891 {
00892   MinX += fLen; MinY += fLen; MinZ += fLen;
00893   MaxX -= fLen; MaxY -= fLen; MaxZ -= fLen;
00894 }
00895 
00896 template <class _Precision>
00897 inline bool BoundBox3<_Precision>::IsInBox (const Vector3<_Precision> &rcVct) const
00898 {
00899   return (IS_ON_RAY (MinX, MaxX, rcVct.x) &&
00900           IS_ON_RAY (MinY, MaxY, rcVct.y) &&
00901           IS_ON_RAY (MinZ, MaxZ, rcVct.z));
00902 }
00903 
00904 template <class _Precision>
00905 inline bool BoundBox3<_Precision>::IsInBox (const BoundBox3<_Precision> &rcBB) const
00906 {
00907   return (IS_ON_RAY (MinX, MaxX, rcBB.MinX) &&
00908           IS_ON_RAY (MinX, MaxX, rcBB.MaxX) &&
00909           IS_ON_RAY (MinY, MaxY, rcBB.MinY) &&
00910           IS_ON_RAY (MinY, MaxY, rcBB.MaxY) &&
00911           IS_ON_RAY (MinZ, MaxZ, rcBB.MinZ) &&
00912           IS_ON_RAY (MinZ, MaxZ, rcBB.MaxZ));
00913 }
00914 
00915 template <class _Precision>
00916 inline bool BoundBox3<_Precision>::IsInBox (const BoundBox2D &rcBB) const
00917 {
00918    return ( IS_ON_RAY (MinX, MaxX, rcBB.fMinX) &&
00919             IS_ON_RAY (MinX, MaxX, rcBB.fMaxX) &&
00920             IS_ON_RAY (MinY, MaxY, rcBB.fMinY) &&
00921             IS_ON_RAY (MinY, MaxY, rcBB.fMaxY) );
00922 }
00923 
00924 template <class _Precision>
00925 inline _Precision BoundBox3<_Precision>::LengthX (void) const
00926 {
00927   return MaxX - MinX;
00928 }
00929 
00930 template <class _Precision>
00931 inline _Precision BoundBox3<_Precision>::LengthY (void) const
00932 {
00933   return MaxY - MinY;
00934 }
00935 
00936 template <class _Precision>
00937 inline _Precision BoundBox3<_Precision>::LengthZ (void) const
00938 {
00939   return MaxZ - MinZ;
00940 }
00941 
00942 template <class _Precision>
00943 inline void BoundBox3<_Precision>::MoveX (_Precision f)
00944 {
00945   MinX += f; MaxX += f;
00946 }
00947 
00948 template <class _Precision>
00949 inline void BoundBox3<_Precision>::MoveY (_Precision f)
00950 {
00951   MinY += f; MaxY += f;
00952 }
00953 
00954 template <class _Precision>
00955 inline void BoundBox3<_Precision>::MoveZ (_Precision f)
00956 {
00957   MinZ += f; MaxZ += f;
00958 }
00959 
00960 template <class _Precision>
00961 inline void BoundBox3<_Precision>::ScaleX (_Precision f)
00962 {
00963   MinX *= f; MaxX *= f;
00964 }
00965 
00966 template <class _Precision>
00967 inline void BoundBox3<_Precision>::ScaleY (_Precision f)
00968 {
00969   MinY *= f; MaxY *= f;
00970 }
00971 
00972 template <class _Precision>
00973 inline void BoundBox3<_Precision>::ScaleZ (_Precision f)
00974 {
00975   MinZ *= f; MaxZ *= f;
00976 }
00977 
00978 typedef BoundBox3<float> BoundBox3f;
00979 typedef BoundBox3<double> BoundBox3d;
00980 
00981 } // namespace Base
00982 
00983 
00984 #endif  // BASE_BOUNDBOX_H
00985 

Generated on Wed Nov 23 18:59:58 2011 for FreeCAD by  doxygen 1.6.1