Clean up code

This commit is contained in:
Markus Koch 2020-05-02 16:51:12 +02:00
parent 25ccfc5df5
commit 0d2945d76f
5 changed files with 135 additions and 112 deletions

View File

@ -4,6 +4,7 @@
#include <math.h> #include <math.h>
#define FP_THRESHOLD 0.01 #define FP_THRESHOLD 0.01
int dijkstra_node_same (struct dijkstra_node *node_a, int dijkstra_node_same (struct dijkstra_node *node_a,
struct dijkstra_node *node_b) struct dijkstra_node *node_b)
{ {
@ -16,6 +17,27 @@ int dijkstra_node_same (struct dijkstra_node *node_a,
return same; 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 *dijkstra_node_exists(GList *list,
struct dijkstra_node *node) struct dijkstra_node *node)
{ {
@ -125,6 +147,29 @@ struct dijkstra_path *dijkstra_path_dup_shallow(struct dijkstra_path *path)
return dup; 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 *dijkstra_disconnect_node_from_path(struct dijkstra_path *path,
struct dijkstra_node *node, struct dijkstra_node *node,
int ref_only) int ref_only)
@ -142,8 +187,7 @@ struct dijkstra_node *dijkstra_disconnect_node_from_path(struct dijkstra_path *p
return node; return node;
} }
int dijkstra_path_intersect(GList **nodes, int dijkstra_path_intersect(struct dijkstra_solver *solver,
GList **paths,
struct dijkstra_path *path_a, struct dijkstra_path *path_a,
struct dijkstra_path *path_b) struct dijkstra_path *path_b)
{ {
@ -190,11 +234,11 @@ int dijkstra_path_intersect(GList **nodes,
i_x = p0_x + (t * s1_x); i_x = p0_x + (t * s1_x);
i_y = p0_y + (t * s1_y); 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) { if (node_new != path_a->source && node_new != path_a->destination) {
path_new = dijkstra_path_dup_shallow(path_a); 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_disconnect_node_from_path(path_a, path_a->destination, 1);
dijkstra_connect_destination_node_to_path(node_new, path_a); 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 // Now do the same thing for path b
if (node_new != path_b->source && node_new != path_b->destination) { if (node_new != path_b->source && node_new != path_b->destination) {
path_new = dijkstra_path_dup_shallow(path_b); 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_disconnect_node_from_path(path_b, path_b->destination, 1);
dijkstra_connect_destination_node_to_path(node_new, path_b); dijkstra_connect_destination_node_to_path(node_new, path_b);
dijkstra_connect_source_node_to_path(node_new, path_new); dijkstra_connect_source_node_to_path(node_new, path_new);
@ -215,8 +259,7 @@ int dijkstra_path_intersect(GList **nodes,
return 0; // No collision return 0; // No collision
} }
struct dijkstra_path *dijkstra_path_new_to_list(GList **nodes, struct dijkstra_path *dijkstra_path_new_to_list(struct dijkstra_solver *solver,
GList **paths,
float x1, float x1,
float y1, float y1,
float x2, float x2,
@ -229,16 +272,16 @@ struct dijkstra_path *dijkstra_path_new_to_list(GList **nodes,
struct dijkstra_path *existing_path; struct dijkstra_path *existing_path;
GList *l, *l_last; GList *l, *l_last;
n1 = dijkstra_node_new_to_list(nodes, x1, y1, NULL); n1 = dijkstra_node_new_to_list(&solver->nodes, x1, y1, NULL);
n2 = dijkstra_node_new_to_list(nodes, x2, y2, NULL); n2 = dijkstra_node_new_to_list(&solver->nodes, x2, y2, NULL);
path = dijkstra_path_new(name, n1, n2, weight); path = dijkstra_path_new(name, n1, n2, weight);
l_last = g_list_last(*paths); l_last = g_list_last(solver->paths);
*paths = g_list_append(*paths, (gpointer) path); 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; 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 */ if (l == l_last) /* Avoid testing newly added paths */
break; break;
} }
@ -246,46 +289,39 @@ struct dijkstra_path *dijkstra_path_new_to_list(GList **nodes,
return path; return path;
} }
/*! struct dijkstra_solver *dijkstra_solver_new()
* \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 *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; struct dijkstra_node *node;
node = malloc(sizeof(*node)); // Free memory
if (node) { for (l = solver->paths; l != NULL; l = l->next) {
node->position.x = x; path = (struct dijkstra_path*) l->data;
node->position.y = y; // TODO: free(path->name);
node->paths = NULL; // 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; for (l = solver->nodes; l != NULL; l = l->next) {
node = (struct dijkstra_node*) l->data;
free(node);
} }
g_list_free(solver->nodes);
/*!
* \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;
} }

View File

@ -5,6 +5,16 @@
typedef int dijkstra_cost; typedef int dijkstra_cost;
struct dijkstra_solver {
GList *nodes;
GList *paths;
};
struct dijkstra_state {
dijkstra_cost cost;
int visited;
};
struct position { struct position {
float x; float x;
float y; float y;
@ -22,27 +32,18 @@ struct dijkstra_node {
GList *paths; GList *paths;
dijkstra_cost cost; int uid;
}; };
struct dijkstra_node *dijkstra_node_new(float x, struct dijkstra_path *dijkstra_path_new_to_list(struct dijkstra_solver *solver,
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,
float x1, float x1,
float y1, float y1,
float x2, float x2,
float y2, float y2,
char *name, char *name,
dijkstra_cost weight); dijkstra_cost weight);
struct dijkstra_solver *dijkstra_solver_new();
void dijkstra_solver_free(struct dijkstra_solver *solver);
#endif // DIJKSTRASEARCH_H #endif // DIJKSTRASEARCH_H

View File

@ -6,8 +6,7 @@
#include <glib-object.h> #include <glib-object.h>
#include <json-glib/json-glib.h> #include <json-glib/json-glib.h>
int add_geojson_to_dijkstra(GList **nodes, int add_geojson_to_dijkstra(struct dijkstra_solver *solver,
GList **paths,
char *filename) char *filename)
{ {
JsonParser *parser; JsonParser *parser;
@ -81,7 +80,7 @@ int add_geojson_to_dijkstra(GList **nodes,
if (j > 0) { if (j > 0) {
stats.paths++; stats.paths++;
dijkstra_path_new_to_list(nodes, paths, dijkstra_path_new_to_list(solver,
x_last, y_last, x_last, y_last,
x, y, x, y,
name, 1); name, 1);

View File

@ -2,9 +2,9 @@
#define GEOJSON_H #define GEOJSON_H
#include <glib.h> #include <glib.h>
#include "dijkstrasearch.h"
int add_geojson_to_dijkstra(GList **nodes, int add_geojson_to_dijkstra(struct dijkstra_solver *solver,
GList **paths,
char *filename); char *filename);
#endif // GEOJSON_H #endif // GEOJSON_H

View File

@ -7,18 +7,15 @@
#include "geojson.h" #include "geojson.h"
#include "logging.h" #include "logging.h"
void add_test_map(GList **nodes, void add_test_map(struct dijkstra_solver *solver)
GList **paths)
{ {
dijkstra_path_new_to_list(nodes, dijkstra_path_new_to_list(solver,
paths,
0,0, 0,0,
0,10, 0,10,
"Vertical", "Vertical",
1); 1);
dijkstra_path_new_to_list(nodes, dijkstra_path_new_to_list(solver,
paths,
0,5, 0,5,
10,5, 10,5,
"Horizontal", "Horizontal",
@ -41,8 +38,7 @@ int main(int argc, char *argv[])
int opt; int opt;
int i; int i;
GList *nodes = NULL; struct dijkstra_solver *solver;
GList *paths = NULL;
GList *l = NULL; GList *l = NULL;
struct dijkstra_node *node; struct dijkstra_node *node;
@ -74,21 +70,27 @@ int main(int argc, char *argv[])
return 1; return 1;
} }
solver = dijkstra_solver_new();
if (!solver) {
report(LL_CRITICAL, "Memory allocation failure.");
return 2;
}
/* Parse file list */ /* Parse file list */
for (i = optind; i < argc; ++i) { 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); // add_test_map(&nodes, &paths);
if (should_report(LL_NOISY)) { 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; 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("Node %p: %f,\t%f [%d paths]\n", node, node->position.x, node->position.y, g_list_length(node->paths));
} }
printf("\n"); 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; path = (struct dijkstra_path*) l->data;
printf("Path %p: %p (%f,%f) -> %p (%f,%f) \t\"%s\"\n", path, printf("Path %p: %p (%f,%f) -> %p (%f,%f) \t\"%s\"\n", path,
path->source, path->source->position.x, path->source->position.y, 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.", report(LL_INFO, "Created graph with %d nodes and %d paths.",
g_list_length(nodes), g_list_length(solver->nodes),
g_list_length(paths)); g_list_length(solver->paths));
// Free memory dijkstra_solver_free(solver);
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);
return 0; return 0;
} }