Advertisement
Guest User

Quadtree.cpp

a guest
Apr 26th, 2014
360
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.76 KB | None | 0 0
  1. #include "Quadtree.h"
  2.  
  3. int Quadtree::MAX_OBJECTS = 3;
  4.  
  5. Quadtree::Quadtree(sf::FloatRect bounds, Quadtree* parent)
  6. {
  7.     mParent = parent;
  8.     mAABB = bounds;
  9.     mDebugRect.setFillColor(sf::Color::Transparent);
  10.     mDebugRect.setOutlineThickness(1.0f);
  11.     mDebugRect.setOutlineColor(sf::Color::Blue);
  12.     mDebugRect.setSize(sf::Vector2f(bounds.width - 4, bounds.height - 4));
  13.     mDebugRect.setPosition(bounds.left +2, bounds.top + 2);
  14. }
  15.  
  16. void Quadtree::drawDebugRect(sf::RenderTarget& target)
  17. {
  18.     target.draw(mDebugRect);
  19.  
  20.     for (auto qtree : mChildren)
  21.     {
  22.         qtree->drawDebugRect(target);
  23.     }
  24. }
  25.  
  26. void Quadtree::insertObject(Boundable* object)
  27. {
  28.     mObjects.push_back(object);
  29.  
  30.     if (getLocalObjectCount() > MAX_OBJECTS && mChildren.empty())
  31.         subdivide();
  32. }
  33.  
  34. void Quadtree::removeObject(Boundable* object)
  35. {
  36.     bool isFound = false;
  37.  
  38.     if (!mObjects.empty())
  39.     {
  40.         auto found = std::find_if(mObjects.begin(), mObjects.end(), [&](Boundable* Qobj) {
  41.             if (object == Qobj)
  42.             {
  43.                 isFound = true;
  44.                 return true;
  45.             }
  46.             else
  47.                 return false;
  48.         });
  49.  
  50.         if (isFound)
  51.             mObjects.erase(found);
  52.  
  53.     }
  54.  
  55.     if (!isFound)
  56.     {
  57.         for (auto& qtree : mChildren)
  58.         {
  59.             qtree->removeObject(object);
  60.         }
  61.     }
  62. }
  63.  
  64. std::set<Quadtree::Pair> Quadtree::collisionPairs()
  65. {
  66.     std::set<Pair> collisionSet;
  67.  
  68.     getCollisionPairs(collisionSet);
  69.  
  70.     return collisionSet;
  71. }
  72.  
  73. int Quadtree::count()
  74. {
  75.     int count = 0;
  76.     getTotalObjectCount(count);
  77.     return count;
  78. }
  79.  
  80. int Quadtree::getObjectLimit()
  81. {
  82.     return Quadtree::MAX_OBJECTS;
  83. }
  84.  
  85. void Quadtree::setObjectLimit(int limit)
  86. {
  87.     Quadtree::MAX_OBJECTS = limit;
  88. }
  89.  
  90. void Quadtree::manage()
  91. {
  92.     updateAll();
  93. }
  94.  
  95. void Quadtree::clear()
  96. {
  97.     mObjects.clear();
  98.     mChildren.clear();
  99. }
  100.  
  101. void Quadtree::updateAll()
  102. {
  103.     for (auto it = mObjects.begin(); it != mObjects.end(); ++it)
  104.     {
  105.  
  106.         int index = getObjIndex((*it));
  107.  
  108.         if (index == -2)
  109.         {
  110.             mParent->insertObject((*it));
  111.         }
  112.         else if (index > -1)
  113.         {
  114.             switch (index)
  115.             {
  116.             case 0:
  117.                 mChildren[0]->insertObject((*it));
  118.                 break;
  119.             case 1:
  120.                 mChildren[1]->insertObject((*it));
  121.                 break;
  122.             case 2:
  123.                 mChildren[2]->insertObject((*it));
  124.                 break;
  125.             case 3:
  126.                 mChildren[3]->insertObject((*it));
  127.                 break;
  128.             default:
  129.                 break;
  130.             }
  131.         }
  132.     }
  133.  
  134.     mObjects.erase(std::remove_if(mObjects.begin(), mObjects.end(), [this](Boundable* obj){ return getObjIndex(obj) == -2 || getObjIndex(obj) > -1; }), mObjects.end());
  135.  
  136.     if (isMarkedForRemoval())
  137.     {
  138.         Quadtree* oldestParent = new Quadtree;
  139.         getOldestParent(oldestParent);
  140.         oldestParent->removeWrecks();
  141.     }
  142.  
  143.     for (auto& c : mChildren)
  144.     {
  145.         c->updateAll();
  146.     }
  147. }
  148.  
  149. void Quadtree::subdivide()
  150. {
  151.     float height = mAABB.height / 2;
  152.     float width = mAABB.width / 2;
  153.     float x = mAABB.left;
  154.     float y = mAABB.top;
  155.  
  156.     mChildren.push_back(new Quadtree(sf::FloatRect(x, y, width, height), this));
  157.     mChildren.push_back(new Quadtree(sf::FloatRect(x + width, y, width, height), this));
  158.     mChildren.push_back(new Quadtree(sf::FloatRect(x, y + height, width, height), this));
  159.     mChildren.push_back(new Quadtree(sf::FloatRect(x + width, y + height, width, height), this));
  160. }
  161.  
  162. void Quadtree::removeWrecks()
  163. {
  164.     for (auto& qtree : mChildren)
  165.     {
  166.         qtree->removeWrecks();
  167.     }
  168.  
  169.  
  170.     if (isMarkedForRemoval())
  171.     {
  172.  
  173.         for (auto it = mChildren.begin(); it != mChildren.end(); ++it)
  174.         {
  175.             for (auto& object : (*it)->mObjects)
  176.             {
  177.                 (*it)->mParent->insertObject(object);
  178.             }
  179.  
  180.             (*it)->mObjects.clear();
  181.         }
  182.  
  183.         mChildren.clear();
  184.     }
  185. }
  186.  
  187. bool Quadtree::isMarkedForRemoval()
  188. {
  189.     int count = 0;
  190.     getTotalObjectCount(count);
  191.     return count <= MAX_OBJECTS && !mChildren.empty();
  192. }
  193.  
  194. bool Quadtree::intersects(Boundable* object)
  195. {
  196.     return mAABB.intersects(object->getBoundingRect());
  197. }
  198.  
  199. int Quadtree::getObjIndex(Boundable* obj)
  200. {
  201.    
  202.     // -2 = parent
  203.     // -1 = this
  204.     // 0 = upleft
  205.     // 1 = upright
  206.     // 2 = downleft
  207.     // 3 = downright
  208.    
  209.  
  210.  
  211.     std::vector<int> counter;
  212.  
  213.     if (!mChildren.empty())
  214.     {
  215.         if (mChildren[0]->intersects(obj))
  216.             counter.push_back(0);
  217.         if (mChildren[1]->intersects(obj))
  218.             counter.push_back(1);
  219.         if (mChildren[2]->intersects(obj))
  220.             counter.push_back(2);
  221.         if (mChildren[3]->intersects(obj))
  222.             counter.push_back(3);
  223.     }
  224.  
  225.     int index;
  226.  
  227.     if (counter.size() == 1)
  228.         index = counter[0];
  229.     else
  230.         index = -1;
  231.  
  232.     if (mParent == nullptr)
  233.         return index;
  234.  
  235.     int indexFromParent;
  236.     indexFromParent = mParent->getObjIndex(obj);
  237.  
  238.     if (indexFromParent <= -1)
  239.         return -2;
  240.     else
  241.         return index;
  242.  
  243. }
  244.  
  245. int Quadtree::getLocalObjectCount()
  246. {
  247.     return mObjects.size();
  248. }
  249.  
  250. void Quadtree::getTotalObjectCount(int& count)
  251. {
  252.     count += getLocalObjectCount();
  253.  
  254.     for (auto& qtree : mChildren)
  255.     {
  256.         qtree->getTotalObjectCount(count);
  257.     }
  258. }
  259.  
  260. void Quadtree::getOldestParent(Quadtree*& parent)
  261. {
  262.     if (mParent != nullptr)
  263.     {
  264.         parent = mParent;
  265.  
  266.         mParent->getOldestParent(parent);
  267.     }
  268.     else
  269.         parent = this;
  270. }
  271.  
  272. void Quadtree::getCollisionPairs(std::set<Quadtree::Pair> & collisionSet)
  273. {
  274.     for (auto& obj1 : mObjects)
  275.     {
  276.  
  277.         for (auto& obj2 : mObjects)
  278.         {
  279.             if (isColliding(obj1, obj2) && obj1 != obj2)
  280.             collisionSet.insert(std::minmax(obj1, obj2));
  281.         }
  282.  
  283.  
  284.         getCollisionPairsFromChildren(collisionSet, obj1);
  285.  
  286.     }
  287.  
  288.     for (auto& qtree : mChildren)
  289.     {
  290.         qtree->getCollisionPairs(collisionSet);
  291.     }
  292. }
  293.  
  294. void Quadtree::getCollisionPairsFromChildren(std::set<Quadtree::Pair> & collisionSet, Boundable* obj)
  295. {
  296.     for (auto& qtree : mChildren)
  297.     {
  298.         for (auto& cObj : qtree->mObjects)
  299.         {
  300.             if (isColliding(obj, cObj))
  301.             collisionSet.insert(std::minmax(obj, cObj));
  302.         }
  303.     }
  304.  
  305.     for (auto& qtree : mChildren)
  306.         qtree->getCollisionPairsFromChildren(collisionSet, obj);
  307. }
  308.  
  309.  
  310. bool isColliding(Boundable* obj1, Boundable* obj2)
  311. {
  312.     return obj1->getBoundingRect().intersects(obj2->getBoundingRect());
  313. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement