cgma
|
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 }