cgma
CubitBox.cpp
Go to the documentation of this file.
00001 //- Class: CubitBox
00002 //- Description: This file defines the CubitBox class.
00003 //- Owner: Greg Sjaardema
00004 //- Checked by:
00005 
00006 #include <cstdio>
00007 #include <cstdlib>
00008 #include <cassert>
00009 
00010 #include "CubitBox.hpp"
00011 #include "CubitVector.hpp"
00012 #include "CubitDefines.h"
00013 
00014 CubitBox::~CubitBox()
00015 {}
00016 
00017 CubitBox::CubitBox() :
00018     minimum_(0.0, 0.0, 0.0),
00019     maximum_(0.0, 0.0, 0.0)
00020 {}
00021 
00022 CubitBox::CubitBox(const CubitVector &min, const CubitVector &max)
00023 {
00024   minimum_.set (CUBIT_MIN (min.x(), max.x()),
00025                 CUBIT_MIN (min.y(), max.y()),
00026                 CUBIT_MIN (min.z(), max.z()));
00027   maximum_.set (CUBIT_MAX (min.x(), max.x()),
00028                 CUBIT_MAX (min.y(), max.y()),
00029                 CUBIT_MAX (min.z(), max.z()));
00030 }
00031 
00032 CubitBox::CubitBox(const CubitVector &min_max) :
00033     minimum_(min_max),
00034     maximum_(min_max)
00035 {}
00036 
00037 CubitBox::CubitBox(const CubitBox& copy_from):
00038     minimum_(copy_from.minimum_),
00039     maximum_(copy_from.maximum_)
00040 {}
00041 
00042 CubitBox::CubitBox(const std::vector<CubitVector> & pts)
00043 {
00044   minimum_.set(0.0, 0.0, 0.0);
00045   maximum_.set(0.0, 0.0, 0.0);
00046   for ( size_t i=0; i<pts.size(); i++ )
00047   {
00048     double x = pts[i].x();
00049     double y = pts[i].y();
00050     double z = pts[i].z();
00051     minimum_.set(CUBIT_MIN(minimum_.x(), x),
00052                  CUBIT_MIN(minimum_.y(), y),
00053                  CUBIT_MIN(minimum_.z(), z));
00054     maximum_.set(CUBIT_MAX(maximum_.x(), x),
00055                  CUBIT_MAX(maximum_.y(), y),
00056                  CUBIT_MAX(maximum_.z(), z));
00057   }
00058 }
00059 
00060 void CubitBox::reset(const CubitVector& vector)
00061 {
00062   minimum_ = vector;
00063   maximum_ = vector;
00064 }
00065 
00066 void CubitBox::reset(const CubitVector &min, const CubitVector &max)
00067 {
00068   minimum_.set (CUBIT_MIN (min.x(), max.x()),
00069         CUBIT_MIN (min.y(), max.y()),
00070         CUBIT_MIN (min.z(), max.z()));
00071   maximum_.set (CUBIT_MAX (min.x(), max.x()),
00072         CUBIT_MAX (min.y(), max.y()),
00073         CUBIT_MAX (min.z(), max.z()));
00074 }
00075 
00076 void CubitBox::reset(const CubitBox &box)
00077 {
00078   minimum_ = box.minimum_;
00079   maximum_ = box.maximum_;
00080 }
00081 
00082 CubitVector CubitBox::minimum() const
00083 {
00084   return CubitVector(minimum_);
00085 }
00086 
00087 CubitVector CubitBox::maximum() const
00088 {
00089   return CubitVector(maximum_);
00090 }
00091 
00092 double CubitBox::max_x() const
00093 {
00094   return maximum_.x();
00095 }
00096 
00097 double CubitBox::max_y() const
00098 {
00099   return maximum_.y();
00100 }
00101 
00102 double CubitBox::max_z() const
00103 {
00104   return maximum_.z();
00105 }
00106 
00107 double CubitBox::min_x() const
00108 {
00109   return minimum_.x();
00110 }
00111 
00112 double CubitBox::min_y() const
00113 {
00114   return minimum_.y();
00115 }
00116 
00117 double CubitBox::min_z() const
00118 {
00119   return minimum_.z();
00120 }
00121 
00122 CubitVector CubitBox::center() const
00123 {
00124   return CubitVector(minimum_ + maximum_) / 2.0;
00125 }
00126 
00127 CubitVector CubitBox::diagonal() const
00128 {
00129   return CubitVector(maximum_ - minimum_);
00130 }
00131 
00132 double CubitBox::minimum_range( void)
00133 {
00134   return CUBIT_MIN(CUBIT_MIN( x_range(), y_range()), z_range());
00135 }
00136 
00137 
00138 double CubitBox::maximum_range( void)
00139 {
00140   return CUBIT_MAX( CUBIT_MAX( x_range(), y_range()), z_range());
00141 }
00142 
00143 double CubitBox::x_range() const
00144 { return (maximum_.x() - minimum_.x()); }
00145 
00146 double CubitBox::y_range() const
00147 { return (maximum_.y() - minimum_.y()); }
00148 
00149 double CubitBox::z_range() const
00150 { return (maximum_.z() - minimum_.z()); }
00151 
00152 CubitBox& CubitBox::operator=(const CubitBox &box)
00153 {
00154   if (this != &box)
00155     {
00156       minimum_ = box.minimum_;
00157       maximum_ = box.maximum_;
00158     }
00159   return *this;
00160 }
00161 
00162 bool CubitBox::overlap( double tolerance , const CubitBox& box ) const
00163 {
00164   //     | - note the '!'.  This condition checks that the boxes
00165   //     |   do NOT intersect and negates the result. 
00166   return ! ( (box.minimum_.x() - maximum_.x() > tolerance) ||
00167              (box.minimum_.y() - maximum_.y() > tolerance) ||
00168              (box.minimum_.z() - maximum_.z() > tolerance) ||
00169              (minimum_.x() - box.maximum_.x() > tolerance) ||
00170              (minimum_.y() - box.maximum_.y() > tolerance) ||
00171              (minimum_.z() - box.maximum_.z() > tolerance) );
00172 }
00173              
00174   
00175   
00176 
00177 // Union of this and box
00178 CubitBox& CubitBox::operator|=(const CubitBox& box)
00179 {
00180   minimum_.x(CUBIT_MIN(minimum_.x(), box.minimum_.x()));
00181   minimum_.y(CUBIT_MIN(minimum_.y(), box.minimum_.y()));
00182   minimum_.z(CUBIT_MIN(minimum_.z(), box.minimum_.z()));
00183 
00184   maximum_.x(CUBIT_MAX(maximum_.x(), box.maximum_.x()));
00185   maximum_.y(CUBIT_MAX(maximum_.y(), box.maximum_.y()));
00186   maximum_.z(CUBIT_MAX(maximum_.z(), box.maximum_.z()));
00187   return *this;
00188 }
00189 
00190 // Union of this and vector
00191 CubitBox& CubitBox::operator|=(const CubitVector& vector)
00192 {
00193   minimum_.x(CUBIT_MIN(minimum_.x(), vector.x()));
00194   minimum_.y(CUBIT_MIN(minimum_.y(), vector.y()));
00195   minimum_.z(CUBIT_MIN(minimum_.z(), vector.z()));
00196 
00197   maximum_.x(CUBIT_MAX(maximum_.x(), vector.x()));
00198   maximum_.y(CUBIT_MAX(maximum_.y(), vector.y()));
00199   maximum_.z(CUBIT_MAX(maximum_.z(), vector.z()));
00200   return *this;
00201 }
00202 
00203 // Intersection of this and box
00204 CubitBox& CubitBox::operator&=(const CubitBox& box)
00205 {
00206   minimum_.x(CUBIT_MAX(minimum_.x(), box.minimum_.x()));
00207   minimum_.y(CUBIT_MAX(minimum_.y(), box.minimum_.y()));
00208   minimum_.z(CUBIT_MAX(minimum_.z(), box.minimum_.z()));
00209 
00210   maximum_.x(CUBIT_MIN(maximum_.x(), box.maximum_.x()));
00211   maximum_.y(CUBIT_MIN(maximum_.y(), box.maximum_.y()));
00212   maximum_.z(CUBIT_MIN(maximum_.z(), box.maximum_.z()));
00213 
00214   if (minimum_.x() > maximum_.x() ||
00215       minimum_.y() > maximum_.y() ||
00216       minimum_.z() > maximum_.z())
00217   {
00218     minimum_.set(0.0, 0.0, 0.0);
00219     maximum_.set(0.0, 0.0, 0.0);
00220   }
00221   return *this;
00222 }
00223 
00224 CubitBox& CubitBox::operator*=(double scale)
00225 {
00226   CubitVector center_vec = center();
00227   *this -= center_vec;
00228   minimum_ *= scale;
00229   maximum_ *= scale;
00230   *this += center_vec;
00231   return *this;
00232 }
00233 
00234 CubitBox& CubitBox::operator/=(double scale)
00235 {
00236   if(scale == 0.0)
00237     throw ("Cannot Divide by Zero");
00238   //assert(scale != 0.0);
00239   *this *= 1/scale;
00240   return *this;
00241 }
00242 
00243 CubitBox& CubitBox::operator+=(const CubitVector& offset)
00244 {
00245   minimum_ += offset;
00246   maximum_ += offset;
00247   return *this;
00248 }
00249 
00250 CubitBox& CubitBox::operator-=(const CubitVector& offset)
00251 {
00252   minimum_ -= offset;
00253   maximum_ -= offset;
00254   return *this;
00255 }
00256 
00257 int CubitBox::operator<(const CubitBox& box) const
00258 {
00259   return (box.minimum_.x() < minimum_.x() &&
00260           box.minimum_.y() < minimum_.y() &&
00261           box.minimum_.z() < minimum_.z() &&
00262           box.maximum_.x() > maximum_.x() &&
00263           box.maximum_.y() > maximum_.y() &&
00264           box.maximum_.z() > maximum_.z());
00265 }
00266 
00267 int CubitBox::operator<=(const CubitBox& box) const
00268 {
00269   return (box.minimum_.x() <= minimum_.x() &&
00270           box.minimum_.y() <= minimum_.y() &&
00271           box.minimum_.z() <= minimum_.z() &&
00272           box.maximum_.x() >= maximum_.x() &&
00273           box.maximum_.y() >= maximum_.y() &&
00274           box.maximum_.z() >= maximum_.z());
00275 }
00276 
00277 int CubitBox::operator>(const CubitBox& box) const
00278 {
00279   return (box.minimum_.x() > minimum_.x() &&
00280           box.minimum_.y() > minimum_.y() &&
00281           box.minimum_.z() > minimum_.z() &&
00282           box.maximum_.x() < maximum_.x() &&
00283           box.maximum_.y() < maximum_.y() &&
00284           box.maximum_.z() < maximum_.z());
00285 }
00286 
00287 int CubitBox::operator>=(const CubitBox& box) const
00288 {
00289   return (box.minimum_.x() >= minimum_.x() &&
00290           box.minimum_.y() >= minimum_.y() &&
00291           box.minimum_.z() >= minimum_.z() &&
00292           box.maximum_.x() <= maximum_.x() &&
00293           box.maximum_.y() <= maximum_.y() &&
00294           box.maximum_.z() <= maximum_.z());
00295 }
00296 
00297 int CubitBox::operator>(const CubitVector& vect) const
00298 {
00299   return (vect.x() > minimum_.x() && vect.x() < maximum_.x() &&
00300           vect.y() > minimum_.y() && vect.y() < maximum_.y() &&
00301           vect.z() > minimum_.z() && vect.z() < maximum_.z() );
00302 }
00303 
00304 int CubitBox::operator>=(const CubitVector& vect) const
00305 {
00306   return (vect.x() >= minimum_.x() && 
00307           vect.x() <= maximum_.x() &&
00308           vect.y() >= minimum_.y() && 
00309           vect.y() <= maximum_.y() &&
00310           vect.z() >= minimum_.z() && 
00311           vect.z() <= maximum_.z() );
00312 }
00313 
00314 CubitBox operator|(const CubitBox& lhs, const CubitBox& rhs)
00315 {
00316   return CubitBox(lhs) |= rhs;
00317 }
00318 
00319 CubitBox operator&(const CubitBox& lhs, const CubitBox& rhs)
00320 {
00321   return CubitBox(lhs) &= rhs;
00322 }
00323 
00324 CubitBox operator*(double lhs, const CubitBox& rhs)
00325 {
00326   return CubitBox(rhs) *= lhs;
00327 }
00328 
00329 CubitBox operator*(const CubitBox& lhs, double rhs)
00330 {
00331   return CubitBox(lhs) *= rhs;
00332 }
00333 
00334 CubitBox operator/(const CubitBox& lhs, double rhs)
00335 {
00336   return CubitBox(lhs) /= rhs;
00337 }
00338 
00339 CubitBox operator+(const CubitBox& lhs, const CubitVector& rhs)
00340 {
00341   return CubitBox(lhs) += rhs;
00342 }
00343 
00344 CubitBox operator-(const CubitBox& lhs, const CubitVector& rhs)
00345 {
00346   return CubitBox(lhs) -= rhs;
00347 }
00348 
00349 double CubitBox::distance_squared( const CubitVector& point ) const
00350 {
00351   return (point - closest_point(point)).length_squared();
00352 }
00353 
00354 
00355 
00356 //-------------------------------------------------------------------------
00357 // Purpose       : Find the closest point on the CubitBox
00358 //
00359 // Special Notes : 
00360 //
00361 // Creator       : Jason Kraftcheck
00362 //
00363 // Creation Date : 03/12/98
00364 //-------------------------------------------------------------------------
00365 CubitVector CubitBox::closest_point( const CubitVector& point ) const
00366 {
00367   CubitVector result;
00368   
00369   if( point.x() < minimum_.x() )
00370     result.x( minimum_.x() );
00371   else if( point.x() > maximum_.x() )
00372     result.x( maximum_.x() );
00373   else
00374     result.x( point.x() );
00375   
00376   if( point.y() < minimum_.y() )
00377     result.y( minimum_.y() );
00378   else if( point.y() > maximum_.y() )
00379     result.y( maximum_.y() );
00380   else
00381     result.y( point.y() );
00382   
00383   if( point.z() < minimum_.z() )
00384     result.z( minimum_.z() );
00385   else if( point.z() > maximum_.z() )
00386     result.z( maximum_.z() );
00387   else
00388     result.z( point.z() );
00389   
00390   return result;
00391 }
00392 
00393 CubitBox::CubitBox(const double min[3], const double max[3])
00394 {
00395   minimum_.set (CUBIT_MIN (min[0], max[0]),
00396                 CUBIT_MIN (min[1], max[1]),
00397                 CUBIT_MIN (min[2], max[2]));
00398   maximum_.set (CUBIT_MAX (min[0], max[0]),
00399                 CUBIT_MAX (min[1], max[1]),
00400                 CUBIT_MAX (min[2], max[2]));
00401 }
00402 
00403 void CubitBox::reset(const double min[3], const double max[3])
00404 {
00405   minimum_.set (CUBIT_MIN (min[0], max[0]),
00406                 CUBIT_MIN (min[1], max[1]),
00407                 CUBIT_MIN (min[2], max[2]));
00408   maximum_.set (CUBIT_MAX (min[0], max[0]),
00409                 CUBIT_MAX (min[1], max[1]),
00410                 CUBIT_MAX (min[2], max[2]));
00411 }
00412 
00413 void CubitBox::get_corners( CubitVector vectors[8] ) const
00414 {
00415   vectors[0] = minimum_;
00416   vectors[1] = CubitVector (maximum_.x(), minimum_.y(), minimum_.z());
00417   vectors[2] = CubitVector (maximum_.x(), maximum_.y(), minimum_.z());
00418   vectors[3] = CubitVector (minimum_.x(), maximum_.y(), minimum_.z());
00419   
00420   vectors[4] = CubitVector (minimum_.x(), minimum_.y(), maximum_.z());
00421   vectors[5] = CubitVector (maximum_.x(), minimum_.y(), maximum_.z());
00422   vectors[6] = maximum_;
00423   vectors[7] = CubitVector (minimum_.x(), maximum_.y(), maximum_.z());
00424 }
00425 
00426 int CubitBox::operator&&(const CubitBox& box) const 
00427 {
00428     // Return false if there is no overlap
00429     // along at least one of the 3 axes.
00430   if (minimum_.x() > box.maximum_.x() ||
00431       maximum_.x() < box.minimum_.x() ||
00432       minimum_.y() > box.maximum_.y() ||
00433       maximum_.y() < box.minimum_.y() ||
00434       minimum_.z() > box.maximum_.z() ||
00435       maximum_.z() < box.minimum_.z() )
00436     return CUBIT_FALSE;
00437   
00438     // If you didn't return false...
00439   return CUBIT_TRUE;
00440 }
00441 
00442 int CubitBox::operator||(const CubitBox& box) const 
00443 {
00444     // Return false if there is no overlap
00445     // along at least one of the 3 axes.
00446   if (minimum_.x() >= box.maximum_.x() ||
00447       maximum_.x() <= box.minimum_.x() ||
00448       minimum_.y() >= box.maximum_.y() ||
00449       maximum_.y() <= box.minimum_.y() ||
00450       minimum_.z() >= box.maximum_.z() ||
00451       maximum_.z() <= box.minimum_.z() )
00452     return CUBIT_FALSE;
00453   
00454     // If you didn't return false...
00455   return CUBIT_TRUE;
00456 }
00457 
00458 int CubitBox::operator<=(const CubitVector& vect) const
00459 {
00460   return (vect.x() <= minimum_.x() ||
00461           vect.x() >= maximum_.x() ||
00462           vect.y() <= minimum_.y() ||
00463           vect.y() >= maximum_.y() ||
00464           vect.z() <= minimum_.z() ||
00465           vect.z() >= maximum_.z() );
00466 }
00467 
00468 /*
00469 Ray-axis Aligned box intersection by
00470 KAY, T. L., AND KAJIYA, J. T.
00471 In Computer Graphics (SIGGRAPH '86 Proceedings) (Aug. 1986), D. C. Evans and R. J. Athay, Eds., vol. 20, pp. 269-278. 
00472 
00473 Determines if there is an intersection between a ray and box but doesn't calculate the intersection.
00474 
00475 */
00476 bool CubitBox::intersect(const CubitVector& ray_origin, const CubitVector& ray_direction)
00477 {
00478     double tNear=CUBIT_DBL_MIN;
00479     double tFar=CUBIT_DBL_MAX;
00480 
00481     for(int i=0;i<3;i++)
00482     {
00483         //X plane
00484         if(fabs(ray_direction[i])<=CUBIT_DBL_MIN)
00485         {
00486             //Ray parallel to x plane
00487             if(ray_origin[i]<this->minimum_[i] || ray_origin[i]>this->maximum_[i])
00488             {
00489                 //Not between
00490                 return false;
00491             }
00492             else
00493             {
00494                 return true;
00495             }
00496         }
00497 
00498         double t1 = (this->minimum_[i] - ray_origin[i]) / ray_direction[i];
00499         double t2 = (this->maximum_[i] - ray_origin[i]) / ray_direction[i];
00500 
00501         if(t1>t2)
00502         {
00503             double temp=t1;
00504             t1=t2;
00505             t2=temp;
00506         }
00507         if(t1>tNear)
00508         {
00509             tNear=t1;
00510         }
00511 
00512         if(t2<tFar)
00513         {
00514             tFar=t2;
00515         }
00516 
00517         if(tNear>tFar)
00518         {
00519             return false;
00520         }
00521 
00522         if(tFar<0)
00523         {
00524             return false;
00525         }
00526 
00527     }
00528 
00529     return true;
00530 }
00531 
00532 /* 
00533 Fast Ray-Box Intersection
00534 by Andrew Woo
00535 from "Graphics Gems", Academic Press, 1990
00536 */
00537 
00538 #define NUMDIM  3
00539 #define RIGHT   0
00540 #define LEFT    1
00541 #define MIDDLE  2
00542 
00543 //char HitBoundingBox(minB,maxB, origin, dir,coord)
00544 //double minB[NUMDIM], maxB[NUMDIM];        /*box */
00545 //double origin[NUMDIM], dir[NUMDIM];       /*ray */
00546 //double coord[NUMDIM];             /* hit point */
00547 bool CubitBox::intersect
00548 (const CubitVector& ray_origin,
00549   const CubitVector& ray_direction,
00550   CubitVector& intersection_pt)
00551 {
00552   bool inside = true;
00553   int quadrant[NUMDIM];
00554   register int i;
00555   int whichPlane;
00556   double maxT[NUMDIM];
00557   double candidatePlane[NUMDIM];
00558 
00559   /* Find candidate planes; this loop can be avoided if
00560   rays cast all from the eye(assume perpsective view) */
00561   for (i=0; i<NUMDIM; i++)
00562   {
00563     if((ray_origin)[i] < (this->minimum())[i])
00564     {
00565       quadrant[i] = LEFT;
00566       candidatePlane[i] = (this->minimum())[i];
00567       inside = false;
00568     }
00569     else if ( (ray_origin)[i] > (this->maximum())[i])
00570     {
00571       quadrant[i] = RIGHT;
00572       candidatePlane[i] = (this->maximum())[i];
00573       inside = false;
00574     }
00575     else    
00576     {
00577       quadrant[i] = MIDDLE;
00578     }
00579   }
00580 
00581   /* Ray origin inside bounding box */
00582   if(inside)
00583   {
00584     intersection_pt = ray_origin;
00585     return true;
00586   }
00587 
00588   /* Calculate T distances to candidate planes */
00589   for (i = 0; i < NUMDIM; i++)
00590   {
00591     if (quadrant[i] != MIDDLE && (ray_direction)[i] !=0.)
00592       maxT[i] = ( candidatePlane[i]-(ray_origin)[i]) / ((ray_direction)[i]);
00593     else
00594       maxT[i] = -1.;
00595   }
00596 
00597   /* Get largest of the maxT's for final choice of intersection */
00598   whichPlane = 0;
00599   for (i = 1; i < NUMDIM; i++)
00600   {
00601     if (maxT[whichPlane] < maxT[i])
00602       whichPlane = i;
00603   }
00604 
00605   /* Check final candidate actually inside box */
00606   double intersection_coords[3];
00607 
00608   if (maxT[whichPlane] < 0.)
00609     return false;
00610 
00611   for (i = 0; i < NUMDIM; i++)
00612   {
00613     if (whichPlane != i)
00614     {
00615       intersection_coords[i] = (ray_origin)[i] + maxT[whichPlane] * (ray_direction)[i];
00616       if (intersection_coords[i] < (this->minimum())[i] ||
00617           intersection_coords[i] > (this->maximum())[i])
00618         return false;
00619     }
00620     else
00621     {
00622       intersection_coords[i] = candidatePlane[i];
00623     }
00624   }
00625 
00626   return true;  /* ray hits box */
00627 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines