]> git.itanic.dy.fi Git - sdl-planets/blob - quadtree.c
72973c8bba7ae35049f087057790db577719edb6
[sdl-planets] / quadtree.c
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 #include "quadtree.h"
5
6 #ifdef DEBUG
7 #define debug 1
8 #else
9 #define debug 0
10 #endif
11
12 static void _trap(int line)
13 {
14         if (debug) {
15                 printf("Trapped from line %d, use debugger to get backtrace\n",
16                         line);
17                 fflush(stdout);
18                 exit(1);
19         }
20 }
21
22 #define trap() _trap(__LINE__)
23
24 static int quadtree_compare_coord(const struct vector *a,
25                                 const struct vector *b)
26 {
27         int up, left;
28
29         up = b->y < a->y;
30         left = b->x < a->x;
31
32         if (up && left)
33                 return 0;
34         if (up && !left)
35                 return 1;
36         if (left)
37                 return 2;
38         return 3;
39 }
40
41 static int quadtree_compare(const struct quadtree *a, const struct quadtree *b)
42 {
43         return quadtree_compare_coord(&a->pos, &b->pos);
44 }
45
46 static void validate_subtree(const struct quadtree *node)
47 {
48         int i, dir;
49         long int children;
50         children = 0;
51
52         if (!node) {
53                 printf("Attempted to validate a null pointer\n");
54                 fflush(stdout);
55                 trap();
56         }
57
58         for (i = 0; i < 4; i++) {
59                 if (!node->child[i])
60                         continue;
61
62                 if (node->child[i]->parent != node) {
63                         printf("%s:%d Fatal! Tree inconsistency detected at "
64                                "child %d %p in node %p, incorrent parent %p\n",
65                                __func__, __LINE__, i, node->child[i], node,
66                                node->child[i]->parent);
67                         fflush(stdout);
68                         trap();
69                 }
70
71                 if (node->parent) {
72                         if (node->child[i] == node->parent) {
73                                 printf("%s:%d Fatal! Tree loop detected "
74                                        "at child %d in node %p\n",
75                                        __func__, __LINE__, i, node);
76                                 fflush(stdout);
77                                 trap();
78                         }
79                 }
80
81                 dir = quadtree_compare(node, node->child[i]);
82
83                 if (dir != i) {
84                         printf("%s:%d Fatal! Spatial inconsistency detected "
85                                 "at child %d in node %p\n"
86                                 "parent: (%f %f), child (%f %f), "
87                                 "dir %d != %d\n",
88                                 __func__, __LINE__, i, node,
89                                 node->pos.x, node->pos.y,
90                                 node->child[i]->pos.x, node->child[i]->pos.y,
91                                 dir, i);
92                         fflush(stdout);
93                         trap();
94                 }
95
96                 children += node->child[i]->children + 1;
97
98                 validate_subtree(node->child[i]);
99         }
100
101         if (node->depth < 0) {
102                 printf("%s:%d Tree statistics inconsistency detected! "
103                        "Negative depth: %ld\n",
104                        __func__, __LINE__, node->depth);
105         }
106
107         if (node->children != children) {
108                 printf("%s:%d Tree statistics inconsistency detected! "
109                        "child count mismatch. Expected %ld, got %ld\n",
110                        __func__, __LINE__, children, node->children);
111                 fflush(stdout);
112                 trap();
113         }
114
115         for (i = 0; i < 4 && node->children; i++) {
116                 if (!node->child[i])
117                         continue;
118
119                 if (node->depth == node->child[i]->depth + 1)
120                         break;
121
122                 if (node->child[i]->depth > node->depth) {
123                         printf("%s:%d Tree statistics inconsistency detected! "
124                                "child depth mismatch %ld > %ld\n",
125                                __func__, __LINE__, node->child[i]->depth,
126                                node->depth);
127                 }
128         }
129
130         if (i == 4) {
131                 printf("%s:%d Tree statistics inconsistency detected! "
132                        "child depth mismatch.",
133                        __func__, __LINE__);
134                 fflush(stdout);
135                 trap();
136         }
137 }
138
139 static void validate_tree(const struct quadtree *node)
140 {
141         int i;
142
143         if (!debug)
144                 return;
145
146         if (!node->parent)
147                 return validate_subtree(node);
148
149         for (i = 0; i < 4; i++)
150                 if (node->parent->child[i] == node)
151                         break;
152
153         if (i == 4) {
154                 printf("%s:%d Tree inconsistency detected! "
155                         "Wrong parent %p for node %p\n",
156                         __func__, __LINE__, node->parent, node);
157                 fflush(stdout);
158                 trap();
159         }
160
161         validate_tree(node->parent);
162 }
163
164 void _quadtree_validate_tree(const struct quadtree *node)
165 {
166         validate_tree(node);
167 }
168
169 static struct quadtree *_quadtree_add(struct quadtree *parent,
170                                 struct quadtree *new)
171 {
172         int ret, i;
173
174         ret = quadtree_compare(parent, new);
175
176         if (ret < 0 || ret >= 4) {
177                 printf("Invalid comparison result of %d\n", ret);
178                 return 0;
179         }
180
181         if (parent->child[ret])
182                 return _quadtree_add(parent->child[ret], new);
183
184         parent->child[ret] = new;
185         new->parent = parent;
186         for (i = 0; i < 4; i++)
187                 new->child[i] = 0;
188
189         return new;
190 }
191
192 static void _recalculate_node_area_stats(struct quadtree *node)
193 {
194                 /* The space covered by the parent node's corner
195                  * points needs be as wide as its widest child node's
196                  * corners.
197                  */
198 #define CHILD_CORNER_SAFE(node, ch_idx, cor_idx, axis)          \
199         ((node)->child[ch_idx] ?                                \
200                 (node)->child[ch_idx]->corner[cor_idx].axis :   \
201                 (node)->pos.axis)
202
203                 node->corner[0].x = MIN(CHILD_CORNER_SAFE(node, 0, 0, x),
204                                         CHILD_CORNER_SAFE(node, 2, 0, x));
205                 node->corner[0].y = MIN(CHILD_CORNER_SAFE(node, 0, 0, y),
206                                         CHILD_CORNER_SAFE(node, 1, 0, y));
207                 node->corner[1].x = MAX(CHILD_CORNER_SAFE(node, 1, 1, x),
208                                         CHILD_CORNER_SAFE(node, 3, 1, x));
209                 node->corner[1].y = MAX(CHILD_CORNER_SAFE(node, 2, 1, y),
210                                         CHILD_CORNER_SAFE(node, 3, 1, y));
211 #undef CHILD_CORNER_SAFE
212 }
213
214 static void recalculate_parent_area_stats(struct quadtree *node)
215 {
216         while (node) {
217                 _recalculate_node_area_stats(node);
218
219                 node = node->parent;
220         }
221 }
222
223 /*
224  * Recursively walk through the tree and propagate changes made to the
225  * given node up until the highest parent.
226  */
227 static void quadtree_recalculate_parent_stats(struct quadtree *node,
228                                                      struct quadtree_ops *ops)
229 {
230         int i;
231
232         while (node) {
233                 node->depth = 0;
234                 node->children = 0;
235
236                 for (i = 0; i < 4; i++) {
237                         if (!node->child[i])
238                                 continue;
239
240                         node->depth = MAX(node->depth,
241                                           node->child[i]->depth + 1);
242                         node->children += node->child[i]->children + 1;
243                 }
244
245                 _recalculate_node_area_stats(node);
246
247                 if (ops->recalculate_stats)
248                         ops->recalculate_stats(node);
249
250                 node = node->parent;
251         }
252 }
253
254 /**
255  * quadtree_add - add a node to a quadtree
256  * @parent: parent node
257  * @new: the new node to be added
258  *
259  * Add a node to a quadtree. The tree is kept in order, the new node
260  * is placed in the end of appropriate branch.
261  *
262  * The case of nodes sharing identical coordinates is not taken into
263  * account at all.
264  */
265
266 struct quadtree *quadtree_add(struct quadtree *parent, struct quadtree *new,
267                               struct quadtree_ops *ops)
268 {
269         if (parent == new)
270                 trap();
271
272         validate_tree(parent);
273
274         _quadtree_add(parent, new);
275
276         if (debug) {
277                 printf("adding node %p to parent %p\n", new, parent);
278                 fflush(stdout);
279         }
280
281         quadtree_recalculate_parent_stats(new, ops);
282
283         validate_tree(new);
284
285         return new;
286 }
287
288 static int is_within(struct vector *pos, struct vector *corner)
289 {
290         if ((pos->x >= corner[1].x) && (pos->x <= corner[0].x) &&
291             (pos->y >= corner[1].y) && (pos->y <= corner[0].y))
292                 return 1;
293         return 0;
294 }
295
296 static int rectangle_and_circle_overlap(struct vector *corner,
297                                         struct vector *pos, double radius)
298 {
299         int vertically_overlapping = 0, horizontally_overlapping = 0;
300
301         if ((pos->x < corner[1].x && pos->x + radius > corner[0].x) ||
302             (pos->x > corner[0].x && pos->x - radius < corner[1].x))
303                 horizontally_overlapping = 1;
304
305         if ((pos->y < corner[1].y && pos->y + radius > corner[0].y) ||
306             (pos->y > corner[0].y && pos->y - radius < corner[1].y))
307                 vertically_overlapping = 1;
308
309         return horizontally_overlapping && vertically_overlapping;
310 }
311
312 static int quadrants_to_search(struct quadtree *node, struct vector *pos,
313                         double dist)
314 {
315         int direction = 0;
316
317         if (dist <= 0)
318                 return 0xf;
319
320         if (node->child[0] &&
321                 rectangle_and_circle_overlap(node->child[0]->corner, pos, dist))
322                 direction |= QUADTREE_UPLEFT;
323
324         if (node->child[1] &&
325                 rectangle_and_circle_overlap(node->child[1]->corner, pos, dist))
326                 direction |= QUADTREE_UPRIGHT;
327
328         if (node->child[2] &&
329                 rectangle_and_circle_overlap(node->child[2]->corner, pos, dist))
330                 direction |= QUADTREE_DOWNLEFT;
331
332         if (node->child[3] &&
333                 rectangle_and_circle_overlap(node->child[3]->corner, pos, dist))
334                 direction |= QUADTREE_DOWNRIGHT;
335
336         return direction;
337 }
338
339 static struct quadtree *quadtree_find_nearest(struct quadtree *tree,
340                                         struct vector *pos,
341                                         struct vector *corner,
342                                         struct quadtree *nearest,
343                                         int depth)
344 {
345         struct vector tmp;
346         struct quadtree *node;
347         double distance = 0, dist;
348         int i, directions;
349
350         if (nearest == NULL)
351                 nearest = tree;
352
353         vector_sub(&nearest->pos, pos, &tmp);
354         distance = vector_abs(&tmp);
355
356         if (tree != nearest) {
357                 vector_sub(&tree->pos, pos, &tmp);
358                 dist = vector_abs(&tmp);
359                 if (dist < distance) {
360                         nearest = tree;
361                         distance = dist;
362                 }
363         }
364
365         if (!is_within(&nearest->pos, corner)) {
366                 if (debug)
367                         printf("Discarding nearest %p "
368                                 "as outside of search window\n", nearest);
369                 nearest = NULL;
370                 distance = -1;
371         }
372
373         directions = quadrants_to_search(tree, pos, distance);
374         if (debug)
375                 printf("%d: Directions: %x\n", depth, directions);
376         for (i = 0; i < 4; i++) {
377                 if (!tree->child[i])
378                         continue;
379
380                 if (!(directions & (1 << i)))
381                         continue;
382
383
384                 node = quadtree_find_nearest(tree->child[i], pos, corner,
385                                         nearest, depth + 1);
386
387                 if (!node)
388                         continue;
389
390                 if (node != nearest) {
391                         vector_sub(&node->pos, pos, &tmp);
392                         dist = vector_abs(&tmp);
393                         if (dist < distance || !nearest) {
394                                 nearest = node;
395                                 distance = dist;
396                         }
397                         /*
398                          * Update the directions where to search for
399                          * since those may not be valid any more
400                          */
401                         directions = quadrants_to_search(tree, pos, distance);
402                         continue;
403                 }
404         }
405
406         if (nearest && !is_within(&nearest->pos, corner)) {
407                 if (debug)
408                         printf("%d: Node %p (%f %f) is not within "
409                                 "search window (%f %f) (%f %f)\n", depth,
410                                 nearest, nearest->pos.x, nearest->pos.y,
411                                 corner[0].x, corner[0].y,
412                                 corner[1].x, corner[1].y);
413                 return NULL;
414         }
415         if (debug)
416                 printf("%d: Node %p (%f %f) is nearest node, dist %f\n",
417                         depth, nearest,
418                         nearest ? nearest->pos.x : -1,
419                         nearest ? nearest->pos.y : -1,
420                         nearest ? distance : -1);
421         return nearest;
422 }
423
424 static struct quadtree *quadtree_find_nearest_noparent(struct quadtree *tree,
425                                                 struct vector *pos,
426                                                 struct vector *corner)
427 {
428         struct quadtree *nearest = NULL;
429         struct vector sub;
430         struct quadtree *node;
431         double dist = 0, dist2;
432         int i;
433
434         nearest = quadtree_find_nearest(tree, pos, corner, nearest, 0);
435
436         if (nearest != tree)
437                 goto out;
438
439         if (debug)
440                 printf("Avoiding parent or NULL node %p\n", nearest);
441
442         /*
443          * oops, we don't want to pick the parent node, let's choose
444          * another one
445          */
446         nearest = NULL;
447         for (i = 0; i < 4; i++) {
448                 if (!tree->child[i])
449                         continue;
450
451                 if (!nearest) {
452                         nearest = quadtree_find_nearest(tree->child[i], pos,
453                                                         corner, nearest, 0);
454
455                         if (nearest == NULL)
456                                 continue;
457
458                         vector_sub(pos, &nearest->pos, &sub);
459                         dist = vector_abs(&sub);
460                         continue;
461                 }
462                 node = quadtree_find_nearest(tree->child[i], pos, corner,
463                                         nearest, 0);
464
465                 if (node == NULL)
466                         continue;
467
468                 vector_sub(pos, &node->pos, &sub);
469                 dist2 = vector_abs(&sub);
470
471                 if (dist2 < dist) {
472                         nearest = node;
473                         dist = dist2;
474                 }
475         }
476
477 out:
478         return nearest;
479 }
480
481 static void get_middle_point(struct vector *corner, struct vector *middle)
482 {
483         middle->x = (corner[0].x + corner[1].x) / (double)2;
484         middle->y = (corner[0].y + corner[1].y) / (double)2;
485 }
486
487 static int quadtree_split_by_node(struct quadtree *node,
488                                 struct vector *corner, int dir)
489 {
490         if (!is_within(&node->pos, corner)) {
491                 if (debug)
492                         printf("Not within search rectangle\n");
493                 return 0;
494         }
495
496         if (debug)
497                 printf("Search rectangle was before (%f %f) (%f %f), (%f %f)\n",
498                         corner[0].x, corner[0].y,
499                         corner[1].x, corner[1].y,
500                         node->pos.x, node->pos.y);
501
502         switch (dir) {
503         case QUADTREE_UPLEFT:
504                 corner[0] = node->pos;
505                 break;
506         case QUADTREE_UPRIGHT:
507                 corner[0].y = node->pos.y;
508                 corner[1].x = node->pos.x;
509                 break;
510         case QUADTREE_DOWNRIGHT:
511                 corner[1] = node->pos;
512                 break;
513         case QUADTREE_DOWNLEFT:
514                 corner[0].x = node->pos.x;
515                 corner[1].y = node->pos.y;
516                 break;
517         default:
518                 trap();
519         }
520
521         if (debug)
522                 printf("Search rectangle is now (%f %f) (%f %f), (%f %f)\n",
523                         corner[0].x, corner[0].y,
524                         corner[1].x, corner[1].y,
525                         node->pos.x, node->pos.y);
526
527         if ((corner[0].x < corner[1].x) ||
528             (corner[0].y < corner[1].y))
529                 trap();
530
531         return 1;
532 }
533
534 /**
535  * Quickly detach a node from a tree. Move all child nodes under
536  * @parent node.
537  */
538 static int _quadtree_del(struct quadtree *node, struct quadtree *parent)
539 {
540         struct quadtree *n;
541         int i;
542
543         /* Detach from the tree */
544         if (node->parent)
545                 for (i = 0; i < 4; i++) {
546                         if (node->parent->child[i] == node) {
547                                 node->parent->child[i] = 0;
548                                 break;
549                         }
550                 }
551
552         if (i == 4)
553                 trap();
554
555         for (i = 0; i < 4; i++) {
556                 if (!node->child[i])
557                         continue;
558
559                 n = node->child[i];
560                 _quadtree_del(n, parent);
561                 _quadtree_add(parent, n);
562                 recalculate_parent_area_stats(n);
563         }
564
565         return 0;
566 }
567
568 /**
569  * Move everything under @tree node to @parent node, everything
570  * else except the @tree node itself
571  */
572 static int optimally_move_tree(struct quadtree *tree, struct quadtree *parent,
573                         struct vector *corner_orig,
574                         struct quadtree_ops *ops)
575 {
576         struct vector corner[2], mid;
577         struct quadtree *t, *tmp;
578         int moved = 0;
579
580         get_middle_point(corner_orig, &mid);
581         t = quadtree_find_nearest_noparent(tree, &mid, corner_orig);
582
583         if (!t) {
584                 if (debug)
585                         printf("Cannot find nearest node\n");
586
587                 goto out;
588         }
589
590         /*
591          * Now we have the t node which contains the object of the
592          * spatial middle coordinates of the tree.
593          */
594
595         if (debug) {
596                 printf("Relocating node %p (%f %f) under parent %p\n", t,
597                         t->pos.x, t->pos.y, parent);
598                 printf("There are %ld child nodes left\n", tree->children);
599                 fflush(stdout);
600         }
601         _quadtree_del(t, tree);
602         quadtree_add(parent, t, ops);
603
604         moved++;
605         tree->children--;
606         if (!tree->children)
607                 goto out;
608
609         /*
610          * Now split the search rectangle in quadtres and do the same
611          * with all of the quarters.
612          */
613
614         corner[0] = corner_orig[0];
615         corner[1] = corner_orig[1];
616         if (quadtree_split_by_node(t, corner, QUADTREE_UPLEFT))
617                 moved += optimally_move_tree(tree, parent, corner, ops);
618
619         corner[0] = corner_orig[0];
620         corner[1] = corner_orig[1];
621         if (quadtree_split_by_node(t, corner, QUADTREE_UPRIGHT))
622                 moved += optimally_move_tree(tree, parent, corner, ops);
623
624         corner[0] = corner_orig[0];
625         corner[1] = corner_orig[1];
626         if (quadtree_split_by_node(t, corner, QUADTREE_DOWNLEFT))
627                 moved += optimally_move_tree(tree, parent, corner, ops);
628
629         corner[0] = corner_orig[0];
630         corner[1] = corner_orig[1];
631         if (quadtree_split_by_node(t, corner, QUADTREE_DOWNRIGHT))
632                 moved += optimally_move_tree(tree, parent, corner, ops);
633
634 out:
635         if (debug)
636                 printf("Now moved %d nodes, %ld left\n", moved, tree->children);
637
638         return moved;
639 }
640
641 /*
642  * quadtree_del - Detach a node from the tree
643  *
644  * Return value: The new root node of the tree. If we are detaching
645  * anything but the root node of the entire tree, the returned root
646  * value will be the original root of the tree.
647  */
648 struct quadtree *quadtree_del(struct quadtree *node,
649                               struct quadtree_ops *ops)
650 {
651         struct quadtree *parent = NULL;
652         struct vector corner[2];
653         int i, children = node->children, moved;
654
655         validate_tree(node);
656
657         if (debug) {
658                 printf("Deleting node %p under parent %p\n",
659                                node, node->parent);
660                 printf("Relocating %ld children\n", node->children);
661                 fflush(stdout);
662         }
663
664         if (!node->parent) {
665                 /*
666                  * We are deleting the root node. This means we have
667                  * to select a new root node and reconstruct the
668                  * entire tree under it again.
669                  */
670                 if (debug) {
671                         printf("Deleting root node\n");
672                         fflush(stdout);
673                 }
674                 for (i = 0; i < 4; i++) {
675                         if (!node->child[i])
676                                 continue;
677
678                         parent = node->child[i];
679                         _quadtree_del(parent, node);
680                         parent->parent = 0;
681                         quadtree_recalculate_parent_stats(parent, ops);
682                         break;
683                 }
684         } else {
685                 /*
686                  * The node has a parent. Detach the node from it and
687                  * relocate the children.
688                  */
689
690                 for (i = 0; i < 4; i++) {
691                         if (node->parent->child[i] == node) {
692                                 node->parent->child[i] = 0;
693                                 break;
694                         }
695                 }
696                 if (i == 4)
697                         trap();
698
699                 parent = node->parent;
700                 node->parent = NULL;
701
702                 /*
703                  * The sub branch is now detached from the main
704                  * tree. Fix the stats.
705                  */
706                 quadtree_recalculate_parent_stats(parent, ops);
707         }
708
709         validate_tree(parent);
710
711         if (!node->children)
712                 goto out;
713         /*
714          * Now we are ready to prepare for relocating the nodes under
715          * the parent.
716          */
717
718         corner[0] = node->corner[1];
719         corner[1] = node->corner[0];
720         if (debug) {
721                 printf("\nInitial Search rectangle (%f %f) (%f %f), (%f %f)\n",
722                         corner[0].x, corner[0].y,
723                         corner[1].x, corner[1].y,
724                         node->pos.x, node->pos.y);
725                 fflush(stdout);
726         }
727         moved = optimally_move_tree(node, parent, corner, ops);
728
729         if (debug) {
730                 if (moved != children) {
731                         printf("Got %d children but %d were moved\n",
732                                 children, moved);
733                         printf("nearest children left:\n");
734                         for (i = 0 ; i < 4; i++)
735                                 if (node->child[i])
736                                         printf("   node %d %p, (%f %f)\n",
737                                                 i, node->child[i],
738                                                 node->child[i]->pos.x,
739                                                 node->child[i]->pos.y);
740                         fflush(stdout);
741                         trap();
742                 }
743                 printf("Delete done, returning parent %p\n", parent);
744                 fflush(stdout);
745         }
746
747 out:
748         validate_tree(parent);
749         return quadtree_find_parent(parent);
750 }
751
752 static void check_for_crossed_subnodes(struct quadtree *node,
753                                 struct vector *limit, struct quadtree_ops *ops)
754 {
755         int direction = 0, i;
756         int up = 0, left = 0, right = 0, down = 0;
757
758         for (i = 0; i < 2; i++) {
759                 if (limit[i].x < node->pos.x)
760                         left = 1;
761                 else
762                         right = 1;
763                 if (limit[i].y < node->pos.y)
764                         up = 1;
765                 else
766                         down = 1;
767         }
768
769         if (left || up)
770                 direction |= QUADTREE_UPLEFT;
771         if (right || up)
772                 direction |= QUADTREE_UPRIGHT;
773         if (left || down)
774                 direction |= QUADTREE_DOWNLEFT;
775         if (right || down)
776                 direction |= QUADTREE_DOWNRIGHT;
777         if ((left && right) || (up && down))
778                 direction |= QUADTREE_SELF;
779
780         if ((direction & QUADTREE_UPLEFT) && node->child[0])
781                 check_for_crossed_subnodes(node->child[0], limit, ops);
782
783         if ((direction & QUADTREE_UPRIGHT) && node->child[1])
784                 check_for_crossed_subnodes(node->child[0], limit, ops);
785
786         if ((direction & QUADTREE_DOWNLEFT) && node->child[2])
787                 check_for_crossed_subnodes(node->child[0], limit, ops);
788
789         if ((direction & QUADTREE_DOWNRIGHT) && node->child[3])
790                 check_for_crossed_subnodes(node->child[0], limit, ops);
791
792         if (direction & QUADTREE_SELF) {
793                 struct quadtree *parent;
794
795                 parent = quadtree_del(node, ops);
796                 quadtree_add(parent, node, ops);
797         }
798 }
799
800 struct quadtree *quadtree_move(struct quadtree *node, struct vector new_pos,
801                         struct quadtree_ops *ops)
802 {
803         struct quadtree *parent, *tree_parent;
804         int modify;
805
806         /* Check if we have crossed any of the parents */
807         parent = node->parent;
808         while (parent) {
809                 if (node->pos.x < parent->pos.x && new_pos.x > parent->pos.x)
810                         modify = 1;
811                 if (node->pos.x > parent->pos.x && new_pos.x < parent->pos.x)
812                         modify = 1;
813                 if (node->pos.y < parent->pos.y && new_pos.y > parent->pos.y)
814                         modify = 1;
815                 if (node->pos.y > parent->pos.y && new_pos.y < parent->pos.y)
816                         modify = 1;
817
818                 if (!modify) {
819                         parent = parent->parent;
820                         continue;
821                 }
822
823                 /*
824                  * If the node has crossed the boundaries, remove it
825                  * from the tree and add it again to it. It is then
826                  * guaranteed to be in the correct position of the
827                  * tree.
828                  */
829                 tree_parent = quadtree_del(node, ops);
830                 node->pos = new_pos;
831                 quadtree_add(tree_parent, node, ops);
832                 return tree_parent;
833         }
834
835         /* Move the node into its new location */
836         node->pos = new_pos;
837         recalculate_parent_area_stats(node);
838
839         if (node->children) {
840                 /*
841                  * Now, search the subtree for any children that are
842                  * located in wrong place and move them into correct
843                  * place within the tree.
844                  */
845                 struct vector limit[2];
846
847                 limit[0] = node->pos;
848                 limit[1] = new_pos;
849                 check_for_crossed_subnodes(node, limit, ops);
850         }
851
852         return quadtree_find_parent(node);
853
854 }
855
856 static int _walk_tree(struct quadtree *head, const struct quadtree_iterator *it)
857 {
858         int direction, count = 0;
859
860         direction = it->direction(head, (struct quadtree_iterator *)it);
861
862         if ((direction & QUADTREE_UPLEFT) && head->child[0])
863                 count += _walk_tree(head->child[0], it);
864
865         if ((direction & QUADTREE_UPRIGHT) && head->child[1])
866                 count += _walk_tree(head->child[1], it);
867
868         if ((direction & QUADTREE_DOWNLEFT) && head->child[2])
869                 count += _walk_tree(head->child[2], it);
870
871         if ((direction & QUADTREE_DOWNRIGHT) && head->child[3])
872                 count += _walk_tree(head->child[3], it);
873
874         if ((direction & QUADTREE_SELF) && it->callback) {
875                 it->callback(head, (struct quadtree_iterator *)it);
876                 count++;
877         }
878
879         return count;
880 }
881
882 int walk_quadtree(const struct quadtree_iterator *it)
883 {
884         return _walk_tree(it->head, it);
885 }