00001
00012 #ifndef _H_CUBIC_BOUNDING_BOX
00013 #define _H_CUBIC_BOUNDING_BOX
00014
00015 #include "Bounding_Box.h"
00016 #include "randomUtils.h"
00017 #include "orderings.h"
00018
00019 #include <iterator>
00020 #include <vector>
00021 #include <sstream>
00022 #include <iostream>
00023 #include <fstream>
00024
00025
00026
00029
00030
00032 #define _SHELL_CODE
00033
00034 #define _SHELL_CODE_MOD
00035
00036
00037
00043 class Cubic_Bounding_Box : public Bounding_Box< Cubic_Bounding_Box > {
00044
00048 friend class CubicLowCoorOrdering< 0, Cubic_Bounding_Box >;
00049
00053 friend class CubicLowCoorOrdering< 1, Cubic_Bounding_Box >;
00054
00058 friend class CubicLowCoorOrdering< 2, Cubic_Bounding_Box >;
00059
00063 friend class DistOrdering< Cubic_Bounding_Box >;
00064
00065
00066 friend class Bisection_Tree;
00067 friend class Cart;
00068 friend class Basic_R_tree;
00069
00070 private:
00071
00079 bool contains( const vector< double > * x ) const {
00080
00081 if ( isEmpty() )
00082 return false;
00083
00084 #ifndef _HP
00085
00086 if ( _mins.size() != x->size() ) {
00087 cerr << "Warning: cannot check if a point with dimension not equal to bounding box dimension is contained within current bounding box!" << endl;
00088 return false;
00089 }
00090 #endif
00091
00092
00093 for ( unsigned int i=0; i<_mins.size(); i++ ) {
00094 double current = (*x)[i];
00095 if ( _maxs[i] < current )
00096 return false;
00097 if ( _mins[i] > current )
00098 return false;
00099 }
00100
00101
00102 return true;
00103 }
00104
00113 vector< double > axpy( const double a, const vector< double > * x, const vector< double > * y ) const {
00114 vector< double > ret;
00115 ret.resize( x->size() );
00116 for( unsigned int i=0; i<x->size(); i++ )
00117 ret[ i ] = a * (*x)[ i ] + (*y)[ i ];
00118 return ret;
00119 }
00120
00121 protected:
00122
00124 static vector<double> temp1;
00125
00127 static vector<double> temp2;
00128
00130 vector<double> _mins;
00131
00133 vector<double> _maxs;
00134
00135 #ifdef _SHELL_CODE
00136
00145 static double UtilDivideSafe( const double num, const double denom, const double defaultRes ) {
00146 return ( denom != 0.0 ? num / denom : defaultRes );
00147 }
00148
00150 static bool BBOverlap( const double *bb1Min, const double *bb1Max, const double *bb2Min, const double *bb2Max,
00151 const int dim ) {
00152 #ifndef _SHELL_CODE_MOD
00153 bool result = true;
00154 #endif
00155 int d;
00156
00157 if ( dim == 3 )
00158 {
00159 #ifndef _SHELL_CODE_MOD
00160 result = ( bb1Min[0] <= bb2Max[0] ) && ( bb1Max[0] >= bb2Min[0] ) && ( bb1Min[1] <= bb2Max[1] ) && ( bb1Max[1] >= bb2Min[1] ) && ( bb1Min[2] <= bb2Max[2] ) && ( bb1Max[2] >= bb2Min[2] );
00161 #else
00162 return ( bb1Min[0] <= bb2Max[0] ) && ( bb1Max[0] >= bb2Min[0] ) && ( bb1Min[1] <= bb2Max[1] ) && ( bb1Max[1] >= bb2Min[1] ) && ( bb1Min[2] <= bb2Max[2] ) && ( bb1Max[2] >= bb2Min[2] );
00163 #endif
00164 }
00165 else
00166 {
00167 #ifndef _SHELL_CODE_MOD
00168 for ( d = 0; ( d < dim ) && result; d++ )
00169 #else
00170 for ( d = 0; ( d < dim ); d++ )
00171 #endif
00172 {
00173 #ifndef _SHELL_CODE_MOD
00174 result = ( bb1Min[d] <= bb2Max[d] ) && ( bb1Max[d] >= bb2Min[d] );
00175 #else
00176 if ( ( bb1Min[d] > bb2Max[d] ) || ( bb1Max[d] < bb2Min[d] ) )
00177 return false;
00178 #endif
00179 }
00180 }
00181 #ifndef _SHELL_CODE_MOD
00182 return ( result );
00183 #else
00184 return true;
00185 #endif
00186 }
00187
00189 static bool BBEdgeIntersect( const int dim, const double *point1, const double *point2, const double *minBB,
00190 const double *maxBB, const int dir, const double fixed_val )
00191 {
00192 #ifndef _SHELL_CODE_MOD
00193 bool intersect = false;
00194 #endif
00195 const double cor = fixed_val;
00196 const double cor1 = point1[dir];
00197 const double cor2 = point2[dir];
00198
00199
00200
00201 #ifdef _SHELL_CODE_MOD
00202 if ( ( cor1 > cor ) && ( cor2 > cor ) )
00203 return false;
00204
00205 if ( ( cor1 < cor ) && (cor2 < cor ) )
00206 return false;
00207 #else
00208 if ( ( cor1 <= cor ) || ( cor2 <= cor ) )
00209 {
00210 if ( ( cor1 >= cor ) || ( cor2 >= cor ) )
00211 {
00212 #endif
00213 const double frac = UtilDivideSafe( cor - cor1, cor2 - cor1, 0.5 );
00214 int d;
00215
00216 #ifdef _ASSERTS_ON
00217 assert( ( frac >= 0. ) && ( frac <= 1. ) );
00218 #endif
00219
00220
00221 #ifdef _SHELL_CODE_MOD
00222 for ( d = 0; ( d < dim ); d++ )
00223 #else
00224 intersect = true;
00225 for ( d = 0; ( d < dim ) && intersect; d++ )
00226 #endif
00227 {
00228 if ( d != dir )
00229 {
00230 const double c = ( 1 - frac ) * point1[d] + ( frac ) * point2[d];
00231 #ifdef _SHELL_CODE_MOD
00232 if ( ( c < minBB[d] ) || ( c > maxBB[d] ) )
00233 return false;
00234 #else
00235 intersect = ( ( c >= minBB[d] ) && ( c <= maxBB[d] ) );
00236 #endif
00237 }
00238 #ifndef _SHELL_CODE_MOD
00239 }
00240 }
00241 #endif
00242 }
00243
00244 #ifdef _SHELL_CODE_MOD
00245 return true;
00246 #else
00247 return ( intersect );
00248 #endif
00249
00250 }
00251
00252 #else
00253
00263 bool edgeLineIntersect( const vector< double > &start, const vector< double > &end, const vector< double > &direction, const int &dim_fixed, const double &fixed_coordinate ) const {
00264
00265 if ( start[dim_fixed] > fixed_coordinate && end[dim_fixed] > fixed_coordinate )
00266 return false;
00267 if ( start[dim_fixed] < fixed_coordinate && end[dim_fixed] < fixed_coordinate )
00268 return false;
00269
00270 const double scale = ( fixed_coordinate - start[dim_fixed] ) / direction[dim_fixed];
00271
00272 #ifdef _DEBUG
00273 cout << "Fixing coordinate " << dim_fixed << endl;
00274 cout << "Scalemin is " << scale << endl;
00275 cout << "Scalemax is " << scale << endl;
00276 #endif
00277
00278
00279 for ( int d=0; d<dim_fixed; d++ ) {
00280 const double yo = scale * direction[d] + start[d];
00281
00282 if ( yo < _mins[d] || yo > _maxs[d] )
00283 return false;
00284 }
00285
00286
00287 for ( unsigned int d=dim_fixed+1; d<start.size(); d++ ) {
00288 const double yo = scale * direction[d] + start[d];
00289
00290 if ( yo < _mins[d] || yo > _maxs[d] )
00291 return false;
00292 }
00293
00294 return true;
00295
00296 }
00297
00305 bool infiniteLineIntersect( const vector< double > const * start, const vector< double > const * end ) const {
00306
00307
00308
00309
00310
00311
00312
00313 #ifdef _DEBUG
00314 cout << "MBR " << toString() << endl;
00315 cout << "Intersecting with line < ";
00316 for( unsigned int i=0; i<start->size(); i++ )
00317 cout << (*start)[ i ] << " ";
00318 cout << "to < ";
00319 for( unsigned int i=0; i<start->size(); i++ )
00320 cout << (*end)[ i ] << " ";
00321 cout << endl;
00322 cout << "Direction vector: < ";
00323 #endif
00324
00325
00326 vector< double > direction;
00327 for( unsigned int i=0; i<start->size(); i++ ) {
00328 direction.push_back( (*end)[ i ] - (*start)[ i ] );
00329
00330 #ifdef _DEBUG
00331 cout << direction[ i ] << " ";
00332 #endif
00333
00334
00335 if ( direction[ i ] == 0 )
00336 if ( (*start)[ i ] < _mins[ i ] || (*start)[ i ] > _maxs[ i ] )
00337 return false;
00338 }
00339
00340 #ifdef _DEBUG
00341 cout << endl;
00342 cout << "No contradiction found." << endl;
00343 #endif
00344
00345
00346 for( unsigned int i=0; i<start->size(); i++ ) {
00347
00348 if ( edgeLineIntersect( *start, *end, direction, i, _mins[ i ] ) )
00349 return true;
00350 if ( edgeLineIntersect( *start, *end, direction, i, _maxs[ i ] ) )
00351 return true;
00352
00353 }
00354
00355 return false;
00356 }
00357 #endif
00358
00359 public:
00360
00362 static CubicLowCoorOrdering< 0, Cubic_Bounding_Box > LCX_ORDERING;
00363
00365 static CubicLowCoorOrdering< 1, Cubic_Bounding_Box > LCY_ORDERING;
00366
00368 static CubicLowCoorOrdering< 2, Cubic_Bounding_Box > LCZ_ORDERING;
00369
00371 static DistOrdering< Cubic_Bounding_Box > DIST_ORDERING;
00372
00374 Cubic_Bounding_Box() {
00375 clear();
00376 }
00377
00386 virtual void writeToFile( ofstream &ofs ) const {
00387
00388 ofs << "-1 ";
00389 ofs << (_mins[0]) << " " << (_mins[1]) << " " << (_mins[2]) << " ";
00390 ofs << (_maxs[0]) << " " << (_maxs[1]) << " " << (_maxs[2]) << endl;
00391
00392 }
00393
00401 virtual bool lineIntersect( const vector< double > &start, const vector< double > &end ) const {
00402
00403 #ifdef _SHELL_CODE
00404 bool intersect = false;
00405
00406 const unsigned int dim = start.size();
00407
00408 unsigned int d;
00409
00410
00411 if ( !intersect )
00412 {
00413
00414 intersect = BBOverlap( &(start)[ 0 ], &(start)[ 0 ], &_mins[ 0 ], &_maxs[ 0 ], dim );
00415 }
00416
00417 if ( !intersect )
00418 {
00419 intersect = BBOverlap( &(end)[ 0 ], &(end)[ 0 ], &_mins[ 0 ], &_maxs[ 0 ], dim );
00420 }
00421
00422
00423 for ( d = 0; ( d < dim ) && !intersect; d++ )
00424 {
00425
00426
00427
00428 intersect = BBEdgeIntersect( dim, &(start)[ 0 ], &(end)[ 0 ], &_mins[ 0 ], &_maxs[ 0 ], d, _maxs[ d ] );
00429
00430 }
00431
00432
00433 for ( d = 0; ( d < dim ) && !intersect; d++ )
00434 {
00435
00436
00437
00438 intersect = BBEdgeIntersect( dim, &(start)[ 0 ], &(end)[ 0 ], &_mins[ 0 ], &_maxs[ 0 ], d, _mins[ d ] );
00439
00440 }
00441
00442 return ( intersect );
00443 #else
00444
00445 if ( contains( Point( start ) ) || contains( Point( end ) ) )
00446 return true;
00447
00448 for( unsigned int i=0; i<start->size(); i++ ) {
00449
00450
00451 if ( (*start)[ i ] < (*end)[ i ] ) {
00452 if ( (*end)[ i ] < _mins[i] || (*start)[ i ] > _maxs[i] )
00453 return false;
00454 } else {
00455 if ( (*start)[ i ] < _mins[i] || (*end)[ i ] > _maxs[i] )
00456 return false;
00457 }
00458
00459 }
00460
00461
00462 return infiniteLineIntersect( start, end );
00463 #endif
00464
00465 }
00466
00474 Cubic_Bounding_Box( vector<double> &mins, vector<double> &maxs ) {
00475
00476 #ifndef _HP
00477
00478 if ( mins.size() != maxs.size() ) {
00479 cerr << "Dimension mis-match in Cubic_Bounding_Box constructor!" << endl;
00480 exit(1);
00481 }
00482 #endif
00483
00484
00485 _mins = mins; _maxs = maxs;
00486 }
00487
00495 Cubic_Bounding_Box( const vector<double> &mins, const vector<double> &maxs ) {
00496
00497 #ifndef _HP
00498
00499 if ( mins.size() != maxs.size() ) {
00500 cerr << "Dimension mis-match in Cubic_Bounding_Box constructor!" << endl;
00501 exit(1);
00502 }
00503 #endif
00504
00505
00506 _mins = mins; _maxs = maxs;
00507 }
00508
00512 ~Cubic_Bounding_Box() {}
00513
00514
00521 Cubic_Bounding_Box( const Cubic_Bounding_Box *toCopy ) {
00522 become( toCopy );
00523 }
00524
00528 virtual void clear() {
00529 _mins.resize( 1 ); _maxs.resize( 1 );
00530 _mins[ 0 ]=0; _maxs[ 0 ]=0;
00531 }
00532
00538 virtual void become( const Cubic_Bounding_Box *toCopy ) {
00539 #ifdef _DEBUG
00540 cout << "Becoming: "; fflush( stdout );
00541 cout << toCopy->toString() << endl; fflush( stdout );
00542 cout << "Dimension check... " << endl; fflush( stdout );
00543 #endif
00544
00545 #ifndef _HP
00546
00547 if ( toCopy->_mins.size() != toCopy->_maxs.size() ) {
00548 cerr << "Dimension mismatch in Cubic_Bounding_Box constructor!" << endl;
00549 exit(1);
00550 }
00551 #endif
00552
00553 #ifdef _DEBUG
00554 cout << "Setting variables..." << endl; fflush( stdout );
00555 #endif
00556
00557
00558 _mins = toCopy->_mins; _maxs = toCopy->_maxs;
00559
00560 #ifdef _DEBUG
00561 cout << "Become successful" << endl; fflush( stdout );
00562 #endif
00563
00564 }
00565
00572 double getMinCoordinateOnDimension( unsigned int i ) const { return _mins[ i ]; }
00573
00580 double getMaxCoordinateOnDimension( unsigned int i ) const { return _maxs[ i ]; }
00581
00587 virtual bool isEmpty() const {
00588 return ( _mins.size()==1 && _mins[0]==0 && _maxs[0]==0 );
00589 }
00590
00600 virtual void getCenterCoordinate( vector< double > * into ) const {
00601
00602
00603 into->resize( _mins.size() );
00604 for( unsigned int i=0; i<_mins.size(); i++ )
00605 (*into)[ i ] = ( _mins[i] + _maxs[i] ) / 2;
00606
00607
00608
00609 }
00610
00618 virtual bool intersects( const Cubic_Bounding_Box &other ) const {
00619 if ( isEmpty() || other.isEmpty() )
00620 return false;
00621
00622 #ifndef _SHELL_CODE
00623
00624 #ifndef _HP
00625
00626 if ( _mins.size() != other._mins.size() ) {
00627 cerr << "Warning: cannot compare two bounding boxes of different dimensions!" << endl;
00628 return false;
00629 }
00630 #endif
00631
00632
00633 for ( int i=0; i<_mins.size(); i++ ) {
00634 if ( _maxs[i] < other._mins[i] )
00635 return false;
00636 if ( other._maxs[i] < _mins[i] )
00637 return false;
00638 }
00639
00640
00641 return true;
00642 #else
00643 return BBOverlap( &_mins[0], &_maxs[0], &(other._mins[0]), &(other._maxs[0]), _mins.size() );
00644 #endif
00645 }
00646
00647
00655 virtual bool contains( const Point &x ) const {
00656
00657 if ( isEmpty() )
00658 return false;
00659
00660
00661 if ( _mins.size() != x.getDimension() ) {
00662 cerr << "Warning: cannot check if a point with dimension not equal to bounding box dimension is contained within current bounding box!" << endl;
00663 return false;
00664 }
00665
00666
00667 for ( unsigned int i=0; i<_mins.size(); i++ ) {
00668 double current = x.getCoordinate(i);
00669 if ( _maxs[i] < current )
00670 return false;
00671 if ( _mins[i] > current )
00672 return false;
00673 }
00674
00675
00676 return true;
00677 }
00678
00685 virtual bool contains( const Cubic_Bounding_Box &other ) const {
00686 return ( contains( &( other._mins ) ) && contains( &( other._maxs ) ) );
00687 }
00688
00690 virtual void unite( const Cubic_Bounding_Box* other ) {
00691 if ( other->isEmpty() )
00692 return;
00693
00694 if ( isEmpty() )
00695 become( other );
00696
00697 #ifndef _HP
00698
00699 if ( _mins.size() != other->_mins.size() ) {
00700 cerr << "Error: Dimension mismatch in Cubic_Bounding_Box::unite() !" << endl;
00701 exit(1);
00702 }
00703 #endif
00704
00705
00706 for ( unsigned int i=0; i<_mins.size(); i++ ) {
00707 if ( _mins[ i ] > other->_mins[ i ] )
00708 _mins[ i ] = other->_mins[ i ];
00709 if ( _maxs[ i ] < other->_maxs[ i ] )
00710 _maxs[ i ] = other->_maxs[ i ];
00711 }
00712 }
00713
00720 virtual Cubic_Bounding_Box unionWith( const Cubic_Bounding_Box &other ) const {
00721 #ifdef _DEBUG
00722 cout << "Unite called" << endl; fflush( stdout );
00723 #endif
00724
00725 if ( isEmpty() && other.isEmpty() )
00726 return Cubic_Bounding_Box();
00727
00728 if ( isEmpty() )
00729 return Cubic_Bounding_Box( other._mins, other._maxs );
00730
00731 if ( other.isEmpty() )
00732 return Cubic_Bounding_Box( _mins, _maxs );
00733
00734 #ifndef _HP
00735
00736 if ( _mins.size() != other._mins.size() ) {
00737 cerr << "Error: Dimension mismatch in Cubic_Bounding_Box::unite() !" << endl;
00738 exit(1);
00739 }
00740 #endif
00741
00742 temp1.resize( _mins.size() ); temp2.resize( _mins.size() );
00743
00744
00745 for ( unsigned int i=0; i<_mins.size(); i++ ) {
00746 if ( _mins[i] < other._mins[i] )
00747 temp1[i] = _mins[i];
00748 else
00749 temp1[i] = other._mins[i];
00750 if ( _maxs[i] > other._maxs[i] )
00751 temp2[i] = _maxs[i];
00752 else
00753 temp2[i] = other._maxs[i];
00754 }
00755
00756 return Cubic_Bounding_Box( temp1, temp2 );
00757 }
00758
00765 virtual Cubic_Bounding_Box intersect( const Cubic_Bounding_Box &other ) const {
00766
00767 #ifdef _DEBUG
00768 cout << "THIS: " << endl << toString();
00769 cout << "THAT: " << endl << other.toString();
00770 #endif
00771
00772 if ( isEmpty() || other.isEmpty() ) {
00773 return Cubic_Bounding_Box();
00774 }
00775
00776 #ifndef _HP
00777
00778 if ( _mins.size() != other._mins.size() ) {
00779 cerr << "Error: Dimension mismatch in Cubic_Bounding_Box::unite() !" << endl;
00780 exit(1);
00781 }
00782 #endif
00783
00784 temp1.resize( _mins.size() ); temp2.resize( _mins.size() );
00785
00786
00787 for ( unsigned int i=0; i<_mins.size(); i++ ) {
00788 if ( ( other._maxs[i] < _mins[i] ) || ( other._mins[i] > _maxs[i] ) ) {
00789 temp1[i] = 1; temp2[i] = 0;
00790 } else {
00791
00792 if ( _mins[i] > other._mins[i] )
00793 temp1[i] = _mins[i];
00794 else
00795 temp1[i] = other._mins[i];
00796
00797 if ( _maxs[i] < other._maxs[i] )
00798 temp2[i] = _maxs[i];
00799 else
00800 temp2[i] = other._maxs[i];
00801 }
00802 }
00803
00804 #ifdef _DEBUG
00805 Cubic_Bounding_Box ret( Cubic_Bounding_Box( temp1, temp2 ) );
00806 cout << "RET : " << endl << ret.toString();
00807 return ret;
00808 #else
00809 return Cubic_Bounding_Box( temp1, temp2 );
00810 #endif
00811
00812 }
00813
00819 static Ordering< Cubic_Bounding_Box > * getDefaultOrdering();
00820
00827 static vector< Ordering< Cubic_Bounding_Box > * > getOrderings();
00828
00834 virtual string toString() const {
00835
00836 ostringstream os;
00837 os << _mins.size() << ": ";
00838 for ( unsigned int i=0; i<_mins.size(); i++ )
00839 os << "< " << _mins[i] << " , " << _maxs[i] << " >" << endl;
00840 return os.str();
00841 }
00842
00848 virtual unsigned int getDimension() const {
00849 return _mins.size();
00850 }
00851
00859 virtual bool isDefining( Cubic_Bounding_Box * other ) const {
00860 bool ret = _mins[ 0 ] < other->_mins[ 0 ];
00861 ret = ret && ( _maxs[ 0 ] > other->_maxs[ 0 ] );
00862 for ( unsigned int i=1; ( i<_mins.size() ) && ret; i++ ) {
00863 ret = ret && ( _mins[ i ] < other->_mins[ i ] );
00864 ret = ret && ( _maxs[ i ] > other->_maxs[ i ] );
00865 }
00866 return !ret;
00867 }
00868
00869 };
00870
00871
00872
00873
00874
00875
00876
00880 ostream& operator<<( ostream &os, const Cubic_Bounding_Box box );
00881
00885 Cubic_Bounding_Box operator&&( const Cubic_Bounding_Box left, const Cubic_Bounding_Box right );
00886
00890 Cubic_Bounding_Box operator||( const Cubic_Bounding_Box left, const Cubic_Bounding_Box right );
00891
00892 #endif