76#ifdef PICO_QT_USE_DOUBLE
89#ifndef PICO_QT_VALUE_TYPE
90#define PICO_QT_VALUE_TYPE uint32_t
225#ifdef PICO_QT_IMPLEMENTATION
232 #define PICO_QT_ASSERT(expr) ((void)0)
234 #ifndef PICO_QT_ASSERT
236 #define PICO_QT_ASSERT(expr) (assert(expr))
240#if !defined(PICO_QT_MALLOC) || !defined(PICO_QT_REALLOC) || !defined(PICO_QT_FREE)
242 #define PICO_QT_MALLOC(size, ctx) (malloc(size))
243 #define PICO_QT_REALLOC(ptr, size, ctx) (realloc(ptr, size))
244 #define PICO_QT_FREE(ptr, ctx) (free(ptr))
247#ifndef PICO_QT_MEMCPY
249 #define PICO_QT_MEMCPY memcpy
252#ifndef PICO_QT_MEMSET
254 #define PICO_QT_MEMSET memset
257#ifndef PICO_QT_BLOCK_SIZE
258 #define PICO_QT_BLOCK_SIZE 128
265#define QT_ASSERT PICO_QT_ASSERT
266#define QT_MEMCPY PICO_QT_MEMCPY
267#define QT_MEMSET PICO_QT_MEMSET
268#define QT_MALLOC PICO_QT_MALLOC
269#define QT_REALLOC PICO_QT_REALLOC
270#define QT_FREE PICO_QT_FREE
280typedef struct qt_node_t qt_node_t;
282typedef struct qt_array_header_t
302 qt_array qt_item_t* items;
305typedef union qt_unode_t
308 union qt_unode_t* next;
311typedef struct qt_node_allocator_t
313 qt_unode_t* free_list;
314 qt_array qt_unode_t** blocks;
315} qt_node_allocator_t;
329 qt_node_allocator_t allocator;
337#define qt_hdr(a) ((qt_array_header_t*)a - 1)
342 #define QT_ARRAY_CANARY(a) ((void)0)
344 #define QT_ARRAY_CANARY(a) ((a) ? QT_ASSERT(qt_hdr(a)->cookie == QT_ARRAY_COOKIE) : (void)0)
348#define QT_ARRAY_COOKIE 0xE6F7E359
352#define qt_array_len(a) (qt_hdr(a)->size)
356#define qt_array_size(a) (QT_ARRAY_CANARY(a), a ? qt_hdr(a)->size : 0)
359#define qt_array_capacity(a) (QT_ARRAY_CANARY(a), (a) ? qt_hdr(a)->capacity : 0)
362#define qt_array_fit(ctx, a, n) ((n) <= qt_array_capacity(a) ? 0 : (*(void**)&(a) = qt_array_fit_impl((a), (n), sizeof(*a), (ctx))))
365#define qt_array_push(ctx, a , ...) (QT_ARRAY_CANARY(a), qt_array_fit((ctx), (a), 1 + ((a) ? qt_array_size(a) : 0)), (a)[qt_array_len(a)++] = (__VA_ARGS__))
368#define qt_array_clear(a) (QT_ARRAY_CANARY(a), a ? (void)(qt_array_len(a) = 0) : (void)0)
371#define qt_array_destroy(ctx, a) (QT_ARRAY_CANARY(a), a ? QT_FREE(qt_hdr(a), (ctx)) : (void)0, a = NULL)
376#define qt_array_remove(a, i) (QT_ARRAY_CANARY(a), a[i] = a[--qt_array_len(a)])
385static void* qt_array_fit_impl(
const void* array,
int new_size,
size_t element_size,
void* mem_ctx);
387static qt_node_t* qt_node_alloc(
qt_t* qt);
388static void qt_node_free(
qt_t* qt, qt_node_t* node);
390static qt_node_t* qt_node_create(
qt_t* qt,
qt_rect_t bounds,
int depth,
int max_depth);
391static void qt_node_destroy(
qt_t* qt, qt_node_t* node);
393static bool qt_node_remove(qt_node_t* node,
qt_value_t value);
396static void qt_node_clear(qt_node_t* node);
398static qt_array qt_item_t* qt_node_all_items(
const qt_t* qt,
const qt_node_t* node, qt_array qt_item_t* items);
400static qt_array
qt_rect_t* qt_node_all_grid_rects(
const qt_t* qt,
const qt_node_t* node, qt_array
qt_rect_t* rects);
410 QT_MEMSET(qt, 0,
sizeof(*qt));
416 qt->root = qt_node_create(qt, bounds, 0, max_depth);
418 qt->mem_ctx = mem_ctx;
427 qt_node_destroy(qt, qt->root);
429 for (
int i = 0; i < qt_array_size(qt->allocator.blocks); i++)
431 QT_FREE(qt->allocator.blocks[i], qt->mem_ctx);
434 qt_array_destroy(qt->mem_ctx, qt->allocator.blocks);
435 QT_FREE(qt, qt->mem_ctx);
442 int max_depth = qt->root->max_depth;
444 qt_node_destroy(qt, qt->root);
446 qt->root = qt_node_create(qt, qt->bounds, 0, max_depth);
452 qt_node_insert(qt, qt->root, &bounds, value);
458 return qt_node_remove(qt->root, value);
471 qt_array
qt_value_t* values = qt_node_query(qt, qt->root, &area, NULL);
481 *size = qt_array_size(values);
495 qt_array
qt_rect_t* rects = qt_node_all_grid_rects(qt, qt->root, NULL);
505 *size = qt_array_size(rects);
517 qt_array_destroy(qt->mem_ctx, array);
523 qt_node_clear(qt->root);
530 qt_array qt_item_t* items = qt_node_all_items(qt, qt->root, NULL);
534 for (
int i = 0; i < qt_array_size(items); i++)
536 qt_insert(qt, items[i].bounds, items[i].value);
539 qt_array_destroy(qt->mem_ctx, items);
546static int qt_max(
int a,
int b)
548 return a > b ? a : b;
552static void* qt_array_fit_impl(
const void* array,
int new_size,
size_t element_size,
void* mem_ctx)
556 QT_ARRAY_CANARY(array);
560 int new_capacity = qt_max(2 * qt_array_capacity(array), qt_max(new_size, 16));
562 QT_ASSERT(new_size <= new_capacity);
566 size_t total_size =
sizeof(qt_array_header_t) + new_capacity * element_size;
568 qt_array_header_t* hdr;
574 hdr = (qt_array_header_t*)QT_REALLOC(qt_hdr(array), total_size, mem_ctx);
580 hdr = (qt_array_header_t*)QT_MALLOC(total_size, mem_ctx);
584 hdr->cookie = QT_ARRAY_COOKIE;
585 hdr->capacity = new_capacity;
586 hdr->data = (
char*)(hdr + 1);
588 return (
void*)(hdr + 1);
601 return r1->
x <= r2->
x &&
603 r1->
x + r1->
w >= r2->
x + r2->
w &&
604 r1->
y + r1->
h >= r2->
y + r2->
h;
612 return r1->
x + r1->
w >= r2->
x &&
613 r1->
y + r1->
h >= r2->
y &&
614 r2->
x + r2->
w >= r1->
x &&
615 r2->
y + r2->
h >= r1->
y;
618static qt_node_t* qt_node_create(
qt_t* qt,
qt_rect_t bounds,
int depth,
int max_depth)
620 qt_node_t* node = qt_node_alloc(qt);
623 node->max_depth = max_depth;
653static void qt_node_destroy(
qt_t* qt, qt_node_t* node)
657 qt_array_destroy(qt->mem_ctx, node->items);
660 for (
int i = 0; i < 4; i++)
663 qt_node_destroy(qt, node->nodes[i]);
667 qt_node_free(qt, node);
681 if (node->depth + 1 < node->max_depth)
684 for (
int i = 0; i < 4; i++)
687 if (qt_rect_contains(&node->bounds[i], bounds))
692 node->nodes[i] = qt_node_create(qt,
699 qt_node_insert(qt, node->nodes[i], bounds, value);
707 qt_array_push(qt->mem_ctx, node->items, (qt_item_t){ *bounds, value });
710static bool qt_node_remove(qt_node_t* node,
qt_value_t value)
716 for (
int i = 0; i < qt_array_size(node->items); i++)
719 if (node->items[i].value == value)
721 qt_array_remove(node->items, i);
727 for (
int i = 0; i < 4; i++)
731 if (qt_node_remove(node->nodes[i], value))
740static qt_array qt_item_t* qt_node_all_items(
const qt_t* qt,
const qt_node_t* node, qt_array qt_item_t* items)
745 for (
int i = 0; i < qt_array_size(node->items); i++)
747 qt_array_push(qt->mem_ctx, items, node->items[i]);
751 for (
int i = 0; i < 4; i++)
754 items = qt_node_all_items(qt, node->nodes[i], items);
765 for (
int i = 0; i < qt_array_size(node->items); i++)
767 qt_array_push(qt->mem_ctx, values, node->items[i].value);
771 for (
int i = 0; i < 4; i++)
774 values = qt_node_all_values(qt, node->nodes[i], values);
780static qt_array
qt_rect_t* qt_node_all_grid_rects(
const qt_t* qt,
const qt_node_t* node, qt_array
qt_rect_t* rects)
785 for (
int i = 0; i < 4; i++)
788 qt_array_push(qt->mem_ctx, rects, node->bounds[i]);
792 for (
int i = 0; i < 4; i++)
795 rects = qt_node_all_grid_rects(qt, node->nodes[i], rects);
808 for (
int i = 0; i < qt_array_size(node->items); i++)
810 const qt_item_t* item = &node->items[i];
812 if (qt_rect_overlaps(area, &item->bounds))
813 qt_array_push(qt->mem_ctx, values, node->items[i].value);
817 for (
int i = 0; i < 4; i++)
823 if (qt_rect_contains(area, &node->bounds[i]))
825 values = qt_node_all_values(qt, node->nodes[i], values);
832 if (qt_rect_overlaps(area, &node->bounds[i]))
834 values = qt_node_query(qt, node->nodes[i], area, values);
843static void qt_node_clear(qt_node_t* node)
845 qt_array_clear(node->items);
847 for (
int i = 0; i < 4; i++)
850 qt_node_clear(node->nodes[i]);
854static void qt_freelist_push(
qt_t* qt, qt_unode_t *unode)
856 qt_node_allocator_t* allocator = &qt->allocator;
857 unode->next = allocator->free_list;
858 allocator->free_list = unode;
861static qt_unode_t* qt_freelist_pop(
qt_t* qt)
863 qt_node_allocator_t* allocator = &qt->allocator;
864 qt_unode_t* unode = allocator->free_list;
865 allocator->free_list = allocator->free_list->next;
869static void qt_block_alloc(
qt_t* qt)
873 qt_node_allocator_t* allocator = &qt->allocator;
875 const int block_count = PICO_QT_BLOCK_SIZE;
877 qt_unode_t* nodes = (qt_unode_t*)QT_MALLOC(
sizeof(qt_unode_t) * block_count, qt->mem_ctx);
879 for (
int i = 0; i < block_count; i++)
881 qt_freelist_push(qt, &nodes[i]);
884 qt_array_push(qt->mem_ctx, allocator->blocks, nodes);
887static qt_node_t* qt_node_alloc(
qt_t* qt)
889 qt_node_allocator_t* allocator = &qt->allocator;
891 if (!allocator->free_list)
897 qt_unode_t* unode = qt_freelist_pop(qt);
898 QT_MEMSET(unode, 0,
sizeof(qt_unode_t));
900 qt_node_t* result = &unode->node;
905static void qt_node_free(
qt_t* qt, qt_node_t* node)
907 qt_freelist_push(qt, (qt_unode_t*)node);
void qt_clean(qt_t *qt)
Resets the tree and reinserts all items.
void qt_insert(qt_t *qt, qt_rect_t bounds, qt_value_t value)
Inserts a value with the specified bounds into a quadtree.
qt_t * qt_create(qt_rect_t bounds, int max_depth, void *mem_ctx)
Creates a quadtree with the specified global bounds.
qt_value_t * qt_query(const qt_t *qt, qt_rect_t area, int *size)
Returns all values associated with items that are either overlapping or contained within the search a...
struct qt_t qt_t
Quadtree data structure.
Definition pico_qt.h:101
PICO_QT_VALUE_TYPE qt_value_t
Node value type (default: uint32_t)
Definition pico_qt.h:96
bool qt_remove(qt_t *qt, qt_value_t value)
Searches for and removes a value in a quadtree.
void qt_free(qt_t *qt, void *array)
Function for deallocating arrays.
void qt_destroy(qt_t *qt)
Destroys a quadtree.
void qt_clear(qt_t *qt)
Removes all items in the tree.
void qt_reset(qt_t *qt)
Removes all nodes in the tree.
#define PICO_QT_VALUE_TYPE
Definition pico_qt.h:90
qt_rect_t qt_make_rect(qt_float x, qt_float y, qt_float w, qt_float h)
Utility function for creating a rectangle.
float qt_float
Single precision floating point type.
Definition pico_qt.h:85
qt_rect_t * qt_grid_rects(const qt_t *qt, int *size)
Returns all bounds associated with the quadtree's recursive grid structure.
Rectangle for representing bounds.
Definition pico_qt.h:107
qt_float x
Definition pico_qt.h:108
qt_float y
Definition pico_qt.h:108
qt_float h
Definition pico_qt.h:108
qt_float w
Definition pico_qt.h:108