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

Contents of /navit/navit/navigation.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 48 - (show annotations) (download)
Sat Oct 24 13:12:03 2015 UTC (8 years, 5 months ago) by zoff99
File MIME type: text/plain
File size: 200871 byte(s)
v2.0.49
1 /**
2 * ZANavi, Zoff Android Navigation system.
3 * Copyright (C) 2011-2015 Zoff <zoff@zoff.cc>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 /**
21 * Navit, a modular navigation system.
22 * Copyright (C) 2005-2008 Navit Team
23 *
24 * This program is free software; you can redistribute it and/or
25 * modify it under the terms of the GNU General Public License
26 * version 2 as published by the Free Software Foundation.
27 *
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
32 *
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the
35 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
36 * Boston, MA 02110-1301, USA.
37 */
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <math.h>
43 #include <ctype.h>
44 #include <glib.h>
45 #include "debug.h"
46 #include "profile.h"
47 #include "navigation.h"
48 #include "coord.h"
49
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
65
66
67
68
69 // #define NAVIT_FUNC_CALLS_DEBUG_PRINT 1
70
71
72 // --------------- debug function calls ------------------
73 // --------------- debug function calls ------------------
74 #ifdef NAVIT_FUNC_CALLS_DEBUG_PRINT
75 #undef return2
76 #define return2 dbg_func(0, global_func_indent_counter, "return(%d)\n", __LINE__);global_func_indent_counter--;return
77
78 #define __F_START__ global_func_indent_counter++;dbg_func(0, global_func_indent_counter, "enter\n");
79 #define __F_END__ dbg_func(0, global_func_indent_counter, "leave\n");global_func_indent_counter--;
80 #else
81 #undef return2
82 #define return2 return
83
84 #define __F_START__
85 #define __F_END__
86 #endif
87 // --------------- debug function calls ------------------
88 // --------------- debug function calls ------------------
89
90
91
92
93
94
95
96 static int roundabout_extra_length = 50;
97
98 struct suffix
99 {
100 char *fullname;
101 char *abbrev;
102 int sex;
103 } suffixes[] = { { "weg", NULL, 1 }, { "platz", "pl.", 1 }, { "ring", NULL, 1 }, { "allee", NULL, 2 }, { "gasse", NULL, 2 }, { "straße", "str.", 2 }, { "strasse", NULL, 2 }, };
104
105
106 int distances[] = { 1, 2, 3, 4, 5, 10, 25, 50, 75, 100, 150, 200, 250, 300, 400, 500, 750, -1 };
107
108
109
110
111
112
113 // -- NEW 002 --
114 /* Allowed values for navigation_maneuver.merge_or_exit
115 * The numeric values are chosen in such a way that they can be interpreted as flags:
116 * 1=merge, 2=exit, 4=interchange, 8=right, 16=left
117 * Identifiers were chosen over flags to enforce certain rules
118 * (merge/exit/interchange and left/right are mutually exclusive, left/right requires merge or exit). */
119 //FIXME: should we make this an enum?
120
121 /** Not merging into or exiting from a motorway_like road */
122 #define mex_none 0
123
124 /** Merging into a motorway-like road, direction undefined */
125 //FIXME: do we need this constant?
126 #define mex_merge 1
127
128 /** Exiting from a motorway-like road, direction undefined.
129 * This should only be used for ramps leading to a non-motorway road.
130 * For interchanges, use {@code mex_interchange} instead. */
131 //FIXME: do we need this constant?
132 #define mex_exit 2
133
134 /** Motorway-like road splits in two.
135 * This should be used for all cases in which ramps lead to another motorway-like road. */
136 #define mex_interchange 4
137
138 /** Merging into a motorway-like road to the right (coming from the left) */
139 #define mex_merge_right 9
140
141 /** Exiting from a motorway-like road to the right.
142 * See {@code mex_exit} for usage. */
143 #define mex_exit_right 10
144
145 /** Merging into a motorway-like road to the left (coming from the right) */
146 #define mex_merge_left 17
147
148 /** Exiting from a motorway-like road to the left.
149 * See {@code mex_exit} for usage. */
150 #define mex_exit_left 18
151
152 /**
153 * @brief Holds information about a navigation maneuver.
154 *
155 * This structure is populated when a navigation maneuver is first analyzed. Its members contain all information
156 * needed to decide whether or not to announce the maneuver, what type of maneuver it is and the information that
157 * was used to determine the former two.
158 */
159 struct navigation_maneuver {
160 enum item_type type; /**< The type of maneuver to perform. Any {@code nav_*} item is permitted here, with one exception:
161 merge or exit maneuvers are indicated by the {@code merge_or_exit} member. The {@code item_type}
162 for such maneuvers should be a turn instruction in cases where the maneuver is ambiguous, or
163 {@code nav_none} for cases in which we would expect the driver to perform this maneuver even
164 without being instructed to do so. **/
165 int delta; /**< Bearing difference (the angle the driver has to steer) for the maneuver */
166 int merge_or_exit; /**< Whether we are merging into or exiting from a motorway_like road or we are at an interchange */
167 int is_complex_t_junction; /**< Whether we are coming from the "stem" of a T junction whose "bar" is a dual-carriageway road and
168 crossing the opposite lane of the "bar" first (i.e. turning left in countries that drive on the
169 right, or turning right in countries that drive on the left). For these maneuvers
170 {@code num_options} is 1 (which means we normally wouldn't announce the maneuver) but drivers
171 would expect an announcement in such cases. */
172 int num_options; /**< Number of permitted candidate ways, i.e. ways which we may enter (based on access flags of the
173 way but without considering turn restrictions). Permitted candidate ways include the route. */
174 int num_new_motorways; /**< Number of permitted candidate ways that are motorway-like */
175 int num_other_ways; /**< Number of permitted candidate ways that are neither ramps nor motorway-like */
176 int old_cat; /**< Maneuver category of the way leading to the maneuver */
177 int new_cat; /**< Maneuver category of the selected way after the maneuver */
178 int max_cat; /**< Highest maneuver category of any permitted candidate way other than the route */
179 int num_similar_ways; /**< Number of candidate ways (including the route) that have a {@code maneuver_category()} similar
180 to {@code old_cat}. See {@code maneuver_required2()} for definition of "similar". */
181 int left; /**< Minimum bearing delta of any candidate way left of the route, -180 for none */
182 int right; /**< Minimum bearing delta of any candidate way right of the route, 180 for none */
183 int is_unambiguous; /**< Whether the maneuver is unambiguous. A maneuver is unambiguous if, despite
184 multiple candidate way being available, we can reasonable expect the driver to
185 continue on the route without being told to do so. This is typically the case when
186 the route stays on the main road and goes straight, while all other candidate ways
187 are minor roads and involve a significant turn. */
188 int is_same_street; /**< Whether the street keeps its name after the maneuver. */
189 };
190 // -- NEW 002 --
191
192
193
194
195
196 struct navigation_command
197 {
198 struct navigation_itm *itm;
199 struct navigation_command *next;
200 struct navigation_command *prev;
201 int delta;
202 int delta_real;
203 int roundabout_delta;
204 int length;
205 // -- NEW 002 --
206 struct navigation_maneuver *maneuver; /**< Details on the maneuver to perform */
207 // -- NEW 002 --
208 };
209
210
211
212
213
214
215
216 // -- NEW 002 --
217 /*@brief A linked list conataining the destination of the road
218 *
219 *
220 * Holds the destination info from the road, that is the place
221 * you drive to if you keep following the road as found on
222 * traffic sign's (ex. Paris, Senlis ...)
223 *
224 *
225 */
226 struct street_destination
227 {
228 struct street_destination *next;
229 char *destination;
230 };
231 // -- NEW 002 --
232
233
234
235
236
237 static void navigation_flush(struct navigation *this_);
238
239 /**
240 * @brief Calculates the delta between two angles
241 * @param angle1 The first angle
242 * @param angle2 The second angle
243 * @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
244 */
245
246 static int angle_delta(int angle1, int angle2)
247 {
248 int delta = angle2 - angle1;
249
250 if (delta <= -180)
251 delta += 360;
252
253 if (delta > 180)
254 delta -= 360;
255
256 return delta;
257 }
258
259 static int angle_median(int angle1, int angle2)
260 {
261 int delta = angle_delta(angle1, angle2);
262 int ret = angle1 + delta / 2;
263
264 if (ret < 0)
265 ret += 360;
266
267 if (ret > 360)
268 ret -= 360;
269
270 return ret;
271 }
272
273 static int angle_opposite(int angle)
274 {
275 return ((angle + 180) % 360);
276 }
277
278 int navigation_get_attr(struct navigation *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter)
279 {
280 struct map_rect *mr;
281 struct item *item;
282 // dbg(1, "enter %s\n", attr_to_name(type));
283 switch (type)
284 {
285 case attr_map:
286 attr->u.map = this_->map;
287 break;
288 case attr_item_type:
289 case attr_length:
290 case attr_navigation_speech:
291 mr = map_rect_new(this_->map, NULL);
292 while ((item = map_rect_get_item(mr)))
293 {
294 if (item->type != type_nav_none && item->type != type_nav_position)
295 {
296 if (type == attr_item_type)
297 attr->u.item_type = item->type;
298 else
299 {
300 if (!item_attr_get(item, type, attr))
301 item = NULL;
302 }
303 break;
304 }
305 }
306 map_rect_destroy(mr);
307 if (!item)
308 return 0;
309 break;
310 default:
311 return 0;
312 }
313 attr->type = type;
314 return 1;
315 }
316
317 int navigation_set_attr(struct navigation *this_, struct attr *attr)
318 {
319 switch (attr->type)
320 {
321 case attr_speech:
322 this_->speech = attr->u.speech;
323 return 1;
324 default:
325 return 0;
326 }
327 }
328
329 struct navigation *
330 navigation_new(struct attr *parent, struct attr **attrs)
331 {
332 int i, j;
333 struct attr * attr;
334 struct navigation *ret=g_new0(struct navigation, 1);
335 ret->hash = item_hash_new();
336 ret->callback = callback_list_new("navigation_new:ret->callback");
337 ret->callback_speech = callback_list_new("navigation_new:ret->callback_speech");
338 ret->level_last = -2;
339 ret->distance_turn = 50;
340 ret->turn_around_limit = 2; // at first occurence of "turn around" -> say so!
341 ret->navit = parent->u.navit;
342 ret->tell_street_name = 1;
343 ret->previous = NULL;
344 ret->cmd_previous = NULL;
345
346 for (j = 0; j <= route_item_last - route_item_first; j++)
347 {
348 for (i = 0; i < 3; i++)
349 {
350 ret->announce[j][i] = -1;
351 }
352 }
353
354 if ((attr = attr_search(attrs, NULL, attr_tell_street_name)))
355 {
356 ret->tell_street_name = attr->u.num;
357 }
358 if ((attr = attr_search(attrs, NULL, attr_delay)))
359 {
360 ret->delay = attr->u.num;
361 }
362
363 return ret;
364 }
365
366 int navigation_set_announce(struct navigation *this_, enum item_type type, int *level)
367 {
368 int i;
369 if (type < route_item_first || type > route_item_last)
370 {
371 dbg(0, "street type %d out of range [%d,%d]", type, route_item_first, route_item_last);
372 return 0;
373 }
374
375 for (i = 0; i < 3; i++)
376 {
377 // dbg(0, "announce=%d type=%s\n", level[i], item_to_name(type));
378 this_->announce[type - route_item_first][i] = level[i];
379 }
380
381 return 1;
382 }
383
384 // global var ------------
385 static int level_static_for_bicycle[3];
386 // global var ------------
387
388
389
390 // ------------------------------------
391 // returns: "0", "1", "2" or "3"
392 // ------------------------------------
393 static int navigation_get_announce_level(struct navigation *this_, enum item_type type, int dist, float speed_in_ms)
394 {
395 int i = 3;
396
397 if (type < route_item_first || type > route_item_last)
398 {
399 return -1;
400 }
401
402 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
403 {
404 #if 0
405 for (i = 0; i < 3; i++)
406 {
407 // dbg(0, "loop(a) i=%d type=%s, route_item_first=%x, announce=%d, dist=%d\n", i, item_to_name(type), route_item_first, level_static_for_bicycle[i], dist);
408 if (dist <= level_static_for_bicycle[i])
409 {
410 //dbg(0, "ret(1a)=%d\n", i);
411 return i;
412 }
413 }
414 #endif
415
416 for (i = 0; i < 3; i++)
417 {
418 if (speed_in_ms > 19.444f) // > 70 km/h
419 {
420
421 if (i == 0)
422 {
423 if (dist <= (int)(global_b_level0_announcement * global_b_levelx_announcement_factor * speed_in_ms) )
424 {
425 return i;
426 }
427 }
428 else if (i == 1)
429 {
430 if (dist <= (int)(global_b_level1_announcement * global_b_levelx_announcement_factor * speed_in_ms) )
431 {
432 return i;
433 }
434 }
435 else
436 {
437 if (dist <= (int)(global_b_level2_announcement * global_b_levelx_announcement_factor * speed_in_ms) )
438 {
439 return i;
440 }
441 }
442 }
443 else if (speed_in_ms > 0.9f)
444 {
445 if (i == 0)
446 {
447 // always have at least 12 meters to turn for level 0 announcement
448 if (dist <= 12)
449 {
450 return i;
451 }
452
453 if (dist <= (int)(global_b_level0_announcement * speed_in_ms) )
454 {
455 dbg(0, "NCC_:0:%d %f\n", (int)(global_b_level0_announcement * speed_in_ms), speed_in_ms);
456 return i;
457 }
458 }
459 else if (i == 1)
460 {
461 if (dist <= (int)(global_b_level1_announcement * speed_in_ms) )
462 {
463 dbg(0, "NCC_:1:%d %f\n", (int)(global_b_level1_announcement * speed_in_ms), speed_in_ms);
464 return i;
465 }
466 }
467 else
468 {
469 if (dist <= (int)(global_b_level2_announcement * speed_in_ms) )
470 {
471 dbg(0, "NCC_:2:%d %f\n", (int)(global_b_level2_announcement * speed_in_ms), speed_in_ms);
472 return i;
473 }
474 }
475 }
476 else
477 {
478 if (dist <= level_static_for_bicycle[i])
479 {
480 //dbg(0, "ret(1a)=%d\n", i);
481 return i;
482 }
483 }
484
485 }
486
487 }
488 else
489 {
490
491 for (i = 0; i < 3; i++)
492 {
493 //dbg(0, "loop(b) i=%d type=%s, route_item_first=%x, announce=%d, dist=%d\n", i, item_to_name(type), route_item_first, (this_->announce[type - route_item_first][i]), dist);
494
495
496 if (speed_in_ms > 19.444f) // > 70 km/h
497 {
498 if (i == 0)
499 {
500 if (dist <= (int)(global_level0_announcement * global_levelx_announcement_factor * speed_in_ms) )
501 {
502 return i;
503 }
504 }
505 else if (i == 1)
506 {
507 if (dist <= (int)(global_level1_announcement * global_levelx_announcement_factor * speed_in_ms) )
508 {
509 return i;
510 }
511 }
512 else
513 {
514 if (dist <= (int)(global_level2_announcement * global_levelx_announcement_factor * speed_in_ms) )
515 {
516 return i;
517 }
518 }
519 }
520 else if (speed_in_ms > 0.9f)
521 {
522 if (i == 0)
523 {
524 // always have at least 12 meters to turn for level 0 announcement
525 if (dist <= 12)
526 {
527 return i;
528 }
529
530 if (dist <= (int)(global_level0_announcement * speed_in_ms) )
531 {
532 dbg(0, "NCC_:0:%d %f\n", (int)(global_level0_announcement * speed_in_ms), speed_in_ms);
533 return i;
534 }
535 }
536 else if (i == 1)
537 {
538 if (dist <= (int)(global_level1_announcement * speed_in_ms) )
539 {
540 dbg(0, "NCC_:1:%d %f\n", (int)(global_level1_announcement * speed_in_ms), speed_in_ms);
541 return i;
542 }
543 }
544 else
545 {
546 if (dist <= (int)(global_level2_announcement * speed_in_ms) )
547 {
548 dbg(0, "NCC_:2:%d %f\n", (int)(global_level2_announcement * speed_in_ms), speed_in_ms);
549 return i;
550 }
551 }
552 }
553 else
554 {
555 if (dist <= this_->announce[type - route_item_first][i])
556 {
557 //dbg(0, "ret(1b)=%d\n", i);
558 return i;
559 }
560 }
561 }
562 }
563
564
565 //dbg(0, "ret(2)=%d\n", i);
566
567 return i;
568 }
569
570
571 static int navigation_get_announce_dist_for_level_on_item_bicycle(struct navigation *this_, enum item_type type, int level, float speed_in_ms)
572 {
573
574 if (speed_in_ms > 19.444f) // > 70 km/h
575 {
576 if (level == 0)
577 {
578 return (int)(global_b_level0_announcement * global_b_levelx_announcement_factor * speed_in_ms);
579 }
580 else if (level == 1)
581 {
582 return (int)(global_b_level1_announcement * global_b_levelx_announcement_factor * speed_in_ms);
583 }
584 else
585 {
586 return (int)(global_b_level2_announcement * global_b_levelx_announcement_factor * speed_in_ms);
587 }
588 }
589 else if (speed_in_ms > 0.9f)
590 {
591 if (level == 0)
592 {
593 // always have at least 12 meters to turn for level 0 announcement
594 if ( (int)(global_b_level0_announcement * speed_in_ms) < 12)
595 {
596 return 12;
597 }
598 else
599 {
600 return (int)(global_b_level0_announcement * speed_in_ms);
601 }
602 }
603 else if (level == 1)
604 {
605 return (int)(global_b_level1_announcement * speed_in_ms);
606 }
607 else
608 {
609 return (int)(global_b_level2_announcement * speed_in_ms);
610 }
611 }
612 else
613 {
614 return level_static_for_bicycle[level];
615 }
616 }
617
618
619 static int navigation_get_announce_dist_for_level_on_item(struct navigation *this_, enum item_type type, int level, float speed_in_ms)
620 {
621
622 if (speed_in_ms > 19.444f) // > 70 km/h
623 {
624 if (level == 0)
625 {
626 return (int)(global_level0_announcement * global_levelx_announcement_factor * speed_in_ms);
627 }
628 else if (level == 1)
629 {
630 return (int)(global_level1_announcement * global_levelx_announcement_factor * speed_in_ms);
631 }
632 else
633 {
634 return (int)(global_level2_announcement * global_levelx_announcement_factor * speed_in_ms);
635 }
636 }
637 else if (speed_in_ms > 0.9f)
638 {
639 if (level == 0)
640 {
641 // always have at least 12 meters to turn for level 0 announcement
642 if ( (int)(global_level0_announcement * speed_in_ms) < 12)
643 {
644 return 12;
645 }
646 else
647 {
648 return (int)(global_level0_announcement * speed_in_ms);
649 }
650 }
651 else if (level == 1)
652 {
653 return (int)(global_level1_announcement * speed_in_ms);
654 }
655 else
656 {
657 return (int)(global_level2_announcement * speed_in_ms);
658 }
659 }
660 else
661 {
662 return this_->announce[type - route_item_first][level];
663 }
664 }
665
666 static int is_way_allowed(struct navigation *nav, struct navigation_way *way, int mode);
667
668 static int navigation_get_announce_level_cmd(struct navigation *this_, struct navigation_itm *itm, struct navigation_command *cmd, int distance, float speed_in_ms)
669 {
670
671 int level2, level = navigation_get_announce_level(this_, itm->way.item.type, distance, speed_in_ms);
672
673 if (this_->cmd_first->itm->prev)
674 {
675 level2 = navigation_get_announce_level(this_, cmd->itm->prev->way.item.type, distance, speed_in_ms);
676 if (level2 > level)
677 {
678 level = level2;
679 }
680 }
681
682 return level;
683 }
684
685 /* 0=N,90=E */
686 static int road_angle_accurate(struct coord *c1, struct coord *c2, int dir)
687 {
688 // COST: 006 acc
689 // dbg(0, "COST:006acc\n");
690
691 int ret = transform_get_angle_delta_accurate(c1, c2, dir);
692 return ret;
693 }
694
695
696 static int road_angle(struct coord *c1, struct coord *c2, int dir)
697 {
698 // COST: 006
699 // dbg(0, "COST:006\n");
700
701 int ret = transform_get_angle_delta(c1, c2, dir);
702 // dbg(1, "road_angle(0x%x,0x%x - 0x%x,0x%x)=%d\n", c1->x, c1->y, c2->x, c2->y, ret);
703 return ret;
704 }
705
706 static char *get_count_str(int n)
707 {
708 switch (n)
709 {
710 case 0:
711 #ifdef HAVE_API_ANDROID
712 #ifdef NAVIT_SAY_DEBUG_PRINT
713 android_send_generic_text(1,"+*#O:first\n");
714 #endif
715 #endif
716 // TRANSLATORS: the following counts refer to streets (example: turn right after the first street)
717 return _("first"); // Not sure if this exists, neither if it will ever be needed
718 case 1:
719 #ifdef HAVE_API_ANDROID
720 #ifdef NAVIT_SAY_DEBUG_PRINT
721 android_send_generic_text(1,"+*#O:first\n");
722 #endif
723 #endif
724 // TRANSLATORS: the following counts refer to streets (example: turn right after the first street)
725 return _("first");
726 case 2:
727 #ifdef HAVE_API_ANDROID
728 #ifdef NAVIT_SAY_DEBUG_PRINT
729 android_send_generic_text(1,"+*#O:second\n");
730 #endif
731 #endif
732 // TRANSLATORS: the following counts refer to streets (example: turn right after the second street)
733 return _("second");
734 case 3:
735 #ifdef HAVE_API_ANDROID
736 #ifdef NAVIT_SAY_DEBUG_PRINT
737 android_send_generic_text(1,"+*#O:third\n");
738 #endif
739 #endif
740 // TRANSLATORS: the following counts refer to streets (example: turn right after the third street)
741 return _("third");
742 case 4:
743 #ifdef HAVE_API_ANDROID
744 #ifdef NAVIT_SAY_DEBUG_PRINT
745 android_send_generic_text(1,"+*#O:fourth\n");
746 #endif
747 #endif
748 // TRANSLATORS: the following counts refer to streets (example: turn right after the fourth street)
749 return _("fourth");
750 case 5:
751 #ifdef HAVE_API_ANDROID
752 #ifdef NAVIT_SAY_DEBUG_PRINT
753 android_send_generic_text(1,"+*#O:fifth\n");
754 #endif
755 #endif
756 // TRANSLATORS: the following counts refer to streets (example: turn right after the fifth street)
757 return _("fifth");
758 case 6:
759 #ifdef HAVE_API_ANDROID
760 #ifdef NAVIT_SAY_DEBUG_PRINT
761 android_send_generic_text(1,"+*#O:sixth\n");
762 #endif
763 #endif
764 // TRANSLATORS: the following counts refer to streets (example: turn right after the sixth street)
765 return _("sixth");
766 case 7:
767 #ifdef HAVE_API_ANDROID
768 #ifdef NAVIT_SAY_DEBUG_PRINT
769 android_send_generic_text(1,"+*#O:seventh\n");
770 #endif
771 #endif
772 // TRANSLATORS: the following counts refer to streets (example: turn right after the seventh street)
773 return _("seventh");
774 case 8:
775 #ifdef HAVE_API_ANDROID
776 #ifdef NAVIT_SAY_DEBUG_PRINT
777 android_send_generic_text(1,"+*#O:eighth\n");
778 #endif
779 #endif
780 // TRANSLATORS: the following counts refer to streets (example: turn right after the eighth street)
781 return _("eighth");
782 case 9:
783 #ifdef HAVE_API_ANDROID
784 #ifdef NAVIT_SAY_DEBUG_PRINT
785 android_send_generic_text(1,"+*#O:ninth\n");
786 #endif
787 #endif
788 // TRANSLATORS: the following counts refer to streets (example: turn right after the ninth street)
789 return _("ninth");
790 default:
791 return NULL;
792 }
793 }
794
795 static char *get_exit_count_str(int n)
796 {
797 switch (n)
798 {
799 case 0:
800 #ifdef HAVE_API_ANDROID
801 #ifdef NAVIT_SAY_DEBUG_PRINT
802 android_send_generic_text(1,"+*#O:first exit\n");
803 #endif
804 #endif
805 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the first exit)
806 return _("first exit"); // Not sure if this exists, neither if it will ever be needed
807 case 1:
808 #ifdef HAVE_API_ANDROID
809 #ifdef NAVIT_SAY_DEBUG_PRINT
810 android_send_generic_text(1,"+*#O:first exit\n");
811 #endif
812 #endif
813 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the first exit)
814 return _("first exit");
815 case 2:
816 #ifdef HAVE_API_ANDROID
817 #ifdef NAVIT_SAY_DEBUG_PRINT
818 android_send_generic_text(1,"+*#O:second exit\n");
819 #endif
820 #endif
821 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the second exit)
822 return _("second exit");
823 case 3:
824 #ifdef HAVE_API_ANDROID
825 #ifdef NAVIT_SAY_DEBUG_PRINT
826 android_send_generic_text(1,"+*#O:third exit\n");
827 #endif
828 #endif
829 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the third exit)
830 return _("third exit");
831 case 4:
832 #ifdef HAVE_API_ANDROID
833 #ifdef NAVIT_SAY_DEBUG_PRINT
834 android_send_generic_text(1,"+*#O:fourth exit\n");
835 #endif
836 #endif
837 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the fourth exit)
838 return _("fourth exit");
839 case 5:
840 #ifdef HAVE_API_ANDROID
841 #ifdef NAVIT_SAY_DEBUG_PRINT
842 android_send_generic_text(1,"+*#O:fifth exit\n");
843 #endif
844 #endif
845 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the fifth exit)
846 return _("fifth exit");
847 case 6:
848 #ifdef HAVE_API_ANDROID
849 #ifdef NAVIT_SAY_DEBUG_PRINT
850 android_send_generic_text(1,"+*#O:sixth exit\n");
851 #endif
852 #endif
853 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the sixth exit)
854 return _("sixth exit");
855 case 7:
856 #ifdef HAVE_API_ANDROID
857 #ifdef NAVIT_SAY_DEBUG_PRINT
858 android_send_generic_text(1,"+*#O:seventh exit\n");
859 #endif
860 #endif
861 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the seventh exit)
862 return _("seventh exit");
863 case 8:
864 #ifdef HAVE_API_ANDROID
865 #ifdef NAVIT_SAY_DEBUG_PRINT
866 android_send_generic_text(1,"+*#O:eighth exit\n");
867 #endif
868 #endif
869 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the eighth exit)
870 return _("eighth exit");
871 case 9:
872 #ifdef HAVE_API_ANDROID
873 #ifdef NAVIT_SAY_DEBUG_PRINT
874 android_send_generic_text(1,"+*#O:ninth exit\n");
875 #endif
876 #endif
877 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the ninth exit)
878 return _("ninth exit");
879 default:
880 return NULL;
881 }
882 }
883
884 static int round_distance(int dist)
885 {
886 if (dist < 100)
887 {
888 dist = (dist + 5) / 10;
889 return dist * 10;
890 }
891 if (dist < 250)
892 {
893 dist = (dist + 13) / 25;
894 return dist * 25;
895 }
896 if (dist < 500)
897 {
898 dist = (dist + 25) / 50;
899 return dist * 50;
900 }
901 if (dist < 1000)
902 {
903 dist = (dist + 50) / 100;
904 return dist * 100;
905 }
906 if (dist < 5000)
907 {
908 dist = (dist + 50) / 100;
909 return dist * 100;
910 }
911 if (dist < 100000)
912 {
913 dist = (dist + 500) / 1000;
914 return dist * 1000;
915 }
916 dist = (dist + 5000) / 10000;
917 return dist * 10000;
918 }
919
920 static int round_for_vocabulary(int vocabulary, int dist, int factor)
921 {
922
923 //dbg(0, "DIST_FEET:rfv:001:d=%d f=%d\n", dist, factor);
924
925 //if (!(vocabulary & 256))
926 //{
927 if (factor != 1)
928 {
929 dist = (dist + factor / 2) / factor;
930 //dbg(0, "DIST_FEET:rfv:002:d=%d\n", dist);
931 }
932 //}
933 //else
934 //{
935 // factor = 1;
936 //}
937
938 if (!(vocabulary & 255))
939 {
940 int i = 0, d = 0, m = 0;
941 while (distances[i] > 0)
942 {
943 if (!i || abs(distances[i] - dist) <= d)
944 {
945 d = abs(distances[i] - dist);
946 //dbg(0, "DIST_FEET:rfv:003:d=%d\n", dist);
947 m = i;
948 }
949
950 if (distances[i] > dist)
951 {
952 break;
953 }
954 i++;
955 }
956 // dbg(0, "converted %d to %d with factor %d\n", dist, distances[m], factor);
957 dist = distances[m];
958 }
959
960 //dbg(0, "DIST_FEET:rfv:002:d=%d f=%d res=%d\n", dist, factor, dist * factor);
961
962 return dist * factor;
963 }
964
965 static int vocabulary_last(int vocabulary)
966 {
967 int i = 0;
968
969 if (vocabulary == 65535)
970 {
971 return 1000;
972 }
973
974 while (distances[i] > 0)
975 {
976 i++;
977 }
978
979 return distances[i - 1];
980 }
981
982 char *
983 get_distance(struct navigation *nav, int dist, enum attr_type type, int is_length)
984 {
985 int imperial = 0;
986 int vocabulary = 65535;
987 struct attr attr;
988
989 if (type == attr_navigation_long)
990 {
991 if (is_length)
992 {
993 #ifdef HAVE_API_ANDROID
994 #ifdef NAVIT_SAY_DEBUG_PRINT
995 android_send_generic_text(1,"+*#O:%d m\n");
996 #endif
997 #endif
998 return g_strdup_printf(_("%d m"), dist);
999 }
1000 else
1001 {
1002 #ifdef HAVE_API_ANDROID
1003 #ifdef NAVIT_SAY_DEBUG_PRINT
1004 android_send_generic_text(1,"+*#O:in %d m\n");
1005 #endif
1006 #endif
1007 return g_strdup_printf(_("in %d m"), dist);
1008 }
1009 }
1010
1011 if (navit_get_attr(nav->navit, attr_imperial, &attr, NULL))
1012 {
1013 imperial = attr.u.num;
1014 }
1015
1016 if (nav->speech && speech_get_attr(nav->speech, attr_vocabulary_distances, &attr, NULL))
1017 {
1018 vocabulary = attr.u.num;
1019 }
1020
1021 if (imperial)
1022 {
1023 //dbg(0, "DIST_FEET:001:d=%d\n", dist);
1024
1025 // if (dist * FEET_PER_METER < vocabulary_last(vocabulary))
1026 if (dist * FEET_PER_METER < 5300) // fix for "0"-miles later!!
1027 {
1028 if (( dist * FEET_PER_METER ) > 1900)
1029 {
1030 //dbg(0, "DIST_FEET:002a:d=%d m=%d\n", dist, (int)(dist * FEET_PER_METER));
1031 dist = round_for_vocabulary(vocabulary, dist * FEET_PER_METER, 500);
1032 }
1033 else if (( dist * FEET_PER_METER ) > 290)
1034 {
1035 //dbg(0, "DIST_FEET:002a:d=%d m=%d\n", dist, (int)(dist * FEET_PER_METER));
1036 dist = round_for_vocabulary(vocabulary, dist * FEET_PER_METER, 100);
1037 }
1038 else if (( dist * FEET_PER_METER ) > 25)
1039 {
1040 //dbg(0, "DIST_FEET:002a:d=%d m=%d\n", dist, (int)(dist * FEET_PER_METER));
1041 dist = round_for_vocabulary(vocabulary, dist * FEET_PER_METER, 20);
1042 }
1043 else
1044 {
1045 //dbg(0, "DIST_FEET:002b:d=%d m=%d\n", dist, dist * FEET_PER_METER);
1046 dist = round_for_vocabulary(vocabulary, dist * FEET_PER_METER, 1);
1047 }
1048
1049 //dbg(0, "DIST_FEET:002:d=%d v=%d\n", dist, vocabulary);
1050
1051 if (is_length)
1052 {
1053 #ifdef HAVE_API_ANDROID
1054 #ifdef NAVIT_SAY_DEBUG_PRINT
1055 android_send_generic_text(1,"+*#O:%d feet\n");
1056 #endif
1057 #endif
1058 return g_strdup_printf(_("%d feet"), dist);
1059 }
1060 else
1061 {
1062 #ifdef HAVE_API_ANDROID
1063 #ifdef NAVIT_SAY_DEBUG_PRINT
1064 android_send_generic_text(1,"+*#O:in %d feet\n");
1065 #endif
1066 #endif
1067 return g_strdup_printf(_("in %d feet"), dist);
1068 }
1069 }
1070 }
1071 else
1072 {
1073 if (dist < vocabulary_last(vocabulary))
1074 {
1075 dist = round_for_vocabulary(vocabulary, dist, 1);
1076 if (is_length)
1077 {
1078 #ifdef HAVE_API_ANDROID
1079 #ifdef NAVIT_SAY_DEBUG_PRINT
1080 android_send_generic_text(1,"+*#O:%d meters\n");
1081 gchar* xy=g_strdup_printf("+*#1:%d\n", dist);
1082 android_send_generic_text(1,xy);
1083 g_free(xy);
1084 #endif
1085 #endif
1086 return g_strdup_printf(_("%d meters"), dist);
1087 }
1088 else
1089 {
1090 #ifdef HAVE_API_ANDROID
1091 #ifdef NAVIT_SAY_DEBUG_PRINT
1092 android_send_generic_text(1,"+*#O:in %d meters\n");
1093 gchar* xy=g_strdup_printf("+*#1:%d\n", dist);
1094 android_send_generic_text(1,xy);
1095 g_free(xy);
1096 #endif
1097 #endif
1098 return g_strdup_printf(_("in %d meters"), dist);
1099 }
1100 }
1101 }
1102
1103 if (imperial)
1104 {
1105 //dbg(0, "DIST_FEET:003:d=%d v=%d\n", dist, vocabulary);
1106 dist = round_for_vocabulary(vocabulary, dist * FEET_PER_METER * 1000 / FEET_PER_MILE, 1000);
1107 //dbg(0, "DIST_FEET:004:d=%d v=%d\n", dist, vocabulary);
1108 }
1109 else
1110 {
1111 dist = round_for_vocabulary(vocabulary, dist, 1000);
1112 }
1113
1114 if (dist < 5000)
1115 {
1116 int rem = (dist / 100) % 10;
1117 if (rem)
1118 {
1119 if (imperial)
1120 {
1121 if (is_length)
1122 {
1123 #ifdef HAVE_API_ANDROID
1124 #ifdef NAVIT_SAY_DEBUG_PRINT
1125 android_send_generic_text(1,"+*#O:%d.%d miles\n");
1126 #endif
1127 #endif
1128 return g_strdup_printf(_("%d.%d miles"), dist / 1000, rem);
1129 }
1130 else
1131 {
1132 #ifdef HAVE_API_ANDROID
1133 #ifdef NAVIT_SAY_DEBUG_PRINT
1134 android_send_generic_text(1,"+*#O:in %d.%d miles\n");
1135 #endif
1136 #endif
1137 //dbg(0, "DIST_FEET:005:d/1000=%d rem=%d\n", dist / 1000, rem);
1138
1139 return g_strdup_printf(_("in %d.%d miles"), dist / 1000, rem);
1140 }
1141 }
1142 else
1143 {
1144 if (is_length)
1145 {
1146 #ifdef HAVE_API_ANDROID
1147 #ifdef NAVIT_SAY_DEBUG_PRINT
1148 android_send_generic_text(1,"+*#O:%d.%d kilometers\n");
1149 #endif
1150 #endif
1151 return g_strdup_printf(_("%d.%d kilometers"), dist / 1000, rem);
1152 }
1153 else
1154 {
1155 #ifdef HAVE_API_ANDROID
1156 #ifdef NAVIT_SAY_DEBUG_PRINT
1157 android_send_generic_text(1,"+*#O:in %d.%d kilometers\n");
1158 #endif
1159 #endif
1160 return g_strdup_printf(_("in %d.%d kilometers"), dist / 1000, rem);
1161 }
1162 }
1163 }
1164 }
1165
1166 if (imperial)
1167 {
1168 if (is_length)
1169 {
1170 return g_strdup_printf(ngettext("one mile", "%d miles", dist / 1000), dist / 1000);
1171 }
1172 else
1173 {
1174 //dbg(0, "DIST_FEET:006:d/1000=%d\n", dist / 1000);
1175
1176 return g_strdup_printf(ngettext("in one mile", "in %d miles", dist / 1000), dist / 1000);
1177 }
1178 }
1179 else
1180 {
1181 if (is_length)
1182 {
1183 #ifdef HAVE_API_ANDROID
1184 #ifdef NAVIT_SAY_DEBUG_PRINT
1185 android_send_generic_text(1,"+*#O:one kilometer|%d kilometers\n");
1186 #endif
1187 #endif
1188 return g_strdup_printf(ngettext("one kilometer", "%d kilometers", dist / 1000), dist / 1000);
1189 }
1190 else
1191 {
1192 #ifdef HAVE_API_ANDROID
1193 #ifdef NAVIT_SAY_DEBUG_PRINT
1194 android_send_generic_text(1,"+*#O:in one kilometer|in %d kilometers\n");
1195 #endif
1196 #endif
1197 return g_strdup_printf(ngettext("in one kilometer", "in %d kilometers", dist / 1000), dist / 1000);
1198 }
1199 }
1200 }
1201
1202 static int navigation_get_real_item_first_coord(struct navigation_way *w, struct coord *c)
1203 {
1204 struct item *ritem = NULL; // the "real" item
1205 struct map_rect *mr;
1206 struct attr attr;
1207 struct coord c2[5];
1208
1209
1210 #if 1
1211 if (!w)
1212 {
1213 return 0;
1214 }
1215
1216 if (!w->item.map)
1217 {
1218 return 0;
1219 }
1220
1221 if ((!w->item.id_hi) && (w->item.id_lo))
1222 {
1223 return 0;
1224 }
1225
1226 mr = map_rect_new(w->item.map, NULL);
1227
1228 if (!mr)
1229 {
1230 return 0;
1231 }
1232
1233 // COST: 001
1234 dbg(0, "COST:001\n");
1235 ritem = map_rect_get_item_byid(mr, w->item.id_hi, w->item.id_lo);
1236
1237 if (!ritem)
1238 {
1239 map_rect_destroy(mr);
1240 return 0;
1241 }
1242
1243 if (item_coord_get(ritem, c2, 2) == 2)
1244 {
1245 c[0].x = c2[0].x;
1246 c[0].y = c2[0].y;
1247 c[1].x = c2[1].x;
1248 c[1].y = c2[1].y;
1249
1250 map_rect_destroy(mr);
1251 return 1;
1252 }
1253
1254 map_rect_destroy(mr);
1255 return 0;
1256
1257 #endif
1258 }
1259
1260 long long navigation_item_get_wayid(struct navigation_way *w)
1261 {
1262 struct item *ritem; // the "real" item
1263 struct map_rect *mr;
1264 struct attr attr;
1265 long long ret = 0;
1266
1267 if (!w)
1268 {
1269 return ret;
1270 }
1271
1272 if (!w->item.map)
1273 {
1274 return ret;
1275 }
1276
1277 if ((!w->item.id_hi) && (w->item.id_lo))
1278 {
1279 return ret;
1280 }
1281
1282 mr = map_rect_new(w->item.map, NULL);
1283
1284 if (!mr)
1285 {
1286 return ret;
1287 }
1288
1289 // COST: 002
1290 dbg(0, "COST:002\n");
1291 ritem = map_rect_get_item_byid(mr, w->item.id_hi, w->item.id_lo);
1292
1293 if (!ritem)
1294 {
1295 map_rect_destroy(mr);
1296 return ret;
1297 }
1298
1299 if (item_attr_get(ritem, attr_osm_wayid, &attr))
1300 {
1301 // dbg(0, "START:attr.u.num64=%x attr.u.num64=%lld\n", attr.u.num64, attr.u.num64);
1302 if (attr.u.num64)
1303 {
1304 ret = *attr.u.num64;
1305 }
1306 // dbg(0, "END:attr.u.num64\n");
1307 }
1308
1309 map_rect_destroy(mr);
1310
1311 // dbg(0, "return 099\n");
1312
1313 return ret;
1314 }
1315
1316 int navigation_item_get_flags(struct navigation_way *w)
1317 {
1318 struct item *ritem; // the "real" item
1319 struct map_rect *mr;
1320 struct attr attr;
1321 long long ret = 0;
1322
1323 if (!w)
1324 {
1325 return ret;
1326 }
1327
1328
1329 // -----------------------------------------
1330 // -----------------------------------------
1331 // flags should be there already!?
1332 if (w->flags != 0)
1333 {
1334 // we already have flags set!
1335 return w->flags;
1336 }
1337 // -----------------------------------------
1338 // -----------------------------------------
1339
1340
1341 if (!w->item.map)
1342 {
1343 return ret;
1344 }
1345
1346 if ((!w->item.id_hi) && (w->item.id_lo))
1347 {
1348 return ret;
1349 }
1350
1351 mr = map_rect_new(w->item.map, NULL);
1352
1353 if (!mr)
1354 {
1355 return ret;
1356 }
1357
1358 // COST: 003
1359 dbg(0, "COST:003\n");
1360 ritem = map_rect_get_item_byid(mr, w->item.id_hi, w->item.id_lo);
1361
1362 if (!ritem)
1363 {
1364 map_rect_destroy(mr);
1365 return ret;
1366 }
1367
1368 if (item_attr_get(ritem, attr_flags, &attr))
1369 {
1370 ret = attr.u.num;
1371 // also set the flags here!!
1372 w->flags = ret;
1373 }
1374 else
1375 {
1376 w->flags = 0;
1377 }
1378
1379 map_rect_destroy(mr);
1380
1381 // dbg(0, "return 099\n");
1382
1383 return ret;
1384 }
1385
1386
1387 /**
1388 * @brief This calculates the angle with which an item starts or ends
1389 *
1390 * This function can be used to get the angle an item (from a route graph map)
1391 * starts or ends with. Note that the angle will point towards the inner of
1392 * the item.
1393 *
1394 * This is meant to be used with items from a route graph map
1395 * With other items this will probably not be optimal...
1396 *
1397 * @param w The way which should be calculated
1398 */
1399 static void calculate_angle(struct navigation_way *w)
1400 {
1401 struct coord cbuf[2];
1402 struct item *ritem; // the "real" item
1403 struct coord c;
1404 struct map_rect *mr;
1405 struct attr attr;
1406
1407 w->angle2 = 361;
1408 mr = map_rect_new(w->item.map, NULL);
1409
1410 if (!mr)
1411 {
1412 return;
1413 }
1414
1415 // COST: 004
1416 dbg(0, "COST:004\n");
1417 ritem = map_rect_get_item_byid(mr, w->item.id_hi, w->item.id_lo);
1418
1419 if (!ritem)
1420 {
1421 // dbg(1, "Item from segment not found on map!\n");
1422 map_rect_destroy(mr);
1423 return;
1424 }
1425
1426 if (ritem->type < type_line || ritem->type >= type_area)
1427 {
1428 map_rect_destroy(mr);
1429 return;
1430 }
1431
1432
1433 if (item_attr_get(ritem, attr_flags, &attr))
1434 {
1435 w->flags = attr.u.num;
1436 }
1437 else
1438 {
1439 w->flags = 0;
1440 }
1441 // dbg(0, "w->flags=%x\n", w->flags);
1442
1443
1444 if (item_attr_get(ritem, attr_street_name, &attr))
1445 {
1446 w->name1 = map_convert_string(ritem->map, attr.u.str);
1447 }
1448 else
1449 {
1450 w->name1 = NULL;
1451 }
1452
1453
1454 if (item_attr_get(ritem, attr_street_name_systematic, &attr))
1455 {
1456 w->name2 = map_convert_string(ritem->map, attr.u.str);
1457 }
1458 else
1459 {
1460 w->name2 = NULL;
1461 }
1462
1463
1464 if (w->dir < 0)
1465 {
1466 if (item_coord_get(ritem, cbuf, 2) != 2)
1467 {
1468 // dbg(1, "Using calculate_angle() with a less-than-two-coords-item?\n");
1469 map_rect_destroy(mr);
1470 return;
1471 }
1472
1473 while (item_coord_get(ritem, &c, 1))
1474 {
1475 cbuf[0] = cbuf[1];
1476 cbuf[1] = c;
1477 }
1478
1479 }
1480 else
1481 {
1482 if (item_coord_get(ritem, cbuf, 2) != 2)
1483 {
1484 // dbg(1, "Using calculate_angle() with a less-than-two-coords-item?\n");
1485 map_rect_destroy(mr);
1486 return;
1487 }
1488
1489 c = cbuf[0];
1490 cbuf[0] = cbuf[1];
1491 cbuf[1] = c;
1492 }
1493
1494 map_rect_destroy(mr);
1495
1496 // w->angle2 = road_angle_accurate(&cbuf[1], &cbuf[0], 0);
1497 w->angle2 = road_angle(&cbuf[1], &cbuf[0], 0);
1498 }
1499
1500 /**
1501 * @brief Returns the time (in seconds) one will drive between two navigation items
1502 *
1503 * This function returns the time needed to drive between two items, including both of them,
1504 * in seconds.
1505 *
1506 * @param from The first item
1507 * @param to The last item
1508 * @return The travel time in seconds, or -1 on error
1509 */
1510 static int navigation_time(struct navigation_itm *from, struct navigation_itm *to)
1511 {
1512 struct navigation_itm *cur;
1513 int time;
1514
1515 time = 0;
1516 cur = from;
1517 while (cur)
1518 {
1519 time += cur->time;
1520
1521 if (cur == to)
1522 {
1523 break;
1524 }
1525 cur = cur->next;
1526 }
1527
1528 if (!cur)
1529 {
1530 return -1;
1531 }
1532
1533 return time;
1534 }
1535
1536
1537
1538 static int navigation_time_real_speed(struct navigation_itm *from, struct navigation_itm *to, int speed_in_kmh)
1539 {
1540 struct navigation_itm *cur;
1541 int time;
1542 int first = 1;
1543 float speed_in_ms = (float) ((float)speed_in_kmh / 3.6f);
1544
1545 time = 0;
1546 cur = from;
1547
1548 while (cur)
1549 {
1550
1551 if (first == 1)
1552 {
1553 first = 0;
1554 if (speed_in_kmh < 1)
1555 {
1556 time += cur->time;
1557 }
1558 else
1559 {
1560 time = time + (int)( ((float)cur->length / speed_in_ms ) * 10.0f );
1561 }
1562 }
1563 else
1564 {
1565 time += cur->time;
1566 }
1567
1568 if (cur == to)
1569 {
1570 break;
1571 }
1572 cur = cur->next;
1573 }
1574
1575 if (!cur)
1576 {
1577 return -1;
1578 }
1579
1580 return time;
1581 }
1582
1583
1584
1585
1586 // -- NEW 002 --
1587 static void navigation_free_list(struct street_destination *list)
1588 {
1589 if (list)
1590 {
1591 struct street_destination *clist = NULL;
1592 while (list)
1593 {
1594 clist = list->next;
1595 if (list->destination)
1596 {
1597 g_free(list->destination);
1598 }
1599
1600 g_free(list);
1601 list = clist;
1602 }
1603 list = NULL;
1604 }
1605 }
1606 // -- NEW 002 --
1607
1608
1609
1610
1611
1612 /**
1613 * @brief Clears the ways one can drive from itm
1614 *
1615 * @param itm The item that should have its ways cleared
1616 */
1617 static void navigation_itm_ways_clear(struct navigation_itm *itm)
1618 {
1619 struct navigation_way *c, *n;
1620
1621 c = itm->way.next;
1622 while (c)
1623 {
1624 n = c->next;
1625 map_convert_free(c->name1);
1626 map_convert_free(c->name2);
1627
1628 if (c->exit_ref)
1629 {
1630 g_free(c->exit_ref);
1631 c->exit_ref = NULL;
1632 }
1633
1634 if (c->exit_label)
1635 {
1636 g_free(c->exit_label);
1637 c->exit_label = NULL;
1638 }
1639
1640 if (c->street_dest_text)
1641 {
1642 g_free(c->street_dest_text);
1643 c->street_dest_text = NULL;
1644 }
1645
1646 if (c->s_destination)
1647 {
1648 navigation_free_list(c->s_destination);
1649 }
1650
1651 g_free(c);
1652 c = NULL;
1653
1654 c = n;
1655 }
1656
1657 itm->way.next = NULL;
1658 }
1659
1660 /**
1661 * @brief Updates the ways one can drive from itm
1662 *
1663 * This updates the list of possible ways to drive to from itm. The item "itm" is on
1664 * and the next navigation item are excluded.
1665 *
1666 * @param itm The item that should be updated
1667 * @param graph_map The route graph's map that these items are on
1668 */
1669 static void navigation_itm_ways_update(struct navigation_itm *itm, struct map *graph_map)
1670 {
1671 struct map_selection coord_sel;
1672 struct map_rect *g_rect; // Contains a map rectangle from the route graph's map
1673 struct item *i, *sitem;
1674 struct attr sitem_attr, direction_attr;
1675 // struct attr flags_attr;
1676 struct navigation_way *w, *l;
1677
1678 navigation_itm_ways_clear(itm);
1679
1680 // These values cause the code in route.c to get us only the route graph point and connected segments
1681 coord_sel.next = NULL;
1682 coord_sel.u.c_rect.lu = itm->start;
1683 coord_sel.u.c_rect.rl = itm->start;
1684 // the selection's order is ignored
1685
1686 g_rect = map_rect_new(graph_map, &coord_sel);
1687
1688 i = map_rect_get_item(g_rect);
1689
1690 if (!i || i->type != type_rg_point)
1691 { // probably offroad?
1692 return;
1693 }
1694
1695 w = NULL;
1696
1697 while (1)
1698 {
1699 i = map_rect_get_item(g_rect);
1700
1701 if (!i)
1702 {
1703 break;
1704 }
1705
1706 if (i->type != type_rg_segment)
1707 {
1708 continue;
1709 }
1710
1711 if (!item_attr_get(i, attr_street_item, &sitem_attr))
1712 {
1713 // dbg(1, "Got no street item for route graph item in entering_straight()\n");
1714 continue;
1715 }
1716
1717 if (!item_attr_get(i, attr_direction, &direction_attr))
1718 {
1719 continue;
1720 }
1721
1722 sitem = sitem_attr.u.item;
1723
1724 if (sitem->type == type_street_turn_restriction_no || sitem->type == type_street_turn_restriction_only)
1725 {
1726 continue;
1727 }
1728
1729 if (item_is_equal(itm->way.item, *sitem) || ((itm->prev) && item_is_equal(itm->prev->way.item, *sitem)))
1730 {
1731 continue;
1732 }
1733
1734 //if (!item_attr_get(i, attr_flags, &flags_attr))
1735 //{
1736 // flags_attr.u.num = 0;
1737 //}
1738 //dbg(0, "w2->flags=%x\n", flags_attr.u.num);
1739
1740 l = w;
1741 w = g_new0(struct navigation_way, 1);
1742 w->dir = direction_attr.u.num;
1743 w->item = *sitem;
1744 w->next = l;
1745 // w->flags = flags_attr.u.num;
1746
1747 calculate_angle(w);
1748 }
1749
1750 map_rect_destroy(g_rect);
1751
1752 itm->way.next = w;
1753 }
1754
1755 static void navigation_destroy_itms_cmds(struct navigation *this_, struct navigation_itm *end)
1756 {
1757 struct navigation_itm *itm;
1758 struct navigation_command *cmd;
1759
1760 // dbg(2, "enter this_=%p this_->first=%p this_->cmd_first=%p end=%p\n", this_, this_->first, this_->cmd_first, end);
1761
1762 if (this_->cmd_first)
1763 {
1764 // dbg(2, "this_->cmd_first->itm=%p\n", this_->cmd_first->itm);
1765 }
1766
1767 while (this_->first && this_->first != end)
1768 {
1769 itm = this_->first;
1770 // dbg(3, "destroying %p\n", itm);
1771 item_hash_remove(this_->hash, &itm->way.item);
1772 this_->first = itm->next;
1773
1774 if (this_->first)
1775 {
1776 this_->first->prev = NULL;
1777 }
1778
1779 if (this_->cmd_first && this_->cmd_first->itm == itm->next)
1780 {
1781 cmd = this_->cmd_first;
1782 this_->cmd_first = cmd->next;
1783 if (cmd->next)
1784 {
1785 cmd->next->prev = NULL;
1786 }
1787 g_free(cmd);
1788 // FF: ??
1789 // cmd = NULL;
1790 }
1791
1792 map_convert_free(itm->way.name1);
1793 map_convert_free(itm->way.name2);
1794
1795 if (itm->way.s_destination)
1796 {
1797 navigation_free_list(itm->way.s_destination);
1798 }
1799
1800 if (itm->way.exit_ref)
1801 {
1802 g_free(itm->way.exit_ref);
1803 itm->way.exit_ref = NULL;
1804 }
1805
1806 if (itm->way.exit_label)
1807 {
1808 g_free(itm->way.exit_label);
1809 itm->way.exit_label = NULL;
1810 }
1811
1812 if (itm->way.street_dest_text)
1813 {
1814 g_free(itm->way.street_dest_text);
1815 itm->way.street_dest_text = NULL;
1816 }
1817
1818 navigation_itm_ways_clear(itm);
1819
1820 g_free(itm);
1821 itm = NULL;
1822 }
1823
1824 if (!this_->first)
1825 {
1826 this_->last = NULL;
1827 }
1828
1829 if (!this_->first && end)
1830 {
1831 // dbg(0, "end wrong\n");
1832 }
1833 }
1834
1835 static void navigation_itm_update(struct navigation_itm *itm, struct item *ritem)
1836 {
1837 struct attr length, time, speed;
1838
1839 if (!item_attr_get(ritem, attr_length, &length))
1840 {
1841 // dbg(0, "no length\n");
1842 return;
1843 }
1844
1845 if (!item_attr_get(ritem, attr_time, &time))
1846 {
1847 // dbg(0, "no time\n");
1848 return;
1849 }
1850
1851 if (!item_attr_get(ritem, attr_speed, &speed))
1852 {
1853 // dbg(0, "no speed\n");
1854 return;
1855 }
1856
1857 // dbg(1, "length=%d time=%d speed=%d\n", length.u.num, time.u.num, speed.u.num);
1858 itm->length = length.u.num;
1859 itm->time = time.u.num;
1860 itm->speed = speed.u.num;
1861 }
1862
1863 /**
1864 * @brief This check if an item is part of a roundabout
1865 *
1866 * @param itm The item to be checked
1867 * @return True if the item is part of a roundabout
1868 */
1869 static int check_roundabout(struct navigation_itm *itm, struct map *graph_map)
1870 {
1871 struct map_selection coord_sel;
1872 struct map_rect *g_rect; // Contains a map rectangle from the route graph's map
1873 struct item *i, *sitem;
1874 struct attr sitem_attr, flags_attr;
1875
1876 // These values cause the code in route.c to get us only the route graph point and connected segments
1877 coord_sel.next = NULL;
1878 coord_sel.u.c_rect.lu = itm->start;
1879 coord_sel.u.c_rect.rl = itm->start;
1880 // the selection's order is ignored
1881
1882 g_rect = map_rect_new(graph_map, &coord_sel);
1883
1884 i = map_rect_get_item(g_rect);
1885
1886 if (!i || i->type != type_rg_point)
1887 {
1888 // probably offroad?
1889 map_rect_destroy(g_rect);
1890 return 0;
1891 }
1892
1893 while (1)
1894 {
1895 i = map_rect_get_item(g_rect);
1896
1897 if (!i)
1898 {
1899 break;
1900 }
1901
1902 if (i->type != type_rg_segment)
1903 {
1904 continue;
1905 }
1906
1907 if (!item_attr_get(i, attr_street_item, &sitem_attr))
1908 {
1909 continue;
1910 }
1911
1912 sitem = sitem_attr.u.item;
1913 if (item_is_equal(itm->way.item, *sitem))
1914 {
1915 if (item_attr_get(i, attr_flags, &flags_attr) && (flags_attr.u.num & NAVIT_AF_ROUNDABOUT))
1916 {
1917 map_rect_destroy(g_rect);
1918 return 1;
1919 }
1920 }
1921 }
1922
1923 map_rect_destroy(g_rect);
1924 return 0;
1925 }
1926
1927
1928
1929 // -- NEW 002 --
1930 static int navigation_split_string_to_list(struct navigation_way *way, char* raw_string, char sep)
1931 {
1932 struct street_destination *new_street_destination = NULL;
1933 struct street_destination *next_street_destination_remember = NULL;
1934 char *pos1 = raw_string;
1935 char *pos2 = NULL;
1936 int count = 0;
1937
1938 navigation_free_list(way->s_destination); /*in case this is a retry with a different separator.*/
1939
1940 //dbg(0,"raw_string=%s split with %c\n",raw_string, sep);
1941 if (strlen(raw_string) > 0)
1942 {
1943 count = 1;
1944 while (pos1)
1945 {
1946 new_street_destination = g_new0(struct street_destination, 1);
1947 new_street_destination->next = next_street_destination_remember;
1948 next_street_destination_remember = new_street_destination;
1949 if ((pos2 = strrchr(pos1, sep)) != NULL)
1950 {
1951 new_street_destination->destination = g_strdup(pos2 + 1);
1952 *pos2 = '\0' ;
1953 //dbg(0,"splitted_off_string=%s\n", new_street_destination->destination);
1954 count++;
1955 }
1956 else
1957 {
1958 new_street_destination->destination = g_strdup(pos1);
1959 pos1 = NULL;
1960 //dbg(0,"head_of_string=%s\n", new_street_destination->destination);
1961 }
1962 way->s_destination = next_street_destination_remember;
1963 }
1964 }
1965 return count;
1966 }
1967
1968 static int navigation_split_string_to_list_2(struct navigation_way *way, char* raw_string, char sep, char sep2)
1969 {
1970 struct street_destination *new_street_destination = NULL;
1971 struct street_destination *next_street_destination_remember = NULL;
1972 char *pos1 = raw_string;
1973 char *pos2 = NULL;
1974 char *pos2a = NULL;
1975 char *pos2b = NULL;
1976 int count = 0;
1977
1978 navigation_free_list(way->s_destination); /*in case this is a retry with a different separator.*/
1979
1980 //dbg(0,"raw_string=%s split with %c\n",raw_string, sep);
1981 if (strlen(raw_string) > 0)
1982 {
1983 count = 1;
1984 while (pos1)
1985 {
1986 new_street_destination = g_new0(struct street_destination, 1);
1987 new_street_destination->next = next_street_destination_remember;
1988 next_street_destination_remember = new_street_destination;
1989
1990 pos2a = strrchr(pos1, sep);
1991 pos2b = strrchr(pos1, sep2);
1992
1993 if (pos2a == NULL)
1994 {
1995 if (pos2b != NULL)
1996 {
1997 pos2 = pos2b;
1998 }
1999 else
2000 {
2001 pos2 = NULL;
2002 }
2003 }
2004 else if (pos2b == NULL)
2005 {
2006 if (pos2a != NULL)
2007 {
2008 pos2 = pos2a;
2009 }
2010 else
2011 {
2012 pos2 = NULL;
2013 }
2014 }
2015 else // both NOT NULL
2016 {
2017 if (pos2a > pos2b)
2018 {
2019 pos2 = pos2b;
2020 }
2021 else
2022 {
2023 pos2 = pos2a;
2024 }
2025 }
2026
2027 if (pos2 != NULL)
2028 {
2029 new_street_destination->destination = g_strdup(pos2 + 1);
2030 *pos2 = '\0' ;
2031 //dbg(0,"splitted_off_string=%s\n", new_street_destination->destination);
2032 count++;
2033 }
2034 else
2035 {
2036 new_street_destination->destination = g_strdup(pos1);
2037 pos1 = NULL;
2038 //dbg(0,"head_of_string=%s\n", new_street_destination->destination);
2039 }
2040 way->s_destination = next_street_destination_remember;
2041 }
2042 }
2043 return count;
2044 }
2045
2046 // -- NEW 002 --
2047
2048
2049
2050
2051
2052
2053
2054
2055 // -- NEW 002 --
2056 /** @brief Selects the destination-names for the next announcement from the
2057 * destination-names that are registered in the following command items.
2058 *
2059 * The aim of this function is to find the destination-name entry that has the most hits in the following
2060 * command items so that the destination name has a relevance over several announcements. If there is no 'winner'
2061 * the entry is selected that is at top of the destination.
2062 *
2063 * thanks to jandegr
2064 */
2065 static navigation_select_announced_destinations(struct navigation_command *current_command)
2066 {
2067 struct street_destination *current_destination = NULL; /* the list pointer of the destination_names of the current command. */
2068 struct street_destination *search_destination = NULL; /* the list pointer of the destination_names of the respective search_command. */
2069
2070 struct navigation_command *search_command = NULL; /* loop through every navigation command up to the end. */
2071
2072 /* limits the number of entries of a destination sign as well as the number of command items to investigate */
2073 #define DEST_MAX_LOOPS_SIGN_TEXTS 10
2074 #define DEST_MAX_LOOPS_NAV_ITEMS 3
2075
2076 int destination_count[DEST_MAX_LOOPS_SIGN_TEXTS] = {0,0,0,0,0,0,0,0,0,0}; /* countains the hits of identical destination signs over all */
2077 /* investigated command items - a 'high score' of destination names */
2078
2079 int destination_index = 0;
2080 int search_command_counter = 0;
2081 int i;
2082 int max_hits;
2083 int max_hit_index;
2084 struct navigation_way *current_nav_way = NULL;
2085
2086 // put text into way struct later -----------------
2087 current_nav_way = &(current_command->itm->way);
2088 if ((current_nav_way) && (current_nav_way->street_dest_text))
2089 {
2090 // already have set a destination --> return
2091 return;
2092 }
2093 current_nav_way->street_dest_text = NULL; // set default to "no value"
2094 // put text into way struct later -----------------
2095
2096
2097 /* search over every following command for seeking identical destination_names */
2098 if (current_command->itm->way.s_destination)
2099 {
2100 /* can we investigate over the following commands? */
2101
2102 if (current_command->next)
2103 {
2104 /* loop over every destination sign of the current command, as far as there are not more than 10 entries. */
2105 destination_index = 0; /* Do only the first DEST_MAX_LOOPS_SIGN_TEXTS destination_signs */
2106 current_destination = current_command->itm->way.s_destination;
2107
2108 while (current_destination && (destination_index < DEST_MAX_LOOPS_SIGN_TEXTS))
2109 { /* initialize the search command */
2110
2111 search_command = current_command->next;
2112 search_command_counter = 0; // Do only the first DEST_MAX_LOOPS_NAV_ITEMS commands.
2113
2114 while (search_command && (search_command_counter < DEST_MAX_LOOPS_NAV_ITEMS))
2115 {
2116 if (search_command->itm)
2117 { /* has the search command any destination_signs? */
2118
2119 if (search_command->itm->way.s_destination)
2120 {
2121 search_destination = search_command->itm->way.s_destination;
2122
2123 while (search_destination)
2124 { /* Search this name in the destination list of the current command. */
2125
2126 if (0 == strcmp(current_destination->destination, search_destination->destination))
2127 { /* enter the destination_name in the investigation list*/
2128
2129 destination_count[destination_index]++;
2130 //search_destination = NULL; /* break condition */
2131 break;
2132 }
2133 else
2134 {
2135 search_destination = search_destination->next;
2136 }
2137 }
2138 }
2139 }
2140 search_command_counter++;
2141 search_command = search_command->next;
2142 }
2143
2144 destination_index++;
2145 current_destination = current_destination->next;
2146 }
2147
2148 /* search for the best candidate */
2149 max_hits = 0;
2150 max_hit_index = 0;
2151 for (i = 0; i < destination_index; i++)
2152 {
2153 if (destination_count[i] > max_hits)
2154 {
2155 max_hits = destination_count[i];
2156 max_hit_index = i;
2157 }
2158 }
2159 /* jump to the corresponding destination_name */
2160 current_destination = current_command->itm->way.s_destination;
2161 for (i = 0; i < max_hit_index; i++)
2162 {
2163 current_destination = current_destination->next;
2164 }
2165 }
2166 else if (current_command->itm->way.exit_label)
2167 {
2168 if ((current_nav_way) && (current_nav_way->street_dest_text))
2169 {
2170 g_free(current_nav_way->street_dest_text);
2171 }
2172
2173 current_nav_way->street_dest_text = g_strdup(current_command->itm->way.exit_label);
2174 #ifdef NAVIT_ROUTING_DEBUG_PRINT
2175 dbg(0, "put exit_label into nav way (C) %s\n", current_command->itm->way.exit_label);
2176 #endif
2177
2178 return;
2179 }
2180 }
2181 else if (current_command->itm->way.exit_label)
2182 {
2183 if ((current_nav_way) && (current_nav_way->street_dest_text))
2184 {
2185 g_free(current_nav_way->street_dest_text);
2186 }
2187
2188 current_nav_way->street_dest_text = g_strdup(current_command->itm->way.exit_label);
2189 #ifdef NAVIT_ROUTING_DEBUG_PRINT
2190 dbg(0, "put exit_label into nav way (A) %s\n", current_command->itm->way.exit_label);
2191 #endif
2192
2193 return;
2194 }
2195
2196
2197
2198
2199
2200 /* return the best candidate, if there is any.*/
2201 if ((current_nav_way) && (current_nav_way->street_dest_text))
2202 {
2203 g_free(current_nav_way->street_dest_text);
2204 current_nav_way->street_dest_text = NULL;
2205 }
2206
2207 if ((current_destination) && (current_destination->destination))
2208 {
2209 current_nav_way->street_dest_text = g_strdup(current_destination->destination);
2210 #ifdef NAVIT_ROUTING_DEBUG_PRINT
2211 dbg(0, "put destination into nav way (B) %s\n", current_nav_way->street_dest_text);
2212 #endif
2213 }
2214 else
2215 {
2216 // stay NULL
2217 //current_nav_way->street_dest_text = NULL;
2218 //dbg(0, "put destination into nav way NULL (C)\n");
2219 }
2220 }
2221 // -- NEW 002 --
2222
2223
2224
2225
2226 static struct navigation_itm *
2227 navigation_itm_new(struct navigation *this_, struct item *ritem)
2228 {
2229 struct navigation_itm *ret=g_new0(struct navigation_itm, 1);
2230 int i = 0;
2231 struct item *sitem;
2232 struct map *graph_map = NULL;
2233 struct attr street_item, direction, route_attr;
2234 struct map_rect *mr;
2235 struct attr attr;
2236 struct coord c[5];
2237
2238 if (ritem)
2239 {
2240 ret->streetname_told = 0;
2241
2242 if (ritem->type == type_street_route_waypoint)
2243 {
2244 dbg(0, "NAVR:XX:0:make street item\n");
2245
2246 while (item_coord_get(ritem, &c[i], 1))
2247 {
2248 if (i < 4)
2249 {
2250 i++;
2251 }
2252 else
2253 {
2254 c[2] = c[3];
2255 c[3] = c[4];
2256 }
2257 }
2258
2259 i--;
2260 ret->start = c[0];
2261 ret->end = c[i];
2262
2263 if (item_attr_get(ritem, attr_direction, &direction))
2264 {
2265 if (direction.u.num < 0)
2266 {
2267 ret->way.dir = -99; // mark waypoint type
2268 }
2269 else
2270 {
2271 ret->way.dir = 99; // mark waypoint type
2272 }
2273 }
2274 else
2275 {
2276 ret->way.dir = 99; // mark waypoint type
2277 }
2278
2279 navigation_itm_update(ret, ritem);
2280 ret->length = 1;
2281 ret->time = 1;
2282 ret->speed = 30;
2283
2284 if (!this_->first)
2285 {
2286 this_->first = ret;
2287 }
2288
2289 if (this_->last)
2290 {
2291 this_->last->next = ret;
2292 ret->prev = this_->last;
2293 //if (graph_map)
2294 //{
2295 // navigation_itm_ways_update(ret, graph_map);
2296 //}
2297 }
2298 this_->last = ret;
2299
2300 return ret;
2301 }
2302
2303 if (!item_attr_get(ritem, attr_street_item, &street_item))
2304 {
2305 dbg(0, "NAVR:XX:1:no street item\n");
2306 g_free(ret);
2307 ret = NULL;
2308 return ret;
2309 }
2310
2311 if (item_attr_get(ritem, attr_direction, &direction))
2312 {
2313 ret->way.dir = direction.u.num;
2314 }
2315 else
2316 {
2317 ret->way.dir = 0;
2318 }
2319
2320 sitem = street_item.u.item;
2321 ret->way.item = *sitem;
2322 item_hash_insert(this_->hash, sitem, ret);
2323 mr = map_rect_new(sitem->map, NULL);
2324
2325 // -- NEW 002 --
2326 struct map *tmap = sitem->map; /*find better name for backup pointer to map*/
2327 // -- NEW 002 --
2328
2329 // COST: 005
2330 dbg(0, "COST:005\n");
2331 if (!(sitem = map_rect_get_item_byid(mr, sitem->id_hi, sitem->id_lo)))
2332 {
2333 // -- NEW 002 --
2334 if (mr)
2335 {
2336 map_rect_destroy(mr);
2337 }
2338 g_free(ret);
2339 ret = NULL;
2340 // -- NEW 002 --
2341
2342 return NULL;
2343 }
2344
2345 // -- NEW 002 --
2346 if (item_attr_get(sitem, attr_flags, &attr))
2347 {
2348 ret->way.flags=attr.u.num;
2349 }
2350 // -- NEW 002 --
2351
2352 if (item_attr_get(sitem, attr_street_name, &attr))
2353 {
2354 ret->way.name1 = map_convert_string(sitem->map, attr.u.str);
2355 }
2356
2357 if (item_attr_get(sitem, attr_street_name_systematic, &attr))
2358 {
2359 ret->way.name2 = map_convert_string(sitem->map, attr.u.str);
2360 }
2361
2362 navigation_itm_update(ret, ritem);
2363
2364 while (item_coord_get(ritem, &c[i], 1))
2365 {
2366 if (i < 4)
2367 {
2368 i++;
2369 }
2370 else
2371 {
2372 c[2] = c[3];
2373 c[3] = c[4];
2374 }
2375 }
2376
2377 i--;
2378
2379
2380
2381 // -- NEW 002 --
2382 if (item_attr_get(sitem, attr_street_destination, &attr))
2383 {
2384 char *destination_raw;
2385 destination_raw = map_convert_string(sitem->map,attr.u.str);
2386 #ifdef NAVIT_ROUTING_DEBUG_PRINT
2387 dbg(0, "DEST::destination_raw=%s\n", destination_raw);
2388 #endif
2389
2390 #ifdef NAVIT_FREE_TEXT_DEBUG_PRINT
2391 char *tt = g_strdup_printf("D:%s", attr.u.str);
2392 route_add_to_freetext_list(&c[0], tt);
2393 g_free(tt);
2394 #endif
2395
2396 // also save full text into "exit_label" --------------
2397 if (ret->way.exit_label)
2398 {
2399 g_free(ret->way.exit_label);
2400 }
2401 ret->way.exit_label = map_convert_string(sitem->map, destination_raw);
2402 // also save full text into "exit_label" --------------
2403
2404 navigation_split_string_to_list(&(ret->way), destination_raw, ';');
2405 g_free(destination_raw);
2406 }
2407 else if (item_attr_get(sitem, attr_street_destination_lanes, &attr))
2408 {
2409 char *destination_raw;
2410 destination_raw = map_convert_string(sitem->map,attr.u.str);
2411 #ifdef NAVIT_ROUTING_DEBUG_PRINT
2412 dbg(0, "DEST::destination_lanes_raw=%s\n", destination_raw);
2413 #endif
2414
2415 #ifdef NAVIT_FREE_TEXT_DEBUG_PRINT
2416 char *tt = g_strdup_printf("d_l:%s", attr.u.str);
2417 route_add_to_freetext_list(&c[0], tt);
2418 g_free(tt);
2419 #endif
2420
2421 // also save full text into "exit_label" --------------
2422 if (ret->way.exit_label)
2423 {
2424 g_free(ret->way.exit_label);
2425 }
2426 ret->way.exit_label = map_convert_string(sitem->map, destination_raw);
2427 // also save full text into "exit_label" --------------
2428
2429 navigation_split_string_to_list_2(&(ret->way), destination_raw, ';', '|');
2430 g_free(destination_raw);
2431 }
2432 // -- NEW 002 --
2433
2434
2435 // ret->way.angle2 = road_angle_accurate(&c[0], &c[1], 0); // angle at start of way
2436 // ret->angle_end = road_angle_accurate(&c[i - 1], &c[i], 0); // angle at end of way
2437 ret->way.angle2 = road_angle(&c[0], &c[1], 0); // angle at start of way
2438 ret->angle_end = road_angle(&c[i - 1], &c[i], 0); // angle at end of way
2439
2440 ret->start = c[0];
2441 ret->end = c[i];
2442
2443 // -- NEW 002 --
2444 /* If we have a ramp check the map for higway_exit info,
2445 * but only on the first node of the ramp.
2446 * Ramps with nodes in reverse order and oneway=-1 are not
2447 * specifically handled, but no occurence known so far either.
2448 * If present, obtain exit_ref, exit_label and exit_to
2449 * from the map.
2450 * exit_to holds info similar to attr_street_destination, and
2451 * we place it in way.s_destination as well, unless the street_destination info
2452 * is already present. In the future it will have to be skipped if destiantion:lanes
2453 * info exists as well.
2454 *
2455 * Now it still holds a bug, if a ramp splits in 2, the exit_to info can end up on
2456 * both continuations of the ramp. Maybe this can be solved by passing the struct
2457 * navigation_maneuver up to here to help decide on exit_to.
2458 *
2459 */
2460
2461 if (item_is_ramp(*sitem)) /* hier motorway_link en trunk_link toevoegen */
2462 {
2463 struct map_selection mselexit;
2464 struct item *rampitem;
2465 struct map_rect *mr2;
2466 struct coord exitcoord;
2467
2468 mselexit.next = NULL;
2469 mselexit.u.c_rect.lu = c[0];
2470 mselexit.u.c_rect.rl = c[0];
2471 mselexit.range = item_range_all;
2472 mselexit.order = 18;
2473
2474 mr2 = map_rect_new(tmap, &mselexit);
2475
2476 while ((rampitem = map_rect_get_item(mr2)))
2477 {
2478 if (rampitem->type == type_highway_exit && item_coord_get(rampitem, &exitcoord, 1)
2479 && exitcoord.x == c[0].x && exitcoord.y == c[0].y)
2480 {
2481 while (item_attr_get(rampitem, attr_any, &attr))
2482 {
2483 if (attr.type && attr.type == attr_label)
2484 {
2485 #ifdef NAVIT_ROUTING_DEBUG_PRINT
2486 dbg(0,"DEST::exit_label=%s\n",attr.u.str);
2487 #endif
2488 if (ret->way.exit_label)
2489 {
2490 g_free(ret->way.exit_label);
2491 }
2492 ret->way.exit_label = map_convert_string(sitem->map,attr.u.str);
2493
2494 #ifdef NAVIT_FREE_TEXT_DEBUG_PRINT
2495 char *tt = g_strdup_printf("exit_label:%s", attr.u.str);
2496 route_add_to_freetext_list(&c[0], tt);
2497 g_free(tt);
2498 #endif
2499
2500 }
2501
2502 if (attr.type == attr_ref)
2503 {
2504 #ifdef NAVIT_ROUTING_DEBUG_PRINT
2505 dbg(0,"DEST::exit_ref=%s\n",attr.u.str);
2506 #endif
2507 if (ret->way.exit_ref)
2508 {
2509 g_free(ret->way.exit_ref);
2510 }
2511 ret->way.exit_ref = map_convert_string(sitem->map,attr.u.str);
2512
2513 #ifdef NAVIT_FREE_TEXT_DEBUG_PRINT
2514 char *tt = g_strdup_printf("exit_ref:%s", attr.u.str);
2515 route_add_to_freetext_list(&c[0], tt);
2516 g_free(tt);
2517 #endif
2518
2519 }
2520
2521 if (attr.type == attr_exit_to)
2522 {
2523 if (attr.u.str && !ret->way.s_destination)
2524 {
2525 char *destination_raw;
2526 destination_raw = map_convert_string(sitem->map,attr.u.str);
2527 #ifdef NAVIT_ROUTING_DEBUG_PRINT
2528 dbg(0,"DEST::destination_raw from exit_to =%s\n",destination_raw);
2529 #endif
2530
2531 // also save full text into "exit_label" --------------
2532 if (ret->way.exit_label)
2533 {
2534 g_free(ret->way.exit_label);
2535 }
2536 ret->way.exit_label = map_convert_string(sitem->map, destination_raw);
2537 // also save full text into "exit_label" --------------
2538
2539 #ifdef NAVIT_FREE_TEXT_DEBUG_PRINT
2540 char *tt = g_strdup_printf("exit_to:%s", destination_raw);
2541 route_add_to_freetext_list(&c[0], tt);
2542 g_free(tt);
2543 #endif
2544
2545 if ((navigation_split_string_to_list(&(ret->way),destination_raw, ';')) < 2)
2546 {
2547 /*
2548 * if a first try did not result in an actual splitting
2549 * retry with ',' as a separator
2550 *
2551 * */
2552 navigation_split_string_to_list(&(ret->way),destination_raw, ',');
2553 }
2554 g_free(destination_raw);
2555 }
2556 }
2557 }
2558 }
2559 }
2560
2561 if (mr2)
2562 {
2563 map_rect_destroy(mr2);
2564 }
2565 }
2566 // -- NEW 002 --
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579 item_attr_get(ritem, attr_route, &route_attr);
2580 graph_map = route_get_graph_map(route_attr.u.route);
2581 if (check_roundabout(ret, graph_map))
2582 {
2583 ret->way.flags |= NAVIT_AF_ROUNDABOUT;
2584 }
2585
2586 // dbg(1, "i=%d start %d end %d '%s' '%s'\n", i, ret->way.angle2, ret->angle_end, ret->way.name1, ret->way.name2);
2587 map_rect_destroy(mr);
2588 }
2589 else
2590 {
2591 if (this_->last)
2592 {
2593 ret->start = ret->end = this_->last->end;
2594 }
2595 }
2596
2597 if (!this_->first)
2598 {
2599 this_->first = ret;
2600 }
2601
2602 if (this_->last)
2603 {
2604 this_->last->next = ret;
2605 ret->prev = this_->last;
2606 if (graph_map)
2607 {
2608 navigation_itm_ways_update(ret, graph_map);
2609 }
2610 }
2611 //dbg(1, "ret=%p\n", ret);
2612 this_->last = ret;
2613 return ret;
2614 }
2615
2616 /**
2617 * @brief Counts how many times a driver could turn right/left
2618 *
2619 * This function counts how many times the driver theoretically could
2620 * turn right/left between two navigation items, not counting the final
2621 * turn itself.
2622 *
2623 * @param from The navigation item which should form the start
2624 * @param to The navigation item which should form the end
2625 * @param direction Set to < 0 to count turns to the left >= 0 for turns to the right
2626 * @return The number of possibilities to turn or -1 on error
2627 */
2628 static int count_possible_turns(struct navigation *nav, struct navigation_itm *from, struct navigation_itm *to, int direction)
2629 {
2630 int count;
2631 struct navigation_itm *curr;
2632 struct navigation_way *w;
2633
2634 if (direction == 0)
2635 {
2636 // we are going straight!!
2637 return -1;
2638 }
2639
2640 count = 0;
2641 curr = from->next;
2642
2643 int cur_next_is_lower_level_street = navigation_is_low_level_street(to->way.item.type);
2644
2645 while (curr && (curr != to))
2646 {
2647 w = curr->way.next;
2648
2649 while (w)
2650 {
2651 if (is_way_allowed(nav, w, 4))
2652 {
2653
2654 // dont count lower level streets, if next turn is NOT also a lower level street
2655 if ((cur_next_is_lower_level_street == 1) || (navigation_is_low_level_street(w->item.type) == 0))
2656 {
2657 if (direction < 0)
2658 {
2659 if (angle_delta(curr->prev->angle_end, w->angle2) < 0)
2660 {
2661 count++;
2662
2663 #ifdef NAVIT_DEBUG_COORD_DIE2TE_LIST
2664 // ------- DEBUG ---------
2665 // ------- DEBUG ---------
2666 // ------- DEBUG ---------
2667 if ((global_debug_coord_list_items + 2) > MAX_DEBUG_COORDS)
2668 {
2669 global_debug_coord_list_items = 0;
2670 }
2671
2672 struct coord c2[5];
2673
2674 if (navigation_get_real_item_first_coord(w, c2))
2675 {
2676 global_debug_coord_list[global_debug_coord_list_items].x = c2[0].x;
2677 global_debug_coord_list[global_debug_coord_list_items].y = c2[0].y;
2678 global_debug_coord_list_items++;
2679 global_debug_coord_list[global_debug_coord_list_items].x = c2[1].x;
2680 global_debug_coord_list[global_debug_coord_list_items].y = c2[1].y;
2681 global_debug_coord_list_items++;
2682 }
2683 // ------- DEBUG ---------
2684 // ------- DEBUG ---------
2685 // ------- DEBUG ---------
2686 #endif
2687
2688
2689 break;
2690 }
2691 }
2692 else if (direction > 0)
2693 {
2694 if (angle_delta(curr->prev->angle_end, w->angle2) > 0)
2695 {
2696 count++;
2697 #ifdef NAVIT_DEBUG_COORD_DIE2TE_LIST
2698 // ------- DEBUG ---------
2699 // ------- DEBUG ---------
2700 // ------- DEBUG ---------
2701 if ((global_debug_coord_list_items + 2) > MAX_DEBUG_COORDS)
2702 {
2703 global_debug_coord_list_items = 0;
2704 }
2705
2706 struct coord c2[5];
2707
2708 if (navigation_get_real_item_first_coord(w, c2))
2709 {
2710 global_debug_coord_list[global_debug_coord_list_items].x = c2[0].x;
2711 global_debug_coord_list[global_debug_coord_list_items].y = c2[0].y;
2712 global_debug_coord_list_items++;
2713 global_debug_coord_list[global_debug_coord_list_items].x = c2[1].x;
2714 global_debug_coord_list[global_debug_coord_list_items].y = c2[1].y;
2715 global_debug_coord_list_items++;
2716 }
2717 // ------- DEBUG ---------
2718 // ------- DEBUG ---------
2719 // ------- DEBUG ---------
2720 #endif
2721
2722 break;
2723 }
2724 }
2725 }
2726 }
2727 w = w->next;
2728 }
2729 curr = curr->next;
2730 }
2731
2732 if (!curr)
2733 {
2734 // from does not lead to to?
2735 return -1;
2736 }
2737
2738 return count;
2739 }
2740
2741 /**
2742 * @brief Calculates distance and time to the destination
2743 *
2744 * This function calculates the distance and the time to the destination of a
2745 * navigation. If incr is set, this is only calculated for the first navigation
2746 * item, which is a lot faster than re-calculation the whole destination, but works
2747 * only if the rest of the navigation already has been calculated.
2748 *
2749 * @param this_ The navigation whose destination / time should be calculated
2750 * @param incr Set this to true to only calculate the first item. See description.
2751 */
2752 static void calculate_dest_distance(struct navigation *this_, int incr)
2753 {
2754 int len = 0, time = 0, count = 0;
2755 struct navigation_itm *next = NULL;
2756 struct navigation_itm *itm = this_->last;
2757
2758 //dbg(1, "enter this_=%p, incr=%d\n", this_, incr);
2759
2760 if (incr)
2761 {
2762 if (itm)
2763 {
2764 //dbg(2, "old values: (%p) time=%d lenght=%d\n", itm,
2765 // itm->dest_length, itm->dest_time);
2766 }
2767 else
2768 {
2769 //dbg(2, "old values: itm is null\n");
2770 }
2771 itm = this_->first;
2772 next = itm->next;
2773 //dbg(2, "itm values: time=%d lenght=%d\n", itm->length, itm->time);
2774 //dbg(2, "next values: (%p) time=%d lenght=%d\n", next, next->dest_length, next->dest_time);
2775 itm->dest_length = next->dest_length + itm->length;
2776 itm->dest_count = next->dest_count + 1;
2777 itm->dest_time = next->dest_time + itm->time;
2778 //dbg(2, "new values: time=%d lenght=%d\n", itm->dest_length, itm->dest_time);
2779 return;
2780 }
2781
2782 while (itm)
2783 {
2784 len += itm->length;
2785 time += itm->time;
2786 itm->dest_length = len;
2787 itm->dest_time = time;
2788 itm->dest_count = count++;
2789 itm = itm->prev;
2790 }
2791 //dbg(1, "len %d time %d\n", len, time);
2792 }
2793
2794 /**
2795 *
2796 * check it w1 is the same as w2 (duplicate way)
2797 *
2798 * @param w1 The first way to be checked
2799 * @param w2 The second way to be checked
2800 * @return 0 -> no, 1 -> yes:it's the same way
2801 *
2802 */
2803 static int is_maybe_same_item(struct navigation_way *w1, struct navigation_way *w2, int reverse_match)
2804 {
2805
2806 dbg(0, "======================================\n");
2807
2808 dbg(0, "w1=%p w2=%p\n", w1, w2);
2809
2810 dbg(0, "w1 type=%s w2 type=%s\n", item_to_name(w1->item.type), item_to_name(w2->item.type));
2811 dbg(0, "w1 dir=%d w2 dir=%d\n", w1->dir, w2->dir);
2812 dbg(0, "w1 angle2=%d w2 angle2=%d\n", w1->angle2, w2->angle2);
2813 dbg(0, "w1 n1=%s w2 n1=%s\n", w1->name1, w2->name1);
2814 dbg(0, "w1 n2=%s w2 n2=%s\n", w1->name2, w2->name2);
2815
2816 #ifdef NAVIT_NAVIGATION_REMOVE_DUPL_WAYS
2817
2818 int dir_reverse = 0;
2819
2820 if (w1->item.type != w2->item.type)
2821 {
2822 dbg(0, "x:w1 type=%s w2 type=%s\n", item_to_name(w1->item.type), item_to_name(w2->item.type));
2823 return 0;
2824 }
2825
2826 #if 0
2827 if (w1->dir != w2->dir)
2828 {
2829 dir_reverse = 1;
2830 }
2831 #endif
2832
2833 if (reverse_match != 0)
2834 {
2835 dir_reverse = 1 - dir_reverse; // toggle "dir_reverse"
2836 }
2837
2838 if (dir_reverse == 0)
2839 {
2840 if ((abs(w1->angle2 - w2->angle2) != 0) && (abs(w1->angle2 - w2->angle2) != 360))
2841 {
2842 dbg(0, "x:000:w1 angle2=%d w2 angle2=%d\n", w1->angle2, w2->angle2);
2843 return 0;
2844 }
2845 }
2846 else
2847 {
2848 if (abs(w1->angle2 - w2->angle2) != 180)
2849 {
2850 dbg(0, "x:180:w1 angle2=%d w2 angle2=%d\n", w1->angle2, w2->angle2);
2851 return 0;
2852 }
2853 }
2854
2855
2856 if ((w1->name1 == NULL) && (w2->name1 == NULL))
2857 {
2858 }
2859 else
2860 {
2861 if ((w1->name1 == NULL) || (w2->name1 == NULL))
2862 {
2863 return 0;
2864 }
2865 else if (strcmp(w1->name1, w2->name1) != 0)
2866 {
2867 dbg(0, "x:w1 n1=%s w2 n1=%s\n", w1->name1, w2->name1);
2868 return 0;
2869 }
2870 }
2871
2872 if ((w1->name2 == NULL) && (w2->name2 == NULL))
2873 {
2874 }
2875 else
2876 {
2877 if ((w1->name2 == NULL) || (w2->name2 == NULL))
2878 {
2879 return 0;
2880 }
2881 else if (strcmp(w1->name2, w2->name2) != 0)
2882 {
2883 dbg(0, "x:w1 n2=%s w2 n2=%s\n", w1->name2, w2->name2);
2884 return 0;
2885 }
2886 }
2887
2888 return 1;
2889
2890 #else
2891
2892 return 0;
2893
2894 #endif
2895
2896 }
2897
2898 /**
2899 * @brief Checks if two navigation items are on the same street
2900 *
2901 * This function checks if two navigation items are on the same street. It returns
2902 * true if either their name or their "systematic name" (e.g. "A6" or "B256") are the
2903 * same.
2904 *
2905 * @param old The first item to be checked
2906 * @param new The second item to be checked
2907 * @return True if both old and new are on the same street
2908 */
2909 static int is_same_street2(char *old_name1, char *old_name2, char *new_name1, char *new_name2)
2910 {
2911 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
2912 {
2913 // always return false when in bicycle mode
2914 return 0;
2915 }
2916
2917 if (old_name1 && new_name1 && !strcmp(old_name1, new_name1))
2918 {
2919 // dbg(1, "is_same_street: '%s' '%s' vs '%s' '%s' yes (1.)\n", old_name2, new_name2, old_name1, new_name1);
2920 return 1;
2921 }
2922
2923 if (old_name2 && new_name2 && !strcmp(old_name2, new_name2))
2924 {
2925 // dbg(1, "is_same_street: '%s' '%s' vs '%s' '%s' yes (2.)\n", old_name2, new_name2, old_name1, new_name1);
2926 return 1;
2927 }
2928
2929 // dbg(1, "is_same_street: '%s' '%s' vs '%s' '%s' no\n", old_name2, new_name2, old_name1, new_name1);
2930 return 0;
2931 }
2932
2933 #if 0
2934 /**
2935 * @brief Checks if two navigation items are on the same street
2936 *
2937 * This function checks if two navigation items are on the same street. It returns
2938 * true if the first part of their "systematic name" is equal. If the "systematic name" is
2939 * for example "A352/E3" (a german highway which at the same time is part of the international
2940 * E-road network), it would only search for "A352" in the second item's systematic name.
2941 *
2942 * @param old The first item to be checked
2943 * @param new The second item to be checked
2944 * @return True if the "systematic name" of both items matches. See description.
2945 */
2946 static int
2947 is_same_street_systematic(struct navigation_itm *old, struct navigation_itm *new)
2948 {
2949 int slashold,slashnew;
2950 if (!old->name2 || !new->name2)
2951 return 1;
2952 slashold=strcspn(old->name2, "/");
2953 slashnew=strcspn(new->name2, "/");
2954 if (slashold != slashnew || strncmp(old->name2, new->name2, slashold))
2955 return 0;
2956 return 1;
2957 }
2958
2959 /**
2960 * @brief Check if there are multiple possibilities to drive from old
2961 *
2962 * This function checks, if there are multiple streets connected to the exit of "old".
2963 * Sometimes it happens that an item on a map is just segmented, without any other streets
2964 * being connected there, and it is not useful if navit creates a maneuver there.
2965 *
2966 * @param new The navigation item we're driving to
2967 * @return True if there are multiple streets
2968 */
2969 static int
2970 maneuver_multiple_streets(struct navigation_itm *new)
2971 {
2972 if (new->way.next)
2973 {
2974 return 1;
2975 }
2976 else
2977 {
2978 return 0;
2979 }
2980 }
2981
2982 /**
2983 * @brief Check if the new item is entered "straight"
2984 *
2985 * This function checks if the new item is entered "straight" from the old item, i.e. if there
2986 * is no other street one could take from the old item on with less steering.
2987 *
2988 * @param new The navigation item we're driving to
2989 * @param diff The absolute angle one needs to steer to drive to this item
2990 * @return True if the new item is entered "straight"
2991 */
2992 static int
2993 maneuver_straight(struct navigation_itm *new, int diff)
2994 {
2995 int curr_diff;
2996 struct navigation_way *w;
2997
2998 w = new->way.next;
2999 dbg(1,"diff=%d\n", diff);
3000 while (w)
3001 {
3002 curr_diff=abs(angle_delta(new->prev->angle_end, w->angle2));
3003 dbg(1,"curr_diff=%d\n", curr_diff);
3004 if (curr_diff < diff)
3005 {
3006 return 0;
3007 }
3008 w = w->next;
3009 }
3010 return 1;
3011 }
3012 #endif
3013
3014 static int maneuver_category(enum item_type type)
3015 {
3016 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
3017 {
3018 switch (type)
3019 {
3020 case type_cycleway:
3021 return 1;
3022 case type_footway:
3023 return 1;
3024 case type_street_service:
3025 return 1;
3026 case type_street_parking_lane:
3027 return 1;
3028 case type_living_street:
3029 return 1;
3030 case type_street_0:
3031 return 1;
3032 case type_street_1_city:
3033 return 2;
3034 case type_street_2_city:
3035 case type_ramp_street_2_city:
3036 return 3;
3037 case type_street_3_city:
3038 case type_ramp_street_3_city:
3039 return 4;
3040 case type_street_4_city:
3041 case type_ramp_street_4_city:
3042 return 5;
3043 case type_highway_city:
3044 return 7;
3045 case type_street_1_land:
3046 return 2;
3047 case type_street_2_land:
3048 return 3;
3049 case type_street_3_land:
3050 return 4;
3051 case type_street_4_land:
3052 return 5;
3053 case type_street_n_lanes:
3054 return 6;
3055 case type_ramp_highway_land:
3056 return 6;
3057 case type_highway_land:
3058 return 7;
3059 //case type_ramp:
3060 // return 0;
3061 case type_roundabout:
3062 return 0;
3063 case type_ferry:
3064 return 0;
3065 default:
3066 return 0;
3067 }
3068 }
3069 else // car mode ---------------
3070 {
3071 switch (type)
3072 {
3073 case type_street_0:
3074 return 1;
3075 case type_street_1_city:
3076 return 2;
3077 case type_street_2_city:
3078 case type_ramp_street_2_city:
3079 return 3;
3080 case type_street_3_city:
3081 case type_ramp_street_3_city:
3082 return 4;
3083 case type_street_4_city:
3084 case type_ramp_street_4_city:
3085 return 5;
3086 case type_highway_city:
3087 return 7;
3088 case type_street_1_land:
3089 return 2;
3090 case type_street_2_land:
3091 return 3;
3092 case type_street_3_land:
3093 return 4;
3094 case type_street_4_land:
3095 return 5;
3096 case type_street_n_lanes:
3097 return 6;
3098 case type_ramp_highway_land:
3099 return 6;
3100 case type_highway_land:
3101 return 7;
3102 //case type_ramp:
3103 // return 0;
3104 case type_roundabout:
3105 return 0;
3106 case type_ferry:
3107 return 0;
3108 default:
3109 return 0;
3110 }
3111 }
3112 }
3113
3114
3115
3116
3117
3118 static int maneuver_category_calc2(enum item_type type)
3119 {
3120 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
3121 {
3122 switch (type)
3123 {
3124 case type_cycleway:
3125 return 1;
3126 case type_footway:
3127 return 1;
3128 case type_street_service:
3129 return 1;
3130 case type_street_parking_lane:
3131 return 1;
3132 case type_living_street:
3133 return 1;
3134 case type_street_0:
3135 return 1;
3136 case type_street_1_city:
3137 return 2;
3138 case type_street_2_city:
3139 case type_ramp_street_2_city:
3140 return 3;
3141 case type_street_3_city:
3142 case type_ramp_street_3_city:
3143 return 4;
3144 case type_street_4_city:
3145 case type_ramp_street_4_city:
3146 return 5;
3147 case type_highway_city:
3148 return 7;
3149 case type_street_1_land:
3150 return 2;
3151 case type_street_2_land:
3152 return 3;
3153 case type_street_3_land:
3154 return 4;
3155 case type_street_4_land:
3156 return 5;
3157 case type_street_n_lanes:
3158 return 6;
3159 case type_ramp_highway_land:
3160 return 6;
3161 case type_highway_land:
3162 return 7;
3163 //case type_ramp:
3164 // return 0;
3165 case type_roundabout:
3166 return 0;
3167 case type_ferry:
3168 return 0;
3169 default:
3170 return 0;
3171 }
3172 }
3173 else
3174 {
3175 switch (type)
3176 {
3177 case type_street_0:
3178 return 1;
3179 case type_street_1_city:
3180 return 1;
3181 case type_street_2_city:
3182 case type_ramp_street_2_city:
3183 return 4;
3184 case type_street_3_city:
3185 case type_ramp_street_3_city:
3186 return 4;
3187 case type_street_4_city:
3188 case type_ramp_street_4_city:
3189 return 4;
3190 case type_highway_city:
3191 return 7;
3192 case type_street_1_land:
3193 return 1;
3194 case type_street_2_land:
3195 return 4;
3196 case type_street_3_land:
3197 return 4;
3198 case type_street_4_land:
3199 return 4;
3200 case type_street_n_lanes:
3201 return 6;
3202 case type_ramp_highway_land:
3203 return 6;
3204 case type_highway_land:
3205 return 7;
3206 //case type_ramp: // ramp need to be high enough
3207 // return 4;
3208 case type_roundabout:
3209 return 0;
3210 case type_ferry:
3211 return 0;
3212 default:
3213 return 0;
3214 }
3215 }
3216 }
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227 static int is_way_allowed(struct navigation *nav, struct navigation_way *way, int mode)
3228 {
3229 if (!nav->vehicleprofile)
3230 {
3231 return 1;
3232 }
3233
3234 return !way->flags || ((way->flags & (way->dir >= 0 ? route_get_real_oneway_mask(way->flags, nav->vehicleprofile->flags_forward_mask) : route_get_real_oneway_mask(way->flags, nav->vehicleprofile->flags_reverse_mask))) == nav->vehicleprofile->flags);
3235 }
3236
3237 /**
3238 * @brief Checks if navit has to create a maneuver to drive from old to new (run only once!!)
3239 *
3240 * This function checks if it has to create a "maneuver" - i.e. guide the user - to drive
3241 * from "old" to "new".
3242 *
3243 * @param old The old navigation item, where we're coming from
3244 * @param new The new navigation item, where we're going to
3245 * @param delta The angle the user has to steer to navigate from old to new
3246 * @param reason A text string explaining how the return value resulted
3247 * @return True if navit should guide the user, false otherwise
3248 */
3249 static int maneuver_required2(struct navigation *nav, struct navigation_itm *old, struct navigation_itm *new, int *delta, int *delta_real, char **reason)
3250 {
3251 int ret = 0, d, dw, dlim;
3252 char *r = NULL;
3253 struct navigation_way *w = NULL;
3254 int cat, ncat, wcat, maxcat, left = -180, right = 180, is_unambigous = 0, is_same_street;
3255 int cat_2 = 0;
3256 int ncat_2 = 0;
3257 int highest_other_cat = 0;
3258 int original_d = 0;
3259
3260 dbg(0, "STRAI:000:\n");
3261 dbg(0, "STRAI:000:======================================\n");
3262
3263 // ---------------------------
3264 //
3265 // HINT: angle < 0 --> left
3266 // > 0 --> right
3267 // = 0 --> straight
3268 //
3269 // ---------------------------
3270
3271 d = angle_delta(old->angle_end, new->way.angle2);
3272 original_d = d;
3273
3274 //long long wayid_old = navigation_item_get_wayid(&(old->way));
3275 //long long wayid_new = navigation_item_get_wayid(&(new->way));
3276 //dbg(0, "Enter d=%d old->angle_end=%d new->way.angle2=%d old_way_id=%lld new_way_id=%lld\n", d, old->angle_end, new->way.angle2, wayid_old, wayid_new);
3277
3278 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2)) // bicycle mode
3279 {
3280 int flags_old = navigation_item_get_flags(&(old->way));
3281 int flags_new = navigation_item_get_flags(&(new->way));
3282
3283 //dbg(0, "(b1)old flags=%x new flags=%x old dir=%d new dir=%d\n", old->way.flags, new->way.flags, old->way.dir, new->way.dir);
3284 //dbg(0, "(b2)old flags=%x new flags=%x\n", (flags_old & NAVIT_AF_ONEWAY), (flags_new & NAVIT_AF_ONEWAY));
3285 //dbg(0, "(b3)old flags=%x new flags=%x\n", (flags_old & NAVIT_AF_ONEWAYREV), (flags_new & NAVIT_AF_ONEWAYREV));
3286
3287 if ((old->way.dir == 1) && ((new->way.dir == -1) && (new->way.flags & NAVIT_AF_ONEWAY_BICYCLE_NO)))
3288 {
3289 r = "yes: bicycle starts going against oneway here (1)";
3290 ret = 1;
3291 //dbg(0, "%s\n", r);
3292 }
3293 else if ( ((old->way.dir == -1) && (!(old->way.flags & NAVIT_AF_ONEWAY_BICYCLE_NO)) ) && ((new->way.dir == -1) && (new->way.flags & NAVIT_AF_ONEWAY_BICYCLE_NO)))
3294 {
3295 r = "yes: bicycle starts going against oneway here (2)";
3296 ret = 1;
3297 //dbg(0, "%s\n", r);
3298 }
3299 }
3300
3301
3302
3303
3304 // z2z2
3305 int have_more_than_one_way_to_turn = 0;
3306 int have_more_than_one_way_to_turn_cycleways = 0;
3307 struct navigation_way *w22;
3308 w22 = new->way.next;
3309 int new_angle_abs = 999;
3310 int new_angle_abs_min = 999;
3311 int new_angle_abs_min_allowed = 999;
3312 int new_angle_real = 999;
3313 int new_angle_min_allowed = 999;
3314 int new_angle_abs_min_ramp_allowed = 999;
3315 int old_angle_abs = abs(d);
3316 int new_angle_closest_to_cur = 999;
3317 int no_correction = 0;
3318
3319 dbg(0, "STRAI:001:d=%d original_d=%d\n", old_angle_abs, original_d);
3320
3321 while (w22)
3322 {
3323
3324 dbg(0, "STRAI:002\n");
3325
3326 //if ((w22->dir == -1) && (w22->flags & NAVIT_AF_ONEWAY))
3327 //{
3328 // // against oneway not allowed
3329 //}
3330 if (((global_vehicle_profile != 1) && (global_vehicle_profile != 2)) // NOT bicycle mode
3331 && (navigation_is_low_level_street(old->way.item.type) == 0)
3332 && (navigation_is_low_level_street(new->way.item.type) == 0)
3333 && (navigation_is_low_level_street(w22->item.type) == 1))
3334 {
3335 // dont count "lower" streets when not on "lower" street now or next
3336 }
3337 else
3338 {
3339
3340 if ( (is_maybe_same_item(&(new->way), w22, 0) == 0) && (is_maybe_same_item(&(old->way), w22, 1) == 0) )
3341 {
3342
3343 new_angle_real = angle_delta(old->angle_end, w22->angle2);
3344 new_angle_abs = abs(new_angle_real);
3345 if (new_angle_abs < new_angle_abs_min)
3346 {
3347 new_angle_abs_min = new_angle_abs;
3348 }
3349
3350 if (is_way_allowed(nav, w22, 1))
3351 {
3352 have_more_than_one_way_to_turn = 1;
3353
3354 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2)) // bicycle mode
3355 {
3356 if (w22->item.type == type_cycleway)
3357 {
3358 have_more_than_one_way_to_turn_cycleways = 1;
3359 }
3360 }
3361
3362 if (maneuver_category_calc2(w22->item.type) > highest_other_cat)
3363 {
3364 highest_other_cat = maneuver_category_calc2(w22->item.type);
3365 }
3366
3367 if (item_is_ramp(w22->item))
3368 {
3369 if (new_angle_abs < new_angle_abs_min_ramp_allowed)
3370 {
3371 new_angle_abs_min_ramp_allowed = new_angle_abs;
3372 }
3373 }
3374
3375 if (abs(new_angle_real - d) < abs(new_angle_closest_to_cur))
3376 {
3377 new_angle_closest_to_cur = new_angle_real;
3378 }
3379
3380 if (new_angle_abs < new_angle_abs_min_allowed)
3381 {
3382 new_angle_abs_min_allowed = new_angle_abs;
3383 new_angle_min_allowed = new_angle_real;
3384 }
3385 }
3386
3387 dbg(0, "STRAI:003:new angle abs=%d min_allowed=%d have_more_than_one_way_to_turn=%d new_angle_closest_to_cur=%d d=%d\n", new_angle_abs, new_angle_abs_min_allowed, have_more_than_one_way_to_turn, new_angle_closest_to_cur, d);
3388
3389 }
3390 }
3391 w22 = w22->next;
3392 }
3393
3394 dbg(0, "STRAI:004 new_angle_abs_min=%d new_angle_abs_min_allowed=%d\n", new_angle_abs_min, new_angle_abs_min_allowed);
3395
3396 if ((new_angle_abs_min_allowed > ROAD_ANGLE_IS_STRAIGHT_ABS) && (old_angle_abs <= ROAD_ANGLE_IS_STRAIGHT_ABS))
3397 {
3398 dbg(0, "STRAI:005 new_abs=%d old_abs=%d\n", new_angle_abs_min_allowed, old_angle_abs);
3399
3400 // we want to drive almost straight, set angle to "0"
3401 d = 0;
3402 }
3403
3404 dbg(0, "STRAI:005a:d=%d\n", d);
3405
3406 if (!r)
3407 {
3408 if (have_more_than_one_way_to_turn == 1) // more than 1 possibility
3409 {
3410 if (new->way.exit_label)
3411 {
3412 // highway to highway, nearest ramp is more than 15° angle turn
3413 if ( (cat > 6) && (ncat > 6) && (highest_other_cat <= 6) && (abs(d) < 12) && (new_angle_abs_min_ramp_allowed > 15) )
3414 {
3415 dbg(0, "STRAI:005a:d=%d\n", d);
3416 r = "no: driving almost straight on highway and no other highway possibilities (1)";
3417 }
3418 else
3419 {
3420 // r = "yes: we have an exit-sign to tell the user";
3421 // ret = 1;
3422 }
3423 }
3424 else if (new->way.s_destination)
3425 {
3426 if ( (cat > 6) && (ncat > 6) && (highest_other_cat <= 6) && (abs(d) < 12) && (new_angle_abs_min_ramp_allowed > 15) )
3427 {
3428 dbg(0, "STRAI:005a:d=%d\n", d);
3429 r = "no: driving almost straight on highway and no other highway possibilities (2)";
3430 }
3431 else
3432 {
3433 // r = "yes: we have a road-sign to tell the user";
3434 // ret = 1;
3435 }
3436 }
3437 else if (item_is_ramp(old->way.item))
3438 {
3439 r = "yes: we are currently on a ramp and have more than 1 road to take";
3440 ret = 1;
3441 }
3442 }
3443 }
3444
3445
3446 if ((global_vehicle_profile != 1) && (global_vehicle_profile != 2))
3447 {
3448 if (!new->way.next)
3449 {
3450 /* No announcement necessary */
3451 r = "no: Only one possibility";
3452 }
3453 else if (!new->way.next->next && item_is_ramp(new->way.next->item) && !is_way_allowed(nav, new->way.next, 1))
3454 {
3455 /* If the other way is only a ramp and it is one-way in the wrong direction, no announcement necessary */
3456 r = "no: Only ramp";
3457 }
3458 }
3459 else // bicycle mode --------------------
3460 {
3461 if (!r)
3462 {
3463 #if 0
3464 if ((!new->way.next) && (abs(d) < 20))
3465 {
3466 /* No announcement necessary */
3467 r = "no: Only one possibility and less than 20° turn";
3468 dbg(0, "%s\n", r);
3469 }
3470 else
3471 {
3472 if (abs(d) > 2)
3473 {
3474 r = "yes: bicycle mode";
3475 dbg(0, "%s\n", r);
3476 ret = 1;
3477 }
3478 else
3479 {
3480 r = "no: less than 3° turn";
3481 dbg(0, "%s\n", r);
3482 }
3483 }
3484 #endif
3485
3486 #if 0
3487 if (!new->way.next)
3488 {
3489 /* No announcement necessary */
3490 r = "no: Only one possibility";
3491 }
3492 #endif
3493
3494 #if 1
3495
3496 if ((old->way.item.type == type_cycleway) && (new->way.item.type == type_cycleway))
3497 {
3498 if (have_more_than_one_way_to_turn_cycleways == 0)
3499 {
3500 if (abs(d) > ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE_CYC_2_CYC)
3501 {
3502 r = "yes: delta over ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE_CYC_2_CYC in bicycle mode (Only one possibility cyc-2-cyc)";
3503 //dbg(0, "%s\n", r);
3504 ret = 1;
3505 }
3506 else
3507 {
3508 r = "no: delta less than ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE_CYC_2_CYC in bicycle mode (Only one possibility cyc-2-cyc)";
3509 //dbg(0, "%s\n", r);
3510 ret = 0;
3511 }
3512 }
3513 else
3514 {
3515 if (abs(d) > ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE_CYC_2_CYC__2)
3516 {
3517 r = "yes: delta over ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE_CYC_2_CYC__2 in bicycle mode (cyc-2cyc)";
3518 //dbg(0, "%s\n", r);
3519 ret = 1;
3520 }
3521 else
3522 {
3523 r = "no: delta less than ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE_CYC_2_CYC__2 in bicycle mode (cyc-2cyc)";
3524 //dbg(0, "%s\n", r);
3525 ret = 0;
3526 }
3527 }
3528 }
3529 else
3530 {
3531
3532 if (!new->way.next)
3533 {
3534 if (abs(d) > ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE)
3535 {
3536 r = "yes: delta over ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE in bicycle mode (Only one possibility)";
3537 //dbg(0, "%s\n", r);
3538 ret = 1;
3539 }
3540 else
3541 {
3542 r = "no: delta less than ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE in bicycle mode (Only one possibility)";
3543 //dbg(0, "%s\n", r);
3544 ret = 0;
3545 }
3546 }
3547 else
3548 {
3549 if (abs(d) > ROAD_ANGLE_MIN__FOR_TURN_BICYCLEMODE_ONLY_1_POSSIBILITY)
3550 {
3551 r = "yes: delta over ROAD_ANGLE_MIN__FOR_TURN_BICYCLEMODE_ONLY_1_POSSIBILITY in bicycle mode";
3552 //dbg(0, "%s\n", r);
3553 ret = 1;
3554 }
3555 else
3556 {
3557 r = "no: delta less than ROAD_ANGLE_MIN__FOR_TURN_BICYCLEMODE_ONLY_1_POSSIBILITY in bicycle mode";
3558 //dbg(0, "%s\n", r);
3559 ret = 0;
3560 }
3561 }
3562
3563 }
3564 #endif
3565
3566 }
3567 }
3568
3569 if (!r)
3570 {
3571 if ((old->way.flags & NAVIT_AF_ROUNDABOUT) && !(new->way.flags & NAVIT_AF_ROUNDABOUT))
3572 {
3573 r = "yes: leaving roundabout";
3574 ret = 1;
3575 }
3576 else if (!(old->way.flags & NAVIT_AF_ROUNDABOUT) && (new->way.flags & NAVIT_AF_ROUNDABOUT))
3577 {
3578 r = "no: entering roundabout";
3579 }
3580 else if ((old->way.flags & NAVIT_AF_ROUNDABOUT) && (new->way.flags & NAVIT_AF_ROUNDABOUT))
3581 {
3582 r = "no: staying in roundabout";
3583 }
3584 }
3585
3586 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
3587 {
3588 if (!r && abs(d) > ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE)
3589 {
3590 /* always make an announcement if you have to make a turn */
3591 r = "yes: delta over ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE in bicycle mode";
3592 //dbg(0, "%s\n", r);
3593 ret = 1;
3594 }
3595 }
3596 else // car mode ---------------------
3597 {
3598 if (!r && abs(d) > 75)
3599 {
3600 /* always make an announcement if you have to make a sharp turn */
3601 r = "yes: delta over 75";
3602 ret = 1;
3603 }
3604 }
3605
3606 cat = maneuver_category(old->way.item.type);
3607 ncat = maneuver_category(new->way.item.type);
3608
3609 cat_2 = maneuver_category_calc2(old->way.item.type);
3610 ncat_2 = maneuver_category_calc2(new->way.item.type);
3611
3612
3613 if (!r)
3614 {
3615 /* Check whether the street keeps its name */
3616 is_same_street = is_same_street2(old->way.name1, old->way.name2, new->way.name1, new->way.name2);
3617
3618 dbg(0, "STRAI:011.01 is_same_street=%d old->way.name1=%s old->way.name2=%s new->way.name1=%s new->way.name2=%s\n", is_same_street, old->way.name1, old->way.name2, new->way.name1, new->way.name2);
3619
3620 w = new->way.next;
3621 maxcat = -1;
3622 while (w)
3623 {
3624 if ( (is_maybe_same_item(&(new->way), w, 0) == 0) && (is_maybe_same_item(&(old->way), w, 1) == 0) )
3625 {
3626 dw = angle_delta(old->angle_end, w->angle2);
3627 dbg(0, "STRAI:011.02 dw=%d l=%d r=%d\n", dw, left, right);
3628
3629 if (dw < 0)
3630 {
3631 if (dw > left)
3632 {
3633 left = dw;
3634 }
3635 }
3636 else
3637 {
3638 if (dw < right)
3639 {
3640 right = dw;
3641 }
3642 }
3643
3644 wcat = maneuver_category(w->item.type);
3645 dbg(0, "STRAI:011.03 wcat=%d\n", wcat);
3646
3647 /* If any other street has the same name [ removed:"but isn't a highway (a highway might split up temporarily)" ], then
3648 we can't use the same name criterium */
3649 // if (is_same_street && is_same_street2(old->way.name1, old->way.name2, w->name1, w->name2) && (cat != 7 || wcat != 7) && is_way_allowed(nav, w, 2))
3650 if (is_same_street && is_same_street2(old->way.name1, old->way.name2, w->name1, w->name2) && is_way_allowed(nav, w, 2))
3651 {
3652 is_same_street = 0;
3653 dbg(0, "STRAI:011.04 is_same_street=%d\n", is_same_street);
3654 }
3655
3656 /* Mark if the street has a higher or the same category */
3657 if (wcat > maxcat)
3658 {
3659 maxcat = wcat;
3660 dbg(0, "STRAI:011.06 maxcat=%d wcat=%d\n", maxcat, wcat);
3661 }
3662
3663 }
3664
3665 w = w->next;
3666 }
3667
3668 if (have_more_than_one_way_to_turn == 1) // more than 1 possibility
3669 {
3670 /* Even if the ramp has the same name, announce it */
3671 if (item_is_ramp(new->way.item) && !item_is_ramp(old->way.item))
3672 {
3673 is_same_street = 0;
3674 dbg(0, "STRAI:011.05.xx is_same_street=%d\n", is_same_street);
3675 }
3676 }
3677
3678 /* get the delta limit for checking for other streets. It is lower if the street has no other
3679 streets of the same or higher category */
3680 if (ncat < cat)
3681 {
3682 dlim = 80;
3683 }
3684 else
3685 {
3686 dlim = 120;
3687 }
3688
3689 /* if the street is really straight, the others might be closer to straight */
3690 if (abs(d) < 20)
3691 {
3692 dlim /= 2;
3693 }
3694
3695 if ((maxcat == ncat && maxcat == cat) || (ncat == 0 && cat == 0))
3696 {
3697 dlim = abs(d) * (620 / 256); // abs(d) * 2.4
3698 }
3699 else if (maxcat < ncat && maxcat < cat)
3700 {
3701 dlim = abs(d) * (128 / 256); // abs(d) * 0.5
3702 }
3703
3704 if (left < -dlim && right > dlim) // no other road is between -dlim : dlim angle (no other road is "dlim" close to straight)
3705 {
3706 is_unambigous = 1;
3707 }
3708
3709 if (!is_same_street && is_unambigous < 1)
3710 {
3711 ret = 1;
3712 r = "yes: (not same street) or (ambigous [nicht eindeutig])";
3713 }
3714 else
3715 {
3716 r = "no: (same street) and (unambigous [eindeutig])";
3717 }
3718
3719 if (ret == 0)
3720 {
3721 // add a new check here:
3722 if (have_more_than_one_way_to_turn == 1)
3723 {
3724
3725 dbg(0, "STRAI:11.07:4.0: cat=%d, ncat=%d, highest_other_cat=%d, d=%d, abs(d)=%d new_angle_closest_to_cur=%d original_d=%d\n", cat, ncat, highest_other_cat, d, abs(d), new_angle_closest_to_cur, original_d);
3726
3727 if ( (cat > 6) && (ncat > 6) && (highest_other_cat <= 6) && (abs(d) < 70) )
3728 {
3729 r = "no: from highway to highway (no other highway possibilities)";
3730 dbg(0, "STRAI:011.07:4 abs(d)=%d cat=%d ncat=%d highest_other_cat=%d\n", abs(d), cat, ncat, highest_other_cat);
3731 }
3732 else
3733 {
3734
3735 if ((ncat == 6) && (highest_other_cat == 6) && (abs(d) < 50) && (abs(new_angle_closest_to_cur - original_d) < 65))
3736 {
3737 ret = 1;
3738 r = "yes: we are driving onto a ramp and there a other ramps near (<50 degrees) to it";
3739 dbg(0, "STRAI:011.07:3.001 ncat=%d highest_other_cat=%d d=%d (new_angle_closest_to_cur=%d - original_d=%d)\n", ncat, highest_other_cat, d, new_angle_closest_to_cur, original_d);
3740 }
3741
3742
3743 if ((d == 0) && (new_angle_abs_min_allowed >= 25))
3744 {
3745 r = "no: driving almost straight, and other ways not very close to straight";
3746 dbg(0, "STRAI:011.07:3 abs(d)=%d new_angle_abs_min_allowed=%d\n", abs(d), new_angle_abs_min_allowed);
3747 }
3748 else
3749 {
3750
3751 if ( (d == 0) && (abs(new_angle_closest_to_cur - original_d) < 16) )
3752 {
3753 ret = 1;
3754 r = "yes: we are going straight and some other way is very close to it";
3755 dbg(0, "STRAI:011.07:0 abs(d)=%d new_angle_abs_min_allowed=%d\n", abs(d), new_angle_abs_min_allowed);
3756 }
3757 else if ( (ncat_2 <= highest_other_cat) && (d == 0) && (abs(new_angle_closest_to_cur - original_d) < 30) )
3758 {
3759 ret = 1;
3760 r = "yes: we are going straight and some other way is very close to it (same or higher cat)";
3761 dbg(0, "STRAI:011.07:7 abs(d)=%d new_angle_abs_min_allowed=%d\n", abs(d), new_angle_abs_min_allowed);
3762 }
3763 else if ((abs(d) > 0) && (new_angle_abs_min_allowed < abs(d)))
3764 {
3765 ret = 1;
3766 r = "yes: some other way is going more straight";
3767 dbg(0, "STRAI:011.07:0 abs(d)=%d new_angle_abs_min_allowed=%d\n", abs(d), new_angle_abs_min_allowed);
3768
3769
3770 if (abs(d) < 10)
3771 {
3772
3773 // ----------########### more way left/right of way ? ###########----------
3774 int more_ways_to_left_ = 0;
3775 int more_ways_to_right_ = 0;
3776 w = new->way.next;
3777 while (w)
3778 {
3779 if (is_way_allowed(nav, w, 1))
3780 {
3781 if ( (is_maybe_same_item(&(new->way), w, 0) == 0) && (is_maybe_same_item(&(old->way), w, 1) == 0) )
3782 {
3783 dbg(0, "STRAI:108.02a delta=%d\n", angle_delta(old->angle_end, w->angle2));
3784
3785 if (is_way_allowed(nav, w, 1))
3786 {
3787 if (angle_delta(old->angle_end, w->angle2) < d) // other ways are going more to the left?
3788 {
3789 more_ways_to_left_++;
3790 }
3791 else if (angle_delta(old->angle_end, w->angle2) > d) // other ways are going more to the right?
3792 {
3793 more_ways_to_right_++;
3794 }
3795 }
3796 }
3797 }
3798 w = w->next;
3799 }
3800
3801 dbg(0, "STRAI:108.02 %d %d\n", more_ways_to_left_, more_ways_to_right_);
3802
3803
3804 if ((d < 0) && (more_ways_to_left_ == 0)) // && (more_ways_to_right_ > 0))
3805 {
3806
3807 dbg(0, "STRAI:108.03:left\n");
3808 *delta_real = 0;
3809 d = -8;
3810 no_correction = 1;
3811 }
3812 else if ((d > 0) && (more_ways_to_left_ > 0)) // && (more_ways_to_right_ == 0))
3813 {
3814 dbg(0, "STRAI:108.04:right\n");
3815 *delta_real = 0;
3816 d = 8;
3817 no_correction = 1;
3818 }
3819
3820
3821
3822 // ----------########### more way left/right of way ? ###########----------
3823
3824 }
3825
3826
3827 }
3828 else if ((abs(d) > 0) && (new_angle_abs_min_allowed < 39) && (is_same_street))
3829 {
3830 if ( (cat == ncat) && (ncat_2 > highest_other_cat) )
3831 {
3832 r = "no: we need to make a turn, but other possibilites are much lower cat roads";
3833 dbg(0, "STRAI:011.07:5iss cat=%d ncat=%d cat_2=%d ncat_2=%d highest_other_cat=%d\n", cat, ncat, cat_2, ncat_2, highest_other_cat);
3834 }
3835 else
3836 {
3837 ret = 1;
3838 r = "yes: we need to make a turn";
3839 dbg(0, "STRAI:011.07:1iss abs(d)=%d new_angle_abs_min_allowed=%d\n", abs(d), new_angle_abs_min_allowed);
3840 }
3841 }
3842 else if ((abs(d) > 0) && (new_angle_abs_min_allowed < 52) && (!is_same_street))
3843 {
3844 if ( (cat == ncat) && (ncat_2 > highest_other_cat) )
3845 {
3846 r = "no: we need to make a turn, but other possibilites are much lower cat roads";
3847 dbg(0, "STRAI:011.07:5nss cat=%d ncat=%d cat_2=%d ncat_2=%d highest_other_cat=%d\n", cat, ncat, cat_2, ncat_2, highest_other_cat);
3848 }
3849 else
3850 {
3851 ret = 1;
3852 r = "yes: we need to make a turn";
3853 dbg(0, "STRAI:011.07:1nss abs(d)=%d new_angle_abs_min_allowed=%d\n", abs(d), new_angle_abs_min_allowed);
3854 }
3855 }
3856 else
3857 {
3858 dbg(0, "STRAI:011.07:6 abs(d)=%d new_angle_abs_min_allowed=%d cat=%d ncat=%d cat_2=%d ncat_2=%d highest_other_cat=%d new_angle_closest_to_cur=%d original_d=%d\n", abs(d), new_angle_abs_min_allowed, cat, ncat, cat_2, ncat_2, highest_other_cat, new_angle_closest_to_cur, original_d);
3859 }
3860 }
3861 }
3862 }
3863 }
3864
3865 dbg(0, "STRAI:011.07 is_unambigous[eindeutig]=%d ret=%d r=%s\n", is_unambigous, ret, r);
3866
3867 #ifdef DEBUG
3868 // 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);
3869 #endif
3870 }
3871
3872
3873
3874
3875
3876
3877 dbg(0, "STRAI:007.00aa:d=%d ******************++++++++++++\n", d);
3878
3879
3880
3881
3882
3883 // correct "delta" (turn angle) here !! ---------------------------
3884 // correct "delta" (turn angle) here !! ---------------------------
3885
3886 if (no_correction == 0)
3887 {
3888 *delta_real = d;
3889 }
3890
3891 if ((ret == 1) && (have_more_than_one_way_to_turn == 1) && (no_correction == 0))
3892 {
3893 w = new->way.next;
3894 //int d2 = angle_delta(old->angle_end, new->way.angle2);
3895 int d2 = d;
3896 //if (d == 0)
3897 //{
3898 // d2 = 0;
3899 //}
3900
3901 int correct_direction = 1;
3902
3903 dbg(0, "STRAI:007.01:d=%d d2=%d\n", d, d2);
3904
3905 if (d2 < 0) // left
3906 {
3907 while (w)
3908 {
3909 if (is_way_allowed(nav, w, 1))
3910 {
3911 if ( (is_maybe_same_item(&(new->way), w, 0) == 0) && (is_maybe_same_item(&(old->way), w, 1) == 0) )
3912 {
3913 if (angle_delta(old->angle_end, w->angle2) > d2) // other ways are going more to the right?
3914 {
3915 correct_direction = 0;
3916 break;
3917 }
3918 }
3919 }
3920 w = w->next;
3921 }
3922
3923 if (correct_direction == 1)
3924 {
3925 #ifdef NAVIT_ROUTING_DEBUG_PRINT
3926 dbg(0, "MAV:001:correct to right\n");
3927 #endif
3928 d = 8; // set to "slight right"
3929 }
3930 }
3931 else if (d2 > 0) // right
3932 {
3933 while (w)
3934 {
3935 if (is_way_allowed(nav, w, 1))
3936 {
3937 if ( (is_maybe_same_item(&(new->way), w, 0) == 0) && (is_maybe_same_item(&(old->way), w, 1) == 0) )
3938 {
3939 if (angle_delta(old->angle_end, w->angle2) < d2) // other ways are going more to the left?
3940 {
3941 correct_direction = 0;
3942 break;
3943 }
3944 }
3945 }
3946 w = w->next;
3947 }
3948
3949 if (correct_direction == 1)
3950 {
3951 #ifdef NAVIT_ROUTING_DEBUG_PRINT
3952 dbg(0, "MAV:002:correct to left\n");
3953 #endif
3954 d = -8; // set to "slight left"
3955 }
3956 }
3957 else // (d2 == 0) // straight
3958 {
3959
3960 dbg(0, "STRAI:008.01:%d (%d < %d) new_angle_abs_min_allowed=%d\n", d2, new_angle_abs_min, ROAD_ANGLE_DISTANCE_FOR_STRAIGHT, new_angle_abs_min_allowed);
3961
3962 int more_ways_to_left = 0;
3963 int more_ways_to_right = 0;
3964
3965 if (new_angle_abs_min_allowed < ROAD_ANGLE_DISTANCE_FOR_STRAIGHT) // if other angles are far different from straight, than let it still be straight! otherwise correct direction
3966 {
3967 dbg(0, "STRAI:008.02\n");
3968
3969
3970 if ((abs(new_angle_closest_to_cur - original_d) <= 25) || (abs(original_d) >= 10))
3971 // if (1 == 1)
3972 {
3973
3974 while (w)
3975 {
3976 if (is_way_allowed(nav, w, 1))
3977 {
3978 if ( (is_maybe_same_item(&(new->way), w, 0) == 0) && (is_maybe_same_item(&(old->way), w, 1) == 0) )
3979 {
3980 dbg(0, "STRAI:008.02a delta=%d\n", angle_delta(old->angle_end, w->angle2));
3981
3982 if (is_way_allowed(nav, w, 1))
3983 {
3984 if (angle_delta(old->angle_end, w->angle2) < d2) // other ways are going more to the left?
3985 {
3986 more_ways_to_left++;
3987 }
3988 else if (angle_delta(old->angle_end, w->angle2) > d2) // other ways are going more to the right?
3989 {
3990 more_ways_to_right++;
3991 }
3992 }
3993 }
3994 }
3995 w = w->next;
3996 }
3997
3998 dbg(0, "STRAI:008.02 %d %d\n", more_ways_to_left, more_ways_to_right);
3999
4000 if ((more_ways_to_left == 0) && (more_ways_to_right > 0))
4001 {
4002
4003 dbg(0, "STRAI:008.03:left\n");
4004
4005 #ifdef NAVIT_ROUTING_DEBUG_PRINT
4006 dbg(0, "MAV:003:correct to left\n");
4007 #endif
4008 d = -8;
4009 }
4010 else if ((more_ways_to_left > 0) && (more_ways_to_right == 0))
4011 {
4012 dbg(0, "STRAI:008.04:right\n");
4013
4014 #ifdef NAVIT_ROUTING_DEBUG_PRINT
4015 dbg(0, "MAV:003:correct to right\n");
4016 #endif
4017 d = 8;
4018 }
4019
4020 }
4021 else
4022 {
4023 dbg(0, "STRAI:008.02f street almost straight and nearest other street at least 25 away: closest=%d orig_d=%d\n", new_angle_closest_to_cur, original_d);
4024 }
4025
4026 }
4027
4028 }
4029
4030 }
4031
4032 // correct "delta" (turn angle) here !! ---------------------------
4033 // correct "delta" (turn angle) here !! ---------------------------
4034
4035
4036
4037
4038
4039
4040
4041
4042 dbg(0, "STRAI:099:ret=%d r=%s d=%d d_real=%d\n", ret, r, d, *delta_real);
4043 dbg(0, "STRAI:099:======================================\n");
4044
4045 *delta = d;
4046 if (reason)
4047 {
4048 *reason = r;
4049 }
4050
4051 return ret;
4052 }
4053
4054 static struct navigation_command *command_new(struct navigation *this_, struct navigation_itm *itm, int delta, int delta_real)
4055 {
4056 struct navigation_command *ret=g_new0(struct navigation_command, 1);
4057
4058 //dbg(1, "enter this_=%p itm=%p delta=%d\n", this_, itm, delta);
4059 ret->delta = delta;
4060 ret->delta_real = delta_real;
4061 ret->itm = itm;
4062
4063 if (itm && itm->prev && itm->way.next && itm->prev->way.next && !(itm->way.flags & NAVIT_AF_ROUNDABOUT) && (itm->prev->way.flags & NAVIT_AF_ROUNDABOUT))
4064 {
4065 int len = 0;
4066 int angle = 0;
4067 int entry_angle;
4068 struct navigation_itm *itm2 = itm->prev;
4069 int exit_angle = angle_median(itm->prev->angle_end, itm->way.next->angle2);
4070 //dbg(1, "exit %d median from %d,%d\n", exit_angle, itm->prev->angle_end, itm->way.next->angle2);
4071
4072 while (itm2 && (itm2->way.flags & NAVIT_AF_ROUNDABOUT))
4073 {
4074 len += itm2->length;
4075 angle = itm2->angle_end;
4076 itm2 = itm2->prev;
4077 }
4078
4079 if (itm2 && itm2->next && itm2->next->way.next)
4080 {
4081 itm2 = itm2->next;
4082 entry_angle = angle_median(angle_opposite(itm2->way.angle2), itm2->way.next->angle2);
4083 // dbg(1, "entry %d median from %d(%d),%d\n", entry_angle, angle_opposite(itm2->way.angle2), itm2->way.angle2, itm2->way.next->angle2);
4084 }
4085 else
4086 {
4087 entry_angle = angle_opposite(angle);
4088 }
4089 //dbg(0, "entry %d exit %d\n", entry_angle, exit_angle);
4090 ret->roundabout_delta = angle_delta(entry_angle, exit_angle);
4091 ret->length = len + roundabout_extra_length;
4092 }
4093
4094 if (this_->cmd_last)
4095 {
4096 this_->cmd_last->next = ret;
4097 ret->prev = this_->cmd_last;
4098 }
4099
4100 this_->cmd_last = ret;
4101
4102 if (!this_->cmd_first)
4103 {
4104 this_->cmd_first = ret;
4105 }
4106
4107 return ret;
4108 }
4109
4110
4111
4112 // ----------- main place where maneuvers generated (run only once) ------------
4113 // ----------- main place where maneuvers generated (run only once) ------------
4114 // ----------- main place where maneuvers generated (run only once) ------------
4115 static void make_maneuvers(struct navigation *this_, struct route *route)
4116 {
4117 __F_START__
4118
4119 struct navigation_itm *itm, *last = NULL, *last_itm = NULL;
4120 int delta;
4121 int delta_real;
4122 itm = this_->first;
4123 this_->cmd_last = NULL;
4124 this_->cmd_first = NULL;
4125 while (itm)
4126 {
4127 if (last)
4128 {
4129 if (maneuver_required2(this_, last_itm, itm, &delta, &delta_real, NULL))
4130 {
4131 //dbg(0, "maneuver_required2 = true\n");
4132 command_new(this_, itm, delta, delta_real);
4133 }
4134 }
4135 else
4136 {
4137 last = itm;
4138 }
4139 last_itm = itm;
4140 itm = itm->next;
4141 }
4142 command_new(this_, last_itm, 0, 0);
4143
4144 __F_END__
4145 }
4146 // ----------- main place where maneuvers generated ------------
4147 // ----------- main place where maneuvers generated ------------
4148 // ----------- main place where maneuvers generated ------------
4149
4150
4151
4152 static int contains_suffix(char *name, char *suffix)
4153 {
4154 if (!suffix)
4155 {
4156 return 0;
4157 }
4158
4159 if (strlen(name) < strlen(suffix))
4160 {
4161 return 0;
4162 }
4163
4164 return !g_strcasecmp(name + strlen(name) - strlen(suffix), suffix);
4165 }
4166
4167 static char *
4168 replace_suffix(char *name, char *search, char *replace)
4169 {
4170 int len = strlen(name) - strlen(search);
4171 char *ret = g_malloc(len + strlen(replace) + 1);
4172
4173 strncpy(ret, name, len);
4174 strcpy(ret + len, replace);
4175
4176 if (isupper(name[len]))
4177 {
4178 ret[len] = toupper(ret[len]);
4179 }
4180
4181 return ret;
4182 }
4183
4184 static char *
4185 navigation_item_destination(struct navigation *nav, struct navigation_itm *itm, struct navigation_itm *next, char *prefix)
4186 {
4187 char *ret = NULL, *name1, *sep, *name2;
4188 char *n1, *n2;
4189 int i, sex;
4190 int vocabulary1 = 65535;
4191 int vocabulary2 = 65535;
4192 struct attr attr;
4193
4194 if (!prefix)
4195 {
4196 prefix = "";
4197 }
4198
4199 if (nav->speech && speech_get_attr(nav->speech, attr_vocabulary_name, &attr, NULL))
4200 {
4201 vocabulary1 = attr.u.num;
4202 }
4203
4204 if (nav->speech && speech_get_attr(nav->speech, attr_vocabulary_name_systematic, &attr, NULL))
4205 {
4206 vocabulary2 = attr.u.num;
4207 }
4208
4209 n1 = itm->way.name1;
4210 n2 = itm->way.name2;
4211
4212 if (!vocabulary1)
4213 n1 = NULL;
4214
4215 if (!vocabulary2)
4216 n2 = NULL;
4217
4218 if (!n1 && !n2 && (item_is_ramp(itm->way.item)) && vocabulary2)
4219 {
4220 //dbg(1,">> Next is ramp %lx current is %lx \n", itm->way.item.type, next->way.item.type);
4221
4222
4223 // disabled for now !!!!!!!! -------------------------
4224 #if 0
4225 if (next->way.item.type == type_ramp)
4226 {
4227 return NULL;
4228 }
4229 #endif
4230 // disabled for now !!!!!!!! -------------------------
4231
4232
4233 //else
4234 //{
4235 // return g_strdup_printf("%s%s",prefix,_("into the ramp"));
4236 //}
4237
4238 #if 0
4239 if (itm->way.item.type == type_highway_city || itm->way.item.type == type_highway_land)
4240 {
4241 #ifdef HAVE_API_ANDROID
4242 #ifdef NAVIT_SAY_DEBUG_PRINT
4243 android_send_generic_text(1,"+*#O:exit\n");
4244 gchar* xy=g_strdup_printf("+*#1:%s\n", prefix);
4245 android_send_generic_text(1,xy);
4246 g_free(xy);
4247 #endif
4248 #endif
4249 return g_strdup_printf("%s%s", prefix, _("exit")); /* %FIXME Can this even be reached? and "exit" is the wrong text anyway ! */
4250 }
4251 else
4252 #endif
4253 {
4254 if (itm->way.street_dest_text)
4255 {
4256 #ifdef HAVE_API_ANDROID
4257 #ifdef NAVIT_SAY_DEBUG_PRINT
4258 gchar* xy=g_strdup_printf("+*#0:%s\n", itm->way.street_dest_text);
4259 android_send_generic_text(1,xy);
4260 g_free(xy);
4261 gchar* xy=g_strdup_printf("+*#1:%s\n", prefix);
4262 android_send_generic_text(1,xy);
4263 g_free(xy);
4264 #endif
4265 #endif
4266
4267 // say the name on the exit sign/destinaion sign
4268 return g_strdup_printf("%s%s", prefix, itm->way.street_dest_text);
4269 }
4270 else
4271 {
4272 #ifdef HAVE_API_ANDROID
4273 #ifdef NAVIT_SAY_DEBUG_PRINT
4274 android_send_generic_text(1,"+*#O:into the ramp\n");
4275 gchar* xy=g_strdup_printf("+*#1:%s\n", prefix);
4276 android_send_generic_text(1,xy);
4277 g_free(xy);
4278 #endif
4279 #endif
4280
4281 return g_strdup_printf("%s%s", prefix, _("into the ramp"));
4282 }
4283 }
4284
4285 }
4286
4287 if (!n1 && !n2 && !itm->way.street_dest_text)
4288 {
4289 return NULL;
4290 }
4291
4292 if (itm->way.street_dest_text)
4293 {
4294 #ifdef HAVE_API_ANDROID
4295 #ifdef NAVIT_SAY_DEBUG_PRINT
4296 gchar* xy=g_strdup_printf("+*#0:%s\n", itm->way.street_dest_text);
4297 android_send_generic_text(1,xy);
4298 g_free(xy);
4299 gchar* xy=g_strdup_printf("+*#1:%s\n", prefix);
4300 android_send_generic_text(1,xy);
4301 g_free(xy);
4302 #endif
4303 #endif
4304 // say the name on the exit sign/destinaion sign
4305 return g_strdup_printf("%s%s", prefix, itm->way.street_dest_text);
4306 }
4307 else if (n1)
4308 {
4309 sex = -1;
4310 name1 = NULL;
4311 for (i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); i++)
4312 {
4313 if (contains_suffix(n1, suffixes[i].fullname))
4314 {
4315 sex = suffixes[i].sex;
4316 name1 = g_strdup(n1);
4317 break;
4318 }
4319 if (contains_suffix(n1, suffixes[i].abbrev))
4320 {
4321 sex = suffixes[i].sex;
4322
4323 // TODO: replacing strings here maybe not so good?!?
4324 name1 = replace_suffix(n1, suffixes[i].abbrev, suffixes[i].fullname);
4325 break;
4326 }
4327 }
4328
4329 if (n2)
4330 {
4331 name2 = n2;
4332 sep = " ";
4333 }
4334 else
4335 {
4336 name2 = "";
4337 sep = "";
4338 }
4339
4340 gchar* xy;
4341 switch (sex)
4342 {
4343 case -1:
4344 #ifdef HAVE_API_ANDROID
4345 #ifdef NAVIT_SAY_DEBUG_PRINT
4346 android_send_generic_text(1,"+*#O:%sinto the street %s%s%s\n");
4347 xy=g_strdup_printf("+*#1:%s\n", prefix);
4348 android_send_generic_text(1,xy);
4349 g_free(xy);
4350 xy=g_strdup_printf("+*#1:%s\n", n1);
4351 android_send_generic_text(1,xy);
4352 g_free(xy);
4353 xy=g_strdup_printf("+*#1:%s\n", sep);
4354 android_send_generic_text(1,xy);
4355 g_free(xy);
4356 xy=g_strdup_printf("+*#1:%s\n", name2);
4357 android_send_generic_text(1,xy);
4358 g_free(xy);
4359 #endif
4360 #endif
4361 // TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name
4362 ret = g_strdup_printf(_("%sinto the street %s%s%s"), prefix, n1, sep, name2);
4363 break;
4364 case 1:
4365 #ifdef HAVE_API_ANDROID
4366 #ifdef NAVIT_SAY_DEBUG_PRINT
4367 android_send_generic_text(1,"+*#O:%sinto the %s%s%s|male form\n");
4368 xy=g_strdup_printf("+*#1:%s\n", prefix);
4369 android_send_generic_text(1,xy);
4370 g_free(xy);
4371 xy=g_strdup_printf("+*#1:%s\n", name1);
4372 android_send_generic_text(1,xy);
4373 g_free(xy);
4374 xy=g_strdup_printf("+*#1:%s\n", sep);
4375 android_send_generic_text(1,xy);
4376 g_free(xy);
4377 xy=g_strdup_printf("+*#1:%s\n", name2);
4378 android_send_generic_text(1,xy);
4379 g_free(xy);
4380 #endif
4381 #endif
4382 // 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
4383 ret = g_strdup_printf(_("%sinto the %s%s%s|male form"), prefix, name1, sep, name2);
4384 break;
4385 case 2:
4386 #ifdef HAVE_API_ANDROID
4387 #ifdef NAVIT_SAY_DEBUG_PRINT
4388 android_send_generic_text(1,"+*#O:%sinto the %s%s%s|female form\n");
4389 xy=g_strdup_printf("+*#1:%s\n", prefix);
4390 android_send_generic_text(1,xy);
4391 g_free(xy);
4392 xy=g_strdup_printf("+*#1:%s\n", name1);
4393 android_send_generic_text(1,xy);
4394 g_free(xy);
4395 xy=g_strdup_printf("+*#1:%s\n", sep);
4396 android_send_generic_text(1,xy);
4397 g_free(xy);
4398 xy=g_strdup_printf("+*#1:%s\n", name2);
4399 android_send_generic_text(1,xy);
4400 g_free(xy);
4401 #endif
4402 #endif
4403 // 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
4404 ret = g_strdup_printf(_("%sinto the %s%s%s|female form"), prefix, name1, sep, name2);
4405 break;
4406 case 3:
4407 #ifdef HAVE_API_ANDROID
4408 #ifdef NAVIT_SAY_DEBUG_PRINT
4409 android_send_generic_text(1,"+*#O:%sinto the %s%s%s|neutral form\n");
4410 xy=g_strdup_printf("+*#1:%s\n", prefix);
4411 android_send_generic_text(1,xy);
4412 g_free(xy);
4413 xy=g_strdup_printf("+*#1:%s\n", name1);
4414 android_send_generic_text(1,xy);
4415 g_free(xy);
4416 xy=g_strdup_printf("+*#1:%s\n", sep);
4417 android_send_generic_text(1,xy);
4418 g_free(xy);
4419 xy=g_strdup_printf("+*#1:%s\n", name2);
4420 android_send_generic_text(1,xy);
4421 g_free(xy);
4422 #endif
4423 #endif
4424 // 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
4425 ret = g_strdup_printf(_("%sinto the %s%s%s|neutral form"), prefix, name1, sep, name2);
4426 break;
4427 }
4428 g_free(name1);
4429
4430 }
4431 else
4432 {
4433 #ifdef HAVE_API_ANDROID
4434 #ifdef NAVIT_SAY_DEBUG_PRINT
4435 android_send_generic_text(1,"+*#O:sinto the %s\n");
4436 gchar* xy=g_strdup_printf("+*#1:%s\n", prefix);
4437 android_send_generic_text(1,xy);
4438 g_free(xy);
4439 xy=g_strdup_printf("+*#1:%s\n", n2);
4440 android_send_generic_text(1,xy);
4441 g_free(xy);
4442 #endif
4443 #endif
4444 // TRANSLATORS: gives the name of the next road to turn into (into the E17)
4445 ret = g_strdup_printf(_("%sinto the %s"), prefix, n2);
4446 }
4447
4448 name1 = ret;
4449
4450 while (name1 && *name1)
4451 {
4452 switch (*name1)
4453 {
4454 case '|':
4455 *name1 = '\0';
4456 break;
4457 case '/':
4458 *name1++ = ' ';
4459 break;
4460 default:
4461 name1++;
4462 }
4463 }
4464
4465 return ret;
4466 }
4467
4468
4469
4470
4471 #define DONT_KNOW_LEVEL -997
4472
4473
4474 static char *
4475 show_maneuver_bicycle(struct navigation *nav, struct navigation_itm *itm, struct navigation_command *cmd, enum attr_type type, int connect, int want_this_level)
4476 {
4477 __F_START__
4478
4479 // TRANSLATORS: right, as in 'Turn right'
4480 char *dir = _("right");
4481 char *strength = "";
4482 int distance = itm->dest_length - cmd->itm->dest_length;
4483 char *d, *ret = NULL;
4484 int delta = cmd->delta;
4485 int delta_real = cmd->delta_real;
4486 int level;
4487 int level_now = 99;
4488 int level3;
4489 int strength_needed;
4490 int skip_roads;
4491 int count_roundabout;
4492 struct navigation_itm *cur;
4493 struct navigation_way *w;
4494 int against_oneway = 0;
4495 int keep_dir = 0;
4496 int old_dir = 0;
4497
4498 if (want_this_level == DONT_KNOW_LEVEL)
4499 {
4500 level3 = 1;
4501 }
4502 else
4503 {
4504 level3 = want_this_level;
4505 }
4506
4507
4508 int cur_vehicle_speed = 0;
4509 if ((global_navit) && (global_navit->vehicle))
4510 {
4511 cur_vehicle_speed = global_navit->vehicle->speed; // in km/h
4512 }
4513
4514 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
4515 {
4516 //dbg(0, "itm->way.flags=%x\n", itm->way.flags);
4517 //dbg(0, "itm->next->way.flags=%x\n", itm->next->way.flags);
4518 //dbg(0, "itm->way.dir=%d itm->next->way.dir=%d\n", itm->way.dir, itm->next->way.dir);
4519
4520 //dbg(0, "2 itm->way.flags=%x\n", cmd->itm->way.flags);
4521 //dbg(0, "2 itm->next->way.flags=%x\n", cmd->itm->next->way.flags);
4522 //dbg(0, "2 itm->way.dir=%d itm->next->way.dir=%d\n", cmd->itm->way.dir, cmd->itm->next->way.dir);
4523
4524 int flags_old = navigation_item_get_flags(&itm->way);
4525 int flags_new = 0;
4526 if (itm->next)
4527 {
4528 flags_new = navigation_item_get_flags(&itm->next->way);
4529 }
4530 //dbg(0, "(2211)old flags=%x new flags=%x\n", flags_old, flags_new);
4531
4532 // long long wayid_old = navigation_item_get_wayid(&(itm->way));
4533 // long long wayid_new = navigation_item_get_wayid(&(itm->next->way));
4534 // dbg(0, "WID old_way_id=%lld new_way_id=%lld\n", wayid_old, wayid_new);
4535
4536
4537 if ( (itm->way.dir == 1) && ((itm->next->way.dir == -1) && (itm->next->way.flags & NAVIT_AF_ONEWAY_BICYCLE_NO)) )
4538 {
4539 against_oneway = 1;
4540 //dbg(0, "SPEAK: (1)going against oneway street!\n");
4541 }
4542 else if ( ((itm->way.dir == -1) && (!(itm->way.flags & NAVIT_AF_ONEWAY_BICYCLE_NO))) && ((itm->next->way.dir == -1) && (itm->next->way.flags & NAVIT_AF_ONEWAY_BICYCLE_NO)) )
4543 {
4544 against_oneway = 1;
4545 //dbg(0, "SPEAK: (2)going against oneway street!\n");
4546 }
4547 }
4548
4549 //dbg(0, "d=%d d3=%d\n", distance, (distance - cmd->length));
4550 level_now = navigation_get_announce_level(nav, itm->way.item.type, distance - cmd->length, 0);
4551 //dbg(0, "level_now=%d\n", level_now);
4552
4553 w = itm->next->way.next;
4554 strength_needed = 0;
4555
4556 if (angle_delta(itm->next->way.angle2, itm->angle_end) < 0) // left
4557 {
4558 while (w)
4559 {
4560 if (angle_delta(w->angle2, itm->angle_end) < 0) // other ways are going left
4561 {
4562 strength_needed = 1;
4563 break;
4564 }
4565 w = w->next;
4566 }
4567 }
4568 else // right
4569 {
4570 while (w)
4571 {
4572 if (angle_delta(w->angle2, itm->angle_end) > 0) // other ways are going right
4573 {
4574 strength_needed = 1;
4575 break;
4576 }
4577 w = w->next;
4578 }
4579 }
4580
4581
4582 if ((strength_needed == 0) && (delta < 9)) // for corrected turn (delta will be 8), use strength ("slight")
4583 {
4584 strength_needed = 1;
4585 }
4586
4587 //dbg(0, "cmd->delta=%d\n", delta);
4588
4589 if (delta < 0)
4590 {
4591 // TRANSLATORS: left, as in 'Turn left'
4592 dir = _("left");
4593 delta = -delta;
4594
4595 old_dir = -1; // left
4596 }
4597 else if (delta > 0)
4598 {
4599
4600 old_dir = 1; // right
4601
4602 // dir = right
4603 }
4604 else // delta == 0 // go straight
4605 {
4606 dir = _("straight");
4607 strength_needed = 0;
4608 }
4609
4610
4611 keep_dir = 0;
4612
4613 if (strength_needed)
4614 {
4615 if (delta < 45)
4616 {
4617 // TRANSLATORS: Don't forget the ending space
4618 // TRANSLATORS: EXAMPLE: turn slight right
4619 strength = _("slighty ");
4620 // TRANSLATORS: Don't forget the ending space
4621 // TRANSLATORS: EXAMPLE: turn slight right
4622 strength = _("slight ");
4623
4624 if (delta_real == 0) // keep left/right
4625 {
4626 if (old_dir == -1)
4627 {
4628 keep_dir = -1;
4629 }
4630 else
4631 {
4632 keep_dir = 1;
4633 }
4634 }
4635 }
4636 else if (delta < 105)
4637 {
4638 strength = "";
4639 }
4640 else if (delta < 165)
4641 {
4642 // TRANSLATORS: Don't forget the ending space
4643 // TRANSLATORS: EXAMPLE: turn hard right
4644 strength = _("hard ");
4645 }
4646 else if (delta < 180)
4647 {
4648 // TRANSLATORS: Don't forget the ending space
4649 // TRANSLATORS: EXAMPLE: turn really hard right
4650 strength = _("really hard ");
4651 }
4652 else
4653 {
4654 // TRANSLATORS: Don't forget the ending space
4655 strength = "";
4656 }
4657 }
4658
4659
4660 if (type != attr_navigation_long_exact)
4661 {
4662 //dbg(0, "round distance d=%d dr=%d\n", distance, round_distance(distance));
4663 distance = round_distance(distance);
4664 }
4665
4666
4667
4668
4669 if (type == attr_navigation_speech)
4670 {
4671 dbg(0, "NAV_TURNAROUND:003 ta=%d talimit=%d\n", nav->turn_around, nav->turn_around_limit);
4672
4673 if (nav->turn_around && nav->turn_around == nav->turn_around_limit)
4674 {
4675 dbg(0, "NAV_TURNAROUND:004\n");
4676
4677 return2 g_strdup(_("When possible, please turn around"));
4678 }
4679
4680 if (!connect)
4681 {
4682 if (want_this_level == DONT_KNOW_LEVEL)
4683 {
4684 level3 = navigation_get_announce_level_cmd(nav, itm, cmd, distance - cmd->length, ((float)cur_vehicle_speed / 3.6f) );
4685 }
4686 else
4687 {
4688 level3 = want_this_level;
4689 }
4690 }
4691
4692 if (want_this_level == DONT_KNOW_LEVEL)
4693 {
4694 level_now = navigation_get_announce_level(nav, itm->way.item.type, distance - cmd->length, ((float)cur_vehicle_speed / 3.6f) );
4695 }
4696 else
4697 {
4698 level_now = want_this_level;
4699 }
4700 }
4701
4702
4703
4704 switch (level3)
4705 {
4706 case 3:
4707 if (distance > 500)
4708 {
4709 d = get_distance(nav, distance, type, 1);
4710 ret = g_strdup_printf(_("Follow the road for the next %s"), d);
4711 g_free(d);
4712 }
4713 else
4714 {
4715 ret = g_strdup("");
4716 }
4717 return2 ret;
4718 // break;
4719 case 2:
4720 d = g_strdup(_("soon"));
4721 break;
4722 case 1:
4723 d = get_distance(nav, distance, attr_navigation_short, 0);
4724 break;
4725 case 0:
4726 // d = g_strdup(_("now"));
4727 d = g_strdup("");
4728 break;
4729 }
4730
4731
4732 // are there more commands left?
4733 if (cmd->itm->next)
4734 {
4735 int tellstreetname = 0;
4736 char *destination = NULL;
4737
4738 if (type == attr_navigation_speech)
4739 {
4740 if (level3 == 1)
4741 {
4742 tellstreetname = 1; // Ok so we tell the name of the street
4743 }
4744 else // if (level3 == 0)
4745 {
4746 tellstreetname = 0;
4747 }
4748 }
4749 else
4750 {
4751 tellstreetname = 1;
4752 }
4753
4754 if (global_speak_streetnames == 0)
4755 {
4756 // never speak streetnames (user config option)
4757 tellstreetname = 0;
4758 }
4759
4760 if (nav->tell_street_name && tellstreetname)
4761 {
4762 destination = navigation_item_destination(nav, cmd->itm, itm, " ");
4763 }
4764
4765
4766 if (connect == 0)
4767 {
4768 //dbg(0, "level3=%5$d str=%1$s%2$s %3$s%4$s\n", strength, dir, d, destination ? destination : "", level3);
4769
4770 if (level3 == 0)
4771 {
4772 if (against_oneway == 1)
4773 {
4774 #if 1
4775 if (delta < 10)
4776 {
4777 ret = g_strdup_printf("%s", _("oncoming traffic!")); // just say "attention oneway street!"
4778 }
4779 else
4780 {
4781 ret = g_strdup_printf("%s, %s", dir, _("oncoming traffic!")); // just say "left" or "right" at the turn + "attention oneway street!"
4782 }
4783 #endif
4784
4785 }
4786 else
4787 {
4788 #if 1
4789 if (delta >= 10)
4790 {
4791 ret = g_strdup(dir); // just say "left" or "right" at the turn
4792 }
4793 else
4794 {
4795 ret = g_strdup("");
4796 }
4797 #endif
4798
4799 #if 0
4800 if (delta == 0)
4801 {
4802 ret = g_strdup(dir); // just say "left" or "right" or "straight" at the turn
4803 }
4804 else
4805 {
4806 if (keep_dir != 0)
4807 {
4808 if (keep_dir == -1)
4809 {
4810 // TRANSLATORS: The argument is the distance. Example: 'keep left in 100 meters'
4811 ret = g_strdup_printf(_("keep left %s"), "");
4812 }
4813 else
4814 {
4815 // TRANSLATORS: The argument is the distance. Example: 'keep right in 100 meters'
4816 ret = g_strdup_printf(_("keep right %s"), "");
4817 }
4818 }
4819 else
4820 {
4821 if (delta >= 10)
4822 {
4823 ret = g_strdup(dir); // just say "left" or "right" at the turn
4824 }
4825 else
4826 {
4827 ret = g_strdup("");
4828 }
4829 }
4830 }
4831 #endif
4832
4833 }
4834 }
4835 else // if (level3 == 1)
4836 {
4837 if ((against_oneway == 1) && (delta < 10))
4838 {
4839 ret = g_strdup(""); // probably just going against a oneway street, but travelling straight on. dont say anything now
4840 }
4841 else
4842 {
4843 if (delta >= 10)
4844 {
4845 // 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'
4846 ret = g_strdup_printf_4_str(_("Turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination : "");
4847 }
4848 else
4849 {
4850 ret = g_strdup("");
4851 }
4852 }
4853 }
4854
4855 }
4856 else // (connect == 1)
4857 {
4858 if (level3 == 0)
4859 {
4860 if (against_oneway == 1)
4861 {
4862 if (delta < 10)
4863 {
4864 ret = g_strdup_printf("%s %s", _("then"), _("oncoming traffic!"));
4865 }
4866 else
4867 {
4868 ret = g_strdup_printf("%s %s %s", _("then"), dir, _("oncoming traffic!"));
4869 }
4870 }
4871 else
4872 {
4873 if (delta >= 10)
4874 {
4875 ret = g_strdup_printf("%s %s", _("then"), dir);
4876 }
4877 else
4878 {
4879 ret = g_strdup("");
4880 }
4881 }
4882 }
4883 else // if (level3 == 1)
4884 {
4885 if (against_oneway == 1)
4886 {
4887 if (delta < 10)
4888 {
4889 // nothing
4890 ret = g_strdup("");
4891 }
4892 else
4893 {
4894 // TRANSLATORS: First argument is strength, second direction, third how many roads to skip, fourth destination
4895 ret = g_strdup_printf_4_str(_("then turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination : "");
4896 }
4897 }
4898 else
4899 {
4900 if (delta >= 10)
4901 {
4902 // TRANSLATORS: First argument is strength, second direction, third how many roads to skip, fourth destination
4903 ret = g_strdup_printf_4_str(_("then turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination : "");
4904 }
4905 else
4906 {
4907 ret = g_strdup("");
4908 }
4909 }
4910 }
4911 }
4912
4913
4914 if (destination)
4915 {
4916 g_free(destination);
4917 destination = NULL;
4918 }
4919 }
4920 // no more commands left, must be at destination
4921 else
4922 {
4923 if (!connect)
4924 {
4925 d = get_distance(nav, distance, type, 1);
4926
4927 // TRANSLATORS: EXAMPLE: You have reached your destination in 300 meters
4928 ret = g_strdup_printf(_("You have reached your destination %s"), d);
4929
4930 g_free(d);
4931 }
4932 else
4933 {
4934 ret = g_strdup(_("then you have reached your destination."));
4935 }
4936 }
4937
4938 return2 ret;
4939
4940 __F_END__
4941 }
4942
4943 int navigation_is_low_level_street(enum item_type t)
4944 {
4945 if (global_vehicle_profile == 0) // only in car profile!
4946 {
4947 if (t == type_street_service)
4948 {
4949 return 1;
4950 }
4951 else if (t == type_street_parking_lane)
4952 {
4953 return 1;
4954 }
4955 else if (t == type_track_ground)
4956 {
4957 return 1;
4958 }
4959 else if (t == type_track_grass)
4960 {
4961 return 1;
4962 }
4963 else if (t == type_track_gravelled)
4964 {
4965 return 1;
4966 }
4967 else if (t == type_track_unpaved)
4968 {
4969 return 1;
4970 }
4971 else if (t == type_track_paved)
4972 {
4973 return 1;
4974 }
4975 }
4976
4977 return 0;
4978 }
4979
4980
4981
4982 static char *
4983 show_maneuver_at_level(struct navigation *nav, struct navigation_itm *itm, struct navigation_command *cmd, enum attr_type type, int connect, int want_this_level, int override_tellstreetname)
4984 {
4985 __F_START__
4986
4987 // TRANSLATORS: right, as in 'Turn right'
4988 char *dir = _("right");
4989 char *strength = "";
4990 int distance = itm->dest_length - cmd->itm->dest_length;
4991 char *d, *ret = NULL;
4992 int delta = cmd->delta;
4993 int delta_real = cmd->delta_real;
4994 int level;
4995 int level_now = 99;
4996 int strength_needed;
4997 int skip_roads;
4998 int count_roundabout; // car mode ----
4999 struct navigation_itm *cur;
5000 struct navigation_way *w;
5001 int against_oneway = 0;
5002 int keep_dir = 0; // car mode ----
5003 int old_dir = 0;
5004
5005 if (connect)
5006 {
5007 level = -2; // level = -2 means "connect to another maneuver via 'then ...'"
5008 }
5009 else
5010 {
5011 if (want_this_level == DONT_KNOW_LEVEL)
5012 {
5013 level = 1;
5014 }
5015 else
5016 {
5017 level = want_this_level;
5018 }
5019 }
5020
5021 int cur_vehicle_speed = 0;
5022 if ((global_navit) && (global_navit->vehicle))
5023 {
5024 cur_vehicle_speed = global_navit->vehicle->speed; // in km/h
5025 }
5026
5027
5028 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
5029 {
5030 //dbg(0, "itm->way.flags=%x\n", itm->way.flags);
5031 //dbg(0, "itm->next->way.flags=%x\n", itm->next->way.flags);
5032
5033 // int flags_old = navigation_item_get_flags(&itm->way);
5034 // int flags_new = navigation_item_get_flags(&itm->next->way);
5035 // dbg(0, "old flags=%x new flags=%x\n", flags_old, flags_new);
5036
5037 if ( (itm->way.dir == 1) && ((itm->next->way.dir == -1) && (itm->next->way.flags & NAVIT_AF_ONEWAY_BICYCLE_NO)) )
5038 {
5039 against_oneway = 1;
5040 //dbg(0, "SPEAK: (1)going against oneway street!\n");
5041 }
5042 else if ( ((itm->way.dir == -1) && (!(itm->way.flags & NAVIT_AF_ONEWAY_BICYCLE_NO))) && ((itm->next->way.dir == -1) && (itm->next->way.flags & NAVIT_AF_ONEWAY_BICYCLE_NO)) )
5043 {
5044 against_oneway = 1;
5045 //dbg(0, "SPEAK: (2)going against oneway street!\n");
5046 }
5047 }
5048
5049 w = itm->next->way.next;
5050 strength_needed = 0;
5051
5052 //dbg(0, "STRENGTH:001:strength_needed = %d delta = %d\n", strength_needed, delta);
5053
5054 if (angle_delta(itm->next->way.angle2, itm->angle_end) < 0) // left
5055 {
5056 while (w)
5057 {
5058 if (angle_delta(w->angle2, itm->angle_end) < 0) // other ways are going left
5059 {
5060 strength_needed = 1;
5061 // dbg(0, "STRENGTH:002:strength_needed = %d\n", strength_needed);
5062 break;
5063 }
5064 w = w->next;
5065 }
5066 }
5067 else // right
5068 {
5069 while (w)
5070 {
5071 if (angle_delta(w->angle2, itm->angle_end) > 0) // other ways are going right
5072 {
5073 strength_needed = 1;
5074 // dbg(0, "STRENGTH:003:strength_needed = %d\n", strength_needed);
5075 break;
5076 }
5077 w = w->next;
5078 }
5079 }
5080
5081 if ((strength_needed == 0) && (delta < 9)) // for corrected turn (delta will be 8), use strength ("slight")
5082 {
5083 strength_needed = 1;
5084 }
5085
5086 // dbg(0, "STRAI:K001:strength_needed=%d delta=%d delta_real=%d\n", strength_needed, delta, delta_real);
5087
5088 //dbg(0, "cmd->delta=%d\n", delta);
5089
5090 if (delta < 0)
5091 {
5092 #ifdef HAVE_API_ANDROID
5093 #ifdef NAVIT_SAY_DEBUG_PRINT
5094 android_send_generic_text(1,"+*#O:left\n");
5095 #endif
5096 #endif
5097 // TRANSLATORS: left, as in 'Turn left'
5098 dir = _("left");
5099 delta = -delta;
5100
5101 old_dir = -1; // left
5102
5103 }
5104 else if (delta > 0)
5105 {
5106
5107 old_dir = 1; // right
5108
5109 // dir = right
5110 #ifdef HAVE_API_ANDROID
5111 #ifdef NAVIT_SAY_DEBUG_PRINT
5112 android_send_generic_text(1,"+*#O:right\n");
5113 #endif
5114 #endif
5115 }
5116 else // delta == 0 // go straight
5117 {
5118 dir = _("straight");
5119 strength_needed = 0;
5120 // dbg(0, "STRENGTH:004:strength_needed = %d\n", strength_needed);
5121 }
5122
5123 dbg(0, "STRAI:K002:*:strength_needed=%d delta=%d delta_real=%d\n", strength_needed, delta, delta_real);
5124
5125
5126 keep_dir = 0;
5127
5128 if (strength_needed)
5129 {
5130 // dbg(0, "STRENGTH:005:\n");
5131
5132
5133 if (delta < 45)
5134 {
5135 #ifdef HAVE_API_ANDROID
5136 #ifdef NAVIT_SAY_DEBUG_PRINT
5137 android_send_generic_text(1,"+*#O:slight \n");
5138 #endif
5139 #endif
5140 // TRANSLATORS: Don't forget the ending space
5141 // TRANSLATORS: EXAMPLE: turn slight right
5142 strength = _("slighty ");
5143 // TRANSLATORS: Don't forget the ending space
5144 // TRANSLATORS: EXAMPLE: turn slight right
5145 strength = _("slight ");
5146
5147 if (delta_real == 0) // keep left/right
5148 {
5149 if (old_dir == -1)
5150 {
5151 keep_dir = -1;
5152 }
5153 else
5154 {
5155 keep_dir = 1;
5156 }
5157 }
5158
5159 dbg(0, "STRENGTH:006:strength_needed = %s\n", strength);
5160
5161 }
5162 else if (delta < 105)
5163 {
5164 strength = "";
5165 }
5166 else if (delta < 165)
5167 {
5168 #ifdef HAVE_API_ANDROID
5169 #ifdef NAVIT_SAY_DEBUG_PRINT
5170 android_send_generic_text(1,"+*#O:hard \n");
5171 #endif
5172 #endif
5173 // TRANSLATORS: Don't forget the ending space
5174 // TRANSLATORS: EXAMPLE: turn hard right
5175 strength = _("hard ");
5176 }
5177 else if (delta < 180)
5178 {
5179 #ifdef HAVE_API_ANDROID
5180 #ifdef NAVIT_SAY_DEBUG_PRINT
5181 android_send_generic_text(1,"+*#O:really hard \n");
5182 #endif
5183 #endif
5184 // TRANSLATORS: Don't forget the ending space
5185 // TRANSLATORS: EXAMPLE: turn really hard right
5186 strength = _("really hard ");
5187 }
5188 else
5189 {
5190 // dbg(1,"delta=%d\n", delta);
5191 strength = "";
5192 }
5193 }
5194
5195 // dbg(0, "STRENGTH:010:strength_needed = %s\n", strength);
5196
5197
5198 if (type != attr_navigation_long_exact)
5199 {
5200 distance = round_distance(distance);
5201 }
5202
5203 if (type == attr_navigation_speech)
5204 {
5205 dbg(0, "NAV_TURNAROUND:001 ta=%d talimit=%d\n", nav->turn_around, nav->turn_around_limit);
5206
5207 if (nav->turn_around && nav->turn_around == nav->turn_around_limit)
5208 {
5209
5210 dbg(0, "NAV_TURNAROUND:002:*******\n");
5211
5212 #ifdef HAVE_API_ANDROID
5213 #ifdef NAVIT_SAY_DEBUG_PRINT
5214 android_send_generic_text(1,"+*#O:When possible, please turn around\n");
5215 #endif
5216 #endif
5217 return2 g_strdup(_("When possible, please turn around"));
5218 }
5219
5220 if (!connect)
5221 {
5222 if (want_this_level == DONT_KNOW_LEVEL)
5223 {
5224 level = navigation_get_announce_level_cmd(nav, itm, cmd, distance - cmd->length, ((float)cur_vehicle_speed / 3.6f) );
5225 }
5226 else
5227 {
5228 level = want_this_level;
5229 }
5230 }
5231
5232 if (want_this_level == DONT_KNOW_LEVEL)
5233 {
5234 level_now = navigation_get_announce_level(nav, itm->way.item.type, distance - cmd->length, ((float)cur_vehicle_speed / 3.6f) );
5235 }
5236 else
5237 {
5238 level_now = want_this_level;
5239 }
5240
5241 }
5242
5243 #ifdef NAVIT_DEBUG_COORD_LIST
5244 int need_clear = 1;
5245 #endif
5246
5247
5248 #if 1
5249 // ------------------- jandegr -------------------
5250
5251 struct navigation_way *candidate_way;
5252
5253 if (cmd->itm->prev->way.flags & NAVIT_AF_ROUNDABOUT)
5254 {
5255 cur = cmd->itm->prev;
5256 count_roundabout = 0;
5257
5258 // ----- fix -----
5259 struct navigation_itm *cur_orig = cur->next;
5260
5261 enum item_type cur_street_type = 0;
5262 int exit_is_lover_street_type = 0;
5263 cur_street_type = cur_orig->way.item.type;
5264 // dbg(0, "curr item type=%s\n", item_to_name(cur_orig->way.item.type));
5265 exit_is_lover_street_type = navigation_is_low_level_street(cur_street_type);
5266
5267 int next_exit_is_lower_street_type = 0;
5268 // ----- fix -----
5269
5270
5271 dbg(0, "ROUNDABT:001:enter\n");
5272
5273 while (cur && (cur->way.flags & NAVIT_AF_ROUNDABOUT))
5274 {
5275
5276 // dbg(0, "ROUNDABT:002:loop-1:w\n");
5277
5278 candidate_way=cur->next->way.next;
5279 while (candidate_way)
5280 {
5281
5282 dbg(0, "ROUNDABT:002:loop-2:w2 type=%s\n", item_to_name(candidate_way->item.type));
5283
5284 // If the next segment has no exit or the exit isn't allowed, don't count it
5285 if (candidate_way && is_way_allowed(nav, candidate_way, 3))
5286 {
5287
5288 dbg(0, "ROUNDABT:003:is_allowed type=%s\n", item_to_name(candidate_way->item.type));
5289
5290 // only count street_service (and lesser streets) if we also exit on street_service (or any lesser street)
5291 if (cur->next)
5292 {
5293 next_exit_is_lower_street_type = navigation_is_low_level_street(candidate_way->item.type);
5294
5295 dbg(0, "ROUNDABT:004:next_exit_is_lower_street_type=%d type=%s\n", next_exit_is_lower_street_type, item_to_name(candidate_way->item.type));
5296 }
5297
5298 if ((exit_is_lover_street_type == 1) || (next_exit_is_lower_street_type == 0))
5299 {
5300 count_roundabout++;
5301
5302 dbg(0, "ROUNDABT:005:found:count_roundabout=%d\n", count_roundabout);
5303
5304 /* As soon as we have an allowed one on this node,
5305 * stop further counting for this node.
5306 */
5307 candidate_way = candidate_way->next;
5308 break;
5309 }
5310 }
5311 candidate_way=candidate_way->next;
5312 }
5313 cur = cur->prev;
5314 }
5315
5316 /*try to figure out if the entry node has a usable exit as well
5317 *
5318 * this will fail for left-hand driving areas
5319 */
5320 if (cur && cur->next)
5321 {
5322 dbg(0, "ROUNDABT:007:entry-check\n");
5323
5324 candidate_way = cur->next->way.next;
5325 while (candidate_way)
5326 {
5327 dbg(0, "ROUNDABT:008:loop-3:w3 type=%s\n", item_to_name(candidate_way->item.type));
5328
5329 if (candidate_way && is_way_allowed(nav,candidate_way,3)
5330 && (cur->angle_end < candidate_way->angle2) && ( candidate_way->angle2 > cur->next->way.angle2 ))
5331 /*for the entry node only count exits to the right ?*/
5332 {
5333 count_roundabout++;
5334
5335 dbg(0, "ROUNDABT:009:entry:found:count_roundabout=%d\n", count_roundabout);
5336 /* As soon as we have an allowed one on this node,
5337 * stop further counting for this node.
5338 */
5339 break;
5340 }
5341 candidate_way = candidate_way->next;
5342 }
5343 }
5344
5345 switch (level)
5346 {
5347 #if 0
5348 case 3:
5349 d=get_distance(nav, distance, type, 1);
5350 return g_strdup_printf(_("Follow the road for the next %s"), d);
5351 #endif
5352 case 2:
5353 return2 g_strdup(_("Enter the roundabout soon"));
5354 case 1:
5355 // TRANSLATORS: EXAMPLE: Leave the roundabout at the second exit
5356 return2 g_strdup_printf(_("Leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
5357 case -2:
5358 // TRANSLATORS: EXAMPLE: ... then leave the roundabout at the second exit
5359 return2 g_strdup_printf(_("then leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
5360 case 0:
5361 // TRANSLATORS: EXAMPLE: Leave the roundabout at the second exit
5362 return2 g_strdup_printf(_("Leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
5363 }
5364 }
5365
5366
5367 // ------------------- jandegr -------------------
5368 #endif
5369
5370
5371
5372
5373
5374
5375
5376 #if 0
5377 // ------------------- zoff -------------------
5378
5379 if (cmd->itm->prev->way.flags & NAVIT_AF_ROUNDABOUT)
5380 {
5381 cur = cmd->itm->prev;
5382 count_roundabout = 0;
5383
5384 struct navigation_itm *cur_orig = cur->next;
5385
5386 enum item_type cur_street_type = 0;
5387 int exit_is_lover_street_type = 0;
5388 cur_street_type = cur_orig->way.item.type;
5389 // dbg(0, "curr item type=%s\n", item_to_name(cur_orig->way.item.type));
5390 exit_is_lover_street_type = navigation_is_low_level_street(cur_street_type);
5391
5392 int next_exit_is_lower_street_type = 0;
5393
5394 while (cur && (cur->way.flags & NAVIT_AF_ROUNDABOUT))
5395 {
5396 // If the next segment has no exit or the exit isn't allowed, don't count it
5397 if (cur->next->way.next && is_way_allowed(nav, cur->next->way.next, 3))
5398 {
5399
5400 // only count street_service (and lesser streets) if we also exit on street_service (or any lesser street)
5401 if (cur->next)
5402 {
5403 next_exit_is_lower_street_type = navigation_is_low_level_street(cur->next->way.next->item.type);
5404 }
5405
5406 if ((exit_is_lover_street_type == 1) || (next_exit_is_lower_street_type == 0))
5407 {
5408 count_roundabout++;
5409
5410 #ifdef NAVIT_DEBUG_COORD_LIST
5411 if (need_clear == 1)
5412 {
5413 need_clear = 0;
5414 global_debug_coord_list_items = 0;
5415
5416 struct coord c2[5];
5417
5418 if (navigation_get_real_item_first_coord(&(cur_orig->way), c2))
5419 {
5420 global_debug_coord_list[global_debug_coord_list_items].x = c2[0].x;
5421 global_debug_coord_list[global_debug_coord_list_items].y = c2[0].y;
5422 global_debug_coord_list_items++;
5423 global_debug_coord_list[global_debug_coord_list_items].x = c2[1].x;
5424 global_debug_coord_list[global_debug_coord_list_items].y = c2[1].y;
5425 global_debug_coord_list_items++;
5426 }
5427
5428 }
5429
5430 struct coord c1[5];
5431 if (navigation_get_real_item_first_coord(cur->next->way.next, c1))
5432 {
5433 if ((global_debug_coord_list_items + 2) > MAX_DEBUG_COORDS)
5434 {
5435 global_debug_coord_list_items = 0;
5436 }
5437
5438 global_debug_coord_list[global_debug_coord_list_items].x = c1[0].x;
5439 global_debug_coord_list[global_debug_coord_list_items].y = c1[0].y;
5440 global_debug_coord_list_items++;
5441 global_debug_coord_list[global_debug_coord_list_items].x = c1[1].x;
5442 global_debug_coord_list[global_debug_coord_list_items].y = c1[1].y;
5443 global_debug_coord_list_items++;
5444 }
5445 #endif
5446
5447 }
5448 }
5449 cur = cur->prev;
5450 }
5451
5452 gchar* xy;
5453
5454 switch (level)
5455 {
5456 case 2:
5457 #ifdef HAVE_API_ANDROID
5458 #ifdef NAVIT_SAY_DEBUG_PRINT
5459 android_send_generic_text(1,"+*#O:Enter the roundabout soon\n");
5460 #endif
5461 #endif
5462 return2 g_strdup(_("Enter the roundabout soon"));
5463
5464
5465
5466
5467 case 1:
5468
5469
5470 #ifdef HAVE_API_ANDROID
5471 #ifdef NAVIT_SAY_DEBUG_PRINT
5472 android_send_generic_text(1,"+*#O:Leave the roundabout at the %s\n");
5473 xy=g_strdup_printf("+*#1:%s\n", get_exit_count_str(count_roundabout));
5474 android_send_generic_text(1,xy);
5475 g_free(xy);
5476 #endif
5477 #endif
5478 // TRANSLATORS: EXAMPLE: Leave the roundabout at the second exit
5479 return2 g_strdup_printf(_("Leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
5480
5481
5482 // ---- DISABLED ----
5483 #if 0
5484 d = get_distance(nav, distance, type, 1);
5485
5486 #ifdef HAVE_API_ANDROID
5487 #ifdef NAVIT_SAY_DEBUG_PRINT
5488 android_send_generic_text(1,"+*#O:In %s, enter the roundabout\n");
5489 xy=g_strdup_printf("+*#1:%s\n", d);
5490 android_send_generic_text(1,xy);
5491 g_free(xy);
5492 #endif
5493 #endif
5494 // TRANSLATORS: %s is the distance to the roundabout
5495 // TRANSLATORS: EXAMPLE: In 300m, enter the roundabout
5496 ret = g_strdup_printf(_("In %s, enter the roundabout"), d);
5497 g_free(d);
5498 return2 ret;
5499 #endif
5500 // ---- DISABLED ----
5501
5502
5503
5504 case -2:
5505 #ifdef HAVE_API_ANDROID
5506 #ifdef NAVIT_SAY_DEBUG_PRINT
5507 android_send_generic_text(1,"+*#O:then leave the roundabout at the %s\n");
5508 xy=g_strdup_printf("+*#1:%s\n", get_exit_count_str(count_roundabout));
5509 android_send_generic_text(1,xy);
5510 g_free(xy);
5511 #endif
5512 #endif
5513 // TRANSLATORS: EXAMPLE: ... then leave the roundabout at the second exit
5514 return2 g_strdup_printf(_("then leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
5515
5516
5517 case 0:
5518 #ifdef HAVE_API_ANDROID
5519 #ifdef NAVIT_SAY_DEBUG_PRINT
5520 android_send_generic_text(1,"+*#O:Leave the roundabout at the %s\n");
5521 xy=g_strdup_printf("+*#1:%s\n", get_exit_count_str(count_roundabout));
5522 android_send_generic_text(1,xy);
5523 g_free(xy);
5524 #endif
5525 #endif
5526 // TRANSLATORS: EXAMPLE: Leave the roundabout at the second exit
5527 return2 g_strdup_printf(_("Leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
5528 }
5529 }
5530
5531 // ------------------- zoff -------------------
5532 #endif
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542 // -- NEW 002 --
5543 if (cmd->itm)
5544 {
5545 // put correct destination into struct (to later show in GUI)
5546 navigation_select_announced_destinations(cmd);
5547 // string is in cmd->itm->way.street_dest_text
5548 }
5549 // -- NEW 002 --
5550
5551
5552
5553 switch (level)
5554 {
5555 case 3:
5556 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
5557 {
5558 if (distance > 500)
5559 {
5560 d = get_distance(nav, distance, type, 1);
5561
5562 #ifdef HAVE_API_ANDROID
5563 #ifdef NAVIT_SAY_DEBUG_PRINT
5564 android_send_generic_text(1,"+*#O:Follow the road for the next %s\n");
5565 gchar* xy=g_strdup_printf("+*#1:%s\n", d);
5566 android_send_generic_text(1,xy);
5567 g_free(xy);
5568 #endif
5569 #endif
5570
5571 ret = g_strdup_printf(_("Follow the road for the next %s"), d);
5572 g_free(d);
5573 }
5574 else
5575 {
5576 ret = g_strdup("");
5577 }
5578 }
5579 else
5580 {
5581 d = get_distance(nav, distance, type, 1);
5582
5583 #ifdef HAVE_API_ANDROID
5584 #ifdef NAVIT_SAY_DEBUG_PRINT
5585 android_send_generic_text(1,"+*#O:Follow the road for the next %s\n");
5586 gchar* xy=g_strdup_printf("+*#1:%s\n", d);
5587 android_send_generic_text(1,xy);
5588 g_free(xy);
5589 #endif
5590 #endif
5591 // TRANSLATORS: EXAMPLE: Follow the road for the next 300 meters
5592 ret = g_strdup_printf(_("Follow the road for the next %s"), d);
5593 g_free(d);
5594 }
5595 return2 ret;
5596 case 2:
5597 #ifdef HAVE_API_ANDROID
5598 #ifdef NAVIT_SAY_DEBUG_PRINT
5599 android_send_generic_text(1,"+*#O:soon\n");
5600 #endif
5601 #endif
5602
5603 // dbg(0, "SPK:*soon*\n");
5604
5605
5606 d = g_strdup(_("soon"));
5607 break;
5608 case 1:
5609 d = get_distance(nav, distance, attr_navigation_short, 0);
5610 break;
5611 case 0:
5612 skip_roads = count_possible_turns(nav, cmd->prev ? cmd->prev->itm : nav->first, cmd->itm, cmd->delta);
5613
5614 dbg(0, "count_possible_turns:1:%d", skip_roads);
5615
5616 if ((skip_roads > 0) && ((global_vehicle_profile != 1) && (global_vehicle_profile != 2)))
5617 {
5618 if (get_count_str(skip_roads + 1))
5619 {
5620
5621 // marker -1- //
5622
5623 #ifdef HAVE_API_ANDROID
5624 #ifdef NAVIT_SAY_DEBUG_PRINT
5625 android_send_generic_text(1,"+*#O:Take the %1$s road to the %2$s\n");
5626 gchar* xy=g_strdup_printf("+*#1:%s\n", get_count_str(skip_roads + 1));
5627 android_send_generic_text(1,xy);
5628 g_free(xy);
5629 xy=g_strdup_printf("+*#1:%s\n", dir);
5630 android_send_generic_text(1,xy);
5631 g_free(xy);
5632 #endif
5633 #endif
5634 // TRANSLATORS: First argument is the how manieth street to take, second the direction
5635 ret = g_strdup_printf_2_str(_("Take the %1$s road to the %2$s"), get_count_str(skip_roads + 1), dir);
5636 return2 ret;
5637 }
5638 else
5639 {
5640 #ifdef HAVE_API_ANDROID
5641 #ifdef NAVIT_SAY_DEBUG_PRINT
5642 android_send_generic_text(1,"+*#O:after %i roads\n");
5643 gchar* xy=g_strdup_printf("+*#1:%i\n", skip_roads);
5644 android_send_generic_text(1,xy);
5645 g_free(xy);
5646 #endif
5647 #endif
5648 d = g_strdup_printf(_("after %i roads"), skip_roads);
5649 }
5650 }
5651 else
5652 {
5653 #ifdef HAVE_API_ANDROID
5654 #ifdef NAVIT_SAY_DEBUG_PRINT
5655 android_send_generic_text(1,"+*#O:now\n");
5656 #endif
5657 #endif
5658 d = g_strdup(_("now"));
5659 }
5660
5661 break;
5662
5663 case -2:
5664 skip_roads = count_possible_turns(nav, cmd->prev->itm, cmd->itm, cmd->delta);
5665
5666 dbg(0, "count_possible_turns:2:%d", skip_roads);
5667
5668 if ((skip_roads > 0) && ((global_vehicle_profile != 1) && (global_vehicle_profile != 2)))
5669 {
5670 // TRANSLATORS: First argument is the how manieth street to take, second the direction
5671 // TRANSLATORS: EXAMPLE: ... then take the second road to the right
5672 if (get_count_str(skip_roads + 1))
5673 {
5674
5675 // marker -2- //
5676
5677 #ifdef HAVE_API_ANDROID
5678 #ifdef NAVIT_SAY_DEBUG_PRINT
5679 android_send_generic_text(1,"+*#O:then take the %1$s road to the %2$s\n");
5680 gchar* xy=g_strdup_printf("+*#1:%s\n", get_count_str(skip_roads + 1));
5681 android_send_generic_text(1,xy);
5682 g_free(xy);
5683 xy=g_strdup_printf("+*#1:%s\n", dir);
5684 android_send_generic_text(1,xy);
5685 g_free(xy);
5686 #endif
5687 #endif
5688 ret = g_strdup_printf_2_str(_("then take the %1$s road to the %2$s"), get_count_str(skip_roads + 1), dir);
5689 return2 ret;
5690 }
5691 else
5692 {
5693 #ifdef HAVE_API_ANDROID
5694 #ifdef NAVIT_SAY_DEBUG_PRINT
5695 android_send_generic_text(1,"+*#O:after %i roads\n");
5696 gchar* xy=g_strdup_printf("+*#1:%i\n", skip_roads);
5697 android_send_generic_text(1,xy);
5698 g_free(xy);
5699 #endif
5700 #endif
5701 d = g_strdup_printf(_("after %i roads"), skip_roads);
5702 }
5703
5704 }
5705 else
5706 {
5707 d = g_strdup("");
5708 }
5709 break;
5710 default:
5711 #ifdef HAVE_API_ANDROID
5712 #ifdef NAVIT_SAY_DEBUG_PRINT
5713 android_send_generic_text(1,"+*#O:error\n");
5714 #endif
5715 #endif
5716 d = g_strdup(_("error"));
5717 }
5718
5719
5720
5721 if (cmd->itm->next)
5722 {
5723 // dbg(0, "SPK:000a\n");
5724
5725 int tellstreetname = 0;
5726 char *destination = NULL;
5727
5728 if (type == attr_navigation_speech)
5729 {
5730 if (level == 1)
5731 {
5732 cmd->itm->streetname_told = 1;
5733 tellstreetname = 1; // Ok so we tell the name of the street
5734 }
5735
5736 if (level == 0)
5737 {
5738 if (cmd->itm->streetname_told == 0) // we are right at the intersection
5739 {
5740 tellstreetname = 1;
5741 }
5742 else
5743 {
5744 cmd->itm->streetname_told = 0; // reset just in case we come to the same street again
5745 }
5746 }
5747
5748 }
5749 else
5750 {
5751 tellstreetname = 1;
5752 }
5753
5754 if (global_speak_streetnames == 0)
5755 {
5756 // never speak streetnames (user config option)
5757 tellstreetname = 0;
5758 }
5759
5760
5761
5762 if (override_tellstreetname != -1)
5763 {
5764
5765 #ifdef NAVIT_ROUTING_DEBUG_PRINT
5766 dbg(0, "SPK:level=%d street_dest_text=%p tellstreetname=%d\n", level, cmd->itm->way.street_dest_text, tellstreetname);
5767 #endif
5768 if (nav->tell_street_name && tellstreetname)
5769 {
5770 destination = navigation_item_destination(nav, cmd->itm, itm, " ");
5771 #ifdef NAVIT_ROUTING_DEBUG_PRINT
5772 dbg(0, "SPK:levelX=%d dest=%s\n", level, destination);
5773 #endif
5774 }
5775 else if ((global_speak_streetnames == 1) && (cmd->itm->way.street_dest_text))
5776 {
5777 destination = navigation_item_destination(nav, cmd->itm, itm, " ");
5778 #ifdef NAVIT_ROUTING_DEBUG_PRINT
5779 dbg(0, "SPK:levely=%d dest=%s d=%s\n", level, destination, cmd->itm->way.street_dest_text);
5780 #endif
5781
5782 cmd->itm->streetname_told = 0;
5783 }
5784 }
5785
5786
5787 // dbg(0, "SPK:001\n");
5788
5789 if (level != -2)
5790 {
5791
5792 //dbg(0, "SPK:002\n");
5793
5794 #ifdef HAVE_API_ANDROID
5795 #ifdef NAVIT_SAY_DEBUG_PRINT
5796 android_send_generic_text(1,"+*#O:Turn %1$s%2$s %3$s%4$s\n");
5797 gchar* xy=g_strdup_printf("+*#1:%s\n", strength);
5798 android_send_generic_text(1,xy);
5799 g_free(xy);
5800 xy=g_strdup_printf("+*#1:%s\n", dir);
5801 android_send_generic_text(1,xy);
5802 g_free(xy);
5803 xy=g_strdup_printf("+*#1:%s\n", d);
5804 android_send_generic_text(1,xy);
5805 g_free(xy);
5806 xy=g_strdup_printf("+*#1:%s\n", destination ? destination : "");
5807 android_send_generic_text(1,xy);
5808 g_free(xy);
5809 #endif
5810 #endif
5811
5812 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2)) // bicycle mode
5813 {
5814 //dbg(0, "level=%5$d level_now=%6$d str=%1$s%2$s %3$s%4$s\n", strength, dir, d, destination ? destination : "", level, level_now);
5815
5816 if (level_now == 0)
5817 {
5818 if (against_oneway == 1)
5819 {
5820 if (delta < 8)
5821 {
5822 ret = g_strdup_printf("%s", _("oncoming traffic!")); // just say "attention oneway street!"
5823 }
5824 else
5825 {
5826 ret = g_strdup_printf("%s, %s", dir, _("oncoming traffic!")); // just say "left" or "right" at the turn + "attention oneway street!"
5827 }
5828 }
5829 else
5830 {
5831 ret = g_strdup(dir); // just say "left" or "right" at the turn
5832 }
5833 }
5834 else
5835 {
5836 if ((against_oneway == 1) && (delta < 8))
5837 {
5838 ret = g_strdup(""); // probably just going against a oneway street, but travelling straight on. dont say anything now
5839 }
5840 else
5841 {
5842 if (delta == 0)
5843 {
5844 // 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'
5845 ret = g_strdup_printf_4_str(_("%1$s%2$s %3$s%4$s"), "", dir, d, destination ? destination : "");
5846 }
5847 else
5848 {
5849 // 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'
5850 ret = g_strdup_printf_4_str(_("Turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination : "");
5851 }
5852 }
5853 }
5854 }
5855 else // car mode
5856 {
5857 if (delta == 0)
5858 {
5859 // 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'
5860 ret = g_strdup_printf_4_str(_("%1$s%2$s %3$s%4$s"), "", dir, d, destination ? destination : "");
5861 }
5862 else
5863 {
5864 if (keep_dir != 0)
5865 {
5866 if (keep_dir == -1)
5867 {
5868 // TRANSLATORS: The argument is the distance. Example: 'keep left in 100 meters'
5869 ret = g_strdup_printf(_("keep left %s"), d);
5870
5871 // dirty hack, so we don't need new translations
5872 char *ret2 = g_strdup_printf("%s%s", ret, destination ? destination : "");
5873 g_free(ret);
5874 ret = ret2;
5875 // ret2 = NULL;
5876 }
5877 else
5878 {
5879 // TRANSLATORS: The argument is the distance. Example: 'keep right in 100 meters'
5880 ret = g_strdup_printf(_("keep right %s"), d);
5881
5882 // dirty hack, so we don't need new translations
5883 char *ret2 = g_strdup_printf("%s%s", ret, destination ? destination : "");
5884 g_free(ret);
5885 ret = ret2;
5886 // ret2 = NULL;
5887 }
5888 }
5889 else
5890 {
5891 // 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'
5892 ret = g_strdup_printf_4_str(_("Turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination : "");
5893 }
5894 }
5895 }
5896 }
5897 else // (level == -2)
5898 {
5899
5900 //dbg(0, "SPK:007\n");
5901
5902
5903 #ifdef HAVE_API_ANDROID
5904 #ifdef NAVIT_SAY_DEBUG_PRINT
5905 android_send_generic_text(1,"+*#O:then turn %1$s%2$s %3$s%4$s\n");
5906 gchar* xy=g_strdup_printf("+*#1:%s\n", strength);
5907 android_send_generic_text(1,xy);
5908 g_free(xy);
5909 xy=g_strdup_printf("+*#1:%s\n", dir);
5910 android_send_generic_text(1,xy);
5911 g_free(xy);
5912 xy=g_strdup_printf("+*#1:%s\n", d);
5913 android_send_generic_text(1,xy);
5914 g_free(xy);
5915 xy=g_strdup_printf("+*#1:%s\n", destination ? destination : "");
5916 android_send_generic_text(1,xy);
5917 g_free(xy);
5918 #endif
5919 #endif
5920 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2)) // bicycle mode
5921 {
5922 if ((against_oneway == 1) && (delta < 8))
5923 {
5924 ret = g_strdup(""); // probably just going against a oneway street, but travelling straight on. dont say anything now
5925 }
5926 else
5927 {
5928 if (delta == 0)
5929 {
5930 // TRANSLATORS: First argument is strength, second direction, third how many roads to skip, fourth destination
5931 ret = g_strdup_printf_4_str(_("then %1$s%2$s %3$s%4$s"), "", dir, d, destination ? destination : "");
5932 }
5933 else
5934 {
5935 // TRANSLATORS: First argument is strength, second direction, third how many roads to skip, fourth destination
5936 ret = g_strdup_printf_4_str(_("then turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination : "");
5937 }
5938 }
5939 }
5940 else // car mode
5941 {
5942 if (delta == 0)
5943 {
5944 // TRANSLATORS: First argument is strength, second direction, third how many roads to skip, fourth destination
5945 ret = g_strdup_printf_4_str(_("then %1$s%2$s %3$s%4$s"), "", dir, d, destination ? destination : "");
5946 }
5947 else
5948 {
5949 if (keep_dir != 0)
5950 {
5951 if (keep_dir == -1)
5952 {
5953 ret = g_strdup_printf("%s", _("then keep left"));
5954 }
5955 else
5956 {
5957 ret = g_strdup_printf("%s", _("then keep right"));
5958 }
5959 }
5960 else
5961 {
5962 // TRANSLATORS: First argument is strength, second direction, third how many roads to skip, fourth destination
5963 ret = g_strdup_printf_4_str(_("then turn %1$s%2$s %3$s%4$s"), strength, dir, d, ""); // dont speak destination when maneuvers are connected!
5964 // ret = g_strdup_printf_4_str(_("then turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination : "");
5965 }
5966 }
5967 }
5968 }
5969 g_free(destination);
5970 }
5971 else
5972 {
5973 if (!connect)
5974 {
5975 #ifdef HAVE_API_ANDROID
5976 #ifdef NAVIT_SAY_DEBUG_PRINT
5977 android_send_generic_text(1,"+*#O:You have reached your destination %s\n");
5978 gchar* xy=g_strdup_printf("+*#1:%s\n", d);
5979 android_send_generic_text(1,xy);
5980 g_free(xy);
5981 #endif
5982 #endif
5983 // TRANSLATORS: EXAMPLE: You have reached your destination in 300 meters
5984 ret = g_strdup_printf(_("You have reached your destination %s"), d);
5985 }
5986 else
5987 {
5988 #ifdef HAVE_API_ANDROID
5989 #ifdef NAVIT_SAY_DEBUG_PRINT
5990 android_send_generic_text(1,"+*#O:then you have reached your destination.\n");
5991 #endif
5992 #endif
5993 ret = g_strdup(_("then you have reached your destination."));
5994 }
5995 }
5996 g_free(d);
5997
5998 return2 ret;
5999
6000 __F_END__
6001 }
6002
6003
6004
6005 static char *
6006 show_maneuver(struct navigation *nav, struct navigation_itm *itm, struct navigation_command *cmd, enum attr_type type, int connect)
6007 {
6008 return show_maneuver_at_level(nav, itm, cmd, type, connect, DONT_KNOW_LEVEL, 0);
6009 }
6010
6011
6012
6013
6014 /**
6015 * @brief Creates announcements for maneuvers, plus maneuvers immediately following the next maneuver
6016 *
6017 * This function does create an announcement for the current maneuver and for maneuvers
6018 * immediately following that maneuver, if these are too close and we're in speech navigation.
6019 *
6020 * @return An announcement that should be made
6021 */
6022 // central entry point for TTS maneuvers --------------
6023 // central entry point for TTS maneuvers --------------
6024 // central entry point for TTS maneuvers --------------
6025 static char *
6026 show_next_maneuvers(struct navigation *nav, struct navigation_itm *itm, struct navigation_command *cmd, enum attr_type type)
6027 {
6028 __F_START__
6029
6030 struct navigation_command *cur, *prev;
6031 int distance = itm->dest_length - cmd->itm->dest_length;
6032 int level, dist, i, time, level2;
6033 int speech_time, time2nav;
6034 char *ret, *old, *buf, *next;
6035 char *ret22;
6036
6037 char *temp_txt = NULL;
6038
6039
6040 //dbg(0, "Enter\n");
6041
6042 if (type != attr_navigation_speech)
6043 {
6044 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
6045 {
6046 return2 show_maneuver_bicycle(nav, itm, cmd, type, 0, DONT_KNOW_LEVEL); // not for speech, so just return the real values
6047 }
6048 else
6049 {
6050 return2 show_maneuver(nav, itm, cmd, type, 0); // not for speech, so just return the real values
6051 }
6052 }
6053
6054
6055 int cur_vehicle_speed = 0;
6056 if ((global_navit) && (global_navit->vehicle))
6057 {
6058 cur_vehicle_speed = global_navit->vehicle->speed; // in km/h
6059 }
6060
6061
6062 dbg(0, "SPEECH:[-0v-] current speed=%d\n", cur_vehicle_speed);
6063
6064
6065 // -- bicycle mode START -------------------------------------
6066 // -- bicycle mode START -------------------------------------
6067 // -- bicycle mode START -------------------------------------
6068 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
6069 {
6070 level = navigation_get_announce_level(nav, itm->way.item.type, distance - cmd->length, 0);
6071
6072 //dbg(0, "level = %d\n", level);
6073 //dbg(0, "(nn)itm->way.flags=%x\n", itm->way.flags);
6074 //dbg(0, "(nn)itm->next->way.flags=%x\n", itm->next->way.flags);
6075 //dbg(0, "(nn)distance=%d cmd->length=%d (minus)=%d\n", distance, cmd->length, (distance - cmd->length));
6076
6077 // in bike mode level should only be "0" or "1" or "3" !
6078
6079 if (level > 2)
6080 {
6081 //dbg(0, "just say the current command\n");
6082 return2 show_maneuver_bicycle(nav, itm, cmd, type, 0, level); // just say the current command
6083 }
6084
6085 if (cmd->itm->told)
6086 {
6087 // current command should not be spoken again!
6088 //dbg(0, "current command should not be spoken again\n");
6089 return2 g_strdup("");
6090 }
6091
6092
6093 //dbg(0, "xx 017a fsp, itm->told=%d l=%d\n", cmd->itm->told, level);
6094 if (level == 0)
6095 {
6096 // this command is spoken (now)
6097 //dbg(0, "this command is spoken (now)\n");
6098 cmd->itm->told = 1;
6099 }
6100 //dbg(0, "xx 017b fsp, itm->told=%d\n", cmd->itm->told);
6101
6102
6103 // current maneuver -------
6104 ret = show_maneuver_bicycle(nav, itm, cmd, type, 0, level); // generate TTS text for current command
6105 //dbg(0, "ret cmd=%s\n", ret);
6106 time2nav = navigation_time(itm, cmd->itm->prev);
6107 //dbg(0, "time2nav = %d\n", time2nav);
6108 old = NULL;
6109 // current maneuver -------
6110
6111 cur = cmd->next;
6112 prev = cmd;
6113
6114 if (cur && cur->itm) // we have a next command
6115 {
6116 dist = prev->itm->dest_length - cur->itm->dest_length;
6117 level2 = navigation_get_announce_level(nav, itm->next->way.item.type, dist, 0);
6118 //dbg(0, "(next)level2 = %d\n", level2);
6119 //dbg(0, "(next)dist=%d\n", dist);
6120
6121 if ((level2 < 2) && (dist < (2 * level_static_for_bicycle[0])))
6122 {
6123 //dbg(0, "link next command, and dont say it again!\n");
6124 old = ret;
6125 buf = show_maneuver_bicycle(nav, prev->itm, cur, type, 1, 0); // generate TTS text for next command, and dont say the next command again!
6126 //dbg(0, "next cmd=%s\n", next);
6127 ret = g_strdup_printf("%s, %s", old, buf);
6128 //dbg(0, "next cmd concat=%s\n", ret);
6129 g_free(buf);
6130 g_free(old);
6131 if (level == 0)
6132 {
6133 // dont say this next command again!
6134 cur->itm->told = 1;
6135 }
6136 }
6137 }
6138 }
6139 // -- bicycle mode END -------------------------------------
6140 // -- bicycle mode END -------------------------------------
6141 // -- bicycle mode END -------------------------------------
6142 else
6143 {
6144
6145
6146
6147 // -------------------------------------------------
6148 // -------------------------------------------------
6149 // -- ******************************************* --
6150 // CAR MODE
6151 // -- ******************************************* --
6152 // -------------------------------------------------
6153 // -------------------------------------------------
6154
6155 level = navigation_get_announce_level(nav, itm->way.item.type, distance - cmd->length, ((float)cur_vehicle_speed / 3.6f));
6156 //dbg(0, "level = %d\n", level);
6157 //dbg(0, "(nn)itm->way.flags=%x\n", itm->way.flags);
6158 //dbg(0, "(nn)itm->next->way.flags=%x\n", itm->next->way.flags);
6159
6160 long temp_ts = -1;
6161 debug_get_timestamp_millis(&temp_ts);
6162 if (global_last_spoken == -1)
6163 {
6164 temp_ts = 99999999;
6165 }
6166
6167 int time2nav_2 = navigation_time_real_speed(itm, cmd->itm->prev, cur_vehicle_speed);
6168
6169 dbg(0, "SPEECH:[-00-] last spoken ago=%f\n", (float)((temp_ts - global_last_spoken) / 1000.0f));
6170 dbg(0, "SPEECH:[-01-] meters to next maneuver=%d\n", (distance - cmd->length));
6171 dbg(0, "SPEECH:[-02-] level=%d\n", level);
6172
6173 #ifdef HAVE_API_ANDROID
6174 temp_txt = g_strdup_printf("SPEECH:[-00-] last spoken ago=%f\n", (float)((temp_ts - global_last_spoken) / 1000.0f));
6175 android_send_generic_text(20, temp_txt);
6176 g_free(temp_txt);
6177
6178 temp_txt = g_strdup_printf("SPEECH:[-01-] meters to next maneuver=%d\n", (distance - cmd->length));
6179 android_send_generic_text(20, temp_txt);
6180 g_free(temp_txt);
6181
6182 temp_txt = g_strdup_printf("SPEECH:[-02-] level=%d\n", level);
6183 android_send_generic_text(20, temp_txt);
6184 g_free(temp_txt);
6185 #endif
6186
6187 dbg(0, "SPEECH:[-03-] time2nav secs=%f\n", ((float)time2nav_2 / 10.0f));
6188
6189 int dist_to_next_spoken_command = -1;
6190 float secs_to_next_spoken_command = -1;
6191 if (level > 0)
6192 {
6193 dist_to_next_spoken_command = (distance - cmd->length) - (navigation_get_announce_dist_for_level_on_item(nav, itm->way.item.type, (level - 1), ((float)cur_vehicle_speed / 3.6f) ) );
6194
6195 if (cur_vehicle_speed > 0)
6196 {
6197 secs_to_next_spoken_command = ((float)dist_to_next_spoken_command / ((float)cur_vehicle_speed / 3.6f));
6198 }
6199 else
6200 {
6201 secs_to_next_spoken_command = ((float)dist_to_next_spoken_command / ((float)itm->speed / 3.6f));
6202 }
6203 }
6204
6205
6206 // current maneuver -------
6207 ret22 = show_maneuver_at_level(nav, itm, cmd, type, 0, level, 0);
6208 // current maneuver -------
6209
6210 if (nav->speech)
6211 {
6212 speech_time = speech_estimate_duration(nav->speech, ret22);
6213 dbg(0, "SPEECH:[-CUR-] secs=%f text=%s\n", ((float)speech_time)/10.0f, ret22);
6214 }
6215 else
6216 {
6217 speech_time = -1;
6218 dbg(0, "SPEECH:[-CUR-] secs=-1 text=%s\n", ret22);
6219 }
6220
6221
6222 dbg(0, "SPEECH:[-03-] meters to next announcement=%d secs to next announcement=%f\n", dist_to_next_spoken_command, secs_to_next_spoken_command);
6223
6224 if (level == 3)
6225 {
6226
6227 // ===========----------- LEVEL 3 -----------===========
6228
6229 #if 0
6230 if (((float)((temp_ts - global_last_spoken) / 1000.0f)) < 3.0f)
6231 {
6232 dbg(0, "SPEECH:[-NOOP-] 004: already spoken in the last 3 secs.\n");
6233 return2 g_strdup(""); // dont speak this command now!
6234 }
6235 #endif
6236
6237 if (secs_to_next_spoken_command < 7 )
6238 {
6239 if (ret22)
6240 {
6241 g_free(ret22);
6242 ret22 = NULL;
6243 }
6244
6245 #ifdef _DEBUG_BUILD_
6246 // speak debug ----
6247 navit_say(global_navit, "level 3a wieder in 7 sekunden");
6248 // speak debug ----
6249 #endif
6250
6251 dbg(0, "SPEECH:[-NOOP-] 006b: want to speak again in less than %d secs. level=%d\n", 7, level);
6252 return2 g_strdup(""); // dont speak this command now!
6253 }
6254
6255 if (secs_to_next_spoken_command < (((float)speech_time/10.0f) + 3) )
6256 {
6257 if (ret22)
6258 {
6259 g_free(ret22);
6260 ret22 = NULL;
6261 }
6262
6263 #ifdef _DEBUG_BUILD_
6264 // speak debug ----
6265 temp_txt = g_strdup_printf("level 3b wieder in %d sekunden", (int)(((float)speech_time/10.0f) + 3));
6266 navit_say(global_navit, temp_txt);
6267 g_free(temp_txt);
6268 // speak debug ----
6269 #endif
6270
6271 dbg(0, "SPEECH:[-NOOP-] 006: want to speak again in less than %d secs. level=%d\n", (((float)speech_time/10.0f) + 3), level );
6272 return2 g_strdup(""); // dont speak this command now!
6273 }
6274 // ===========----------- LEVEL 3 -----------===========
6275
6276
6277 }
6278 else if (level == 2)
6279 {
6280
6281 // ===========----------- LEVEL 2 -----------===========
6282
6283
6284 #if 0
6285 if (secs_to_next_spoken_command < 3 )
6286 {
6287 if (ret22)
6288 {
6289 g_free(ret22);
6290 ret22 = NULL;
6291 }
6292
6293 #ifdef _DEBUG_BUILD_
6294 // speak debug ----
6295 navit_say(global_navit, "level 2a wieder in 3 sekunden");
6296 // speak debug ----
6297 #endif
6298
6299 dbg(0, "SPEECH:[-NOOP-] 007b: want to speak again in less than %d secs. level=%d\n", 3, level);
6300 return2 g_strdup(""); // dont speak this command now!
6301 }
6302 #endif
6303
6304 #if 1
6305 if (secs_to_next_spoken_command < (((float)speech_time/10.0f) + 1) )
6306 {
6307 if (ret22)
6308 {
6309 g_free(ret22);
6310 ret22 = NULL;
6311 }
6312
6313 #ifdef _DEBUG_BUILD_
6314 // speak debug ----
6315 temp_txt = g_strdup_printf("level 2b wieder in %d sekunden", (int)(((float)speech_time/10.0f) + 1));
6316 navit_say(global_navit, temp_txt);
6317 // speak debug ----
6318 #endif
6319
6320 dbg(0, "SPEECH:[-NOOP-] 007: want to speak again in less than %d secs. level=%d\n", (int)(((float)speech_time/10.0f) + 1), level);
6321 return2 g_strdup(""); // dont speak this command now!
6322 }
6323 #endif
6324
6325 #if 0
6326 if (((float)((temp_ts - global_last_spoken) / 1000.0f)) < 5.0f)
6327 {
6328 if (ret22)
6329 {
6330 g_free(ret22);
6331 ret22 = NULL;
6332 }
6333
6334 #ifdef _DEBUG_BUILD_
6335 // speak debug ----
6336 navit_say(global_navit, "level 2c schon vor 5 sekunden");
6337 // speak debug ----
6338 #endif
6339
6340 dbg(0, "SPEECH:[-NOOP-] 005: already spoken in the last 5 secs. level=%d\n", level);
6341 return2 g_strdup(""); // dont speak this command now!
6342 }
6343 #endif
6344
6345 // ===========----------- LEVEL 2 -----------===========
6346
6347
6348 }
6349 else if (level == 1)
6350 {
6351
6352 // ===========----------- LEVEL 1 -----------===========
6353
6354
6355 #if 0
6356 if (((float)time2nav_2 / 10.0f) < 5.0f)
6357 {
6358 dbg(0, "SPEECH:[-NOOP-] 001: less than 5 secs. to maneuver\n");
6359 return2 g_strdup(""); // dont speak this command now!
6360 }
6361 #endif
6362
6363 #if 0
6364 if ((distance - cmd->length) < 50)
6365 {
6366 dbg(0, "SPEECH:[-NOOP-] 003: less than 50 meters to maneuver\n");
6367 return2 g_strdup(""); // dont speak this command now!
6368 }
6369 #endif
6370
6371
6372 if (dist_to_next_spoken_command < 18)
6373 {
6374 if (ret22)
6375 {
6376 g_free(ret22);
6377 ret22 = NULL;
6378 }
6379
6380 #ifdef _DEBUG_BUILD_
6381 // speak debug ----
6382 temp_txt = g_strdup_printf("level 1a wieder in %d sekunden", 18);
6383 navit_say(global_navit, temp_txt);
6384 g_free(temp_txt);
6385 // speak debug ----
6386 #endif
6387
6388
6389 dbg(0, "SPEECH:[-NOOP-] 011: less than 18 meters to next announcement\n");
6390 return2 g_strdup(""); // dont speak this command now!
6391 }
6392
6393 #if 0
6394 if (((float)((temp_ts - global_last_spoken) / 1000.0f)) < 4.0f)
6395 {
6396 if (ret22)
6397 {
6398 g_free(ret22);
6399 ret22 = NULL;
6400 }
6401
6402 dbg(0, "SPEECH:[-NOOP-] 002: already spoken in the last 4 secs. level=%d\n", level);
6403 return2 g_strdup(""); // dont speak this command now!
6404 }
6405 #endif
6406
6407 if (secs_to_next_spoken_command < (((float)speech_time/10.0f) + 1) )
6408 {
6409 if (secs_to_next_spoken_command < 3.0f)
6410 {
6411 if (ret22)
6412 {
6413 g_free(ret22);
6414 ret22 = NULL;
6415 }
6416
6417 #ifdef _DEBUG_BUILD_
6418 // speak debug ----
6419 temp_txt = g_strdup_printf("level 1b wieder in %d sekunden", 3);
6420 navit_say(global_navit, temp_txt);
6421 g_free(temp_txt);
6422 // speak debug ----
6423 #endif
6424
6425
6426 dbg(0, "SPEECH:[-NOOP-] 008: want to speak again in less than %d secs. level=%d\n", (((float)speech_time/10.0f) + 1), level);
6427 return2 g_strdup(""); // dont speak this command now!
6428 }
6429 else
6430 {
6431 // if we have at least 3 seconds left, still say level 1 announcement (without the streetname/destination name)
6432 dbg(0, "SPEECH:[-NOOP-] 008lo: use level=%d announcement without destination name\n", level);
6433 if (ret22)
6434 {
6435 g_free(ret22);
6436 ret22 = NULL;
6437 }
6438 ret22 = show_maneuver_at_level(nav, itm, cmd, type, 0, level, -1);
6439 if (nav->speech)
6440 {
6441 speech_time = speech_estimate_duration(nav->speech, ret22);
6442 dbg(0, "SPEECH:[-CUR-] :lo: secs=%f text=%s\n", ((float)speech_time)/10.0f, ret22);
6443 }
6444 else
6445 {
6446 speech_time = -1;
6447 dbg(0, "SPEECH:[-CUR-] :lo: secs=-1 text=%s\n", next);
6448 }
6449
6450 if (secs_to_next_spoken_command < (((float)speech_time/10.0f) + 0) )
6451 {
6452 if (ret22)
6453 {
6454 g_free(ret22);
6455 ret22 = NULL;
6456 }
6457
6458 #ifdef _DEBUG_BUILD_
6459 // speak debug ----
6460 temp_txt = g_strdup_printf("level 1c wieder in %d sekunden", (int)(((float)speech_time/10.0f) + 0));
6461 navit_say(global_navit, temp_txt);
6462 g_free(temp_txt);
6463 // speak debug ----
6464 #endif
6465
6466
6467 dbg(0, "SPEECH:[-NOOP-] 008loEE: giving up on this announcement\n");
6468 return2 g_strdup(""); // dont speak this command now!
6469 }
6470 }
6471 }
6472
6473 // ===========----------- LEVEL 1 -----------===========
6474
6475 }
6476
6477
6478
6479
6480
6481
6482 #ifdef HAVE_API_ANDROID
6483 temp_txt = g_strdup_printf("SPEECH:[-03-] time2nav secs=%f\n", ((float)time2nav_2 / 10.0f));
6484 android_send_generic_text(20, temp_txt);
6485 g_free(temp_txt);
6486 #endif
6487
6488 if (level > 1)
6489 {
6490 dbg(0, "SPEECH:[-R1-]\n");
6491 return2 ret22; // We accumulate maneuvers only if they are close (level-0 and level-1)
6492 }
6493
6494 if (cmd->itm->told)
6495 {
6496 #ifdef HAVE_API_ANDROID
6497 #ifdef NAVIT_SAY_DEBUG_PRINT
6498 android_send_generic_text(1,"+*#C1:*CANCEL*\n");
6499 #endif
6500 #endif
6501 dbg(0, "SPEECH:[-R2-]\n");
6502 #ifdef HAVE_API_ANDROID
6503 temp_txt = g_strdup("SPEECH:[-R2-]\n");
6504 android_send_generic_text(20, temp_txt);
6505 g_free(temp_txt);
6506 #endif
6507 if (ret22)
6508 {
6509 g_free(ret22);
6510 ret22 = NULL;
6511 }
6512
6513
6514 return2 g_strdup("");
6515 }
6516
6517
6518 // current maneuver -------
6519 ret = ret22;
6520 time2nav = navigation_time_real_speed(itm, cmd->itm->prev, cur_vehicle_speed);
6521 // current maneuver -------
6522
6523
6524 #if 0
6525 if (nav->speech)
6526 {
6527 speech_time = speech_estimate_duration(nav->speech, ret);
6528 dbg(0, "SPEECH:[-CUR-] secs=%f text=%s\n", ((float)speech_time)/10.0f, ret);
6529 }
6530 else
6531 {
6532 speech_time = -1;
6533 dbg(0, "SPEECH:[-CUR-] secs=-1 text=%s\n", next);
6534 }
6535 #endif
6536
6537
6538 old = NULL;
6539
6540 dbg(0, "SPEECH:[-04-] time2nav secs=%f\n", ((float)time2nav / 10.0f));
6541 #ifdef HAVE_API_ANDROID
6542 temp_txt = g_strdup_printf("SPEECH:[-04-] time2nav secs=%f\n", ((float)time2nav / 10.0f));
6543 android_send_generic_text(20, temp_txt);
6544 g_free(temp_txt);
6545 #endif
6546
6547
6548
6549
6550 // next maneuver -------
6551 cur = cmd->next;
6552 prev = cmd;
6553 // next maneuver -------
6554
6555
6556 i = 0;
6557 int max_announcements = 3;
6558 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
6559 {
6560 max_announcements = 2;
6561 }
6562
6563 while (cur && cur->itm) // only accumulate at "level 0" or "level 1"
6564 {
6565 // We don't merge more than "max_announcements" announcements...
6566 if (i > (max_announcements - 2))
6567 {
6568 break;
6569 }
6570
6571 dist = prev->itm->dest_length - cur->itm->dest_length; // distance between next 2 maneuvers in meters
6572
6573 if (dist > 420) // too far apart, bail out
6574 {
6575 break;
6576 }
6577
6578 next = show_maneuver(nav, prev->itm, cur, type, 0);
6579 if (nav->speech)
6580 {
6581 speech_time = speech_estimate_duration(nav->speech, next);
6582 dbg(0, "SPEECH:[-NXT-] secs=%f text=%s\n", ((float)speech_time)/10.0f, next);
6583 }
6584 else
6585 {
6586 speech_time = -1;
6587 dbg(0, "SPEECH:[-NXT-] secs=-1 text=%s\n", next);
6588 }
6589 g_free(next);
6590
6591 if (speech_time == -1)
6592 {
6593 // user didn't set cps
6594 speech_time = 25; // assume 2.5 seconds
6595 dbg(0, "SPEECH:[-NXT-](2) secs=%f\n", ((float)speech_time)/10.0f);
6596 }
6597
6598 //if (cur_vehicle_speed > 0)
6599 //{
6600 // time = ((float)dist / ((float)cur_vehicle_speed / 3.6f)) * 10;
6601 //}
6602 //else
6603 //{
6604 // time = navigation_time_real_speed(prev->itm, cur->itm->prev, cur_vehicle_speed);
6605 time = navigation_time(prev->itm, cur->itm->prev);
6606 //}
6607
6608 dbg(0, "SPEECH:[-NXT-][-05-] dist meters=%d time secs=%f speech_time=%f\n", dist, ((float)time)/10.0f, ((float)speech_time)/10.0f);
6609 #ifdef HAVE_API_ANDROID
6610 temp_txt = g_strdup_printf("SPEECH:[-05-] dist meters=%d time secs=%f speech_time=%f\n", dist, ((float)time)/10.0f, ((float)speech_time)/10.0f);
6611 android_send_generic_text(20, temp_txt);
6612 g_free(temp_txt);
6613 #endif
6614
6615
6616 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
6617 {
6618 // !! should never get here !!
6619 }
6620 else
6621 {
6622 dbg(0, "SPEECH: time secs=%f speech_time secs=%f [if (time >= (speech_time + 35))]\n", ((float)time)/10.0f, ((float)speech_time)/10.0f);
6623
6624 if (i == 0)
6625 {
6626 if (dist < 170) // distance between maneuvers less than 170m --> always merge maneuvers
6627 {
6628 }
6629 else
6630 {
6631 // **OLD** // if (time >= (speech_time + 35)) // (time to turn) >= (time to speak command + 3.5 secs.)
6632 if (time > ((global_level1_announcement * 10.0f) - 3) ) // more than "global_level1_announcement" seconds to next maneuver -> don't merge it
6633 {
6634 dbg(0, "SPEECH:*break first*\n");
6635 break;
6636 }
6637 }
6638 }
6639 else
6640 {
6641 if (time > (global_level0_announcement * 10.0f)) // more than "global_level0_announcement" seconds to next maneuver -> don't merge it
6642 {
6643 dbg(0, "SPEECH:*break next*\n");
6644 break;
6645 }
6646 }
6647 }
6648
6649 old = ret;
6650 buf = show_maneuver(nav, prev->itm, cur, type, 1);
6651 ret = g_strdup_printf("%s, %s", old, buf);
6652 g_free(buf);
6653
6654 dbg(0, "SPEECH: speech_est_dur secs=%f time2nav secs=%f\n", (float)(speech_estimate_duration(nav->speech, ret))/10.0f, (float)time2nav/10.0f);
6655 // if (nav->speech && speech_estimate_duration(nav->speech, ret) > time2nav)
6656 // {
6657 // g_free(ret);
6658 // ret = old;
6659 // i = (max_announcements - 1); // This will terminate the loop
6660 // dbg(0, "SPEECH:*terminate loop*\n");
6661 // }
6662 // else
6663 // {
6664 g_free(old);
6665 // }
6666
6667
6668 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
6669 {
6670 // !! should never get here !!
6671 }
6672 else
6673 {
6674 #if 0
6675 dbg(0, "SPEECH: time secs=%f speech_time secs=%f [if (time <= speech_time)]\n", ((float)time)/10.0f, ((float)speech_time)/10.0f);
6676 // If the two maneuvers are *really* close, we shouldn't tell the second one again, because TTS won't be fast enough
6677 if (time <= speech_time)
6678 {
6679 #ifdef HAVE_API_ANDROID
6680 #ifdef NAVIT_SAY_DEBUG_PRINT
6681 android_send_generic_text(1,"+*#C2:*CANCEL*\n");
6682 #endif
6683 #endif
6684 //dbg(0, "cancel speak:%s\n", ret);
6685 cur->itm->told = 1;
6686 }
6687 #endif
6688 }
6689
6690 prev = cur;
6691 cur = cur->next;
6692 i++;
6693 }
6694
6695 // -------------------------------------------------
6696 // -------------------------------------------------
6697 // -- ******************************************* --
6698 // CAR MODE
6699 // -- ******************************************* --
6700 // -------------------------------------------------
6701 // -------------------------------------------------
6702
6703 }
6704
6705 dbg(0, "SPEECH:[-Re-]\n");
6706 #ifdef HAVE_API_ANDROID
6707 temp_txt = g_strdup("SPEECH:[-Re-]\n");
6708 android_send_generic_text(20, temp_txt);
6709 g_free(temp_txt);
6710 #endif
6711
6712 return2 ret;
6713
6714 __F_END__
6715 }
6716 // central entry point for TTS maneuvers --------------
6717 // central entry point for TTS maneuvers --------------
6718 // central entry point for TTS maneuvers --------------
6719
6720
6721
6722 // ----- global var, BAD!! -------
6723 int global_spoke_last_position_update = 0;
6724 int previous_dest_length = -1;
6725 int previous_dest_length_save = -1;
6726 struct navigation_command *last_first_cmd_save = NULL;
6727 int global_turn_around_spoken = 0;
6728 // ----- global var, BAD!! -------
6729
6730 static void navigation_call_callbacks(struct navigation *this_, int force_speech)
6731 {
6732 __F_START__
6733
6734 int distance, level = 0;
6735 int level_cur;
6736 int distance_orig;
6737 void *p = this_;
6738 int dont_speak_yet = 0;
6739 int level_last_save = 99;
6740
6741 if (!this_->cmd_first)
6742 {
6743 //dbg(0, "ret 0001\n");
6744 global_spoke_last_position_update = 0;
6745 return2;
6746 }
6747
6748 // EMPTY: calls nothing!!
6749 // ****** // callback_list_call(this_->callback, 1, &p);
6750
6751 //if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
6752 //{
6753 // force_speech = 7;
6754 //}
6755
6756 //dbg(0, "force_speech=%d turn_around=%d turn_around_limit=%d\n", force_speech, this_->turn_around, this_->turn_around_limit);
6757
6758 distance = this_->first->dest_length - this_->cmd_first->itm->dest_length;
6759 //dbg(0, "fdl=%d cmdidl=%d\n", this_->first->dest_length, this_->cmd_first->itm->dest_length);
6760 distance_orig = distance;
6761 distance = round_distance(distance);
6762
6763 int cur_vehicle_speed = 0;
6764 if ((global_navit) && (global_navit->vehicle))
6765 {
6766 cur_vehicle_speed = global_navit->vehicle->speed;
6767 }
6768
6769 dbg(0, "NCC_:distance_orig=%d distance=%d curr vehicle speed=%d force_speech=%d\n", distance_orig, distance, global_navit->vehicle->speed, force_speech);
6770
6771
6772 if (this_->turn_around_limit && this_->turn_around == this_->turn_around_limit)
6773 {
6774
6775 dbg(0, "NAV_TURNAROUND:005 ta=%d talimit=%d\n", this_->turn_around, this_->turn_around_limit);
6776
6777 //dbg(0, "xx 001 d=%d rd=%d dt=%d\n", distance_orig, distance_orig, this_->distance_turn);
6778 #if 0
6779 while (distance > this_->distance_turn)
6780 {
6781 this_->level_last = 4;
6782 level = 4;
6783 force_speech = 2;
6784
6785 if (this_->distance_turn >= 500)
6786 {
6787 this_->distance_turn *= 2;
6788 }
6789 else
6790 {
6791 this_->distance_turn = 500;
6792 }
6793 #endif
6794
6795 // we need to force a maneuver for "turn around" ------------------
6796 this_->level_last = 4;
6797 level = 4;
6798 force_speech = 2;
6799 // this_->distance_turn *= 100;
6800
6801 #if 1
6802 global_driven_away_from_route = 0;
6803 global_spoke_last_position_update = 0;
6804 global_last_spoken = -1;
6805 previous_dest_length = -1;
6806 previous_dest_length_save = -1;
6807 last_first_cmd_save = NULL;
6808 #endif
6809
6810 this_->level_last = 99;
6811
6812
6813 this_->level_last = level;
6814 this_->curr_delay = 0;
6815
6816 dbg(0, "NCC_:force_speech=%d distance=%d level=%d global_spoke_last_position_update=%d\n", force_speech, distance, level, global_spoke_last_position_update);
6817 dbg(0, "NCC_:========= END ==========\n");
6818
6819 global_spoke_last_position_update = 1;
6820
6821 // ----------------------------------
6822 // ----------------------------------
6823 // calls -> calls navit_speak
6824 //
6825 callback_list_call(this_->callback_speech, 1, &p);
6826 // ----------------------------------
6827 // ----------------------------------
6828
6829
6830 return2;
6831
6832 // we need to force a maneuver for "turn around" ------------------
6833
6834 #if 0
6835 dbg(0, "NCC_:loop 001 d=%d dt=%d force_speech=%d\n", distance, this_->distance_turn, force_speech);
6836 }
6837 #endif
6838
6839 }
6840 else if (!this_->turn_around_limit || this_->turn_around != this_->turn_around_limit)
6841 {
6842 this_->distance_turn = 50;
6843
6844 global_turn_around_spoken = 0; // reset turn around speak flag
6845
6846 //dbg(0, "lcur=%d lprev=%d lnext=%d\n", this_->cmd_first->itm->length, this_->cmd_first->itm->prev->length, this_->cmd_first->itm->next->length);
6847 //dbg(0, "xx 002a d=%d d2=%d diff=%d\n", distance, (distance - this_->cmd_first->length), (this_->cmd_first->itm->length - distance_orig));
6848
6849 //dbg(0, "xx 002a ll001=%d\n", (this_->cmd_first->itm->prev->dest_length - this_->cmd_first->itm->dest_length));
6850
6851 distance -= this_->cmd_first->length;
6852
6853
6854 level = navigation_get_announce_level_cmd(this_, this_->first, this_->cmd_first, distance_orig, ((float)cur_vehicle_speed / 3.6f) );
6855 level_cur = navigation_get_announce_level(this_, this_->first->way.item.type, distance_orig, ((float)cur_vehicle_speed / 3.6f));
6856
6857
6858
6859 if (last_first_cmd_save != this_->cmd_first)
6860 {
6861 last_first_cmd_save = this_->cmd_first;
6862 previous_dest_length = previous_dest_length_save;
6863 }
6864 previous_dest_length_save = this_->cmd_first->itm->dest_length;
6865 // level_last_save = this_->level_last;
6866
6867 //dbg(0, "NCC_:\n");
6868 //dbg(0, "NCC_:0---passed item?---\n");
6869 // dbg(0, "NCC_:level=%d level_cur=%d this_->level_last=%d distance_orig=%d distance=%d\n", level, level_cur, this_->level_last, distance_orig, distance);
6870
6871 #if 1
6872 if (previous_dest_length == -1)
6873 {
6874 dbg(0, "NCC_:no prev nav command\n");
6875 }
6876 else
6877 {
6878 if (distance_orig > 40)
6879 {
6880 if ((distance_orig + 25) >= (previous_dest_length - this_->cmd_first->itm->dest_length))
6881 {
6882 // we are still within 25 meters of the previous navigation command item
6883 dont_speak_yet = 1;
6884 dbg(0, "NCC_:too close to last command, speak later level=%d level_cur=%d back-distance=%d\n", level, level_cur, (previous_dest_length - this_->cmd_first->itm->dest_length));
6885 }
6886 }
6887 #if 1
6888 else if (distance_orig > 20)
6889 {
6890 if ((distance_orig) > (previous_dest_length - this_->cmd_first->itm->dest_length))
6891 {
6892 // we are still at the position of the previous navigation command item
6893 dont_speak_yet = 1;
6894 dbg(0, "NCC_:too close to last command, speak later level=%d level_cur=%d back-distance=%d\n", level, level_cur, (previous_dest_length - this_->cmd_first->itm->dest_length));
6895 }
6896 }
6897 #endif
6898 }
6899 #endif
6900
6901 //dbg(0, "NCC_:1---passed item?---\n");
6902 //dbg(0, "NCC_:\n");
6903
6904
6905
6906
6907 //dbg(0, "xx 002 d=%d rd=%d dt=%d l=%d lcur=%d ll=%d\n", distance_orig, distance, this_->distance_turn, level, level_cur, this_->level_last);
6908
6909 if (level < this_->level_last)
6910 {
6911 /* only tell if the level is valid for more than 3 seconds */
6912 int speed_distance = this_->first->speed * 30 / 36;
6913
6914 dbg(0, "NCC_:speed_distance=%d\n", speed_distance);
6915
6916
6917 //dbg(0, "xx 003 speed_distance=%d this_->first->speed=%d globalslp=%d\n", speed_distance, this_->first->speed, global_spoke_last_position_update);
6918
6919 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
6920 {
6921
6922 level = level_cur;
6923
6924 if ((level_cur > 0) && (global_spoke_last_position_update > 0))
6925 {
6926 // skip this time, speak command on the next update
6927 dbg(0, "NCC_:SKIP[1] this update, speak next update (%d)! level=%d level_cur=%d\n", global_spoke_last_position_update, level, level_cur);
6928 }
6929 else
6930 {
6931 this_->level_last = level_cur;
6932 force_speech = 3;
6933 dbg(0, "NCC_:force_speech(2)=%d\n", force_speech);
6934 }
6935 }
6936 else
6937 {
6938 if (distance < speed_distance || navigation_get_announce_level_cmd(this_, this_->first, this_->cmd_first, distance - speed_distance, ((float)cur_vehicle_speed / 3.6f) ) == level)
6939 {
6940 //dbg(0, "distance %d speed_distance %d\n", distance, speed_distance);
6941 //dbg(0, "level %d < %d\n", level, this_->level_last);
6942 this_->level_last = level;
6943 force_speech = 3;
6944 dbg(0, "NCC_:force_speech(3)=%d\n", force_speech);
6945 //dbg(0, "xx 004\n");
6946 }
6947 }
6948 }
6949
6950
6951 if (!item_is_equal(this_->cmd_first->itm->way.item, this_->item_last))
6952 {
6953 //dbg(0, "xx 005\n");
6954
6955 this_->item_last = this_->cmd_first->itm->way.item;
6956 this_->level_last = 99; // new item, reset command level
6957
6958 dbg(0, "NCC_:Ni---new navigation command item!!---\n");
6959
6960 if (this_->delay)
6961 {
6962 this_->curr_delay = this_->delay;
6963 }
6964 else
6965 {
6966 // if ((level_cur > 0) && (global_spoke_last_position_update > 0) && (distance_orig > 50))
6967 // {
6968 // // skip this time, speak command on the next update
6969 // dbg(0, "NCC_:SKIP[2] speech this update, speak at next update (%d)!\n", global_spoke_last_position_update);
6970 // }
6971 // else
6972 // {
6973 force_speech = 5;
6974 dbg(0, "NCC_:force_speech(4)=%d\n", force_speech);
6975 // }
6976 }
6977 }
6978 else
6979 {
6980 //dbg(0, "xx 006\n");
6981
6982 if (this_->curr_delay)
6983 {
6984 this_->curr_delay--;
6985
6986 if (!this_->curr_delay)
6987 {
6988 force_speech = 4;
6989 dbg(0, "NCC_:force_speech(5)=%d\n", force_speech);
6990 }
6991 }
6992 }
6993 }
6994
6995 if (global_spoke_last_position_update > 0)
6996 {
6997 //dbg(0,"globalslp(1)=%d\n", global_spoke_last_position_update);
6998 global_spoke_last_position_update--;
6999 //dbg(0,"globalslp(2)=%d\n", global_spoke_last_position_update);
7000 }
7001
7002
7003 #if 0
7004 //dbg(0,"XA 000\n");
7005 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2)) // bicycle mode
7006 {
7007 if ((this_->previous) && (!item_is_equal(this_->cmd_first->itm->way.item, this_->previous->way.item)))
7008 {
7009 // item has changed, check if we missed a spoken level 0 command
7010 if (this_->previous->told == 0)
7011 {
7012 dbg(0, "NCC_:MISSED a level 0 spoken command!\n");
7013
7014 char *dir2 = _("right");
7015 int delta2 = this_->cmd_previous->delta;
7016 dbg(0, "NCC_:missed delta = %d\n", delta2);
7017 if (delta2 < 0)
7018 {
7019 // TRANSLATORS: left, as in 'Turn left'
7020 dir2 = _("left");
7021 delta2 = -delta2;
7022 }
7023
7024 if (delta2 > 20)
7025 {
7026 dbg(0,"NCC_:XA 002a\n");
7027 navit_say(this_->navit, dir2);
7028 this_->previous->told = 1;
7029 }
7030 }
7031 }
7032 }
7033 #endif
7034
7035
7036 this_->previous = this_->cmd_first->itm;
7037 this_->cmd_previous = this_->cmd_first;
7038
7039 #if 1
7040 if ((dont_speak_yet == 1) && (force_speech))
7041 {
7042 dbg(0,"NCC_:this_->level_last = 99\n");
7043 this_->level_last = 99;
7044 }
7045 #endif
7046
7047 if (global_driven_away_from_route == 1)
7048 {
7049 dbg(0,"NCC_:** NEW PATH **\n");
7050 global_driven_away_from_route = 0;
7051 global_spoke_last_position_update = 0;
7052 global_last_spoken = -1;
7053 previous_dest_length = -1;
7054 previous_dest_length_save = -1;
7055 last_first_cmd_save = NULL;
7056
7057 this_->level_last = 99;
7058 }
7059
7060 if ( (dont_speak_yet == 0) || ((global_vehicle_profile == 1) || (global_vehicle_profile == 2)) )
7061 {
7062 if (force_speech)
7063 {
7064 this_->level_last = level;
7065 this_->curr_delay = 0;
7066
7067 dbg(0, "NCC_:force_speech=%d distance=%d level=%d global_spoke_last_position_update=%d\n", force_speech, distance, level, global_spoke_last_position_update);
7068 dbg(0, "NCC_:========= END ==========\n");
7069
7070 global_spoke_last_position_update = 1;
7071
7072 // ----------------------------------
7073 // ----------------------------------
7074 // calls -> calls navit_speak
7075 //
7076 callback_list_call(this_->callback_speech, 1, &p);
7077 // ----------------------------------
7078 // ----------------------------------
7079 }
7080 }
7081
7082 __F_END__
7083 }
7084
7085
7086 // ----------- main place where navigation commands are generated ------------
7087 // ----------- main place where navigation commands are generated ------------
7088 // ----------- main place where navigation commands are generated ------------
7089 static void navigation_update(struct navigation *this_, struct route *route, struct attr *attr)
7090 {
7091 __F_START__
7092
7093 struct map *map;
7094 struct map_rect *mr;
7095 struct item *ritem; /* Holds an item from the route map */
7096 struct item *sitem; /* Holds the corresponding item from the actual map */
7097 struct attr street_item, street_direction;
7098 struct navigation_itm *itm;
7099 struct attr vehicleprofile;
7100 int mode = 0, incr = 0, first = 1;
7101
7102 //dbg(0, "Enter\n");
7103
7104 if (attr->type != attr_route_status)
7105 {
7106 //dbg(0, "return 001\n");
7107 return2;
7108 }
7109
7110 #ifdef NAVIT_ROUTING_DEBUG_PRINT
7111 dbg(0, "RS:001:route_status=%s\n", route_status_to_name(attr->u.num));
7112 #endif
7113
7114
7115 dbg(0, "NCC_:NU:RRRRSSSSSS::route_status=%s\n", route_status_to_name(attr->u.num));
7116
7117 if (attr->u.num == route_status_path_done_new)
7118 {
7119 // route calculated new, you drove a different path?
7120 global_driven_away_from_route = 1;
7121 }
7122
7123
7124 //dbg(1, "enter %d\n", mode);
7125 if (attr->u.num == route_status_no_destination || attr->u.num == route_status_not_found || attr->u.num == route_status_path_done_new)
7126 {
7127 dbg(0, "NCC_:NU:navigation_flush\n");
7128 navigation_flush(this_);
7129 }
7130
7131 if (attr->u.num != route_status_path_done_new && attr->u.num != route_status_path_done_incremental)
7132 {
7133 //dbg(0, "return 002\n");
7134 dbg(0, "NCC_:NU:ret 001\n");
7135
7136 return2;
7137 }
7138
7139 if (!this_->route)
7140 {
7141 //dbg(0, "return 003\n");
7142 dbg(0, "NCC_:NU:ret 002\n");
7143
7144 return2;
7145 }
7146
7147 map = route_get_map(this_->route);
7148 if (!map)
7149 {
7150 //dbg(0, "return 004\n");
7151 return2;
7152 }
7153
7154 mr = map_rect_new(map, NULL);
7155
7156 if (!mr)
7157 {
7158 //dbg(0, "return 005\n");
7159 return2;
7160 }
7161
7162 if (route_get_attr(route, attr_vehicleprofile, &vehicleprofile, NULL))
7163 {
7164 this_->vehicleprofile = vehicleprofile.u.vehicleprofile;
7165 }
7166 else
7167 {
7168 this_->vehicleprofile = NULL;
7169 }
7170
7171 //dbg(1,"enter\n");
7172
7173 dbg(0, "NCC_:NU:------ LOOP START ------\n");
7174
7175 int first_item = 1;
7176 this_->turn_around = 0;
7177
7178 while ((ritem = map_rect_get_item(mr)))
7179 {
7180
7181 dbg(0, "NAVR:001:%s\n", item_to_name(ritem->type));
7182
7183 #if 0
7184 if (ritem->type == type_route_start && this_->turn_around > -this_->turn_around_limit + 1)
7185 {
7186 this_->turn_around--;
7187 }
7188
7189 if (ritem->type == type_route_start_reverse && this_->turn_around < this_->turn_around_limit)
7190 {
7191 this_->turn_around++;
7192 dbg(0, "NAVR:001.1:** TURN AROUND **\n");
7193 }
7194 #endif
7195
7196 #if 1
7197 if (first_item == 1)
7198 {
7199 first_item = 0;
7200 if (ritem->type == type_route_start_reverse)
7201 {
7202 this_->turn_around = this_->turn_around_limit;
7203
7204 dbg(0, "NAV_TURNAROUND:006 ta=%d talimit=%d\n", this_->turn_around, this_->turn_around_limit);
7205
7206 dbg(0, "NAVR:001.1:T_A:** TURN AROUND **:%s\n", item_to_name(ritem->type));
7207 }
7208 else
7209 {
7210 dbg(0, "NAVR:001.1:T_A:first item=%s\n", item_to_name(ritem->type));
7211 }
7212 }
7213 #endif
7214
7215
7216 dbg(0, "NAVR:001:X1:%s\n", item_to_name(ritem->type));
7217 if ((ritem->type != type_street_route) && (ritem->type != type_street_route_waypoint))
7218 {
7219 dbg(0, "NAVR:001:X2R:%s\n", item_to_name(ritem->type));
7220 continue;
7221 }
7222 dbg(0, "NAVR:001:X3:%s\n", item_to_name(ritem->type));
7223
7224 if (first && item_attr_get(ritem, attr_street_item, &street_item))
7225 {
7226 first = 0;
7227 if (!item_attr_get(ritem, attr_direction, &street_direction))
7228 {
7229 street_direction.u.num = 0;
7230 }
7231
7232 sitem = street_item.u.item;
7233 //dbg(1,"sitem=%p\n", sitem);
7234 itm = item_hash_lookup(this_->hash, sitem);
7235 //dbg(2,"itm for item with id (0x%x,0x%x) is %p\n", sitem->id_hi, sitem->id_lo, itm);
7236
7237 if (itm && itm->way.dir != street_direction.u.num)
7238 {
7239 //dbg(2,"wrong direction\n");
7240 dbg(0, "NAVR:001.2:*+ WRONG DIRECTION +*\n");
7241 itm = NULL;
7242 }
7243
7244 dbg(0, "NCC_:NU:navigation_destroy_itms_cmds\n");
7245 navigation_destroy_itms_cmds(this_, itm);
7246
7247 if (itm)
7248 {
7249 dbg(0, "NCC_:NU:navigation_itm_update\n");
7250
7251 navigation_itm_update(itm, ritem);
7252 break;
7253 }
7254 //dbg(1,"not on track\n");
7255 }
7256
7257 dbg(0, "NAVR:001:X4:%s\n", item_to_name(ritem->type));
7258 dbg(0, "NCC_:NU:navigation_itm_new\n");
7259 navigation_itm_new(this_, ritem);
7260 dbg(0, "NAVR:001:X5:%s\n", item_to_name(ritem->type));
7261
7262 }
7263
7264
7265 dbg(0, "NCC_:NU:------ LOOP END ------\n");
7266
7267
7268 //dbg(2, "turn_around=%d\n", this_->turn_around);
7269
7270 if (first)
7271 {
7272
7273 #ifdef NAVIT_FREE_TEXT_DEBUG_PRINT
7274 dbg(0, "DEST::route_clear_freetext_list\n");
7275 route_clear_freetext_list();
7276 #endif
7277
7278 dbg(0, "NCC_:NU:navigation_destroy_itms_cmds[first]\n");
7279
7280 navigation_destroy_itms_cmds(this_, NULL);
7281 }
7282 else
7283 {
7284 if (!ritem)
7285 {
7286 dbg(0, "NCC_:NU:navigation_itm_new[!ritem]\n");
7287 navigation_itm_new(this_, NULL);
7288 //dbg(0, "Enter: make_maneuvers\n");
7289 dbg(0, "NAVR:001.2:*= MAKE MANEUVERS =*\n");
7290 dbg(0, "NCC_:NU:make_maneuvers[!ritem]\n");
7291 make_maneuvers(this_, this_->route);
7292 //dbg(0, "end : make_maneuvers\n");
7293 }
7294
7295 dbg(0, "NCC_:NU:calculate_dest_distance\n");
7296 calculate_dest_distance(this_, incr);
7297
7298 // calls navit_speak later !! ----------
7299 navigation_call_callbacks(this_, FALSE);
7300 // calls navit_speak later !! ----------
7301 }
7302 map_rect_destroy(mr);
7303
7304 __F_END__
7305 }
7306 // ----------- main place where navigation commands are generated ------------
7307 // ----------- main place where navigation commands are generated ------------
7308 // ----------- main place where navigation commands are generated ------------
7309
7310
7311 static void navigation_flush(struct navigation *this_)
7312 {
7313 __F_START__
7314 navigation_destroy_itms_cmds(this_, NULL);
7315 __F_END__
7316 }
7317
7318 void navigation_destroy(struct navigation *this_)
7319 {
7320 navigation_flush(this_);
7321 item_hash_destroy(this_->hash);
7322 callback_list_destroy(this_->callback);
7323 callback_list_destroy(this_->callback_speech);
7324 g_free(this_);
7325 }
7326
7327 int navigation_register_callback(struct navigation *this_, enum attr_type type, struct callback *cb)
7328 {
7329 __F_START__
7330
7331 if (type == attr_navigation_speech)
7332 {
7333 callback_list_add(this_->callback_speech, cb);
7334 }
7335 else
7336 {
7337 callback_list_add(this_->callback, cb);
7338 }
7339
7340 return2 1;
7341
7342 __F_END__
7343 }
7344
7345 void navigation_unregister_callback(struct navigation *this_, enum attr_type type, struct callback *cb)
7346 {
7347 __F_START__
7348
7349 if (type == attr_navigation_speech)
7350 {
7351 callback_list_remove_destroy(this_->callback_speech, cb);
7352 }
7353 else
7354 {
7355 callback_list_remove_destroy(this_->callback, cb);
7356 }
7357
7358 __F_END__
7359 }
7360
7361 struct map *
7362 navigation_get_map(struct navigation *this_)
7363 {
7364 struct attr *attrs[5];
7365 struct attr type, navigation, data, description;
7366 type.type = attr_type;
7367 type.u.str = "navigation";
7368 navigation.type = attr_navigation;
7369 navigation.u.navigation = this_;
7370 data.type = attr_data;
7371 data.u.str = "";
7372 description.type = attr_description;
7373 description.u.str = "Navigation";
7374
7375 attrs[0] = &type;
7376 attrs[1] = &navigation;
7377 attrs[2] = &data;
7378 attrs[3] = &description;
7379 attrs[4] = NULL;
7380
7381 if (!this_->map)
7382 {
7383 this_->map = map_new(NULL, attrs);
7384 }
7385
7386 return this_->map;
7387 }
7388
7389 struct map_priv
7390 {
7391 struct navigation *navigation;
7392 };
7393
7394 struct map_rect_priv
7395 {
7396 struct navigation *nav;
7397 struct navigation_command *cmd;
7398 struct navigation_command *cmd_next;
7399 struct navigation_itm *itm;
7400 struct navigation_itm *itm_next;
7401 struct navigation_itm *cmd_itm;
7402 struct navigation_itm *cmd_itm_next;
7403 struct item item;
7404 enum attr_type attr_next;
7405 int ccount;
7406 int debug_idx;
7407 struct navigation_way *ways;
7408 int show_all;
7409 char *str;
7410 };
7411
7412 static int navigation_map_item_coord_get(void *priv_data, struct coord *c, int count)
7413 {
7414 struct map_rect_priv *this = priv_data;
7415
7416 if (this->ccount || !count)
7417 {
7418 // dbg(0, "NAVICG:return 001 %d %d\n", this->ccount, count);
7419 return 0;
7420 }
7421
7422 if (this->item.type == type_nav_waypoint)
7423 {
7424 if (this->itm->way.dir == 99)
7425 {
7426 dbg(0, "NAVICG:waypoint:END of seg\n");
7427 *c = this->itm->end;
7428 }
7429 else
7430 {
7431 dbg(0, "NAVICG:waypoint:start of seg\n");
7432 *c = this->itm->start;
7433 }
7434 }
7435 else
7436 {
7437 // dbg(0, "NAVICG:normal type=%s cc=%d\n", item_to_name(this->item.type), this->ccount);
7438 *c = this->itm->start;
7439 }
7440
7441 this->ccount = 1;
7442
7443 return 1;
7444 }
7445
7446 static int navigation_map_item_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
7447 {
7448 struct map_rect_priv *this_ = priv_data;
7449 struct navigation_command *cmd = this_->cmd;
7450 struct navigation_itm *itm = this_->itm;
7451 struct navigation_itm *prev = itm->prev;
7452 attr->type = attr_type;
7453
7454 if (this_->str)
7455 {
7456 g_free(this_->str);
7457 this_->str = NULL;
7458 }
7459
7460 if (cmd)
7461 {
7462 if (cmd->itm != itm)
7463 {
7464 cmd = NULL;
7465 }
7466 }
7467
7468 switch (attr_type)
7469 {
7470 case attr_navigation_short:
7471 this_->attr_next = attr_navigation_long;
7472 if (cmd)
7473 {
7474 //dbg(0, "attr_navigation_short\n");
7475 this_->str = attr->u.str = show_next_maneuvers(this_->nav, this_->cmd_itm, cmd, attr_type);
7476 return 1;
7477 }
7478 return 0;
7479 case attr_navigation_long:
7480 this_->attr_next = attr_navigation_long_exact;
7481 if (cmd)
7482 {
7483 //dbg(0, "attr_navigation_long\n");
7484 this_->str = attr->u.str = show_next_maneuvers(this_->nav, this_->cmd_itm, cmd, attr_type);
7485 return 1;
7486 }
7487 return 0;
7488 case attr_navigation_long_exact:
7489 this_->attr_next = attr_navigation_speech;
7490 if (cmd)
7491 {
7492 //dbg(0, "attr_navigation_long_exact\n");
7493 this_->str = attr->u.str = show_next_maneuvers(this_->nav, this_->cmd_itm, cmd, attr_type);
7494 return 1;
7495 }
7496 return 0;
7497 case attr_navigation_speech:
7498 this_->attr_next = attr_length;
7499 if (cmd)
7500 {
7501 //dbg(0, "attr_navigation_speech\n");
7502 //dbg(0, "Enter: attr_navigation_speech\n");
7503 this_->str = attr->u.str = show_next_maneuvers(this_->nav, this_->cmd_itm, this_->cmd, attr_type);
7504 //dbg(0, "back : attr_navigation_speech\n");
7505 return 1;
7506 }
7507 else if (this_->nav->turn_around_limit && this_->nav->turn_around == this_->nav->turn_around_limit)
7508 {
7509 if (global_turn_around_spoken == 0)
7510 {
7511 this_->str = attr->u.str = g_strdup(_("When possible, please turn around"));
7512 global_turn_around_spoken = 1;
7513 return 1;
7514 }
7515 else
7516 {
7517 return 0;
7518 }
7519 }
7520 return 0;
7521 case attr_length:
7522 this_->attr_next = attr_time;
7523 if (cmd)
7524 {
7525 attr->u.num = this_->cmd_itm->dest_length - cmd->itm->dest_length;
7526 return 1;
7527 }
7528 return 0;
7529 case attr_time:
7530 this_->attr_next = attr_destination_length;
7531 if (cmd)
7532 {
7533 attr->u.num = this_->cmd_itm->dest_time - cmd->itm->dest_time;
7534 return 1;
7535 }
7536 return 0;
7537
7538 case attr_destination_length:
7539 attr->u.num = itm->dest_length;
7540 this_->attr_next = attr_destination_time;
7541 return 1;
7542
7543 case attr_destination_time:
7544 attr->u.num = itm->dest_time;
7545 this_->attr_next = attr_street_name;
7546 return 1;
7547
7548 case attr_street_name:
7549 attr->u.str = itm->way.name1;
7550 this_->attr_next = attr_street_name_systematic;
7551 if (attr->u.str)
7552 return 1;
7553 return 0;
7554
7555 case attr_street_name_systematic:
7556 attr->u.str = itm->way.name2;
7557 this_->attr_next = attr_street_destination;
7558 if (attr->u.str)
7559 return 1;
7560 return 0;
7561
7562 case attr_street_destination:
7563 attr->u.str = itm->way.street_dest_text;
7564 this_->attr_next = attr_debug;
7565 if (attr->u.str)
7566 {
7567 return 1;
7568 }
7569 return 0;
7570
7571 case attr_debug:
7572 switch (this_->debug_idx)
7573 {
7574 case 0:
7575 this_->debug_idx++;
7576 this_->str = attr->u.str = g_strdup_printf("angle:%d (- %d)", itm->way.angle2, itm->angle_end);
7577 return 1;
7578 case 1:
7579 this_->debug_idx++;
7580 this_->str = attr->u.str = g_strdup_printf("item type:%s", item_to_name(itm->way.item.type));
7581 return 1;
7582 case 2:
7583 this_->debug_idx++;
7584 if (cmd)
7585 {
7586 this_->str = attr->u.str = g_strdup_printf("delta:%d", cmd->delta);
7587 return 1;
7588 }
7589 case 3:
7590 this_->debug_idx++;
7591 if (prev)
7592 {
7593 this_->str = attr->u.str = g_strdup_printf("prev street_name:%s", prev->way.name1);
7594 return 1;
7595 }
7596 case 4:
7597 this_->debug_idx++;
7598 if (prev)
7599 {
7600 this_->str = attr->u.str = g_strdup_printf("prev street_name_systematic:%s", prev->way.name2);
7601 return 1;
7602 }
7603 case 5:
7604 this_->debug_idx++;
7605 if (prev)
7606 {
7607 this_->str = attr->u.str = g_strdup_printf("prev angle:(%d -) %d", prev->way.angle2, prev->angle_end);
7608 return 1;
7609 }
7610 case 6:
7611 this_->debug_idx++;
7612 this_->ways = itm->way.next;
7613 if (prev)
7614 {
7615 this_->str = attr->u.str = g_strdup_printf("prev item type:%s", item_to_name(prev->way.item.type));
7616 return 1;
7617 }
7618 case 7:
7619 if (this_->ways && prev)
7620 {
7621 this_->str = attr->u.str = g_strdup_printf("other item angle:%d delta:%d flags:%d dir:%d type:%s id:(0x%x,0x%x)", this_->ways->angle2, angle_delta(prev->angle_end, this_->ways->angle2), this_->ways->flags, this_->ways->dir, item_to_name(this_->ways->item.type), this_->ways->item.id_hi, this_->ways->item.id_lo);
7622 this_->ways = this_->ways->next;
7623 return 1;
7624 }
7625 this_->debug_idx++;
7626 case 8:
7627 this_->debug_idx++;
7628 if (prev)
7629 {
7630 int delta = 0;
7631 int delta_real = 0;
7632 char *reason = NULL;
7633 maneuver_required2(this_->nav, prev, itm, &delta, &delta_real, &reason);
7634 this_->str = attr->u.str = g_strdup_printf("reason:%s", reason);
7635 return 1;
7636 }
7637
7638 default:
7639 this_->attr_next = attr_none;
7640 return 0;
7641 }
7642
7643 case attr_any:
7644 while (this_->attr_next != attr_none)
7645 {
7646 if (navigation_map_item_attr_get(priv_data, this_->attr_next, attr))
7647 return 1;
7648 }
7649 return 0;
7650
7651 default:
7652 attr->type = attr_none;
7653 return 0;
7654 }
7655 }
7656
7657 static struct item_methods navigation_map_item_methods = { NULL, navigation_map_item_coord_get, NULL, navigation_map_item_attr_get, };
7658
7659 static void navigation_map_destroy(struct map_priv *priv)
7660 {
7661 g_free(priv);
7662 }
7663
7664 static void navigation_map_rect_init(struct map_rect_priv *priv)
7665 {
7666 priv->cmd_next = priv->nav->cmd_first;
7667 priv->cmd_itm_next = priv->itm_next = priv->nav->first;
7668 }
7669
7670 static struct map_rect_priv *
7671 navigation_map_rect_new(struct map_priv *priv, struct map_selection *sel)
7672 {
7673 struct navigation *nav = priv->navigation;
7674 struct map_rect_priv *ret=g_new0(struct map_rect_priv, 1);
7675 ret->nav = nav;
7676
7677 navigation_map_rect_init(ret);
7678
7679 ret->item.meth = &navigation_map_item_methods;
7680 ret->item.priv_data = ret;
7681
7682 #ifdef DEBUG
7683 ret->show_all=1;
7684 #endif
7685
7686 return ret;
7687 }
7688
7689 static void navigation_map_rect_destroy(struct map_rect_priv *priv)
7690 {
7691 g_free(priv);
7692 }
7693
7694
7695
7696 void navigation_dump_items(struct navigation *this_)
7697 {
7698 if (this_->first)
7699 {
7700 dbg(0, "NAVR:dump:=================++++++++++++================\n");
7701 struct navigation_itm *i;
7702 int count = 0;
7703
7704 i = this_->first;
7705 while (i)
7706 {
7707 count++;
7708 i = i->next;
7709 }
7710
7711 i = this_->first;
7712 while (i)
7713 {
7714 count--;
7715 dbg(0, "NAVR:dump:count=%d %p %d\n", count, i, i->way.dir);
7716 i = i->next;
7717 }
7718 dbg(0, "NAVR:dump:=================++++++++++++================\n");
7719 }
7720 }
7721
7722
7723 // -----------------------------------
7724 static int save_last_dest_count = -1;
7725 // -----------------------------------
7726
7727 static struct item *
7728 navigation_map_get_item(struct map_rect_priv *priv)
7729 {
7730 struct item *ret = &priv->item;
7731 int delta;
7732
7733 int fake_dir1;
7734 int fake_dir2;
7735
7736 dbg(0, "NAVR:ROUTE:Enter:\n");
7737 dbg(0, "NAVR:ROUTE:Enter:------------------------\n");
7738
7739 if (!priv->itm_next)
7740 {
7741 dbg(0, "NAVR:ROUTE:006:0000\n");
7742 return NULL;
7743 }
7744
7745 int stepped_to_waypoint = 0;
7746
7747 // now check if we missed a waypoint, if so -> move back to waypoint -------------------------
7748 if (priv->itm)
7749 {
7750 if (save_last_dest_count != -1)
7751 {
7752 int count_back = (save_last_dest_count - priv->itm->dest_count - 1);
7753 int count_forw = count_back;
7754 dbg(0, "NAVR:ROUTE:006:cback:%d = (%d - %d - 1)\n", count_back, save_last_dest_count, priv->itm->dest_count);
7755
7756 struct navigation_itm *i = priv->itm;
7757
7758 // go to first item to check
7759 while (count_back > 0)
7760 {
7761 count_back--;
7762 if (i->prev)
7763 {
7764 i = i->prev;
7765 dbg(0, "NAVR:ROUTE:006:cback:stepping back to item #%d dir=%d\n", i->dest_count, i->way.dir);
7766 }
7767 }
7768
7769 // now step forward until waypoint found, or just skip the whole thing if we dont find any waypoint
7770 while (count_forw > 0)
7771 {
7772 if (i)
7773 {
7774 dbg(0, "NAVR:ROUTE:006:cback:stepping forw to item #%d dir=%d\n", i->dest_count, i->way.dir);
7775
7776 if ((i->way.dir == 99) || (i->way.dir == -99))
7777 {
7778 // found a waypoint
7779 priv->itm = i;
7780 stepped_to_waypoint = 1;
7781
7782 dbg(0, "NAVR:ROUTE:006:cback:stepping found waypoint item #%d dir=%d itm=%p\n", priv->itm->dest_count, priv->itm->way.dir, priv->itm);
7783
7784 break;
7785 }
7786
7787 count_forw--;
7788 if (i->next)
7789 {
7790 i = i->next;
7791 }
7792 }
7793 }
7794
7795 }
7796 }
7797 // now check if we missed a waypoint, if so -> move back to waypoint -------------------------
7798
7799
7800 if (priv->itm)
7801 {
7802 dbg(0, "NAVR:ROUTE:006:8888:1: %p dir=%d DST_COUNT(1)=%d\n", priv->itm, priv->itm->way.dir, priv->itm->dest_count);
7803 fake_dir1 = priv->itm->way.dir;
7804 save_last_dest_count = priv->itm->dest_count;
7805 }
7806 else
7807 {
7808 dbg(0, "NAVR:ROUTE:006:8888:1: NULL\n");
7809 fake_dir1 = 0;
7810 save_last_dest_count = -1;
7811 }
7812
7813 if (stepped_to_waypoint != 1)
7814 {
7815 priv->itm = priv->itm_next;
7816 }
7817
7818
7819 fake_dir2 = priv->itm->way.dir;
7820 dbg(0, "NAVR:ROUTE:006:8888:2: %p dir=%d DST_COUNT(2)=%d\n", priv->itm, priv->itm->way.dir, priv->itm->dest_count);
7821 priv->cmd = priv->cmd_next;
7822 priv->cmd_itm = priv->cmd_itm_next;
7823
7824 if ((priv->itm->way.dir == 99) || (priv->itm->way.dir == -99))
7825 {
7826 // return fake waypoint item!! ---------
7827 ret->type = type_nav_waypoint;
7828 ret->id_lo = priv->itm->dest_count;
7829 priv->ccount = 0;
7830
7831 priv->itm_next = priv->itm->next;
7832
7833 dbg(0, "NAVR:ROUTE:006:fake:%s dir=%d ,,,,,\n", item_to_name(ret->type), priv->itm->way.dir);
7834
7835 return ret;
7836 }
7837
7838
7839
7840 // navigation_dump_items(priv->nav);
7841
7842 if (!priv->cmd)
7843 {
7844 dbg(0, "NAVR:ROUTE:006:1111\n");
7845 return NULL;
7846 }
7847
7848
7849 if (!priv->show_all && priv->itm->prev != NULL)
7850 {
7851 dbg(0, "NAVR:ROUTE:006:112a\n");
7852 priv->itm = priv->cmd->itm;
7853 }
7854
7855 priv->itm_next = priv->itm->next;
7856
7857 if (priv->itm->prev)
7858 {
7859 ret->type = type_nav_none;
7860 }
7861 else
7862 {
7863 ret->type = type_nav_position;
7864 }
7865
7866 dbg(0, "NAVR:ROUTE:006:2222 %p dir=%d\n", priv->itm, priv->itm->way.dir);
7867
7868 if (priv->cmd->itm == priv->itm)
7869 {
7870
7871 dbg(0, "NAVR:ROUTE:006:3333 %p dir=%d %p\n", priv->itm, priv->itm->way.dir, route_get_map(global_navit->route));
7872 // item_dump_coords(priv->itm, route_get_map(global_navit->route));
7873
7874 priv->cmd_itm_next = priv->cmd->itm;
7875 priv->cmd_next = priv->cmd->next;
7876
7877 if (priv->cmd_itm_next && !priv->cmd_itm_next->next)
7878 {
7879 ret->type = type_nav_destination;
7880 }
7881 else
7882 {
7883 if (priv->itm && priv->itm->prev && !(priv->itm->way.flags & NAVIT_AF_ROUNDABOUT) && (priv->itm->prev->way.flags & NAVIT_AF_ROUNDABOUT))
7884 {
7885 enum item_type r = type_none, l = type_none;
7886 switch (((180 + 22) - priv->cmd->roundabout_delta) / 45)
7887 {
7888 case 0:
7889 case 1:
7890 r = type_nav_roundabout_r1;
7891 l = type_nav_roundabout_l7;
7892 break;
7893 case 2:
7894 r = type_nav_roundabout_r2;
7895 l = type_nav_roundabout_l6;
7896 break;
7897 case 3:
7898 r = type_nav_roundabout_r3;
7899 l = type_nav_roundabout_l5;
7900 break;
7901 case 4:
7902 r = type_nav_roundabout_r4;
7903 l = type_nav_roundabout_l4;
7904 break;
7905 case 5:
7906 r = type_nav_roundabout_r5;
7907 l = type_nav_roundabout_l3;
7908 break;
7909 case 6:
7910 r = type_nav_roundabout_r6;
7911 l = type_nav_roundabout_l2;
7912 break;
7913 case 7:
7914 r = type_nav_roundabout_r7;
7915 l = type_nav_roundabout_l1;
7916 break;
7917 case 8:
7918 r = type_nav_roundabout_r8;
7919 l = type_nav_roundabout_l8;
7920 break;
7921 }
7922 // dbg(0, "delta %d\n", priv->cmd->delta);
7923
7924 if (priv->cmd->delta < 0)
7925 {
7926 ret->type = l;
7927 }
7928 else
7929 {
7930 ret->type = r;
7931 }
7932 }
7933 else
7934 {
7935 delta = priv->cmd->delta;
7936 if (delta < 0)
7937 {
7938 delta = -delta;
7939 if (delta < 45)
7940 ret->type = type_nav_left_1;
7941 else if (delta < 105)
7942 ret->type = type_nav_left_2;
7943 else if (delta < 165)
7944 ret->type = type_nav_left_3;
7945 else
7946 ret->type = type_none;
7947 }
7948 else if (delta > 0)
7949 {
7950 if (delta < 45)
7951 ret->type = type_nav_right_1;
7952 else if (delta < 105)
7953 ret->type = type_nav_right_2;
7954 else if (delta < 165)
7955 ret->type = type_nav_right_3;
7956 else
7957 ret->type = type_none;
7958 }
7959 else // delta == 0
7960 {
7961 ret->type = type_nav_straight;
7962 }
7963 }
7964 }
7965 }
7966
7967 priv->ccount = 0;
7968 priv->debug_idx = 0;
7969 priv->attr_next = attr_navigation_short;
7970
7971 ret->id_lo = priv->itm->dest_count;
7972
7973 // dbg(0, "NAVR:ROUTE:006:%s ,,,,, ta=%d talim=%d\n", item_to_name(ret->type), priv->nav->turn_around, priv->nav->turn_around_limit);
7974
7975
7976 // check for "turn around" and return "type_nav_turnaround" !! ---------------
7977 if ((priv->nav->turn_around && priv->nav->turn_around == priv->nav->turn_around_limit) && (ret->type == type_nav_position))
7978 {
7979 // dbg(0, "priv->itm->dest_count=%d\n", priv->itm->dest_count);
7980 ret->type = type_nav_turnaround_right;
7981 }
7982 // check for "turn around" and return "type_nav_turnaround" !! ---------------
7983
7984 // dbg(0, "NAVR:ROUTE:007a:%s ,,,,, priv->itm->dest_count=%d\n", item_to_name(ret->type), priv->itm->dest_count);
7985
7986 return ret;
7987 }
7988
7989 static struct item *
7990 navigation_map_get_item_byid(struct map_rect_priv *priv, int id_hi, int id_lo)
7991 {
7992 struct item *ret;
7993 navigation_map_rect_init(priv);
7994 while ((ret = navigation_map_get_item(priv)))
7995 {
7996 if (ret->id_hi == id_hi && ret->id_lo == id_lo)
7997 return ret;
7998 }
7999 return NULL;
8000 }
8001
8002 static struct map_methods navigation_map_meth = { projection_mg, "utf-8", navigation_map_destroy, navigation_map_rect_new, navigation_map_rect_destroy, navigation_map_get_item, navigation_map_get_item_byid, NULL, NULL, NULL, };
8003
8004 struct map_priv *
8005 navigation_map_new(struct map_methods *meth, struct attr **attrs, struct callback_list *cbl)
8006 {
8007 struct map_priv *ret;
8008 struct attr *navigation_attr;
8009
8010 navigation_attr = attr_search(attrs, NULL, attr_navigation);
8011
8012 if (!navigation_attr)
8013 {
8014 return NULL;
8015 }
8016
8017 ret=g_new0(struct map_priv, 1);
8018 *meth = navigation_map_meth;
8019 ret->navigation = navigation_attr->u.navigation;
8020
8021 level_static_for_bicycle[0] = 22; // in meters
8022 level_static_for_bicycle[1] = 100; // in meters
8023 level_static_for_bicycle[2] = -1; // dont announce
8024
8025 return ret;
8026 }
8027
8028 void navigation_set_route(struct navigation *this_, struct route *route)
8029 {
8030 __F_START__
8031
8032 struct attr callback;
8033 this_->route = route;
8034 this_->route_cb = callback_new_attr_1(callback_cast(navigation_update), attr_route_status, this_);
8035 callback_add_names(this_->route_cb, "navigation_set_route", "navigation_update");
8036 callback.type = attr_callback;
8037 callback.u.callback = this_->route_cb;
8038 route_add_attr(route, &callback);
8039
8040 __F_END__
8041 }
8042
8043 void navigation_init(void)
8044 {
8045 #ifdef PLUGSSS
8046 plugin_register_map_type("navigation", navigation_map_new);
8047 #endif
8048 }
8049
8050

   
Visit the ZANavi Wiki