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
|
130
src/main.c
130
src/main.c
@ -1,10 +1,46 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
#include "dijkstrasearch.h"
|
#include "dijkstrasearch.h"
|
||||||
#include <glib/glist.h>
|
#include <glib/glist.h>
|
||||||
|
#include "geojson.h"
|
||||||
|
#include "logging.h"
|
||||||
|
|
||||||
|
void add_test_map(GList **nodes,
|
||||||
int main()
|
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 *nodes = NULL;
|
||||||
GList *paths = NULL;
|
GList *paths = NULL;
|
||||||
|
|
||||||
@ -12,36 +48,76 @@ int main()
|
|||||||
struct dijkstra_node *node;
|
struct dijkstra_node *node;
|
||||||
struct dijkstra_path *path;
|
struct dijkstra_path *path;
|
||||||
|
|
||||||
dijkstra_path_new_to_list(&nodes,
|
set_log_level(LL_INFO);
|
||||||
&paths,
|
|
||||||
0,0,
|
|
||||||
0,10,
|
|
||||||
"Vertical",
|
|
||||||
1);
|
|
||||||
|
|
||||||
dijkstra_path_new_to_list(&nodes,
|
// Process arguments
|
||||||
&paths,
|
while((opt = getopt(argc, argv, "vs")) != -1) {
|
||||||
0,5,
|
switch(opt)
|
||||||
10,5,
|
{
|
||||||
"Horizontal",
|
case 'v':
|
||||||
1);
|
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));
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
for (l = 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,
|
||||||
|
path->destination, path->destination->position.x, path->destination->position.y,
|
||||||
|
path->name);
|
||||||
|
}
|
||||||
|
printf("\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) {
|
for (l = 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));
|
free(node);
|
||||||
}
|
}
|
||||||
printf("\n");
|
g_list_free(nodes);
|
||||||
|
|
||||||
for (l = 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,
|
|
||||||
path->destination, path->destination->position.x, path->destination->position.y,
|
|
||||||
path->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\nDone.\n");
|
|
||||||
|
|
||||||
// TODO: Free memory
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user