Implement GeoJson loader
This commit is contained in:
parent
f9e9726974
commit
25ccfc5df5
119
src/geojson.c
Normal file
119
src/geojson.c
Normal file
@ -0,0 +1,119 @@
|
||||
#include "geojson.h"
|
||||
#include "dijkstrasearch.h"
|
||||
#include "logging.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <glib-object.h>
|
||||
#include <json-glib/json-glib.h>
|
||||
|
||||
int add_geojson_to_dijkstra(GList **nodes,
|
||||
GList **paths,
|
||||
char *filename)
|
||||
{
|
||||
JsonParser *parser;
|
||||
JsonNode *root;
|
||||
JsonArray *arr;
|
||||
JsonNode *node;
|
||||
JsonReader *reader;
|
||||
GError *error;
|
||||
|
||||
int i, j;
|
||||
int i_max, j_max;
|
||||
|
||||
char *name = NULL;
|
||||
int x, y;
|
||||
int x_last, y_last;
|
||||
|
||||
struct _stats {
|
||||
int nodes;
|
||||
int paths;
|
||||
} stats = {.nodes = 0, .paths = 0};
|
||||
|
||||
report(LL_INFO, "Loading GeoJson data from %s...", filename);
|
||||
|
||||
parser = json_parser_new ();
|
||||
|
||||
error = NULL;
|
||||
json_parser_load_from_file(parser, filename, &error);
|
||||
if (error)
|
||||
{
|
||||
report(LL_ERROR, "Unable to parse `%s': %s\n", filename, error->message);
|
||||
g_error_free(error);
|
||||
g_object_unref(parser);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
root = json_parser_get_root(parser);
|
||||
|
||||
arr = json_node_get_array(root);
|
||||
if (arr) {
|
||||
i_max = json_array_get_length(arr);
|
||||
for (i = 0; i < i_max; i++)
|
||||
{
|
||||
node = json_array_get_element(arr, i);
|
||||
if (node) {
|
||||
reader = json_reader_new(node);
|
||||
|
||||
json_reader_read_member(reader, "properties");
|
||||
if (json_reader_get_error(reader)) {
|
||||
g_object_unref(reader);
|
||||
continue;
|
||||
}
|
||||
json_reader_read_member(reader, "name");
|
||||
name = strdup(json_reader_get_string_value(reader));
|
||||
json_reader_end_member(reader); // name
|
||||
json_reader_end_member(reader); // properties
|
||||
|
||||
json_reader_read_member(reader, "geometry");
|
||||
json_reader_read_member(reader, "coordinates");
|
||||
if (json_reader_is_array(reader)) {
|
||||
j_max = json_reader_count_elements(reader);
|
||||
for (j = 0; j < j_max; j++) {
|
||||
json_reader_read_element(reader, j);
|
||||
if (json_reader_is_array(reader)) {
|
||||
stats.nodes++;
|
||||
json_reader_read_element(reader, 0);
|
||||
x = json_reader_get_int_value(reader);
|
||||
json_reader_end_element(reader);
|
||||
json_reader_read_element(reader, 1);
|
||||
y = json_reader_get_int_value(reader);
|
||||
json_reader_end_element(reader);
|
||||
|
||||
if (j > 0) {
|
||||
stats.paths++;
|
||||
dijkstra_path_new_to_list(nodes, paths,
|
||||
x_last, y_last,
|
||||
x, y,
|
||||
name, 1);
|
||||
}
|
||||
|
||||
x_last = x;
|
||||
y_last = y;
|
||||
} else {
|
||||
report(LL_WARNING, "err 1\n");
|
||||
}
|
||||
json_reader_end_element(reader);
|
||||
}
|
||||
} else {
|
||||
report(LL_WARNING, "err 0\n");
|
||||
}
|
||||
json_reader_end_member(reader); // coordinates
|
||||
json_reader_end_member(reader); // geometry
|
||||
|
||||
g_object_unref(reader);
|
||||
} else {
|
||||
report(LL_ERROR, "Invalid geojson file.\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
report(LL_ERROR, "Invalid geojson file.\n");
|
||||
}
|
||||
|
||||
report(LL_INFO, "Imported %d nodes and %d paths from GeoJson.",
|
||||
stats.nodes,
|
||||
stats.paths);
|
||||
|
||||
g_object_unref (parser);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
10
src/geojson.h
Normal file
10
src/geojson.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef GEOJSON_H
|
||||
#define GEOJSON_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
int add_geojson_to_dijkstra(GList **nodes,
|
||||
GList **paths,
|
||||
char *filename);
|
||||
|
||||
#endif // GEOJSON_H
|
60
src/logging.c
Normal file
60
src/logging.c
Normal file
@ -0,0 +1,60 @@
|
||||
/* ----------------------------------------------------------------------------
|
||||
* C-Report
|
||||
* ----------------------------------------------------------------------------
|
||||
* Author : Markus Koch <markus@notsyncing.net>
|
||||
* Contributors : None
|
||||
* License : Mozilla Public License (MPL) Version 2
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "logging.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
static enum log_level current_log_level = LL_INFO;
|
||||
|
||||
static const char *ll_string[] = {
|
||||
"\x1B[31m\x1B[1m[X] ",
|
||||
"\x1B[31m[E] ",
|
||||
"\x1B[33m[W] ",
|
||||
"\x1B[32m[I] ",
|
||||
"\x1B[34m[D] ",
|
||||
"\x1B[34m[d] ",
|
||||
"[?] "
|
||||
};
|
||||
|
||||
int should_report(enum log_level log_level)
|
||||
{
|
||||
return (log_level <= current_log_level);
|
||||
}
|
||||
|
||||
enum log_level report(enum log_level log_level, const char *format, ...)
|
||||
{
|
||||
va_list vargs;
|
||||
|
||||
if (log_level > LL_COUNT)
|
||||
log_level = LL_COUNT;
|
||||
|
||||
if (should_report(log_level)) {
|
||||
va_start(vargs, format);
|
||||
fprintf(stderr, "%s", ll_string[log_level]);
|
||||
vfprintf(stderr, format, vargs);
|
||||
fprintf(stderr, "\x1B[0m\n");
|
||||
va_end(vargs);
|
||||
}
|
||||
|
||||
return log_level;
|
||||
}
|
||||
|
||||
void set_log_level(enum log_level log_level)
|
||||
{
|
||||
if (log_level >= LL_COUNT)
|
||||
log_level = LL_COUNT - 1;
|
||||
current_log_level = log_level;
|
||||
}
|
||||
|
||||
enum log_level get_log_level()
|
||||
{
|
||||
return current_log_level;
|
||||
}
|
28
src/logging.h
Normal file
28
src/logging.h
Normal file
@ -0,0 +1,28 @@
|
||||
/* ----------------------------------------------------------------------------
|
||||
* C-Report
|
||||
* ----------------------------------------------------------------------------
|
||||
* Author : Markus Koch <markus@notsyncing.net>
|
||||
* Contributors : None
|
||||
* License : Mozilla Public License (MPL) Version 2
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LOGGING_H
|
||||
#define LOGGING_H
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
enum log_level {LL_CRITICAL = 0,
|
||||
LL_ERROR,
|
||||
LL_WARNING,
|
||||
LL_INFO,
|
||||
LL_DEBUG,
|
||||
LL_NOISY,
|
||||
LL_COUNT};
|
||||
int should_report(enum log_level log_level);
|
||||
enum log_level report(enum log_level log_level, const char *format, ...);
|
||||
void set_log_level(enum log_level log_level);
|
||||
enum log_level get_log_level();
|
||||
|
||||
#endif // LOGGING_H
|
108
src/main.c
108
src/main.c
@ -1,10 +1,46 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include "dijkstrasearch.h"
|
||||
#include <glib/glist.h>
|
||||
#include "geojson.h"
|
||||
#include "logging.h"
|
||||
|
||||
|
||||
int main()
|
||||
void add_test_map(GList **nodes,
|
||||
GList **paths)
|
||||
{
|
||||
dijkstra_path_new_to_list(nodes,
|
||||
paths,
|
||||
0,0,
|
||||
0,10,
|
||||
"Vertical",
|
||||
1);
|
||||
|
||||
dijkstra_path_new_to_list(nodes,
|
||||
paths,
|
||||
0,5,
|
||||
10,5,
|
||||
"Horizontal",
|
||||
1);
|
||||
}
|
||||
|
||||
void help(const char *exec)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: %s [OPTION] [FILE]...\n"
|
||||
"Start the lifo-dijkstraserv routing server.\n\n"
|
||||
" -s\tset output to silent\n"
|
||||
" -v\tincrease verbosity. Maybe used multiple times.\n"
|
||||
" -p\tport number (default 6802)\n",
|
||||
exec);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int opt;
|
||||
int i;
|
||||
|
||||
GList *nodes = NULL;
|
||||
GList *paths = NULL;
|
||||
|
||||
@ -12,20 +48,40 @@ int main()
|
||||
struct dijkstra_node *node;
|
||||
struct dijkstra_path *path;
|
||||
|
||||
dijkstra_path_new_to_list(&nodes,
|
||||
&paths,
|
||||
0,0,
|
||||
0,10,
|
||||
"Vertical",
|
||||
1);
|
||||
set_log_level(LL_INFO);
|
||||
|
||||
dijkstra_path_new_to_list(&nodes,
|
||||
&paths,
|
||||
0,5,
|
||||
10,5,
|
||||
"Horizontal",
|
||||
1);
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
if (optind == argc) {
|
||||
help(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Parse file list */
|
||||
for (i = optind; i < argc; ++i) {
|
||||
add_geojson_to_dijkstra(&nodes, &paths, argv[i]);
|
||||
}
|
||||
|
||||
// add_test_map(&nodes, &paths);
|
||||
|
||||
if (should_report(LL_NOISY)) {
|
||||
for (l = 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));
|
||||
@ -39,9 +95,29 @@ int main()
|
||||
path->destination, path->destination->position.x, path->destination->position.y,
|
||||
path->name);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("\nDone.\n");
|
||||
report(LL_INFO, "Created graph with %d nodes and %d paths.",
|
||||
g_list_length(nodes),
|
||||
g_list_length(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);
|
||||
|
||||
// TODO: Free memory
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user