diff --git a/include/quad.h b/include/quad.h index 94ef915..47a2947 100644 --- a/include/quad.h +++ b/include/quad.h @@ -40,33 +40,25 @@ typedef struct quadtree_t { } quadtree_t; -static bool point_in_rect(point_t* point, rect_t* boundary) { - return point->x >= boundary->x0 && point->x <= boundary->x1 && - point->y >= boundary->y0 && point->y <= boundary->y1; -} - void qtree_new(quadtree_t* qtree, rect_t* boundary); void qtree_del(quadtree_t* qtree); void qtree_insert(quadtree_t* qtree, point_t* point); void qtree_graph(quadtree_t* qtree); void qtree_query(quadtree_t* qtree, rect_t* search_area, int* count); double qtree_nearest_neighbor(quadtree_t* qtree, point_t* query, point_t* nearest); - -node_t* node_new(rect_t* boundary); -void rect_divide(rect_t* src, rect_t* dest); -int point_get_quadrant(rect_t* rect, point_t* point); -bool node_is_leaf(node_t* node); -void node_insert(node_t* node, point_t* point); - -bool rect_intersect(rect_t* r1, rect_t* r2); -void node_query(node_t* node, rect_t* search_area, int* count); - -void node_nearest_neighbor(node_t* node, point_t* query, point_t* nearest, double* best_dist_squared); -double point_to_rect_distance(point_t* p, rect_t* rect); -void node_remove_point(node_t* node, point_t* point); -void node_merge(node_t* node); void qtree_update_point(quadtree_t* qtree, point_t* old_point, point_t* new_point); -void node_del_all(node_t* node); -void node_graph(node_t* node); +void qtree_merge(quadtree_t* qtree); +void qtree_remove_point(quadtree_t* qtree, point_t* point); + +static node_t* node_new(rect_t* boundary); +static bool node_is_leaf(node_t* node); +static void node_insert(node_t* node, point_t* point); +static void node_query(node_t* node, rect_t* search_area, int* count); +static void node_nearest_neighbor(node_t* node, point_t* query, point_t* nearest, double* best_dist_squared); +static double point_to_rect_distance(point_t* p, rect_t* rect); +static void node_remove_point(node_t* node, point_t* point); +static void node_merge(node_t* node); +static void node_del_all(node_t* node); +static void node_graph(node_t* node); #endif // QUAD_H diff --git a/src/quad.c b/src/quad.c index a78fc79..2eff572 100644 --- a/src/quad.c +++ b/src/quad.c @@ -15,7 +15,10 @@ static double distance_sq(point_t* p1, point_t* p2) { return (p1->x - p2->x) * (p1->x - p2->x) + (p1->y - p2->y) * (p1->y - p2->y); } - +static bool point_in_rect(point_t* point, rect_t* boundary) { + return point->x >= boundary->x0 && point->x <= boundary->x1 && + point->y >= boundary->y0 && point->y <= boundary->y1; +} void qtree_new(quadtree_t* qtree, rect_t* boundary) { qtree->root = node_new(boundary); @@ -35,7 +38,7 @@ node_t* node_new(rect_t* boundary) { return node; } -void rect_divide(rect_t* src, rect_t* dest) { +static void rect_divide(rect_t* src, rect_t* dest) { const int mid_x = (src->x0 + src->x1) / 2; const int mid_y = (src->y0 + src->y1) / 2; dest[IND_NW] = (rect_t) {src->x0 , src->y0 , mid_x , mid_y }; @@ -44,7 +47,7 @@ void rect_divide(rect_t* src, rect_t* dest) { dest[IND_SW] = (rect_t) {src->x0 , mid_y+1 , mid_x , src->y1}; } -int point_get_quadrant(rect_t* rect, point_t* point) { +static int point_get_quadrant(rect_t* rect, point_t* point) { const int x = point->x, y = point->y; const int w = abs(rect->x0 - rect->x1), h = abs(rect->y0 - rect->y1); if ((rect->x0 <= x) && (x < rect->x0 + w/2) && (rect->y0 <= y) && (y < rect->y0 + h/2)) @@ -58,11 +61,11 @@ else if ((rect->x0 <= x) && (x < rect->x0 + w/2) && (rect->y0 + h/2 <= y) && (y return -1; // error - not in rectangle } -bool node_is_leaf(node_t* node) { +static bool node_is_leaf(node_t* node) { return (node != NULL) ? (node->nw == NULL && node->ne == NULL && node->se == NULL && node->sw == NULL) : false; } -void node_insert(node_t* node, point_t* point) { +static void node_insert(node_t* node, point_t* point) { if (node->count < g_capacity && node_is_leaf(node)) { node->points[node->count++] = *point; } else { @@ -99,7 +102,7 @@ void qtree_insert(quadtree_t* qtree, point_t* point) { node_insert(qtree->root, point); } -bool rect_intersect(rect_t* r1, rect_t* r2) { +static bool rect_intersect(rect_t* r1, rect_t* r2) { // the max of the left edges and the min of the right edges int left = r1->x0 > r2->x0 ? r1->x0 : r2->x0; int right = r1->x1 < r2->x1 ? r1->x1 : r2->x1; @@ -109,7 +112,7 @@ bool rect_intersect(rect_t* r1, rect_t* r2) { return left <= right && top <= bottom; } -void node_query(node_t* node, rect_t* search_area, int* count) { +static void node_query(node_t* node, rect_t* search_area, int* count) { if (!rect_intersect(&node->boundary, search_area)) return; // If the node is a leaf and the boundary overlaps with the search area, count the points @@ -130,7 +133,7 @@ void qtree_query(quadtree_t* qtree, rect_t* search_area, int* count) { node_query(qtree->root, search_area, count); } -double point_rect_distsq(point_t* p, rect_t* rect) { +static double point_rect_distsq(point_t* p, rect_t* rect) { /* * Why the formula max(x0 - x, x - x1, 0)^2 + * max(y0 - y, y - y1, 0)^2 works for the distance between a @@ -178,7 +181,7 @@ double point_rect_distsq(point_t* p, rect_t* rect) { return dx * dx + dy * dy; } -void node_nearest_neighbor(node_t* node, point_t* query, point_t* nearest, double* best_dist_squared) { +static void node_nearest_neighbor(node_t* node, point_t* query, point_t* nearest, double* best_dist_squared) { if (!node) return; if (node_is_leaf(node)) { @@ -212,7 +215,7 @@ double qtree_nearest_neighbor(quadtree_t* qtree, point_t* query, point_t* neares return best_dist_squared; } -void node_remove_point(node_t* node, point_t* point) { +static void node_remove_point(node_t* node, point_t* point) { if (node_is_leaf(node)) { for (int i = 0; i < node->count; ++i) { if (node->points[i].id == point->id) { @@ -231,8 +234,11 @@ void node_remove_point(node_t* node, point_t* point) { } } +void qtree_remove_point(quadtree_t* qtree, point_t* point) { + node_remove_point(qtree->root, point); +} -void node_merge(node_t* node) { +static void node_merge(node_t* node) { if (node_is_leaf(node)) return; node_t* children[4] = { node->nw, node->ne, node->se, node->sw }; @@ -270,13 +276,16 @@ void node_merge(node_t* node) { } } +void qtree_merge(quadtree_t* qtree) { + node_merge(qtree->root); +} + void qtree_update_point(quadtree_t* qtree, point_t* old_point, point_t* new_point) { - node_t* root = qtree->root; - node_remove_point(root, old_point); + node_remove_point(qtree->root, old_point); old_point->x = new_point->x; old_point->y = new_point->y; old_point->id = new_point->id; - node_insert(root, old_point); + node_insert(qtree->root, old_point); } void node_del_all(node_t* node) { @@ -297,7 +306,7 @@ void qtree_del(quadtree_t* qtree) { } -void node_graph(node_t* node) { +static void node_graph(node_t* node) { if (node == NULL) return; // If it's a leaf node, print the boundary and the points in it diff --git a/test/test.c b/test/test.c index c9502b1..d15664c 100644 --- a/test/test.c +++ b/test/test.c @@ -2,6 +2,7 @@ #include "nanotest.h" #include #include +#include static bool are_points_equal(point_t* p1, point_t* p2) { return p1->id == p2->id; @@ -35,8 +36,9 @@ int main(int argc, char** argv) { //------------------------------------------------------------------------- point_t nearest; point_t query = {160, 78}; - double dist_nearest_squared = INT_MAX; - quadtree_nearest_neighbor(qtree.root, &query, &nearest, &dist_nearest_squared); + //double dist_nearest_squared = INT_MAX; + //quadtree_nearest_neighbor(qtree.root, &query, &nearest, &dist_nearest_squared); + double dist_nearest_squared = qtree_nearest_neighbor(&qtree, &query, &nearest); NTEST_ASSERT(3.99 <= dist_nearest_squared && dist_nearest_squared <= 4.01); NTEST_ASSERT(nearest.id == points[4].id); //------------------------------------------------------------------------- @@ -44,7 +46,7 @@ int main(int argc, char** argv) { //------------------------------------------------------------------------- int how_many = 0; rect_t search_area = {100, 50, 200, 100}; - quadtree_query(qtree.root, &search_area, &how_many); + qtree_query(&qtree, &search_area, &how_many); NTEST_ASSERT(how_many == 4); //------------------------------------------------------------------------- // Update point @@ -57,7 +59,7 @@ int main(int argc, char** argv) { // Merge //------------------------------------------------------------------------- // now sw->nw should have one point and so should sw->ne; mergeable into sw - node_merge(qtree.root); + qtree_merge(&qtree); // p7, p8 should have propagated up into sw NTEST_ASSERT(qtree.root->sw->count == 2); NTEST_ASSERT((are_points_equal(&qtree.root->sw->points[1], &points[7]) && @@ -68,7 +70,7 @@ int main(int argc, char** argv) { // Point deletion //------------------------------------------------------------------------- NTEST_ASSERT(qtree.root->nw->se->sw->count == 1); - node_remove_point(qtree.root, &points[5]); + qtree_remove_point(&qtree, &points[5]); NTEST_ASSERT(qtree.root->nw->se->sw->count == 0); return 0; }