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

Contents of /navit/navit/navigation.c

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki