├── Object.cpp ├── Object.h ├── Quadtree.cpp ├── Quadtree.h └── main.cpp /Object.cpp: -------------------------------------------------------------------------------- 1 | #include "Object.h" 2 | 3 | 4 | Object::Object( float _x, float _y, float _width, float _height ) : 5 | x ( _x ), 6 | y ( _y ), 7 | width ( _width ), 8 | height ( _height ) 9 | { 10 | shape.setPosition( x, y ); 11 | shape.setSize( sf::Vector2f( width, height ) ); 12 | shape.setFillColor( sf::Color( 32, 128, 255 ) ); 13 | } 14 | 15 | void Object::Draw( sf::RenderTarget &canvas ) { 16 | canvas.draw( shape ); 17 | } -------------------------------------------------------------------------------- /Object.h: -------------------------------------------------------------------------------- 1 | #ifndef __OBJECT_H__ 2 | #define __OBJECT_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class Object { 9 | public: 10 | float x; 11 | float y; 12 | float width; 13 | float height; 14 | 15 | Object( float x, float y, float width, float height ); 16 | 17 | void Draw( sf::RenderTarget &canvas ); 18 | 19 | private: 20 | sf::RectangleShape shape; 21 | }; 22 | 23 | #endif -------------------------------------------------------------------------------- /Quadtree.cpp: -------------------------------------------------------------------------------- 1 | #include "Quadtree.h" 2 | #include "Object.h" 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | Quadtree::Quadtree(float _x, float _y, float _width, float _height, int _level, int _maxLevel) : 9 | x (_x), 10 | y (_y), 11 | width (_width), 12 | height (_height), 13 | level (_level), 14 | maxLevel(_maxLevel) 15 | { 16 | shape.setPosition(x, y); 17 | shape.setSize(sf::Vector2f(width, height)); 18 | shape.setFillColor(sf::Color(0, 0, 0, 0)); 19 | shape.setOutlineThickness(1.0f); 20 | shape.setOutlineColor(sf::Color(64, 128, 255)); 21 | text.setPosition(x, y + level * 16); 22 | text.setCharacterSize(12); 23 | 24 | if (level == maxLevel) { 25 | return; 26 | } 27 | 28 | NW = new Quadtree(x, y, width / 2.0f, height / 2.0f, level+1, maxLevel); 29 | NE = new Quadtree(x + width / 2.0f, y, width / 2.0f, height / 2.0f, level+1, maxLevel); 30 | SW = new Quadtree(x, y + height / 2.0f, width / 2.0f, height / 2.0f, level+1, maxLevel); 31 | SE = new Quadtree(x + width / 2.0f, y + height / 2.0f, width / 2.0f, height / 2.0f, level+1, maxLevel); 32 | } 33 | 34 | Quadtree::~Quadtree() 35 | { 36 | if (level == maxLevel) 37 | return; 38 | 39 | delete NW; 40 | delete NE; 41 | delete SW; 42 | delete SE; 43 | } 44 | 45 | void Quadtree::AddObject(Object *object) { 46 | if (level == maxLevel) { 47 | objects.push_back(object); 48 | return; 49 | } 50 | if (contains(NW, object)) { 51 | NW->AddObject(object); return; 52 | } else if (contains(NE, object)) { 53 | NE->AddObject(object); return; 54 | } else if (contains(SW, object)) { 55 | SW->AddObject(object); return; 56 | } else if (contains(SE, object)) { 57 | SE->AddObject(object); return; 58 | } 59 | if (contains(this, object)) { 60 | objects.push_back(object); 61 | } 62 | } 63 | 64 | vector Quadtree::GetObjectsAt(float _x, float _y) { 65 | if (level == maxLevel) { 66 | return objects; 67 | } 68 | 69 | vector returnObjects, childReturnObjects; 70 | if (!objects.empty()) { 71 | returnObjects = objects; 72 | } 73 | if (_x > x + width / 2.0f && _x < x + width) { 74 | if (_y > y + height / 2.0f && _y < y + height) { 75 | childReturnObjects = SE->GetObjectsAt(_x, _y); 76 | returnObjects.insert(returnObjects.end(), childReturnObjects.begin(), childReturnObjects.end()); 77 | return returnObjects; 78 | } else if (_y > y && _y <= y + height / 2.0f) { 79 | childReturnObjects = NE->GetObjectsAt(_x, _y); 80 | returnObjects.insert(returnObjects.end(), childReturnObjects.begin(), childReturnObjects.end()); 81 | return returnObjects; 82 | } 83 | } else if (_x > x && _x <= x + width / 2.0f) { 84 | if (_y > y + height / 2.0f && _y < y + height) { 85 | childReturnObjects = SW->GetObjectsAt(_x, _y); 86 | returnObjects.insert(returnObjects.end(), childReturnObjects.begin(), childReturnObjects.end()); 87 | return returnObjects; 88 | } else if (_y > y && _y <= y + height / 2.0f) { 89 | childReturnObjects = NW->GetObjectsAt(_x, _y); 90 | returnObjects.insert(returnObjects.end(), childReturnObjects.begin(), childReturnObjects.end()); 91 | return returnObjects; 92 | } 93 | } 94 | return returnObjects; 95 | } 96 | 97 | void Quadtree::Clear() { 98 | if (level == maxLevel) { 99 | objects.clear(); 100 | return; 101 | } else { 102 | NW->Clear(); 103 | NE->Clear(); 104 | SW->Clear(); 105 | SE->Clear(); 106 | } 107 | if (!objects.empty()) { 108 | objects.clear(); 109 | } 110 | } 111 | 112 | void Quadtree::SetFont(const sf::Font &font) { 113 | text.setFont(font); 114 | if (level != maxLevel) { 115 | NW->SetFont(font); 116 | NE->SetFont(font); 117 | SW->SetFont(font); 118 | SE->SetFont(font); 119 | } 120 | } 121 | 122 | void Quadtree::Draw(sf::RenderTarget &canvas) { 123 | stringstream ss; 124 | ss << objects.size(); 125 | string numObjectsStr = ss.str(); 126 | text.setString(numObjectsStr); 127 | canvas.draw(shape); 128 | canvas.draw(text); 129 | if (level != maxLevel) { 130 | NW->Draw(canvas); 131 | NE->Draw(canvas); 132 | SW->Draw(canvas); 133 | SE->Draw(canvas); 134 | } 135 | } 136 | 137 | bool Quadtree::contains(Quadtree *child, Object *object) { 138 | return !(object->x < child->x || 139 | object->y < child->y || 140 | object->x > child->x + child->width || 141 | object->y > child->y + child->height || 142 | object->x + object->width < child->x || 143 | object->y + object->height < child->y || 144 | object->x + object->width > child->x + child->width || 145 | object->y + object->height > child->y + child->height); 146 | } 147 | -------------------------------------------------------------------------------- /Quadtree.h: -------------------------------------------------------------------------------- 1 | #ifndef __QUADTREE_H__ 2 | #define __QUADTREE_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | class Quadtree; 12 | class Object; 13 | 14 | class Quadtree { 15 | public: 16 | Quadtree(float x, float y, float width, float height, int level, int maxLevel); 17 | 18 | ~Quadtree(); 19 | 20 | void AddObject(Object *object); 21 | vector GetObjectsAt(float x, float y); 22 | void Clear(); 23 | 24 | void SetFont(const sf::Font &font); 25 | void Draw(sf::RenderTarget &canvas); 26 | 27 | private: 28 | float x; 29 | float y; 30 | float width; 31 | float height; 32 | int level; 33 | int maxLevel; 34 | vector objects; 35 | 36 | Quadtree * parent; 37 | Quadtree * NW; 38 | Quadtree * NE; 39 | Quadtree * SW; 40 | Quadtree * SE; 41 | 42 | sf::RectangleShape shape; 43 | sf::Text text; 44 | 45 | bool contains(Quadtree *child, Object *object); 46 | }; 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | // QuadtreeSimple.cpp : Demonstrates the use of Quadtree using SFML 2 | // 3 | 4 | #include "Quadtree.h" 5 | #include "Object.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | int main() 12 | { 13 | using namespace std; 14 | 15 | sf::RenderWindow app( sf::VideoMode( 800, 600, 32 ), "Quadtree" ); 16 | app.setFramerateLimit( 60 ); 17 | 18 | sf::Font font; 19 | font.loadFromFile( "DroidSans.ttf" ); 20 | 21 | Quadtree quadtree( 0.0f, 0.0f, 800.0f, 600.0f, 0, 3 ); 22 | quadtree.SetFont( font ); 23 | 24 | vector objects; 25 | 26 | while( app.isOpen() ) { 27 | sf::Event event; 28 | sf::Vector2i mousePosition = sf::Mouse::getPosition( app ); 29 | while( app.pollEvent( event ) ) { 30 | if ( event.type == sf::Event::KeyPressed ) { 31 | if ( event.key.code == sf::Keyboard::Escape ) { 32 | app.close(); 33 | } 34 | } 35 | if ( event.type == sf::Event::MouseButtonPressed ) { 36 | objects.push_back( Object( mousePosition.x, mousePosition.y, 32, 32 ) ); 37 | } 38 | } 39 | app.clear(); 40 | 41 | for ( int n = 0; n < objects.size(); ++n ) { 42 | quadtree.AddObject( &objects[n] ); 43 | objects[n].Draw( app ); 44 | } 45 | quadtree.Draw( app ); 46 | 47 | vector returnObjects = quadtree.GetObjectsAt( mousePosition.x, mousePosition.y ); 48 | cout << returnObjects.size() << endl; 49 | quadtree.Clear(); 50 | 51 | app.display(); 52 | } 53 | 54 | return 0; 55 | } --------------------------------------------------------------------------------