lifo-dijkstraserv/src/geojson.c

169 lines
4.2 KiB
C

#include "geojson.h"
#include "dijkstragraph.h"
#include "logging.h"
#include <stdlib.h>
#include <glib-object.h>
#include <json-glib/json-glib.h>
int add_geojson_to_dijkstra(struct dijkstra_solver *solver,
char *filename, char *type)
{
JsonParser *parser;
JsonNode *root;
JsonArray *arr;
JsonNode *node;
JsonReader *reader;
GError *error;
int i, j;
int i_max, j_max;
char *name = NULL;
char *access = NULL;
int x, y, z;
int x_last, y_last, z_last;
char *layer_name;
enum dijkstra_layer_type layer_type;
struct dijkstra_layer *layer = NULL;
struct _stats {
int nodes;
int paths;
} stats = {.nodes = 0, .paths = 0};
report(LL_INFO, "Loading GeoJson '%s' data from %s...", type, filename);
if (!strcmp("streets", type))
layer_type = STREET;
else if (!strcmp("trainlines", type))
layer_type = TRAINLINE;
else if (!strcmp("access", type))
layer_type = ACCESS;
else {
report(LL_ERROR, "Type '%s' not supported.\n", type);
return EXIT_FAILURE;
}
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
if (layer_type == ACCESS) {
access = name;
name = strchr(name, ':');
if (name == NULL) {
report(LL_ERROR,
"Invalid name for accesss. '%s'",
access);
g_object_unref(reader);
continue;
}
*name = '\0';
do
name++;
while (*name == ' ' && *name != '\0');
}
json_reader_read_member(reader, "geometry");
json_reader_read_member(reader, "coordinates");
if (layer_type == STREET) // For streets, this means elevation
z_last = 0; // By default, let's assume height 0
else if (layer_type == ACCESS) // For access, it's the relative speed as well
z_last = 10; // 10 percent
else // For trainlines, z means relative speed to walking
z_last = 1000; // 2 times faster than walking
layer_name = name;
layer = dijkstra_layer_new_to_list(solver, layer_type, layer_name, access);
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 (json_reader_count_elements(reader) > 2) {
json_reader_read_element(reader, 2);
z = json_reader_get_int_value(reader);
json_reader_end_element(reader);
} else {
z = z_last;
}
if (j > 0) {
stats.paths++;
dijkstra_path_new_to_list(solver,
x_last, y_last,
x, y,
z, z_last,
layer,
name,
DIJKSTRA_WEIGHT_AUTO);
}
x_last = x;
y_last = y;
z_last = z;
} 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;
}