2 * Hic Est Leo -- Graph and Routing
4 * (c) 2022 Martin Mares <mj@ucw.cz>
10 #include <ucw/clists.h>
11 #include <ucw/mempool.h>
20 static struct mempool *graph_pool;
21 static clist graph_vertices;
25 struct osm_node *node;
30 cnode n; // In src->edges
31 struct graph_vertex *dest;
32 struct graph_edge *twin;
37 static uint num_vertices;
38 static uint num_edges;
40 static struct graph_vertex *graph_lookup_vertex(struct osm_node *n)
44 struct graph_vertex *v = mp_alloc_zero(graph_pool, sizeof(*v));
47 clist_init(&v->edges);
48 clist_add_tail(&graph_vertices, &v->n);
54 static struct graph_vertex *graph_vertex_by_node_id(osm_id_t id)
56 struct osm_node *n = (struct osm_node *) osm_obj_find_by_id(OSM_TYPE_NODE, id);
58 die("Cannot find node #%jd", (uintmax_t) id);
60 ASSERT(n->vertex->node);
64 static struct graph_edge *graph_add_edge(struct graph_vertex *u, struct graph_vertex *v, struct osm_way *way, double length)
66 struct graph_edge *e1 = mp_alloc_zero(graph_pool, sizeof(*e1));
67 struct graph_edge *e2 = mp_alloc_zero(graph_pool, sizeof(*e2));
70 clist_add_tail(&u->edges, &e1->n);
76 clist_add_tail(&v->edges, &e2->n);
85 static void graph_optimize(void)
87 struct graph_vertex *v, *tmp;
89 CLIST_WALK_DELSAFE(v, graph_vertices, tmp)
92 CLIST_FOR_EACH(struct graph_edge *, e, v->edges)
97 struct graph_edge *e1 = clist_remove_head(&v->edges);
98 struct graph_edge *f1 = clist_remove_head(&v->edges);
99 struct graph_vertex *x = e1->dest;
100 struct graph_vertex *y = f1->dest;
101 clist_remove(&e1->twin->n);
102 clist_remove(&f1->twin->n);
108 graph_add_edge(x, y, e1->way, e1->length + f1->length);
113 static bool way_is_edge(struct osm_way *w)
115 osm_val_t hwy = osm_obj_find_tag(&w->o, KEY_HIGHWAY);
120 case VALUE_SECONDARY:
121 case VALUE_MOTORWAY_LINK:
122 case VALUE_TRUNK_LINK:
123 case VALUE_PRIMARY_LINK:
124 case VALUE_SECONDARY_LINK:
131 static void way_add_edge(struct osm_way *w)
133 struct osm_node *prev_n = NULL;
134 struct graph_vertex *prev_v = NULL;
136 OSM_FOR_EACH_BEGIN(struct osm_node *, n, w->nodes)
138 struct graph_vertex *v = graph_lookup_vertex(n);
141 double length = hypot(n->x - prev_n->x, n->y - prev_n->y);
142 graph_add_edge(prev_v, v, w, length);
150 void graph_build(void)
152 graph_pool = mp_new(65536);
153 clist_init(&graph_vertices);
155 // We are considering only the first data source for the graph.
156 // Otherwise, things start becoming ugly, because node IDs are generally not unique.
158 struct data_source *ds = clist_head(&map_sources);
161 CLIST_FOR_EACH(struct osm_way *, w, osm_this->obj_list[OSM_TYPE_WAY])
166 msg(L_INFO, "Built road graph: %u vertices, %u edges", num_vertices, num_edges);
169 msg(L_INFO, "Optimized road graph: %u vertices, %u edges", num_vertices, num_edges);
171 struct graph_vertex *v1 = graph_vertex_by_node_id(32292698); // Praha-Zbraslav, K Přehradám
172 struct graph_vertex *v2 = graph_vertex_by_node_id(21289321); // Brno, Heršpická x Opuštěná
173 msg(L_INFO, "Finding path from #%jd to #%jd", (uintmax_t) v1->node->o.id, (uintmax_t) v2->node->o.id);