diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2d96ee8 --- /dev/null +++ b/Makefile @@ -0,0 +1,42 @@ +## +## EPITECH PROJECT, 2019 +## quadtree +## File description: +## Makefile +## + +SRC = src/quadtree.c \ + src/qt_split.c \ + src/utility/calloc.c + +OBJ = $(SRC:%.c=%.o) + +INCLUDE = -I ./include + +CFLAGS = $(INCLUDE) -Wall -Wextra -Wshadow + +LDFLAGS = + +NAME = libquadtree.a + +CC = gcc + +AR = ar rc + +all: build + +build: $(OBJ) + $(AR) $(NAME) $(OBJ) + +clean: + $(RM) $(OBJ) + +fclean: clean + $(RM) $(NAME) + +re: fclean all + +dbg: CFLAGS += -g +dbg: re + +.PHONY: all build clean fclean \ No newline at end of file diff --git a/include/quadtree.h b/include/quadtree.h new file mode 100644 index 0000000..f0c702d --- /dev/null +++ b/include/quadtree.h @@ -0,0 +1,38 @@ +/* +** EPITECH PROJECT, 2019 +** quadtree +** File description: +** quadtree +*/ + +#pragma once + +#include + +typedef struct quadtree quadtree; + +typedef struct qt_intrect +{ + int x; + int y; + int h; + int w; +} qt_intrect; + +typedef struct qt_object +{ + int id; + qt_intrect rect; +} qt_object; + +struct quadtree +{ + qt_intrect rect; + int capacity; + void **objects; +}; + +int qt_add(quadtree *tree, qt_object *obj); +bool qt_collide(qt_intrect r1, qt_intrect r2); +qt_object *qt_getobj(quadtree *tree, int id); +int qt_update(quadtree *tree, qt_object *obj); \ No newline at end of file diff --git a/include/quadtree_internal.h b/include/quadtree_internal.h new file mode 100644 index 0000000..7cc49be --- /dev/null +++ b/include/quadtree_internal.h @@ -0,0 +1,12 @@ +/* +** EPITECH PROJECT, 2019 +** quadtree +** File description: +** quadtree_internal +*/ + +#pragma once + +void *my_calloc(int capacity, int size); + +quadtree **qt_split(quadtree *tree); \ No newline at end of file diff --git a/src/qt_split.c b/src/qt_split.c new file mode 100644 index 0000000..122c5cc --- /dev/null +++ b/src/qt_split.c @@ -0,0 +1,44 @@ +/* +** EPITECH PROJECT, 2019 +** quadtree +** File description: +** qt_split +*/ + +#include "quadtree.h" +#include "quadtree_internal.h" +#include + +qt_object **qt_filter_objects(quadtree *tree, qt_intrect rect) +{ + qt_object **objs = my_calloc(tree->capacity, sizeof(qt_object *)); + int len = 0; + + for (int i = 0; tree->objects[i]; i++) { + if (qt_collide(((qt_object *)tree->objects[i])->rect, rect)) + objs[len++] = (qt_object *)tree->objects[i]; + } + return (objs); +} + +quadtree **qt_split(quadtree *tree) +{ + quadtree **ret = malloc(sizeof(quadtree *) * 4); + + if (!ret) + return (NULL); + for (int i = 0; i < 4; i++) { + ret[i] = malloc(sizeof(quadtree)); + if (!ret[i]) + return (NULL); + ret[i]->capacity = tree->capacity; + ret[i]->rect.h = tree->rect.h / 2; + ret[i]->rect.w = tree->rect.w / 2; + ret[i]->rect.x = !(i % 2) ? tree->rect.x : tree->rect.x + tree->rect.w; + ret[i]->rect.y = !(i > 1) ? tree->rect.y : tree->rect.y + tree->rect.h; + ret[i]->objects = (void **)qt_filter_objects(tree, ret[i]->rect); + } + tree->capacity = -1; + tree->objects = (void **)ret; + return (ret); +} \ No newline at end of file diff --git a/src/quadtree.c b/src/quadtree.c new file mode 100644 index 0000000..d104378 --- /dev/null +++ b/src/quadtree.c @@ -0,0 +1,84 @@ +/* +** EPITECH PROJECT, 2019 +** quadtree +** File description: +** quadtree +*/ + +#include "quadtree.h" +#include "quadtree_internal.h" +#include +#include + +quadtree *qt_create(qt_intrect rect, int capacity) +{ + quadtree *tree = malloc(sizeof(quadtree)); + + if (!tree) + return (NULL); + tree->rect = rect; + tree->capacity = capacity; + tree->objects = my_calloc(capacity, sizeof(*tree->objects)); + if (!tree->objects) { + free(tree); + return (NULL); + } + return (tree); +} + +bool qt_collide(qt_intrect r1, qt_intrect r2) +{ + if (r1.x + r1.w < r2.x || r2.x + r2.w < r1.x) + return (false); + if (r1.y + r1.h < r2.y || r2.y + r2.h < r1.y) + return (false); + return (true); +} + +int qt_add(quadtree *tree, qt_object *obj) +{ + int i = 0; + + if (tree->capacity > 0) { + while (tree->objects[i++]); + if (i < tree->capacity) + tree->objects[i] = obj; + else + qt_split(tree); + return (0); + } + for (i = 0; i < 4; i++) { + if (qt_collide(((qt_object *)tree->objects[i])->rect, obj->rect)) + qt_add((quadtree *)tree->objects[i], obj); + } + return (0); +} + +qt_object *qt_getobj(quadtree *tree, int id) +{ + qt_object *obj; + + if (tree->capacity == -1) { + for (int i = 0; i < 4; i++) { + obj = qt_getobj(tree->objects[i], id); + if (obj) + return (obj); + } + return (NULL); + } + for (int i = 0; tree->objects[i]; i++) { + if (((qt_object *)tree->objects[i])->id == id) + return ((qt_object *)tree->objects[i]); + } + return (NULL); +} + +int qt_update(quadtree *tree, qt_object *obj) +{ + qt_object *o = qt_getobj(tree, obj->id); + + if (!o) + return (-1); + *o = *obj; + return (0); +} \ No newline at end of file diff --git a/src/utility/calloc.c b/src/utility/calloc.c new file mode 100644 index 0000000..e0ef09d --- /dev/null +++ b/src/utility/calloc.c @@ -0,0 +1,19 @@ +/* +** EPITECH PROJECT, 2019 +** quadtree +** File description: +** calloc +*/ + +#include +#include + +void *my_calloc(int capacity, int size) +{ + void *alloc = malloc(capacity * size); + + if (!alloc) + return (NULL); + memset(alloc, 0, capacity * size); + return (alloc); +} \ No newline at end of file