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

Contents of /navit/navit/navigation.c

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki