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

Contents of /navit/navit/navigation.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 56 - (show annotations) (download)
Sun Mar 19 08:44:36 2017 UTC (7 years ago) by zoff99
File MIME type: text/plain
File size: 205756 byte(s)
updates
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 NULL;
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 NULL;
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 NULL;
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
3250 //UNIT_TESTS_001_PATTERN_START
3251 static int maneuver_required2(struct navigation *nav, struct navigation_itm *old, struct navigation_itm *new, int *delta, int *delta_real, char **reason)
3252 {
3253
3254 int ret = 0, d, dw, dlim;
3255 char *r = NULL;
3256 struct navigation_way *w = NULL;
3257 int cat, ncat, wcat, maxcat, left = -180, right = 180, is_unambigous = 0, is_same_street;
3258 int cat_2 = 0;
3259 int ncat_2 = 0;
3260 int highest_other_cat = 0;
3261 int original_d = 0;
3262
3263 dbg(0, "STRAI:000:\n");
3264 dbg(0, "STRAI:000:======================================\n");
3265
3266 tests_dbg(0, "\n=== maneuver_required2 [ENTER] ===");
3267
3268 // ---------------------------
3269 //
3270 // HINT: angle < 0 --> left
3271 // > 0 --> right
3272 // = 0 --> straight
3273 //
3274 // ---------------------------
3275
3276 d = angle_delta(old->angle_end, new->way.angle2);
3277 original_d = d;
3278
3279
3280 #ifdef _CIDEBUG_BUILD_
3281 tests_dbg(0, "angle<0 : left");
3282 struct coord_geo g22;
3283 transform_to_geo(projection_mg, &old->end, &g22);
3284 tests_dbg(0, "http://www.openstreetmap.org/search?query=%f %f#map=19/%f/%f", g22.lat, g22.lng, g22.lat, g22.lng);
3285
3286 tests_dbg(0, "delta=%d delta_real=%d d=%d", *delta, *delta_real, d);
3287 tests_dbg(0, "old->angle_end=%d new->way.angle2=%d", old->angle_end, new->way.angle2);
3288 tests_dbg(0, "from type=%s", item_to_name(old->way.item.type));
3289 tests_dbg(0, "to type=%s", item_to_name(new->way.item.type));
3290 #endif
3291
3292
3293 //long long wayid_old = navigation_item_get_wayid(&(old->way));
3294 //long long wayid_new = navigation_item_get_wayid(&(new->way));
3295 //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);
3296
3297 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2)) // bicycle mode
3298 {
3299 int flags_old = navigation_item_get_flags(&(old->way));
3300 int flags_new = navigation_item_get_flags(&(new->way));
3301
3302 //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);
3303 //dbg(0, "(b2)old flags=%x new flags=%x\n", (flags_old & NAVIT_AF_ONEWAY), (flags_new & NAVIT_AF_ONEWAY));
3304 //dbg(0, "(b3)old flags=%x new flags=%x\n", (flags_old & NAVIT_AF_ONEWAYREV), (flags_new & NAVIT_AF_ONEWAYREV));
3305
3306 if ((old->way.dir == 1) && ((new->way.dir == -1) && (new->way.flags & NAVIT_AF_ONEWAY_BICYCLE_NO)))
3307 {
3308 r = "yes: bicycle starts going against oneway here (1)";
3309 tests_dbg(0, "yes: bicycle starts going against oneway here (1)");
3310 ret = 1;
3311 //dbg(0, "%s\n", r);
3312 }
3313 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)))
3314 {
3315 r = "yes: bicycle starts going against oneway here (2)";
3316 ret = 1;
3317 //dbg(0, "%s\n", r);
3318 }
3319 }
3320
3321
3322
3323
3324 // z2z2
3325 int have_more_than_one_way_to_turn = 0;
3326 int have_more_than_one_way_to_turn_cycleways = 0;
3327 struct navigation_way *w22;
3328 w22 = new->way.next;
3329 int new_angle_abs = 999;
3330 int new_angle_abs_min = 999;
3331 int new_angle_abs_min_allowed = 999;
3332 int new_angle_real = 999;
3333 int new_angle_min_allowed = 999;
3334 int new_angle_abs_min_ramp_allowed = 999;
3335 int old_angle_abs = abs(d);
3336 int new_angle_closest_to_cur = 999;
3337 int no_correction = 0;
3338
3339 dbg(0, "STRAI:001:d=%d original_d=%d\n", old_angle_abs, original_d);
3340 tests_dbg(0, "STRAI:001:d=%d original_d=%d", old_angle_abs, original_d);
3341
3342 tests_dbg(0, "\n-- other ways START --");
3343
3344 while (w22)
3345 {
3346
3347 dbg(0, "STRAI:002\n");
3348
3349 //if ((w22->dir == -1) && (w22->flags & NAVIT_AF_ONEWAY))
3350 //{
3351 // // against oneway not allowed
3352 //}
3353 if (((global_vehicle_profile != 1) && (global_vehicle_profile != 2)) // NOT bicycle mode
3354 && (navigation_is_low_level_street(old->way.item.type) == 0)
3355 && (navigation_is_low_level_street(new->way.item.type) == 0)
3356 && (navigation_is_low_level_street(w22->item.type) == 1))
3357 {
3358 // dont count "lower" streets when not on "lower" street now or next
3359 }
3360 else
3361 {
3362
3363 if ( (is_maybe_same_item(&(new->way), w22, 0) == 0) && (is_maybe_same_item(&(old->way), w22, 1) == 0) )
3364 {
3365
3366 new_angle_real = angle_delta(old->angle_end, w22->angle2);
3367 new_angle_abs = abs(new_angle_real);
3368 if (new_angle_abs < new_angle_abs_min)
3369 {
3370 new_angle_abs_min = new_angle_abs;
3371 }
3372
3373 tests_dbg(0, "new_angle_real=%d new_angle_abs=%d is allowed=%d", new_angle_real, new_angle_abs, is_way_allowed(nav, w22, 1));
3374 tests_dbg(0, "old->angle_end=%d w22->angle2=%d", old->angle_end, w22->angle2);
3375 tests_dbg(0, "new_angle_abs_min=%d", new_angle_abs_min);
3376 tests_dbg(0, "other type=%s is_ramp=%d", item_to_name(w22->item.type), item_is_ramp(w22->item));
3377
3378 if (is_way_allowed(nav, w22, 1))
3379 {
3380 have_more_than_one_way_to_turn = 1;
3381
3382 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2)) // bicycle mode
3383 {
3384 if (w22->item.type == type_cycleway)
3385 {
3386 have_more_than_one_way_to_turn_cycleways = 1;
3387 }
3388 }
3389
3390 if (maneuver_category_calc2(w22->item.type) > highest_other_cat)
3391 {
3392 highest_other_cat = maneuver_category_calc2(w22->item.type);
3393 }
3394
3395 if (item_is_ramp(w22->item))
3396 {
3397 if (new_angle_abs < new_angle_abs_min_ramp_allowed)
3398 {
3399 new_angle_abs_min_ramp_allowed = new_angle_abs;
3400 }
3401 }
3402
3403 if (abs(new_angle_real - d) < abs(new_angle_closest_to_cur))
3404 {
3405 new_angle_closest_to_cur = new_angle_real;
3406 }
3407
3408 if (new_angle_abs < new_angle_abs_min_allowed)
3409 {
3410 new_angle_abs_min_allowed = new_angle_abs;
3411 new_angle_min_allowed = new_angle_real;
3412 }
3413 }
3414
3415 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);
3416
3417 tests_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", new_angle_abs, new_angle_abs_min_allowed, have_more_than_one_way_to_turn, new_angle_closest_to_cur, d);
3418
3419
3420 }
3421 }
3422 w22 = w22->next;
3423 }
3424
3425 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);
3426 tests_dbg(0, "STRAI:004 new_angle_abs_min=%d new_angle_abs_min_allowed=%d", new_angle_abs_min, new_angle_abs_min_allowed);
3427
3428 tests_dbg(0, "-- other ways END --\n");
3429
3430
3431 if ((new_angle_abs_min_allowed > ROAD_ANGLE_IS_STRAIGHT_ABS) && (old_angle_abs <= ROAD_ANGLE_IS_STRAIGHT_ABS))
3432 {
3433 dbg(0, "STRAI:005 new_abs=%d old_abs=%d\n", new_angle_abs_min_allowed, old_angle_abs);
3434 tests_dbg(0, "we want to drive almost straight, set angle to 0");
3435 // we want to drive almost straight, set angle to "0"
3436 d = 0;
3437 }
3438
3439 dbg(0, "STRAI:005a:d=%d\n", d);
3440 tests_dbg(0, "STRAI:005a:d=%d", d);
3441
3442 if (!r)
3443 {
3444 if (have_more_than_one_way_to_turn == 1) // more than 1 possibility
3445 {
3446 if (new->way.exit_label)
3447 {
3448 // highway to highway, nearest ramp is more than 15° angle turn
3449 if ( (cat > 6) && (ncat > 6) && (highest_other_cat <= 6) && (abs(d) < 12) && (new_angle_abs_min_ramp_allowed > 15) )
3450 {
3451 dbg(0, "STRAI:005a:d=%d\n", d);
3452 r = "no: driving almost straight on highway and no other highway possibilities (1)";
3453 tests_dbg(0, "no: STRAI:005a: driving almost straight on highway and no other highway possibilities (1)");
3454 }
3455 else
3456 {
3457 // r = "yes: we have an exit-sign to tell the user";
3458 // ret = 1;
3459 }
3460 }
3461 else if (new->way.s_destination)
3462 {
3463 if ( (cat > 6) && (ncat > 6) && (highest_other_cat <= 6) && (abs(d) < 12) && (new_angle_abs_min_ramp_allowed > 15) )
3464 {
3465 dbg(0, "STRAI:005a:d=%d\n", d);
3466 r = "no: driving almost straight on highway and no other highway possibilities (2)";
3467 tests_dbg(0, "no: STRAI:005a: driving almost straight on highway and no other highway possibilities (2)");
3468 }
3469 else
3470 {
3471 // r = "yes: we have a road-sign to tell the user";
3472 // ret = 1;
3473 }
3474 }
3475 else if (item_is_ramp(old->way.item))
3476 {
3477 r = "yes: we are currently on a ramp and have more than 1 road to take";
3478 tests_dbg(0, "yes: 001: we are currently on a ramp and have more than 1 road to take");
3479 ret = 1;
3480 }
3481 }
3482 }
3483
3484
3485 if ((global_vehicle_profile != 1) && (global_vehicle_profile != 2))
3486 {
3487 if (!new->way.next)
3488 {
3489 /* No announcement necessary */
3490 r = "no: Only one possibility";
3491 tests_dbg(0, "no: 002: Only one possibility");
3492 }
3493 else if (!new->way.next->next && item_is_ramp(new->way.next->item) && !is_way_allowed(nav, new->way.next, 1))
3494 {
3495 /* If the other way is only a ramp and it is one-way in the wrong direction, no announcement necessary */
3496 r = "no: Only ramp";
3497 tests_dbg(0, "no: 003: Only ramp");
3498 }
3499 }
3500 else // bicycle mode --------------------
3501 {
3502 if (!r)
3503 {
3504 #if 0
3505 if ((!new->way.next) && (abs(d) < 20))
3506 {
3507 /* No announcement necessary */
3508 r = "no: Only one possibility and less than 20° turn";
3509 tests_dbg(0, "no: 004: Only one possibility and less than 20° turn");
3510 dbg(0, "%s\n", r);
3511 }
3512 else
3513 {
3514 if (abs(d) > 2)
3515 {
3516 r = "yes: bicycle mode";
3517 dbg(0, "%s\n", r);
3518 ret = 1;
3519 }
3520 else
3521 {
3522 r = "no: less than 3° turn";
3523 dbg(0, "%s\n", r);
3524 }
3525 }
3526 #endif
3527
3528 #if 0
3529 if (!new->way.next)
3530 {
3531 /* No announcement necessary */
3532 r = "no: Only one possibility";
3533 }
3534 #endif
3535
3536 #if 1
3537
3538 if ((old->way.item.type == type_cycleway) && (new->way.item.type == type_cycleway))
3539 {
3540 if (have_more_than_one_way_to_turn_cycleways == 0)
3541 {
3542 if (abs(d) > ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE_CYC_2_CYC)
3543 {
3544 r = "yes: delta over ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE_CYC_2_CYC in bicycle mode (Only one possibility cyc-2-cyc)";
3545 //dbg(0, "%s\n", r);
3546 ret = 1;
3547 }
3548 else
3549 {
3550 r = "no: delta less than ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE_CYC_2_CYC in bicycle mode (Only one possibility cyc-2-cyc)";
3551 //dbg(0, "%s\n", r);
3552 ret = 0;
3553 }
3554 }
3555 else
3556 {
3557 if (abs(d) > ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE_CYC_2_CYC__2)
3558 {
3559 r = "yes: delta over ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE_CYC_2_CYC__2 in bicycle mode (cyc-2cyc)";
3560 //dbg(0, "%s\n", r);
3561 ret = 1;
3562 }
3563 else
3564 {
3565 r = "no: delta less than ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE_CYC_2_CYC__2 in bicycle mode (cyc-2cyc)";
3566 //dbg(0, "%s\n", r);
3567 ret = 0;
3568 }
3569 }
3570 }
3571 else
3572 {
3573
3574 if (!new->way.next)
3575 {
3576 if (abs(d) > ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE)
3577 {
3578 r = "yes: delta over ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE in bicycle mode (Only one possibility)";
3579 //dbg(0, "%s\n", r);
3580 ret = 1;
3581 }
3582 else
3583 {
3584 r = "no: delta less than ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE in bicycle mode (Only one possibility)";
3585 //dbg(0, "%s\n", r);
3586 ret = 0;
3587 }
3588 }
3589 else
3590 {
3591 if (abs(d) > ROAD_ANGLE_MIN__FOR_TURN_BICYCLEMODE_ONLY_1_POSSIBILITY)
3592 {
3593 r = "yes: delta over ROAD_ANGLE_MIN__FOR_TURN_BICYCLEMODE_ONLY_1_POSSIBILITY in bicycle mode";
3594 //dbg(0, "%s\n", r);
3595 ret = 1;
3596 }
3597 else
3598 {
3599 r = "no: delta less than ROAD_ANGLE_MIN__FOR_TURN_BICYCLEMODE_ONLY_1_POSSIBILITY in bicycle mode";
3600 //dbg(0, "%s\n", r);
3601 ret = 0;
3602 }
3603 }
3604
3605 }
3606 #endif
3607
3608 }
3609 }
3610
3611 if (!r)
3612 {
3613 if ((old->way.flags & NAVIT_AF_ROUNDABOUT) && !(new->way.flags & NAVIT_AF_ROUNDABOUT))
3614 {
3615 r = "yes: leaving roundabout";
3616 tests_dbg(0, "yes: 005: leaving roundabout");
3617 ret = 1;
3618 }
3619 else if (!(old->way.flags & NAVIT_AF_ROUNDABOUT) && (new->way.flags & NAVIT_AF_ROUNDABOUT))
3620 {
3621 r = "no: entering roundabout";
3622 tests_dbg(0, "no: 006: entering roundabout");
3623 }
3624 else if ((old->way.flags & NAVIT_AF_ROUNDABOUT) && (new->way.flags & NAVIT_AF_ROUNDABOUT))
3625 {
3626 r = "no: staying in roundabout";
3627 tests_dbg(0, "no: 007: staying in roundabout");
3628 }
3629 }
3630
3631 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
3632 {
3633 if (!r && abs(d) > ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE)
3634 {
3635 /* always make an announcement if you have to make a turn */
3636 r = "yes: delta over ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE in bicycle mode";
3637 //dbg(0, "%s\n", r);
3638 ret = 1;
3639 }
3640 }
3641 else // car mode ---------------------
3642 {
3643 if (!r && abs(d) > 75)
3644 {
3645 /* always make an announcement if you have to make a sharp turn */
3646 r = "yes: delta over 75";
3647 tests_dbg(0, "yes: 008: delta over 75");
3648 ret = 1;
3649 }
3650 }
3651
3652 cat = maneuver_category(old->way.item.type);
3653 ncat = maneuver_category(new->way.item.type);
3654
3655 cat_2 = maneuver_category_calc2(old->way.item.type);
3656 ncat_2 = maneuver_category_calc2(new->way.item.type);
3657
3658
3659 if (!r)
3660 {
3661 /* Check whether the street keeps its name */
3662 is_same_street = is_same_street2(old->way.name1, old->way.name2, new->way.name1, new->way.name2);
3663
3664 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);
3665
3666 w = new->way.next;
3667 maxcat = -1;
3668 while (w)
3669 {
3670 if ( (is_maybe_same_item(&(new->way), w, 0) == 0) && (is_maybe_same_item(&(old->way), w, 1) == 0) )
3671 {
3672 dw = angle_delta(old->angle_end, w->angle2);
3673 dbg(0, "STRAI:011.02 dw=%d l=%d r=%d\n", dw, left, right);
3674
3675 if (dw < 0)
3676 {
3677 if (dw > left)
3678 {
3679 left = dw;
3680 }
3681 }
3682 else
3683 {
3684 if (dw < right)
3685 {
3686 right = dw;
3687 }
3688 }
3689
3690 wcat = maneuver_category(w->item.type);
3691 dbg(0, "STRAI:011.03 wcat=%d\n", wcat);
3692
3693 /* If any other street has the same name [ removed:"but isn't a highway (a highway might split up temporarily)" ], then
3694 we can't use the same name criterium */
3695 // 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))
3696 if (is_same_street && is_same_street2(old->way.name1, old->way.name2, w->name1, w->name2) && is_way_allowed(nav, w, 2))
3697 {
3698 is_same_street = 0;
3699 dbg(0, "STRAI:011.04 is_same_street=%d\n", is_same_street);
3700 }
3701
3702 /* Mark if the street has a higher or the same category */
3703 if (wcat > maxcat)
3704 {
3705 maxcat = wcat;
3706 dbg(0, "STRAI:011.06 maxcat=%d wcat=%d\n", maxcat, wcat);
3707 }
3708
3709 }
3710
3711 w = w->next;
3712 }
3713
3714 if (have_more_than_one_way_to_turn == 1) // more than 1 possibility
3715 {
3716 /* Even if the ramp has the same name, announce it */
3717 if (item_is_ramp(new->way.item) && !item_is_ramp(old->way.item))
3718 {
3719 is_same_street = 0;
3720 dbg(0, "STRAI:011.05.xx is_same_street=%d\n", is_same_street);
3721 }
3722 }
3723
3724 /* get the delta limit for checking for other streets. It is lower if the street has no other
3725 streets of the same or higher category */
3726 if (ncat < cat)
3727 {
3728 dlim = 80;
3729 }
3730 else
3731 {
3732 dlim = 120;
3733 }
3734
3735 /* if the street is really straight, the others might be closer to straight */
3736 if (abs(d) < 20)
3737 {
3738 dlim /= 2;
3739 }
3740
3741 if ((maxcat == ncat && maxcat == cat) || (ncat == 0 && cat == 0))
3742 {
3743 dlim = abs(d) * (620 / 256); // abs(d) * 2.4
3744 }
3745 else if (maxcat < ncat && maxcat < cat)
3746 {
3747 dlim = abs(d) * (128 / 256); // abs(d) * 0.5
3748 }
3749
3750 if (left < -dlim && right > dlim) // no other road is between -dlim : dlim angle (no other road is "dlim" close to straight)
3751 {
3752 is_unambigous = 1;
3753 }
3754
3755 if (!is_same_street && is_unambigous < 1)
3756 {
3757 ret = 1;
3758 r = "yes: (not same street) or (ambigous [nicht eindeutig])";
3759 tests_dbg(0, "yes: 009: (not same street) or (ambigous [nicht eindeutig])");
3760 }
3761 else
3762 {
3763 r = "no: (same street) and (unambigous [eindeutig])";
3764 tests_dbg(0, "no: 010: (same street) and (unambigous [eindeutig])");
3765 }
3766
3767 if (ret == 0)
3768 {
3769 tests_dbg(0, "enter: ret==0");
3770
3771 // add a new check here:
3772 if (have_more_than_one_way_to_turn == 1)
3773 {
3774 tests_dbg(0, "have_more_than_one_way_to_turn == 1");
3775
3776 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);
3777
3778 if ( (cat > 6) && (ncat > 6) && (highest_other_cat <= 6) && (abs(d) < 70) )
3779 {
3780 r = "no: from highway to highway (no other highway possibilities)";
3781 tests_dbg(0, "no: 011: from highway to highway (no other highway possibilities)");
3782 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);
3783 }
3784 else
3785 {
3786
3787 if ((ncat == 6) && (highest_other_cat == 6) && (abs(d) < 50) && (abs(new_angle_closest_to_cur - original_d) < 65))
3788 {
3789 ret = 1;
3790 r = "yes: we are driving onto a ramp and there a other ramps near (<50 degrees) to it";
3791 tests_dbg(0, "yes: 012: we are driving onto a ramp and there a other ramps near (<50 degrees) to it");
3792 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);
3793 }
3794
3795
3796 if ((d == 0) && (new_angle_abs_min_allowed >= 25))
3797 {
3798 r = "no: driving almost straight, and other ways not very close to straight";
3799 tests_dbg(0, "no: 013: driving almost straight, and other ways not very close to straight");
3800 dbg(0, "STRAI:011.07:3 abs(d)=%d new_angle_abs_min_allowed=%d\n", abs(d), new_angle_abs_min_allowed);
3801 }
3802 else
3803 {
3804
3805 if ( (d == 0) && (abs(new_angle_closest_to_cur - original_d) < 16) )
3806 {
3807 ret = 1;
3808 r = "yes: we are going straight and some other way is very close to it";
3809 tests_dbg(0, "yes: 014: we are going straight and some other way is very close to it");
3810 dbg(0, "STRAI:011.07:0 abs(d)=%d new_angle_abs_min_allowed=%d\n", abs(d), new_angle_abs_min_allowed);
3811 }
3812 else if ( (ncat_2 <= highest_other_cat) && (d == 0) && (abs(new_angle_closest_to_cur - original_d) < 30) )
3813 {
3814 ret = 1;
3815 r = "yes: we are going straight and some other way is very close to it (same or higher cat)";
3816 tests_dbg(0, "yes: 015: we are going straight and some other way is very close to it (same or higher cat)");
3817 dbg(0, "STRAI:011.07:7 abs(d)=%d new_angle_abs_min_allowed=%d\n", abs(d), new_angle_abs_min_allowed);
3818 }
3819 else if ((abs(d) > 0) && (new_angle_abs_min_allowed < abs(d)))
3820 {
3821 ret = 1;
3822 r = "yes: some other way is going more straight";
3823 tests_dbg(0, "yes: 016: some other way is going more straight");
3824 dbg(0, "STRAI:011.07:0 abs(d)=%d new_angle_abs_min_allowed=%d\n", abs(d), new_angle_abs_min_allowed);
3825
3826
3827 if (abs(d) < 10)
3828 {
3829
3830 tests_dbg(0, "enter: (abs(d) < 10)");
3831
3832 // ----------########### more ways left/right of way ? ###########----------
3833 int more_ways_to_left_ = 0;
3834 int more_ways_to_right_ = 0;
3835 w = new->way.next;
3836 while (w)
3837 {
3838 if (is_way_allowed(nav, w, 1))
3839 {
3840 if ( (is_maybe_same_item(&(new->way), w, 0) == 0) && (is_maybe_same_item(&(old->way), w, 1) == 0) )
3841 {
3842 dbg(0, "STRAI:108.02a delta=%d\n", angle_delta(old->angle_end, w->angle2));
3843
3844 if (is_way_allowed(nav, w, 1))
3845 {
3846 if (angle_delta(old->angle_end, w->angle2) < d) // other ways are going more to the left?
3847 {
3848 more_ways_to_left_++;
3849 }
3850 else if (angle_delta(old->angle_end, w->angle2) > d) // other ways are going more to the right?
3851 {
3852 more_ways_to_right_++;
3853 }
3854 }
3855 }
3856 }
3857 w = w->next;
3858 }
3859
3860 tests_dbg(0, "STRAI:108.02 %d %d\n", more_ways_to_left_, more_ways_to_right_);
3861 dbg(0, "STRAI:108.02 %d %d\n", more_ways_to_left_, more_ways_to_right_);
3862
3863
3864 if ((d < 0) && (more_ways_to_left_ == 0)) // && (more_ways_to_right_ > 0))
3865 {
3866
3867 dbg(0, "STRAI:108.03:left\n");
3868 tests_dbg(0, "STRAI:108.03:left\n");
3869 *delta_real = 0;
3870 d = -8;
3871 no_correction = 1;
3872 }
3873 else if ((d > 0) && (more_ways_to_left_ > 0)) // && (more_ways_to_right_ == 0))
3874 {
3875 dbg(0, "STRAI:108.04:right\n");
3876 tests_dbg(0, "STRAI:108.04:right\n");
3877 *delta_real = 0;
3878 d = 8;
3879 no_correction = 1;
3880 }
3881
3882
3883
3884 // ----------########### more ways left/right of way ? ###########----------
3885
3886 }
3887
3888
3889 }
3890 else if ((abs(d) > 0) && (new_angle_abs_min_allowed < 39) && (is_same_street))
3891 {
3892 if ( (cat == ncat) && (ncat_2 > highest_other_cat) )
3893 {
3894 r = "no: we need to make a turn, but other possibilites are much lower cat roads";
3895 tests_dbg(0, "no: 017: we need to make a turn, but other possibilites are much lower cat roads");
3896 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);
3897 }
3898 else
3899 {
3900 ret = 1;
3901 r = "yes: we need to make a turn";
3902 tests_dbg(0, "yes: 018: we need to make a turn");
3903 dbg(0, "STRAI:011.07:1iss abs(d)=%d new_angle_abs_min_allowed=%d\n", abs(d), new_angle_abs_min_allowed);
3904 }
3905 }
3906 else if ((abs(d) > 0) && (new_angle_abs_min_allowed < 52) && (!is_same_street))
3907 {
3908 if ( (cat == ncat) && (ncat_2 > highest_other_cat) )
3909 {
3910 r = "no: we need to make a turn, but other possibilites are much lower cat roads";
3911 tests_dbg(0, "no: 019: we need to make a turn, but other possibilites are much lower cat roads");
3912 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);
3913 }
3914 else
3915 {
3916 ret = 1;
3917 r = "yes: we need to make a turn";
3918 tests_dbg(0, "yes: 020: we need to make a turn");
3919 dbg(0, "STRAI:011.07:1nss abs(d)=%d new_angle_abs_min_allowed=%d\n", abs(d), new_angle_abs_min_allowed);
3920 }
3921 }
3922 else
3923 {
3924 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);
3925 }
3926 }
3927 }
3928 }
3929 }
3930
3931 dbg(0, "STRAI:011.07 is_unambigous[eindeutig]=%d ret=%d r=%s\n", is_unambigous, ret, r);
3932 tests_dbg(0, "STRAI:011.07 is_unambigous[eindeutig]=%d ret=%d r=%s", is_unambigous, ret, r);
3933
3934 #ifdef DEBUG
3935 // 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);
3936 #endif
3937 }
3938
3939
3940
3941
3942
3943
3944 dbg(0, "STRAI:007.00aa:d=%d ******************++++++++++++\n", d);
3945
3946
3947
3948
3949
3950 // correct "delta" (turn angle) here !! ---------------------------
3951 // correct "delta" (turn angle) here !! ---------------------------
3952
3953 if (no_correction == 0)
3954 {
3955 tests_dbg(0, "enter: no_correction == 0");
3956 *delta_real = d;
3957 }
3958
3959 if ((ret == 1) && (have_more_than_one_way_to_turn == 1) && (no_correction == 0))
3960 {
3961 w = new->way.next;
3962 //int d2 = angle_delta(old->angle_end, new->way.angle2);
3963 int d2 = d;
3964 //if (d == 0)
3965 //{
3966 // d2 = 0;
3967 //}
3968
3969 int correct_direction = 1;
3970
3971 dbg(0, "STRAI:007.01:d=%d d2=%d\n", d, d2);
3972 tests_dbg(0, "STRAI:007.01:d=%d d2=%d\n", d, d2);
3973
3974 if (d2 < 0) // left
3975 {
3976 while (w)
3977 {
3978 if (is_way_allowed(nav, w, 1))
3979 {
3980 if ( (is_maybe_same_item(&(new->way), w, 0) == 0) && (is_maybe_same_item(&(old->way), w, 1) == 0) )
3981 {
3982 if (angle_delta(old->angle_end, w->angle2) > d2) // other ways are going more to the right?
3983 {
3984 correct_direction = 0;
3985 break;
3986 }
3987 }
3988 }
3989 w = w->next;
3990 }
3991
3992 if (correct_direction == 1)
3993 {
3994 tests_dbg(0, "MAV:001:correct to right\n");
3995 #ifdef NAVIT_ROUTING_DEBUG_PRINT
3996 dbg(0, "MAV:001:correct to right\n");
3997 #endif
3998 d = 8; // set to "slight right"
3999 }
4000 }
4001 else if (d2 > 0) // right
4002 {
4003 while (w)
4004 {
4005 if (is_way_allowed(nav, w, 1))
4006 {
4007 if ( (is_maybe_same_item(&(new->way), w, 0) == 0) && (is_maybe_same_item(&(old->way), w, 1) == 0) )
4008 {
4009 if (angle_delta(old->angle_end, w->angle2) < d2) // other ways are going more to the left?
4010 {
4011 correct_direction = 0;
4012 break;
4013 }
4014 }
4015 }
4016 w = w->next;
4017 }
4018
4019 if (correct_direction == 1)
4020 {
4021 tests_dbg(0, "MAV:002:correct to left\n");
4022 #ifdef NAVIT_ROUTING_DEBUG_PRINT
4023 dbg(0, "MAV:002:correct to left\n");
4024 #endif
4025 d = -8; // set to "slight left"
4026 }
4027 }
4028 else // (d2 == 0) // straight
4029 {
4030
4031 tests_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);
4032 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);
4033
4034 int more_ways_to_left = 0;
4035 int more_ways_to_right = 0;
4036
4037 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
4038 {
4039 tests_dbg(0, "STRAI:008.02\n");
4040 dbg(0, "STRAI:008.02\n");
4041
4042
4043 if ((abs(new_angle_closest_to_cur - original_d) <= 25) || (abs(original_d) >= 10))
4044 // if (1 == 1)
4045 {
4046
4047 while (w)
4048 {
4049 if (is_way_allowed(nav, w, 1))
4050 {
4051 if ( (is_maybe_same_item(&(new->way), w, 0) == 0) && (is_maybe_same_item(&(old->way), w, 1) == 0) )
4052 {
4053 tests_dbg(0, "STRAI:008.02a delta=%d\n", angle_delta(old->angle_end, w->angle2));
4054 dbg(0, "STRAI:008.02a delta=%d\n", angle_delta(old->angle_end, w->angle2));
4055
4056 if (is_way_allowed(nav, w, 1))
4057 {
4058 if (angle_delta(old->angle_end, w->angle2) < d2) // other ways are going more to the left?
4059 {
4060 more_ways_to_left++;
4061 }
4062 else if (angle_delta(old->angle_end, w->angle2) > d2) // other ways are going more to the right?
4063 {
4064 more_ways_to_right++;
4065 }
4066 }
4067 }
4068 }
4069 w = w->next;
4070 }
4071
4072 tests_dbg(0, "STRAI:008.02 %d %d\n", more_ways_to_left, more_ways_to_right);
4073 dbg(0, "STRAI:008.02 %d %d\n", more_ways_to_left, more_ways_to_right);
4074
4075 if ((more_ways_to_left == 0) && (more_ways_to_right > 0))
4076 {
4077
4078 tests_dbg(0, "STRAI:008.03:left\n");
4079 dbg(0, "STRAI:008.03:left\n");
4080
4081 #ifdef NAVIT_ROUTING_DEBUG_PRINT
4082 dbg(0, "MAV:003:correct to left\n");
4083 #endif
4084 d = -8;
4085 }
4086 else if ((more_ways_to_left > 0) && (more_ways_to_right == 0))
4087 {
4088 tests_dbg(0, "STRAI:008.04:right\n");
4089 dbg(0, "STRAI:008.04:right\n");
4090
4091 #ifdef NAVIT_ROUTING_DEBUG_PRINT
4092 dbg(0, "MAV:003:correct to right\n");
4093 #endif
4094 d = 8;
4095 }
4096
4097 }
4098 else
4099 {
4100 tests_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);
4101 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);
4102 }
4103
4104 }
4105
4106 }
4107
4108 }
4109
4110 // correct "delta" (turn angle) here !! ---------------------------
4111 // correct "delta" (turn angle) here !! ---------------------------
4112
4113
4114
4115
4116
4117
4118
4119
4120 tests_dbg(0, "STRAI:099:ret=%d r=%s d=%d d_real=%d\n", ret, r, d, *delta_real);
4121 dbg(0, "STRAI:099:ret=%d r=%s d=%d d_real=%d\n", ret, r, d, *delta_real);
4122 dbg(0, "STRAI:099:======================================\n");
4123
4124 *delta = d;
4125 if (reason)
4126 {
4127 *reason = r;
4128 }
4129
4130 tests_dbg(0, "=== maneuver_required2 [Exit] ===");
4131
4132
4133 return ret;
4134 }
4135 //UNIT_TESTS_001_PATTERN_END
4136
4137
4138 static struct navigation_command *command_new(struct navigation *this_, struct navigation_itm *itm, int delta, int delta_real)
4139 {
4140 struct navigation_command *ret=g_new0(struct navigation_command, 1);
4141
4142 //dbg(1, "enter this_=%p itm=%p delta=%d\n", this_, itm, delta);
4143 ret->delta = delta;
4144 ret->delta_real = delta_real;
4145 ret->itm = itm;
4146
4147 if (itm && itm->prev && itm->way.next && itm->prev->way.next && !(itm->way.flags & NAVIT_AF_ROUNDABOUT) && (itm->prev->way.flags & NAVIT_AF_ROUNDABOUT))
4148 {
4149 int len = 0;
4150 int angle = 0;
4151 int entry_angle;
4152 struct navigation_itm *itm2 = itm->prev;
4153 int exit_angle = angle_median(itm->prev->angle_end, itm->way.next->angle2);
4154 //dbg(1, "exit %d median from %d,%d\n", exit_angle, itm->prev->angle_end, itm->way.next->angle2);
4155
4156 while (itm2 && (itm2->way.flags & NAVIT_AF_ROUNDABOUT))
4157 {
4158 len += itm2->length;
4159 angle = itm2->angle_end;
4160 itm2 = itm2->prev;
4161 }
4162
4163 if (itm2 && itm2->next && itm2->next->way.next)
4164 {
4165 itm2 = itm2->next;
4166 entry_angle = angle_median(angle_opposite(itm2->way.angle2), itm2->way.next->angle2);
4167 // dbg(1, "entry %d median from %d(%d),%d\n", entry_angle, angle_opposite(itm2->way.angle2), itm2->way.angle2, itm2->way.next->angle2);
4168 }
4169 else
4170 {
4171 entry_angle = angle_opposite(angle);
4172 }
4173 //dbg(0, "entry %d exit %d\n", entry_angle, exit_angle);
4174 ret->roundabout_delta = angle_delta(entry_angle, exit_angle);
4175 ret->length = len + roundabout_extra_length;
4176 }
4177
4178 if (this_->cmd_last)
4179 {
4180 this_->cmd_last->next = ret;
4181 ret->prev = this_->cmd_last;
4182 }
4183
4184 this_->cmd_last = ret;
4185
4186 if (!this_->cmd_first)
4187 {
4188 this_->cmd_first = ret;
4189 }
4190
4191 return ret;
4192 }
4193
4194
4195
4196 // ----------- main place where maneuvers generated (run only once) ------------
4197 // ----------- main place where maneuvers generated (run only once) ------------
4198 // ----------- main place where maneuvers generated (run only once) ------------
4199 static void make_maneuvers(struct navigation *this_, struct route *route)
4200 {
4201 __F_START__
4202
4203 struct navigation_itm *itm, *last = NULL, *last_itm = NULL;
4204 int delta;
4205 int delta_real;
4206 itm = this_->first;
4207 this_->cmd_last = NULL;
4208 this_->cmd_first = NULL;
4209 while (itm)
4210 {
4211 if (last)
4212 {
4213 if (maneuver_required2(this_, last_itm, itm, &delta, &delta_real, NULL))
4214 {
4215 //dbg(0, "maneuver_required2 = true\n");
4216 command_new(this_, itm, delta, delta_real);
4217 }
4218 }
4219 else
4220 {
4221 last = itm;
4222 }
4223 last_itm = itm;
4224 itm = itm->next;
4225 }
4226 command_new(this_, last_itm, 0, 0);
4227
4228 __F_END__
4229 }
4230 // ----------- main place where maneuvers generated ------------
4231 // ----------- main place where maneuvers generated ------------
4232 // ----------- main place where maneuvers generated ------------
4233
4234
4235
4236 static int contains_suffix(char *name, char *suffix)
4237 {
4238 if (!suffix)
4239 {
4240 return 0;
4241 }
4242
4243 if (strlen(name) < strlen(suffix))
4244 {
4245 return 0;
4246 }
4247
4248 return !g_strcasecmp(name + strlen(name) - strlen(suffix), suffix);
4249 }
4250
4251 static char *
4252 replace_suffix(char *name, char *search, char *replace)
4253 {
4254 int len = strlen(name) - strlen(search);
4255 char *ret = g_malloc(len + strlen(replace) + 1);
4256
4257 strncpy(ret, name, len);
4258 strcpy(ret + len, replace);
4259
4260 if (isupper(name[len]))
4261 {
4262 ret[len] = toupper(ret[len]);
4263 }
4264
4265 return ret;
4266 }
4267
4268 static char *
4269 navigation_item_destination(struct navigation *nav, struct navigation_itm *itm, struct navigation_itm *next, char *prefix)
4270 {
4271 char *ret = NULL, *name1, *sep, *name2;
4272 char *n1, *n2;
4273 int i, sex;
4274 int vocabulary1 = 65535;
4275 int vocabulary2 = 65535;
4276 struct attr attr;
4277
4278 if (!prefix)
4279 {
4280 prefix = "";
4281 }
4282
4283 if (nav->speech && speech_get_attr(nav->speech, attr_vocabulary_name, &attr, NULL))
4284 {
4285 vocabulary1 = attr.u.num;
4286 }
4287
4288 if (nav->speech && speech_get_attr(nav->speech, attr_vocabulary_name_systematic, &attr, NULL))
4289 {
4290 vocabulary2 = attr.u.num;
4291 }
4292
4293 n1 = itm->way.name1;
4294 n2 = itm->way.name2;
4295
4296 if (!vocabulary1)
4297 n1 = NULL;
4298
4299 if (!vocabulary2)
4300 n2 = NULL;
4301
4302 if (!n1 && !n2 && (item_is_ramp(itm->way.item)) && vocabulary2)
4303 {
4304 //dbg(1,">> Next is ramp %lx current is %lx \n", itm->way.item.type, next->way.item.type);
4305
4306
4307 // disabled for now !!!!!!!! -------------------------
4308 #if 0
4309 if (next->way.item.type == type_ramp)
4310 {
4311 return NULL;
4312 }
4313 #endif
4314 // disabled for now !!!!!!!! -------------------------
4315
4316
4317 //else
4318 //{
4319 // return g_strdup_printf("%s%s",prefix,_("into the ramp"));
4320 //}
4321
4322 #if 0
4323 if (itm->way.item.type == type_highway_city || itm->way.item.type == type_highway_land)
4324 {
4325 #ifdef HAVE_API_ANDROID
4326 #ifdef NAVIT_SAY_DEBUG_PRINT
4327 android_send_generic_text(1,"+*#O:exit\n");
4328 gchar* xy=g_strdup_printf("+*#1:%s\n", prefix);
4329 android_send_generic_text(1,xy);
4330 g_free(xy);
4331 #endif
4332 #endif
4333 return g_strdup_printf("%s%s", prefix, _("exit")); /* %FIXME Can this even be reached? and "exit" is the wrong text anyway ! */
4334 }
4335 else
4336 #endif
4337 {
4338 if (itm->way.street_dest_text)
4339 {
4340 #ifdef HAVE_API_ANDROID
4341 #ifdef NAVIT_SAY_DEBUG_PRINT
4342 gchar* xy=g_strdup_printf("+*#0:%s\n", itm->way.street_dest_text);
4343 android_send_generic_text(1,xy);
4344 g_free(xy);
4345 gchar* xy=g_strdup_printf("+*#1:%s\n", prefix);
4346 android_send_generic_text(1,xy);
4347 g_free(xy);
4348 #endif
4349 #endif
4350
4351 // say the name on the exit sign/destinaion sign
4352 return g_strdup_printf("%s%s", prefix, itm->way.street_dest_text);
4353 }
4354 else
4355 {
4356 #ifdef HAVE_API_ANDROID
4357 #ifdef NAVIT_SAY_DEBUG_PRINT
4358 android_send_generic_text(1,"+*#O:into the ramp\n");
4359 gchar* xy=g_strdup_printf("+*#1:%s\n", prefix);
4360 android_send_generic_text(1,xy);
4361 g_free(xy);
4362 #endif
4363 #endif
4364
4365 return g_strdup_printf("%s%s", prefix, _("into the ramp"));
4366 }
4367 }
4368
4369 }
4370
4371 if (!n1 && !n2 && !itm->way.street_dest_text)
4372 {
4373 return NULL;
4374 }
4375
4376 if (itm->way.street_dest_text)
4377 {
4378 #ifdef HAVE_API_ANDROID
4379 #ifdef NAVIT_SAY_DEBUG_PRINT
4380 gchar* xy=g_strdup_printf("+*#0:%s\n", itm->way.street_dest_text);
4381 android_send_generic_text(1,xy);
4382 g_free(xy);
4383 gchar* xy=g_strdup_printf("+*#1:%s\n", prefix);
4384 android_send_generic_text(1,xy);
4385 g_free(xy);
4386 #endif
4387 #endif
4388 // say the name on the exit sign/destinaion sign
4389 return g_strdup_printf("%s%s", prefix, itm->way.street_dest_text);
4390 }
4391 else if (n1)
4392 {
4393 sex = -1;
4394 name1 = NULL;
4395 for (i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); i++)
4396 {
4397 if (contains_suffix(n1, suffixes[i].fullname))
4398 {
4399 sex = suffixes[i].sex;
4400 name1 = g_strdup(n1);
4401 break;
4402 }
4403 if (contains_suffix(n1, suffixes[i].abbrev))
4404 {
4405 sex = suffixes[i].sex;
4406
4407 // TODO: replacing strings here maybe not so good?!?
4408 name1 = replace_suffix(n1, suffixes[i].abbrev, suffixes[i].fullname);
4409 break;
4410 }
4411 }
4412
4413 if (n2)
4414 {
4415 name2 = n2;
4416 sep = " ";
4417 }
4418 else
4419 {
4420 name2 = "";
4421 sep = "";
4422 }
4423
4424 gchar* xy;
4425 switch (sex)
4426 {
4427 case -1:
4428 #ifdef HAVE_API_ANDROID
4429 #ifdef NAVIT_SAY_DEBUG_PRINT
4430 android_send_generic_text(1,"+*#O:%sinto the street %s%s%s\n");
4431 xy=g_strdup_printf("+*#1:%s\n", prefix);
4432 android_send_generic_text(1,xy);
4433 g_free(xy);
4434 xy=g_strdup_printf("+*#1:%s\n", n1);
4435 android_send_generic_text(1,xy);
4436 g_free(xy);
4437 xy=g_strdup_printf("+*#1:%s\n", sep);
4438 android_send_generic_text(1,xy);
4439 g_free(xy);
4440 xy=g_strdup_printf("+*#1:%s\n", name2);
4441 android_send_generic_text(1,xy);
4442 g_free(xy);
4443 #endif
4444 #endif
4445 // TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name
4446 ret = g_strdup_printf(_("%sinto the street %s%s%s"), prefix, n1, sep, name2);
4447 break;
4448 case 1:
4449 #ifdef HAVE_API_ANDROID
4450 #ifdef NAVIT_SAY_DEBUG_PRINT
4451 android_send_generic_text(1,"+*#O:%sinto the %s%s%s|male form\n");
4452 xy=g_strdup_printf("+*#1:%s\n", prefix);
4453 android_send_generic_text(1,xy);
4454 g_free(xy);
4455 xy=g_strdup_printf("+*#1:%s\n", name1);
4456 android_send_generic_text(1,xy);
4457 g_free(xy);
4458 xy=g_strdup_printf("+*#1:%s\n", sep);
4459 android_send_generic_text(1,xy);
4460 g_free(xy);
4461 xy=g_strdup_printf("+*#1:%s\n", name2);
4462 android_send_generic_text(1,xy);
4463 g_free(xy);
4464 #endif
4465 #endif
4466 // 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
4467 ret = g_strdup_printf(_("%sinto the %s%s%s|male form"), prefix, name1, sep, name2);
4468 break;
4469 case 2:
4470 #ifdef HAVE_API_ANDROID
4471 #ifdef NAVIT_SAY_DEBUG_PRINT
4472 android_send_generic_text(1,"+*#O:%sinto the %s%s%s|female form\n");
4473 xy=g_strdup_printf("+*#1:%s\n", prefix);
4474 android_send_generic_text(1,xy);
4475 g_free(xy);
4476 xy=g_strdup_printf("+*#1:%s\n", name1);
4477 android_send_generic_text(1,xy);
4478 g_free(xy);
4479 xy=g_strdup_printf("+*#1:%s\n", sep);
4480 android_send_generic_text(1,xy);
4481 g_free(xy);
4482 xy=g_strdup_printf("+*#1:%s\n", name2);
4483 android_send_generic_text(1,xy);
4484 g_free(xy);
4485 #endif
4486 #endif
4487 // 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
4488 ret = g_strdup_printf(_("%sinto the %s%s%s|female form"), prefix, name1, sep, name2);
4489 break;
4490 case 3:
4491 #ifdef HAVE_API_ANDROID
4492 #ifdef NAVIT_SAY_DEBUG_PRINT
4493 android_send_generic_text(1,"+*#O:%sinto the %s%s%s|neutral form\n");
4494 xy=g_strdup_printf("+*#1:%s\n", prefix);
4495 android_send_generic_text(1,xy);
4496 g_free(xy);
4497 xy=g_strdup_printf("+*#1:%s\n", name1);
4498 android_send_generic_text(1,xy);
4499 g_free(xy);
4500 xy=g_strdup_printf("+*#1:%s\n", sep);
4501 android_send_generic_text(1,xy);
4502 g_free(xy);
4503 xy=g_strdup_printf("+*#1:%s\n", name2);
4504 android_send_generic_text(1,xy);
4505 g_free(xy);
4506 #endif
4507 #endif
4508 // 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
4509 ret = g_strdup_printf(_("%sinto the %s%s%s|neutral form"), prefix, name1, sep, name2);
4510 break;
4511 }
4512 g_free(name1);
4513
4514 }
4515 else
4516 {
4517 #ifdef HAVE_API_ANDROID
4518 #ifdef NAVIT_SAY_DEBUG_PRINT
4519 android_send_generic_text(1,"+*#O:sinto the %s\n");
4520 gchar* xy=g_strdup_printf("+*#1:%s\n", prefix);
4521 android_send_generic_text(1,xy);
4522 g_free(xy);
4523 xy=g_strdup_printf("+*#1:%s\n", n2);
4524 android_send_generic_text(1,xy);
4525 g_free(xy);
4526 #endif
4527 #endif
4528 // TRANSLATORS: gives the name of the next road to turn into (into the E17)
4529 ret = g_strdup_printf(_("%sinto the %s"), prefix, n2);
4530 }
4531
4532 name1 = ret;
4533
4534 while (name1 && *name1)
4535 {
4536 switch (*name1)
4537 {
4538 case '|':
4539 *name1 = '\0';
4540 break;
4541 case '/':
4542 *name1++ = ' ';
4543 break;
4544 default:
4545 name1++;
4546 }
4547 }
4548
4549 return ret;
4550 }
4551
4552
4553
4554
4555 #define DONT_KNOW_LEVEL -997
4556
4557
4558 static char *
4559 show_maneuver_bicycle(struct navigation *nav, struct navigation_itm *itm, struct navigation_command *cmd, enum attr_type type, int connect, int want_this_level)
4560 {
4561 __F_START__
4562
4563 // TRANSLATORS: right, as in 'Turn right'
4564 char *dir = _("right");
4565 char *strength = "";
4566 int distance = itm->dest_length - cmd->itm->dest_length;
4567 char *d, *ret = NULL;
4568 int delta = cmd->delta;
4569 int delta_real = cmd->delta_real;
4570 int level;
4571 int level_now = 99;
4572 int level3;
4573 int strength_needed;
4574 int skip_roads;
4575 int count_roundabout;
4576 struct navigation_itm *cur;
4577 struct navigation_way *w;
4578 int against_oneway = 0;
4579 int keep_dir = 0;
4580 int old_dir = 0;
4581
4582 if (want_this_level == DONT_KNOW_LEVEL)
4583 {
4584 level3 = 1;
4585 }
4586 else
4587 {
4588 level3 = want_this_level;
4589 }
4590
4591
4592 int cur_vehicle_speed = 0;
4593 if ((global_navit) && (global_navit->vehicle))
4594 {
4595 cur_vehicle_speed = global_navit->vehicle->speed; // in km/h
4596 }
4597
4598 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
4599 {
4600 //dbg(0, "itm->way.flags=%x\n", itm->way.flags);
4601 //dbg(0, "itm->next->way.flags=%x\n", itm->next->way.flags);
4602 //dbg(0, "itm->way.dir=%d itm->next->way.dir=%d\n", itm->way.dir, itm->next->way.dir);
4603
4604 //dbg(0, "2 itm->way.flags=%x\n", cmd->itm->way.flags);
4605 //dbg(0, "2 itm->next->way.flags=%x\n", cmd->itm->next->way.flags);
4606 //dbg(0, "2 itm->way.dir=%d itm->next->way.dir=%d\n", cmd->itm->way.dir, cmd->itm->next->way.dir);
4607
4608 int flags_old = navigation_item_get_flags(&itm->way);
4609 int flags_new = 0;
4610 if (itm->next)
4611 {
4612 flags_new = navigation_item_get_flags(&itm->next->way);
4613 }
4614 //dbg(0, "(2211)old flags=%x new flags=%x\n", flags_old, flags_new);
4615
4616 // long long wayid_old = navigation_item_get_wayid(&(itm->way));
4617 // long long wayid_new = navigation_item_get_wayid(&(itm->next->way));
4618 // dbg(0, "WID old_way_id=%lld new_way_id=%lld\n", wayid_old, wayid_new);
4619
4620
4621 if ( (itm->way.dir == 1) && ((itm->next->way.dir == -1) && (itm->next->way.flags & NAVIT_AF_ONEWAY_BICYCLE_NO)) )
4622 {
4623 against_oneway = 1;
4624 //dbg(0, "SPEAK: (1)going against oneway street!\n");
4625 }
4626 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)) )
4627 {
4628 against_oneway = 1;
4629 //dbg(0, "SPEAK: (2)going against oneway street!\n");
4630 }
4631 }
4632
4633 //dbg(0, "d=%d d3=%d\n", distance, (distance - cmd->length));
4634 level_now = navigation_get_announce_level(nav, itm->way.item.type, distance - cmd->length, 0);
4635 //dbg(0, "level_now=%d\n", level_now);
4636
4637 w = itm->next->way.next;
4638 strength_needed = 0;
4639
4640 if (angle_delta(itm->next->way.angle2, itm->angle_end) < 0) // left
4641 {
4642 while (w)
4643 {
4644 if (angle_delta(w->angle2, itm->angle_end) < 0) // other ways are going left
4645 {
4646 strength_needed = 1;
4647 break;
4648 }
4649 w = w->next;
4650 }
4651 }
4652 else // right
4653 {
4654 while (w)
4655 {
4656 if (angle_delta(w->angle2, itm->angle_end) > 0) // other ways are going right
4657 {
4658 strength_needed = 1;
4659 break;
4660 }
4661 w = w->next;
4662 }
4663 }
4664
4665
4666 if ((strength_needed == 0) && (delta < 9)) // for corrected turn (delta will be 8), use strength ("slight")
4667 {
4668 strength_needed = 1;
4669 }
4670
4671 //dbg(0, "cmd->delta=%d\n", delta);
4672
4673 if (delta < 0)
4674 {
4675 // TRANSLATORS: left, as in 'Turn left'
4676 dir = _("left");
4677 delta = -delta;
4678
4679 old_dir = -1; // left
4680 }
4681 else if (delta > 0)
4682 {
4683
4684 old_dir = 1; // right
4685
4686 // dir = right
4687 }
4688 else // delta == 0 // go straight
4689 {
4690 dir = _("straight");
4691 strength_needed = 0;
4692 }
4693
4694
4695 keep_dir = 0;
4696
4697 if (strength_needed)
4698 {
4699 if (delta < 45)
4700 {
4701 // TRANSLATORS: Don't forget the ending space
4702 // TRANSLATORS: EXAMPLE: turn slight right
4703 strength = _("slighty ");
4704 // TRANSLATORS: Don't forget the ending space
4705 // TRANSLATORS: EXAMPLE: turn slight right
4706 strength = _("slight ");
4707
4708 if (delta_real == 0) // keep left/right
4709 {
4710 if (old_dir == -1)
4711 {
4712 keep_dir = -1;
4713 }
4714 else
4715 {
4716 keep_dir = 1;
4717 }
4718 }
4719 }
4720 else if (delta < 105)
4721 {
4722 strength = "";
4723 }
4724 else if (delta < 165)
4725 {
4726 // TRANSLATORS: Don't forget the ending space
4727 // TRANSLATORS: EXAMPLE: turn hard right
4728 strength = _("hard ");
4729 }
4730 else if (delta < 180)
4731 {
4732 // TRANSLATORS: Don't forget the ending space
4733 // TRANSLATORS: EXAMPLE: turn really hard right
4734 strength = _("really hard ");
4735 }
4736 else
4737 {
4738 // TRANSLATORS: Don't forget the ending space
4739 strength = "";
4740 }
4741 }
4742
4743
4744 if (type != attr_navigation_long_exact)
4745 {
4746 //dbg(0, "round distance d=%d dr=%d\n", distance, round_distance(distance));
4747 distance = round_distance(distance);
4748 }
4749
4750
4751
4752
4753 if (type == attr_navigation_speech)
4754 {
4755 dbg(0, "NAV_TURNAROUND:003 ta=%d talimit=%d\n", nav->turn_around, nav->turn_around_limit);
4756
4757 if (nav->turn_around && nav->turn_around == nav->turn_around_limit)
4758 {
4759 dbg(0, "NAV_TURNAROUND:004\n");
4760
4761 return2 g_strdup(_("When possible, please turn around"));
4762 }
4763
4764 if (!connect)
4765 {
4766 if (want_this_level == DONT_KNOW_LEVEL)
4767 {
4768 level3 = navigation_get_announce_level_cmd(nav, itm, cmd, distance - cmd->length, ((float)cur_vehicle_speed / 3.6f) );
4769 }
4770 else
4771 {
4772 level3 = want_this_level;
4773 }
4774 }
4775
4776 if (want_this_level == DONT_KNOW_LEVEL)
4777 {
4778 level_now = navigation_get_announce_level(nav, itm->way.item.type, distance - cmd->length, ((float)cur_vehicle_speed / 3.6f) );
4779 }
4780 else
4781 {
4782 level_now = want_this_level;
4783 }
4784 }
4785
4786
4787
4788 switch (level3)
4789 {
4790 case 3:
4791 if (distance > 500)
4792 {
4793 d = get_distance(nav, distance, type, 1);
4794 ret = g_strdup_printf(_("Follow the road for the next %s"), d);
4795 g_free(d);
4796 }
4797 else
4798 {
4799 ret = g_strdup("");
4800 }
4801 return2 ret;
4802 // break;
4803 case 2:
4804 d = g_strdup(_("soon"));
4805 break;
4806 case 1:
4807 d = get_distance(nav, distance, attr_navigation_short, 0);
4808 break;
4809 case 0:
4810 // d = g_strdup(_("now"));
4811 d = g_strdup("");
4812 break;
4813 }
4814
4815
4816 // are there more commands left?
4817 if (cmd->itm->next)
4818 {
4819 int tellstreetname = 0;
4820 char *destination = NULL;
4821
4822 if (type == attr_navigation_speech)
4823 {
4824 if (level3 == 1)
4825 {
4826 tellstreetname = 1; // Ok so we tell the name of the street
4827 }
4828 else // if (level3 == 0)
4829 {
4830 tellstreetname = 0;
4831 }
4832 }
4833 else
4834 {
4835 tellstreetname = 1;
4836 }
4837
4838 if (global_speak_streetnames == 0)
4839 {
4840 // never speak streetnames (user config option)
4841 tellstreetname = 0;
4842 }
4843
4844 if (nav->tell_street_name && tellstreetname)
4845 {
4846 destination = navigation_item_destination(nav, cmd->itm, itm, " ");
4847 }
4848
4849
4850 if (connect == 0)
4851 {
4852 //dbg(0, "level3=%5$d str=%1$s%2$s %3$s%4$s\n", strength, dir, d, destination ? destination : "", level3);
4853
4854 if (level3 == 0)
4855 {
4856 if (against_oneway == 1)
4857 {
4858 #if 1
4859 if (delta < 10)
4860 {
4861 ret = g_strdup_printf("%s", _("oncoming traffic!")); // just say "attention oneway street!"
4862 }
4863 else
4864 {
4865 ret = g_strdup_printf("%s, %s", dir, _("oncoming traffic!")); // just say "left" or "right" at the turn + "attention oneway street!"
4866 }
4867 #endif
4868
4869 }
4870 else
4871 {
4872 #if 1
4873 if (delta >= 10)
4874 {
4875 ret = g_strdup(dir); // just say "left" or "right" at the turn
4876 }
4877 else
4878 {
4879 ret = g_strdup("");
4880 }
4881 #endif
4882
4883 #if 0
4884 if (delta == 0)
4885 {
4886 ret = g_strdup(dir); // just say "left" or "right" or "straight" at the turn
4887 }
4888 else
4889 {
4890 if (keep_dir != 0)
4891 {
4892 if (keep_dir == -1)
4893 {
4894 // TRANSLATORS: The argument is the distance. Example: 'keep left in 100 meters'
4895 ret = g_strdup_printf(_("keep left %s"), "");
4896 }
4897 else
4898 {
4899 // TRANSLATORS: The argument is the distance. Example: 'keep right in 100 meters'
4900 ret = g_strdup_printf(_("keep right %s"), "");
4901 }
4902 }
4903 else
4904 {
4905 if (delta >= 10)
4906 {
4907 ret = g_strdup(dir); // just say "left" or "right" at the turn
4908 }
4909 else
4910 {
4911 ret = g_strdup("");
4912 }
4913 }
4914 }
4915 #endif
4916
4917 }
4918 }
4919 else // if (level3 == 1)
4920 {
4921 if ((against_oneway == 1) && (delta < 10))
4922 {
4923 ret = g_strdup(""); // probably just going against a oneway street, but travelling straight on. dont say anything now
4924 }
4925 else
4926 {
4927 if (delta >= 10)
4928 {
4929 // 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'
4930 ret = g_strdup_printf_4_str(_("Turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination : "");
4931 }
4932 else
4933 {
4934 ret = g_strdup("");
4935 }
4936 }
4937 }
4938
4939 }
4940 else // (connect == 1)
4941 {
4942 if (level3 == 0)
4943 {
4944 if (against_oneway == 1)
4945 {
4946 if (delta < 10)
4947 {
4948 ret = g_strdup_printf("%s %s", _("then"), _("oncoming traffic!"));
4949 }
4950 else
4951 {
4952 ret = g_strdup_printf("%s %s %s", _("then"), dir, _("oncoming traffic!"));
4953 }
4954 }
4955 else
4956 {
4957 if (delta >= 10)
4958 {
4959 ret = g_strdup_printf("%s %s", _("then"), dir);
4960 }
4961 else
4962 {
4963 ret = g_strdup("");
4964 }
4965 }
4966 }
4967 else // if (level3 == 1)
4968 {
4969 if (against_oneway == 1)
4970 {
4971 if (delta < 10)
4972 {
4973 // nothing
4974 ret = g_strdup("");
4975 }
4976 else
4977 {
4978 // TRANSLATORS: First argument is strength, second direction, third distance, fourth destination
4979 ret = g_strdup_printf_4_str(_("then turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination : "");
4980 }
4981 }
4982 else
4983 {
4984 if (delta >= 10)
4985 {
4986 // TRANSLATORS: First argument is strength, second direction, third distance, fourth destination
4987 ret = g_strdup_printf_4_str(_("then turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination : "");
4988 }
4989 else
4990 {
4991 ret = g_strdup("");
4992 }
4993 }
4994 }
4995 }
4996
4997
4998 if (destination)
4999 {
5000 g_free(destination);
5001 destination = NULL;
5002 }
5003 }
5004 // no more commands left, must be at destination
5005 else
5006 {
5007 if (!connect)
5008 {
5009 d = get_distance(nav, distance, type, 1);
5010
5011 // TRANSLATORS: EXAMPLE: You have reached your destination in 300 meters
5012 ret = g_strdup_printf(_("You have reached your destination %s"), d);
5013
5014 g_free(d);
5015 }
5016 else
5017 {
5018 ret = g_strdup(_("then you have reached your destination."));
5019 }
5020 }
5021
5022 return2 ret;
5023
5024 __F_END__
5025 }
5026
5027 int navigation_is_low_level_street(enum item_type t)
5028 {
5029 if (global_vehicle_profile == 0) // only in car profile!
5030 {
5031 if (t == type_street_service)
5032 {
5033 return 1;
5034 }
5035 else if (t == type_street_parking_lane)
5036 {
5037 return 1;
5038 }
5039 else if (t == type_track_ground)
5040 {
5041 return 1;
5042 }
5043 else if (t == type_track_grass)
5044 {
5045 return 1;
5046 }
5047 else if (t == type_track_gravelled)
5048 {
5049 return 1;
5050 }
5051 else if (t == type_track_unpaved)
5052 {
5053 return 1;
5054 }
5055 else if (t == type_track_paved)
5056 {
5057 return 1;
5058 }
5059 }
5060
5061 return 0;
5062 }
5063
5064
5065
5066 static char *
5067 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)
5068 {
5069 __F_START__
5070
5071 // TRANSLATORS: right, as in 'Turn right'
5072 char *dir = _("right");
5073 char *strength = "";
5074 int distance = itm->dest_length - cmd->itm->dest_length;
5075 char *d, *ret = NULL;
5076 int delta = cmd->delta;
5077 int delta_real = cmd->delta_real;
5078 int level;
5079 int level_now = 99;
5080 int strength_needed;
5081 int skip_roads;
5082 int count_roundabout; // car mode ----
5083 struct navigation_itm *cur;
5084 struct navigation_way *w;
5085 int against_oneway = 0;
5086 int keep_dir = 0; // car mode ----
5087 int old_dir = 0;
5088
5089 if (connect)
5090 {
5091 level = -2; // level = -2 means "connect to another maneuver via 'then ...'"
5092 }
5093 else
5094 {
5095 if (want_this_level == DONT_KNOW_LEVEL)
5096 {
5097 level = 1;
5098 }
5099 else
5100 {
5101 level = want_this_level;
5102 }
5103 }
5104
5105 int cur_vehicle_speed = 0;
5106 if ((global_navit) && (global_navit->vehicle))
5107 {
5108 cur_vehicle_speed = global_navit->vehicle->speed; // in km/h
5109 }
5110
5111
5112 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
5113 {
5114 //dbg(0, "itm->way.flags=%x\n", itm->way.flags);
5115 //dbg(0, "itm->next->way.flags=%x\n", itm->next->way.flags);
5116
5117 // int flags_old = navigation_item_get_flags(&itm->way);
5118 // int flags_new = navigation_item_get_flags(&itm->next->way);
5119 // dbg(0, "old flags=%x new flags=%x\n", flags_old, flags_new);
5120
5121 if ( (itm->way.dir == 1) && ((itm->next->way.dir == -1) && (itm->next->way.flags & NAVIT_AF_ONEWAY_BICYCLE_NO)) )
5122 {
5123 against_oneway = 1;
5124 //dbg(0, "SPEAK: (1)going against oneway street!\n");
5125 }
5126 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)) )
5127 {
5128 against_oneway = 1;
5129 //dbg(0, "SPEAK: (2)going against oneway street!\n");
5130 }
5131 }
5132
5133 w = itm->next->way.next;
5134 strength_needed = 0;
5135
5136 //dbg(0, "STRENGTH:001:strength_needed = %d delta = %d\n", strength_needed, delta);
5137
5138 if (angle_delta(itm->next->way.angle2, itm->angle_end) < 0) // left
5139 {
5140 while (w)
5141 {
5142 if (angle_delta(w->angle2, itm->angle_end) < 0) // other ways are going left
5143 {
5144 strength_needed = 1;
5145 // dbg(0, "STRENGTH:002:strength_needed = %d\n", strength_needed);
5146 break;
5147 }
5148 w = w->next;
5149 }
5150 }
5151 else // right
5152 {
5153 while (w)
5154 {
5155 if (angle_delta(w->angle2, itm->angle_end) > 0) // other ways are going right
5156 {
5157 strength_needed = 1;
5158 // dbg(0, "STRENGTH:003:strength_needed = %d\n", strength_needed);
5159 break;
5160 }
5161 w = w->next;
5162 }
5163 }
5164
5165 if ((strength_needed == 0) && (delta < 9)) // for corrected turn (delta will be 8), use strength ("slight")
5166 {
5167 strength_needed = 1;
5168 }
5169
5170 // dbg(0, "STRAI:K001:strength_needed=%d delta=%d delta_real=%d\n", strength_needed, delta, delta_real);
5171
5172 //dbg(0, "cmd->delta=%d\n", delta);
5173
5174 if (delta < 0)
5175 {
5176 #ifdef HAVE_API_ANDROID
5177 #ifdef NAVIT_SAY_DEBUG_PRINT
5178 android_send_generic_text(1,"+*#O:left\n");
5179 #endif
5180 #endif
5181 // TRANSLATORS: left, as in 'Turn left'
5182 dir = _("left");
5183 delta = -delta;
5184
5185 old_dir = -1; // left
5186
5187 }
5188 else if (delta > 0)
5189 {
5190
5191 old_dir = 1; // right
5192
5193 // dir = right
5194 #ifdef HAVE_API_ANDROID
5195 #ifdef NAVIT_SAY_DEBUG_PRINT
5196 android_send_generic_text(1,"+*#O:right\n");
5197 #endif
5198 #endif
5199 }
5200 else // delta == 0 // go straight
5201 {
5202 dir = _("straight");
5203 strength_needed = 0;
5204 // dbg(0, "STRENGTH:004:strength_needed = %d\n", strength_needed);
5205 }
5206
5207 dbg(0, "STRAI:K002:*:strength_needed=%d delta=%d delta_real=%d\n", strength_needed, delta, delta_real);
5208
5209
5210 keep_dir = 0;
5211
5212 if (strength_needed)
5213 {
5214 // dbg(0, "STRENGTH:005:\n");
5215
5216
5217 if (delta < 45)
5218 {
5219 #ifdef HAVE_API_ANDROID
5220 #ifdef NAVIT_SAY_DEBUG_PRINT
5221 android_send_generic_text(1,"+*#O:slight \n");
5222 #endif
5223 #endif
5224 // TRANSLATORS: Don't forget the ending space
5225 // TRANSLATORS: EXAMPLE: turn slight right
5226 strength = _("slighty ");
5227 // TRANSLATORS: Don't forget the ending space
5228 // TRANSLATORS: EXAMPLE: turn slight right
5229 strength = _("slight ");
5230
5231 if (delta_real == 0) // keep left/right
5232 {
5233 if (old_dir == -1)
5234 {
5235 keep_dir = -1;
5236 }
5237 else
5238 {
5239 keep_dir = 1;
5240 }
5241 }
5242
5243 dbg(0, "STRENGTH:006:strength_needed = %s\n", strength);
5244
5245 }
5246 else if (delta < 105)
5247 {
5248 strength = "";
5249 }
5250 else if (delta < 165)
5251 {
5252 #ifdef HAVE_API_ANDROID
5253 #ifdef NAVIT_SAY_DEBUG_PRINT
5254 android_send_generic_text(1,"+*#O:hard \n");
5255 #endif
5256 #endif
5257 // TRANSLATORS: Don't forget the ending space
5258 // TRANSLATORS: EXAMPLE: turn hard right
5259 strength = _("hard ");
5260 }
5261 else if (delta < 180)
5262 {
5263 #ifdef HAVE_API_ANDROID
5264 #ifdef NAVIT_SAY_DEBUG_PRINT
5265 android_send_generic_text(1,"+*#O:really hard \n");
5266 #endif
5267 #endif
5268 // TRANSLATORS: Don't forget the ending space
5269 // TRANSLATORS: EXAMPLE: turn really hard right
5270 strength = _("really hard ");
5271 }
5272 else
5273 {
5274 // dbg(1,"delta=%d\n", delta);
5275 strength = "";
5276 }
5277 }
5278
5279 // dbg(0, "STRENGTH:010:strength_needed = %s\n", strength);
5280
5281
5282 if (type != attr_navigation_long_exact)
5283 {
5284 distance = round_distance(distance);
5285 }
5286
5287 if (type == attr_navigation_speech)
5288 {
5289 dbg(0, "NAV_TURNAROUND:001 ta=%d talimit=%d\n", nav->turn_around, nav->turn_around_limit);
5290
5291 if (nav->turn_around && nav->turn_around == nav->turn_around_limit)
5292 {
5293
5294 dbg(0, "NAV_TURNAROUND:002:*******\n");
5295
5296 #ifdef HAVE_API_ANDROID
5297 #ifdef NAVIT_SAY_DEBUG_PRINT
5298 android_send_generic_text(1,"+*#O:When possible, please turn around\n");
5299 #endif
5300 #endif
5301 return2 g_strdup(_("When possible, please turn around"));
5302 }
5303
5304 if (!connect)
5305 {
5306 if (want_this_level == DONT_KNOW_LEVEL)
5307 {
5308 level = navigation_get_announce_level_cmd(nav, itm, cmd, distance - cmd->length, ((float)cur_vehicle_speed / 3.6f) );
5309 }
5310 else
5311 {
5312 level = want_this_level;
5313 }
5314 }
5315
5316 if (want_this_level == DONT_KNOW_LEVEL)
5317 {
5318 level_now = navigation_get_announce_level(nav, itm->way.item.type, distance - cmd->length, ((float)cur_vehicle_speed / 3.6f) );
5319 }
5320 else
5321 {
5322 level_now = want_this_level;
5323 }
5324
5325 }
5326
5327 #ifdef NAVIT_DEBUG_COORD_LIST
5328 int need_clear = 1;
5329 #endif
5330
5331
5332 #if 1
5333 // ------------------- jandegr -------------------
5334
5335 struct navigation_way *candidate_way;
5336
5337 if (cmd->itm->prev->way.flags & NAVIT_AF_ROUNDABOUT)
5338 {
5339 cur = cmd->itm->prev;
5340 count_roundabout = 0;
5341
5342 // ----- fix -----
5343 struct navigation_itm *cur_orig = cur->next;
5344
5345 enum item_type cur_street_type = 0;
5346 int exit_is_lover_street_type = 0;
5347 cur_street_type = cur_orig->way.item.type;
5348 // dbg(0, "curr item type=%s\n", item_to_name(cur_orig->way.item.type));
5349 exit_is_lover_street_type = navigation_is_low_level_street(cur_street_type);
5350
5351 int next_exit_is_lower_street_type = 0;
5352 // ----- fix -----
5353
5354
5355 dbg(0, "ROUNDABT:001:enter\n");
5356
5357 while (cur && (cur->way.flags & NAVIT_AF_ROUNDABOUT))
5358 {
5359
5360 // dbg(0, "ROUNDABT:002:loop-1:w\n");
5361
5362 candidate_way=cur->next->way.next;
5363 while (candidate_way)
5364 {
5365
5366 dbg(0, "ROUNDABT:002:loop-2:w2 type=%s\n", item_to_name(candidate_way->item.type));
5367
5368 // If the next segment has no exit or the exit isn't allowed, don't count it
5369 if (candidate_way && is_way_allowed(nav, candidate_way, 3))
5370 {
5371
5372 dbg(0, "ROUNDABT:003:is_allowed type=%s\n", item_to_name(candidate_way->item.type));
5373
5374 // only count street_service (and lesser streets) if we also exit on street_service (or any lesser street)
5375 if (cur->next)
5376 {
5377 next_exit_is_lower_street_type = navigation_is_low_level_street(candidate_way->item.type);
5378
5379 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));
5380 }
5381
5382 if ((exit_is_lover_street_type == 1) || (next_exit_is_lower_street_type == 0))
5383 {
5384 count_roundabout++;
5385
5386 dbg(0, "ROUNDABT:005:found:count_roundabout=%d\n", count_roundabout);
5387
5388 /* As soon as we have an allowed one on this node,
5389 * stop further counting for this node.
5390 */
5391 candidate_way = candidate_way->next;
5392 break;
5393 }
5394 }
5395 candidate_way=candidate_way->next;
5396 }
5397 cur = cur->prev;
5398 }
5399
5400 /*try to figure out if the entry node has a usable exit as well
5401 *
5402 * this will fail for left-hand driving areas
5403 */
5404 if (cur && cur->next)
5405 {
5406 dbg(0, "ROUNDABT:007:entry-check\n");
5407
5408 candidate_way = cur->next->way.next;
5409 while (candidate_way)
5410 {
5411 dbg(0, "ROUNDABT:008:loop-3:w3 type=%s\n", item_to_name(candidate_way->item.type));
5412
5413 if (candidate_way && is_way_allowed(nav,candidate_way,3)
5414 && (cur->angle_end < candidate_way->angle2) && ( candidate_way->angle2 > cur->next->way.angle2 ))
5415 /*for the entry node only count exits to the right ?*/
5416 {
5417 count_roundabout++;
5418
5419 dbg(0, "ROUNDABT:009:entry:found:count_roundabout=%d\n", count_roundabout);
5420 /* As soon as we have an allowed one on this node,
5421 * stop further counting for this node.
5422 */
5423 break;
5424 }
5425 candidate_way = candidate_way->next;
5426 }
5427 }
5428
5429 switch (level)
5430 {
5431 #if 0
5432 case 3:
5433 d=get_distance(nav, distance, type, 1);
5434 return g_strdup_printf(_("Follow the road for the next %s"), d);
5435 #endif
5436 case 2:
5437 return2 g_strdup(_("Enter the roundabout soon"));
5438 case 1:
5439 // TRANSLATORS: EXAMPLE: Leave the roundabout at the second exit
5440 return2 g_strdup_printf(_("Leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
5441 case -2:
5442 // TRANSLATORS: EXAMPLE: ... then leave the roundabout at the second exit
5443 return2 g_strdup_printf(_("then leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
5444 case 0:
5445 // TRANSLATORS: EXAMPLE: Leave the roundabout at the second exit
5446 return2 g_strdup_printf(_("Leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
5447 }
5448 }
5449
5450
5451 // ------------------- jandegr -------------------
5452 #endif
5453
5454
5455
5456
5457
5458
5459
5460 #if 0
5461 // ------------------- zoff -------------------
5462
5463 if (cmd->itm->prev->way.flags & NAVIT_AF_ROUNDABOUT)
5464 {
5465 cur = cmd->itm->prev;
5466 count_roundabout = 0;
5467
5468 struct navigation_itm *cur_orig = cur->next;
5469
5470 enum item_type cur_street_type = 0;
5471 int exit_is_lover_street_type = 0;
5472 cur_street_type = cur_orig->way.item.type;
5473 // dbg(0, "curr item type=%s\n", item_to_name(cur_orig->way.item.type));
5474 exit_is_lover_street_type = navigation_is_low_level_street(cur_street_type);
5475
5476 int next_exit_is_lower_street_type = 0;
5477
5478 while (cur && (cur->way.flags & NAVIT_AF_ROUNDABOUT))
5479 {
5480 // If the next segment has no exit or the exit isn't allowed, don't count it
5481 if (cur->next->way.next && is_way_allowed(nav, cur->next->way.next, 3))
5482 {
5483
5484 // only count street_service (and lesser streets) if we also exit on street_service (or any lesser street)
5485 if (cur->next)
5486 {
5487 next_exit_is_lower_street_type = navigation_is_low_level_street(cur->next->way.next->item.type);
5488 }
5489
5490 if ((exit_is_lover_street_type == 1) || (next_exit_is_lower_street_type == 0))
5491 {
5492 count_roundabout++;
5493
5494 #ifdef NAVIT_DEBUG_COORD_LIST
5495 if (need_clear == 1)
5496 {
5497 need_clear = 0;
5498 global_debug_coord_list_items = 0;
5499
5500 struct coord c2[5];
5501
5502 if (navigation_get_real_item_first_coord(&(cur_orig->way), c2))
5503 {
5504 global_debug_coord_list[global_debug_coord_list_items].x = c2[0].x;
5505 global_debug_coord_list[global_debug_coord_list_items].y = c2[0].y;
5506 global_debug_coord_list_items++;
5507 global_debug_coord_list[global_debug_coord_list_items].x = c2[1].x;
5508 global_debug_coord_list[global_debug_coord_list_items].y = c2[1].y;
5509 global_debug_coord_list_items++;
5510 }
5511
5512 }
5513
5514 struct coord c1[5];
5515 if (navigation_get_real_item_first_coord(cur->next->way.next, c1))
5516 {
5517 if ((global_debug_coord_list_items + 2) > MAX_DEBUG_COORDS)
5518 {
5519 global_debug_coord_list_items = 0;
5520 }
5521
5522 global_debug_coord_list[global_debug_coord_list_items].x = c1[0].x;
5523 global_debug_coord_list[global_debug_coord_list_items].y = c1[0].y;
5524 global_debug_coord_list_items++;
5525 global_debug_coord_list[global_debug_coord_list_items].x = c1[1].x;
5526 global_debug_coord_list[global_debug_coord_list_items].y = c1[1].y;
5527 global_debug_coord_list_items++;
5528 }
5529 #endif
5530
5531 }
5532 }
5533 cur = cur->prev;
5534 }
5535
5536 gchar* xy;
5537
5538 switch (level)
5539 {
5540 case 2:
5541 #ifdef HAVE_API_ANDROID
5542 #ifdef NAVIT_SAY_DEBUG_PRINT
5543 android_send_generic_text(1,"+*#O:Enter the roundabout soon\n");
5544 #endif
5545 #endif
5546 return2 g_strdup(_("Enter the roundabout soon"));
5547
5548
5549
5550
5551 case 1:
5552
5553
5554 #ifdef HAVE_API_ANDROID
5555 #ifdef NAVIT_SAY_DEBUG_PRINT
5556 android_send_generic_text(1,"+*#O:Leave the roundabout at the %s\n");
5557 xy=g_strdup_printf("+*#1:%s\n", get_exit_count_str(count_roundabout));
5558 android_send_generic_text(1,xy);
5559 g_free(xy);
5560 #endif
5561 #endif
5562 // TRANSLATORS: EXAMPLE: Leave the roundabout at the second exit
5563 return2 g_strdup_printf(_("Leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
5564
5565
5566 // ---- DISABLED ----
5567 #if 0
5568 d = get_distance(nav, distance, type, 1);
5569
5570 #ifdef HAVE_API_ANDROID
5571 #ifdef NAVIT_SAY_DEBUG_PRINT
5572 android_send_generic_text(1,"+*#O:In %s, enter the roundabout\n");
5573 xy=g_strdup_printf("+*#1:%s\n", d);
5574 android_send_generic_text(1,xy);
5575 g_free(xy);
5576 #endif
5577 #endif
5578 // TRANSLATORS: %s is the distance to the roundabout
5579 // TRANSLATORS: EXAMPLE: In 300m, enter the roundabout
5580 ret = g_strdup_printf(_("In %s, enter the roundabout"), d);
5581 g_free(d);
5582 return2 ret;
5583 #endif
5584 // ---- DISABLED ----
5585
5586
5587
5588 case -2:
5589 #ifdef HAVE_API_ANDROID
5590 #ifdef NAVIT_SAY_DEBUG_PRINT
5591 android_send_generic_text(1,"+*#O:then leave the roundabout at the %s\n");
5592 xy=g_strdup_printf("+*#1:%s\n", get_exit_count_str(count_roundabout));
5593 android_send_generic_text(1,xy);
5594 g_free(xy);
5595 #endif
5596 #endif
5597 // TRANSLATORS: EXAMPLE: ... then leave the roundabout at the second exit
5598 return2 g_strdup_printf(_("then leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
5599
5600
5601 case 0:
5602 #ifdef HAVE_API_ANDROID
5603 #ifdef NAVIT_SAY_DEBUG_PRINT
5604 android_send_generic_text(1,"+*#O:Leave the roundabout at the %s\n");
5605 xy=g_strdup_printf("+*#1:%s\n", get_exit_count_str(count_roundabout));
5606 android_send_generic_text(1,xy);
5607 g_free(xy);
5608 #endif
5609 #endif
5610 // TRANSLATORS: EXAMPLE: Leave the roundabout at the second exit
5611 return2 g_strdup_printf(_("Leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
5612 }
5613 }
5614
5615 // ------------------- zoff -------------------
5616 #endif
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626 // -- NEW 002 --
5627 if (cmd->itm)
5628 {
5629 // put correct destination into struct (to later show in GUI)
5630 navigation_select_announced_destinations(cmd);
5631 // string is in cmd->itm->way.street_dest_text
5632 }
5633 // -- NEW 002 --
5634
5635
5636
5637 switch (level)
5638 {
5639 case 3:
5640 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
5641 {
5642 if (distance > 500)
5643 {
5644 d = get_distance(nav, distance, type, 1);
5645
5646 #ifdef HAVE_API_ANDROID
5647 #ifdef NAVIT_SAY_DEBUG_PRINT
5648 android_send_generic_text(1,"+*#O:Follow the road for the next %s\n");
5649 gchar* xy=g_strdup_printf("+*#1:%s\n", d);
5650 android_send_generic_text(1,xy);
5651 g_free(xy);
5652 #endif
5653 #endif
5654
5655 ret = g_strdup_printf(_("Follow the road for the next %s"), d);
5656 g_free(d);
5657 }
5658 else
5659 {
5660 ret = g_strdup("");
5661 }
5662 }
5663 else
5664 {
5665 d = get_distance(nav, distance, type, 1);
5666
5667 #ifdef HAVE_API_ANDROID
5668 #ifdef NAVIT_SAY_DEBUG_PRINT
5669 android_send_generic_text(1,"+*#O:Follow the road for the next %s\n");
5670 gchar* xy=g_strdup_printf("+*#1:%s\n", d);
5671 android_send_generic_text(1,xy);
5672 g_free(xy);
5673 #endif
5674 #endif
5675 // TRANSLATORS: EXAMPLE: Follow the road for the next 300 meters
5676 ret = g_strdup_printf(_("Follow the road for the next %s"), d);
5677 g_free(d);
5678 }
5679 return2 ret;
5680 case 2:
5681 #ifdef HAVE_API_ANDROID
5682 #ifdef NAVIT_SAY_DEBUG_PRINT
5683 android_send_generic_text(1,"+*#O:soon\n");
5684 #endif
5685 #endif
5686
5687 // dbg(0, "SPK:*soon*\n");
5688
5689
5690 d = g_strdup(_("soon"));
5691 break;
5692 case 1:
5693 d = get_distance(nav, distance, attr_navigation_short, 0);
5694 break;
5695 case 0:
5696 // DISABLE S_R // skip_roads = count_possible_turns(nav, cmd->prev ? cmd->prev->itm : nav->first, cmd->itm, cmd->delta);
5697 skip_roads = 0;
5698
5699 dbg(0, "count_possible_turns:1:%d", skip_roads);
5700
5701 if ((skip_roads > 0) && ((global_vehicle_profile != 1) && (global_vehicle_profile != 2)))
5702 {
5703 if (get_count_str(skip_roads + 1))
5704 {
5705
5706 // marker -1- //
5707
5708 #ifdef HAVE_API_ANDROID
5709 #ifdef NAVIT_SAY_DEBUG_PRINT
5710 android_send_generic_text(1,"+*#O:Take the %1$s road to the %2$s\n");
5711 gchar* xy=g_strdup_printf("+*#1:%s\n", get_count_str(skip_roads + 1));
5712 android_send_generic_text(1,xy);
5713 g_free(xy);
5714 xy=g_strdup_printf("+*#1:%s\n", dir);
5715 android_send_generic_text(1,xy);
5716 g_free(xy);
5717 #endif
5718 #endif
5719 // TRANSLATORS: First argument is the how manieth street to take, second the direction
5720 ret = g_strdup_printf_2_str(_("Take the %1$s road to the %2$s"), get_count_str(skip_roads + 1), dir);
5721 return2 ret;
5722 }
5723 else
5724 {
5725 #ifdef HAVE_API_ANDROID
5726 #ifdef NAVIT_SAY_DEBUG_PRINT
5727 android_send_generic_text(1,"+*#O:after %i roads\n");
5728 gchar* xy=g_strdup_printf("+*#1:%i\n", skip_roads);
5729 android_send_generic_text(1,xy);
5730 g_free(xy);
5731 #endif
5732 #endif
5733 d = g_strdup_printf(_("after %i roads"), skip_roads);
5734 }
5735 }
5736 else
5737 {
5738 #ifdef HAVE_API_ANDROID
5739 #ifdef NAVIT_SAY_DEBUG_PRINT
5740 android_send_generic_text(1,"+*#O:now\n");
5741 #endif
5742 #endif
5743 d = g_strdup(_("now"));
5744 }
5745
5746 break;
5747
5748 case -2:
5749 // DISABLE S_R // skip_roads = count_possible_turns(nav, cmd->prev->itm, cmd->itm, cmd->delta);
5750 skip_roads = 0;
5751
5752 dbg(0, "count_possible_turns:2:%d", skip_roads);
5753
5754 if ((skip_roads > 0) && ((global_vehicle_profile != 1) && (global_vehicle_profile != 2)))
5755 {
5756 // TRANSLATORS: First argument is the how manieth street to take, second the direction
5757 // TRANSLATORS: EXAMPLE: ... then take the second road to the right
5758 if (get_count_str(skip_roads + 1))
5759 {
5760
5761 // marker -2- //
5762
5763 #ifdef HAVE_API_ANDROID
5764 #ifdef NAVIT_SAY_DEBUG_PRINT
5765 android_send_generic_text(1,"+*#O:then take the %1$s road to the %2$s\n");
5766 gchar* xy=g_strdup_printf("+*#1:%s\n", get_count_str(skip_roads + 1));
5767 android_send_generic_text(1,xy);
5768 g_free(xy);
5769 xy=g_strdup_printf("+*#1:%s\n", dir);
5770 android_send_generic_text(1,xy);
5771 g_free(xy);
5772 #endif
5773 #endif
5774 ret = g_strdup_printf_2_str(_("then take the %1$s road to the %2$s"), get_count_str(skip_roads + 1), dir);
5775 return2 ret;
5776 }
5777 else
5778 {
5779 #ifdef HAVE_API_ANDROID
5780 #ifdef NAVIT_SAY_DEBUG_PRINT
5781 android_send_generic_text(1,"+*#O:after %i roads\n");
5782 gchar* xy=g_strdup_printf("+*#1:%i\n", skip_roads);
5783 android_send_generic_text(1,xy);
5784 g_free(xy);
5785 #endif
5786 #endif
5787 d = g_strdup_printf(_("after %i roads"), skip_roads);
5788 }
5789
5790 }
5791 else
5792 {
5793 d = g_strdup("");
5794 }
5795 break;
5796 default:
5797 #ifdef HAVE_API_ANDROID
5798 #ifdef NAVIT_SAY_DEBUG_PRINT
5799 android_send_generic_text(1,"+*#O:error\n");
5800 #endif
5801 #endif
5802 d = g_strdup(_("error"));
5803 }
5804
5805
5806
5807 if (cmd->itm->next)
5808 {
5809 // dbg(0, "SPK:000a\n");
5810
5811 int tellstreetname = 0;
5812 char *destination = NULL;
5813
5814 if (type == attr_navigation_speech)
5815 {
5816 if (level == 1)
5817 {
5818 cmd->itm->streetname_told = 1;
5819 tellstreetname = 1; // Ok so we tell the name of the street
5820 }
5821
5822 if (level == 0)
5823 {
5824 if (cmd->itm->streetname_told == 0) // we are right at the intersection
5825 {
5826 tellstreetname = 1;
5827 }
5828 else
5829 {
5830 cmd->itm->streetname_told = 0; // reset just in case we come to the same street again
5831 }
5832 }
5833
5834 }
5835 else
5836 {
5837 tellstreetname = 1;
5838 }
5839
5840 if (global_speak_streetnames == 0)
5841 {
5842 // never speak streetnames (user config option)
5843 tellstreetname = 0;
5844 }
5845
5846
5847
5848 if (override_tellstreetname != -1)
5849 {
5850
5851 #ifdef NAVIT_ROUTING_DEBUG_PRINT
5852 dbg(0, "SPK:level=%d street_dest_text=%p tellstreetname=%d\n", level, cmd->itm->way.street_dest_text, tellstreetname);
5853 #endif
5854 if (nav->tell_street_name && tellstreetname)
5855 {
5856 destination = navigation_item_destination(nav, cmd->itm, itm, " ");
5857 #ifdef NAVIT_ROUTING_DEBUG_PRINT
5858 dbg(0, "SPK:levelX=%d dest=%s\n", level, destination);
5859 #endif
5860 }
5861 else if ((global_speak_streetnames == 1) && (cmd->itm->way.street_dest_text))
5862 {
5863 destination = navigation_item_destination(nav, cmd->itm, itm, " ");
5864 #ifdef NAVIT_ROUTING_DEBUG_PRINT
5865 dbg(0, "SPK:levely=%d dest=%s d=%s\n", level, destination, cmd->itm->way.street_dest_text);
5866 #endif
5867
5868 cmd->itm->streetname_told = 0;
5869 }
5870 }
5871
5872
5873 // dbg(0, "SPK:001\n");
5874
5875 if (level != -2)
5876 {
5877
5878 //dbg(0, "SPK:002\n");
5879
5880 #ifdef HAVE_API_ANDROID
5881 #ifdef NAVIT_SAY_DEBUG_PRINT
5882 android_send_generic_text(1,"+*#O:Turn %1$s%2$s %3$s%4$s\n");
5883 gchar* xy=g_strdup_printf("+*#1:%s\n", strength);
5884 android_send_generic_text(1,xy);
5885 g_free(xy);
5886 xy=g_strdup_printf("+*#1:%s\n", dir);
5887 android_send_generic_text(1,xy);
5888 g_free(xy);
5889 xy=g_strdup_printf("+*#1:%s\n", d);
5890 android_send_generic_text(1,xy);
5891 g_free(xy);
5892 xy=g_strdup_printf("+*#1:%s\n", destination ? destination : "");
5893 android_send_generic_text(1,xy);
5894 g_free(xy);
5895 #endif
5896 #endif
5897
5898 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2)) // bicycle mode
5899 {
5900 //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);
5901
5902 if (level_now == 0)
5903 {
5904 if (against_oneway == 1)
5905 {
5906 if (delta < 8)
5907 {
5908 ret = g_strdup_printf("%s", _("oncoming traffic!")); // just say "attention oneway street!"
5909 }
5910 else
5911 {
5912 ret = g_strdup_printf("%s, %s", dir, _("oncoming traffic!")); // just say "left" or "right" at the turn + "attention oneway street!"
5913 }
5914 }
5915 else
5916 {
5917 ret = g_strdup(dir); // just say "left" or "right" at the turn
5918 }
5919 }
5920 else
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: 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'
5931 ret = g_strdup_printf_4_str(_("%1$s%2$s %3$s%4$s"), "", dir, d, destination ? destination : "");
5932 }
5933 else
5934 {
5935 // 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'
5936 ret = g_strdup_printf_4_str(_("Turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination : "");
5937 }
5938 }
5939 }
5940 }
5941 else // car mode
5942 {
5943 if (delta == 0)
5944 {
5945 // 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'
5946 ret = g_strdup_printf_4_str(_("%1$s%2$s %3$s%4$s"), "", dir, d, destination ? destination : "");
5947 }
5948 else
5949 {
5950 if (keep_dir != 0)
5951 {
5952 if (keep_dir == -1)
5953 {
5954 // TRANSLATORS: The argument is the distance. Example: 'keep left in 100 meters'
5955 ret = g_strdup_printf(_("keep left %s"), d);
5956
5957 // dirty hack, so we don't need new translations
5958 char *ret2 = g_strdup_printf("%s%s", ret, destination ? destination : "");
5959 g_free(ret);
5960 ret = ret2;
5961 // ret2 = NULL;
5962 }
5963 else
5964 {
5965 // TRANSLATORS: The argument is the distance. Example: 'keep right in 100 meters'
5966 ret = g_strdup_printf(_("keep right %s"), d);
5967
5968 // dirty hack, so we don't need new translations
5969 char *ret2 = g_strdup_printf("%s%s", ret, destination ? destination : "");
5970 g_free(ret);
5971 ret = ret2;
5972 // ret2 = NULL;
5973 }
5974 }
5975 else
5976 {
5977 // 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'
5978 ret = g_strdup_printf_4_str(_("Turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination : "");
5979 }
5980 }
5981 }
5982 }
5983 else // (level == -2)
5984 {
5985
5986 //dbg(0, "SPK:007\n");
5987
5988
5989 #ifdef HAVE_API_ANDROID
5990 #ifdef NAVIT_SAY_DEBUG_PRINT
5991 android_send_generic_text(1,"+*#O:then turn %1$s%2$s %3$s%4$s\n");
5992 gchar* xy=g_strdup_printf("+*#1:%s\n", strength);
5993 android_send_generic_text(1,xy);
5994 g_free(xy);
5995 xy=g_strdup_printf("+*#1:%s\n", dir);
5996 android_send_generic_text(1,xy);
5997 g_free(xy);
5998 xy=g_strdup_printf("+*#1:%s\n", d);
5999 android_send_generic_text(1,xy);
6000 g_free(xy);
6001 xy=g_strdup_printf("+*#1:%s\n", destination ? destination : "");
6002 android_send_generic_text(1,xy);
6003 g_free(xy);
6004 #endif
6005 #endif
6006 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2)) // bicycle mode
6007 {
6008 if ((against_oneway == 1) && (delta < 8))
6009 {
6010 ret = g_strdup(""); // probably just going against a oneway street, but travelling straight on. dont say anything now
6011 }
6012 else
6013 {
6014 if (delta == 0)
6015 {
6016 // TRANSLATORS: First argument is strength, second direction, third how many roads to skip, fourth destination
6017 ret = g_strdup_printf_4_str(_("then %1$s%2$s %3$s%4$s"), "", dir, d, destination ? destination : "");
6018 }
6019 else
6020 {
6021 // TRANSLATORS: First argument is strength, second direction, third how many roads to skip, fourth destination
6022 ret = g_strdup_printf_4_str(_("then turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination : "");
6023 }
6024 }
6025 }
6026 else // car mode
6027 {
6028 if (delta == 0)
6029 {
6030 // TRANSLATORS: First argument is strength, second direction, third how many roads to skip, fourth destination
6031 ret = g_strdup_printf_4_str(_("then %1$s%2$s %3$s%4$s"), "", dir, d, destination ? destination : "");
6032 }
6033 else
6034 {
6035 if (keep_dir != 0)
6036 {
6037 if (keep_dir == -1)
6038 {
6039 ret = g_strdup_printf("%s", _("then keep left"));
6040 }
6041 else
6042 {
6043 ret = g_strdup_printf("%s", _("then keep right"));
6044 }
6045 }
6046 else
6047 {
6048 // TRANSLATORS: First argument is strength, second direction, third how many roads to skip, fourth destination
6049 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!
6050 // ret = g_strdup_printf_4_str(_("then turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination : "");
6051 }
6052 }
6053 }
6054 }
6055 g_free(destination);
6056 }
6057 else
6058 {
6059 if (!connect)
6060 {
6061 #ifdef HAVE_API_ANDROID
6062 #ifdef NAVIT_SAY_DEBUG_PRINT
6063 android_send_generic_text(1,"+*#O:You have reached your destination %s\n");
6064 gchar* xy=g_strdup_printf("+*#1:%s\n", d);
6065 android_send_generic_text(1,xy);
6066 g_free(xy);
6067 #endif
6068 #endif
6069 // TRANSLATORS: EXAMPLE: You have reached your destination in 300 meters
6070 ret = g_strdup_printf(_("You have reached your destination %s"), d);
6071 }
6072 else
6073 {
6074 #ifdef HAVE_API_ANDROID
6075 #ifdef NAVIT_SAY_DEBUG_PRINT
6076 android_send_generic_text(1,"+*#O:then you have reached your destination.\n");
6077 #endif
6078 #endif
6079 ret = g_strdup(_("then you have reached your destination."));
6080 }
6081 }
6082 g_free(d);
6083
6084 return2 ret;
6085
6086 __F_END__
6087 }
6088
6089
6090
6091 static char *
6092 show_maneuver(struct navigation *nav, struct navigation_itm *itm, struct navigation_command *cmd, enum attr_type type, int connect)
6093 {
6094 return show_maneuver_at_level(nav, itm, cmd, type, connect, DONT_KNOW_LEVEL, 0);
6095 }
6096
6097
6098
6099
6100 /**
6101 * @brief Creates announcements for maneuvers, plus maneuvers immediately following the next maneuver
6102 *
6103 * This function does create an announcement for the current maneuver and for maneuvers
6104 * immediately following that maneuver, if these are too close and we're in speech navigation.
6105 *
6106 * @return An announcement that should be made
6107 */
6108 // central entry point for TTS maneuvers --------------
6109 // central entry point for TTS maneuvers --------------
6110 // central entry point for TTS maneuvers --------------
6111 static char *
6112 show_next_maneuvers(struct navigation *nav, struct navigation_itm *itm, struct navigation_command *cmd, enum attr_type type)
6113 {
6114 __F_START__
6115
6116 struct navigation_command *cur, *prev;
6117 int distance = itm->dest_length - cmd->itm->dest_length;
6118 int level, dist, i, time, level2;
6119 int speech_time, time2nav;
6120 char *ret, *old, *buf, *next;
6121 char *ret22;
6122
6123 char *temp_txt = NULL;
6124
6125
6126 //dbg(0, "Enter\n");
6127
6128 if (type != attr_navigation_speech)
6129 {
6130 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
6131 {
6132 return2 show_maneuver_bicycle(nav, itm, cmd, type, 0, DONT_KNOW_LEVEL); // not for speech, so just return the real values
6133 }
6134 else
6135 {
6136 return2 show_maneuver(nav, itm, cmd, type, 0); // not for speech, so just return the real values
6137 }
6138 }
6139
6140
6141 int cur_vehicle_speed = 0;
6142 if ((global_navit) && (global_navit->vehicle))
6143 {
6144 cur_vehicle_speed = global_navit->vehicle->speed; // in km/h
6145 }
6146
6147
6148 dbg(0, "SPEECH:[-0v-] current speed=%d\n", cur_vehicle_speed);
6149
6150
6151 // -- bicycle mode START -------------------------------------
6152 // -- bicycle mode START -------------------------------------
6153 // -- bicycle mode START -------------------------------------
6154 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
6155 {
6156 level = navigation_get_announce_level(nav, itm->way.item.type, distance - cmd->length, 0);
6157
6158 //dbg(0, "level = %d\n", level);
6159 //dbg(0, "(nn)itm->way.flags=%x\n", itm->way.flags);
6160 //dbg(0, "(nn)itm->next->way.flags=%x\n", itm->next->way.flags);
6161 //dbg(0, "(nn)distance=%d cmd->length=%d (minus)=%d\n", distance, cmd->length, (distance - cmd->length));
6162
6163 // in bike mode level should only be "0" or "1" or "3" !
6164
6165 if (level > 2)
6166 {
6167 //dbg(0, "just say the current command\n");
6168 return2 show_maneuver_bicycle(nav, itm, cmd, type, 0, level); // just say the current command
6169 }
6170
6171 if (cmd->itm->told)
6172 {
6173 // current command should not be spoken again!
6174 //dbg(0, "current command should not be spoken again\n");
6175 return2 g_strdup("");
6176 }
6177
6178
6179 //dbg(0, "xx 017a fsp, itm->told=%d l=%d\n", cmd->itm->told, level);
6180 if (level == 0)
6181 {
6182 // this command is spoken (now)
6183 //dbg(0, "this command is spoken (now)\n");
6184 cmd->itm->told = 1;
6185 }
6186 //dbg(0, "xx 017b fsp, itm->told=%d\n", cmd->itm->told);
6187
6188
6189 // current maneuver -------
6190 ret = show_maneuver_bicycle(nav, itm, cmd, type, 0, level); // generate TTS text for current command
6191 //dbg(0, "ret cmd=%s\n", ret);
6192 time2nav = navigation_time(itm, cmd->itm->prev);
6193 //dbg(0, "time2nav = %d\n", time2nav);
6194 old = NULL;
6195 // current maneuver -------
6196
6197 cur = cmd->next;
6198 prev = cmd;
6199
6200 if (cur && cur->itm) // we have a next command
6201 {
6202 dist = prev->itm->dest_length - cur->itm->dest_length;
6203 level2 = navigation_get_announce_level(nav, itm->next->way.item.type, dist, 0);
6204 //dbg(0, "(next)level2 = %d\n", level2);
6205 //dbg(0, "(next)dist=%d\n", dist);
6206
6207 if ((level2 < 2) && (dist < (2 * level_static_for_bicycle[0])))
6208 {
6209 //dbg(0, "link next command, and dont say it again!\n");
6210 old = ret;
6211 buf = show_maneuver_bicycle(nav, prev->itm, cur, type, 1, 0); // generate TTS text for next command, and dont say the next command again!
6212 //dbg(0, "next cmd=%s\n", next);
6213 ret = g_strdup_printf("%s, %s", old, buf);
6214 //dbg(0, "next cmd concat=%s\n", ret);
6215 g_free(buf);
6216 g_free(old);
6217 if (level == 0)
6218 {
6219 // dont say this next command again!
6220 cur->itm->told = 1;
6221 }
6222 }
6223 }
6224 }
6225 // -- bicycle mode END -------------------------------------
6226 // -- bicycle mode END -------------------------------------
6227 // -- bicycle mode END -------------------------------------
6228 else
6229 {
6230
6231
6232
6233 // -------------------------------------------------
6234 // -------------------------------------------------
6235 // -- ******************************************* --
6236 // CAR MODE
6237 // -- ******************************************* --
6238 // -------------------------------------------------
6239 // -------------------------------------------------
6240
6241 level = navigation_get_announce_level(nav, itm->way.item.type, distance - cmd->length, ((float)cur_vehicle_speed / 3.6f));
6242 //dbg(0, "level = %d\n", level);
6243 //dbg(0, "(nn)itm->way.flags=%x\n", itm->way.flags);
6244 //dbg(0, "(nn)itm->next->way.flags=%x\n", itm->next->way.flags);
6245
6246 long temp_ts = -1;
6247 debug_get_timestamp_millis(&temp_ts);
6248 if (global_last_spoken == -1)
6249 {
6250 temp_ts = 99999999;
6251 }
6252
6253 int time2nav_2 = navigation_time_real_speed(itm, cmd->itm->prev, cur_vehicle_speed);
6254
6255 dbg(0, "SPEECH:[-00-] last spoken ago=%f\n", (float)((temp_ts - global_last_spoken) / 1000.0f));
6256 dbg(0, "SPEECH:[-01-] meters to next maneuver=%d\n", (distance - cmd->length));
6257 dbg(0, "SPEECH:[-02-] level=%d\n", level);
6258
6259 #ifdef HAVE_API_ANDROID
6260 temp_txt = g_strdup_printf("SPEECH:[-00-] last spoken ago=%f\n", (float)((temp_ts - global_last_spoken) / 1000.0f));
6261 android_send_generic_text(20, temp_txt);
6262 g_free(temp_txt);
6263
6264 temp_txt = g_strdup_printf("SPEECH:[-01-] meters to next maneuver=%d\n", (distance - cmd->length));
6265 android_send_generic_text(20, temp_txt);
6266 g_free(temp_txt);
6267
6268 temp_txt = g_strdup_printf("SPEECH:[-02-] level=%d\n", level);
6269 android_send_generic_text(20, temp_txt);
6270 g_free(temp_txt);
6271 #endif
6272
6273 dbg(0, "SPEECH:[-03-] time2nav secs=%f\n", ((float)time2nav_2 / 10.0f));
6274
6275 int dist_to_next_spoken_command = -1;
6276 float secs_to_next_spoken_command = -1;
6277 if (level > 0)
6278 {
6279 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) ) );
6280
6281 if (cur_vehicle_speed > 0)
6282 {
6283 secs_to_next_spoken_command = ((float)dist_to_next_spoken_command / ((float)cur_vehicle_speed / 3.6f));
6284 }
6285 else
6286 {
6287 secs_to_next_spoken_command = ((float)dist_to_next_spoken_command / ((float)itm->speed / 3.6f));
6288 }
6289 }
6290
6291
6292 // current maneuver -------
6293 ret22 = show_maneuver_at_level(nav, itm, cmd, type, 0, level, 0);
6294 // current maneuver -------
6295
6296 if (nav->speech)
6297 {
6298 speech_time = speech_estimate_duration(nav->speech, ret22);
6299 dbg(0, "SPEECH:[-CUR-] secs=%f text=%s\n", ((float)speech_time)/10.0f, ret22);
6300 }
6301 else
6302 {
6303 speech_time = -1;
6304 dbg(0, "SPEECH:[-CUR-] secs=-1 text=%s\n", ret22);
6305 }
6306
6307
6308 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);
6309
6310 if (level == 3)
6311 {
6312
6313 // ===========----------- LEVEL 3 -----------===========
6314
6315 #if 0
6316 if (((float)((temp_ts - global_last_spoken) / 1000.0f)) < 3.0f)
6317 {
6318 dbg(0, "SPEECH:[-NOOP-] 004: already spoken in the last 3 secs.\n");
6319 return2 g_strdup(""); // dont speak this command now!
6320 }
6321 #endif
6322
6323 if (secs_to_next_spoken_command < 7 )
6324 {
6325 if (ret22)
6326 {
6327 g_free(ret22);
6328 ret22 = NULL;
6329 }
6330
6331 #ifdef _DEBUG_BUILD_
6332 // speak debug ----
6333 navit_say(global_navit, "level 3a wieder in 7 sekunden");
6334 // speak debug ----
6335 #endif
6336
6337 dbg(0, "SPEECH:[-NOOP-] 006b: want to speak again in less than %d secs. level=%d\n", 7, level);
6338 return2 g_strdup(""); // dont speak this command now!
6339 }
6340
6341 if (secs_to_next_spoken_command < (((float)speech_time/10.0f) + 3) )
6342 {
6343 if (ret22)
6344 {
6345 g_free(ret22);
6346 ret22 = NULL;
6347 }
6348
6349 #ifdef _DEBUG_BUILD_
6350 // speak debug ----
6351 temp_txt = g_strdup_printf("level 3b wieder in %d sekunden", (int)(((float)speech_time/10.0f) + 3));
6352 navit_say(global_navit, temp_txt);
6353 g_free(temp_txt);
6354 // speak debug ----
6355 #endif
6356
6357 dbg(0, "SPEECH:[-NOOP-] 006: want to speak again in less than %d secs. level=%d\n", (((float)speech_time/10.0f) + 3), level );
6358 return2 g_strdup(""); // dont speak this command now!
6359 }
6360 // ===========----------- LEVEL 3 -----------===========
6361
6362
6363 }
6364 else if (level == 2)
6365 {
6366
6367 // ===========----------- LEVEL 2 -----------===========
6368
6369
6370 #if 0
6371 if (secs_to_next_spoken_command < 3 )
6372 {
6373 if (ret22)
6374 {
6375 g_free(ret22);
6376 ret22 = NULL;
6377 }
6378
6379 #ifdef _DEBUG_BUILD_
6380 // speak debug ----
6381 navit_say(global_navit, "level 2a wieder in 3 sekunden");
6382 // speak debug ----
6383 #endif
6384
6385 dbg(0, "SPEECH:[-NOOP-] 007b: want to speak again in less than %d secs. level=%d\n", 3, level);
6386 return2 g_strdup(""); // dont speak this command now!
6387 }
6388 #endif
6389
6390 #if 1
6391 if (secs_to_next_spoken_command < (((float)speech_time/10.0f) + 1) )
6392 {
6393 if (ret22)
6394 {
6395 g_free(ret22);
6396 ret22 = NULL;
6397 }
6398
6399 #ifdef _DEBUG_BUILD_
6400 // speak debug ----
6401 temp_txt = g_strdup_printf("level 2b wieder in %d sekunden", (int)(((float)speech_time/10.0f) + 1));
6402 navit_say(global_navit, temp_txt);
6403 // speak debug ----
6404 #endif
6405
6406 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);
6407 return2 g_strdup(""); // dont speak this command now!
6408 }
6409 #endif
6410
6411 #if 0
6412 if (((float)((temp_ts - global_last_spoken) / 1000.0f)) < 5.0f)
6413 {
6414 if (ret22)
6415 {
6416 g_free(ret22);
6417 ret22 = NULL;
6418 }
6419
6420 #ifdef _DEBUG_BUILD_
6421 // speak debug ----
6422 navit_say(global_navit, "level 2c schon vor 5 sekunden");
6423 // speak debug ----
6424 #endif
6425
6426 dbg(0, "SPEECH:[-NOOP-] 005: already spoken in the last 5 secs. level=%d\n", level);
6427 return2 g_strdup(""); // dont speak this command now!
6428 }
6429 #endif
6430
6431 // ===========----------- LEVEL 2 -----------===========
6432
6433
6434 }
6435 else if (level == 1)
6436 {
6437
6438 // ===========----------- LEVEL 1 -----------===========
6439
6440
6441 #if 0
6442 if (((float)time2nav_2 / 10.0f) < 5.0f)
6443 {
6444 dbg(0, "SPEECH:[-NOOP-] 001: less than 5 secs. to maneuver\n");
6445 return2 g_strdup(""); // dont speak this command now!
6446 }
6447 #endif
6448
6449 #if 0
6450 if ((distance - cmd->length) < 50)
6451 {
6452 dbg(0, "SPEECH:[-NOOP-] 003: less than 50 meters to maneuver\n");
6453 return2 g_strdup(""); // dont speak this command now!
6454 }
6455 #endif
6456
6457
6458 if (dist_to_next_spoken_command < 18)
6459 {
6460 if (ret22)
6461 {
6462 g_free(ret22);
6463 ret22 = NULL;
6464 }
6465
6466 #ifdef _DEBUG_BUILD_
6467 // speak debug ----
6468 temp_txt = g_strdup_printf("level 1a wieder in %d sekunden", 18);
6469 navit_say(global_navit, temp_txt);
6470 g_free(temp_txt);
6471 // speak debug ----
6472 #endif
6473
6474
6475 dbg(0, "SPEECH:[-NOOP-] 011: less than 18 meters to next announcement\n");
6476 return2 g_strdup(""); // dont speak this command now!
6477 }
6478
6479 #if 0
6480 if (((float)((temp_ts - global_last_spoken) / 1000.0f)) < 4.0f)
6481 {
6482 if (ret22)
6483 {
6484 g_free(ret22);
6485 ret22 = NULL;
6486 }
6487
6488 dbg(0, "SPEECH:[-NOOP-] 002: already spoken in the last 4 secs. level=%d\n", level);
6489 return2 g_strdup(""); // dont speak this command now!
6490 }
6491 #endif
6492
6493 if (secs_to_next_spoken_command < (((float)speech_time/10.0f) + 1) )
6494 {
6495 if (secs_to_next_spoken_command < 3.0f)
6496 {
6497 if (ret22)
6498 {
6499 g_free(ret22);
6500 ret22 = NULL;
6501 }
6502
6503 #ifdef _DEBUG_BUILD_
6504 // speak debug ----
6505 temp_txt = g_strdup_printf("level 1b wieder in %d sekunden", 3);
6506 navit_say(global_navit, temp_txt);
6507 g_free(temp_txt);
6508 // speak debug ----
6509 #endif
6510
6511
6512 dbg(0, "SPEECH:[-NOOP-] 008: want to speak again in less than %d secs. level=%d\n", (((float)speech_time/10.0f) + 1), level);
6513 return2 g_strdup(""); // dont speak this command now!
6514 }
6515 else
6516 {
6517 // if we have at least 3 seconds left, still say level 1 announcement (without the streetname/destination name)
6518 dbg(0, "SPEECH:[-NOOP-] 008lo: use level=%d announcement without destination name\n", level);
6519 if (ret22)
6520 {
6521 g_free(ret22);
6522 ret22 = NULL;
6523 }
6524 ret22 = show_maneuver_at_level(nav, itm, cmd, type, 0, level, -1);
6525 if (nav->speech)
6526 {
6527 speech_time = speech_estimate_duration(nav->speech, ret22);
6528 dbg(0, "SPEECH:[-CUR-] :lo: secs=%f text=%s\n", ((float)speech_time)/10.0f, ret22);
6529 }
6530 else
6531 {
6532 speech_time = -1;
6533 dbg(0, "SPEECH:[-CUR-] :lo: secs=-1 text=%s\n", next);
6534 }
6535
6536 if (secs_to_next_spoken_command < (((float)speech_time/10.0f) + 0) )
6537 {
6538 if (ret22)
6539 {
6540 g_free(ret22);
6541 ret22 = NULL;
6542 }
6543
6544 #ifdef _DEBUG_BUILD_
6545 // speak debug ----
6546 temp_txt = g_strdup_printf("level 1c wieder in %d sekunden", (int)(((float)speech_time/10.0f) + 0));
6547 navit_say(global_navit, temp_txt);
6548 g_free(temp_txt);
6549 // speak debug ----
6550 #endif
6551
6552
6553 dbg(0, "SPEECH:[-NOOP-] 008loEE: giving up on this announcement\n");
6554 return2 g_strdup(""); // dont speak this command now!
6555 }
6556 }
6557 }
6558
6559 // ===========----------- LEVEL 1 -----------===========
6560
6561 }
6562
6563
6564
6565
6566
6567
6568 #ifdef HAVE_API_ANDROID
6569 temp_txt = g_strdup_printf("SPEECH:[-03-] time2nav secs=%f\n", ((float)time2nav_2 / 10.0f));
6570 android_send_generic_text(20, temp_txt);
6571 g_free(temp_txt);
6572 #endif
6573
6574 if (level > 1)
6575 {
6576 dbg(0, "SPEECH:[-R1-]\n");
6577 return2 ret22; // We accumulate maneuvers only if they are close (level-0 and level-1)
6578 }
6579
6580 if (cmd->itm->told)
6581 {
6582 #ifdef HAVE_API_ANDROID
6583 #ifdef NAVIT_SAY_DEBUG_PRINT
6584 android_send_generic_text(1,"+*#C1:*CANCEL*\n");
6585 #endif
6586 #endif
6587 dbg(0, "SPEECH:[-R2-]\n");
6588 #ifdef HAVE_API_ANDROID
6589 temp_txt = g_strdup("SPEECH:[-R2-]\n");
6590 android_send_generic_text(20, temp_txt);
6591 g_free(temp_txt);
6592 #endif
6593 if (ret22)
6594 {
6595 g_free(ret22);
6596 ret22 = NULL;
6597 }
6598
6599
6600 return2 g_strdup("");
6601 }
6602
6603
6604 // current maneuver -------
6605 ret = ret22;
6606 time2nav = navigation_time_real_speed(itm, cmd->itm->prev, cur_vehicle_speed);
6607 // current maneuver -------
6608
6609
6610 #if 0
6611 if (nav->speech)
6612 {
6613 speech_time = speech_estimate_duration(nav->speech, ret);
6614 dbg(0, "SPEECH:[-CUR-] secs=%f text=%s\n", ((float)speech_time)/10.0f, ret);
6615 }
6616 else
6617 {
6618 speech_time = -1;
6619 dbg(0, "SPEECH:[-CUR-] secs=-1 text=%s\n", next);
6620 }
6621 #endif
6622
6623
6624 old = NULL;
6625
6626 dbg(0, "SPEECH:[-04-] time2nav secs=%f\n", ((float)time2nav / 10.0f));
6627 #ifdef HAVE_API_ANDROID
6628 temp_txt = g_strdup_printf("SPEECH:[-04-] time2nav secs=%f\n", ((float)time2nav / 10.0f));
6629 android_send_generic_text(20, temp_txt);
6630 g_free(temp_txt);
6631 #endif
6632
6633
6634
6635
6636 // next maneuver -------
6637 cur = cmd->next;
6638 prev = cmd;
6639 // next maneuver -------
6640
6641
6642 i = 0;
6643 int max_announcements = 3;
6644 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
6645 {
6646 max_announcements = 2;
6647 }
6648
6649 while (cur && cur->itm) // only accumulate at "level 0" or "level 1"
6650 {
6651 // We don't merge more than "max_announcements" announcements...
6652 if (i > (max_announcements - 2))
6653 {
6654 break;
6655 }
6656
6657 dist = prev->itm->dest_length - cur->itm->dest_length; // distance between next 2 maneuvers in meters
6658
6659 if (dist > 420) // too far apart, bail out
6660 {
6661 break;
6662 }
6663
6664 next = show_maneuver(nav, prev->itm, cur, type, 0);
6665 if (nav->speech)
6666 {
6667 speech_time = speech_estimate_duration(nav->speech, next);
6668 dbg(0, "SPEECH:[-NXT-] secs=%f text=%s\n", ((float)speech_time)/10.0f, next);
6669 }
6670 else
6671 {
6672 speech_time = -1;
6673 dbg(0, "SPEECH:[-NXT-] secs=-1 text=%s\n", next);
6674 }
6675 g_free(next);
6676
6677 if (speech_time == -1)
6678 {
6679 // user didn't set cps
6680 speech_time = 25; // assume 2.5 seconds
6681 dbg(0, "SPEECH:[-NXT-](2) secs=%f\n", ((float)speech_time)/10.0f);
6682 }
6683
6684 //if (cur_vehicle_speed > 0)
6685 //{
6686 // time = ((float)dist / ((float)cur_vehicle_speed / 3.6f)) * 10;
6687 //}
6688 //else
6689 //{
6690 // time = navigation_time_real_speed(prev->itm, cur->itm->prev, cur_vehicle_speed);
6691 time = navigation_time(prev->itm, cur->itm->prev);
6692 //}
6693
6694 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);
6695 #ifdef HAVE_API_ANDROID
6696 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);
6697 android_send_generic_text(20, temp_txt);
6698 g_free(temp_txt);
6699 #endif
6700
6701
6702 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
6703 {
6704 // !! should never get here !!
6705 }
6706 else
6707 {
6708 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);
6709
6710 if (i == 0)
6711 {
6712 if (dist < 170) // distance between maneuvers less than 170m --> always merge maneuvers
6713 {
6714 }
6715 else
6716 {
6717 // **OLD** // if (time >= (speech_time + 35)) // (time to turn) >= (time to speak command + 3.5 secs.)
6718 if (time > ((global_level1_announcement * 10.0f) - 3) ) // more than "global_level1_announcement" seconds to next maneuver -> don't merge it
6719 {
6720 dbg(0, "SPEECH:*break first*\n");
6721 break;
6722 }
6723 }
6724 }
6725 else
6726 {
6727 if (time > (global_level0_announcement * 10.0f)) // more than "global_level0_announcement" seconds to next maneuver -> don't merge it
6728 {
6729 dbg(0, "SPEECH:*break next*\n");
6730 break;
6731 }
6732 }
6733 }
6734
6735 old = ret;
6736 buf = show_maneuver(nav, prev->itm, cur, type, 1);
6737 ret = g_strdup_printf("%s, %s", old, buf);
6738 g_free(buf);
6739
6740 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);
6741 // if (nav->speech && speech_estimate_duration(nav->speech, ret) > time2nav)
6742 // {
6743 // g_free(ret);
6744 // ret = old;
6745 // i = (max_announcements - 1); // This will terminate the loop
6746 // dbg(0, "SPEECH:*terminate loop*\n");
6747 // }
6748 // else
6749 // {
6750 g_free(old);
6751 // }
6752
6753
6754 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
6755 {
6756 // !! should never get here !!
6757 }
6758 else
6759 {
6760 #if 0
6761 dbg(0, "SPEECH: time secs=%f speech_time secs=%f [if (time <= speech_time)]\n", ((float)time)/10.0f, ((float)speech_time)/10.0f);
6762 // If the two maneuvers are *really* close, we shouldn't tell the second one again, because TTS won't be fast enough
6763 if (time <= speech_time)
6764 {
6765 #ifdef HAVE_API_ANDROID
6766 #ifdef NAVIT_SAY_DEBUG_PRINT
6767 android_send_generic_text(1,"+*#C2:*CANCEL*\n");
6768 #endif
6769 #endif
6770 //dbg(0, "cancel speak:%s\n", ret);
6771 cur->itm->told = 1;
6772 }
6773 #endif
6774 }
6775
6776 prev = cur;
6777 cur = cur->next;
6778 i++;
6779 }
6780
6781 // -------------------------------------------------
6782 // -------------------------------------------------
6783 // -- ******************************************* --
6784 // CAR MODE
6785 // -- ******************************************* --
6786 // -------------------------------------------------
6787 // -------------------------------------------------
6788
6789 }
6790
6791 dbg(0, "SPEECH:[-Re-]\n");
6792 #ifdef HAVE_API_ANDROID
6793 temp_txt = g_strdup("SPEECH:[-Re-]\n");
6794 android_send_generic_text(20, temp_txt);
6795 g_free(temp_txt);
6796 #endif
6797
6798 return2 ret;
6799
6800 __F_END__
6801 }
6802 // central entry point for TTS maneuvers --------------
6803 // central entry point for TTS maneuvers --------------
6804 // central entry point for TTS maneuvers --------------
6805
6806
6807
6808 // ----- global var, BAD!! -------
6809 int global_spoke_last_position_update = 0;
6810 int previous_dest_length = -1;
6811 int previous_dest_length_save = -1;
6812 struct navigation_command *last_first_cmd_save = NULL;
6813 int global_turn_around_spoken = 0;
6814 // ----- global var, BAD!! -------
6815
6816 static void navigation_call_callbacks(struct navigation *this_, int force_speech)
6817 {
6818 __F_START__
6819
6820 int distance, level = 0;
6821 int level_cur;
6822 int distance_orig;
6823 void *p = this_;
6824 int dont_speak_yet = 0;
6825 int level_last_save = 99;
6826
6827 if (!this_->cmd_first)
6828 {
6829 //dbg(0, "ret 0001\n");
6830 global_spoke_last_position_update = 0;
6831 return2;
6832 }
6833
6834 // EMPTY: calls nothing!!
6835 // ****** // callback_list_call(this_->callback, 1, &p);
6836
6837 //if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
6838 //{
6839 // force_speech = 7;
6840 //}
6841
6842 //dbg(0, "force_speech=%d turn_around=%d turn_around_limit=%d\n", force_speech, this_->turn_around, this_->turn_around_limit);
6843
6844 distance = this_->first->dest_length - this_->cmd_first->itm->dest_length;
6845 //dbg(0, "fdl=%d cmdidl=%d\n", this_->first->dest_length, this_->cmd_first->itm->dest_length);
6846 distance_orig = distance;
6847 distance = round_distance(distance);
6848
6849 int cur_vehicle_speed = 0;
6850 if ((global_navit) && (global_navit->vehicle))
6851 {
6852 cur_vehicle_speed = global_navit->vehicle->speed;
6853 }
6854
6855 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);
6856
6857
6858 if (this_->turn_around_limit && this_->turn_around == this_->turn_around_limit)
6859 {
6860
6861 dbg(0, "NAV_TURNAROUND:005 ta=%d talimit=%d\n", this_->turn_around, this_->turn_around_limit);
6862
6863 //dbg(0, "xx 001 d=%d rd=%d dt=%d\n", distance_orig, distance_orig, this_->distance_turn);
6864 #if 0
6865 while (distance > this_->distance_turn)
6866 {
6867 this_->level_last = 4;
6868 level = 4;
6869 force_speech = 2;
6870
6871 if (this_->distance_turn >= 500)
6872 {
6873 this_->distance_turn *= 2;
6874 }
6875 else
6876 {
6877 this_->distance_turn = 500;
6878 }
6879 #endif
6880
6881 // we need to force a maneuver for "turn around" ------------------
6882 this_->level_last = 4;
6883 level = 4;
6884 force_speech = 2;
6885 // this_->distance_turn *= 100;
6886
6887 #if 1
6888 global_driven_away_from_route = 0;
6889 global_spoke_last_position_update = 0;
6890 global_last_spoken = -1;
6891 previous_dest_length = -1;
6892 previous_dest_length_save = -1;
6893 last_first_cmd_save = NULL;
6894 #endif
6895
6896 this_->level_last = 99;
6897
6898
6899 this_->level_last = level;
6900 this_->curr_delay = 0;
6901
6902 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);
6903 dbg(0, "NCC_:========= END ==========\n");
6904
6905 global_spoke_last_position_update = 1;
6906
6907 // ----------------------------------
6908 // ----------------------------------
6909 // calls -> calls navit_speak
6910 //
6911 callback_list_call(this_->callback_speech, 1, &p);
6912 // ----------------------------------
6913 // ----------------------------------
6914
6915
6916 return2;
6917
6918 // we need to force a maneuver for "turn around" ------------------
6919
6920 #if 0
6921 dbg(0, "NCC_:loop 001 d=%d dt=%d force_speech=%d\n", distance, this_->distance_turn, force_speech);
6922 }
6923 #endif
6924
6925 }
6926 else if (!this_->turn_around_limit || this_->turn_around != this_->turn_around_limit)
6927 {
6928 this_->distance_turn = 50;
6929
6930 global_turn_around_spoken = 0; // reset turn around speak flag
6931
6932 //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);
6933 //dbg(0, "xx 002a d=%d d2=%d diff=%d\n", distance, (distance - this_->cmd_first->length), (this_->cmd_first->itm->length - distance_orig));
6934
6935 //dbg(0, "xx 002a ll001=%d\n", (this_->cmd_first->itm->prev->dest_length - this_->cmd_first->itm->dest_length));
6936
6937 distance -= this_->cmd_first->length;
6938
6939
6940 level = navigation_get_announce_level_cmd(this_, this_->first, this_->cmd_first, distance_orig, ((float)cur_vehicle_speed / 3.6f) );
6941 level_cur = navigation_get_announce_level(this_, this_->first->way.item.type, distance_orig, ((float)cur_vehicle_speed / 3.6f));
6942
6943
6944
6945 if (last_first_cmd_save != this_->cmd_first)
6946 {
6947 last_first_cmd_save = this_->cmd_first;
6948 previous_dest_length = previous_dest_length_save;
6949 }
6950 previous_dest_length_save = this_->cmd_first->itm->dest_length;
6951 // level_last_save = this_->level_last;
6952
6953 //dbg(0, "NCC_:\n");
6954 //dbg(0, "NCC_:0---passed item?---\n");
6955 // 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);
6956
6957 #if 1
6958 if (previous_dest_length == -1)
6959 {
6960 dbg(0, "NCC_:no prev nav command\n");
6961 }
6962 else
6963 {
6964 if (distance_orig > 40)
6965 {
6966 if ((distance_orig + 25) >= (previous_dest_length - this_->cmd_first->itm->dest_length))
6967 {
6968 // we are still within 25 meters of the previous navigation command item
6969 dont_speak_yet = 1;
6970 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));
6971 }
6972 }
6973 #if 1
6974 else if (distance_orig > 20)
6975 {
6976 if ((distance_orig) > (previous_dest_length - this_->cmd_first->itm->dest_length))
6977 {
6978 // we are still at the position of the previous navigation command item
6979 dont_speak_yet = 1;
6980 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));
6981 }
6982 }
6983 #endif
6984 }
6985 #endif
6986
6987 //dbg(0, "NCC_:1---passed item?---\n");
6988 //dbg(0, "NCC_:\n");
6989
6990
6991
6992
6993 //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);
6994
6995 if (level < this_->level_last)
6996 {
6997 /* only tell if the level is valid for more than 3 seconds */
6998 int speed_distance = this_->first->speed * 30 / 36;
6999
7000 dbg(0, "NCC_:speed_distance=%d\n", speed_distance);
7001
7002
7003 //dbg(0, "xx 003 speed_distance=%d this_->first->speed=%d globalslp=%d\n", speed_distance, this_->first->speed, global_spoke_last_position_update);
7004
7005 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
7006 {
7007
7008 level = level_cur;
7009
7010 if ((level_cur > 0) && (global_spoke_last_position_update > 0))
7011 {
7012 // skip this time, speak command on the next update
7013 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);
7014 }
7015 else
7016 {
7017 this_->level_last = level_cur;
7018 force_speech = 3;
7019 dbg(0, "NCC_:force_speech(2)=%d\n", force_speech);
7020 }
7021 }
7022 else
7023 {
7024 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)
7025 {
7026 //dbg(0, "distance %d speed_distance %d\n", distance, speed_distance);
7027 //dbg(0, "level %d < %d\n", level, this_->level_last);
7028 this_->level_last = level;
7029 force_speech = 3;
7030 dbg(0, "NCC_:force_speech(3)=%d\n", force_speech);
7031 //dbg(0, "xx 004\n");
7032 }
7033 }
7034 }
7035
7036
7037 if (!item_is_equal(this_->cmd_first->itm->way.item, this_->item_last))
7038 {
7039 //dbg(0, "xx 005\n");
7040
7041 this_->item_last = this_->cmd_first->itm->way.item;
7042 this_->level_last = 99; // new item, reset command level
7043
7044 dbg(0, "NCC_:Ni---new navigation command item!!---\n");
7045
7046 if (this_->delay)
7047 {
7048 this_->curr_delay = this_->delay;
7049 }
7050 else
7051 {
7052 // if ((level_cur > 0) && (global_spoke_last_position_update > 0) && (distance_orig > 50))
7053 // {
7054 // // skip this time, speak command on the next update
7055 // dbg(0, "NCC_:SKIP[2] speech this update, speak at next update (%d)!\n", global_spoke_last_position_update);
7056 // }
7057 // else
7058 // {
7059 force_speech = 5;
7060 dbg(0, "NCC_:force_speech(4)=%d\n", force_speech);
7061 // }
7062 }
7063 }
7064 else
7065 {
7066 //dbg(0, "xx 006\n");
7067
7068 if (this_->curr_delay)
7069 {
7070 this_->curr_delay--;
7071
7072 if (!this_->curr_delay)
7073 {
7074 force_speech = 4;
7075 dbg(0, "NCC_:force_speech(5)=%d\n", force_speech);
7076 }
7077 }
7078 }
7079 }
7080
7081 if (global_spoke_last_position_update > 0)
7082 {
7083 //dbg(0,"globalslp(1)=%d\n", global_spoke_last_position_update);
7084 global_spoke_last_position_update--;
7085 //dbg(0,"globalslp(2)=%d\n", global_spoke_last_position_update);
7086 }
7087
7088
7089 #if 0
7090 //dbg(0,"XA 000\n");
7091 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2)) // bicycle mode
7092 {
7093 if ((this_->previous) && (!item_is_equal(this_->cmd_first->itm->way.item, this_->previous->way.item)))
7094 {
7095 // item has changed, check if we missed a spoken level 0 command
7096 if (this_->previous->told == 0)
7097 {
7098 dbg(0, "NCC_:MISSED a level 0 spoken command!\n");
7099
7100 char *dir2 = _("right");
7101 int delta2 = this_->cmd_previous->delta;
7102 dbg(0, "NCC_:missed delta = %d\n", delta2);
7103 if (delta2 < 0)
7104 {
7105 // TRANSLATORS: left, as in 'Turn left'
7106 dir2 = _("left");
7107 delta2 = -delta2;
7108 }
7109
7110 if (delta2 > 20)
7111 {
7112 dbg(0,"NCC_:XA 002a\n");
7113 navit_say(this_->navit, dir2);
7114 this_->previous->told = 1;
7115 }
7116 }
7117 }
7118 }
7119 #endif
7120
7121
7122 this_->previous = this_->cmd_first->itm;
7123 this_->cmd_previous = this_->cmd_first;
7124
7125 #if 1
7126 if ((dont_speak_yet == 1) && (force_speech))
7127 {
7128 dbg(0,"NCC_:this_->level_last = 99\n");
7129 this_->level_last = 99;
7130 }
7131 #endif
7132
7133 if (global_driven_away_from_route == 1)
7134 {
7135 dbg(0,"NCC_:** NEW PATH **\n");
7136 global_driven_away_from_route = 0;
7137 global_spoke_last_position_update = 0;
7138 global_last_spoken = -1;
7139 previous_dest_length = -1;
7140 previous_dest_length_save = -1;
7141 last_first_cmd_save = NULL;
7142
7143 this_->level_last = 99;
7144 }
7145
7146 if ( (dont_speak_yet == 0) || ((global_vehicle_profile == 1) || (global_vehicle_profile == 2)) )
7147 {
7148 if (force_speech)
7149 {
7150 this_->level_last = level;
7151 this_->curr_delay = 0;
7152
7153 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);
7154 dbg(0, "NCC_:========= END ==========\n");
7155
7156 global_spoke_last_position_update = 1;
7157
7158 // ----------------------------------
7159 // ----------------------------------
7160 // calls -> calls navit_speak
7161 //
7162 callback_list_call(this_->callback_speech, 1, &p);
7163 // ----------------------------------
7164 // ----------------------------------
7165 }
7166 }
7167
7168 __F_END__
7169 }
7170
7171
7172 // ----------- main place where navigation commands are generated ------------
7173 // ----------- main place where navigation commands are generated ------------
7174 // ----------- main place where navigation commands are generated ------------
7175 static void navigation_update(struct navigation *this_, struct route *route, struct attr *attr)
7176 {
7177 __F_START__
7178
7179 struct map *map;
7180 struct map_rect *mr;
7181 struct item *ritem; /* Holds an item from the route map */
7182 struct item *sitem; /* Holds the corresponding item from the actual map */
7183 struct attr street_item, street_direction;
7184 struct navigation_itm *itm;
7185 struct attr vehicleprofile;
7186 int mode = 0, incr = 0, first = 1;
7187
7188 //dbg(0, "Enter\n");
7189
7190 if (attr->type != attr_route_status)
7191 {
7192 //dbg(0, "return 001\n");
7193 return2;
7194 }
7195
7196 #ifdef NAVIT_ROUTING_DEBUG_PRINT
7197 dbg(0, "RS:001:route_status=%s\n", route_status_to_name(attr->u.num));
7198 #endif
7199
7200
7201 dbg(0, "NCC_:NU:RRRRSSSSSS::route_status=%s\n", route_status_to_name(attr->u.num));
7202
7203 if (attr->u.num == route_status_path_done_new)
7204 {
7205 // route calculated new, you drove a different path?
7206 global_driven_away_from_route = 1;
7207 }
7208
7209
7210 //dbg(1, "enter %d\n", mode);
7211 if (attr->u.num == route_status_no_destination || attr->u.num == route_status_not_found || attr->u.num == route_status_path_done_new)
7212 {
7213 dbg(0, "NCC_:NU:navigation_flush\n");
7214 navigation_flush(this_);
7215 }
7216
7217 if (attr->u.num != route_status_path_done_new && attr->u.num != route_status_path_done_incremental)
7218 {
7219 //dbg(0, "return 002\n");
7220 dbg(0, "NCC_:NU:ret 001\n");
7221
7222 return2;
7223 }
7224
7225 if (!this_->route)
7226 {
7227 //dbg(0, "return 003\n");
7228 dbg(0, "NCC_:NU:ret 002\n");
7229
7230 return2;
7231 }
7232
7233 map = route_get_map(this_->route);
7234 if (!map)
7235 {
7236 //dbg(0, "return 004\n");
7237 return2;
7238 }
7239
7240 mr = map_rect_new(map, NULL);
7241
7242 if (!mr)
7243 {
7244 //dbg(0, "return 005\n");
7245 return2;
7246 }
7247
7248 if (route_get_attr(route, attr_vehicleprofile, &vehicleprofile, NULL))
7249 {
7250 this_->vehicleprofile = vehicleprofile.u.vehicleprofile;
7251 }
7252 else
7253 {
7254 this_->vehicleprofile = NULL;
7255 }
7256
7257 //dbg(1,"enter\n");
7258
7259 dbg(0, "NCC_:NU:------ LOOP START ------\n");
7260
7261 int first_item = 1;
7262 this_->turn_around = 0;
7263
7264 while ((ritem = map_rect_get_item(mr)))
7265 {
7266
7267 dbg(0, "NAVR:001:%s\n", item_to_name(ritem->type));
7268
7269 #if 0
7270 if (ritem->type == type_route_start && this_->turn_around > -this_->turn_around_limit + 1)
7271 {
7272 this_->turn_around--;
7273 }
7274
7275 if (ritem->type == type_route_start_reverse && this_->turn_around < this_->turn_around_limit)
7276 {
7277 this_->turn_around++;
7278 dbg(0, "NAVR:001.1:** TURN AROUND **\n");
7279 }
7280 #endif
7281
7282 #if 1
7283 if (first_item == 1)
7284 {
7285 first_item = 0;
7286 if (ritem->type == type_route_start_reverse)
7287 {
7288 this_->turn_around = this_->turn_around_limit;
7289
7290 dbg(0, "NAV_TURNAROUND:006 ta=%d talimit=%d\n", this_->turn_around, this_->turn_around_limit);
7291
7292 dbg(0, "NAVR:001.1:T_A:** TURN AROUND **:%s\n", item_to_name(ritem->type));
7293 }
7294 else
7295 {
7296 dbg(0, "NAVR:001.1:T_A:first item=%s\n", item_to_name(ritem->type));
7297 }
7298 }
7299 #endif
7300
7301
7302 dbg(0, "NAVR:001:X1:%s\n", item_to_name(ritem->type));
7303 if ((ritem->type != type_street_route) && (ritem->type != type_street_route_waypoint))
7304 {
7305 dbg(0, "NAVR:001:X2R:%s\n", item_to_name(ritem->type));
7306 continue;
7307 }
7308 dbg(0, "NAVR:001:X3:%s\n", item_to_name(ritem->type));
7309
7310 if (first && item_attr_get(ritem, attr_street_item, &street_item))
7311 {
7312 first = 0;
7313 if (!item_attr_get(ritem, attr_direction, &street_direction))
7314 {
7315 street_direction.u.num = 0;
7316 }
7317
7318 sitem = street_item.u.item;
7319 //dbg(1,"sitem=%p\n", sitem);
7320 itm = item_hash_lookup(this_->hash, sitem);
7321 //dbg(2,"itm for item with id (0x%x,0x%x) is %p\n", sitem->id_hi, sitem->id_lo, itm);
7322
7323 if (itm && itm->way.dir != street_direction.u.num)
7324 {
7325 //dbg(2,"wrong direction\n");
7326 dbg(0, "NAVR:001.2:*+ WRONG DIRECTION +*\n");
7327 itm = NULL;
7328 }
7329
7330 dbg(0, "NCC_:NU:navigation_destroy_itms_cmds\n");
7331 navigation_destroy_itms_cmds(this_, itm);
7332
7333 if (itm)
7334 {
7335 dbg(0, "NCC_:NU:navigation_itm_update\n");
7336
7337 navigation_itm_update(itm, ritem);
7338 break;
7339 }
7340 //dbg(1,"not on track\n");
7341 }
7342
7343 dbg(0, "NAVR:001:X4:%s\n", item_to_name(ritem->type));
7344 dbg(0, "NCC_:NU:navigation_itm_new\n");
7345 navigation_itm_new(this_, ritem);
7346 dbg(0, "NAVR:001:X5:%s\n", item_to_name(ritem->type));
7347
7348 }
7349
7350
7351 dbg(0, "NCC_:NU:------ LOOP END ------\n");
7352
7353
7354 //dbg(2, "turn_around=%d\n", this_->turn_around);
7355
7356 if (first)
7357 {
7358
7359 #ifdef NAVIT_FREE_TEXT_DEBUG_PRINT
7360 dbg(0, "DEST::route_clear_freetext_list\n");
7361 route_clear_freetext_list();
7362 #endif
7363
7364 dbg(0, "NCC_:NU:navigation_destroy_itms_cmds[first]\n");
7365
7366 navigation_destroy_itms_cmds(this_, NULL);
7367 }
7368 else
7369 {
7370 if (!ritem)
7371 {
7372 dbg(0, "NCC_:NU:navigation_itm_new[!ritem]\n");
7373 navigation_itm_new(this_, NULL);
7374 //dbg(0, "Enter: make_maneuvers\n");
7375 dbg(0, "NAVR:001.2:*= MAKE MANEUVERS =*\n");
7376 dbg(0, "NCC_:NU:make_maneuvers[!ritem]\n");
7377 make_maneuvers(this_, this_->route);
7378 //dbg(0, "end : make_maneuvers\n");
7379 }
7380
7381 dbg(0, "NCC_:NU:calculate_dest_distance\n");
7382 calculate_dest_distance(this_, incr);
7383
7384 // calls navit_speak later !! ----------
7385 navigation_call_callbacks(this_, FALSE);
7386 // calls navit_speak later !! ----------
7387 }
7388 map_rect_destroy(mr);
7389
7390 __F_END__
7391 }
7392 // ----------- main place where navigation commands are generated ------------
7393 // ----------- main place where navigation commands are generated ------------
7394 // ----------- main place where navigation commands are generated ------------
7395
7396
7397 static void navigation_flush(struct navigation *this_)
7398 {
7399 __F_START__
7400 navigation_destroy_itms_cmds(this_, NULL);
7401 __F_END__
7402 }
7403
7404 void navigation_destroy(struct navigation *this_)
7405 {
7406 navigation_flush(this_);
7407 item_hash_destroy(this_->hash);
7408 callback_list_destroy(this_->callback);
7409 callback_list_destroy(this_->callback_speech);
7410 g_free(this_);
7411 }
7412
7413 int navigation_register_callback(struct navigation *this_, enum attr_type type, struct callback *cb)
7414 {
7415 __F_START__
7416
7417 if (type == attr_navigation_speech)
7418 {
7419 callback_list_add(this_->callback_speech, cb);
7420 }
7421 else
7422 {
7423 callback_list_add(this_->callback, cb);
7424 }
7425
7426 return2 1;
7427
7428 __F_END__
7429 }
7430
7431 void navigation_unregister_callback(struct navigation *this_, enum attr_type type, struct callback *cb)
7432 {
7433 __F_START__
7434
7435 if (type == attr_navigation_speech)
7436 {
7437 callback_list_remove_destroy(this_->callback_speech, cb);
7438 }
7439 else
7440 {
7441 callback_list_remove_destroy(this_->callback, cb);
7442 }
7443
7444 __F_END__
7445 }
7446
7447 struct map *
7448 navigation_get_map(struct navigation *this_)
7449 {
7450 struct attr *attrs[5];
7451 struct attr type, navigation, data, description;
7452 type.type = attr_type;
7453 type.u.str = "navigation";
7454 navigation.type = attr_navigation;
7455 navigation.u.navigation = this_;
7456 data.type = attr_data;
7457 data.u.str = "";
7458 description.type = attr_description;
7459 description.u.str = "Navigation";
7460
7461 attrs[0] = &type;
7462 attrs[1] = &navigation;
7463 attrs[2] = &data;
7464 attrs[3] = &description;
7465 attrs[4] = NULL;
7466
7467 if (!this_->map)
7468 {
7469 this_->map = map_new(NULL, attrs);
7470 }
7471
7472 return this_->map;
7473 }
7474
7475 struct map_priv
7476 {
7477 struct navigation *navigation;
7478 };
7479
7480 struct map_rect_priv
7481 {
7482 struct navigation *nav;
7483 struct navigation_command *cmd;
7484 struct navigation_command *cmd_next;
7485 struct navigation_itm *itm;
7486 struct navigation_itm *itm_next;
7487 struct navigation_itm *cmd_itm;
7488 struct navigation_itm *cmd_itm_next;
7489 struct item item;
7490 enum attr_type attr_next;
7491 int ccount;
7492 int debug_idx;
7493 struct navigation_way *ways;
7494 int show_all;
7495 char *str;
7496 };
7497
7498 static int navigation_map_item_coord_get(void *priv_data, struct coord *c, int count)
7499 {
7500 struct map_rect_priv *this = priv_data;
7501
7502 if (this->ccount || !count)
7503 {
7504 // dbg(0, "NAVICG:return 001 %d %d\n", this->ccount, count);
7505 return 0;
7506 }
7507
7508 if (this->item.type == type_nav_waypoint)
7509 {
7510 if (this->itm->way.dir == 99)
7511 {
7512 dbg(0, "NAVICG:waypoint:END of seg\n");
7513 *c = this->itm->end;
7514 }
7515 else
7516 {
7517 dbg(0, "NAVICG:waypoint:start of seg\n");
7518 *c = this->itm->start;
7519 }
7520 }
7521 else
7522 {
7523 // dbg(0, "NAVICG:normal type=%s cc=%d\n", item_to_name(this->item.type), this->ccount);
7524 *c = this->itm->start;
7525 }
7526
7527 this->ccount = 1;
7528
7529 return 1;
7530 }
7531
7532 static int navigation_map_item_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
7533 {
7534 struct map_rect_priv *this_ = priv_data;
7535 struct navigation_command *cmd = this_->cmd;
7536 struct navigation_itm *itm = this_->itm;
7537 struct navigation_itm *prev = itm->prev;
7538 attr->type = attr_type;
7539
7540 if (this_->str)
7541 {
7542 g_free(this_->str);
7543 this_->str = NULL;
7544 }
7545
7546 if (cmd)
7547 {
7548 if (cmd->itm != itm)
7549 {
7550 cmd = NULL;
7551 }
7552 }
7553
7554 switch (attr_type)
7555 {
7556 case attr_navigation_short:
7557 this_->attr_next = attr_navigation_long;
7558 if (cmd)
7559 {
7560 //dbg(0, "attr_navigation_short\n");
7561 this_->str = attr->u.str = show_next_maneuvers(this_->nav, this_->cmd_itm, cmd, attr_type);
7562 return 1;
7563 }
7564 return 0;
7565 case attr_navigation_long:
7566 this_->attr_next = attr_navigation_long_exact;
7567 if (cmd)
7568 {
7569 //dbg(0, "attr_navigation_long\n");
7570 this_->str = attr->u.str = show_next_maneuvers(this_->nav, this_->cmd_itm, cmd, attr_type);
7571 return 1;
7572 }
7573 return 0;
7574 case attr_navigation_long_exact:
7575 this_->attr_next = attr_navigation_speech;
7576 if (cmd)
7577 {
7578 //dbg(0, "attr_navigation_long_exact\n");
7579 this_->str = attr->u.str = show_next_maneuvers(this_->nav, this_->cmd_itm, cmd, attr_type);
7580 return 1;
7581 }
7582 return 0;
7583 case attr_navigation_speech:
7584 this_->attr_next = attr_length;
7585 if (cmd)
7586 {
7587 //dbg(0, "attr_navigation_speech\n");
7588 //dbg(0, "Enter: attr_navigation_speech\n");
7589 this_->str = attr->u.str = show_next_maneuvers(this_->nav, this_->cmd_itm, this_->cmd, attr_type);
7590 //dbg(0, "back : attr_navigation_speech\n");
7591 return 1;
7592 }
7593 else if (this_->nav->turn_around_limit && this_->nav->turn_around == this_->nav->turn_around_limit)
7594 {
7595 if (global_turn_around_spoken == 0)
7596 {
7597 this_->str = attr->u.str = g_strdup(_("When possible, please turn around"));
7598 global_turn_around_spoken = 1;
7599 return 1;
7600 }
7601 else
7602 {
7603 return 0;
7604 }
7605 }
7606 return 0;
7607 case attr_length:
7608 this_->attr_next = attr_time;
7609 if (cmd)
7610 {
7611 attr->u.num = this_->cmd_itm->dest_length - cmd->itm->dest_length;
7612 return 1;
7613 }
7614 return 0;
7615 case attr_time:
7616 this_->attr_next = attr_destination_length;
7617 if (cmd)
7618 {
7619 attr->u.num = this_->cmd_itm->dest_time - cmd->itm->dest_time;
7620 return 1;
7621 }
7622 return 0;
7623
7624 case attr_destination_length:
7625 attr->u.num = itm->dest_length;
7626 this_->attr_next = attr_destination_time;
7627 return 1;
7628
7629 case attr_destination_time:
7630 attr->u.num = itm->dest_time;
7631 this_->attr_next = attr_street_name;
7632 return 1;
7633
7634 case attr_street_name:
7635 attr->u.str = itm->way.name1;
7636 this_->attr_next = attr_street_name_systematic;
7637 if (attr->u.str)
7638 return 1;
7639 return 0;
7640
7641 case attr_street_name_systematic:
7642 attr->u.str = itm->way.name2;
7643 this_->attr_next = attr_street_destination;
7644 if (attr->u.str)
7645 return 1;
7646 return 0;
7647
7648 case attr_street_destination:
7649 attr->u.str = itm->way.street_dest_text;
7650 this_->attr_next = attr_debug;
7651 if (attr->u.str)
7652 {
7653 return 1;
7654 }
7655 return 0;
7656
7657 case attr_debug:
7658 switch (this_->debug_idx)
7659 {
7660 case 0:
7661 this_->debug_idx++;
7662 this_->str = attr->u.str = g_strdup_printf("angle:%d (- %d)", itm->way.angle2, itm->angle_end);
7663 return 1;
7664 case 1:
7665 this_->debug_idx++;
7666 this_->str = attr->u.str = g_strdup_printf("item type:%s", item_to_name(itm->way.item.type));
7667 return 1;
7668 case 2:
7669 this_->debug_idx++;
7670 if (cmd)
7671 {
7672 this_->str = attr->u.str = g_strdup_printf("delta:%d", cmd->delta);
7673 return 1;
7674 }
7675 case 3:
7676 this_->debug_idx++;
7677 if (prev)
7678 {
7679 this_->str = attr->u.str = g_strdup_printf("prev street_name:%s", prev->way.name1);
7680 return 1;
7681 }
7682 case 4:
7683 this_->debug_idx++;
7684 if (prev)
7685 {
7686 this_->str = attr->u.str = g_strdup_printf("prev street_name_systematic:%s", prev->way.name2);
7687 return 1;
7688 }
7689 case 5:
7690 this_->debug_idx++;
7691 if (prev)
7692 {
7693 this_->str = attr->u.str = g_strdup_printf("prev angle:(%d -) %d", prev->way.angle2, prev->angle_end);
7694 return 1;
7695 }
7696 case 6:
7697 this_->debug_idx++;
7698 this_->ways = itm->way.next;
7699 if (prev)
7700 {
7701 this_->str = attr->u.str = g_strdup_printf("prev item type:%s", item_to_name(prev->way.item.type));
7702 return 1;
7703 }
7704 case 7:
7705 if (this_->ways && prev)
7706 {
7707 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);
7708 this_->ways = this_->ways->next;
7709 return 1;
7710 }
7711 this_->debug_idx++;
7712 case 8:
7713 this_->debug_idx++;
7714 if (prev)
7715 {
7716 int delta = 0;
7717 int delta_real = 0;
7718 char *reason = NULL;
7719 maneuver_required2(this_->nav, prev, itm, &delta, &delta_real, &reason);
7720 this_->str = attr->u.str = g_strdup_printf("reason:%s", reason);
7721 return 1;
7722 }
7723
7724 default:
7725 this_->attr_next = attr_none;
7726 return 0;
7727 }
7728
7729 case attr_any:
7730 while (this_->attr_next != attr_none)
7731 {
7732 if (navigation_map_item_attr_get(priv_data, this_->attr_next, attr))
7733 return 1;
7734 }
7735 return 0;
7736
7737 default:
7738 attr->type = attr_none;
7739 return 0;
7740 }
7741 }
7742
7743 static struct item_methods navigation_map_item_methods = { NULL, navigation_map_item_coord_get, NULL, navigation_map_item_attr_get, };
7744
7745 static void navigation_map_destroy(struct map_priv *priv)
7746 {
7747 g_free(priv);
7748 }
7749
7750 static void navigation_map_rect_init(struct map_rect_priv *priv)
7751 {
7752 priv->cmd_next = priv->nav->cmd_first;
7753 priv->cmd_itm_next = priv->itm_next = priv->nav->first;
7754 }
7755
7756 static struct map_rect_priv *
7757 navigation_map_rect_new(struct map_priv *priv, struct map_selection *sel)
7758 {
7759 struct navigation *nav = priv->navigation;
7760 struct map_rect_priv *ret=g_new0(struct map_rect_priv, 1);
7761 ret->nav = nav;
7762
7763 navigation_map_rect_init(ret);
7764
7765 ret->item.meth = &navigation_map_item_methods;
7766 ret->item.priv_data = ret;
7767
7768 #ifdef DEBUG
7769 ret->show_all=1;
7770 #endif
7771
7772 return ret;
7773 }
7774
7775 static void navigation_map_rect_destroy(struct map_rect_priv *priv)
7776 {
7777 g_free(priv);
7778 }
7779
7780
7781
7782 void navigation_dump_items(struct navigation *this_)
7783 {
7784 if (this_->first)
7785 {
7786 dbg(0, "NAVR:dump:=================++++++++++++================\n");
7787 struct navigation_itm *i;
7788 int count = 0;
7789
7790 i = this_->first;
7791 while (i)
7792 {
7793 count++;
7794 i = i->next;
7795 }
7796
7797 i = this_->first;
7798 while (i)
7799 {
7800 count--;
7801 dbg(0, "NAVR:dump:count=%d %p %d\n", count, i, i->way.dir);
7802 i = i->next;
7803 }
7804 dbg(0, "NAVR:dump:=================++++++++++++================\n");
7805 }
7806 }
7807
7808
7809 // -----------------------------------
7810 static int save_last_dest_count = -1;
7811 // -----------------------------------
7812
7813 static struct item *
7814 navigation_map_get_item(struct map_rect_priv *priv)
7815 {
7816 struct item *ret = &priv->item;
7817 int delta;
7818
7819 int fake_dir1;
7820 int fake_dir2;
7821
7822 dbg(0, "NAVR:ROUTE:Enter:\n");
7823 dbg(0, "NAVR:ROUTE:Enter:------------------------\n");
7824
7825 if (!priv->itm_next)
7826 {
7827 dbg(0, "NAVR:ROUTE:006:0000\n");
7828 return NULL;
7829 }
7830
7831 int stepped_to_waypoint = 0;
7832
7833 // now check if we missed a waypoint, if so -> move back to waypoint -------------------------
7834 if (priv->itm)
7835 {
7836 if (save_last_dest_count != -1)
7837 {
7838 int count_back = (save_last_dest_count - priv->itm->dest_count - 1);
7839 int count_forw = count_back;
7840 dbg(0, "NAVR:ROUTE:006:cback:%d = (%d - %d - 1)\n", count_back, save_last_dest_count, priv->itm->dest_count);
7841
7842 struct navigation_itm *i = priv->itm;
7843
7844 // go to first item to check
7845 while (count_back > 0)
7846 {
7847 count_back--;
7848 if (i->prev)
7849 {
7850 i = i->prev;
7851 dbg(0, "NAVR:ROUTE:006:cback:stepping back to item #%d dir=%d\n", i->dest_count, i->way.dir);
7852 }
7853 }
7854
7855 // now step forward until waypoint found, or just skip the whole thing if we dont find any waypoint
7856 while (count_forw > 0)
7857 {
7858 if (i)
7859 {
7860 dbg(0, "NAVR:ROUTE:006:cback:stepping forw to item #%d dir=%d\n", i->dest_count, i->way.dir);
7861
7862 if ((i->way.dir == 99) || (i->way.dir == -99))
7863 {
7864 // found a waypoint
7865 priv->itm = i;
7866 stepped_to_waypoint = 1;
7867
7868 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);
7869
7870 break;
7871 }
7872
7873 count_forw--;
7874 if (i->next)
7875 {
7876 i = i->next;
7877 }
7878 }
7879 }
7880
7881 }
7882 }
7883 // now check if we missed a waypoint, if so -> move back to waypoint -------------------------
7884
7885
7886 if (priv->itm)
7887 {
7888 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);
7889 fake_dir1 = priv->itm->way.dir;
7890 save_last_dest_count = priv->itm->dest_count;
7891 }
7892 else
7893 {
7894 dbg(0, "NAVR:ROUTE:006:8888:1: NULL\n");
7895 fake_dir1 = 0;
7896 save_last_dest_count = -1;
7897 }
7898
7899 if (stepped_to_waypoint != 1)
7900 {
7901 priv->itm = priv->itm_next;
7902 }
7903
7904
7905 fake_dir2 = priv->itm->way.dir;
7906 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);
7907 priv->cmd = priv->cmd_next;
7908 priv->cmd_itm = priv->cmd_itm_next;
7909
7910 if ((priv->itm->way.dir == 99) || (priv->itm->way.dir == -99))
7911 {
7912 // return fake waypoint item!! ---------
7913 ret->type = type_nav_waypoint;
7914 ret->id_lo = priv->itm->dest_count;
7915 priv->ccount = 0;
7916
7917 priv->itm_next = priv->itm->next;
7918
7919 dbg(0, "NAVR:ROUTE:006:fake:%s dir=%d ,,,,,\n", item_to_name(ret->type), priv->itm->way.dir);
7920
7921 return ret;
7922 }
7923
7924
7925
7926 // navigation_dump_items(priv->nav);
7927
7928 if (!priv->cmd)
7929 {
7930 dbg(0, "NAVR:ROUTE:006:1111\n");
7931 return NULL;
7932 }
7933
7934
7935 if (!priv->show_all && priv->itm->prev != NULL)
7936 {
7937 dbg(0, "NAVR:ROUTE:006:112a\n");
7938 priv->itm = priv->cmd->itm;
7939 }
7940
7941 priv->itm_next = priv->itm->next;
7942
7943 if (priv->itm->prev)
7944 {
7945 ret->type = type_nav_none;
7946 }
7947 else
7948 {
7949 ret->type = type_nav_position;
7950 }
7951
7952 dbg(0, "NAVR:ROUTE:006:2222 %p dir=%d\n", priv->itm, priv->itm->way.dir);
7953
7954 if (priv->cmd->itm == priv->itm)
7955 {
7956
7957 dbg(0, "NAVR:ROUTE:006:3333 %p dir=%d %p\n", priv->itm, priv->itm->way.dir, route_get_map(global_navit->route));
7958 // item_dump_coords(priv->itm, route_get_map(global_navit->route));
7959
7960 priv->cmd_itm_next = priv->cmd->itm;
7961 priv->cmd_next = priv->cmd->next;
7962
7963 if (priv->cmd_itm_next && !priv->cmd_itm_next->next)
7964 {
7965 ret->type = type_nav_destination;
7966 }
7967 else
7968 {
7969 if (priv->itm && priv->itm->prev && !(priv->itm->way.flags & NAVIT_AF_ROUNDABOUT) && (priv->itm->prev->way.flags & NAVIT_AF_ROUNDABOUT))
7970 {
7971 enum item_type r = type_none, l = type_none;
7972 switch (((180 + 22) - priv->cmd->roundabout_delta) / 45)
7973 {
7974 case 0:
7975 case 1:
7976 r = type_nav_roundabout_r1;
7977 l = type_nav_roundabout_l7;
7978 break;
7979 case 2:
7980 r = type_nav_roundabout_r2;
7981 l = type_nav_roundabout_l6;
7982 break;
7983 case 3:
7984 r = type_nav_roundabout_r3;
7985 l = type_nav_roundabout_l5;
7986 break;
7987 case 4:
7988 r = type_nav_roundabout_r4;
7989 l = type_nav_roundabout_l4;
7990 break;
7991 case 5:
7992 r = type_nav_roundabout_r5;
7993 l = type_nav_roundabout_l3;
7994 break;
7995 case 6:
7996 r = type_nav_roundabout_r6;
7997 l = type_nav_roundabout_l2;
7998 break;
7999 case 7:
8000 r = type_nav_roundabout_r7;
8001 l = type_nav_roundabout_l1;
8002 break;
8003 case 8:
8004 r = type_nav_roundabout_r8;
8005 l = type_nav_roundabout_l8;
8006 break;
8007 }
8008 // dbg(0, "delta %d\n", priv->cmd->delta);
8009
8010 if (priv->cmd->delta < 0)
8011 {
8012 ret->type = l;
8013 }
8014 else
8015 {
8016 ret->type = r;
8017 }
8018 }
8019 else
8020 {
8021 delta = priv->cmd->delta;
8022 if (delta < 0)
8023 {
8024 delta = -delta;
8025 if (delta < 45)
8026 ret->type = type_nav_left_1;
8027 else if (delta < 105)
8028 ret->type = type_nav_left_2;
8029 else if (delta < 165)
8030 ret->type = type_nav_left_3;
8031 else
8032 ret->type = type_none;
8033 }
8034 else if (delta > 0)
8035 {
8036 if (delta < 45)
8037 ret->type = type_nav_right_1;
8038 else if (delta < 105)
8039 ret->type = type_nav_right_2;
8040 else if (delta < 165)
8041 ret->type = type_nav_right_3;
8042 else
8043 ret->type = type_none;
8044 }
8045 else // delta == 0
8046 {
8047 ret->type = type_nav_straight;
8048 }
8049 }
8050 }
8051 }
8052
8053 priv->ccount = 0;
8054 priv->debug_idx = 0;
8055 priv->attr_next = attr_navigation_short;
8056
8057 ret->id_lo = priv->itm->dest_count;
8058
8059 // 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);
8060
8061
8062 // check for "turn around" and return "type_nav_turnaround" !! ---------------
8063 if ((priv->nav->turn_around && priv->nav->turn_around == priv->nav->turn_around_limit) && (ret->type == type_nav_position))
8064 {
8065 // dbg(0, "priv->itm->dest_count=%d\n", priv->itm->dest_count);
8066 ret->type = type_nav_turnaround_right;
8067 }
8068 // check for "turn around" and return "type_nav_turnaround" !! ---------------
8069
8070 // dbg(0, "NAVR:ROUTE:007a:%s ,,,,, priv->itm->dest_count=%d\n", item_to_name(ret->type), priv->itm->dest_count);
8071
8072 return ret;
8073 }
8074
8075 static struct item *
8076 navigation_map_get_item_byid(struct map_rect_priv *priv, int id_hi, int id_lo)
8077 {
8078 struct item *ret;
8079 navigation_map_rect_init(priv);
8080 while ((ret = navigation_map_get_item(priv)))
8081 {
8082 if (ret->id_hi == id_hi && ret->id_lo == id_lo)
8083 return ret;
8084 }
8085 return NULL;
8086 }
8087
8088 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, };
8089
8090 struct map_priv *
8091 navigation_map_new(struct map_methods *meth, struct attr **attrs, struct callback_list *cbl)
8092 {
8093 struct map_priv *ret;
8094 struct attr *navigation_attr;
8095
8096 navigation_attr = attr_search(attrs, NULL, attr_navigation);
8097
8098 if (!navigation_attr)
8099 {
8100 return NULL;
8101 }
8102
8103 ret=g_new0(struct map_priv, 1);
8104 *meth = navigation_map_meth;
8105 ret->navigation = navigation_attr->u.navigation;
8106
8107 level_static_for_bicycle[0] = 22; // in meters
8108 level_static_for_bicycle[1] = 100; // in meters
8109 level_static_for_bicycle[2] = -1; // dont announce
8110
8111 return ret;
8112 }
8113
8114 void navigation_set_route(struct navigation *this_, struct route *route)
8115 {
8116 __F_START__
8117
8118 struct attr callback;
8119 this_->route = route;
8120 this_->route_cb = callback_new_attr_1(callback_cast(navigation_update), attr_route_status, this_);
8121 callback_add_names(this_->route_cb, "navigation_set_route", "navigation_update");
8122 callback.type = attr_callback;
8123 callback.u.callback = this_->route_cb;
8124 route_add_attr(route, &callback);
8125
8126 __F_END__
8127 }
8128
8129 void navigation_init(void)
8130 {
8131 #ifdef PLUGSSS
8132 plugin_register_map_type("navigation", navigation_map_new);
8133 #endif
8134 }
8135
8136
8137

   
Visit the ZANavi Wiki