diff --git a/A1/coord_query_kdtree b/A1/coord_query_kdtree new file mode 100755 index 0000000..9f2db6c Binary files /dev/null and b/A1/coord_query_kdtree differ diff --git a/A1/coord_query_kdtree.c b/A1/coord_query_kdtree.c new file mode 100644 index 0000000..fed49ef --- /dev/null +++ b/A1/coord_query_kdtree.c @@ -0,0 +1,119 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "record.h" +#include "euclidean_distance.h" +#include "coord_query.h" + +int lon_comp_func(const void* a, const void* b) { + return ( + ((struct record*)a)->lon - ((struct record*)b)->lon + ); +} + +int lat_comp_func(const void* a, const void* b) { + return ( + ((struct record*)a)->lat - ((struct record*)b)->lat + ); +} + +struct node { + struct record* record; + double point[2]; + int axis; + struct node* left; + struct node* right; +}; + +struct node* kdtree(struct record* points, int depth, int n) { + int axis = depth % 2; + + if (axis == 0) { + qsort(points, n, sizeof(struct record*), lon_comp_func); + } else { + qsort(points, n, sizeof(struct record*), lat_comp_func); + } + struct record* median = &points[n / 2]; + struct node* new_node = malloc(sizeof(struct node)); + new_node->record = median; + new_node->point[0] = median->lon; + new_node->point[1] = median->lat; + new_node->axis = axis; + if (n/2 != 0) { + new_node->left = kdtree(points, depth+1, n/2); + } else { + new_node->left = NULL; + } + if (n/2 + 1 <= n - 1) { + new_node->right = kdtree(&points[n/2 + 1], depth+1, n/2 - 1 + (n % 2)); + } else { + new_node->right = NULL; + } + + return new_node; +} + +struct node* mk_kdtree(struct record* rs, int n) { + struct node* data = kdtree(rs, 0, n); + + return data; +} + +void free_kdtree(struct node* data) { + if (data == NULL) { + return; + } + + struct node* left = data->left; + struct node* right = data->right; + + free_kdtree(left); + free_kdtree(right); +} + +void lookup(struct record* closest, double closest_dist, double query[2], struct node* tree) { + if (tree == NULL) { + return; + } + + double compare_coord[2] = {tree->point[0], tree->point[1]}; + double dist = calc_euclidean(query, compare_coord); + if (dist < closest_dist) { + closest = tree->record; + closest_dist = dist; + } + + double diff = tree->point[tree->axis] - query[tree->axis]; + + if (diff >= 0 || closest_dist > fabs(diff)) { + lookup(closest, closest_dist, query, tree->left); + } else if (diff <= 0 || closest_dist > fabs(diff)) { + lookup(closest, closest_dist, query, tree->right); + } + + return; +} + +const struct record* lookup_kdtree(struct node *data, double lon, double lat) { + struct record* closest = &(*data->record); + double compare_coord[2] = {data->point[0], data->point[1]}; + double query[2] = {lon, lat}; + double closest_dist = calc_euclidean(query, compare_coord); + + lookup(closest, closest_dist, query, data); + + return closest; +} + +int main(int argc, char** argv) { + return coord_query_loop(argc, argv, + (mk_index_fn)mk_kdtree, + (free_index_fn)free_kdtree, + (lookup_fn)lookup_kdtree); +} diff --git a/A1/coord_query_naive b/A1/coord_query_naive new file mode 100755 index 0000000..daf5db9 Binary files /dev/null and b/A1/coord_query_naive differ diff --git a/A1/coord_query_naive.c b/A1/coord_query_naive.c index 9d27882..796af35 100644 --- a/A1/coord_query_naive.c +++ b/A1/coord_query_naive.c @@ -7,6 +7,7 @@ #include #include "record.h" +#include "euclidean_distance.h" #include "coord_query.h" struct naive_data { @@ -15,18 +16,36 @@ struct naive_data { }; struct naive_data* mk_naive(struct record* rs, int n) { - assert(0); - // TODO + struct naive_data* data = malloc(sizeof(struct naive_data*)); + data->rs = rs; + data->n = n; + + return data; } void free_naive(struct naive_data* data) { - assert(0); - // TODO + free(data); } const struct record* lookup_naive(struct naive_data *data, double lon, double lat) { - assert(0); - // TODO + double search_coords[2] = {lon, lat}; + struct record* closest_point = &data->rs[0]; + + double compare_coords[2] = {(closest_point)->lon, (closest_point)->lat}; + double dist = calc_euclidean(search_coords, compare_coords); + double closest_dist = dist; + + for (int i = 1 ; i < data->n ; i++) { + double compare_coords[2] = {(&data->rs[i])->lon, (&data->rs[i])->lat}; + double dist = calc_euclidean(search_coords, compare_coords); + + if (dist < closest_dist) { + closest_point = &data->rs[i]; + closest_dist = dist; + } + } + + return closest_point; } int main(int argc, char** argv) { diff --git a/A1/euclidean_distance.h b/A1/euclidean_distance.h new file mode 100644 index 0000000..a660bd3 --- /dev/null +++ b/A1/euclidean_distance.h @@ -0,0 +1,10 @@ +#ifndef EUCLIDEAN_DISTANCE_H +#define EUCLIDEAN_DISTANCE_H + +#include + +static double calc_euclidean(double coord_1[2], double coord_2[2]) { + return sqrt(pow((coord_1[0] - coord_2[0]),2) + pow((coord_1[1] - coord_2[1]),2)); +} + +#endif