8 #include <ucw/mempool.h>
13 #include "lab-utils.h"
14 #include "lab-bitmaps.h"
15 #include "lab-lines.h"
17 #define BLOCK_SIZE 4096
31 struct graph_edge *first;
38 struct graph_edge **edges;
48 struct graph_edge *prev;
49 struct graph_edge *next;
50 struct graph_node *n1;
51 struct graph_node *n2;
54 struct sym_line *line;
57 struct graph_node *anode;
58 struct graph_node *bnode; // DEBUG PRINT
62 #define HASH_NODE struct graph_node
63 #define HASH_PREFIX(x) hash_##x
64 #define HASH_KEY_ATOMIC id
65 #define HASH_WANT_FIND
67 #define HASH_WANT_CLEANUP
68 #include <ucw/hashtable.h>
70 static void bfs(uns longline);
71 static void bfs_edge(struct graph_edge *e, struct graph_node *node, struct graph_node *anode, enum edge_dir dir);
73 static void make_graph(void);
74 static void label_graph(void);
75 static void make_segments(void);
76 static void make_sections(void);
78 static void cut_edge(struct graph_edge *e, double dist);
79 static struct request_line *make_new_line(void);
80 static struct request_section *make_new_section(struct request_line *rl);
81 static struct request_segment *make_new_segment(struct request_section *rls, struct symbol *sym);
84 static int num_edges = 0;
85 static int dbg_num_hits = 0;
87 static struct graph_edge **bfs_queue;
89 static double conf_max_section_length = 80, conf_max_section_overlay = 10;
91 static struct cf_section lines_cf = {
93 CF_DOUBLE("MaxSectionLenght", &conf_max_section_length),
94 CF_DOUBLE("MaxSectionOverlay", &conf_max_section_overlay),
101 cf_declare_section("Labelling", &lines_cf, 0);
104 static struct request_line *make_new_line(void)
106 struct request_line *rl = GARY_PUSH(requests_line);
107 rl->request.ind = num_requests++;
108 rl->request.type = REQUEST_LINE;
109 GARY_INIT(rl->sections, 0);
110 GARY_INIT(rl->request.variants, 0);
115 static struct request_section *make_new_section(struct request_line *rl)
117 struct request_section *rls = GARY_PUSH(rl->sections);
118 rls->request.ind = num_requests++;
119 rls->request.type = REQUEST_SECTION;
120 rls->num_segments = 0;
121 GARY_INIT(rls->segments, 0);
122 GARY_INIT(rls->request.variants, 0);
127 static struct request_segment *make_new_segment(struct request_section *rls, struct symbol *sym)
129 struct request_segment *rs = GARY_PUSH(rls->segments);
132 rs->request.ind = num_requests++;
133 rs->request.type = REQUEST_SEGMENT;
135 GARY_INIT(rs->request.variants, 0);
138 struct variant *v = GARY_PUSH(rs->request.variants);
145 static void make_graph(void)
148 struct mempool *mp_edges = mp_new(BLOCK_SIZE);
150 DEBUG(dbg_graph, VERBOSITY_GENERAL, "Extracting nodes, will iterate over %zu ways\n", GARY_SIZE(buffer_line));
151 for (uns i=0; i<GARY_SIZE(buffer_line); i++)
153 struct osm_way *way = (struct osm_way *) buffer_line[i].line->s.o;
154 struct graph_node *g_prev = NULL;
155 struct osm_node *o_prev = NULL;
157 CLIST_FOR_EACH(struct osm_ref *, ref, way->nodes)
159 // FIXME: Shall osm_object's type be checked here?
160 struct osm_node *o_node = (struct osm_node *) ref->o;
162 struct graph_node *g_node = hash_find(ref->o->id);
165 g_node = hash_new(ref->o->id);
166 GARY_INIT(g_node->edges, 0);
168 g_node->id = ref->o->id;
169 g_node->num = num_nodes++;
179 struct graph_edge *e = mp_alloc(mp_edges, sizeof(struct graph_edge));
180 e->num = num_edges++;
181 e->id = buffer_line[i].line->s.o->id;
182 e->color = buffer_line[i].line->color;
183 e->length = hypot(abs(o_prev->x - o_node->x), abs(o_prev->y - o_node->y));
189 e->longline = (uns) -1;
190 e->line = buffer_line[i].line;
194 struct graph_edge **edge = GARY_PUSH(g_prev->edges);
196 edge = GARY_PUSH(g_node->edges);
205 void dump_graph(void)
207 HASH_FOR_ALL(hash, node)
209 printf("* Node: (%d) #%ju [%.2f; %.2f]\n", node->num, node->id, node->o->x, node->o->y);
210 for (uns i=0; i<GARY_SIZE(node->edges); i++)
212 struct graph_edge *e = node->edges[i];
213 printf("\t edge (%d) #%ju to ", e->num, e->id);
214 if (node->edges[i]->n1->id == node->id)
215 printf("(%d) #%ju [%.2f; %.2f]\n", e->n2->num, e->n2->id, e->n2->o->x, e->n2->o->y);
216 else if (node->edges[i]->n2->id == node->id)
217 printf("(%d) #%ju [%.2f; %.2f]\n", e->n1->num, e->n1->id, e->n1->o->x, e->n1->o->y);
220 // This shouldn't ever happen
221 printf("BEWARE! Edge is associated with a node it doesn't belongs to!\n");
226 if ((node->edges[i]->label) && (node->edges[i]->label->type == SYMBOLIZER_TEXT)) printf(" labelled %s;", osm_val_decode(((struct sym_text *) node->edges[i]->label)->text));
227 else if ((node->edges[i]->label)) printf("Labelled\n");
229 printf(" colored %d;", node->edges[i]->color);
230 printf(" length %.2f", node->edges[i]->length);
237 static void label_graph(void)
239 DEBUG(dbg_graph, VERBOSITY_GENERAL, "There are %zu line labels requested\n", GARY_SIZE(buffer_linelabel));
240 for (uns i=0; i<GARY_SIZE(buffer_linelabel); i++)
242 if (buffer_linelabel[i].label->type == SYMBOLIZER_TEXT)
243 DEBUG(dbg_graph, VERBOSITY_INDIVIDUAL, "Labelling nodes of way %s\n", osm_val_decode(((struct sym_text *) buffer_linelabel[i].label)->text));
244 CLIST_FOR_EACH(struct osm_ref *, ref, buffer_linelabel[i].way->nodes)
246 DEBUG(dbg_graph, VERBOSITY_PLACEMENT, "Looking for node %ju\n", ref->o->id);
247 struct graph_node *n = hash_find(ref->o->id);
250 printf("BEWARE! Requested node couldn't be found.\n");
254 DEBUG(dbg_graph, VERBOSITY_ALL, "Searching among %zu edges\n", GARY_SIZE(n->edges));
255 for (uns j=0; j<GARY_SIZE(n->edges); j++)
257 if (n->edges[j]->id == buffer_linelabel[i].way->o.id)
259 DEBUG(dbg_graph, VERBOSITY_ALL, "Labelling node %ju\n", n->id);
260 n->edges[j]->label = buffer_linelabel[i].label;
261 n->edges[j]->zindex = buffer_linelabel[i].zindex;
269 static void bfs_edge(struct graph_edge *e, struct graph_node *node, struct graph_node *anode, enum edge_dir dir)
271 DEBUG(dbg_bfs, VERBOSITY_PLACEMENT, "BFS edge called for edge %d (going %d) in direction %d\n", e->num, e->dir, dir);
272 struct graph_edge *candidate = NULL;
274 for (uns i=0; i<GARY_SIZE(node->edges); i++)
276 struct graph_edge *other = node->edges[i];
277 if ((other->longline != (uns) -1) && (other->longline != e->longline)) continue;
279 if ((uns) other->visited != e->longline) {
280 DEBUG(dbg_bfs, VERBOSITY_PLACEMENT, "Pushing new edge %d / %ju\n", other->num, other->id);
281 struct graph_edge **e_ptr = GARY_PUSH(bfs_queue);
283 other->visited = e->longline;
286 if (((other->n1->id == node->id) && (other->n2->id == anode->id)) ||
287 ((other->n2->id == node->id) && (other->n1->id == anode->id)))
290 if (((other->n1->id == node->id) || (other->n2->id == node->id)) &&
291 (e->label) && (other->label) &&
292 (e->label->type == SYMBOLIZER_TEXT) && (other->label->type == SYMBOLIZER_TEXT) &&
293 (((struct sym_text *) e->label)->text == ((struct sym_text *) other->label)->text))
295 if (! candidate || (other->length > candidate->length))
302 DEBUG(dbg_bfs, VERBOSITY_PLACEMENT, "New line in longline %u\n", e->longline);
303 struct graph_edge *other = candidate;
304 other->longline = e->longline;
306 if (((dir == DIR_BWD) && (other->n1->id == node->id)) ||
307 ((dir == DIR_FWD) && (other->n2->id == node->id)))
309 struct graph_node *swp = other->n2;
310 other->n2 = other->n1;
319 longlines[other->longline].first = other;
332 static void bfs(uns longline)
334 DEBUG(dbg_bfs, VERBOSITY_INDIVIDUAL, "BFS called for longline %u\n", longline);
335 DEBUG(dbg_bfs, VERBOSITY_INDIVIDUAL, "%zu longlines exist\n", GARY_SIZE(longlines));
337 for (uns i=0; i<GARY_SIZE(bfs_queue); i++)
339 struct graph_edge *cur = bfs_queue[i];
340 DEBUG(dbg_bfs, VERBOSITY_PLACEMENT, "Exploring new edge %d; %zu remaining\n", cur->num, GARY_SIZE(bfs_queue));
342 cur->visited = longline;
344 if (cur->longline == (uns) -1)
347 if (cur->dir == DIR_UNSET)
349 cur->dir = DIR_CENTER;
350 bfs_edge(cur, cur->n1, cur->n2, DIR_BWD);
351 bfs_edge(cur, cur->n2, cur->n1, DIR_FWD);
358 bfs_edge(cur, cur->n1, cur->n2, cur->dir);
361 bfs_edge(cur, cur->n2, cur->n1, cur->dir);
371 static void make_sections(void)
373 GARY_INIT(bfs_queue, 0);
374 GARY_INIT(longlines, 0);
376 HASH_FOR_ALL(hash, node)
378 for (uns i=0; i<GARY_SIZE(node->edges); i++)
380 if ((node->edges[i]->label) && (node->edges[i]->longline == (uns) -1))
382 GARY_PUSH(longlines);
383 longlines[GARY_SIZE(longlines)-1].first = node->edges[i];
385 DEBUG(dbg_bfs, VERBOSITY_INDIVIDUAL, "Running new BFS\n");
386 DEBUG(dbg_bfs, VERBOSITY_INDIVIDUAL, "Creating longline %zu\n", GARY_SIZE(longlines)-1);
388 GARY_RESIZE(bfs_queue, 0);
389 struct graph_edge **e = GARY_PUSH(bfs_queue);
391 node->edges[i]->longline = GARY_SIZE(longlines)-1;
392 bfs(node->edges[i]->longline);
394 DEBUG(dbg_bfs, VERBOSITY_INDIVIDUAL, "Joined %d edges\n", dbg_num_hits); dbg_num_hits = 0;
395 DEBUG(dbg_bfs, VERBOSITY_INDIVIDUAL, "Planned %zu edges\n", GARY_SIZE(bfs_queue));
401 GARY_FREE(bfs_queue);
404 static void cut_edge(struct graph_edge *e, double dist)
406 DEBUG(dbg_segments, VERBOSITY_PLACEMENT, "Cutting [%.2f; %.2f] -- [%.2f; %.2f] to dist %.2f\n", e->n1->o->x, e->n1->o->y, e->n2->o->x, e->n2->o->y, dist);
408 struct graph_edge *new = xmalloc(sizeof(struct graph_edge));
412 switch (e->label->type)
414 case SYMBOLIZER_TEXT:
415 new->label = xmalloc(sizeof(struct sym_text));
416 *((struct sym_text *) new->label) = *((struct sym_text *) e->label);
422 struct osm_node *n1 = e->n1->o;
423 struct osm_node *n2 = e->n2->o;
425 if ((n1->x == n2->x) && (n1->y == n2->y))
427 printf("[%.2f; %.2f] -- [%.2f; %.2f]\n", n1->x, n1->y, n2->x, n2->y);
428 DEBUG(dbg_segments, VERBOSITY_PLACEMENT, "Won't cut point\n");
432 struct osm_node *n11 = xmalloc(sizeof(struct osm_node));
433 struct graph_node *gn = xmalloc(sizeof(struct graph_node));
435 double vsize = hypot(n1->x - n2->x, n1->y - n2->y);
436 n11->x = n1->x + (n2->x - n1->x) / vsize * dist;
437 n11->y = n1->y + (n2->y - n1->y) / vsize * dist;
439 e->n2 = new->n1 = gn;
441 e->length = hypot(abs(n1->x - n11->x), abs(n1->y - n11->y));
442 new->length = hypot(abs(n11->x - n2->x), abs(n11->y - n2->y));
446 static void make_segments(void)
448 for (uns i=0; i<GARY_SIZE(longlines); i++)
450 // Skip lines which are not labelled
451 if (! (longlines[i].first && longlines[i].first->label))
454 struct request_line *request = make_new_line();
455 struct request_section *rls = make_new_section(request);
456 struct request_segment *rs = NULL;
458 struct graph_edge *e = longlines[i].first;
459 double cur_length = 0;
461 struct sym_text *st = NULL;
462 if (e->label->type == SYMBOLIZER_TEXT)
464 st = (struct sym_text *) e->label;
468 // FIXME: Should other label types be supported in future?
469 DEBUG(dbg_segments, VERBOSITY_PLACEMENT, "Warning: Skipping line\n");
473 DEBUG(dbg_segments, VERBOSITY_INDIVIDUAL, "New longline\n");
479 DEBUG(dbg_segments, VERBOSITY_PLACEMENT, "BEWARE: Edge cycle\n");
484 DEBUG(dbg_segments, VERBOSITY_PLACEMENT, "Taking edge from [%.2f; %.2f] to [%.2f; %.2f] of length %.2f\n", e->n1->o->x, e->n1->o->y, e->n2->o->x, e->n2->o->y, e->length);
486 if (st && (e->length < st->tw))
489 DEBUG(dbg_segments, VERBOSITY_PLACEMENT, "Warning: Skipping segment\n");
493 if (cur_length + e->length > conf_max_section_length + conf_max_section_overlay)
495 DEBUG(dbg_segments, VERBOSITY_PLACEMENT, "Edge too long, length is %.2f; %.2f - %.2f = %.2f\n", e->length, conf_max_section_length, cur_length, conf_max_section_length - cur_length);
496 // HACK to prevent cutting to 0 lenght
497 cut_edge(e, max2(conf_max_section_length - cur_length, 2));
500 rs = make_new_segment(rls, NULL);
501 rs->label = xmalloc(sizeof(struct sym_text));
502 *((struct sym_text *) rs->label) = *((struct sym_text *) e->label);
504 rs->x1 = e->n1->o->x;
505 rs->y1 = e->n1->o->y;
506 rs->x2 = e->n2->o->x;
507 rs->y2 = e->n2->o->y;
509 rs->slope = (rs->y2 - rs->y1) / (rs->x2 - rs->x1);
510 ((struct sym_text *) rs->label)->rotate = convert_to_deg(atan(rs->slope));
511 struct variant *v = GARY_PUSH(rs->request.variants);
512 make_bitmap(v, rs->label);
514 rs->zindex = e->zindex;
516 cur_length += e->length;
517 if (cur_length > conf_max_section_length)
519 DEBUG(dbg_segments, VERBOSITY_PLACEMENT, "Making new section, new length would be %f, allowed is %.2f / %.2f\n", cur_length + e->length, conf_max_section_length, conf_max_section_overlay);
521 rls = make_new_section(request);
528 if (request->sections[0].num_segments == 0)
530 DEBUG(dbg_segments, VERBOSITY_INDIVIDUAL, "WARNING: Longline without any segment, skipped\n");
532 struct request_section *rls = &request->sections[0];
533 GARY_FREE(rls->segments);
534 GARY_FREE(rls->request.variants);
536 struct request_line *rl = &requests_line[GARY_SIZE(requests_line)-1];
537 GARY_FREE(rl->sections);
538 GARY_FREE(rl->request.variants);
540 GARY_POP(requests_line);
546 void segment_lines(void)
554 void lines_cleanup(void)
559 void dump_longlines(void)
561 printf("*** Longlines dump\n");
562 for (uns i=0; i<GARY_SIZE(longlines); i++)
564 printf("Longline %u:", i);
565 struct graph_edge *e = longlines[i].first;
566 if ((e->label) && (e->label->type == SYMBOLIZER_TEXT))
567 printf(" labelled %s", osm_val_decode(((struct sym_text *) e->label)->text));
572 printf("\t#%ju (%d): [%.2f; %.2f] -- [%.2f; %.2f] (dir %d)\n",
573 e->id, e->num, e->n1->o->x, e->n1->o->y, e->n2->o->x, e->n2->o->y, e->dir);