Skip to content

Commit

Permalink
Make node-related functions static, define qtree-operand functions as…
Browse files Browse the repository at this point in the history
… interface
  • Loading branch information
leonmavr committed Sep 17, 2024
1 parent a9bf72e commit a9ddf0c
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 41 deletions.
34 changes: 13 additions & 21 deletions include/quad.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
39 changes: 24 additions & 15 deletions src/quad.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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 };
Expand All @@ -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))
Expand All @@ -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 {
Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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) {
Expand All @@ -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 };
Expand Down Expand Up @@ -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) {
Expand All @@ -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
Expand Down
12 changes: 7 additions & 5 deletions test/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "nanotest.h"
#include <assert.h>
#include <limits.h>
#include <math.h>

static bool are_points_equal(point_t* p1, point_t* p2) {
return p1->id == p2->id;
Expand Down Expand Up @@ -35,16 +36,17 @@ 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);
//-------------------------------------------------------------------------
// Rectangular query
//-------------------------------------------------------------------------
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
Expand All @@ -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]) &&
Expand All @@ -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;
}

0 comments on commit a9ddf0c

Please sign in to comment.