GRASS 8 Programmer's Manual 8.6.0dev(2026)-c83afef6d3
Loading...
Searching...
No Matches
kdtree.h
Go to the documentation of this file.
1/*!
2 * \file kdtree.h
3 *
4 * \brief Dynamic balanced k-d tree implementation
5 *
6 * k-d tree is a multidimensional (k-dimensional) binary search tree for
7 * nearest neighbor search and is part of \ref btree2.
8 *
9 * Copyright and license:
10 *
11 * SPDX-FileCopyrightText: 2014 GRASS Development Team
12 * SPDX-License-Identifier: GPL-2.0-or-later
13 *
14 * \author Markus Metz
15 *
16 * \par References
17 * Bentley, J. L. (1975). "Multidimensional binary search trees used for
18 * associative searching". Communications of the ACM 18 (9): 509.
19 * doi:10.1145/361002.361007
20 *
21 * \par Features
22 * - This k-d tree is a dynamic tree:
23 * elements can be inserted and removed any time.
24 * - This k-d tree is balanced:
25 * subtrees have a similar depth (the difference in subtrees' depths is
26 * not allowed to be larger than the balancing tolerance).
27 *
28 * Here is a structure of basic usage:
29 *
30 * Create a new k-d tree:
31 *
32 * kdtree_create(...);
33 *
34 * Insert points into the tree:
35 *
36 * kdtree_insert(...);
37 *
38 * Optionally optimize the tree:
39 *
40 * kdtree_optimize(...);
41 *
42 * Search k nearest neighbors:
43 *
44 * kdtree_knn(...);
45 *
46 * Search all neighbors in radius:
47 *
48 * kdtree_dnn(...);
49 *
50 * Destroy the tree:
51 *
52 * kdtree_destroy(...);
53 *
54 * \todo
55 * Doxygen ignores comment for last parameter after `);`.
56 * The parameter description now goes to the end of function description.
57 *
58 * \todo
59 * Include formatting to function descriptions.
60 */
61
62/*!
63 * \brief Node for k-d tree
64 */
65struct kdnode {
66 unsigned char dim; /*!< split dimension of this node */
67 unsigned char depth; /*!< depth at this node */
68 unsigned char balance; /*!< flag to indicate if balancing is needed */
69 double *c; /*!< coordinates */
70 int uid; /*!< unique id of this node */
71 struct kdnode
72 *child[2]; /*!< link to children: `[0]` for smaller, `[1]` for larger */
73};
74
75/*!
76 * \brief k-d tree
77 */
78struct kdtree {
79 unsigned char ndims; /*!< number of dimensions */
80 unsigned char *nextdim; /*!< split dimension of child nodes */
81 int csize; /*!< size of coordinates in bytes */
82 int btol; /*!< balancing tolerance */
83 size_t count; /*!< number of items in the tree */
84 struct kdnode *root; /*!< tree root */
85};
86
87/*!
88 * \brief k-d tree traversal
89 */
90struct kdtrav {
91 struct kdtree *tree; /*!< tree being traversed */
92 struct kdnode *curr_node; /*!< current node */
93 struct kdnode *up[256]; /*!< stack of parent nodes */
94 int top; /*!< index for stack */
95 int first; /*!< little helper flag */
96};
97
98/*! create a new k-d tree */
99struct kdtree *kdtree_create(char ndims, /*!< number of dimensions */
100 int *btol /*!< optional balancing tolerance */
101);
102
103/*! destroy a tree */
104void kdtree_destroy(struct kdtree *t);
105
106/*! clear a tree, removing all entries */
107void kdtree_clear(struct kdtree *t);
108
109/*! insert an item (coordinates c and uid) into the k-d tree */
110int kdtree_insert(struct kdtree *t, /*!< k-d tree */
111 double *c, /*!< coordinates */
112 int uid, /*!< the point's unique id */
113 int dc /*!< allow duplicate coordinates */
114);
115
116/*! remove an item from the k-d tree
117 * coordinates c and uid must match */
118int kdtree_remove(struct kdtree *t, /*!< k-d tree */
119 double *c, /*!< coordinates */
120 int uid /*!< the point's unique id */
121);
122
123/*! find k nearest neighbors
124 * results are stored in uid (uids) and d (squared distances)
125 * optionally an uid to be skipped can be given
126 * useful when searching for the nearest neighbors of an item
127 * that is also in the tree */
128int kdtree_knn(struct kdtree *t, /*!< k-d tree */
129 double *c, /*!< coordinates */
130 int *uid, /*!< unique ids of the neighbors */
131 double *d, /*!< squared distances to the neighbors */
132 int k, /*!< number of neighbors to find */
133 int *skip /*!< unique id to skip */
134);
135
136/*! find all nearest neighbors within distance aka radius search
137 * results are stored in puid (uids) and pd (squared distances)
138 * memory is allocated as needed, the calling fn must free the memory
139 * optionally an uid to be skipped can be given */
140int kdtree_dnn(
141 struct kdtree *t, /*!< k-d tree */
142 double *c, /*!< coordinates */
143 int **puid, /*!< unique ids of the neighbors */
144 double **pd, /*!< squared distances to the neighbors */
145 double maxdist, /*!< radius to search around the given coordinates */
146 int *skip /*!< unique id to skip */
147);
148
149/*! find all nearest neighbors within range aka box search
150 * the range is specified with min and max for each dimension as
151 * (min1, min2, ..., minn, max1, max2, ..., maxn)
152 * results are stored in puid (uids) and pd (squared distances)
153 * memory is allocated as needed, the calling fn must free the memory
154 * optionally an uid to be skipped can be given */
155int kdtree_rnn(struct kdtree *t, /*!< k-d tree */
156 double *c, /*!< coordinates for range */
157 int **puid, /*!< unique ids of the neighbors */
158 int *skip /*!< unique id to skip */
159);
160
161/*! k-d tree optimization, only useful if the tree will be heavily used
162 * (more searches than items in the tree)
163 * level 0 = a bit, 1 = more, 2 = a lot */
164void kdtree_optimize(struct kdtree *t, /*!< k-d tree */
165 int level /*!< optimization level */
166);
167
168/*! initialize tree traversal
169 * (re-)sets trav structure
170 * returns 0
171 */
172int kdtree_init_trav(struct kdtrav *trav, struct kdtree *tree);
173
174/*! traverse the tree
175 * useful to get all items in the tree non-recursively
176 * struct kdtrav *trav needs to be initialized first
177 * returns 1, 0 when finished
178 */
179int kdtree_traverse(struct kdtrav *trav, double *c, int *uid);
void kdtree_optimize(struct kdtree *t, int level)
Definition kdtree.c:332
int kdtree_rnn(struct kdtree *t, double *c, int **puid, int *skip)
Definition kdtree.c:749
struct kdtree * kdtree_create(char ndims, int *btol)
Definition kdtree.c:109
int kdtree_traverse(struct kdtrav *trav, double *c, int *uid)
Definition kdtree.c:860
void kdtree_clear(struct kdtree *t)
Definition kdtree.c:137
int kdtree_insert(struct kdtree *t, double *c, int uid, int dc)
Definition kdtree.c:177
int kdtree_knn(struct kdtree *t, double *c, int *uid, double *d, int k, int *skip)
Definition kdtree.c:510
void kdtree_destroy(struct kdtree *t)
Definition kdtree.c:165
int kdtree_dnn(struct kdtree *t, double *c, int **puid, double **pd, double maxdist, int *skip)
Definition kdtree.c:634
int kdtree_init_trav(struct kdtrav *trav, struct kdtree *tree)
Definition kdtree.c:845
int kdtree_remove(struct kdtree *t, double *c, int uid)
Definition kdtree.c:200
double t
Definition r_raster.c:37
Node for k-d tree.
Definition kdtree.h:65
unsigned char dim
Definition kdtree.h:66
unsigned char balance
Definition kdtree.h:68
unsigned char depth
Definition kdtree.h:67
struct kdnode * child[2]
Definition kdtree.h:71
int uid
Definition kdtree.h:70
double * c
Definition kdtree.h:69
k-d tree traversal
Definition kdtree.h:90
struct kdtree * tree
Definition kdtree.h:91
struct kdnode * curr_node
Definition kdtree.h:92
struct kdnode * up[256]
Definition kdtree.h:93
int top
Definition kdtree.h:94
int first
Definition kdtree.h:95
k-d tree
Definition kdtree.h:78
unsigned char * nextdim
Definition kdtree.h:80
unsigned char ndims
Definition kdtree.h:79
int btol
Definition kdtree.h:82
size_t count
Definition kdtree.h:83
int csize
Definition kdtree.h:81
struct kdnode * root
Definition kdtree.h:84