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

Contents of /navit/navit/navigation.c

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki