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

Contents of /navit/navit/navigation.c

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki