diff --git a/src/dijkstrasearch.c b/src/dijkstrasearch.c index c3ea2cb..cf92984 100644 --- a/src/dijkstrasearch.c +++ b/src/dijkstrasearch.c @@ -4,6 +4,7 @@ #include #define FP_THRESHOLD 0.01 + int dijkstra_node_same (struct dijkstra_node *node_a, struct dijkstra_node *node_b) { @@ -16,6 +17,27 @@ int dijkstra_node_same (struct dijkstra_node *node_a, return same; } +/*! + * \brief dijkstra_node_new creates a new dijkstra_node + * \param x x position + * \param y y position + * \return a new dijkstra node or NULL. Needs to be freed manually. + */ +struct dijkstra_node *dijkstra_node_new(float x, + float y) +{ + struct dijkstra_node *node; + + node = malloc(sizeof(*node)); + if (node) { + node->position.x = x; + node->position.y = y; + node->paths = NULL; + } + + return node; +} + struct dijkstra_node *dijkstra_node_exists(GList *list, struct dijkstra_node *node) { @@ -125,6 +147,29 @@ struct dijkstra_path *dijkstra_path_dup_shallow(struct dijkstra_path *path) return dup; } +/*! + * \brief dijkstra_path_new creates a new dijkstra_path between two nodes. + * \param name the name of the path (pointer is not copied and must stay valid!) + * \return a new dijkstra path or NULL. Needs to be freed manually. + */ +struct dijkstra_path *dijkstra_path_new(char *name, + struct dijkstra_node *source, + struct dijkstra_node *destination, + dijkstra_cost weight) +{ + struct dijkstra_path *path; + + path = malloc(sizeof(*path)); + if (path) { + path->name = name; + path->weight = weight; + + dijkstra_connect_nodes_to_path(source, destination, path); + } + + return path; +} + struct dijkstra_node *dijkstra_disconnect_node_from_path(struct dijkstra_path *path, struct dijkstra_node *node, int ref_only) @@ -142,8 +187,7 @@ struct dijkstra_node *dijkstra_disconnect_node_from_path(struct dijkstra_path *p return node; } -int dijkstra_path_intersect(GList **nodes, - GList **paths, +int dijkstra_path_intersect(struct dijkstra_solver *solver, struct dijkstra_path *path_a, struct dijkstra_path *path_b) { @@ -190,11 +234,11 @@ int dijkstra_path_intersect(GList **nodes, i_x = p0_x + (t * s1_x); i_y = p0_y + (t * s1_y); - node_new = dijkstra_node_new_to_list(nodes, i_x, i_y, &is_new); + node_new = dijkstra_node_new_to_list(&solver->nodes, i_x, i_y, &is_new); if (node_new != path_a->source && node_new != path_a->destination) { path_new = dijkstra_path_dup_shallow(path_a); - *paths = g_list_append(*paths, (gpointer) path_new); + solver->paths = g_list_append(solver->paths, (gpointer) path_new); dijkstra_disconnect_node_from_path(path_a, path_a->destination, 1); dijkstra_connect_destination_node_to_path(node_new, path_a); @@ -204,7 +248,7 @@ int dijkstra_path_intersect(GList **nodes, // Now do the same thing for path b if (node_new != path_b->source && node_new != path_b->destination) { path_new = dijkstra_path_dup_shallow(path_b); - *paths = g_list_append(*paths, (gpointer) path_new); + solver->paths = g_list_append(solver->paths, (gpointer) path_new); dijkstra_disconnect_node_from_path(path_b, path_b->destination, 1); dijkstra_connect_destination_node_to_path(node_new, path_b); dijkstra_connect_source_node_to_path(node_new, path_new); @@ -215,8 +259,7 @@ int dijkstra_path_intersect(GList **nodes, return 0; // No collision } -struct dijkstra_path *dijkstra_path_new_to_list(GList **nodes, - GList **paths, +struct dijkstra_path *dijkstra_path_new_to_list(struct dijkstra_solver *solver, float x1, float y1, float x2, @@ -229,16 +272,16 @@ struct dijkstra_path *dijkstra_path_new_to_list(GList **nodes, struct dijkstra_path *existing_path; GList *l, *l_last; - n1 = dijkstra_node_new_to_list(nodes, x1, y1, NULL); - n2 = dijkstra_node_new_to_list(nodes, x2, y2, NULL); + n1 = dijkstra_node_new_to_list(&solver->nodes, x1, y1, NULL); + n2 = dijkstra_node_new_to_list(&solver->nodes, x2, y2, NULL); path = dijkstra_path_new(name, n1, n2, weight); - l_last = g_list_last(*paths); - *paths = g_list_append(*paths, (gpointer) path); + l_last = g_list_last(solver->paths); + solver->paths = g_list_append(solver->paths, (gpointer) path); - for (l = *paths; l != NULL; l = l->next) { + for (l = solver->paths; l != NULL; l = l->next) { existing_path = (struct dijkstra_path*) l->data; - dijkstra_path_intersect(nodes, paths, path, existing_path); + dijkstra_path_intersect(solver, path, existing_path); if (l == l_last) /* Avoid testing newly added paths */ break; } @@ -246,46 +289,39 @@ struct dijkstra_path *dijkstra_path_new_to_list(GList **nodes, return path; } -/*! - * \brief dijkstra_node_new creates a new dijkstra_node - * \param x x position - * \param y y position - * \return a new dijkstra node or NULL. Needs to be freed manually. - */ -struct dijkstra_node *dijkstra_node_new(float x, - float y) +struct dijkstra_solver *dijkstra_solver_new() { + struct dijkstra_solver *solver; + + solver = malloc(sizeof(*solver)); + if (solver) { + solver->nodes = NULL; + solver->paths = NULL; + } + + return solver; +} + +void dijkstra_solver_free(struct dijkstra_solver *solver) +{ + GList *l; + struct dijkstra_path *path; struct dijkstra_node *node; - node = malloc(sizeof(*node)); - if (node) { - node->position.x = x; - node->position.y = y; - node->paths = NULL; + // Free memory + for (l = solver->paths; l != NULL; l = l->next) { + path = (struct dijkstra_path*) l->data; + // TODO: free(path->name); + // Currently, we reuse the existing memory block when for the + // name when cloning streets. As such, clearing it here will + // cause a double free if the street has been split. + free(path); } + g_list_free(solver->paths); - return node; -} - -/*! - * \brief dijkstra_path_new creates a new dijkstra_path between two nodes. - * \param name the name of the path (pointer is not copied and must stay valid!) - * \return a new dijkstra path or NULL. Needs to be freed manually. - */ -struct dijkstra_path *dijkstra_path_new(char *name, - struct dijkstra_node *source, - struct dijkstra_node *destination, - dijkstra_cost weight) -{ - struct dijkstra_path *path; - - path = malloc(sizeof(*path)); - if (path) { - path->name = name; - path->weight = weight; - - dijkstra_connect_nodes_to_path(source, destination, path); + for (l = solver->nodes; l != NULL; l = l->next) { + node = (struct dijkstra_node*) l->data; + free(node); } - - return path; + g_list_free(solver->nodes); } diff --git a/src/dijkstrasearch.h b/src/dijkstrasearch.h index a959e5a..ca7e30e 100644 --- a/src/dijkstrasearch.h +++ b/src/dijkstrasearch.h @@ -5,6 +5,16 @@ typedef int dijkstra_cost; +struct dijkstra_solver { + GList *nodes; + GList *paths; +}; + +struct dijkstra_state { + dijkstra_cost cost; + int visited; +}; + struct position { float x; float y; @@ -22,27 +32,18 @@ struct dijkstra_node { GList *paths; - dijkstra_cost cost; + int uid; }; -struct dijkstra_node *dijkstra_node_new(float x, - float y); -struct dijkstra_path *dijkstra_path_new(char *name, - struct dijkstra_node *source, - struct dijkstra_node *destination, - dijkstra_cost weight); - -int dijkstra_path_intersect(GList **nodes, - GList **paths, - struct dijkstra_path *path_a, - struct dijkstra_path *path_b); - -struct dijkstra_path *dijkstra_path_new_to_list(GList **nodes, - GList **paths, +struct dijkstra_path *dijkstra_path_new_to_list(struct dijkstra_solver *solver, float x1, float y1, float x2, float y2, char *name, dijkstra_cost weight); + +struct dijkstra_solver *dijkstra_solver_new(); +void dijkstra_solver_free(struct dijkstra_solver *solver); + #endif // DIJKSTRASEARCH_H diff --git a/src/geojson.c b/src/geojson.c index 6eba032..88622b7 100644 --- a/src/geojson.c +++ b/src/geojson.c @@ -6,8 +6,7 @@ #include #include -int add_geojson_to_dijkstra(GList **nodes, - GList **paths, +int add_geojson_to_dijkstra(struct dijkstra_solver *solver, char *filename) { JsonParser *parser; @@ -81,7 +80,7 @@ int add_geojson_to_dijkstra(GList **nodes, if (j > 0) { stats.paths++; - dijkstra_path_new_to_list(nodes, paths, + dijkstra_path_new_to_list(solver, x_last, y_last, x, y, name, 1); diff --git a/src/geojson.h b/src/geojson.h index 7ad3c7e..13cb5f3 100644 --- a/src/geojson.h +++ b/src/geojson.h @@ -2,9 +2,9 @@ #define GEOJSON_H #include +#include "dijkstrasearch.h" -int add_geojson_to_dijkstra(GList **nodes, - GList **paths, +int add_geojson_to_dijkstra(struct dijkstra_solver *solver, char *filename); #endif // GEOJSON_H diff --git a/src/main.c b/src/main.c index 8de7024..17ddfd0 100644 --- a/src/main.c +++ b/src/main.c @@ -7,18 +7,15 @@ #include "geojson.h" #include "logging.h" -void add_test_map(GList **nodes, - GList **paths) +void add_test_map(struct dijkstra_solver *solver) { - dijkstra_path_new_to_list(nodes, - paths, + dijkstra_path_new_to_list(solver, 0,0, 0,10, "Vertical", 1); - dijkstra_path_new_to_list(nodes, - paths, + dijkstra_path_new_to_list(solver, 0,5, 10,5, "Horizontal", @@ -41,8 +38,7 @@ int main(int argc, char *argv[]) int opt; int i; - GList *nodes = NULL; - GList *paths = NULL; + struct dijkstra_solver *solver; GList *l = NULL; struct dijkstra_node *node; @@ -53,20 +49,20 @@ int main(int argc, char *argv[]) // Process arguments while((opt = getopt(argc, argv, "vs")) != -1) { switch(opt) - { - case 'v': - set_log_level(get_log_level() + 1); - break; - case 's': - set_log_level(0); - break; - case ':': - case '?': - help(argv[0]); - return 1; - default: - break; - } + { + case 'v': + set_log_level(get_log_level() + 1); + break; + case 's': + set_log_level(0); + break; + case ':': + case '?': + help(argv[0]); + return 1; + default: + break; + } } if (optind == argc) { @@ -74,21 +70,27 @@ int main(int argc, char *argv[]) return 1; } + solver = dijkstra_solver_new(); + if (!solver) { + report(LL_CRITICAL, "Memory allocation failure."); + return 2; + } + /* Parse file list */ for (i = optind; i < argc; ++i) { - add_geojson_to_dijkstra(&nodes, &paths, argv[i]); + add_geojson_to_dijkstra(solver, argv[i]); } // add_test_map(&nodes, &paths); if (should_report(LL_NOISY)) { - for (l = nodes; l != NULL; l = l->next) { + for (l = solver->nodes; l != NULL; l = l->next) { node = (struct dijkstra_node*) l->data; printf("Node %p: %f,\t%f [%d paths]\n", node, node->position.x, node->position.y, g_list_length(node->paths)); } printf("\n"); - for (l = paths; l != NULL; l = l->next) { + for (l = solver->paths; l != NULL; l = l->next) { path = (struct dijkstra_path*) l->data; printf("Path %p: %p (%f,%f) -> %p (%f,%f) \t\"%s\"\n", path, path->source, path->source->position.x, path->source->position.y, @@ -99,25 +101,10 @@ int main(int argc, char *argv[]) } report(LL_INFO, "Created graph with %d nodes and %d paths.", - g_list_length(nodes), - g_list_length(paths)); + g_list_length(solver->nodes), + g_list_length(solver->paths)); - // Free memory - for (l = paths; l != NULL; l = l->next) { - path = (struct dijkstra_path*) l->data; - // TODO: free(path->name); - // Currently, we reuse the existing memory block when for the - // name when cloning streets. As such, clearing it here will - // cause a double free if the street has been split. - free(path); - } - g_list_free(paths); - - for (l = nodes; l != NULL; l = l->next) { - node = (struct dijkstra_node*) l->data; - free(node); - } - g_list_free(nodes); + dijkstra_solver_free(solver); return 0; }