From d74e8185f566be8e42ec8c07a433210727bf9d14 Mon Sep 17 00:00:00 2001 From: sam Date: Sat, 15 Jun 2024 20:32:28 +1200 Subject: [PATCH] quadtree experiment --- quadtree/a.out | Bin 0 -> 18832 bytes quadtree/main.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++ quadtree/naive.c | 35 ++++++++++++++ 3 files changed, 157 insertions(+) create mode 100755 quadtree/a.out create mode 100644 quadtree/main.c create mode 100644 quadtree/naive.c diff --git a/quadtree/a.out b/quadtree/a.out new file mode 100755 index 0000000000000000000000000000000000000000..3e0322ff27e10518cc794867107e9d480751295f GIT binary patch literal 18832 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 +#include +#include + +typedef struct Node { + Rectangle bounds; + Vector2 entities[4]; + int entity_count; + struct Node* children[4]; +} Node; + +Node* create_node(Rectangle bounds) { + Node* n = calloc(1, sizeof(Node)); + n->bounds = bounds; + return n; +} + +void split_node(Node* n) { + Rectangle b = n->bounds; + Vector2 half = (Vector2){ b.width / 2.0f, b.height / 2.0f }; + n->children[0] = create_node((Rectangle){ b.x, b.y, half.x, half.y }); + n->children[1] = create_node((Rectangle){ b.x + half.x, b.y, half.x, half.y }); + n->children[2] = create_node((Rectangle){ b.x, b.y + half.y, half.x, half.y }); + n->children[3] = create_node((Rectangle){ b.x + half.x, b.y + half.y, half.x, half.y }); +} + +int inside(Node* n, Vector2 p) { + return p.x > n->bounds.x && p.x < n->bounds.x + n->bounds.width && + p.y > n->bounds.y && p.y < n->bounds.y + n->bounds.height; +} + +int is_leaf(Node* n) { + return + n->children[0] == NULL && + n->children[1] == NULL && + n->children[2] == NULL && + n->children[3] == NULL; +} + +void add(Node* n, Vector2 p) { + if(n->entity_count >= 4) { + if(is_leaf(n)) { + split_node(n); + } + + int added = 0; + + for(int i = 0; i < 4; i++) { + if(inside(n->children[i], p)) { + add(n->children[i], p); + added = 1; + break; + } + } + + if(!added) { + add(n->children[0], p); + } + } else { + n->entities[n->entity_count++] = p; + } +} + +void draw(Vector2 p, Color c) { + DrawCircleV(p, 5.0f, c); +} + +void visualize(Node* n) { + //DrawRectangleLinesEx(n->bounds, 1.0f, RED); + + if(!is_leaf(n)) { + visualize(n->children[0]); + visualize(n->children[1]); + visualize(n->children[2]); + visualize(n->children[3]); + } + + Vector2 m_pos = GetMousePosition(); + + if(inside(n, m_pos)) { + //DrawRectangleLinesEx(n->bounds, 1.0f, BLUE); + for(int i = 0; i < n->entity_count; i++) { + if(CheckCollisionCircles(m_pos, 1.0f, n->entities[i], 5.0f)) { + draw(n->entities[i], GREEN); + } else { + draw(n->entities[i], WHITE); + } + } + } else { + for(int i = 0; i < n->entity_count; i++) { + draw(n->entities[i], WHITE); + } + } +} + +int main() { + const int width = 800; + const int height = 600; + InitWindow(width, height, "quadtree"); + + Node* root = create_node((Rectangle){ 0.0f, 0.0f, width, height }); + + for(int i = 0; i < 5000; i++) { + add(root, (Vector2){ GetRandomValue(0, width), GetRandomValue(0, height) }); + } + + while(!WindowShouldClose()) { + /*if(IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { + add(root, GetMousePosition()); + }*/ + + BeginDrawing(); + { + ClearBackground(BLACK); + visualize(root); + DrawFPS(10, 10); + } + EndDrawing(); + } + + CloseWindow(); +} diff --git a/quadtree/naive.c b/quadtree/naive.c new file mode 100644 index 0000000..2b06943 --- /dev/null +++ b/quadtree/naive.c @@ -0,0 +1,35 @@ +#include + +int main() { + const int width = 800; + const int height = 600; + InitWindow(width, height, "naive"); + + const int size = 5000; + Vector2 data[size]; + for(int i = 0; i < size; i++) { + data[i] = (Vector2){ GetRandomValue(0, 800), GetRandomValue(0, 600) }; + } + + while(!WindowShouldClose()) { + BeginDrawing(); + { + ClearBackground(BLACK); + + for(int i = 0; i < size; i++) { + if(CheckCollisionCircles(GetMousePosition(), 1.0f, data[i], 5.0f)) { + DrawCircleV(data[i], 5.0f, GREEN); + } else { + DrawCircleV(data[i], 5.0f, WHITE); + } + } + + DrawFPS(10, 10); + } + EndDrawing(); + } + + CloseWindow(); + + return 0; +}