✨ coord_query
This commit is contained in:
BIN
A1/coord_query_kdtree
Executable file
BIN
A1/coord_query_kdtree
Executable file
Binary file not shown.
119
A1/coord_query_kdtree.c
Normal file
119
A1/coord_query_kdtree.c
Normal file
@ -0,0 +1,119 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#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);
|
||||
}
|
BIN
A1/coord_query_naive
Executable file
BIN
A1/coord_query_naive
Executable file
Binary file not shown.
@ -7,6 +7,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
#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) {
|
||||
|
10
A1/euclidean_distance.h
Normal file
10
A1/euclidean_distance.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef EUCLIDEAN_DISTANCE_H
|
||||
#define EUCLIDEAN_DISTANCE_H
|
||||
|
||||
#include <math.h>
|
||||
|
||||
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
|
Reference in New Issue
Block a user