00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00043 #ifndef TREE_BOUNDS_H
00044 #define TREE_BOUNDS_H
00045
00046 #include "fastlib/la/matrix.h"
00047 #include "fastlib/la/la.h"
00048
00049 #include "fastlib/math/math_lib.h"
00050
00056 template<int t_pow = 2>
00057 class DHrectBound {
00058 public:
00059 static const int PREFERRED_POWER = t_pow;
00060
00061 private:
00062 DRange *bounds_;
00063 index_t dim_;
00064
00065 OBJECT_TRAVERSAL(DHrectBound) {
00066 OT_OBJ(dim_);
00067 OT_ALLOC(bounds_, dim_);
00068 };
00069
00070 public:
00075 void Init(index_t dimension) {
00076
00077 bounds_ = mem::Alloc<DRange>(dimension);
00078
00079 dim_ = dimension;
00080 Reset();
00081 }
00082
00090 void AverageBoxesInit(const DHrectBound& box1, const DHrectBound& box2) {
00091
00092 index_t dim = box1.dim();
00093 DEBUG_ASSERT(dim == box2.dim());
00094
00095 Init(dim);
00096
00097 for (index_t i = 0; i < dim; i++) {
00098
00099 DRange range;
00100 range = box1.get(i) + box2.get(i);
00101 range *= 0.5;
00102 bounds_[i] = range;
00103
00104 }
00105
00106 }
00107
00111 void Reset() {
00112 for (index_t i = 0; i < dim_; i++) {
00113 bounds_[i].InitEmptySet();
00114 }
00115 }
00116
00120 bool Contains(const Vector& point) const {
00121 for (index_t i = 0; i < point.length(); i++) {
00122 if (!bounds_[i].Contains(point[i])) {
00123 return false;
00124 }
00125 }
00126
00127 return true;
00128 }
00129
00130 bool Contains(const Vector& point, const Vector& box) const {
00131 const DRange *a = this->bounds_;
00132 for (index_t i = 0; i < point.length(); i++){
00133 if (a[i].hi > a[i].lo){
00134 if (!bounds_[i].Contains(point[i])){
00135 return false;
00136 }
00137 } else if(point[i] > a[i].hi & point[i] < a[i].lo){
00138 return false;
00139 }
00140 }
00141 return true;
00142 }
00143
00144
00146 index_t dim() const {
00147 return dim_;
00148 }
00149
00153 const DRange& get(index_t i) const {
00154 DEBUG_BOUNDS(i, dim_);
00155 return bounds_[i];
00156 }
00157
00161 double CalculateMaxDistanceSq() const {
00162 double max_distance=0;
00163 for (index_t i = 0; i < dim_; i++) {
00164 max_distance+=math::Sqr(bounds_[i].width());
00165 }
00166 return max_distance;
00167 }
00168
00170 void CalculateMidpoint(Vector *centroid) const {
00171 centroid->Init(dim_);
00172 for (index_t i = 0; i < dim_; i++) {
00173 (*centroid)[i] = bounds_[i].mid();
00174 }
00175 }
00177 void CalculateMidpointOverwrite(Vector *centroid) const {
00178 for (index_t i = 0; i < dim_; i++) {
00179 (*centroid)[i] = bounds_[i].mid();
00180 }
00181 }
00182
00183
00187 double MinDistanceSq(const double *mpoint) const {
00188 double sum = 0;
00189 const DRange *mbound = bounds_;
00190
00191 index_t d = dim_;
00192
00193 do {
00194 double v = *mpoint;
00195 double v1 = mbound->lo - v;
00196 double v2 = v - mbound->hi;
00197
00198 v = (v1 + fabs(v1)) + (v2 + fabs(v2));
00199
00200 mbound++;
00201 mpoint++;
00202
00203 sum += math::Pow<t_pow, 1>(v);
00204 } while (--d);
00205
00206 return math::Pow<2, t_pow>(sum) / 4;
00207 }
00208
00213 double MinDistanceSq(const DHrectBound& other, const Vector& offset) const {
00214 double sum = 0;
00215 const DRange *a = this->bounds_;
00216 const DRange *b = other.bounds_;
00217 index_t mdim = dim_;
00218
00219 DEBUG_SAME_SIZE(dim_, other.dim_);
00220
00221
00222 for (index_t d = 0; d < mdim; d++) {
00223 double v1 = b[d].lo - offset[d] - a[d].hi;
00224 double v2 = a[d].lo + offset[d] - b[d].lo;
00225
00226 double v = (v1 + fabs(v1)) + (v2 + fabs(v2));
00227
00228 sum += math::Pow<t_pow, 1>(v);
00229 }
00230
00231 return math::Pow<2, t_pow>(sum) / 4;
00232 }
00233
00237 double MinDistanceSq(const Vector& point) const {
00238 DEBUG_SAME_SIZE(point.length(), dim_);
00239 return MinDistanceSq(point.ptr());
00240 }
00241
00247 double MinDistanceSq(const DHrectBound& other) const {
00248 double sum = 0;
00249 const DRange *a = this->bounds_;
00250 const DRange *b = other.bounds_;
00251 index_t mdim = dim_;
00252
00253 DEBUG_SAME_SIZE(dim_, other.dim_);
00254
00255 for (index_t d = 0; d < mdim; d++) {
00256 double v1 = b[d].lo - a[d].hi;
00257 double v2 = a[d].lo - b[d].hi;
00258
00259
00260
00261 double v = (v1 + fabs(v1)) + (v2 + fabs(v2));
00262
00263 sum += math::Pow<t_pow, 1>(v);
00264 }
00265
00266 return math::Pow<2, t_pow>(sum) / 4;
00267 }
00268
00269
00273 double MaxDistanceSq(const Vector& point) const {
00274 double sum = 0;
00275
00276 DEBUG_SAME_SIZE(point.length(), dim_);
00277
00278 for (index_t d = 0; d < dim_; d++) {
00279 double v = std::max(point[d] - bounds_[d].lo, bounds_[d].hi - point[d]);
00280 sum += math::Pow<t_pow, 1>(v);
00281 }
00282
00283 return math::Pow<2, t_pow>(sum);
00284 }
00285
00289 double MaxDistanceSq(const double *point) const {
00290 double sum = 0;
00291
00292 for (index_t d = 0; d < dim_; d++) {
00293 double v = std::max(point[d] - bounds_[d].lo, bounds_[d].hi - point[d]);
00294 sum += math::Pow<t_pow, 1>(v);
00295 }
00296
00297 return math::Pow<2, t_pow>(sum);
00298 }
00299
00303 double MaxDistanceSq(const DHrectBound& other) const {
00304 double sum = 0;
00305 const DRange *a = this->bounds_;
00306 const DRange *b = other.bounds_;
00307
00308 DEBUG_SAME_SIZE(dim_, other.dim_);
00309
00310 for (index_t d = 0; d < dim_; d++) {
00311 double v = std::max(b[d].hi - a[d].lo, a[d].hi - b[d].lo);
00312 sum += math::PowAbs<t_pow, 1>(v);
00313 }
00314
00315 return math::Pow<2, t_pow>(sum);
00316 }
00317
00321 double MaxDistanceSq(const DHrectBound& other, const Vector& offset) const {
00322 double sum = 0;
00323 const DRange *a = this->bounds_;
00324 const DRange *b = other.bounds_;
00325
00326 DEBUG_SAME_SIZE(dim_, other.dim_);
00327
00328 for (index_t d = 0; d < dim_; d++) {
00329 double v = std::max(b[d].hi + offset[d] - a[d].lo,
00330 a[d].hi - offset[d] - b[d].lo);
00331 sum += math::PowAbs<t_pow, 1>(v);
00332 }
00333
00334 return math::Pow<2, t_pow>(sum);
00335 }
00336
00341 double PeriodicMinDistanceSq(const DHrectBound& other, const Vector& box_size)
00342 const {
00343 double sum = 0;
00344 const DRange *a = this->bounds_;
00345 const DRange *b = other.bounds_;
00346
00347 DEBUG_SAME_SIZE(dim_, other.dim_);
00348
00349 for (index_t d = 0; d < dim_; d++){
00350 double v = 0, d1, d2, d3;
00351 d1 = (a[d].hi > a[d].lo | b[d].hi > b[d].lo)*
00352 min(b[d].lo - a[d].hi, a[d].lo-b[d].hi);
00353 d2 = (a[d].hi > a[d].lo & b[d].hi > b[d].lo)*
00354 min(b[d].lo - a[d].hi, a[d].lo-b[d].hi + box_size[d]);
00355 d3 = (a[d].hi > a[d].lo & b[d].hi > b[d].lo)*
00356 min(b[d].lo - a[d].hi + box_size[d], a[d].lo-b[d].hi);
00357 v = (d1 + fabs(d1)) + (d2+ fabs(d2)) + (d3 + fabs(d3));
00358 sum += math::Pow<t_pow, 1>(v);
00359 }
00360 return math::Pow<2, t_pow>(sum) / 4;
00361 }
00362
00363
00364
00365 double PeriodicMinDistanceSq(const Vector& point, const Vector& box_size)
00366 const {
00367 double sum = 0;
00368 const DRange *b = this->bounds_;
00369
00370 for (index_t d = 0; d < dim_; d++){
00371 double a = point[d];
00372 double v = 0, bh;
00373 bh = b[d].hi-b[d].lo;
00374 bh = bh - floor(bh / box_size[d])*box_size[d];
00375 a = a - b[d].lo;
00376 a = a - floor(a / box_size[d])*box_size[d];
00377 if (bh > a){
00378 v = min(a - bh, box_size[d]-a);
00379 }
00380 sum += math::Pow<t_pow, 1>(v);
00381 }
00382
00383 return math::Pow<2, t_pow>(sum);
00384 }
00385
00386
00387
00388
00393 double PeriodicMaxDistanceSq(const DHrectBound& other, const Vector& box_size)
00394 const {
00395 double sum = 0;
00396 const DRange *a = this->bounds_;
00397 const DRange *b = other.bounds_;
00398
00399 DEBUG_SAME_SIZE(dim_, other.dim_);
00400
00401 for (index_t d = 0; d < dim_; d++){
00402 double v = box_size[d] / 2.0;
00403 double dh, dl;
00404 dh = a[d].hi - b[d].lo;
00405 dh = dh - floor(dh / box_size[d])*box_size[d];
00406 dl = b[d].hi - a[d].lo;
00407 dl = dl - floor(dl / box_size[d])*box_size[d];
00408 v = max(min(dh,v), min(dl, v));
00409
00410 sum += math::PowAbs<t_pow, 1>(v);
00411 }
00412 return math::Pow<2, t_pow>(sum);
00413 }
00414
00415
00416 double PeriodicMaxDistanceSq(const Vector& point, const Vector& box_size)
00417 const {
00418 double sum = 0;
00419 const DRange *a = this->bounds_;
00420 for (index_t d = 0; d < dim_; d++){
00421 double b = point[d];
00422 double v = box_size[d] / 2.0;
00423 double ah, al;
00424 ah = a[d].hi - b;
00425 ah = ah - floor(ah / box_size[d])*box_size[d];
00426 if (ah < v){
00427 v = ah;
00428 } else {
00429 al = a[d].lo - b;
00430 al = al - floor(al / box_size[d])*box_size[d];
00431 if (al > v){
00432 v = 2*v-al;
00433 }
00434 }
00435 sum += math::PowAbs<t_pow, 1>(v);
00436 }
00437 return math::Pow<2, t_pow>(sum);
00438 }
00439
00440
00441 double MaxDelta(const DHrectBound& other, double box_width, int dim)
00442 const{
00443 const DRange *a = this->bounds_;
00444 const DRange *b = other.bounds_;
00445 double result = 0.5*box_width;
00446 double temp = b[dim].hi - a[dim].lo;
00447 temp = temp - floor(temp / box_width)*box_width;
00448 if (temp > box_width / 2){
00449 temp = b[dim].lo - a[dim].hi;
00450 temp = temp - floor(temp / box_width)*box_width;
00451 if (temp > box_width / 2){
00452 result = b[dim].hi - a[dim].lo;
00453 result = result - floor(temp / box_width + 1)*box_width;
00454 }
00455 } else {
00456 result = temp;
00457 }
00458 return result;
00459 }
00460
00461 double MinDelta(const DHrectBound& other, double box_width, int dim)
00462 const{
00463 const DRange *a = this->bounds_;
00464 const DRange *b = other.bounds_;
00465 double result = -0.5*box_width;
00466 double temp = b[dim].hi - a[dim].lo;
00467 temp = temp - floor(temp/ box_width)*box_width;
00468 if (temp > box_width / 2){
00469 temp = b[dim].hi - a[dim].hi;
00470 temp = temp - floor(temp / box_width)*box_width;
00471 if (temp > box_width / 2){
00472 result = temp - box_width;
00473 }
00474 } else {
00475 temp = b[dim].hi - a[dim].hi;
00476 result = temp - floor(temp / box_width)*box_width;
00477 }
00478 return result;
00479 }
00480
00481
00482
00486 DRange RangeDistanceSq(const DHrectBound& other) const {
00487 double sum_lo = 0;
00488 double sum_hi = 0;
00489 const DRange *a = this->bounds_;
00490 const DRange *b = other.bounds_;
00491 index_t mdim = dim_;
00492
00493 DEBUG_SAME_SIZE(dim_, other.dim_);
00494
00495 for (index_t d = 0; d < mdim; d++) {
00496 double v1 = b[d].lo - a[d].hi;
00497 double v2 = a[d].lo - b[d].hi;
00498
00499
00500
00501 double v_lo = (v1 + fabs(v1)) + (v2 + fabs(v2));
00502 double v_hi = -std::min(v1, v2);
00503
00504 sum_lo += math::Pow<t_pow, 1>(v_lo);
00505 sum_hi += math::Pow<t_pow, 1>(v_hi);
00506 }
00507
00508 return DRange(math::Pow<2, t_pow>(sum_lo) / 4,
00509 math::Pow<2, t_pow>(sum_hi));
00510 }
00511
00515 DRange RangeDistanceSq(const Vector& point) const {
00516 double sum_lo = 0;
00517 double sum_hi = 0;
00518 const double *mpoint = point.ptr();
00519 const DRange *mbound = bounds_;
00520
00521 DEBUG_SAME_SIZE(point.length(), dim_);
00522
00523 index_t d = dim_;
00524 do {
00525 double v = *mpoint;
00526 double v1 = mbound->lo - v;
00527 double v2 = v - mbound->hi;
00528
00529 sum_lo += math::Pow<t_pow, 1>((v1 + fabs(v1)) + (v2 + fabs(v2)));
00530 sum_hi += math::Pow<t_pow, 1>(-std::min(v1, v2));
00531
00532 mpoint++;
00533 mbound++;
00534 } while (--d);
00535
00536 return DRange(math::Pow<2, t_pow>(sum_lo) / 4,
00537 math::Pow<2, t_pow>(sum_hi));
00538 }
00539
00551 double MinToMidSq(const DHrectBound& other) const {
00552 double sum = 0;
00553 const DRange *a = this->bounds_;
00554 const DRange *b = other.bounds_;
00555
00556 DEBUG_SAME_SIZE(dim_, other.dim_);
00557
00558 for (index_t d = 0; d < dim_; d++) {
00559 double v = b->mid();
00560 double v1 = a->lo - v;
00561 double v2 = v - a->hi;
00562
00563 v = (v1 + fabs(v1)) + (v2 + fabs(v2));
00564
00565 a++;
00566 b++;
00567
00568 sum += math::Pow<t_pow, 1>(v);
00569 }
00570
00571 return math::Pow<2, t_pow>(sum) / 4;
00572 }
00573
00577 double MinimaxDistanceSq(const DHrectBound& other) const {
00578 double sum = 0;
00579 const DRange *a = this->bounds_;
00580 const DRange *b = other.bounds_;
00581 index_t mdim = dim_;
00582
00583 DEBUG_SAME_SIZE(dim_, other.dim_);
00584
00585 for (index_t d = 0; d < mdim; d++) {
00586 double v1 = b[d].hi - a[d].hi;
00587 double v2 = a[d].lo - b[d].lo;
00588 double v = std::max(v1, v2);
00589 v = (v + fabs(v));
00590 sum += math::Pow<t_pow, 1>(v);
00591 }
00592
00593 return math::Pow<2, t_pow>(sum) / 4;
00594 }
00595
00599 double MidDistanceSq(const DHrectBound& other) const {
00600 double sum = 0;
00601 const DRange *a = this->bounds_;
00602 const DRange *b = other.bounds_;
00603
00604 DEBUG_SAME_SIZE(dim_, other.dim_);
00605
00606 for (index_t d = 0; d < dim_; d++) {
00607 sum += math::PowAbs<t_pow, 1>(a[d].hi + a[d].lo - b[d].hi - b[d].lo);
00608 }
00609
00610 return math::Pow<2, t_pow>(sum) / 4;
00611 }
00612
00616 DHrectBound& operator |= (const Vector& vector) {
00617 DEBUG_SAME_SIZE(vector.length(), dim_);
00618
00619 for (index_t i = 0; i < dim_; i++) {
00620 bounds_[i] |= vector[i];
00621 }
00622
00623 return *this;
00624 }
00625
00629 DHrectBound& operator |= (const DHrectBound& other) {
00630 DEBUG_SAME_SIZE(other.dim_, dim_);
00631
00632 for (index_t i = 0; i < dim_; i++) {
00633 bounds_[i] |= other.bounds_[i];
00634 }
00635
00636 return *this;
00637 }
00638
00639
00644 DHrectBound& Add(const Vector& other, const Vector& size){
00645 DEBUG_SAME_SIZE(other.length(), dim_);
00646
00647 if (bounds_[0].hi < 0){
00648 for (index_t i = 0; i < dim_; i++){
00649 bounds_[i] |= other[i];
00650 }
00651 }
00652
00653 for (index_t i= 0; i < dim_; i++){
00654 double ah, al;
00655 ah = bounds_[i].hi - other[i];
00656 al = bounds_[i].lo - other[i];
00657 ah = ah - floor(ah / size[i])*size[i];
00658 al = al - floor(al / size[i])*size[i];
00659 if (ah < al){
00660 if (size[i] - ah < al){
00661 bounds_[i].hi = other[i];
00662 } else {
00663 bounds_[i].lo = other[i];
00664 }
00665 }
00666 }
00667 return *this;
00668 }
00669
00670
00674 DHrectBound& Add(const DHrectBound& other, const Vector& size){
00675 if (bounds_[0].hi < 0){
00676 for (index_t i = 0; i < dim_; i++){
00677 bounds_[i] |= other.bounds_[i];
00678 }
00679 }
00680
00681 for (index_t i = 0; i < dim_; i++) {
00682 double ah, al, bh, bl;
00683 ah = bounds_[i].hi;
00684 al = bounds_[i].lo;
00685 bh = other.bounds_[i].hi;
00686 bl = other.bounds_[i].lo;
00687 ah = ah - al;
00688 bh = bh - al;
00689 bl = bl - al;
00690 ah = ah - floor(ah / size[i])*size[i];
00691 bh = bh - floor(bh / size[i])*size[i];
00692 bl = bl - floor(bl / size[i])*size[i];
00693
00694 if (((bh > ah) & (bh < bl | ah > bl )) ||
00695 (bh >= bl & bl > ah & bh < ah -bl + size[i])){
00696 bounds_[i].hi = other.bounds_[i].hi;
00697 }
00698
00699 if (bl > ah && ((bl > bh) || (bh >= ah -bl + size[i]))){
00700 bounds_[i].lo = other.bounds_[i].lo;
00701 }
00702
00703 if (unlikely(ah > bl & bl > bh)){
00704 bounds_[i].lo = 0;
00705 bounds_[i].hi = size[i];
00706 }
00707
00708
00709 }
00710 return *this;
00711 }
00712
00713
00714
00715 };
00716
00723 template<int t_pow>
00724 class LMetric {
00725 public:
00729 static double Distance(const Vector& a, const Vector& b) {
00730 return math::Pow<1, t_pow>(
00731 la::RawLMetric<t_pow>(a.length(), a.ptr(), b.ptr()));
00732 }
00733
00741 template<int t_result_pow>
00742 static double PowDistance(const Vector& a, const Vector& b) {
00743 return math::Pow<t_result_pow, t_pow>(
00744 la::RawLMetric<t_pow>(a.length(), a.ptr(), b.ptr()));
00745 }
00746 };
00747
00756 template<typename TMetric = LMetric<2>, typename TPoint = Vector>
00757 class DBallBound {
00758 public:
00759 typedef TPoint Point;
00760 typedef TMetric Metric;
00761
00762 private:
00763 double radius_;
00764 TPoint center_;
00765
00766 OBJECT_TRAVERSAL(DBallBound) {
00767 OT_OBJ(radius_);
00768 OT_OBJ(center_);
00769 }
00770
00771 public:
00772 double radius() const {
00773 return radius_;
00774 }
00775
00776 void set_radius(double d) {
00777 radius_ = d;
00778 }
00779
00780 const TPoint& center() const {
00781 return center_;
00782 }
00783
00784 TPoint& center() {
00785 return center_;
00786 }
00787
00791 bool Contains(const Point& point) const {
00792 return MidDistance(point) <= radius_;
00793 }
00794
00802 void CalculateMidpoint(Point *centroid) const {
00803 ot::InitCopy(centroid, center_);
00804 }
00805
00809 double MinDistance(const Point& point) const {
00810 return math::ClampNonNegative(MidDistance(point) - radius_);
00811 }
00812
00813 double MinDistanceSq(const Point& point) const {
00814 return math::Pow<2, 1>(MinDistance(point));
00815 }
00816
00820 double MinDistance(const DBallBound& other) const {
00821 double delta = MidDistance(other.center_) - radius_ - other.radius_;
00822 return math::ClampNonNegative(delta);
00823 }
00824
00825 double MinDistanceSq(const DBallBound& other) const {
00826 return math::Pow<2, 1>(MinDistance(other));
00827 }
00828
00832 double MaxDistance(const Point& point) const {
00833 return MidDistance(point) + radius_;
00834 }
00835
00836 double MaxDistanceSq(const Point& point) const {
00837 return math::Pow<2, 1>(MaxDistance(point));
00838 }
00839
00843 double MaxDistance(const DBallBound& other) const {
00844 return MidDistance(other.center_) + radius_ + other.radius_;
00845 }
00846
00847 double MaxDistanceSq(const DBallBound& other) const {
00848 return math::Pow<2, 1>(MaxDistance(other));
00849 }
00850
00856 DRange RangeDistance(const DBallBound& other) const {
00857 double delta = MidDistance(other.center_);
00858 double sumradius = radius_ + other.radius_;
00859 return DRange(
00860 math::ClampNonNegative(delta - sumradius),
00861 delta + sumradius);
00862 }
00863
00864 DRange RangeDistanceSq(const DBallBound& other) const {
00865 double delta = MidDistance(other.center_);
00866 double sumradius = radius_ + other.radius_;
00867 return DRange(
00868 math::Pow<2, 1>(math::ClampNonNegative(delta - sumradius)),
00869 math::Pow<2, 1>(delta + sumradius));
00870 }
00871
00883 double MinToMid(const DBallBound& other) const {
00884 double delta = MidDistance(other.center_) - radius_;
00885 return math::ClampNonNegative(delta);
00886 }
00887
00888 double MinToMidSq(const DBallBound& other) const {
00889 return math::Pow<2, 1>(MinToMid(other));
00890 }
00891
00895 double MinimaxDistance(const DBallBound& other) const {
00896 double delta = MidDistance(other.center_) + other.radius_ - radius_;
00897 return math::ClampNonNegative(delta);
00898 }
00899
00900 double MinimaxDistanceSq(const DBallBound& other) const {
00901 return math::Pow<2, 1>(MinimaxDistance(other));
00902 }
00903
00907 double MidDistance(const DBallBound& other) const {
00908 return MidDistance(other.center_);
00909 }
00910
00911 double MidDistanceSq(const DBallBound& other) const {
00912 return math::Pow<2, 1>(MidDistance(other));
00913 }
00914
00915 double MidDistance(const Point& point) const {
00916 return Metric::Distance(center_, point);
00917 }
00918 };
00919
00920 #endif