Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
n_trees.c
Go to the documentation of this file.
1/*
2 * Nilorea Library
3 * Copyright (C) 2005-2026 Castagnier Mickael
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
27#include <stdlib.h>
28#include <string.h>
29#include <pthread.h>
30
31#include "nilorea/n_common.h"
32#include "nilorea/n_log.h"
33#include "nilorea/n_str.h"
34#include "nilorea/n_trees.h"
35
41 TREE* tree = NULL;
42 Malloc(tree, TREE, 1);
43 __n_assert(tree, n_log(LOG_ERR, "Failed to allocate memory for tree"); return NULL;);
44
45 tree->root = NULL;
46 tree->nb_nodes = 0;
47 tree->height = 0;
48 pthread_rwlock_init(&(tree->rwlock), NULL);
49
50 return tree;
51}
52
59TREE_NODE* tree_create_node(NODE_DATA value, void (*destroy_func)(void* ptr)) {
60 TREE_NODE* node = (TREE_NODE*)malloc(sizeof(TREE_NODE));
61 if (node == NULL) {
62 n_log(LOG_ERR, "Failed to allocate memory for tree node");
63 return NULL;
64 }
65
66 node->data = value;
67 node->destroy_func = destroy_func;
68 node->parent_list_node = NULL;
69 node->parent = NULL;
71 if (!node->children) {
72 Free(node);
73 return NULL;
74 }
75
76 return node;
77}
78
86 if (parent == NULL || child == NULL) {
87 return FALSE;
88 }
89
90 if (parent->children == NULL) {
92 __n_assert(parent->children, n_log(LOG_ERR, "Failed to create parent->children list"); return FALSE;);
93 }
94
95 LIST_NODE* node = new_list_node(child, NULL);
96 __n_assert(node, n_log(LOG_ERR, "Failed to create child node"); return FALSE;);
97
98 if (!list_node_push(parent->children, node)) {
99 if (node->destroy_func != NULL) {
100 node->destroy_func(node->ptr);
101 }
102 Free(node);
103 return FALSE;
104 }
105
106 child->parent_list_node = node;
107 child->parent = parent;
108
109 return TRUE;
110}
111
118int tree_delete_node(TREE* tree, TREE_NODE* node) {
119 if (tree == NULL || node == NULL) {
120 return FALSE;
121 }
122
123 // Recursively delete child nodes
124 LIST_NODE* child_node = node->children->start;
125 while (child_node) {
126 LIST_NODE* next_node = child_node->next;
127 TREE_NODE* child = (TREE_NODE*)child_node->ptr;
128 tree_delete_node(tree, child);
129 child_node = next_node;
130 }
131 list_destroy(&node->children);
132
133 // Remove the node from its parent's child list, if applicable
134 if (node->parent && node->parent->children) {
136 }
137
138 // Free node data if necessary
139 if (node->destroy_func) {
140 node->destroy_func(node->data.value.ptr);
141 }
142
143 // Free the node itself
144 free(node);
145 tree->nb_nodes--;
146
147 return TRUE;
148}
149
154void tree_destroy(TREE** tree) {
155 if (tree == NULL || *tree == NULL) {
156 return;
157 }
158
159 TREE_NODE* root = (*tree)->root;
160 if (root != NULL) {
161 tree_delete_node(*tree, root);
162 }
163
164 pthread_rwlock_destroy(&((*tree)->rwlock));
165 free(*tree);
166 *tree = NULL;
167}
168
176 return (a.i > b.i) - (a.i < b.i);
177}
178
186 return (a.f > b.f) - (a.f < b.f);
187}
188
196 return (a.d > b.d) - (a.d < b.d);
197}
198
204 printf("%d", val.i);
205}
206
213 printf("%f", val.f);
214}
215
221 printf("%lf", val.d);
222}
223
229QUADTREE* create_quadtree(int coord_type) {
230 QUADTREE* qt = (QUADTREE*)calloc(1, sizeof(QUADTREE));
231 if (!qt) {
232 n_log(LOG_ERR, "Failed to allocate QUADTREE");
233 return NULL;
234 }
235
236 qt->coord_type = coord_type;
237 qt->root = NULL;
238
239 switch (coord_type) {
240 case COORD_INT:
241 qt->compare = compare_int;
242 qt->print = print_int;
243 break;
244 case COORD_FLOAT:
246 qt->print = print_float;
247 break;
248 case COORD_DOUBLE:
250 qt->print = print_double;
251 break;
252 default:
253 qt->compare = NULL;
254 qt->print = NULL;
255 n_log(LOG_ERR, "Unknown coord_type %d", coord_type);
256 Free(qt);
257 return NULL;
258 }
259
260 return qt;
261}
262
271 QUADTREE_NODE* node = (QUADTREE_NODE*)malloc(sizeof(QUADTREE_NODE));
272 if (!node) {
273 n_log(LOG_ERR, "Failed to allocate QUADTREE_NODE");
274 return NULL;
275 }
276 node->x = x;
277 node->y = y;
278 node->data_ptr = data_ptr;
279 node->nw = NULL;
280 node->ne = NULL;
281 node->sw = NULL;
282 node->se = NULL;
283 return node;
284}
285
294void insert(QUADTREE* qt, QUADTREE_NODE** root, COORD_VALUE x, COORD_VALUE y, void* data_ptr) {
295 __n_assert(qt, return);
296
297 if (*root == NULL) {
298 *root = create_node(x, y, data_ptr);
299 __n_assert(*root, n_log(LOG_ERR, "Failed to create node"); return);
300 return;
301 }
302
303 if (qt->compare(x, (*root)->x) < 0 && qt->compare(y, (*root)->y) < 0) {
304 insert(qt, &((*root)->sw), x, y, data_ptr);
305 } else if (qt->compare(x, (*root)->x) < 0 && qt->compare(y, (*root)->y) >= 0) {
306 insert(qt, &((*root)->nw), x, y, data_ptr);
307 } else if (qt->compare(x, (*root)->x) >= 0 && qt->compare(y, (*root)->y) < 0) {
308 insert(qt, &((*root)->se), x, y, data_ptr);
309 } else if (qt->compare(x, (*root)->x) >= 0 && qt->compare(y, (*root)->y) >= 0) {
310 insert(qt, &((*root)->ne), x, y, data_ptr);
311 }
312}
313
323 if (root == NULL || (qt->compare(root->x, x) == 0 && qt->compare(root->y, y) == 0)) {
324 return root;
325 }
326
327 if (qt->compare(x, root->x) < 0 && qt->compare(y, root->y) < 0) {
328 return search(qt, root->sw, x, y);
329 } else if (qt->compare(x, root->x) < 0 && qt->compare(y, root->y) >= 0) {
330 return search(qt, root->nw, x, y);
331 } else if (qt->compare(x, root->x) >= 0 && qt->compare(y, root->y) < 0) {
332 return search(qt, root->se, x, y);
333 } else if (qt->compare(x, root->x) >= 0 && qt->compare(y, root->y) >= 0) {
334 return search(qt, root->ne, x, y);
335 }
336
337 return NULL; // Should not reach here
338}
339
345 __n_assert(root, return);
346
347 free_quadtree(root->nw);
348 free_quadtree(root->ne);
349 free_quadtree(root->sw);
350 free_quadtree(root->se);
351
352 free(root);
353}
354
361OCTREE_NODE* create_octree_node(POINT3D point, void* data_ptr) {
362 OCTREE_NODE* node = (OCTREE_NODE*)malloc(sizeof(OCTREE_NODE));
363 if (!node) {
364 n_log(LOG_ERR, "Failed to allocate OCTREE_NODE");
365 return NULL;
366 }
367
368 node->point = point;
369 node->data_ptr = data_ptr;
370 for (int i = 0; i < 8; i++) {
371 node->children[i] = NULL;
372 }
373
374 return node;
375}
376
383 OCTREE* octree = (OCTREE*)malloc(sizeof(OCTREE));
384 if (!octree) {
385 n_log(LOG_ERR, "Failed to allocate OCTREE");
386 return NULL;
387 }
388
389 octree->root = NULL;
390 octree->coord_type = type;
391
392 return octree;
393}
394
402int determine_octant(POINT3D point, POINT3D center, int type) {
403 int octant = 0;
404 if (type == COORD_INT) {
405 if (point.x.i >= center.x.i) octant |= 4;
406 if (point.y.i >= center.y.i) octant |= 2;
407 if (point.z.i >= center.z.i) octant |= 1;
408 } else if (type == COORD_FLOAT) {
409 if (point.x.f >= center.x.f) octant |= 4;
410 if (point.y.f >= center.y.f) octant |= 2;
411 if (point.z.f >= center.z.f) octant |= 1;
412 } else if (type == COORD_DOUBLE) {
413 if (point.x.d >= center.x.d) octant |= 4;
414 if (point.y.d >= center.y.d) octant |= 2;
415 if (point.z.d >= center.z.d) octant |= 1;
416 }
417 return octant;
418}
419
427void insert_octree_node(OCTREE_NODE* node, POINT3D point, void* data_ptr, int type) {
428 int octant = determine_octant(point, node->point, type);
429 if (!node->children[octant]) {
430 node->children[octant] = create_octree_node(point, data_ptr);
431 } else {
432 insert_octree_node(node->children[octant], point, data_ptr, type);
433 }
434}
435
442void insert_octree(OCTREE* octree, POINT3D point, void* data_ptr) {
443 if (!octree->root) {
444 octree->root = create_octree_node(point, data_ptr);
445 } else {
446 insert_octree_node(octree->root, point, data_ptr, octree->coord_type);
447 }
448}
449
455 if (node) {
456 for (int i = 0; i < 8; i++) {
457 free_octree_node(node->children[i]);
458 }
459 free(node);
460 }
461}
462
467void free_octree(OCTREE* octree) {
468 if (octree) {
469 free_octree_node(octree->root);
470 free(octree);
471 }
472}
#define Malloc(__ptr, __struct, __size)
Malloc Handler to get errors and set to 0.
Definition n_common.h:203
#define __n_assert(__ptr, __ret)
macro to assert things
Definition n_common.h:278
#define Free(__ptr)
Free Handler to get errors.
Definition n_common.h:262
void * ptr
void pointer to store
Definition n_list.h:45
LIST_NODE * start
pointer to the start of the list
Definition n_list.h:65
void(* destroy_func)(void *ptr)
pointer to destructor function if any, else NULL
Definition n_list.h:48
struct LIST_NODE * next
pointer to the next node
Definition n_list.h:51
LIST_NODE * new_list_node(void *ptr, void(*destructor)(void *ptr))
Allocate a new node to link in a list.
Definition n_list.c:56
int list_destroy(LIST **list)
Empty and Free a list container.
Definition n_list.c:547
void * remove_list_node_f(LIST *list, LIST_NODE *node)
Internal function called each time we need to get a node out of a list.
Definition n_list.c:75
LIST * new_generic_list(size_t max_items)
Initialiaze a generic list container to max_items pointers.
Definition n_list.c:36
#define MAX_LIST_ITEMS
flag to pass to new_generic_list for the maximum possible number of item in a list
Definition n_list.h:74
int list_node_push(LIST *list, LIST_NODE *node)
Add a filled node to the end of the list.
Definition n_list.c:116
Structure of a generic list node.
Definition n_list.h:43
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:88
#define LOG_ERR
error conditions
Definition n_log.h:75
print_func print
pointer to print function
Definition n_trees.h:170
compare_func compare
pointer to comparison function
Definition n_trees.h:168
TREE_NODE * root
pointer to first node
Definition n_trees.h:84
pthread_rwlock_t rwlock
mutex for thread safety (optional)
Definition n_trees.h:86
struct QUADTREE_NODE * nw
North-West child.
Definition n_trees.h:154
int coord_type
type of coordinate used in the quad tree
Definition n_trees.h:166
size_t nb_nodes
number of nodes in the tree
Definition n_trees.h:88
COORD_VALUE z
z coordinate
Definition n_trees.h:135
double d
Definition n_trees.h:115
void * data_ptr
Pointer to additional data, can be NULL.
Definition n_trees.h:191
OCTREE_NODE * root
tree list first node
Definition n_trees.h:199
COORD_VALUE y
Y coordinate.
Definition n_trees.h:148
QUADTREE_NODE * root
tree list first node
Definition n_trees.h:172
union NODE_DATA_TYPES value
node value
Definition n_trees.h:62
NODE_DATA data
structure holding values for node
Definition n_trees.h:70
struct QUADTREE_NODE * sw
South-West child.
Definition n_trees.h:158
COORD_VALUE x
x coordinate
Definition n_trees.h:131
float f
Definition n_trees.h:114
void * ptr
pointer type
Definition n_trees.h:52
void * data_ptr
Pointer to data, can be NULL.
Definition n_trees.h:152
struct QUADTREE_NODE * se
South-East child.
Definition n_trees.h:160
POINT3D point
Point represented by this node.
Definition n_trees.h:189
struct QUADTREE_NODE * ne
North-East child.
Definition n_trees.h:156
void(* destroy_func)(void *ptr)
value destructor if of type ptr and specified, else a simple free will be used
Definition n_trees.h:72
COORD_VALUE y
y coordinate
Definition n_trees.h:133
COORD_VALUE x
X coordinate.
Definition n_trees.h:146
struct OCTREE_NODE * children[8]
Child nodes.
Definition n_trees.h:193
LIST_NODE * parent_list_node
pointer to parent container of the TREE_NODE, LIST_NODE
Definition n_trees.h:76
struct TREE_NODE * parent
pointer to parent
Definition n_trees.h:74
size_t height
height of the tree
Definition n_trees.h:90
LIST * children
ordered list of children
Definition n_trees.h:78
int coord_type
Coordinate type for the entire tree.
Definition n_trees.h:201
void free_octree_node(OCTREE_NODE *node)
recursive function to free an OCTREE node and its children
Definition n_trees.c:454
void insert_octree(OCTREE *octree, POINT3D point, void *data_ptr)
Insert a point into the OCTREE.
Definition n_trees.c:442
int tree_insert_child(TREE_NODE *parent, TREE_NODE *child)
insert a child node into the parent node
Definition n_trees.c:85
void free_quadtree(QUADTREE_NODE *root)
Function to free the quad tree.
Definition n_trees.c:344
TREE * new_tree()
create a new TREE
Definition n_trees.c:40
TREE_NODE * tree_create_node(NODE_DATA value, void(*destroy_func)(void *ptr))
create a TREE node
Definition n_trees.c:59
QUADTREE_NODE * search(QUADTREE *qt, QUADTREE_NODE *root, COORD_VALUE x, COORD_VALUE y)
Function to search for a point in the quad tree.
Definition n_trees.c:322
void free_octree(OCTREE *octree)
free the OCTREE
Definition n_trees.c:467
void tree_destroy(TREE **tree)
destroy a TREE
Definition n_trees.c:154
OCTREE_NODE * create_octree_node(POINT3D point, void *data_ptr)
create and OCTREE node
Definition n_trees.c:361
OCTREE * create_octree(int type)
Create a new OCTREE with a specified coordinate type.
Definition n_trees.c:382
int tree_delete_node(TREE *tree, TREE_NODE *node)
delete a TREE node
Definition n_trees.c:118
void insert(QUADTREE *qt, QUADTREE_NODE **root, COORD_VALUE x, COORD_VALUE y, void *data_ptr)
Function to insert a point into the quad tree.
Definition n_trees.c:294
QUADTREE * create_quadtree(int coord_type)
Function to create a new quad tree.
Definition n_trees.c:229
QUADTREE_NODE * create_node(COORD_VALUE x, COORD_VALUE y, void *data_ptr)
function to create a new quad tree node
Definition n_trees.c:270
@ COORD_INT
Definition n_trees.h:106
@ COORD_DOUBLE
Definition n_trees.h:108
@ COORD_FLOAT
Definition n_trees.h:107
structure of a TREE node data
Definition n_trees.h:60
structure of an OCTREE
Definition n_trees.h:197
structure of an OCTREE node
Definition n_trees.h:187
Structure for a POINT3D in the 3D space.
Definition n_trees.h:128
structure of a quad tree
Definition n_trees.h:164
structure of a quad tree node
Definition n_trees.h:144
structure of a TREE
Definition n_trees.h:82
structure of a n-ary TREE node
Definition n_trees.h:68
Union to store the coordinate values.
Definition n_trees.h:112
Common headers and low-level functions & define.
Generic log system.
N_STR and string function declaration.
int determine_octant(POINT3D point, POINT3D center, int type)
function to determine the octant for the given point relative to the node
Definition n_trees.c:402
void insert_octree_node(OCTREE_NODE *node, POINT3D point, void *data_ptr, int type)
recursive function to insert a point into the OCTREE
Definition n_trees.c:427
void print_int(COORD_VALUE val)
print int function
Definition n_trees.c:203
int compare_float(COORD_VALUE a, COORD_VALUE b)
float comparison function
Definition n_trees.c:185
int compare_double(COORD_VALUE a, COORD_VALUE b)
double comparison functions
Definition n_trees.c:195
void print_double(COORD_VALUE val)
print double function
Definition n_trees.c:220
int compare_int(COORD_VALUE a, COORD_VALUE b)
int comparison function
Definition n_trees.c:175
void print_float(COORD_VALUE val)
print float function
Definition n_trees.c:212
trees module headers