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 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * permissions and limitations under the License.
16 *
17 * SPDX-License-Identifier: Apache-2.0
18 */
19
28#include <stdlib.h>
29#include <string.h>
30#include <pthread.h>
31
32#include "nilorea/n_common.h"
33#include "nilorea/n_log.h"
34#include "nilorea/n_str.h"
35#include "nilorea/n_trees.h"
36
42 TREE* tree = NULL;
43 Malloc(tree, TREE, 1);
44 __n_assert(tree, n_log(LOG_ERR, "Failed to allocate memory for tree"); return NULL;);
45
46 tree->root = NULL;
47 tree->nb_nodes = 0;
48 tree->height = 0;
49 pthread_rwlock_init(&(tree->rwlock), NULL);
50
51 return tree;
52}
53
60TREE_NODE* tree_create_node(NODE_DATA value, void (*destroy_func)(void* ptr)) {
61 TREE_NODE* node = (TREE_NODE*)malloc(sizeof(TREE_NODE));
62 if (node == NULL) {
63 n_log(LOG_ERR, "Failed to allocate memory for tree node");
64 return NULL;
65 }
66
67 node->data = value;
68 node->destroy_func = destroy_func;
69 node->parent_list_node = NULL;
70 node->parent = NULL;
72 if (!node->children) {
73 Free(node);
74 return NULL;
75 }
76
77 return node;
78}
79
87 if (parent == NULL || child == NULL) {
88 return FALSE;
89 }
90
91 if (parent->children == NULL) {
93 __n_assert(parent->children, n_log(LOG_ERR, "Failed to create parent->children list"); return FALSE;);
94 }
95
96 LIST_NODE* node = new_list_node(child, NULL);
97 __n_assert(node, n_log(LOG_ERR, "Failed to create child node"); return FALSE;);
98
99 if (!list_node_push(parent->children, node)) {
100 if (node->destroy_func != NULL) {
101 node->destroy_func(node->ptr);
102 }
103 Free(node);
104 return FALSE;
105 }
106
107 child->parent_list_node = node;
108 child->parent = parent;
109
110 return TRUE;
111}
112
119int tree_delete_node(TREE* tree, TREE_NODE* node) {
120 if (tree == NULL || node == NULL) {
121 return FALSE;
122 }
123
124 // Recursively delete child nodes
125 LIST_NODE* child_node = node->children->start;
126 while (child_node) {
127 LIST_NODE* next_node = child_node->next;
128 TREE_NODE* child = (TREE_NODE*)child_node->ptr;
129 tree_delete_node(tree, child);
130 child_node = next_node;
131 }
132 list_destroy(&node->children);
133
134 // Remove the node from its parent's child list, if applicable
135 if (node->parent && node->parent->children) {
137 }
138
139 // Free node data if necessary
140 if (node->destroy_func) {
141 node->destroy_func(node->data.value.ptr);
142 }
143
144 // Free the node itself
145 free(node);
146 tree->nb_nodes--;
147
148 return TRUE;
149}
150
155void tree_destroy(TREE** tree) {
156 if (tree == NULL || *tree == NULL) {
157 return;
158 }
159
160 TREE_NODE* root = (*tree)->root;
161 if (root != NULL) {
162 tree_delete_node(*tree, root);
163 }
164
165 pthread_rwlock_destroy(&((*tree)->rwlock));
166 free(*tree);
167 *tree = NULL;
168}
169
177 return (a.i > b.i) - (a.i < b.i);
178}
179
187 return (a.f > b.f) - (a.f < b.f);
188}
189
197 return (a.d > b.d) - (a.d < b.d);
198}
199
205 printf("%d", val.i);
206}
207
214 printf("%f", val.f);
215}
216
222 printf("%lf", val.d);
223}
224
230QUADTREE* create_quadtree(int coord_type) {
231 QUADTREE* qt = (QUADTREE*)calloc(1, sizeof(QUADTREE));
232 if (!qt) {
233 n_log(LOG_ERR, "Failed to allocate QUADTREE");
234 return NULL;
235 }
236
237 qt->coord_type = coord_type;
238 qt->root = NULL;
239
240 switch (coord_type) {
241 case COORD_INT:
242 qt->compare = compare_int;
243 qt->print = print_int;
244 break;
245 case COORD_FLOAT:
247 qt->print = print_float;
248 break;
249 case COORD_DOUBLE:
251 qt->print = print_double;
252 break;
253 default:
254 qt->compare = NULL;
255 qt->print = NULL;
256 n_log(LOG_ERR, "Unknown coord_type %d", coord_type);
257 Free(qt);
258 return NULL;
259 }
260
261 return qt;
262}
263
272 QUADTREE_NODE* node = (QUADTREE_NODE*)malloc(sizeof(QUADTREE_NODE));
273 if (!node) {
274 n_log(LOG_ERR, "Failed to allocate QUADTREE_NODE");
275 return NULL;
276 }
277 node->x = x;
278 node->y = y;
279 node->data_ptr = data_ptr;
280 node->nw = NULL;
281 node->ne = NULL;
282 node->sw = NULL;
283 node->se = NULL;
284 return node;
285}
286
295void insert(QUADTREE* qt, QUADTREE_NODE** root, COORD_VALUE x, COORD_VALUE y, void* data_ptr) {
296 __n_assert(qt, return);
297
298 if (*root == NULL) {
299 *root = create_node(x, y, data_ptr);
300 __n_assert(*root, n_log(LOG_ERR, "Failed to create node"); return);
301 return;
302 }
303
304 if (qt->compare(x, (*root)->x) < 0 && qt->compare(y, (*root)->y) < 0) {
305 insert(qt, &((*root)->sw), x, y, data_ptr);
306 } else if (qt->compare(x, (*root)->x) < 0 && qt->compare(y, (*root)->y) >= 0) {
307 insert(qt, &((*root)->nw), x, y, data_ptr);
308 } else if (qt->compare(x, (*root)->x) >= 0 && qt->compare(y, (*root)->y) < 0) {
309 insert(qt, &((*root)->se), x, y, data_ptr);
310 } else if (qt->compare(x, (*root)->x) >= 0 && qt->compare(y, (*root)->y) >= 0) {
311 insert(qt, &((*root)->ne), x, y, data_ptr);
312 }
313}
314
324 if (root == NULL || (qt->compare(root->x, x) == 0 && qt->compare(root->y, y) == 0)) {
325 return root;
326 }
327
328 if (qt->compare(x, root->x) < 0 && qt->compare(y, root->y) < 0) {
329 return search(qt, root->sw, x, y);
330 } else if (qt->compare(x, root->x) < 0 && qt->compare(y, root->y) >= 0) {
331 return search(qt, root->nw, x, y);
332 } else if (qt->compare(x, root->x) >= 0 && qt->compare(y, root->y) < 0) {
333 return search(qt, root->se, x, y);
334 } else if (qt->compare(x, root->x) >= 0 && qt->compare(y, root->y) >= 0) {
335 return search(qt, root->ne, x, y);
336 }
337
338 return NULL; // Should not reach here
339}
340
346 __n_assert(root, return);
347
348 free_quadtree(root->nw);
349 free_quadtree(root->ne);
350 free_quadtree(root->sw);
351 free_quadtree(root->se);
352
353 free(root);
354}
355
362OCTREE_NODE* create_octree_node(POINT3D point, void* data_ptr) {
363 OCTREE_NODE* node = (OCTREE_NODE*)malloc(sizeof(OCTREE_NODE));
364 if (!node) {
365 n_log(LOG_ERR, "Failed to allocate OCTREE_NODE");
366 return NULL;
367 }
368
369 node->point = point;
370 node->data_ptr = data_ptr;
371 for (int i = 0; i < 8; i++) {
372 node->children[i] = NULL;
373 }
374
375 return node;
376}
377
384 OCTREE* octree = (OCTREE*)malloc(sizeof(OCTREE));
385 if (!octree) {
386 n_log(LOG_ERR, "Failed to allocate OCTREE");
387 return NULL;
388 }
389
390 octree->root = NULL;
391 octree->coord_type = type;
392
393 return octree;
394}
395
403int determine_octant(POINT3D point, POINT3D center, int type) {
404 int octant = 0;
405 if (type == COORD_INT) {
406 if (point.x.i >= center.x.i) octant |= 4;
407 if (point.y.i >= center.y.i) octant |= 2;
408 if (point.z.i >= center.z.i) octant |= 1;
409 } else if (type == COORD_FLOAT) {
410 if (point.x.f >= center.x.f) octant |= 4;
411 if (point.y.f >= center.y.f) octant |= 2;
412 if (point.z.f >= center.z.f) octant |= 1;
413 } else if (type == COORD_DOUBLE) {
414 if (point.x.d >= center.x.d) octant |= 4;
415 if (point.y.d >= center.y.d) octant |= 2;
416 if (point.z.d >= center.z.d) octant |= 1;
417 }
418 return octant;
419}
420
428void insert_octree_node(OCTREE_NODE* node, POINT3D point, void* data_ptr, int type) {
429 int octant = determine_octant(point, node->point, type);
430 if (!node->children[octant]) {
431 node->children[octant] = create_octree_node(point, data_ptr);
432 } else {
433 insert_octree_node(node->children[octant], point, data_ptr, type);
434 }
435}
436
443void insert_octree(OCTREE* octree, POINT3D point, void* data_ptr) {
444 if (!octree->root) {
445 octree->root = create_octree_node(point, data_ptr);
446 } else {
447 insert_octree_node(octree->root, point, data_ptr, octree->coord_type);
448 }
449}
450
456 if (node) {
457 for (int i = 0; i < 8; i++) {
458 free_octree_node(node->children[i]);
459 }
460 free(node);
461 }
462}
463
468void free_octree(OCTREE* octree) {
469 if (octree) {
470 free_octree_node(octree->root);
471 free(octree);
472 }
473}
#define Malloc(__ptr, __struct, __size)
Malloc Handler to get errors and set to 0.
Definition n_common.h:204
#define __n_assert(__ptr, __ret)
macro to assert things
Definition n_common.h:279
#define Free(__ptr)
Free Handler to get errors.
Definition n_common.h:263
void * ptr
void pointer to store
Definition n_list.h:46
LIST_NODE * start
pointer to the start of the list
Definition n_list.h:66
void(* destroy_func)(void *ptr)
pointer to destructor function if any, else NULL
Definition n_list.h:49
struct LIST_NODE * next
pointer to the next node
Definition n_list.h:52
LIST_NODE * new_list_node(void *ptr, void(*destructor)(void *ptr))
Allocate a new node to link in a list.
Definition n_list.c:57
int list_destroy(LIST **list)
Empty and Free a list container.
Definition n_list.c:548
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:76
LIST * new_generic_list(size_t max_items)
Initialiaze a generic list container to max_items pointers.
Definition n_list.c:37
#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:75
int list_node_push(LIST *list, LIST_NODE *node)
Add a filled node to the end of the list.
Definition n_list.c:117
Structure of a generic list node.
Definition n_list.h:44
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:89
#define LOG_ERR
error conditions
Definition n_log.h:76
print_func print
pointer to print function
Definition n_trees.h:171
compare_func compare
pointer to comparison function
Definition n_trees.h:169
TREE_NODE * root
pointer to first node
Definition n_trees.h:85
pthread_rwlock_t rwlock
mutex for thread safety (optional)
Definition n_trees.h:87
struct QUADTREE_NODE * nw
North-West child.
Definition n_trees.h:155
int coord_type
type of coordinate used in the quad tree
Definition n_trees.h:167
size_t nb_nodes
number of nodes in the tree
Definition n_trees.h:89
COORD_VALUE z
z coordinate
Definition n_trees.h:136
double d
Definition n_trees.h:116
void * data_ptr
Pointer to additional data, can be NULL.
Definition n_trees.h:192
OCTREE_NODE * root
tree list first node
Definition n_trees.h:200
COORD_VALUE y
Y coordinate.
Definition n_trees.h:149
QUADTREE_NODE * root
tree list first node
Definition n_trees.h:173
union NODE_DATA_TYPES value
node value
Definition n_trees.h:63
NODE_DATA data
structure holding values for node
Definition n_trees.h:71
struct QUADTREE_NODE * sw
South-West child.
Definition n_trees.h:159
COORD_VALUE x
x coordinate
Definition n_trees.h:132
float f
Definition n_trees.h:115
void * ptr
pointer type
Definition n_trees.h:53
void * data_ptr
Pointer to data, can be NULL.
Definition n_trees.h:153
struct QUADTREE_NODE * se
South-East child.
Definition n_trees.h:161
POINT3D point
Point represented by this node.
Definition n_trees.h:190
struct QUADTREE_NODE * ne
North-East child.
Definition n_trees.h:157
void(* destroy_func)(void *ptr)
value destructor if of type ptr and specified, else a simple free will be used
Definition n_trees.h:73
COORD_VALUE y
y coordinate
Definition n_trees.h:134
COORD_VALUE x
X coordinate.
Definition n_trees.h:147
struct OCTREE_NODE * children[8]
Child nodes.
Definition n_trees.h:194
LIST_NODE * parent_list_node
pointer to parent container of the TREE_NODE, LIST_NODE
Definition n_trees.h:77
struct TREE_NODE * parent
pointer to parent
Definition n_trees.h:75
size_t height
height of the tree
Definition n_trees.h:91
LIST * children
ordered list of children
Definition n_trees.h:79
int coord_type
Coordinate type for the entire tree.
Definition n_trees.h:202
void free_octree_node(OCTREE_NODE *node)
recursive function to free an OCTREE node and its children
Definition n_trees.c:455
void insert_octree(OCTREE *octree, POINT3D point, void *data_ptr)
Insert a point into the OCTREE.
Definition n_trees.c:443
int tree_insert_child(TREE_NODE *parent, TREE_NODE *child)
insert a child node into the parent node
Definition n_trees.c:86
void free_quadtree(QUADTREE_NODE *root)
Function to free the quad tree.
Definition n_trees.c:345
TREE * new_tree()
create a new TREE
Definition n_trees.c:41
TREE_NODE * tree_create_node(NODE_DATA value, void(*destroy_func)(void *ptr))
create a TREE node
Definition n_trees.c:60
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:323
void free_octree(OCTREE *octree)
free the OCTREE
Definition n_trees.c:468
void tree_destroy(TREE **tree)
destroy a TREE
Definition n_trees.c:155
OCTREE_NODE * create_octree_node(POINT3D point, void *data_ptr)
create and OCTREE node
Definition n_trees.c:362
OCTREE * create_octree(int type)
Create a new OCTREE with a specified coordinate type.
Definition n_trees.c:383
int tree_delete_node(TREE *tree, TREE_NODE *node)
delete a TREE node
Definition n_trees.c:119
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:295
QUADTREE * create_quadtree(int coord_type)
Function to create a new quad tree.
Definition n_trees.c:230
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:271
@ COORD_INT
Definition n_trees.h:107
@ COORD_DOUBLE
Definition n_trees.h:109
@ COORD_FLOAT
Definition n_trees.h:108
structure of a TREE node data
Definition n_trees.h:61
structure of an OCTREE
Definition n_trees.h:198
structure of an OCTREE node
Definition n_trees.h:188
Structure for a POINT3D in the 3D space.
Definition n_trees.h:129
structure of a quad tree
Definition n_trees.h:165
structure of a quad tree node
Definition n_trees.h:145
structure of a TREE
Definition n_trees.h:83
structure of a n-ary TREE node
Definition n_trees.h:69
Union to store the coordinate values.
Definition n_trees.h:113
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:403
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:428
void print_int(COORD_VALUE val)
print int function
Definition n_trees.c:204
int compare_float(COORD_VALUE a, COORD_VALUE b)
float comparison function
Definition n_trees.c:186
int compare_double(COORD_VALUE a, COORD_VALUE b)
double comparison functions
Definition n_trees.c:196
void print_double(COORD_VALUE val)
print double function
Definition n_trees.c:221
int compare_int(COORD_VALUE a, COORD_VALUE b)
int comparison function
Definition n_trees.c:176
void print_float(COORD_VALUE val)
print float function
Definition n_trees.c:213
trees module headers