Quadtree.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. #include "Quadtree.h"
  2. #include <algorithm>
  3. #include <assert.h>
  4. using namespace ltbl;
  5. Quadtree::Quadtree()
  6. : _minNumNodeOccupants(3),
  7. _maxNumNodeOccupants(6),
  8. _maxLevels(40),
  9. _oversizeMultiplier(1.0f)
  10. {}
  11. void Quadtree::operator=(const Quadtree &other) {
  12. _minNumNodeOccupants = other._minNumNodeOccupants;
  13. _maxNumNodeOccupants = other._maxNumNodeOccupants;
  14. _maxLevels = other._maxLevels;
  15. _oversizeMultiplier = other._oversizeMultiplier;
  16. _outsideRoot = other._outsideRoot;
  17. if (other._pRootNode != nullptr) {
  18. _pRootNode.reset(new QuadtreeNode());
  19. recursiveCopy(_pRootNode.get(), other._pRootNode.get(), nullptr);
  20. }
  21. }
  22. void Quadtree::setQuadtree(QuadtreeOccupant* oc) {
  23. oc->_pQuadtree = this;
  24. }
  25. void Quadtree::recursiveCopy(QuadtreeNode* pThisNode, QuadtreeNode* pOtherNode, QuadtreeNode* pThisParent) {
  26. pThisNode->_hasChildren = pOtherNode->_hasChildren;
  27. pThisNode->_level = pOtherNode->_level;
  28. pThisNode->_numOccupantsBelow = pOtherNode->_numOccupantsBelow;
  29. pThisNode->_occupants = pOtherNode->_occupants;
  30. pThisNode->_region = pOtherNode->_region;
  31. pThisNode->_pParent = pThisParent;
  32. pThisNode->_pQuadtree = this;
  33. if (pThisNode->_hasChildren)
  34. for (int i = 0; i < 4; i++) {
  35. pThisNode->_children[i].reset(new QuadtreeNode());
  36. recursiveCopy(pThisNode->_children[i].get(), pOtherNode->_children[i].get(), pThisNode);
  37. }
  38. }
  39. void Quadtree::queryRegion(std::vector<QuadtreeOccupant*> &result, const sf::FloatRect &region) {
  40. // Query outside root elements
  41. for (auto oc : _outsideRoot) {
  42. // Intersects, add to list
  43. if (oc != nullptr && region.intersects(oc->getAABB()))
  44. result.push_back(oc);
  45. }
  46. std::list<QuadtreeNode*> open;
  47. open.push_back(_pRootNode.get());
  48. while (!open.empty()) {
  49. // Depth-first (results in less memory usage), remove objects from open list
  50. QuadtreeNode* pCurrent = open.back();
  51. open.pop_back();
  52. if (region.intersects(pCurrent->_region)) {
  53. for (auto oc : pCurrent->_occupants) {
  54. // Visible, add to list
  55. if (oc != nullptr && region.intersects(oc->getAABB()))
  56. result.push_back(oc);
  57. }
  58. // Add children to open list if they intersect the region
  59. if (pCurrent->_hasChildren)
  60. for (int i = 0; i < 4; i++)
  61. if (pCurrent->_children[i]->getNumOccupantsBelow() != 0)
  62. open.push_back(pCurrent->_children[i].get());
  63. }
  64. }
  65. }
  66. void Quadtree::queryPoint(std::vector<QuadtreeOccupant*> &result, const sf::Vector2f &p) {
  67. // Query outside root elements
  68. for (std::unordered_set<QuadtreeOccupant*>::iterator it = _outsideRoot.begin(); it != _outsideRoot.end(); it++) {
  69. QuadtreeOccupant* oc = *it;
  70. if (oc != nullptr && oc->getAABB().contains(p))
  71. // Intersects, add to list
  72. result.push_back(oc);
  73. }
  74. std::list<QuadtreeNode*> open;
  75. open.push_back(_pRootNode.get());
  76. while (!open.empty()) {
  77. // Depth-first (results in less memory usage), remove objects from open list
  78. QuadtreeNode* pCurrent = open.back();
  79. open.pop_back();
  80. if (pCurrent->_region.contains(p)) {
  81. for (std::unordered_set<QuadtreeOccupant*>::iterator it = pCurrent->_occupants.begin(); it != pCurrent->_occupants.end(); it++) {
  82. QuadtreeOccupant* oc = *it;
  83. if (oc != nullptr && oc->getAABB().contains(p))
  84. // Visible, add to list
  85. result.push_back(oc);
  86. }
  87. // Add children to open list if they intersect the region
  88. if (pCurrent->_hasChildren)
  89. for (int i = 0; i < 4; i++)
  90. if (pCurrent->_children[i]->getNumOccupantsBelow() != 0)
  91. open.push_back(pCurrent->_children[i].get());
  92. }
  93. }
  94. }
  95. void Quadtree::queryShape(std::vector<QuadtreeOccupant*> &result, const sf::ConvexShape &shape) {
  96. // Query outside root elements
  97. for (std::unordered_set<QuadtreeOccupant*>::iterator it = _outsideRoot.begin(); it != _outsideRoot.end(); it++) {
  98. QuadtreeOccupant* oc = *it;
  99. if (oc != nullptr && shapeIntersection(shapeFromRect(oc->getAABB()), shape))
  100. // Intersects, add to list
  101. result.push_back(oc);
  102. }
  103. std::list<QuadtreeNode*> open;
  104. open.push_back(_pRootNode.get());
  105. while (!open.empty()) {
  106. // Depth-first (results in less memory usage), remove objects from open list
  107. QuadtreeNode* pCurrent = open.back();
  108. open.pop_back();
  109. if (shapeIntersection(shapeFromRect(pCurrent->_region), shape)) {
  110. for (std::unordered_set<QuadtreeOccupant*>::iterator it = pCurrent->_occupants.begin(); it != pCurrent->_occupants.end(); it++) {
  111. QuadtreeOccupant* oc = *it;
  112. sf::ConvexShape r = shapeFromRect(oc->getAABB());
  113. if (oc != nullptr && shapeIntersection(shapeFromRect(oc->getAABB()), shape))
  114. // Visible, add to list
  115. result.push_back(oc);
  116. }
  117. // Add children to open list if they intersect the region
  118. if (pCurrent->_hasChildren)
  119. for (int i = 0; i < 4; i++)
  120. if (pCurrent->_children[i]->getNumOccupantsBelow() != 0)
  121. open.push_back(pCurrent->_children[i].get());
  122. }
  123. }
  124. }