Advertisement
Guest User

Qtree.inl

a guest
Apr 25th, 2014
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.53 KB | None | 0 0
  1.  
  2. template <class Object>
  3. Quadtree<Object>::Quadtree(sf::Vector2f startingPoint, float width, float height, Quadtree<Object>* parent) {
  4.     mAABB.left = startingPoint.x;
  5.     mAABB.top =  startingPoint.y;
  6.     mAABB.width =   width;
  7.     mAABB.height = height;
  8.  
  9.     mDebugRect.setFillColor(sf::Color::Transparent);
  10.     mDebugRect.setOutlineThickness(1.0f);
  11.     mDebugRect.setOutlineColor(sf::Color::Blue);
  12.     mDebugRect.setSize(sf::Vector2f(width-4, height-4));
  13.     mDebugRect.setPosition(startingPoint.x + 2, startingPoint.y+2);
  14.    
  15.     mParent = parent;
  16. }
  17.  
  18.  
  19. template <class Object>
  20. void Quadtree<Object>::removeWrecks()
  21. {
  22.     // Reverse iteration
  23.     for (auto qtree : mChildren)
  24.     {
  25.         qtree->removeWrecks();
  26.     }
  27.  
  28.     // If the number of objects < 4 and children vector not empty
  29.     if (isMarkedForRemoval())
  30.     {
  31.         // Moving all of the objects of the children to the parent
  32.         for (auto it = mChildren.begin(); it != mChildren.end(); ++it)
  33.         {
  34.             for (auto object : (*it)->mObjects)
  35.             {
  36.                 (*it)->mParent->insertObject((object));
  37.             }
  38.             // Deleting child objects
  39.             (*it)->mObjects.clear();
  40.         }
  41.         // Deleting children
  42.         mChildren.clear();
  43.     }
  44. }
  45.  
  46. template <class Object>
  47. int Quadtree<Object>::getLocalObjectCount()
  48. {
  49.     return mObjects.size();
  50. }
  51.  
  52. template <class Object>
  53. void Quadtree<Object>::getTotalObjectCount(int& count)
  54. {
  55.     count += getLocalObjectCount();
  56.  
  57.     for (auto qtree : mChildren)
  58.     {
  59.         qtree->getTotalObjectCount(count);
  60.     }
  61. }
  62.  
  63. template <class Object>
  64. void Quadtree<Object>::insertObject(Object* object)
  65. {
  66.     mObjects.push_back(object);
  67.  
  68.     if (getLocalObjectCount() > MAX_OBJECTS && mChildren.empty())
  69.         subdivide();
  70. }
  71.  
  72.  
  73. template <class Object>
  74. void Quadtree<Object>::removeObject(Object* object)
  75. {
  76.     // Searching the object to remove, recursively through all of the children, if found, it erases it.
  77.     bool isFound = false;
  78.  
  79.     if (!mObjects.empty())
  80.     {
  81.         auto found = std::find_if(mObjects.begin(), mObjects.end(), [&](Object* Qobj) {
  82.             if (object == Qobj)
  83.             {
  84.                 isFound = true;
  85.                 return true;
  86.             }
  87.             else
  88.                 return false;
  89.         });
  90.  
  91.         if (isFound)
  92.             mObjects.erase(found);
  93.  
  94.     }
  95.  
  96.     if (!isFound)
  97.     {
  98.         for (auto qtree : mChildren)
  99.         {
  100.             qtree->removeObject(object);
  101.         }
  102.     }
  103. }
  104.  
  105. template <class Object>
  106. void Quadtree<Object>::updateAll()
  107. {
  108.     // Updating objects position on the quadtree
  109.     for (auto it = mObjects.begin(); it != mObjects.end(); ++it)
  110.     {
  111.         // getObjIndex returns a value which indicates the new position according to object's bounding rect.
  112.         int index = getObjIndex((*it));
  113.  
  114.  
  115.         // moving the object if needed
  116.  
  117.         if (index == -2)
  118.         {
  119.             mParent->insertObject((*it));
  120.         }
  121.         else if (index > -1)
  122.         {
  123.             switch (index)
  124.             {
  125.             case 0:
  126.                 mChildren[0]->insertObject((*it));
  127.                 break;
  128.             case 1:
  129.                 mChildren[1]->insertObject((*it));
  130.                 break;
  131.             case 2:
  132.                 mChildren[2]->insertObject((*it));
  133.                 break;
  134.             case 3:
  135.                 mChildren[3]->insertObject((*it));     
  136.                 break;
  137.             default:
  138.                 break;
  139.             }
  140.         }
  141.     }
  142.  
  143.     // erasing the moved objects from their old position ( = here )
  144.     mObjects.erase(std::remove_if(mObjects.begin(), mObjects.end(), [this](Object* obj){ return getObjIndex(obj) == -2 || getObjIndex(obj) > -1; }), mObjects.end());
  145.  
  146.     // if marked for removal, we tell the oldest parent to remove his children which are marked for removal
  147.     if (isMarkedForRemoval())
  148.     {
  149.         Quadtree<Object>* oldestParent = new Quadtree<Object>();
  150.         getOldestParent(oldestParent);
  151.         oldestParent->removeWrecks();
  152.     }
  153.  
  154.     for (auto c : mChildren)
  155.     {
  156.         c->updateAll();
  157.     }
  158.  
  159. }
  160.  
  161. template <class Object>
  162. int Quadtree<Object>::getObjIndex(Object* obj)
  163. {
  164.     /*
  165.     -2 = parent
  166.     -1 = this
  167.      0 = upleft
  168.      1 = upright
  169.      2 = downleft
  170.      3 = downright
  171.      */
  172.            
  173.    
  174.     std::vector<int> counter;                    
  175.                                  
  176.     if (!mChildren.empty())
  177.     {
  178.         if (mChildren[0]->intersects(obj))
  179.             counter.push_back(0);
  180.         if (mChildren[1]->intersects(obj))
  181.             counter.push_back(1);
  182.         if (mChildren[2]->intersects(obj))
  183.             counter.push_back(2);
  184.         if (mChildren[3]->intersects(obj))
  185.             counter.push_back(3);
  186.     }
  187.                                                  
  188.     int index;                                    
  189.    
  190.     // if there is only one intersection, it means that only one child contains the object, we assign it to there
  191.     // if there is more, the object don't move
  192.     if (counter.size() == 1)                      
  193.         index = counter[0];                      
  194.     else                                          
  195.         index = -1;                              
  196.                                                  
  197.     if (mParent == nullptr)                      
  198.         return index;                            
  199.  
  200.     // it is important to get the position relative to all of his parents, if the object intersects more than one of his parents (for example the center), the object has to be moved to the parent of this parent,
  201.     // this is done recursively.
  202.     int indexFromParent;                          
  203.     indexFromParent = mParent->getObjIndex(obj);  
  204.                                                                  
  205.     if (indexFromParent <= -1)                    
  206.         return -2;                  
  207.     else                                          
  208.         return index;                            
  209.    
  210. }
  211.  
  212. template <class Object>
  213. void Quadtree<Object>::subdivide()
  214. {
  215.     float height = mAABB.height / 2;
  216.     float width  = mAABB.width / 2;
  217.     float x = mAABB.left;
  218.     float y = mAABB.top;
  219.  
  220.     mChildren.push_back(new Quadtree(sf::Vector2f(x        , y         ), width, height, this));
  221.     mChildren.push_back(new Quadtree(sf::Vector2f(x + width, y         ), width, height, this));
  222.     mChildren.push_back(new Quadtree(sf::Vector2f(x        , y + height), width, height, this));
  223.     mChildren.push_back(new Quadtree(sf::Vector2f(x + width, y + height), width, height, this));
  224. }
  225.  
  226. template <class Object>
  227. void Quadtree<Object>::manage()
  228. {
  229.     updateAll();
  230. }
  231.  
  232. template <class Object>
  233. bool Quadtree<Object>::intersects(Object* object)
  234. {
  235.     return mAABB.intersects(object->getBoundingRect());
  236. }
  237.  
  238. template <class Object>
  239. void Quadtree<Object>::draw(sf::RenderTarget& target)
  240. {
  241.     target.draw(mDebugRect);
  242.  
  243.     for (auto qtree : mChildren)
  244.     {
  245.         qtree->draw(target);
  246.     }
  247. }
  248.  
  249.  
  250. template <class Object>
  251. bool Quadtree<Object>::isMarkedForRemoval()
  252. {
  253.     int count = 0;
  254.     getTotalObjectCount(count);
  255.     return count <= MAX_OBJECTS && !mChildren.empty();
  256. }
  257.  
  258.  
  259. template <class Object>
  260. void Quadtree<Object>::getOldestParent(Quadtree<Object>*& parent)
  261. {
  262.     if (mParent != nullptr)
  263.     {
  264.         parent = mParent;
  265.  
  266.         mParent->getOldestParent(parent);
  267.     }
  268.     else
  269.         parent = this;
  270. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement