Advertisement
ulfben

quad tree

Feb 25th, 2025
176
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.18 KB | None | 0 0
  1. #pragma once
  2. #include "raylib.h"
  3. #include <cassert>
  4. #include <memory>
  5. #include <vector>
  6.  
  7. template<class T>
  8. class QuadTree{
  9.    static constexpr size_t MAX_DEPTH = 8;
  10.    Rectangle boundary = {};
  11.    size_t capacity = 0;
  12.    size_t depth = 0;
  13.    std::vector<T*> objects{};
  14.    bool subdivided = false;
  15.    std::unique_ptr<QuadTree> north_west{nullptr};
  16.    std::unique_ptr<QuadTree> north_east{nullptr};
  17.    std::unique_ptr<QuadTree> south_west{nullptr};
  18.    std::unique_ptr<QuadTree> south_east{nullptr};  
  19.  
  20.    void subdivide(){
  21.       float x = boundary.x;
  22.       float y = boundary.y;
  23.       float w = boundary.width / 2.0f;
  24.       float h = boundary.height / 2.0f;
  25.  
  26.       Rectangle nw_rect = {x, y, w, h};
  27.       north_west = std::make_unique<QuadTree>(nw_rect, capacity, depth + 1);
  28.  
  29.       Rectangle ne_rect = {x + w, y, w, h};
  30.       north_east = std::make_unique<QuadTree>(ne_rect, capacity, depth + 1);
  31.  
  32.       Rectangle sw_rect = {x, y + h, w, h};
  33.       south_west = std::make_unique<QuadTree>(sw_rect, capacity, depth + 1);
  34.  
  35.       Rectangle se_rect = {x + w, y + h, w, h};
  36.       south_east = std::make_unique<QuadTree>(se_rect, capacity, depth + 1);
  37.  
  38.       subdivided = true;
  39.    }
  40.    
  41. public:
  42.    QuadTree(const Rectangle& boundary, size_t capacity, size_t depth = 0)
  43.       : boundary(boundary), capacity(capacity), depth(depth){
  44.       assert(depth <= MAX_DEPTH);
  45.       assert(capacity > 0);
  46.    }
  47.  
  48.    bool insert(T* obj){
  49.       if(!CheckCollisionPointRec(obj->position, boundary)){
  50.          return false;
  51.       }
  52.  
  53.       if(objects.size() < capacity || depth >= MAX_DEPTH){
  54.          objects.push_back(obj);
  55.          return true;
  56.       }
  57.  
  58.       if(!subdivided){
  59.          subdivide();
  60.       }
  61.       if(north_west->insert(obj)) return true;
  62.       if(north_east->insert(obj)) return true;
  63.       if(south_west->insert(obj)) return true;
  64.       if(south_east->insert(obj)) return true;
  65.      
  66.       assert(false && "should not happen if obj is within the boundary");
  67.       return false;
  68.    }
  69.      
  70.    void query_range(const Rectangle& range, std::vector<const T*>& found) const{
  71.       if(!CheckCollisionRecs(boundary, range)){
  72.          return;
  73.       }
  74.       for(auto obj : objects){        
  75.          if(CheckCollisionPointRec(obj->position, range)){
  76.             found.push_back(obj);
  77.          }
  78.       }
  79.       if(subdivided){
  80.          north_west->query_range(range, found);
  81.          north_east->query_range(range, found);
  82.          south_west->query_range(range, found);
  83.          south_east->query_range(range, found);
  84.       }
  85.    }
  86.  
  87.    void clear() noexcept{
  88.       objects.clear();
  89.       if(subdivided){
  90.          north_west->clear();
  91.          north_east->clear();
  92.          south_west->clear();
  93.          south_east->clear();
  94.          north_west.reset(nullptr);
  95.          north_east.reset(nullptr);
  96.          south_west.reset(nullptr);
  97.          south_east.reset(nullptr);
  98.          subdivided = false;
  99.       }
  100.    }
  101.    void render() const noexcept{
  102.       DrawRectangleLinesEx(boundary, 1, GREEN);      
  103.       if(subdivided){
  104.          north_west->render();
  105.          north_east->render();
  106.          south_west->render();
  107.          south_east->render();
  108.       }
  109.    }  
  110. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement