/[zanavi_public1]/navit/navit/navigation.c
ZANavi

Contents of /navit/navit/navigation.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 27 - (show annotations) (download)
Mon Apr 9 21:27:36 2012 UTC (11 years, 11 months ago) by zoff99
File MIME type: text/plain
File size: 79814 byte(s)
lots of new stuff, tranlsations, bug fixes ...
1 /**
2 * ZANavi, Zoff Android Navigation system.
3 * Copyright (C) 2011-2012 Zoff <zoff@zoff.cc>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 /**
21 * Navit, a modular navigation system.
22 * Copyright (C) 2005-2008 Navit Team
23 *
24 * This program is free software; you can redistribute it and/or
25 * modify it under the terms of the GNU General Public License
26 * version 2 as published by the Free Software Foundation.
27 *
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
32 *
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the
35 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
36 * Boston, MA 02110-1301, USA.
37 */
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <math.h>
43 #include <ctype.h>
44 #include <glib.h>
45 #include "debug.h"
46 #include "profile.h"
47 #include "navigation.h"
48 #include "coord.h"
49 #include "item.h"
50 #include "route.h"
51 #include "transform.h"
52 #include "mapset.h"
53 #include "projection.h"
54 #include "map.h"
55 #include "navit.h"
56 #include "callback.h"
57 #include "speech.h"
58 #include "vehicleprofile.h"
59 #include "plugin.h"
60 #include "navit_nls.h"
61
62 /* #define DEBUG */
63
64 static int roundabout_extra_length = 50;
65
66 struct suffix
67 {
68 char *fullname;
69 char *abbrev;
70 int sex;
71 } suffixes[] =
72 {
73 { "weg", NULL, 1 },
74 { "platz", "pl.", 1 },
75 { "ring", NULL, 1 },
76 { "allee", NULL, 2 },
77 { "gasse", NULL, 2 },
78 { "straße", "str.", 2 },
79 { "strasse", NULL, 2 }, };
80
81 struct navigation
82 {
83 struct route *route;
84 struct map *map;
85 struct item_hash *hash;
86 struct vehicleprofile *vehicleprofile;
87 struct navigation_itm *first;
88 struct navigation_itm *last;
89 struct navigation_command *cmd_first;
90 struct navigation_command *cmd_last;
91 struct callback_list *callback_speech;
92 struct callback_list *callback;
93 struct navit *navit;
94 struct speech *speech;
95 int level_last;
96 struct item item_last;
97 int turn_around;
98 int turn_around_limit;
99 int distance_turn;
100 struct callback *route_cb;
101 int announce[route_item_last - route_item_first + 1][3];
102 int tell_street_name;
103 int delay;
104 int curr_delay;
105 };
106
107 int distances[] =
108 { 1, 2, 3, 4, 5, 10, 25, 50, 75, 100, 150, 200, 250, 300, 400, 500, 750, -1 };
109
110 struct navigation_command
111 {
112 struct navigation_itm *itm;
113 struct navigation_command *next;
114 struct navigation_command *prev;
115 int delta;
116 int roundabout_delta;
117 int length;
118 };
119
120 static void navigation_flush(struct navigation *this_);
121
122 /**
123 * @brief Calculates the delta between two angles
124 * @param angle1 The first angle
125 * @param angle2 The second angle
126 * @return The difference between the angles: -179..-1=angle2 is left of angle1,0=same,1..179=angle2 is right of angle1,180=angle1 is opposite of angle2
127 */
128
129 static int angle_delta(int angle1, int angle2)
130 {
131 int delta = angle2 - angle1;
132 if (delta <= -180)
133 delta += 360;
134 if (delta > 180)
135 delta -= 360;
136 return delta;
137 }
138
139 static int angle_median(int angle1, int angle2)
140 {
141 int delta = angle_delta(angle1, angle2);
142 int ret = angle1 + delta / 2;
143 if (ret < 0)
144 ret += 360;
145 if (ret > 360)
146 ret -= 360;
147 return ret;
148 }
149
150 static int angle_opposite(int angle)
151 {
152 return ((angle + 180) % 360);
153 }
154
155 int navigation_get_attr(struct navigation *this_, enum attr_type type,
156 struct attr *attr, struct attr_iter *iter)
157 {
158 struct map_rect *mr;
159 struct item *item;
160 dbg(1, "enter %s\n", attr_to_name(type));
161 switch (type)
162 {
163 case attr_map:
164 attr->u.map = this_->map;
165 break;
166 case attr_item_type:
167 case attr_length:
168 case attr_navigation_speech:
169 mr = map_rect_new(this_->map, NULL);
170 while ((item = map_rect_get_item(mr)))
171 {
172 if (item->type != type_nav_none && item->type
173 != type_nav_position)
174 {
175 if (type == attr_item_type)
176 attr->u.item_type = item->type;
177 else
178 {
179 if (!item_attr_get(item, type, attr))
180 item = NULL;
181 }
182 break;
183 }
184 }
185 map_rect_destroy(mr);
186 if (!item)
187 return 0;
188 break;
189 default:
190 return 0;
191 }
192 attr->type = type;
193 return 1;
194 }
195
196 int navigation_set_attr(struct navigation *this_, struct attr *attr)
197 {
198 switch (attr->type)
199 {
200 case attr_speech:
201 this_->speech = attr->u.speech;
202 return 1;
203 default:
204 return 0;
205 }
206 }
207
208 struct navigation *
209 navigation_new(struct attr *parent, struct attr **attrs)
210 {
211 int i, j;
212 struct attr * attr;
213 struct navigation *ret=g_new0(struct navigation, 1);
214 ret->hash = item_hash_new();
215 ret->callback = callback_list_new();
216 ret->callback_speech = callback_list_new();
217 ret->level_last = -2;
218 ret->distance_turn = 50;
219 ret->turn_around_limit = 3;
220 ret->navit = parent->u.navit;
221 ret->tell_street_name = 1;
222
223 for (j = 0; j <= route_item_last - route_item_first; j++)
224 {
225 for (i = 0; i < 3; i++)
226 {
227 ret->announce[j][i] = -1;
228 }
229 }
230
231 if ((attr = attr_search(attrs, NULL, attr_tell_street_name)))
232 {
233 ret->tell_street_name = attr->u.num;
234 }
235 if ((attr = attr_search(attrs, NULL, attr_delay)))
236 {
237 ret->delay = attr->u.num;
238 }
239
240 return ret;
241 }
242
243 int navigation_set_announce(struct navigation *this_, enum item_type type,
244 int *level)
245 {
246 int i;
247 if (type < route_item_first || type > route_item_last)
248 {
249 dbg(0, "street type %d out of range [%d,%d]", type, route_item_first,
250 route_item_last);
251 return 0;
252 }
253 for (i = 0; i < 3; i++)
254 this_->announce[type - route_item_first][i] = level[i];
255 return 1;
256 }
257
258 static int navigation_get_announce_level(struct navigation *this_,
259 enum item_type type, int dist)
260 {
261 int i;
262
263 if (type < route_item_first || type > route_item_last)
264 return -1;
265 for (i = 0; i < 3; i++)
266 {
267 if (dist <= this_->announce[type - route_item_first][i])
268 return i;
269 }
270 return i;
271 }
272
273 /**
274 * @brief Holds a way that one could possibly drive from a navigation item
275 */
276 struct navigation_way
277 {
278 struct navigation_way *next; /**< Pointer to a linked-list of all navigation_ways from this navigation item */
279 short dir; /**< The direction -1 or 1 of the way */
280 short angle2; /**< The angle one has to steer to drive from the old item to this street */
281 int flags; /**< The flags of the way */
282 struct item item; /**< The item of the way */
283 char *name1;
284 char *name2;
285 };
286
287 struct navigation_itm
288 {
289 struct navigation_way way;
290 int angle_end;
291 struct coord start, end;
292 int time;
293 int length;
294 int speed;
295 int dest_time;
296 int dest_length;
297 int told; /**< Indicates if this item's announcement has been told earlier and should not be told again*/
298 int streetname_told; /**< Indicates if this item's streetname has been told in speech navigation*/
299 int dest_count;
300 struct navigation_itm *next;
301 struct navigation_itm *prev;
302 };
303
304 static int is_way_allowed(struct navigation *nav, struct navigation_way *way,
305 int mode);
306
307 static int navigation_get_announce_level_cmd(struct navigation *this_,
308 struct navigation_itm *itm, struct navigation_command *cmd,
309 int distance)
310 {
311 int level2, level = navigation_get_announce_level(this_,
312 itm->way.item.type, distance);
313 if (this_->cmd_first->itm->prev)
314 {
315 level2 = navigation_get_announce_level(this_,
316 cmd->itm->prev->way.item.type, distance);
317 if (level2 > level)
318 level = level2;
319 }
320 return level;
321 }
322
323 /* 0=N,90=E */
324 static int road_angle(struct coord *c1, struct coord *c2, int dir)
325 {
326 int ret = transform_get_angle_delta(c1, c2, dir);
327 // dbg(1, "road_angle(0x%x,0x%x - 0x%x,0x%x)=%d\n", c1->x, c1->y, c2->x, c2->y, ret);
328 return ret;
329 }
330
331 static char *get_count_str(int n)
332 {
333 switch (n)
334 {
335 case 0:
336 #ifdef HAVE_API_ANDROID
337 android_send_generic_text(1,"+*#O:zeroth\n");
338 #endif
339 // TRANSLATORS: the following counts refer to streets (example: turn right after the zeroth street)
340 return _("zeroth"); // Not sure if this exists, neither if it will ever be needed
341 case 1:
342 #ifdef HAVE_API_ANDROID
343 android_send_generic_text(1,"+*#O:first\n");
344 #endif
345 // TRANSLATORS: the following counts refer to streets (example: turn right after the first street)
346 return _("first");
347 case 2:
348 #ifdef HAVE_API_ANDROID
349 android_send_generic_text(1,"+*#O:second\n");
350 #endif
351 // TRANSLATORS: the following counts refer to streets (example: turn right after the second street)
352 return _("second");
353 case 3:
354 #ifdef HAVE_API_ANDROID
355 android_send_generic_text(1,"+*#O:third\n");
356 #endif
357 // TRANSLATORS: the following counts refer to streets (example: turn right after the third street)
358 return _("third");
359 case 4:
360 #ifdef HAVE_API_ANDROID
361 android_send_generic_text(1,"+*#O:fourth\n");
362 #endif
363 // TRANSLATORS: the following counts refer to streets (example: turn right after the fourth street)
364 return _("fourth");
365 case 5:
366 #ifdef HAVE_API_ANDROID
367 android_send_generic_text(1,"+*#O:fifth\n");
368 #endif
369 // TRANSLATORS: the following counts refer to streets (example: turn right after the fifth street)
370 return _("fifth");
371 case 6:
372 #ifdef HAVE_API_ANDROID
373 android_send_generic_text(1,"+*#O:sixth\n");
374 #endif
375 // TRANSLATORS: the following counts refer to streets (example: turn right after the sixth street)
376 return _("sixth");
377 case 7:
378 #ifdef HAVE_API_ANDROID
379 android_send_generic_text(1,"+*#O:seventh\n");
380 #endif
381 // TRANSLATORS: the following counts refer to streets (example: turn right after the seventh street)
382 return _("seventh");
383 case 8:
384 #ifdef HAVE_API_ANDROID
385 android_send_generic_text(1,"+*#O:eighth\n");
386 #endif
387 // TRANSLATORS: the following counts refer to streets (example: turn right after the eighth street)
388 return _("eighth");
389 case 9:
390 #ifdef HAVE_API_ANDROID
391 android_send_generic_text(1,"+*#O:ninth\n");
392 #endif
393 // TRANSLATORS: the following counts refer to streets (example: turn right after the ninth street)
394 return _("ninth");
395 default:
396 return NULL;
397 }
398 }
399
400 static char *get_exit_count_str(int n)
401 {
402 switch (n)
403 {
404 case 0:
405 #ifdef HAVE_API_ANDROID
406 android_send_generic_text(1,"+*#O:zeroth exit\n");
407 #endif
408 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the zeroth exit)
409 return _("zeroth exit"); // Not sure if this exists, neither if it will ever be needed
410 case 1:
411 #ifdef HAVE_API_ANDROID
412 android_send_generic_text(1,"+*#O:first exit\n");
413 #endif
414 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the first exit)
415 return _("first exit");
416 case 2:
417 #ifdef HAVE_API_ANDROID
418 android_send_generic_text(1,"+*#O:second exit\n");
419 #endif
420 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the second exit)
421 return _("second exit");
422 case 3:
423 #ifdef HAVE_API_ANDROID
424 android_send_generic_text(1,"+*#O:third exit\n");
425 #endif
426 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the third exit)
427 return _("third exit");
428 case 4:
429 #ifdef HAVE_API_ANDROID
430 android_send_generic_text(1,"+*#O:fourth exit\n");
431 #endif
432 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the fourth exit)
433 return _("fourth exit");
434 case 5:
435 #ifdef HAVE_API_ANDROID
436 android_send_generic_text(1,"+*#O:fifth exit\n");
437 #endif
438 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the fifth exit)
439 return _("fifth exit");
440 case 6:
441 #ifdef HAVE_API_ANDROID
442 android_send_generic_text(1,"+*#O:sixth exit\n");
443 #endif
444 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the sixth exit)
445 return _("sixth exit");
446 case 7:
447 #ifdef HAVE_API_ANDROID
448 android_send_generic_text(1,"+*#O:seventh exit\n");
449 #endif
450 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the seventh exit)
451 return _("seventh exit");
452 case 8:
453 #ifdef HAVE_API_ANDROID
454 android_send_generic_text(1,"+*#O:eighth exit\n");
455 #endif
456 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the eighth exit)
457 return _("eighth exit");
458 case 9:
459 #ifdef HAVE_API_ANDROID
460 android_send_generic_text(1,"+*#O:ninth exit\n");
461 #endif
462 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the ninth exit)
463 return _("ninth exit");
464 default:
465 return NULL;
466 }
467 }
468 static int round_distance(int dist)
469 {
470 if (dist < 100)
471 {
472 dist = (dist + 5) / 10;
473 return dist * 10;
474 }
475 if (dist < 250)
476 {
477 dist = (dist + 13) / 25;
478 return dist * 25;
479 }
480 if (dist < 500)
481 {
482 dist = (dist + 25) / 50;
483 return dist * 50;
484 }
485 if (dist < 1000)
486 {
487 dist = (dist + 50) / 100;
488 return dist * 100;
489 }
490 if (dist < 5000)
491 {
492 dist = (dist + 50) / 100;
493 return dist * 100;
494 }
495 if (dist < 100000)
496 {
497 dist = (dist + 500) / 1000;
498 return dist * 1000;
499 }
500 dist = (dist + 5000) / 10000;
501 return dist * 10000;
502 }
503
504 static int round_for_vocabulary(int vocabulary, int dist, int factor)
505 {
506 if (!(vocabulary & 256))
507 {
508 if (factor != 1)
509 dist = (dist + factor / 2) / factor;
510 }
511 else
512 factor = 1;
513 if (!(vocabulary & 255))
514 {
515 int i = 0, d = 0, m = 0;
516 while (distances[i] > 0)
517 {
518 if (!i || abs(distances[i] - dist) <= d)
519 {
520 d = abs(distances[i] - dist);
521 m = i;
522 }
523 if (distances[i] > dist)
524 break;
525 i++;
526 }
527 // dbg(0, "converted %d to %d with factor %d\n", dist, distances[m], factor);
528 dist = distances[m];
529 }
530 return dist * factor;
531 }
532
533 static int vocabulary_last(int vocabulary)
534 {
535 int i = 0;
536 if (vocabulary == 65535)
537 return 1000;
538 while (distances[i] > 0)
539 i++;
540 return distances[i - 1];
541 }
542
543 static char *
544 get_distance(struct navigation *nav, int dist, enum attr_type type,
545 int is_length)
546 {
547 int imperial = 0, vocabulary = 65535;
548 struct attr attr;
549
550 if (type == attr_navigation_long)
551 {
552 if (is_length)
553 {
554 #ifdef HAVE_API_ANDROID
555 android_send_generic_text(1,"+*#O:%d m\n");
556 #endif
557 return g_strdup_printf(_("%d m"), dist);
558 }
559 else
560 {
561 #ifdef HAVE_API_ANDROID
562 android_send_generic_text(1,"+*#O:in %d m\n");
563 #endif
564 return g_strdup_printf(_("in %d m"), dist);
565 }
566 }
567 if (navit_get_attr(nav->navit, attr_imperial, &attr, NULL))
568 imperial = attr.u.num;
569 if (nav->speech && speech_get_attr(nav->speech, attr_vocabulary_distances,
570 &attr, NULL))
571 vocabulary = attr.u.num;
572 if (imperial)
573 {
574 if (dist * FEET_PER_METER < vocabulary_last(vocabulary))
575 {
576 dist = round_for_vocabulary(vocabulary, dist * FEET_PER_METER, 1);
577 if (is_length)
578 {
579 #ifdef HAVE_API_ANDROID
580 android_send_generic_text(1,"+*#O:%d feet\n");
581 #endif
582 return g_strdup_printf(_("%d feet"), dist);
583 }
584 else
585 {
586 #ifdef HAVE_API_ANDROID
587 android_send_generic_text(1,"+*#O:in %d feet\n");
588 #endif
589 return g_strdup_printf(_("in %d feet"), dist);
590 }
591 }
592 }
593 else
594 {
595 if (dist < vocabulary_last(vocabulary))
596 {
597 dist = round_for_vocabulary(vocabulary, dist, 1);
598 if (is_length)
599 {
600 #ifdef HAVE_API_ANDROID
601 android_send_generic_text(1,"+*#O:%d meters\n");
602 gchar* xy=g_strdup_printf("+*#1:%d\n", dist);
603 android_send_generic_text(1,xy);
604 g_free(xy);
605 #endif
606 return g_strdup_printf(_("%d meters"), dist);
607 }
608 else
609 {
610 #ifdef HAVE_API_ANDROID
611 android_send_generic_text(1,"+*#O:in %d meters\n");
612 gchar* xy=g_strdup_printf("+*#1:%d\n", dist);
613 android_send_generic_text(1,xy);
614 g_free(xy);
615 #endif
616 return g_strdup_printf(_("in %d meters"), dist);
617 }
618 }
619 }
620 if (imperial)
621 {
622 dist = round_for_vocabulary(vocabulary,
623 dist * FEET_PER_METER * 1000 / FEET_PER_MILE, 1000);
624 }
625 else
626 {
627 dist = round_for_vocabulary(vocabulary, dist, 1000);
628 }
629
630 if (dist < 5000)
631 {
632 int rem = (dist / 100) % 10;
633 if (rem)
634 {
635 if (imperial)
636 {
637 if (is_length)
638 {
639 #ifdef HAVE_API_ANDROID
640 android_send_generic_text(1,"+*#O:%d.%d miles\n");
641 #endif
642 return g_strdup_printf(_("%d.%d miles"), dist / 1000, rem);
643 }
644 else
645 {
646 #ifdef HAVE_API_ANDROID
647 android_send_generic_text(1,"+*#O:in %d.%d miles\n");
648 #endif
649 return g_strdup_printf(_("in %d.%d miles"), dist / 1000,
650 rem);
651 }
652 }
653 else
654 {
655 if (is_length)
656 {
657 #ifdef HAVE_API_ANDROID
658 android_send_generic_text(1,"+*#O:%d.%d kilometers\n");
659 #endif
660 return g_strdup_printf(_("%d.%d kilometers"), dist / 1000,
661 rem);
662 }
663 else
664 {
665 #ifdef HAVE_API_ANDROID
666 android_send_generic_text(1,"+*#O:in %d.%d kilometers\n");
667 #endif
668 return g_strdup_printf(_("in %d.%d kilometers"),
669 dist / 1000, rem);
670 }
671 }
672 }
673 }
674 if (imperial)
675 {
676 if (is_length)
677 return g_strdup_printf(
678 ngettext("one mile", "%d miles", dist / 1000), dist / 1000);
679 else
680 return g_strdup_printf(
681 ngettext("in one mile", "in %d miles", dist / 1000),
682 dist / 1000);
683 }
684 else
685 {
686 if (is_length)
687 {
688 #ifdef HAVE_API_ANDROID
689 android_send_generic_text(1,"+*#O:one kilometer|%d kilometers\n");
690 #endif
691 return g_strdup_printf(
692 ngettext("one kilometer", "%d kilometers", dist / 1000),
693 dist / 1000);
694 }
695 else
696 {
697 #ifdef HAVE_API_ANDROID
698 android_send_generic_text(1,"+*#O:in one kilometer|in %d kilometers\n");
699 #endif
700 return g_strdup_printf(
701 ngettext("in one kilometer", "in %d kilometers",
702 dist / 1000), dist / 1000);
703 }
704 }
705 }
706
707 /**
708 * @brief This calculates the angle with which an item starts or ends
709 *
710 * This function can be used to get the angle an item (from a route graph map)
711 * starts or ends with. Note that the angle will point towards the inner of
712 * the item.
713 *
714 * This is meant to be used with items from a route graph map
715 * With other items this will probably not be optimal...
716 *
717 * @param w The way which should be calculated
718 */
719 static void calculate_angle(struct navigation_way *w)
720 {
721 struct coord cbuf[2];
722 struct item *ritem; // the "real" item
723 struct coord c;
724 struct map_rect *mr;
725 struct attr attr;
726
727 w->angle2 = 361;
728 mr = map_rect_new(w->item.map, NULL);
729 if (!mr)
730 return;
731
732 ritem = map_rect_get_item_byid(mr, w->item.id_hi, w->item.id_lo);
733 if (!ritem)
734 {
735 dbg(1, "Item from segment not found on map!\n");
736 map_rect_destroy(mr);
737 return;
738 }
739
740 if (ritem->type < type_line || ritem->type >= type_area)
741 {
742 map_rect_destroy(mr);
743 return;
744 }
745 if (item_attr_get(ritem, attr_flags, &attr))
746 w->flags = attr.u.num;
747 else
748 w->flags = 0;
749 if (item_attr_get(ritem, attr_street_name, &attr))
750 w->name1 = map_convert_string(ritem->map, attr.u.str);
751 else
752 w->name1 = NULL;
753 if (item_attr_get(ritem, attr_street_name_systematic, &attr))
754 w->name2 = map_convert_string(ritem->map, attr.u.str);
755 else
756 w->name2 = NULL;
757
758 if (w->dir < 0)
759 {
760 if (item_coord_get(ritem, cbuf, 2) != 2)
761 {
762 dbg(1,
763 "Using calculate_angle() with a less-than-two-coords-item?\n");
764 map_rect_destroy(mr);
765 return;
766 }
767
768 while (item_coord_get(ritem, &c, 1))
769 {
770 cbuf[0] = cbuf[1];
771 cbuf[1] = c;
772 }
773
774 }
775 else
776 {
777 if (item_coord_get(ritem, cbuf, 2) != 2)
778 {
779 dbg(1,
780 "Using calculate_angle() with a less-than-two-coords-item?\n");
781 map_rect_destroy(mr);
782 return;
783 }
784 c = cbuf[0];
785 cbuf[0] = cbuf[1];
786 cbuf[1] = c;
787 }
788
789 map_rect_destroy(mr);
790
791 w->angle2 = road_angle(&cbuf[1], &cbuf[0], 0);
792 }
793
794 /**
795 * @brief Returns the time (in seconds) one will drive between two navigation items
796 *
797 * This function returns the time needed to drive between two items, including both of them,
798 * in seconds.
799 *
800 * @param from The first item
801 * @param to The last item
802 * @return The travel time in seconds, or -1 on error
803 */
804 static int navigation_time(struct navigation_itm *from,
805 struct navigation_itm *to)
806 {
807 struct navigation_itm *cur;
808 int time;
809
810 time = 0;
811 cur = from;
812 while (cur)
813 {
814 time += cur->time;
815
816 if (cur == to)
817 {
818 break;
819 }
820 cur = cur->next;
821 }
822
823 if (!cur)
824 {
825 return -1;
826 }
827
828 return time;
829 }
830
831 /**
832 * @brief Clears the ways one can drive from itm
833 *
834 * @param itm The item that should have its ways cleared
835 */
836 static void navigation_itm_ways_clear(struct navigation_itm *itm)
837 {
838 struct navigation_way *c, *n;
839
840 c = itm->way.next;
841 while (c)
842 {
843 n = c->next;
844 map_convert_free(c->name1);
845 map_convert_free(c->name2);
846 g_free(c);
847 c = n;
848 }
849
850 itm->way.next = NULL;
851 }
852
853 /**
854 * @brief Updates the ways one can drive from itm
855 *
856 * This updates the list of possible ways to drive to from itm. The item "itm" is on
857 * and the next navigation item are excluded.
858 *
859 * @param itm The item that should be updated
860 * @param graph_map The route graph's map that these items are on
861 */
862 static void navigation_itm_ways_update(struct navigation_itm *itm,
863 struct map *graph_map)
864 {
865 struct map_selection coord_sel;
866 struct map_rect *g_rect; // Contains a map rectangle from the route graph's map
867 struct item *i, *sitem;
868 struct attr sitem_attr, direction_attr;
869 struct navigation_way *w, *l;
870
871 navigation_itm_ways_clear(itm);
872
873 // These values cause the code in route.c to get us only the route graph point and connected segments
874 coord_sel.next = NULL;
875 coord_sel.u.c_rect.lu = itm->start;
876 coord_sel.u.c_rect.rl = itm->start;
877 // the selection's order is ignored
878
879 g_rect = map_rect_new(graph_map, &coord_sel);
880
881 i = map_rect_get_item(g_rect);
882 if (!i || i->type != type_rg_point)
883 { // probably offroad?
884 return;
885 }
886
887 w = NULL;
888
889 while (1)
890 {
891 i = map_rect_get_item(g_rect);
892
893 if (!i)
894 {
895 break;
896 }
897
898 if (i->type != type_rg_segment)
899 {
900 continue;
901 }
902
903 if (!item_attr_get(i, attr_street_item, &sitem_attr))
904 {
905 dbg(1,
906 "Got no street item for route graph item in entering_straight()\n");
907 continue;
908 }
909
910 if (!item_attr_get(i, attr_direction, &direction_attr))
911 {
912 continue;
913 }
914
915 sitem = sitem_attr.u.item;
916 if (sitem->type == type_street_turn_restriction_no || sitem->type
917 == type_street_turn_restriction_only)
918 continue;
919
920 if (item_is_equal(itm->way.item, *sitem) || ((itm->prev)
921 && item_is_equal(itm->prev->way.item, *sitem)))
922 {
923 continue;
924 }
925
926 l = w;
927 w = g_new(struct navigation_way, 1);
928 w->dir = direction_attr.u.num;
929 w->item = *sitem;
930 w->next = l;
931 calculate_angle(w);
932 }
933
934 map_rect_destroy(g_rect);
935
936 itm->way.next = w;
937 }
938
939 static void navigation_destroy_itms_cmds(struct navigation *this_,
940 struct navigation_itm *end)
941 {
942 struct navigation_itm *itm;
943 struct navigation_command *cmd;
944 // dbg(2, "enter this_=%p this_->first=%p this_->cmd_first=%p end=%p\n", this_, this_->first, this_->cmd_first, end);
945 if (this_->cmd_first)
946 {
947 // dbg(2, "this_->cmd_first->itm=%p\n", this_->cmd_first->itm);
948 }
949 while (this_->first && this_->first != end)
950 {
951 itm = this_->first;
952 // dbg(3, "destroying %p\n", itm);
953 item_hash_remove(this_->hash, &itm->way.item);
954 this_->first = itm->next;
955 if (this_->first)
956 this_->first->prev = NULL;
957 if (this_->cmd_first && this_->cmd_first->itm == itm->next)
958 {
959 cmd = this_->cmd_first;
960 this_->cmd_first = cmd->next;
961 if (cmd->next)
962 {
963 cmd->next->prev = NULL;
964 }
965 g_free(cmd);
966 }
967 map_convert_free(itm->way.name1);
968 map_convert_free(itm->way.name2);
969 navigation_itm_ways_clear(itm);
970 g_free(itm);
971 }
972 if (!this_->first)
973 this_->last = NULL;
974 if (!this_->first && end)
975 {
976 // dbg(0, "end wrong\n");
977 }
978 // dbg(2, "ret this_->first=%p this_->cmd_first=%p\n", this_->first, this_->cmd_first);
979 }
980
981 static void navigation_itm_update(struct navigation_itm *itm,
982 struct item *ritem)
983 {
984 struct attr length, time, speed;
985
986 if (!item_attr_get(ritem, attr_length, &length))
987 {
988 // dbg(0, "no length\n");
989 return;
990 }
991 if (!item_attr_get(ritem, attr_time, &time))
992 {
993 // dbg(0, "no time\n");
994 return;
995 }
996 if (!item_attr_get(ritem, attr_speed, &speed))
997 {
998 // dbg(0, "no time\n");
999 return;
1000 }
1001
1002 // dbg(1, "length=%d time=%d speed=%d\n", length.u.num, time.u.num, speed.u.num);
1003 itm->length = length.u.num;
1004 itm->time = time.u.num;
1005 itm->speed = speed.u.num;
1006 }
1007
1008 /**
1009 * @brief This check if an item is part of a roundabout
1010 *
1011 * @param itm The item to be checked
1012 * @return True if the item is part of a roundabout
1013 */
1014 static int check_roundabout(struct navigation_itm *itm, struct map *graph_map)
1015 {
1016 struct map_selection coord_sel;
1017 struct map_rect *g_rect; // Contains a map rectangle from the route graph's map
1018 struct item *i, *sitem;
1019 struct attr sitem_attr, flags_attr;
1020
1021 // These values cause the code in route.c to get us only the route graph point and connected segments
1022 coord_sel.next = NULL;
1023 coord_sel.u.c_rect.lu = itm->start;
1024 coord_sel.u.c_rect.rl = itm->start;
1025 // the selection's order is ignored
1026
1027 g_rect = map_rect_new(graph_map, &coord_sel);
1028
1029 i = map_rect_get_item(g_rect);
1030 if (!i || i->type != type_rg_point)
1031 { // probably offroad?
1032 map_rect_destroy(g_rect);
1033 return 0;
1034 }
1035
1036 while (1)
1037 {
1038 i = map_rect_get_item(g_rect);
1039
1040 if (!i)
1041 {
1042 break;
1043 }
1044
1045 if (i->type != type_rg_segment)
1046 {
1047 continue;
1048 }
1049
1050 if (!item_attr_get(i, attr_street_item, &sitem_attr))
1051 {
1052 continue;
1053 }
1054
1055 sitem = sitem_attr.u.item;
1056 if (item_is_equal(itm->way.item, *sitem))
1057 {
1058 if (item_attr_get(i, attr_flags, &flags_attr) && (flags_attr.u.num
1059 & AF_ROUNDABOUT))
1060 {
1061 map_rect_destroy(g_rect);
1062 return 1;
1063 }
1064 }
1065 }
1066
1067 map_rect_destroy(g_rect);
1068 return 0;
1069 }
1070
1071 static struct navigation_itm *
1072 navigation_itm_new(struct navigation *this_, struct item *ritem)
1073 {
1074 struct navigation_itm *ret=g_new0(struct navigation_itm, 1);
1075 int i = 0;
1076 struct item *sitem;
1077 struct map *graph_map = NULL;
1078 struct attr street_item, direction, route_attr;
1079 struct map_rect *mr;
1080 struct attr attr;
1081 struct coord c[5];
1082
1083 if (ritem)
1084 {
1085 ret->streetname_told = 0;
1086 if (!item_attr_get(ritem, attr_street_item, &street_item))
1087 {
1088 //dbg(1, "no street item\n");
1089 g_free(ret);
1090 ret = NULL;
1091 return ret;
1092 }
1093 if (item_attr_get(ritem, attr_direction, &direction))
1094 ret->way.dir = direction.u.num;
1095 else
1096 ret->way.dir = 0;
1097
1098 sitem = street_item.u.item;
1099 ret->way.item = *sitem;
1100 item_hash_insert(this_->hash, sitem, ret);
1101 mr = map_rect_new(sitem->map, NULL);
1102 if (!(sitem = map_rect_get_item_byid(mr, sitem->id_hi, sitem->id_lo)))
1103 return NULL;
1104 if (item_attr_get(sitem, attr_street_name, &attr))
1105 ret->way.name1 = map_convert_string(sitem->map, attr.u.str);
1106 if (item_attr_get(sitem, attr_street_name_systematic, &attr))
1107 ret->way.name2 = map_convert_string(sitem->map, attr.u.str);
1108 navigation_itm_update(ret, ritem);
1109
1110 while (item_coord_get(ritem, &c[i], 1))
1111 {
1112 //dbg(1, "coord %d 0x%x 0x%x\n", i, c[i].x, c[i].y);
1113
1114 if (i < 4)
1115 i++;
1116 else
1117 {
1118 c[2] = c[3];
1119 c[3] = c[4];
1120 }
1121 }
1122 //dbg(1, "count=%d\n", i);
1123 i--;
1124
1125 ret->way.angle2 = road_angle(&c[0], &c[1], 0);
1126 ret->angle_end = road_angle(&c[i - 1], &c[i], 0);
1127
1128 ret->start = c[0];
1129 ret->end = c[i];
1130
1131 item_attr_get(ritem, attr_route, &route_attr);
1132 graph_map = route_get_graph_map(route_attr.u.route);
1133 if (check_roundabout(ret, graph_map))
1134 {
1135 ret->way.flags |= AF_ROUNDABOUT;
1136 }
1137
1138 // dbg(1, "i=%d start %d end %d '%s' '%s'\n", i, ret->way.angle2, ret->angle_end, ret->way.name1, ret->way.name2);
1139 map_rect_destroy(mr);
1140 }
1141 else
1142 {
1143 if (this_->last)
1144 ret->start = ret->end = this_->last->end;
1145 }
1146 if (!this_->first)
1147 this_->first = ret;
1148 if (this_->last)
1149 {
1150 this_->last->next = ret;
1151 ret->prev = this_->last;
1152 if (graph_map)
1153 {
1154 navigation_itm_ways_update(ret, graph_map);
1155 }
1156 }
1157 //dbg(1, "ret=%p\n", ret);
1158 this_->last = ret;
1159 return ret;
1160 }
1161
1162 /**
1163 * @brief Counts how many times a driver could turn right/left
1164 *
1165 * This function counts how many times the driver theoretically could
1166 * turn right/left between two navigation items, not counting the final
1167 * turn itself.
1168 *
1169 * @param from The navigation item which should form the start
1170 * @param to The navigation item which should form the end
1171 * @param direction Set to < 0 to count turns to the left >= 0 for turns to the right
1172 * @return The number of possibilities to turn or -1 on error
1173 */
1174 static int count_possible_turns(struct navigation *nav,
1175 struct navigation_itm *from, struct navigation_itm *to, int direction)
1176 {
1177 int count;
1178 struct navigation_itm *curr;
1179 struct navigation_way *w;
1180
1181 count = 0;
1182 curr = from->next;
1183 while (curr && (curr != to))
1184 {
1185 w = curr->way.next;
1186
1187 while (w)
1188 {
1189 if (is_way_allowed(nav, w, 4))
1190 {
1191 if (direction < 0)
1192 {
1193 if (angle_delta(curr->prev->angle_end, w->angle2) < 0)
1194 {
1195 count++;
1196 break;
1197 }
1198 }
1199 else
1200 {
1201 if (angle_delta(curr->prev->angle_end, w->angle2) > 0)
1202 {
1203 count++;
1204 break;
1205 }
1206 }
1207 }
1208 w = w->next;
1209 }
1210 curr = curr->next;
1211 }
1212
1213 if (!curr)
1214 { // from does not lead to to?
1215 return -1;
1216 }
1217
1218 return count;
1219 }
1220
1221 /**
1222 * @brief Calculates distance and time to the destination
1223 *
1224 * This function calculates the distance and the time to the destination of a
1225 * navigation. If incr is set, this is only calculated for the first navigation
1226 * item, which is a lot faster than re-calculation the whole destination, but works
1227 * only if the rest of the navigation already has been calculated.
1228 *
1229 * @param this_ The navigation whose destination / time should be calculated
1230 * @param incr Set this to true to only calculate the first item. See description.
1231 */
1232 static void calculate_dest_distance(struct navigation *this_, int incr)
1233 {
1234 int len = 0, time = 0, count = 0;
1235 struct navigation_itm *next, *itm = this_->last;
1236 //dbg(1, "enter this_=%p, incr=%d\n", this_, incr);
1237 if (incr)
1238 {
1239 if (itm)
1240 {
1241 //dbg(2, "old values: (%p) time=%d lenght=%d\n", itm,
1242 // itm->dest_length, itm->dest_time);
1243 }
1244 else
1245 {
1246 //dbg(2, "old values: itm is null\n");
1247 }
1248 itm = this_->first;
1249 next = itm->next;
1250 //dbg(2, "itm values: time=%d lenght=%d\n", itm->length, itm->time);
1251 //dbg(2, "next values: (%p) time=%d lenght=%d\n", next, next->dest_length, next->dest_time);
1252 itm->dest_length = next->dest_length + itm->length;
1253 itm->dest_count = next->dest_count + 1;
1254 itm->dest_time = next->dest_time + itm->time;
1255 //dbg(2, "new values: time=%d lenght=%d\n", itm->dest_length, itm->dest_time);
1256 return;
1257 }
1258 while (itm)
1259 {
1260 len += itm->length;
1261 time += itm->time;
1262 itm->dest_length = len;
1263 itm->dest_time = time;
1264 itm->dest_count = count++;
1265 itm = itm->prev;
1266 }
1267 //dbg(1, "len %d time %d\n", len, time);
1268 }
1269
1270 /**
1271 * @brief Checks if two navigation items are on the same street
1272 *
1273 * This function checks if two navigation items are on the same street. It returns
1274 * true if either their name or their "systematic name" (e.g. "A6" or "B256") are the
1275 * same.
1276 *
1277 * @param old The first item to be checked
1278 * @param new The second item to be checked
1279 * @return True if both old and new are on the same street
1280 */
1281 static int is_same_street2(char *old_name1, char *old_name2, char *new_name1,
1282 char *new_name2)
1283 {
1284 if (old_name1 && new_name1 && !strcmp(old_name1, new_name1))
1285 {
1286 // dbg(1, "is_same_street: '%s' '%s' vs '%s' '%s' yes (1.)\n", old_name2, new_name2, old_name1, new_name1);
1287 return 1;
1288 }
1289 if (old_name2 && new_name2 && !strcmp(old_name2, new_name2))
1290 {
1291 // dbg(1, "is_same_street: '%s' '%s' vs '%s' '%s' yes (2.)\n", old_name2, new_name2, old_name1, new_name1);
1292 return 1;
1293 }
1294 // dbg(1, "is_same_street: '%s' '%s' vs '%s' '%s' no\n", old_name2, new_name2, old_name1, new_name1);
1295 return 0;
1296 }
1297
1298 #if 0
1299 /**
1300 * @brief Checks if two navigation items are on the same street
1301 *
1302 * This function checks if two navigation items are on the same street. It returns
1303 * true if the first part of their "systematic name" is equal. If the "systematic name" is
1304 * for example "A352/E3" (a german highway which at the same time is part of the international
1305 * E-road network), it would only search for "A352" in the second item's systematic name.
1306 *
1307 * @param old The first item to be checked
1308 * @param new The second item to be checked
1309 * @return True if the "systematic name" of both items matches. See description.
1310 */
1311 static int
1312 is_same_street_systematic(struct navigation_itm *old, struct navigation_itm *new)
1313 {
1314 int slashold,slashnew;
1315 if (!old->name2 || !new->name2)
1316 return 1;
1317 slashold=strcspn(old->name2, "/");
1318 slashnew=strcspn(new->name2, "/");
1319 if (slashold != slashnew || strncmp(old->name2, new->name2, slashold))
1320 return 0;
1321 return 1;
1322 }
1323
1324 /**
1325 * @brief Check if there are multiple possibilities to drive from old
1326 *
1327 * This function checks, if there are multiple streets connected to the exit of "old".
1328 * Sometimes it happens that an item on a map is just segmented, without any other streets
1329 * being connected there, and it is not useful if navit creates a maneuver there.
1330 *
1331 * @param new The navigation item we're driving to
1332 * @return True if there are multiple streets
1333 */
1334 static int
1335 maneuver_multiple_streets(struct navigation_itm *new)
1336 {
1337 if (new->way.next)
1338 {
1339 return 1;
1340 }
1341 else
1342 {
1343 return 0;
1344 }
1345 }
1346
1347 /**
1348 * @brief Check if the new item is entered "straight"
1349 *
1350 * This function checks if the new item is entered "straight" from the old item, i.e. if there
1351 * is no other street one could take from the old item on with less steering.
1352 *
1353 * @param new The navigation item we're driving to
1354 * @param diff The absolute angle one needs to steer to drive to this item
1355 * @return True if the new item is entered "straight"
1356 */
1357 static int
1358 maneuver_straight(struct navigation_itm *new, int diff)
1359 {
1360 int curr_diff;
1361 struct navigation_way *w;
1362
1363 w = new->way.next;
1364 dbg(1,"diff=%d\n", diff);
1365 while (w)
1366 {
1367 curr_diff=abs(angle_delta(new->prev->angle_end, w->angle2));
1368 dbg(1,"curr_diff=%d\n", curr_diff);
1369 if (curr_diff < diff)
1370 {
1371 return 0;
1372 }
1373 w = w->next;
1374 }
1375 return 1;
1376 }
1377 #endif
1378
1379 static int maneuver_category(enum item_type type)
1380 {
1381 switch (type)
1382 {
1383 case type_street_0:
1384 return 1;
1385 case type_street_1_city:
1386 return 2;
1387 case type_street_2_city:
1388 return 3;
1389 case type_street_3_city:
1390 return 4;
1391 case type_street_4_city:
1392 return 5;
1393 case type_highway_city:
1394 return 7;
1395 case type_street_1_land:
1396 return 2;
1397 case type_street_2_land:
1398 return 3;
1399 case type_street_3_land:
1400 return 4;
1401 case type_street_4_land:
1402 return 5;
1403 case type_street_n_lanes:
1404 return 6;
1405 case type_highway_land:
1406 return 7;
1407 case type_ramp:
1408 return 0;
1409 case type_roundabout:
1410 return 0;
1411 case type_ferry:
1412 return 0;
1413 default:
1414 return 0;
1415 }
1416
1417 }
1418
1419 static int is_way_allowed(struct navigation *nav, struct navigation_way *way,
1420 int mode)
1421 {
1422 if (!nav->vehicleprofile)
1423 {
1424 return 1;
1425 }
1426 return !way->flags || ((way->flags
1427 & (way->dir >= 0 ? nav->vehicleprofile->flags_forward_mask
1428 : nav->vehicleprofile->flags_reverse_mask))
1429 == nav->vehicleprofile->flags);
1430 }
1431
1432 /**
1433 * @brief Checks if navit has to create a maneuver to drive from old to new
1434 *
1435 * This function checks if it has to create a "maneuver" - i.e. guide the user - to drive
1436 * from "old" to "new".
1437 *
1438 * @param old The old navigation item, where we're coming from
1439 * @param new The new navigation item, where we're going to
1440 * @param delta The angle the user has to steer to navigate from old to new
1441 * @param reason A text string explaining how the return value resulted
1442 * @return True if navit should guide the user, false otherwise
1443 */
1444 static int maneuver_required2(struct navigation *nav,
1445 struct navigation_itm *old, struct navigation_itm *new, int *delta,
1446 char **reason)
1447 {
1448 int ret = 0, d, dw, dlim;
1449 char *r = NULL;
1450 struct navigation_way *w;
1451 int cat, ncat, wcat, maxcat, left = -180, right = 180, is_unambigous = 0,
1452 is_same_street;
1453
1454 //dbg(1, "enter %p %p %p\n", old, new, delta);
1455 d = angle_delta(old->angle_end, new->way.angle2);
1456 if (!new->way.next)
1457 {
1458 /* No announcement necessary */
1459 r = "no: Only one possibility";
1460 }
1461 else if (!new->way.next->next && new->way.next->item.type == type_ramp
1462 && !is_way_allowed(nav, new->way.next, 1))
1463 {
1464 /* If the other way is only a ramp and it is one-way in the wrong direction, no announcement necessary */
1465 r = "no: Only ramp";
1466 }
1467 if (!r)
1468 {
1469 if ((old->way.flags & AF_ROUNDABOUT) && !(new->way.flags
1470 & AF_ROUNDABOUT))
1471 {
1472 r = "yes: leaving roundabout";
1473 ret = 1;
1474 }
1475 else if (!(old->way.flags & AF_ROUNDABOUT) && (new->way.flags
1476 & AF_ROUNDABOUT))
1477 {
1478 r = "no: entering roundabout";
1479 }
1480 else if ((old->way.flags & AF_ROUNDABOUT) && (new->way.flags
1481 & AF_ROUNDABOUT))
1482 r = "no: staying in roundabout";
1483 }
1484 if (!r && abs(d) > 75)
1485 {
1486 /* always make an announcement if you have to make a sharp turn */
1487 r = "yes: delta over 75";
1488 ret = 1;
1489 }
1490 cat = maneuver_category(old->way.item.type);
1491 ncat = maneuver_category(new->way.item.type);
1492 if (!r)
1493 {
1494 /* Check whether the street keeps its name */
1495 is_same_street = is_same_street2(old->way.name1, old->way.name2,
1496 new->way.name1, new->way.name2);
1497 w = new->way.next;
1498 maxcat = -1;
1499 while (w)
1500 {
1501 dw = angle_delta(old->angle_end, w->angle2);
1502 if (dw < 0)
1503 {
1504 if (dw > left)
1505 left = dw;
1506 }
1507 else
1508 {
1509 if (dw < right)
1510 right = dw;
1511 }
1512 wcat = maneuver_category(w->item.type);
1513 /* If any other street has the same name but isn't a highway (a highway might split up temporarily), then
1514 we can't use the same name criterium */
1515 if (is_same_street && is_same_street2(old->way.name1,
1516 old->way.name2, w->name1, w->name2) && (cat != 7 || wcat
1517 != 7) && is_way_allowed(nav, w, 2))
1518 is_same_street = 0;
1519 /* Even if the ramp has the same name, announce it */
1520 if (new->way.item.type == type_ramp && old->way.item.type
1521 != type_ramp)
1522 is_same_street = 0;
1523 /* Mark if the street has a higher or the same category */
1524 if (wcat > maxcat)
1525 maxcat = wcat;
1526 w = w->next;
1527 }
1528 /* get the delta limit for checking for other streets. It is lower if the street has no other
1529 streets of the same or higher category */
1530 if (ncat < cat)
1531 dlim = 80;
1532 else
1533 dlim = 120;
1534 /* if the street is really straight, the others might be closer to straight */
1535 if (abs(d) < 20)
1536 dlim /= 2;
1537 if ((maxcat == ncat && maxcat == cat) || (ncat == 0 && cat == 0))
1538 dlim = abs(d) * 620 / 256;
1539 else if (maxcat < ncat && maxcat < cat)
1540 dlim = abs(d) * 128 / 256;
1541 if (left < -dlim && right > dlim)
1542 is_unambigous = 1;
1543 if (!is_same_street && is_unambigous < 1)
1544 {
1545 ret = 1;
1546 r = "yes: not same street or ambigous";
1547 }
1548 else
1549 r = "no: same street and unambigous";
1550 #ifdef DEBUG
1551 // r=g_strdup_printf("yes: d %d left %d right %d dlim=%d cat old:%d new:%d max:%d unambigous=%d same_street=%d", d, left, right, dlim, cat, ncat, maxcat, is_unambigous, is_same_street);
1552 #endif
1553 }
1554 *delta = d;
1555 if (reason)
1556 {
1557 *reason = r;
1558 }
1559 return ret;
1560
1561 #if 0
1562 if (new->item.type == old->item.type || (new->item.type != type_ramp && old->item.type != type_ramp))
1563 {
1564 if (is_same_street2(old, new))
1565 {
1566 if (! entering_straight(new, abs(*delta)))
1567 {
1568 dbg(1, "maneuver_required: Not driving straight: yes\n");
1569 if (reason)
1570 *reason="yes: Not driving straight";
1571 return 1;
1572 }
1573
1574 if (check_multiple_streets(new))
1575 {
1576 if (entering_straight(new,abs(*delta)*2))
1577 {
1578 if (reason)
1579 *reason="no: delta < ext_limit for same name";
1580 return 0;
1581 }
1582 if (reason)
1583 *reason="yes: delta > ext_limit for same name";
1584 return 1;
1585 }
1586 else
1587 {
1588 dbg(1, "maneuver_required: Staying on the same street: no\n");
1589 if (reason)
1590 *reason="no: Staying on same street";
1591 return 0;
1592 }
1593 }
1594 }
1595 else
1596 dbg(1, "maneuver_required: old or new is ramp\n");
1597 #if 0
1598 if (old->item.type == type_ramp && (new->item.type == type_highway_city || new->item.type == type_highway_land))
1599 {
1600 dbg(1, "no_maneuver_required: old is ramp new is highway\n");
1601 if (reason)
1602 *reason="no: old is ramp new is highway";
1603 return 0;
1604 }
1605 #endif
1606 #if 0
1607 if (old->crossings_end == 2)
1608 {
1609 dbg(1, "maneuver_required: only 2 connections: no\n");
1610 return 0;
1611 }
1612 #endif
1613 dbg(1,"delta=%d-%d=%d\n", new->way.angle2, old->angle_end, *delta);
1614 if ((new->item.type == type_highway_land || new->item.type == type_highway_city || old->item.type == type_highway_land || old->item.type == type_highway_city) && (!is_same_street_systematic(old, new) || (old->name2 != NULL && new->name2 == NULL)))
1615 {
1616 dbg(1, "maneuver_required: highway changed name\n");
1617 if (reason)
1618 *reason="yes: highway changed name";
1619 return 1;
1620 }
1621 if (abs(*delta) < straight_limit)
1622 {
1623 if (! entering_straight(new,abs(*delta)))
1624 {
1625 if (reason)
1626 *reason="yes: not straight";
1627 dbg(1, "maneuver_required: not driving straight: yes\n");
1628 return 1;
1629 }
1630
1631 dbg(1, "maneuver_required: delta(%d) < %d: no\n", *delta, straight_limit);
1632 if (reason)
1633 *reason="no: delta < limit";
1634 return 0;
1635 }
1636 if (abs(*delta) < ext_straight_limit)
1637 {
1638 if (entering_straight(new,abs(*delta)*2))
1639 {
1640 if (reason)
1641 *reason="no: delta < ext_limit";
1642 return 0;
1643 }
1644 }
1645
1646 if (! check_multiple_streets(new))
1647 {
1648 dbg(1, "maneuver_required: only one possibility: no\n");
1649 if (reason)
1650 *reason="no: only one possibility";
1651 return 0;
1652 }
1653
1654 dbg(1, "maneuver_required: delta=%d: yes\n", *delta);
1655 if (reason)
1656 *reason="yes: delta >= limit";
1657 return 1;
1658 #endif
1659 }
1660
1661 static struct navigation_command *
1662 command_new(struct navigation *this_, struct navigation_itm *itm, int delta)
1663 {
1664 struct navigation_command *ret=g_new0(struct navigation_command, 1);
1665 //dbg(1, "enter this_=%p itm=%p delta=%d\n", this_, itm, delta);
1666 ret->delta = delta;
1667 ret->itm = itm;
1668 if (itm && itm->prev && itm->way.next && itm->prev->way.next
1669 && !(itm->way.flags & AF_ROUNDABOUT) && (itm->prev->way.flags
1670 & AF_ROUNDABOUT))
1671 {
1672 int len = 0;
1673 int angle = 0;
1674 int entry_angle;
1675 struct navigation_itm *itm2 = itm->prev;
1676 int exit_angle = angle_median(itm->prev->angle_end,
1677 itm->way.next->angle2);
1678 //dbg(1, "exit %d median from %d,%d\n", exit_angle, itm->prev->angle_end, itm->way.next->angle2);
1679 while (itm2 && (itm2->way.flags & AF_ROUNDABOUT))
1680 {
1681 len += itm2->length;
1682 angle = itm2->angle_end;
1683 itm2 = itm2->prev;
1684 }
1685 if (itm2 && itm2->next && itm2->next->way.next)
1686 {
1687 itm2 = itm2->next;
1688 entry_angle = angle_median(angle_opposite(itm2->way.angle2),
1689 itm2->way.next->angle2);
1690 // dbg(1, "entry %d median from %d(%d),%d\n", entry_angle, angle_opposite(itm2->way.angle2), itm2->way.angle2, itm2->way.next->angle2);
1691 }
1692 else
1693 {
1694 entry_angle = angle_opposite(angle);
1695 }
1696 //dbg(0, "entry %d exit %d\n", entry_angle, exit_angle);
1697 ret->roundabout_delta = angle_delta(entry_angle, exit_angle);
1698 ret->length = len + roundabout_extra_length;
1699 }
1700 if (this_->cmd_last)
1701 {
1702 this_->cmd_last->next = ret;
1703 ret->prev = this_->cmd_last;
1704 }
1705 this_->cmd_last = ret;
1706
1707 if (!this_->cmd_first)
1708 this_->cmd_first = ret;
1709 return ret;
1710 }
1711
1712 static void make_maneuvers(struct navigation *this_, struct route *route)
1713 {
1714 struct navigation_itm *itm, *last = NULL, *last_itm = NULL;
1715 int delta;
1716 itm = this_->first;
1717 this_->cmd_last = NULL;
1718 this_->cmd_first = NULL;
1719 while (itm)
1720 {
1721 if (last)
1722 {
1723 if (maneuver_required2(this_, last_itm, itm, &delta, NULL))
1724 {
1725 command_new(this_, itm, delta);
1726 }
1727 }
1728 else
1729 last = itm;
1730 last_itm = itm;
1731 itm = itm->next;
1732 }
1733 command_new(this_, last_itm, 0);
1734 }
1735
1736 static int contains_suffix(char *name, char *suffix)
1737 {
1738 if (!suffix)
1739 return 0;
1740 if (strlen(name) < strlen(suffix))
1741 return 0;
1742 return !g_strcasecmp(name + strlen(name) - strlen(suffix), suffix);
1743 }
1744
1745 static char *
1746 replace_suffix(char *name, char *search, char *replace)
1747 {
1748 int len = strlen(name) - strlen(search);
1749 char *ret = g_malloc(len + strlen(replace) + 1);
1750 strncpy(ret, name, len);
1751 strcpy(ret + len, replace);
1752 if (isupper(name[len]))
1753 {
1754 ret[len] = toupper(ret[len]);
1755 }
1756
1757 return ret;
1758 }
1759
1760 static char *
1761 navigation_item_destination(struct navigation *nav, struct navigation_itm *itm,
1762 struct navigation_itm *next, char *prefix)
1763 {
1764 char *ret = NULL, *name1, *sep, *name2;
1765 char *n1, *n2;
1766 int i, sex;
1767 int vocabulary1 = 65535;
1768 int vocabulary2 = 65535;
1769 struct attr attr;
1770
1771 if (!prefix)
1772 prefix = "";
1773 if (nav->speech && speech_get_attr(nav->speech, attr_vocabulary_name,
1774 &attr, NULL))
1775 vocabulary1 = attr.u.num;
1776 if (nav->speech && speech_get_attr(nav->speech,
1777 attr_vocabulary_name_systematic, &attr, NULL))
1778 vocabulary2 = attr.u.num;
1779 n1 = itm->way.name1;
1780 n2 = itm->way.name2;
1781 if (!vocabulary1)
1782 n1 = NULL;
1783 if (!vocabulary2)
1784 n2 = NULL;
1785 if (!n1 && !n2 && itm->way.item.type == type_ramp && vocabulary2)
1786 {
1787 //dbg(1,">> Next is ramp %lx current is %lx \n", itm->way.item.type, next->way.item.type);
1788
1789 if (next->way.item.type == type_ramp)
1790 return NULL;
1791 if (itm->way.item.type == type_highway_city || itm->way.item.type
1792 == type_highway_land)
1793 {
1794 #ifdef HAVE_API_ANDROID
1795 android_send_generic_text(1,"+*#O:exit\n");
1796 gchar* xy=g_strdup_printf("+*#1:%s\n", prefix);
1797 android_send_generic_text(1,xy);
1798 g_free(xy);
1799 #endif
1800 return g_strdup_printf("%s%s", prefix, _("exit")); /* %FIXME Can this even be reached? and "exit" is the wrong text anyway ! */
1801 }
1802 else
1803 {
1804 #ifdef HAVE_API_ANDROID
1805 android_send_generic_text(1,"+*#O:into the ramp\n");
1806 gchar* xy=g_strdup_printf("+*#1:%s\n", prefix);
1807 android_send_generic_text(1,xy);
1808 g_free(xy);
1809 #endif
1810 return g_strdup_printf("%s%s", prefix, _("into the ramp"));
1811 }
1812
1813 }
1814
1815 if (!n1 && !n2)
1816 {
1817 return NULL;
1818 }
1819
1820 if (n1)
1821 {
1822 sex = -1;
1823 name1 = NULL;
1824 for (i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); i++)
1825 {
1826 if (contains_suffix(n1, suffixes[i].fullname))
1827 {
1828 sex = suffixes[i].sex;
1829 name1 = g_strdup(n1);
1830 break;
1831 }
1832 if (contains_suffix(n1, suffixes[i].abbrev))
1833 {
1834 sex = suffixes[i].sex;
1835 name1 = replace_suffix(n1, suffixes[i].abbrev,
1836 suffixes[i].fullname);
1837 break;
1838 }
1839 }
1840
1841 if (n2)
1842 {
1843 name2 = n2;
1844 sep = " ";
1845 }
1846 else
1847 {
1848 name2 = "";
1849 sep = "";
1850 }
1851
1852 gchar* xy;
1853 switch (sex)
1854 {
1855 case -1:
1856 #ifdef HAVE_API_ANDROID
1857 android_send_generic_text(1,"+*#O:%sinto the street %s%s%s\n");
1858 xy=g_strdup_printf("+*#1:%s\n", prefix);
1859 android_send_generic_text(1,xy);
1860 g_free(xy);
1861 xy=g_strdup_printf("+*#1:%s\n", n1);
1862 android_send_generic_text(1,xy);
1863 g_free(xy);
1864 xy=g_strdup_printf("+*#1:%s\n", sep);
1865 android_send_generic_text(1,xy);
1866 g_free(xy);
1867 xy=g_strdup_printf("+*#1:%s\n", name2);
1868 android_send_generic_text(1,xy);
1869 g_free(xy);
1870 #endif
1871 // TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name
1872 ret = g_strdup_printf(_("%sinto the street %s%s%s"), prefix,
1873 n1, sep, name2);
1874 break;
1875 case 1:
1876 #ifdef HAVE_API_ANDROID
1877 android_send_generic_text(1,"+*#O:%sinto the %s%s%s|male form\n");
1878 xy=g_strdup_printf("+*#1:%s\n", prefix);
1879 android_send_generic_text(1,xy);
1880 g_free(xy);
1881 xy=g_strdup_printf("+*#1:%s\n", name1);
1882 android_send_generic_text(1,xy);
1883 g_free(xy);
1884 xy=g_strdup_printf("+*#1:%s\n", sep);
1885 android_send_generic_text(1,xy);
1886 g_free(xy);
1887 xy=g_strdup_printf("+*#1:%s\n", name2);
1888 android_send_generic_text(1,xy);
1889 g_free(xy);
1890 #endif
1891 // TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name. Male form. The stuff after | doesn't have to be included
1892 ret = g_strdup_printf(_("%sinto the %s%s%s|male form"), prefix,
1893 name1, sep, name2);
1894 break;
1895 case 2:
1896 #ifdef HAVE_API_ANDROID
1897 android_send_generic_text(1,"+*#O:%sinto the %s%s%s|female form\n");
1898 xy=g_strdup_printf("+*#1:%s\n", prefix);
1899 android_send_generic_text(1,xy);
1900 g_free(xy);
1901 xy=g_strdup_printf("+*#1:%s\n", name1);
1902 android_send_generic_text(1,xy);
1903 g_free(xy);
1904 xy=g_strdup_printf("+*#1:%s\n", sep);
1905 android_send_generic_text(1,xy);
1906 g_free(xy);
1907 xy=g_strdup_printf("+*#1:%s\n", name2);
1908 android_send_generic_text(1,xy);
1909 g_free(xy);
1910 #endif
1911 // TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name. Female form. The stuff after | doesn't have to be included
1912 ret = g_strdup_printf(_("%sinto the %s%s%s|female form"),
1913 prefix, name1, sep, name2);
1914 break;
1915 case 3:
1916 #ifdef HAVE_API_ANDROID
1917 android_send_generic_text(1,"+*#O:%sinto the %s%s%s|neutral form\n");
1918 xy=g_strdup_printf("+*#1:%s\n", prefix);
1919 android_send_generic_text(1,xy);
1920 g_free(xy);
1921 xy=g_strdup_printf("+*#1:%s\n", name1);
1922 android_send_generic_text(1,xy);
1923 g_free(xy);
1924 xy=g_strdup_printf("+*#1:%s\n", sep);
1925 android_send_generic_text(1,xy);
1926 g_free(xy);
1927 xy=g_strdup_printf("+*#1:%s\n", name2);
1928 android_send_generic_text(1,xy);
1929 g_free(xy);
1930 #endif
1931 // TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name. Neutral form. The stuff after | doesn't have to be included
1932 ret = g_strdup_printf(_("%sinto the %s%s%s|neutral form"),
1933 prefix, name1, sep, name2);
1934 break;
1935 }
1936 g_free(name1);
1937
1938 }
1939 else
1940 {
1941 #ifdef HAVE_API_ANDROID
1942 android_send_generic_text(1,"+*#O:sinto the %s\n");
1943 gchar* xy=g_strdup_printf("+*#1:%s\n", prefix);
1944 android_send_generic_text(1,xy);
1945 g_free(xy);
1946 xy=g_strdup_printf("+*#1:%s\n", n2);
1947 android_send_generic_text(1,xy);
1948 g_free(xy);
1949 #endif
1950 // TRANSLATORS: gives the name of the next road to turn into (into the E17)
1951 ret = g_strdup_printf(_("%sinto the %s"), prefix, n2);
1952 }
1953
1954 name1 = ret;
1955
1956 while (name1 && *name1)
1957 {
1958 switch (*name1)
1959 {
1960 case '|':
1961 *name1 = '\0';
1962 break;
1963 case '/':
1964 *name1++ = ' ';
1965 break;
1966 default:
1967 name1++;
1968 }
1969 }
1970
1971 return ret;
1972 }
1973
1974 static char *
1975 show_maneuver(struct navigation *nav, struct navigation_itm *itm,
1976 struct navigation_command *cmd, enum attr_type type, int connect)
1977 {
1978 // TRANSLATORS: right, as in 'Turn right'
1979 char *dir = _("right");
1980 char *strength = "";
1981 int distance = itm->dest_length - cmd->itm->dest_length;
1982 char *d, *ret = NULL;
1983 int delta = cmd->delta;
1984 int level;
1985 int strength_needed;
1986 int skip_roads;
1987 int count_roundabout;
1988 struct navigation_itm *cur;
1989 struct navigation_way *w;
1990
1991 if (connect)
1992 {
1993 level = -2; // level = -2 means "connect to another maneuver via 'then ...'"
1994 }
1995 else
1996 {
1997 level = 1;
1998 }
1999
2000 w = itm->next->way.next;
2001 strength_needed = 0;
2002
2003 if (angle_delta(itm->next->way.angle2, itm->angle_end) < 0)
2004 {
2005 while (w)
2006 {
2007 if (angle_delta(w->angle2, itm->angle_end) < 0)
2008 {
2009 strength_needed = 1;
2010 break;
2011 }
2012 w = w->next;
2013 }
2014 }
2015 else
2016 {
2017 while (w)
2018 {
2019 if (angle_delta(w->angle2, itm->angle_end) > 0)
2020 {
2021 strength_needed = 1;
2022 break;
2023 }
2024 w = w->next;
2025 }
2026 }
2027
2028 if (delta < 0)
2029 {
2030 #ifdef HAVE_API_ANDROID
2031 android_send_generic_text(1,"+*#O:left\n");
2032 #endif
2033 // TRANSLATORS: left, as in 'Turn left'
2034 dir = _("left");
2035 delta = -delta;
2036 }
2037 else
2038 {
2039 // dir = right
2040 #ifdef HAVE_API_ANDROID
2041 android_send_generic_text(1,"+*#O:right\n");
2042 #endif
2043 }
2044
2045 if (strength_needed)
2046 {
2047 if (delta < 45)
2048 {
2049 #ifdef HAVE_API_ANDROID
2050 android_send_generic_text(1,"+*#O:slight \n");
2051 #endif
2052 // TRANSLATORS: Don't forget the ending space
2053 // TRANSLATORS: EXAMPLE: turn slight right
2054 strength = _("slight ");
2055 }
2056 else if (delta < 105)
2057 {
2058 strength = "";
2059 }
2060 else if (delta < 165)
2061 {
2062 #ifdef HAVE_API_ANDROID
2063 android_send_generic_text(1,"+*#O:hard \n");
2064 #endif
2065 // TRANSLATORS: Don't forget the ending space
2066 // TRANSLATORS: EXAMPLE: turn hard right
2067 strength = _("hard ");
2068 }
2069 else if (delta < 180)
2070 {
2071 #ifdef HAVE_API_ANDROID
2072 android_send_generic_text(1,"+*#O:really hard \n");
2073 #endif
2074 // TRANSLATORS: Don't forget the ending space
2075 // TRANSLATORS: EXAMPLE: turn really hard right
2076 strength = _("really hard ");
2077 }
2078 else
2079 {
2080 // dbg(1,"delta=%d\n", delta);
2081 // TRANSLATORS: Don't forget the ending space
2082 //strength=_("unknown ");
2083 strength = "";
2084 }
2085 }
2086
2087 if (type != attr_navigation_long_exact)
2088 {
2089 distance = round_distance(distance);
2090 }
2091
2092 if (type == attr_navigation_speech)
2093 {
2094 if (nav->turn_around && nav->turn_around == nav->turn_around_limit)
2095 {
2096 #ifdef HAVE_API_ANDROID
2097 android_send_generic_text(1,"+*#O:When possible, please turn around\n");
2098 #endif
2099 return g_strdup(_("When possible, please turn around"));
2100 }
2101
2102 if (!connect)
2103 {
2104 level = navigation_get_announce_level_cmd(nav, itm, cmd,
2105 distance - cmd->length);
2106 }
2107 // dbg(1,"distance=%d level=%d type=0x%x\n", distance, level, itm->way.item.type);
2108 }
2109
2110 if (cmd->itm->prev->way.flags & AF_ROUNDABOUT)
2111 {
2112 cur = cmd->itm->prev;
2113 count_roundabout = 0;
2114 while (cur && (cur->way.flags & AF_ROUNDABOUT))
2115 {
2116 // If the next segment has no exit or the exit isn't allowed, don't count it
2117 if (cur->next->way.next && is_way_allowed(nav, cur->next->way.next,
2118 3))
2119 {
2120 count_roundabout++;
2121 }
2122 cur = cur->prev;
2123 }
2124
2125 gchar* xy;
2126
2127 switch (level)
2128 {
2129 case 2:
2130 #ifdef HAVE_API_ANDROID
2131 android_send_generic_text(1,"+*#O:Enter the roundabout soon\n");
2132 #endif
2133 return g_strdup(_("Enter the roundabout soon"));
2134 case 1:
2135 d = get_distance(nav, distance, type, 1);
2136
2137 #ifdef HAVE_API_ANDROID
2138 android_send_generic_text(1,"+*#O:In %s, enter the roundabout\n");
2139 xy=g_strdup_printf("+*#1:%s\n", d);
2140 android_send_generic_text(1,xy);
2141 g_free(xy);
2142 #endif
2143 // TRANSLATORS: %s is the distance to the roundabout
2144 // TRANSLATORS: EXAMPLE: In 300m, enter the roundabout
2145 ret = g_strdup_printf(_("In %s, enter the roundabout"), d);
2146 g_free(d);
2147 return ret;
2148 case -2:
2149 #ifdef HAVE_API_ANDROID
2150 android_send_generic_text(1,"+*#O:then leave the roundabout at the %s\n");
2151 xy=g_strdup_printf("+*#1:%s\n", get_exit_count_str(count_roundabout));
2152 android_send_generic_text(1,xy);
2153 g_free(xy);
2154 #endif
2155 // TRANSLATORS: EXAMPLE: ... then leave the roundabout at the second exit
2156 return g_strdup_printf(
2157 _("then leave the roundabout at the %s"),
2158 get_exit_count_str(count_roundabout));
2159 case 0:
2160 #ifdef HAVE_API_ANDROID
2161 android_send_generic_text(1,"+*#O:Leave the roundabout at the %s\n");
2162 xy=g_strdup_printf("+*#1:%s\n", get_exit_count_str(count_roundabout));
2163 android_send_generic_text(1,xy);
2164 g_free(xy);
2165 #endif
2166 // TRANSLATORS: EXAMPLE: Leave the roundabout at the second exit
2167 return g_strdup_printf(_("Leave the roundabout at the %s"),
2168 get_exit_count_str(count_roundabout));
2169 }
2170 }
2171
2172 switch (level)
2173 {
2174 case 3:
2175 d = get_distance(nav, distance, type, 1);
2176
2177 #ifdef HAVE_API_ANDROID
2178 android_send_generic_text(1,"+*#O:Follow the road for the next %s\n");
2179 gchar* xy=g_strdup_printf("+*#1:%s\n", d);
2180 android_send_generic_text(1,xy);
2181 g_free(xy);
2182 #endif
2183 // TRANSLATORS: EXAMPLE: Follow the road for the next 300 meters
2184 ret = g_strdup_printf(_("Follow the road for the next %s"), d);
2185 g_free(d);
2186 return ret;
2187 case 2:
2188 #ifdef HAVE_API_ANDROID
2189 android_send_generic_text(1,"+*#O:soon\n");
2190 #endif
2191 d = g_strdup(_("soon"));
2192 break;
2193 case 1:
2194 d = get_distance(nav, distance, attr_navigation_short, 0);
2195 break;
2196 case 0:
2197 skip_roads = count_possible_turns(nav,
2198 cmd->prev ? cmd->prev->itm : nav->first, cmd->itm,
2199 cmd->delta);
2200 if (skip_roads > 0)
2201 {
2202 if (get_count_str(skip_roads + 1))
2203 {
2204 #ifdef HAVE_API_ANDROID
2205 android_send_generic_text(1,"+*#O:Take the %1$s road to the %2$s\n");
2206 gchar* xy=g_strdup_printf("+*#1:%s\n", get_count_str(skip_roads + 1));
2207 android_send_generic_text(1,xy);
2208 g_free(xy);
2209 xy=g_strdup_printf("+*#1:%s\n", dir);
2210 android_send_generic_text(1,xy);
2211 g_free(xy);
2212 #endif
2213 // TRANSLATORS: First argument is the how manieth street to take, second the direction
2214 ret = g_strdup_printf(_("Take the %1$s road to the %2$s"),
2215 get_count_str(skip_roads + 1), dir);
2216 return ret;
2217 }
2218 else
2219 {
2220 #ifdef HAVE_API_ANDROID
2221 android_send_generic_text(1,"+*#O:after %i roads\n");
2222 gchar* xy=g_strdup_printf("+*#1:%i\n", skip_roads);
2223 android_send_generic_text(1,xy);
2224 g_free(xy);
2225 #endif
2226 d = g_strdup_printf(_("after %i roads"), skip_roads);
2227 }
2228 }
2229 else
2230 {
2231 #ifdef HAVE_API_ANDROID
2232 android_send_generic_text(1,"+*#O:now\n");
2233 #endif
2234 d = g_strdup(_("now"));
2235 }
2236 break;
2237 case -2:
2238 skip_roads = count_possible_turns(nav, cmd->prev->itm, cmd->itm,
2239 cmd->delta);
2240 if (skip_roads > 0)
2241 {
2242 // TRANSLATORS: First argument is the how manieth street to take, second the direction
2243 // TRANSLATORS: EXAMPLE: ... then take the second road to the right
2244 if (get_count_str(skip_roads + 1))
2245 {
2246 #ifdef HAVE_API_ANDROID
2247 android_send_generic_text(1,"+*#O:then take the %1$s road to the %2$s\n");
2248 gchar* xy=g_strdup_printf("+*#1:%s\n", get_count_str(skip_roads + 1));
2249 android_send_generic_text(1,xy);
2250 g_free(xy);
2251 xy=g_strdup_printf("+*#1:%s\n", dir);
2252 android_send_generic_text(1,xy);
2253 g_free(xy);
2254 #endif
2255 ret = g_strdup_printf(
2256 _("then take the %1$s road to the %2$s"),
2257 get_count_str(skip_roads + 1), dir);
2258 return ret;
2259 }
2260 else
2261 {
2262 #ifdef HAVE_API_ANDROID
2263 android_send_generic_text(1,"+*#O:after %i roads\n");
2264 gchar* xy=g_strdup_printf("+*#1:%i\n", skip_roads);
2265 android_send_generic_text(1,xy);
2266 g_free(xy);
2267 #endif
2268 d = g_strdup_printf(_("after %i roads"), skip_roads);
2269 }
2270
2271 }
2272 else
2273 {
2274 d = g_strdup("");
2275 }
2276 break;
2277 default:
2278 #ifdef HAVE_API_ANDROID
2279 android_send_generic_text(1,"+*#O:error\n");
2280 #endif
2281 d = g_strdup(_("error"));
2282 }
2283
2284 if (cmd->itm->next)
2285 {
2286 int tellstreetname = 0;
2287 char *destination = NULL;
2288
2289 if (type == attr_navigation_speech)
2290 { // In voice mode
2291 // In Voice Mode only tell the street name in level 1 or in level 0 if level 1
2292 // was skipped
2293
2294 if (level == 1)
2295 { // we are close to the intersection
2296 cmd->itm->streetname_told = 1; // remeber to be checked when we turn
2297 tellstreetname = 1; // Ok so we tell the name of the street
2298 }
2299
2300 if (level == 0)
2301 {
2302 if (cmd->itm->streetname_told == 0) // we are right at the intersection
2303 {
2304 tellstreetname = 1;
2305 }
2306 else
2307 {
2308 cmd->itm->streetname_told = 0; // reset just in case we come to the same street again
2309 }
2310 }
2311
2312 }
2313 else
2314 {
2315 tellstreetname = 1;
2316 }
2317
2318 if (global_speak_streetnames == 0)
2319 {
2320 // never speak streetnames (user config option)
2321 tellstreetname = 0;
2322 }
2323
2324 if (nav->tell_street_name && tellstreetname)
2325 {
2326 destination = navigation_item_destination(nav, cmd->itm, itm, " ");
2327 }
2328
2329 if (level != -2)
2330 {
2331 #ifdef HAVE_API_ANDROID
2332 android_send_generic_text(1,"+*#O:Turn %1$s%2$s %3$s%4$s\n");
2333 gchar* xy=g_strdup_printf("+*#1:%s\n", strength);
2334 android_send_generic_text(1,xy);
2335 g_free(xy);
2336 xy=g_strdup_printf("+*#1:%s\n", dir);
2337 android_send_generic_text(1,xy);
2338 g_free(xy);
2339 xy=g_strdup_printf("+*#1:%s\n", d);
2340 android_send_generic_text(1,xy);
2341 g_free(xy);
2342 xy=g_strdup_printf("+*#1:%s\n", destination ? destination : "");
2343 android_send_generic_text(1,xy);
2344 g_free(xy);
2345 #endif
2346 // TRANSLATORS: The first argument is strength, the second direction, the third distance and the fourth destination Example: 'Turn 'slightly' 'left' in '100 m' 'onto baker street'
2347 ret = g_strdup_printf(_("Turn %1$s%2$s %3$s%4$s"), strength, dir,
2348 d, destination ? destination : "");
2349 }
2350 else
2351 {
2352 #ifdef HAVE_API_ANDROID
2353 android_send_generic_text(1,"+*#O:then turn %1$s%2$s %3$s%4$s\n");
2354 gchar* xy=g_strdup_printf("+*#1:%s\n", strength);
2355 android_send_generic_text(1,xy);
2356 g_free(xy);
2357 xy=g_strdup_printf("+*#1:%s\n", dir);
2358 android_send_generic_text(1,xy);
2359 g_free(xy);
2360 xy=g_strdup_printf("+*#1:%s\n", d);
2361 android_send_generic_text(1,xy);
2362 g_free(xy);
2363 xy=g_strdup_printf("+*#1:%s\n", destination ? destination : "");
2364 android_send_generic_text(1,xy);
2365 g_free(xy);
2366 #endif
2367 // TRANSLATORS: First argument is strength, second direction, third how many roads to skip, fourth destination
2368 ret = g_strdup_printf(_("then turn %1$s%2$s %3$s%4$s"), strength,
2369 dir, d, destination ? destination : "");
2370 }
2371 g_free(destination);
2372 }
2373 else
2374 {
2375 if (!connect)
2376 {
2377 #ifdef HAVE_API_ANDROID
2378 android_send_generic_text(1,"+*#O:You have reached your destination %s\n");
2379 gchar* xy=g_strdup_printf("+*#1:%s\n", d);
2380 android_send_generic_text(1,xy);
2381 g_free(xy);
2382 #endif
2383 // TRANSLATORS: EXAMPLE: You have reached your destination in 300 meters
2384 ret = g_strdup_printf(_("You have reached your destination %s"), d);
2385 }
2386 else
2387 {
2388 #ifdef HAVE_API_ANDROID
2389 android_send_generic_text(1,"+*#O:then you have reached your destination.\n");
2390 #endif
2391 ret = g_strdup_printf(_("then you have reached your destination."));
2392 }
2393 }
2394 g_free(d);
2395 return ret;
2396 }
2397
2398 /**
2399 * @brief Creates announcements for maneuvers, plus maneuvers immediately following the next maneuver
2400 *
2401 * This function does create an announcement for the current maneuver and for maneuvers
2402 * immediately following that maneuver, if these are too close and we're in speech navigation.
2403 *
2404 * @return An announcement that should be made
2405 */
2406 static char *
2407 show_next_maneuvers(struct navigation *nav, struct navigation_itm *itm,
2408 struct navigation_command *cmd, enum attr_type type)
2409 {
2410 struct navigation_command *cur, *prev;
2411 int distance = itm->dest_length - cmd->itm->dest_length;
2412 int level, dist, i, time;
2413 int speech_time, time2nav;
2414 char *ret, *old, *buf, *next;
2415
2416 if (type != attr_navigation_speech)
2417 {
2418 return show_maneuver(nav, itm, cmd, type, 0); // We accumulate maneuvers only in speech navigation
2419 }
2420
2421 level = navigation_get_announce_level(nav, itm->way.item.type,
2422 distance - cmd->length);
2423
2424 if (level > 1)
2425 {
2426 return show_maneuver(nav, itm, cmd, type, 0); // We accumulate maneuvers only if they are close
2427 }
2428
2429 if (cmd->itm->told)
2430 {
2431 #ifdef HAVE_API_ANDROID
2432 android_send_generic_text(1,"+*#C1:*CANCEL*\n");
2433 #endif
2434 return g_strdup("");
2435 }
2436
2437 ret = show_maneuver(nav, itm, cmd, type, 0);
2438 time2nav = navigation_time(itm, cmd->itm->prev);
2439 old = NULL;
2440
2441 cur = cmd->next;
2442 prev = cmd;
2443 i = 0;
2444 while (cur && cur->itm)
2445 {
2446 // We don't merge more than 3 announcements...
2447 if (i > 1)
2448 { // if you change this, please also change the value below, that is used to terminate the loop
2449 break;
2450 }
2451
2452 next = show_maneuver(nav, prev->itm, cur, type, 0);
2453 if (nav->speech)
2454 {
2455 speech_time = speech_estimate_duration(nav->speech, next);
2456 }
2457 else
2458 {
2459 speech_time = -1;
2460 }
2461 g_free(next);
2462
2463 if (speech_time == -1)
2464 { // user didn't set cps
2465 speech_time = 30; // assume 3 seconds
2466 }
2467
2468 dist = prev->itm->dest_length - cur->itm->dest_length;
2469 time = navigation_time(prev->itm, cur->itm->prev);
2470
2471 if (time >= (speech_time + 30))
2472 { // 3 seconds for understanding what has been said
2473 break;
2474 }
2475
2476 old = ret;
2477 buf = show_maneuver(nav, prev->itm, cur, type, 1);
2478 ret = g_strdup_printf("%s, %s", old, buf);
2479 g_free(buf);
2480
2481 if (nav->speech && speech_estimate_duration(nav->speech, ret)
2482 > time2nav)
2483 {
2484 g_free(ret);
2485 ret = old;
2486 i = 2; // This will terminate the loop
2487 }
2488 else
2489 {
2490 g_free(old);
2491 }
2492
2493 // If the two maneuvers are *really* close, we shouldn't tell the second one again, because TTS won't be fast enough
2494 if (time <= speech_time)
2495 {
2496 #ifdef HAVE_API_ANDROID
2497 android_send_generic_text(1,"+*#C2:*CANCEL*\n");
2498 #endif
2499 cur->itm->told = 1;
2500 }
2501
2502 prev = cur;
2503 cur = cur->next;
2504 i++;
2505 }
2506
2507 return ret;
2508 }
2509
2510 static void navigation_call_callbacks(struct navigation *this_,
2511 int force_speech)
2512 {
2513 int distance, level = 0;
2514 void *p = this_;
2515 if (!this_->cmd_first)
2516 return;
2517 callback_list_call(this_->callback, 1, &p);
2518 //dbg(1,"force_speech=%d turn_around=%d turn_around_limit=%d\n", force_speech, this_->turn_around, this_->turn_around_limit);
2519 distance = round_distance(
2520 this_->first->dest_length - this_->cmd_first->itm->dest_length);
2521 if (this_->turn_around_limit && this_->turn_around
2522 == this_->turn_around_limit)
2523 {
2524 //dbg(1,"distance=%d distance_turn=%d\n", distance, this_->distance_turn);
2525 while (distance > this_->distance_turn)
2526 {
2527 this_->level_last = 4;
2528 level = 4;
2529 force_speech = 2;
2530 if (this_->distance_turn >= 500)
2531 this_->distance_turn *= 2;
2532 else
2533 this_->distance_turn = 500;
2534 }
2535 }
2536 else if (!this_->turn_around_limit || this_->turn_around
2537 == -this_->turn_around_limit + 1)
2538 {
2539 this_->distance_turn = 50;
2540 distance -= this_->cmd_first->length;
2541 level = navigation_get_announce_level_cmd(this_, this_->first,
2542 this_->cmd_first, distance);
2543 if (level < this_->level_last)
2544 {
2545 /* only tell if the level is valid for more than 3 seconds */
2546 int speed_distance = this_->first->speed * 30 / 36;
2547 if (distance < speed_distance || navigation_get_announce_level_cmd(
2548 this_, this_->first, this_->cmd_first,
2549 distance - speed_distance) == level)
2550 {
2551 dbg(1, "distance %d speed_distance %d\n", distance,
2552 speed_distance);
2553 dbg(1, "level %d < %d\n", level, this_->level_last);
2554 this_->level_last = level;
2555 force_speech = 3;
2556 }
2557 }
2558
2559 if (!item_is_equal(this_->cmd_first->itm->way.item, this_->item_last))
2560 {
2561 this_->item_last = this_->cmd_first->itm->way.item;
2562 if (this_->delay)
2563 this_->curr_delay = this_->delay;
2564 else
2565 force_speech = 5;
2566 }
2567 else
2568 {
2569 if (this_->curr_delay)
2570 {
2571 this_->curr_delay--;
2572 if (!this_->curr_delay)
2573 force_speech = 4;
2574 }
2575 }
2576 }
2577
2578 if (force_speech)
2579 {
2580 this_->level_last = level;
2581 this_->curr_delay = 0;
2582 dbg(1, "force_speech=%d distance=%d level=%d type=0x%x\n",
2583 force_speech, distance, level, this_->first->way.item.type);
2584 callback_list_call(this_->callback_speech, 1, &p);
2585 }
2586 }
2587
2588 static void navigation_update(struct navigation *this_, struct route *route,
2589 struct attr *attr)
2590 {
2591 struct map *map;
2592 struct map_rect *mr;
2593 struct item *ritem; /* Holds an item from the route map */
2594 struct item *sitem; /* Holds the corresponding item from the actual map */
2595 struct attr street_item, street_direction;
2596 struct navigation_itm *itm;
2597 struct attr vehicleprofile;
2598 int mode = 0, incr = 0, first = 1;
2599 if (attr->type != attr_route_status)
2600 return;
2601
2602 dbg(1, "enter %d\n", mode);
2603 if (attr->u.num == route_status_no_destination || attr->u.num
2604 == route_status_not_found || attr->u.num
2605 == route_status_path_done_new)
2606 navigation_flush(this_);
2607 if (attr->u.num != route_status_path_done_new && attr->u.num
2608 != route_status_path_done_incremental)
2609 return;
2610
2611 if (!this_->route)
2612 return;
2613 map = route_get_map(this_->route);
2614 if (!map)
2615 return;
2616 mr = map_rect_new(map, NULL);
2617 if (!mr)
2618 return;
2619 if (route_get_attr(route, attr_vehicleprofile, &vehicleprofile, NULL))
2620 this_->vehicleprofile = vehicleprofile.u.vehicleprofile;
2621 else
2622 this_->vehicleprofile = NULL;
2623 //dbg(1,"enter\n");
2624
2625 while ((ritem = map_rect_get_item(mr)))
2626 {
2627 if (ritem->type == type_route_start && this_->turn_around
2628 > -this_->turn_around_limit + 1)
2629 this_->turn_around--;
2630 if (ritem->type == type_route_start_reverse && this_->turn_around
2631 < this_->turn_around_limit)
2632 this_->turn_around++;
2633 if (ritem->type != type_street_route)
2634 continue;
2635
2636 if (first && item_attr_get(ritem, attr_street_item, &street_item))
2637 {
2638 first = 0;
2639 if (!item_attr_get(ritem, attr_direction, &street_direction))
2640 street_direction.u.num = 0;
2641 sitem = street_item.u.item;
2642 //dbg(1,"sitem=%p\n", sitem);
2643 itm = item_hash_lookup(this_->hash, sitem);
2644 //dbg(2,"itm for item with id (0x%x,0x%x) is %p\n", sitem->id_hi, sitem->id_lo, itm);
2645
2646 if (itm && itm->way.dir != street_direction.u.num)
2647 {
2648 //dbg(2,"wrong direction\n");
2649 itm = NULL;
2650 }
2651 navigation_destroy_itms_cmds(this_, itm);
2652 if (itm)
2653 {
2654 navigation_itm_update(itm, ritem);
2655 break;
2656 }
2657 //dbg(1,"not on track\n");
2658 }
2659 navigation_itm_new(this_, ritem);
2660 }
2661 dbg(2, "turn_around=%d\n", this_->turn_around);
2662 if (first)
2663 navigation_destroy_itms_cmds(this_, NULL);
2664 else
2665 {
2666 if (!ritem)
2667 {
2668 navigation_itm_new(this_, NULL);
2669 make_maneuvers(this_, this_->route);
2670 }
2671 calculate_dest_distance(this_, incr);
2672 //profile(0,"end");
2673 navigation_call_callbacks(this_, FALSE);
2674 }
2675 map_rect_destroy(mr);
2676 }
2677
2678 static void navigation_flush(struct navigation *this_)
2679 {
2680 navigation_destroy_itms_cmds(this_, NULL);
2681 }
2682
2683 void navigation_destroy(struct navigation *this_)
2684 {
2685 navigation_flush(this_);
2686 item_hash_destroy(this_->hash);
2687 callback_list_destroy(this_->callback);
2688 callback_list_destroy(this_->callback_speech);
2689 g_free(this_);
2690 }
2691
2692 int navigation_register_callback(struct navigation *this_, enum attr_type type,
2693 struct callback *cb)
2694 {
2695 if (type == attr_navigation_speech)
2696 callback_list_add(this_->callback_speech, cb);
2697 else
2698 callback_list_add(this_->callback, cb);
2699 return 1;
2700 }
2701
2702 void navigation_unregister_callback(struct navigation *this_,
2703 enum attr_type type, struct callback *cb)
2704 {
2705 if (type == attr_navigation_speech)
2706 callback_list_remove_destroy(this_->callback_speech, cb);
2707 else
2708 callback_list_remove_destroy(this_->callback, cb);
2709 }
2710
2711 struct map *
2712 navigation_get_map(struct navigation *this_)
2713 {
2714 struct attr *attrs[5];
2715 struct attr type, navigation, data, description;
2716 type.type = attr_type;
2717 type.u.str = "navigation";
2718 navigation.type = attr_navigation;
2719 navigation.u.navigation = this_;
2720 data.type = attr_data;
2721 data.u.str = "";
2722 description.type = attr_description;
2723 description.u.str = "Navigation";
2724
2725 attrs[0] = &type;
2726 attrs[1] = &navigation;
2727 attrs[2] = &data;
2728 attrs[3] = &description;
2729 attrs[4] = NULL;
2730 if (!this_->map)
2731 this_->map = map_new(NULL, attrs);
2732 return this_->map;
2733 }
2734
2735 struct map_priv
2736 {
2737 struct navigation *navigation;
2738 };
2739
2740 struct map_rect_priv
2741 {
2742 struct navigation *nav;
2743 struct navigation_command *cmd;
2744 struct navigation_command *cmd_next;
2745 struct navigation_itm *itm;
2746 struct navigation_itm *itm_next;
2747 struct navigation_itm *cmd_itm;
2748 struct navigation_itm *cmd_itm_next;
2749 struct item item;
2750 enum attr_type attr_next;
2751 int ccount;
2752 int debug_idx;
2753 struct navigation_way *ways;
2754 int show_all;
2755 char *str;
2756 };
2757
2758 static int navigation_map_item_coord_get(void *priv_data, struct coord *c,
2759 int count)
2760 {
2761 struct map_rect_priv *this = priv_data;
2762 if (this->ccount || !count)
2763 return 0;
2764 *c = this->itm->start;
2765 this->ccount = 1;
2766 return 1;
2767 }
2768
2769 static int navigation_map_item_attr_get(void *priv_data,
2770 enum attr_type attr_type, struct attr *attr)
2771 {
2772 struct map_rect_priv *this_ = priv_data;
2773 struct navigation_command *cmd = this_->cmd;
2774 struct navigation_itm *itm = this_->itm;
2775 struct navigation_itm *prev = itm->prev;
2776 attr->type = attr_type;
2777
2778 if (this_->str)
2779 {
2780 g_free(this_->str);
2781 this_->str = NULL;
2782 }
2783
2784 if (cmd)
2785 {
2786 if (cmd->itm != itm)
2787 cmd = NULL;
2788 }
2789 switch (attr_type)
2790 {
2791 case attr_navigation_short:
2792 this_->attr_next = attr_navigation_long;
2793 if (cmd)
2794 {
2795 this_->str = attr->u.str = show_next_maneuvers(this_->nav,
2796 this_->cmd_itm, cmd, attr_type);
2797 return 1;
2798 }
2799 return 0;
2800 case attr_navigation_long:
2801 this_->attr_next = attr_navigation_long_exact;
2802 if (cmd)
2803 {
2804 this_->str = attr->u.str = show_next_maneuvers(this_->nav,
2805 this_->cmd_itm, cmd, attr_type);
2806 return 1;
2807 }
2808 return 0;
2809 case attr_navigation_long_exact:
2810 this_->attr_next = attr_navigation_speech;
2811 if (cmd)
2812 {
2813 this_->str = attr->u.str = show_next_maneuvers(this_->nav,
2814 this_->cmd_itm, cmd, attr_type);
2815 return 1;
2816 }
2817 return 0;
2818 case attr_navigation_speech:
2819 this_->attr_next = attr_length;
2820 if (cmd)
2821 {
2822 this_->str = attr->u.str = show_next_maneuvers(this_->nav,
2823 this_->cmd_itm, this_->cmd, attr_type);
2824 return 1;
2825 }
2826 return 0;
2827 case attr_length:
2828 this_->attr_next = attr_time;
2829 if (cmd)
2830 {
2831 attr->u.num = this_->cmd_itm->dest_length
2832 - cmd->itm->dest_length;
2833 return 1;
2834 }
2835 return 0;
2836 case attr_time:
2837 this_->attr_next = attr_destination_length;
2838 if (cmd)
2839 {
2840 attr->u.num = this_->cmd_itm->dest_time - cmd->itm->dest_time;
2841 return 1;
2842 }
2843 return 0;
2844 case attr_destination_length:
2845 attr->u.num = itm->dest_length;
2846 this_->attr_next = attr_destination_time;
2847 return 1;
2848 case attr_destination_time:
2849 attr->u.num = itm->dest_time;
2850 this_->attr_next = attr_street_name;
2851 return 1;
2852 case attr_street_name:
2853 attr->u.str = itm->way.name1;
2854 this_->attr_next = attr_street_name_systematic;
2855 if (attr->u.str)
2856 return 1;
2857 return 0;
2858 case attr_street_name_systematic:
2859 attr->u.str = itm->way.name2;
2860 this_->attr_next = attr_debug;
2861 if (attr->u.str)
2862 return 1;
2863 return 0;
2864 case attr_debug:
2865 switch (this_->debug_idx)
2866 {
2867 case 0:
2868 this_->debug_idx++;
2869 this_->str = attr->u.str = g_strdup_printf(
2870 "angle:%d (- %d)", itm->way.angle2, itm->angle_end);
2871 return 1;
2872 case 1:
2873 this_->debug_idx++;
2874 this_->str = attr->u.str = g_strdup_printf("item type:%s",
2875 item_to_name(itm->way.item.type));
2876 return 1;
2877 case 2:
2878 this_->debug_idx++;
2879 if (cmd)
2880 {
2881 this_->str = attr->u.str = g_strdup_printf("delta:%d",
2882 cmd->delta);
2883 return 1;
2884 }
2885 case 3:
2886 this_->debug_idx++;
2887 if (prev)
2888 {
2889 this_->str = attr->u.str = g_strdup_printf(
2890 "prev street_name:%s", prev->way.name1);
2891 return 1;
2892 }
2893 case 4:
2894 this_->debug_idx++;
2895 if (prev)
2896 {
2897 this_->str = attr->u.str = g_strdup_printf(
2898 "prev street_name_systematic:%s",
2899 prev->way.name2);
2900 return 1;
2901 }
2902 case 5:
2903 this_->debug_idx++;
2904 if (prev)
2905 {
2906 this_->str = attr->u.str = g_strdup_printf(
2907 "prev angle:(%d -) %d", prev->way.angle2,
2908 prev->angle_end);
2909 return 1;
2910 }
2911 case 6:
2912 this_->debug_idx++;
2913 this_->ways = itm->way.next;
2914 if (prev)
2915 {
2916 this_->str = attr->u.str = g_strdup_printf(
2917 "prev item type:%s",
2918 item_to_name(prev->way.item.type));
2919 return 1;
2920 }
2921 case 7:
2922 if (this_->ways && prev)
2923 {
2924 this_->str
2925 = attr->u.str
2926 = g_strdup_printf(
2927 "other item angle:%d delta:%d flags:%d dir:%d type:%s id:(0x%x,0x%x)",
2928 this_->ways->angle2,
2929 angle_delta(prev->angle_end,
2930 this_->ways->angle2),
2931 this_->ways->flags,
2932 this_->ways->dir,
2933 item_to_name(
2934 this_->ways->item.type),
2935 this_->ways->item.id_hi,
2936 this_->ways->item.id_lo);
2937 this_->ways = this_->ways->next;
2938 return 1;
2939 }
2940 this_->debug_idx++;
2941 case 8:
2942 this_->debug_idx++;
2943 if (prev)
2944 {
2945 int delta = 0;
2946 char *reason = NULL;
2947 maneuver_required2(this_->nav, prev, itm, &delta,
2948 &reason);
2949 this_->str = attr->u.str = g_strdup_printf("reason:%s",
2950 reason);
2951 return 1;
2952 }
2953
2954 default:
2955 this_->attr_next = attr_none;
2956 return 0;
2957 }
2958 case attr_any:
2959 while (this_->attr_next != attr_none)
2960 {
2961 if (navigation_map_item_attr_get(priv_data, this_->attr_next,
2962 attr))
2963 return 1;
2964 }
2965 return 0;
2966 default:
2967 attr->type = attr_none;
2968 return 0;
2969 }
2970 }
2971
2972 static struct item_methods navigation_map_item_methods =
2973 { NULL, navigation_map_item_coord_get, NULL, navigation_map_item_attr_get, };
2974
2975 static void navigation_map_destroy(struct map_priv *priv)
2976 {
2977 g_free(priv);
2978 }
2979
2980 static void navigation_map_rect_init(struct map_rect_priv *priv)
2981 {
2982 priv->cmd_next = priv->nav->cmd_first;
2983 priv->cmd_itm_next = priv->itm_next = priv->nav->first;
2984 }
2985
2986 static struct map_rect_priv *
2987 navigation_map_rect_new(struct map_priv *priv, struct map_selection *sel)
2988 {
2989 struct navigation *nav = priv->navigation;
2990 struct map_rect_priv *ret=g_new0(struct map_rect_priv, 1);
2991 ret->nav = nav;
2992 navigation_map_rect_init(ret);
2993 ret->item.meth = &navigation_map_item_methods;
2994 ret->item.priv_data = ret;
2995 #ifdef DEBUG
2996 ret->show_all=1;
2997 #endif
2998 return ret;
2999 }
3000
3001 static void navigation_map_rect_destroy(struct map_rect_priv *priv)
3002 {
3003 g_free(priv);
3004 }
3005
3006 static struct item *
3007 navigation_map_get_item(struct map_rect_priv *priv)
3008 {
3009 struct item *ret = &priv->item;
3010 int delta;
3011 if (!priv->itm_next)
3012 return NULL;
3013 priv->itm = priv->itm_next;
3014 priv->cmd = priv->cmd_next;
3015 priv->cmd_itm = priv->cmd_itm_next;
3016 if (!priv->cmd)
3017 return NULL;
3018 if (!priv->show_all && priv->itm->prev != NULL)
3019 priv->itm = priv->cmd->itm;
3020 priv->itm_next = priv->itm->next;
3021 if (priv->itm->prev)
3022 ret->type = type_nav_none;
3023 else
3024 ret->type = type_nav_position;
3025 if (priv->cmd->itm == priv->itm)
3026 {
3027 priv->cmd_itm_next = priv->cmd->itm;
3028 priv->cmd_next = priv->cmd->next;
3029 if (priv->cmd_itm_next && !priv->cmd_itm_next->next)
3030 ret->type = type_nav_destination;
3031 else
3032 {
3033 if (priv->itm && priv->itm->prev && !(priv->itm->way.flags
3034 & AF_ROUNDABOUT) && (priv->itm->prev->way.flags
3035 & AF_ROUNDABOUT))
3036 {
3037 enum item_type r = type_none, l = type_none;
3038 switch (((180 + 22) - priv->cmd->roundabout_delta) / 45)
3039 {
3040 case 0:
3041 case 1:
3042 r = type_nav_roundabout_r1;
3043 l = type_nav_roundabout_l7;
3044 break;
3045 case 2:
3046 r = type_nav_roundabout_r2;
3047 l = type_nav_roundabout_l6;
3048 break;
3049 case 3:
3050 r = type_nav_roundabout_r3;
3051 l = type_nav_roundabout_l5;
3052 break;
3053 case 4:
3054 r = type_nav_roundabout_r4;
3055 l = type_nav_roundabout_l4;
3056 break;
3057 case 5:
3058 r = type_nav_roundabout_r5;
3059 l = type_nav_roundabout_l3;
3060 break;
3061 case 6:
3062 r = type_nav_roundabout_r6;
3063 l = type_nav_roundabout_l2;
3064 break;
3065 case 7:
3066 r = type_nav_roundabout_r7;
3067 l = type_nav_roundabout_l1;
3068 break;
3069 case 8:
3070 r = type_nav_roundabout_r8;
3071 l = type_nav_roundabout_l8;
3072 break;
3073 }
3074 dbg(1, "delta %d\n", priv->cmd->delta);
3075 if (priv->cmd->delta < 0)
3076 ret->type = l;
3077 else
3078 ret->type = r;
3079 }
3080 else
3081 {
3082 delta = priv->cmd->delta;
3083 if (delta < 0)
3084 {
3085 delta = -delta;
3086 if (delta < 45)
3087 ret->type = type_nav_left_1;
3088 else if (delta < 105)
3089 ret->type = type_nav_left_2;
3090 else if (delta < 165)
3091 ret->type = type_nav_left_3;
3092 else
3093 ret->type = type_none;
3094 }
3095 else
3096 {
3097 if (delta < 45)
3098 ret->type = type_nav_right_1;
3099 else if (delta < 105)
3100 ret->type = type_nav_right_2;
3101 else if (delta < 165)
3102 ret->type = type_nav_right_3;
3103 else
3104 ret->type = type_none;
3105 }
3106 }
3107 }
3108 }
3109 priv->ccount = 0;
3110 priv->debug_idx = 0;
3111 priv->attr_next = attr_navigation_short;
3112
3113 ret->id_lo = priv->itm->dest_count;
3114 dbg(1, "type=%d\n", ret->type);
3115 return ret;
3116 }
3117
3118 static struct item *
3119 navigation_map_get_item_byid(struct map_rect_priv *priv, int id_hi, int id_lo)
3120 {
3121 struct item *ret;
3122 navigation_map_rect_init(priv);
3123 while ((ret = navigation_map_get_item(priv)))
3124 {
3125 if (ret->id_hi == id_hi && ret->id_lo == id_lo)
3126 return ret;
3127 }
3128 return NULL;
3129 }
3130
3131 static struct map_methods navigation_map_meth =
3132 { projection_mg, "utf-8", navigation_map_destroy, navigation_map_rect_new,
3133 navigation_map_rect_destroy, navigation_map_get_item,
3134 navigation_map_get_item_byid, NULL, NULL, NULL, };
3135
3136 static struct map_priv *
3137 navigation_map_new(struct map_methods *meth, struct attr **attrs,
3138 struct callback_list *cbl)
3139 {
3140 struct map_priv *ret;
3141 struct attr *navigation_attr;
3142
3143 navigation_attr = attr_search(attrs, NULL, attr_navigation);
3144 if (!navigation_attr)
3145 return NULL;ret=g_new0(struct map_priv, 1);
3146 *meth = navigation_map_meth;
3147 ret->navigation = navigation_attr->u.navigation;
3148
3149 return ret;
3150 }
3151
3152 void navigation_set_route(struct navigation *this_, struct route *route)
3153 {
3154 struct attr callback;
3155 this_->route = route;
3156 this_->route_cb = callback_new_attr_1(callback_cast(navigation_update),
3157 attr_route_status, this_);
3158 callback.type = attr_callback;
3159 callback.u.callback = this_->route_cb;
3160 route_add_attr(route, &callback);
3161 }
3162
3163 void navigation_init(void)
3164 {
3165 plugin_register_map_type("navigation", navigation_map_new);
3166 }

   
Visit the ZANavi Wiki