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

Contents of /navit/navit/navigation.c

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki