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
00032
00033
00034
00035 #include "kdtree.h"
00036
00037 #include "perf/perf.h"
00038 #include "util/distribution.h"
00039
00040
00041 namespace kdtree {
00042
00043
00044
00045
00046 Entry::~Entry(void) throw() { }
00047
00048 static const float s_eps = 1.0e-9;
00049
00050
00051
00052
00053
00054
00055
00056 eSort
00057 sortPoint
00058 (
00059 IN const plane_t& plane,
00060 IN const point3d_t& point
00061 )
00062 throw()
00063 {
00064 float delta = 0.0;
00065 switch (plane.axis) {
00066 case eAxis_X:
00067 delta = point.x - plane.value;
00068 break;
00069
00070 case eAxis_Y:
00071 delta = point.y - plane.value;
00072 break;
00073
00074 case eAxis_Z:
00075 delta = point.z - plane.value;
00076 break;
00077
00078 default:
00079 return eSort_Invalid;
00080 }
00081
00082 if (delta < -s_eps)
00083 return eSort_Left;
00084 if (delta > s_eps)
00085 return eSort_Right;
00086
00087
00088 return eSort_Straddle;
00089 }
00090
00091
00092
00093 eSort
00094 sortRect
00095 (
00096 IN const plane_t& plane,
00097 IN const rect3d_t& r
00098 )
00099 throw()
00100 {
00101
00102
00103 eSort sort = eSort_Invalid;
00104 for (int i = 0; i < rect3d_t::eMaxCorners; ++i) {
00105 point3d_t p = r.getCorner(i);
00106 eSort val = sortPoint(plane, p);
00107 if (eSort_Straddle == val)
00108 continue;
00109
00110 if (eSort_Invalid == sort) {
00111 sort = val;
00112 } else if (sort != val) {
00113 return eSort_Straddle;
00114 }
00115 }
00116
00117
00118 if (eSort_Invalid == sort) {
00119
00120
00121
00122
00123 return eSort_Straddle;
00124 }
00125 return sort;
00126 }
00127
00128
00129
00130 static eAxis
00131 getLongAxis
00132 (
00133 IN const rect3d_t& r
00134 )
00135 throw()
00136 {
00137 float dx = r.x1 - r.x0;
00138 float dy = r.y1 - r.y0;
00139 float dz = r.z1 - r.z0;
00140
00141 eAxis axis = eAxis_Invalid;
00142
00143 if (dx > dy) {
00144 if (dx > dz) {
00145 axis = eAxis_X;
00146 } else {
00147 axis = eAxis_Z;
00148 }
00149 } else if (dy > dz) {
00150 axis = eAxis_Y;
00151 } else {
00152 axis = eAxis_Z;
00153 }
00154
00155 return axis;
00156 }
00157
00158
00159
00160
00161 static void
00162 simpleSplit
00163 (
00164 IN const rect3d_t& r,
00165 OUT plane_t& plane
00166 )
00167 throw()
00168 {
00169 plane.axis = getLongAxis(r);
00170 switch (plane.axis) {
00171 case eAxis_X:
00172 plane.value = 0.5 * (r.x0 + r.x1);
00173 break;
00174
00175 case eAxis_Y:
00176 plane.value = 0.5 * (r.y0 + r.y1);
00177 break;
00178
00179 case eAxis_Z:
00180 plane.value = 0.5 * (r.z0 + r.z1);
00181 break;
00182
00183 default:
00184 ASSERT(false, "Bad axis: %d", plane.axis);
00185 }
00186 }
00187
00188
00189
00190 static void
00191 measureSplit
00192 (
00193 IN const plane_t& plane,
00194 IN const Node::vec_entries_t& vec,
00195 OUT int& nLeft,
00196 OUT int& nRight
00197 )
00198 throw()
00199 {
00200
00201 nLeft = nRight = 0;
00202 for (Node::vec_entries_t::const_iterator i = vec.begin();
00203 i != vec.end(); ++i) {
00204 const Node::entry_rec_t& er = *i;
00205 eSort sort = sortRect(plane, er.rect);
00206 if (eSort_Left == sort) {
00207 ++nLeft;
00208 } else if (eSort_Right == sort) {
00209 ++nRight;
00210 }
00211 }
00212 }
00213
00214
00215
00216 static void
00217 bestSplit
00218 (
00219 IN int offset,
00220 IN const Node::vec_entries_t& vec,
00221 OUT plane_t& plane,
00222 OUT int& nLeft,
00223 OUT int& nRight
00224 )
00225 {
00226 ASSERT(offset >= 0 && offset < 3, "Bad offset: %d", offset);
00227 plane.clear();
00228 plane.axis = (eAxis) (offset + 1);
00229
00230
00231
00232
00233 distribution_t<float> dist;
00234 for (Node::vec_entries_t::const_iterator i = vec.begin();
00235 i != vec.end(); ++i) {
00236 const Node::entry_rec_t& er = *i;
00237 const float * p0 = &er.rect.x0;
00238 p0 += offset;
00239
00240 dist.addSample(*p0);
00241 }
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 int N = dist.size();
00256 ASSERT(N > 1, "Not enough entries");
00257 int start = 0;
00258 int end = N - 1;
00259
00260 int nLeftStart, nLeftEnd;
00261 plane.value = dist.getValueAtIndex(start);
00262 measureSplit(plane, vec, nLeftStart, nRight);
00263 plane.value = dist.getValueAtIndex(end);
00264 measureSplit(plane, vec, nLeftEnd, nRight);
00265
00266 int mid = end / 2;
00267
00268
00269 while (true) {
00270
00271
00272 int nLeftMid;
00273 plane.value = dist.getValueAtIndex(mid);
00274 measureSplit(plane, vec, nLeftMid, nRight);
00275
00276
00277
00278
00279
00280 if (nLeftMid > nRight) {
00281
00282
00283
00284 if (mid - start < 2) {
00285
00286 if (nLeftStart > 0) {
00287 mid = start;
00288 }
00289 break;
00290 }
00291
00292
00293 end = mid;
00294 nLeftEnd = nLeftMid;
00295 } else if (nLeftMid < nRight) {
00296
00297
00298
00299 if (end - mid < 2) {
00300
00301 if (!nLeftMid) {
00302 mid = end;
00303 }
00304 break;
00305 }
00306
00307
00308 start = mid;
00309 nLeftStart = nLeftMid;
00310 } else {
00311
00312
00313 break;
00314 }
00315
00316
00317 mid = (start + end) / 2;
00318 }
00319
00320
00321
00322 plane.value = dist.getValueAtIndex(mid);
00323
00324 measureSplit(plane, vec, nLeft, nRight);
00325
00326 }
00327
00328
00329
00330 static void
00331 balancedSplit
00332 (
00333 IN const rect3d_t& r,
00334 OUT plane_t& plane,
00335 IN const Node::vec_entries_t& vec
00336 )
00337 throw()
00338 {
00339
00340 plane_t planes[3];
00341 int N = vec.size();
00342 ASSERT(N > 1, "Only works with 2 or more entries!");
00343 int iPreferred = getLongAxis(r) - 1;
00344 int iBest = 0;
00345 float dBest = 1.0;
00346 for (int i = 0; i < 3; ++i) {
00347 int nLeft, nRight;
00348 bestSplit(i, vec, planes[i], nLeft, nRight);
00349
00350
00351 float rLeft = (1.0 * nLeft) / (1.0 * N);
00352 float rRight = (1.0 * nRight) / (1.0 * N);
00353
00354
00355
00356
00357
00358
00359 float dLeft = rLeft - 0.5;
00360 float dRight = rRight - 0.5;
00361 float d2 = (dLeft * dLeft) + (dRight * dRight);
00362
00363 if (d2 < dBest) {
00364 iBest = i;
00365 dBest = d2;
00366 } else if (d2 == dBest && i == iPreferred) {
00367
00368 iBest = i;
00369 }
00370 }
00371
00372
00373
00374 ASSERT(iBest >= 0 && iBest < 3, "Bad best offset: %d", iBest);
00375
00376
00377 plane = planes[iBest];
00378 }
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482 static void
00483 getLeftRightBounds
00484 (
00485 IN const rect3d_t& r,
00486 IN const plane_t& plane,
00487 OUT rect3d_t& left,
00488 OUT rect3d_t& right
00489 )
00490 throw()
00491 {
00492 left = r;
00493 right = r;
00494
00495 switch (plane.axis) {
00496 case eAxis_X:
00497 left.x1 = right.x0 = plane.value;
00498 break;
00499
00500 case eAxis_Y:
00501 left.y1 = right.y0 = plane.value;
00502 break;
00503
00504 case eAxis_Z:
00505 left.z1 = right.z0 = plane.value;
00506 break;
00507
00508 default:
00509 ASSERT(false, "Invalid axis: %d", plane.axis);
00510 }
00511 }
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521 Node::Node(void)
00522 throw()
00523 {
00524 m_user = NULL;
00525 m_left = m_right = NULL;
00526 m_bounds.clear();
00527 m_sortPlane.clear();
00528 }
00529
00530
00531
00532 Node::~Node(void)
00533 throw()
00534 {
00535 }
00536
00537
00538
00539 void
00540 Node::initialize
00541 (
00542 IN const rect3d_t& bounds
00543 )
00544 {
00545 m_bounds = bounds;
00546 }
00547
00548
00549
00550 int
00551 Node::getTreeDepth
00552 (
00553 void
00554 )
00555 const
00556 throw()
00557 {
00558 int maxChild = (m_left) ? m_left->getTreeDepth() : 0;
00559 if (m_right) {
00560 int n = m_right->getTreeDepth();
00561 if (n > maxChild) {
00562 maxChild = n;
00563 }
00564 }
00565 return maxChild + 1;
00566 }
00567
00568
00569
00570 int
00571 Node::getNodeCount
00572 (
00573 void
00574 )
00575 const
00576 throw()
00577 {
00578 int iLeft = (m_left) ? m_left->getNodeCount() : 0;
00579 int iRight = (m_right) ? m_right->getNodeCount() : 0;
00580 return iLeft + iRight + 1;
00581 }
00582
00583
00584
00585 int
00586 Node::getStaticEntryCount
00587 (
00588 void
00589 )
00590 const
00591 throw()
00592 {
00593 int iLeft = (m_left) ? m_left->getStaticEntryCount() : 0;
00594 int iRight = (m_right) ? m_right->getStaticEntryCount() : 0;
00595 return iLeft + iRight + m_entries.size();
00596 }
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606 void
00607 Node::addStaticEntry
00608 (
00609 IN smart_ptr<Entry>& entry,
00610 IN const rect3d_t& r
00611 )
00612 {
00613
00614
00615
00616 if (!m_bounds.containsRect(r)) {
00617 m_bounds.dump("Node boundary");
00618 r.dump("Entity box");
00619 ASSERT_THROW(false,
00620 "Incoming entry is not contained by kd-tree node");
00621 }
00622
00623 if (m_left || m_right) {
00624
00625 eSort sort = sortRect(m_sortPlane, r);
00626 switch (sort) {
00627 case eSort_Left:
00628 m_left->addStaticEntry(entry, r);
00629 return;
00630 case eSort_Right:
00631 m_right->addStaticEntry(entry, r);
00632 return;
00633 case eSort_Straddle:
00634 break;
00635 default:
00636 ASSERT(false, "bad sort");
00637 }
00638 }
00639
00640
00641 entry_rec_t er;
00642 er.entry = entry;
00643 er.rect = r;
00644 m_entries.push_back(er);
00645 }
00646
00647
00648
00649 void
00650 Node::addDynamicEntry
00651 (
00652 IN smart_ptr<dynamic_entry_t>& dyn
00653 )
00654 {
00655 ASSERT(dyn, "null");
00656 ASSERT(!dyn->next, "should only pass in an unlinked entry");
00657
00658
00659 if (m_left) {
00660 switch (sortRect(m_sortPlane, dyn->rect)) {
00661 case eSort_Left:
00662 m_left->addDynamicEntry(dyn);
00663 return;
00664
00665 case eSort_Right:
00666 m_right->addDynamicEntry(dyn);
00667 return;
00668
00669 default:
00670
00671 break;
00672 }
00673 }
00674
00675
00676 dyn->next = m_dynamic;
00677 m_dynamic = dyn;
00678 }
00679
00680
00681
00682 bool
00683 Node::removeStaticEntry
00684 (
00685 IN Entry * entry
00686 )
00687 throw()
00688 {
00689 ASSERT(entry, "null");
00690
00691
00692
00693 for (vec_entries_t::iterator i = m_entries.begin();
00694 i != m_entries.end(); ++i) {
00695 entry_rec_t& er = *i;
00696 if (entry == er.entry) {
00697 m_entries.erase(i);
00698 return true;
00699 }
00700 }
00701
00702
00703 return false;
00704 }
00705
00706
00707
00708 smart_ptr<Node::dynamic_entry_t>
00709 Node::popDynamicEntry
00710 (
00711 void
00712 )
00713 throw()
00714 {
00715 smart_ptr<dynamic_entry_t> dyn = m_dynamic;
00716 if (dyn) {
00717 m_dynamic = dyn->next;
00718 dyn->next = NULL;
00719 }
00720 return dyn;
00721 }
00722
00723
00724
00725 eAction
00726 Node::iterateStaticEntries
00727 (
00728 IN const rect3d_t& r,
00729 IN iteration_callback callback,
00730 IN void * context
00731 )
00732 {
00733 ASSERT(r.isValid(), "invalid");
00734 ASSERT(callback, "null");
00735
00736
00737
00738 for (vec_entries_t::iterator i = m_entries.begin();
00739 i != m_entries.end();) {
00740 vec_entries_t::iterator next = i;
00741 ++next;
00742
00743 entry_rec_t& er = *i;
00744 if (r.intersectsRect(er.rect)) {
00745
00746
00747 eAction act = callback(context, er.entry, er.rect);
00748 if (eAction_Remove & act) {
00749 m_entries.erase(i);
00750 }
00751 if (eAction_Halt & act)
00752 return eAction_Halt;
00753 }
00754
00755
00756 i = next;
00757 }
00758
00759
00760 if (!m_left)
00761 return eAction_Continue;
00762
00763
00764 eSort sort = sortRect(m_sortPlane, r);
00765
00766 if (eSort_Left == sort || eSort_Straddle == sort) {
00767 eAction act = m_left->iterateStaticEntries(r, callback, context);
00768 if (eAction_Halt & act)
00769 return eAction_Halt;
00770 }
00771 if (eSort_Right == sort || eSort_Straddle == sort) {
00772 eAction act = m_right->iterateStaticEntries(r, callback, context);
00773 if (eAction_Halt & act)
00774 return eAction_Halt;
00775 }
00776
00777
00778 return eAction_Continue;
00779 }
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789 void
00790 Node::subdivide
00791 (
00792 IN eStrategy strategy,
00793 IN float param
00794 )
00795 {
00796
00797 int minSize = (param < 2) ? 2 : param;
00798 if (!m_left && (int) m_entries.size() <= minSize) {
00799 return;
00800 }
00801
00802
00803 if (!m_left) {
00804 this->subdivideInternal(strategy, param);
00805 }
00806
00807
00808 vec_entries_t vecNew;
00809 for (vec_entries_t::iterator i = m_entries.begin();
00810 i != m_entries.end(); ++i) {
00811 entry_rec_t& er = *i;
00812
00813
00814 eSort sort = sortRect(m_sortPlane, er.rect);
00815 if (eSort_Left == sort) {
00816 m_left->addStaticEntry(er.entry, er.rect);
00817 } else if (eSort_Right == sort) {
00818 m_right->addStaticEntry(er.entry, er.rect);
00819 } else if (eSort_Straddle == sort) {
00820 vecNew.push_back(er);
00821 } else {
00822 ASSERT(false, "bad sort result");
00823 }
00824 }
00825
00826
00827 m_entries.clear();
00828 m_entries = vecNew;
00829
00830
00831 int nLeft = m_left->getStaticEntryCount();
00832 int nRight = m_right->getStaticEntryCount();
00833 if (!nLeft || !nRight) {
00834
00835 return;
00836 }
00837
00838
00839 m_left->subdivide(strategy, param);
00840 m_right->subdivide(strategy, param);
00841
00842
00843
00844
00845
00846
00847 }
00848
00849
00850
00851 void
00852 Node::subdivideInternal
00853 (
00854 IN eStrategy strategy,
00855 IN float param
00856 )
00857 {
00858 ASSERT(!m_left && !m_right, "already have children?");
00859
00860
00861 switch (strategy) {
00862 case eStrategy_Naive:
00863 simpleSplit(m_bounds, m_sortPlane);
00864 break;
00865
00866 case eStrategy_Balance:
00867 balancedSplit(m_bounds, m_sortPlane, m_entries);
00868 break;
00869
00870 default:
00871 ASSERT(false, "Unknown strategy: %d", strategy);
00872 }
00873
00874
00875
00876 rect3d_t rLeft, rRight;
00877 getLeftRightBounds(m_bounds, m_sortPlane, rLeft, rRight);
00878
00879
00880 ASSERT(rLeft.isValid(), "invalid");
00881 ASSERT(rRight.isValid(), "invalid");
00882
00883
00884 m_left = Node::create(rLeft);
00885 ASSERT(m_left, "failed to create left child");
00886 m_right = Node::create(rRight);
00887 ASSERT(m_right, "failed to create right child");
00888 }
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898 smart_ptr<Node>
00899 Node::create
00900 (
00901 IN const rect3d_t& bounds
00902 )
00903 {
00904 ASSERT(bounds.isValid(), "invalid");
00905
00906 smart_ptr<Node> local = new Node;
00907 ASSERT(local, "out of memory");
00908
00909 local->initialize(bounds);
00910
00911 return local;
00912 }
00913
00914
00915
00916 };
00917
00918