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

Contents of /navit/navit/navigation.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 47 - (show annotations) (download)
Sat Sep 12 11:02:16 2015 UTC (8 years, 6 months ago) by zoff99
File MIME type: text/plain
File size: 201322 byte(s)
v2.0.48
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:first\n");
790 #endif
791 #endif
792 // TRANSLATORS: the following counts refer to streets (example: turn right after the first street)
793 return _("first"); // 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:first exit\n");
879 #endif
880 #endif
881 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the first exit)
882 return _("first 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 * thanks to jandegr
2140 */
2141 static navigation_select_announced_destinations(struct navigation_command *current_command)
2142 {
2143 struct street_destination *current_destination = NULL; /* the list pointer of the destination_names of the current command. */
2144 struct street_destination *search_destination = NULL; /* the list pointer of the destination_names of the respective search_command. */
2145
2146 struct navigation_command *search_command = NULL; /* loop through every navigation command up to the end. */
2147
2148 /* limits the number of entries of a destination sign as well as the number of command items to investigate */
2149 #define DEST_MAX_LOOPS_SIGN_TEXTS 10
2150 #define DEST_MAX_LOOPS_NAV_ITEMS 3
2151
2152 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 */
2153 /* investigated command items - a 'high score' of destination names */
2154
2155 int destination_index = 0;
2156 int search_command_counter = 0;
2157 int i;
2158 int max_hits;
2159 int max_hit_index;
2160 struct navigation_way *current_nav_way = NULL;
2161
2162 // put text into way struct later -----------------
2163 current_nav_way = &(current_command->itm->way);
2164 if ((current_nav_way) && (current_nav_way->street_dest_text))
2165 {
2166 // already have set a destination --> return
2167 return;
2168 }
2169 current_nav_way->street_dest_text = NULL; // set default to "no value"
2170 // put text into way struct later -----------------
2171
2172
2173 /* search over every following command for seeking identical destination_names */
2174 if (current_command->itm->way.s_destination)
2175 {
2176 /* can we investigate over the following commands? */
2177
2178 if (current_command->next)
2179 {
2180 /* loop over every destination sign of the current command, as far as there are not more than 10 entries. */
2181 destination_index = 0; /* Do only the first DEST_MAX_LOOPS_SIGN_TEXTS destination_signs */
2182 current_destination = current_command->itm->way.s_destination;
2183
2184 while (current_destination && (destination_index < DEST_MAX_LOOPS_SIGN_TEXTS))
2185 { /* initialize the search command */
2186
2187 search_command = current_command->next;
2188 search_command_counter = 0; // Do only the first DEST_MAX_LOOPS_NAV_ITEMS commands.
2189
2190 while (search_command && (search_command_counter < DEST_MAX_LOOPS_NAV_ITEMS))
2191 {
2192 if (search_command->itm)
2193 { /* has the search command any destination_signs? */
2194
2195 if (search_command->itm->way.s_destination)
2196 {
2197 search_destination = search_command->itm->way.s_destination;
2198
2199 while (search_destination)
2200 { /* Search this name in the destination list of the current command. */
2201
2202 if (0 == strcmp(current_destination->destination, search_destination->destination))
2203 { /* enter the destination_name in the investigation list*/
2204
2205 destination_count[destination_index]++;
2206 //search_destination = NULL; /* break condition */
2207 break;
2208 }
2209 else
2210 {
2211 search_destination = search_destination->next;
2212 }
2213 }
2214 }
2215 }
2216 search_command_counter++;
2217 search_command = search_command->next;
2218 }
2219
2220 destination_index++;
2221 current_destination = current_destination->next;
2222 }
2223
2224 /* search for the best candidate */
2225 max_hits = 0;
2226 max_hit_index = 0;
2227 for (i = 0; i < destination_index; i++)
2228 {
2229 if (destination_count[i] > max_hits)
2230 {
2231 max_hits = destination_count[i];
2232 max_hit_index = i;
2233 }
2234 }
2235 /* jump to the corresponding destination_name */
2236 current_destination = current_command->itm->way.s_destination;
2237 for (i = 0; i < max_hit_index; i++)
2238 {
2239 current_destination = current_destination->next;
2240 }
2241 }
2242 else if (current_command->itm->way.exit_label)
2243 {
2244 if ((current_nav_way) && (current_nav_way->street_dest_text))
2245 {
2246 g_free(current_nav_way->street_dest_text);
2247 }
2248
2249 current_nav_way->street_dest_text = g_strdup(current_command->itm->way.exit_label);
2250 #ifdef NAVIT_ROUTING_DEBUG_PRINT
2251 dbg(0, "put exit_label into nav way (C) %s\n", current_command->itm->way.exit_label);
2252 #endif
2253
2254 return;
2255 }
2256 }
2257 else if (current_command->itm->way.exit_label)
2258 {
2259 if ((current_nav_way) && (current_nav_way->street_dest_text))
2260 {
2261 g_free(current_nav_way->street_dest_text);
2262 }
2263
2264 current_nav_way->street_dest_text = g_strdup(current_command->itm->way.exit_label);
2265 #ifdef NAVIT_ROUTING_DEBUG_PRINT
2266 dbg(0, "put exit_label into nav way (A) %s\n", current_command->itm->way.exit_label);
2267 #endif
2268
2269 return;
2270 }
2271
2272
2273
2274
2275
2276 /* return the best candidate, if there is any.*/
2277 if ((current_nav_way) && (current_nav_way->street_dest_text))
2278 {
2279 g_free(current_nav_way->street_dest_text);
2280 current_nav_way->street_dest_text = NULL;
2281 }
2282
2283 if ((current_destination) && (current_destination->destination))
2284 {
2285 current_nav_way->street_dest_text = g_strdup(current_destination->destination);
2286 #ifdef NAVIT_ROUTING_DEBUG_PRINT
2287 dbg(0, "put destination into nav way (B) %s\n", current_nav_way->street_dest_text);
2288 #endif
2289 }
2290 else
2291 {
2292 // stay NULL
2293 //current_nav_way->street_dest_text = NULL;
2294 //dbg(0, "put destination into nav way NULL (C)\n");
2295 }
2296 }
2297 // -- NEW 002 --
2298
2299
2300
2301
2302 static struct navigation_itm *
2303 navigation_itm_new(struct navigation *this_, struct item *ritem)
2304 {
2305 struct navigation_itm *ret=g_new0(struct navigation_itm, 1);
2306 int i = 0;
2307 struct item *sitem;
2308 struct map *graph_map = NULL;
2309 struct attr street_item, direction, route_attr;
2310 struct map_rect *mr;
2311 struct attr attr;
2312 struct coord c[5];
2313
2314 if (ritem)
2315 {
2316 ret->streetname_told = 0;
2317
2318 if (ritem->type == type_street_route_waypoint)
2319 {
2320 dbg(0, "NAVR:XX:0:make street item\n");
2321
2322 while (item_coord_get(ritem, &c[i], 1))
2323 {
2324 if (i < 4)
2325 {
2326 i++;
2327 }
2328 else
2329 {
2330 c[2] = c[3];
2331 c[3] = c[4];
2332 }
2333 }
2334
2335 i--;
2336 ret->start = c[0];
2337 ret->end = c[i];
2338
2339 if (item_attr_get(ritem, attr_direction, &direction))
2340 {
2341 if (direction.u.num < 0)
2342 {
2343 ret->way.dir = -99; // mark waypoint type
2344 }
2345 else
2346 {
2347 ret->way.dir = 99; // mark waypoint type
2348 }
2349 }
2350 else
2351 {
2352 ret->way.dir = 99; // mark waypoint type
2353 }
2354
2355 navigation_itm_update(ret, ritem);
2356 ret->length = 1;
2357 ret->time = 1;
2358 ret->speed = 30;
2359
2360 if (!this_->first)
2361 {
2362 this_->first = ret;
2363 }
2364
2365 if (this_->last)
2366 {
2367 this_->last->next = ret;
2368 ret->prev = this_->last;
2369 //if (graph_map)
2370 //{
2371 // navigation_itm_ways_update(ret, graph_map);
2372 //}
2373 }
2374 this_->last = ret;
2375
2376 return ret;
2377 }
2378
2379 if (!item_attr_get(ritem, attr_street_item, &street_item))
2380 {
2381 dbg(0, "NAVR:XX:1:no street item\n");
2382 g_free(ret);
2383 ret = NULL;
2384 return ret;
2385 }
2386
2387 if (item_attr_get(ritem, attr_direction, &direction))
2388 {
2389 ret->way.dir = direction.u.num;
2390 }
2391 else
2392 {
2393 ret->way.dir = 0;
2394 }
2395
2396 sitem = street_item.u.item;
2397 ret->way.item = *sitem;
2398 item_hash_insert(this_->hash, sitem, ret);
2399 mr = map_rect_new(sitem->map, NULL);
2400
2401 // -- NEW 002 --
2402 struct map *tmap = sitem->map; /*find better name for backup pointer to map*/
2403 // -- NEW 002 --
2404
2405 // COST: 005
2406 dbg(0, "COST:005\n");
2407 if (!(sitem = map_rect_get_item_byid(mr, sitem->id_hi, sitem->id_lo)))
2408 {
2409 // -- NEW 002 --
2410 if (mr)
2411 {
2412 map_rect_destroy(mr);
2413 }
2414 g_free(ret);
2415 ret = NULL;
2416 // -- NEW 002 --
2417
2418 return NULL;
2419 }
2420
2421 // -- NEW 002 --
2422 if (item_attr_get(sitem, attr_flags, &attr))
2423 {
2424 ret->way.flags=attr.u.num;
2425 }
2426 // -- NEW 002 --
2427
2428 if (item_attr_get(sitem, attr_street_name, &attr))
2429 {
2430 ret->way.name1 = map_convert_string(sitem->map, attr.u.str);
2431 }
2432
2433 if (item_attr_get(sitem, attr_street_name_systematic, &attr))
2434 {
2435 ret->way.name2 = map_convert_string(sitem->map, attr.u.str);
2436 }
2437
2438 navigation_itm_update(ret, ritem);
2439
2440 while (item_coord_get(ritem, &c[i], 1))
2441 {
2442 if (i < 4)
2443 {
2444 i++;
2445 }
2446 else
2447 {
2448 c[2] = c[3];
2449 c[3] = c[4];
2450 }
2451 }
2452
2453 i--;
2454
2455
2456
2457 // -- NEW 002 --
2458 if (item_attr_get(sitem, attr_street_destination, &attr))
2459 {
2460 char *destination_raw;
2461 destination_raw = map_convert_string(sitem->map,attr.u.str);
2462 #ifdef NAVIT_ROUTING_DEBUG_PRINT
2463 dbg(0, "DEST::destination_raw=%s\n", destination_raw);
2464 #endif
2465
2466 #ifdef NAVIT_FREE_TEXT_DEBUG_PRINT
2467 char *tt = g_strdup_printf("D:%s", attr.u.str);
2468 route_add_to_freetext_list(&c[0], tt);
2469 g_free(tt);
2470 #endif
2471
2472 // also save full text into "exit_label" --------------
2473 if (ret->way.exit_label)
2474 {
2475 g_free(ret->way.exit_label);
2476 }
2477 ret->way.exit_label = map_convert_string(sitem->map, destination_raw);
2478 // also save full text into "exit_label" --------------
2479
2480 navigation_split_string_to_list(&(ret->way), destination_raw, ';');
2481 g_free(destination_raw);
2482 }
2483 else if (item_attr_get(sitem, attr_street_destination_lanes, &attr))
2484 {
2485 char *destination_raw;
2486 destination_raw = map_convert_string(sitem->map,attr.u.str);
2487 #ifdef NAVIT_ROUTING_DEBUG_PRINT
2488 dbg(0, "DEST::destination_lanes_raw=%s\n", destination_raw);
2489 #endif
2490
2491 #ifdef NAVIT_FREE_TEXT_DEBUG_PRINT
2492 char *tt = g_strdup_printf("d_l:%s", attr.u.str);
2493 route_add_to_freetext_list(&c[0], tt);
2494 g_free(tt);
2495 #endif
2496
2497 // also save full text into "exit_label" --------------
2498 if (ret->way.exit_label)
2499 {
2500 g_free(ret->way.exit_label);
2501 }
2502 ret->way.exit_label = map_convert_string(sitem->map, destination_raw);
2503 // also save full text into "exit_label" --------------
2504
2505 navigation_split_string_to_list_2(&(ret->way), destination_raw, ';', '|');
2506 g_free(destination_raw);
2507 }
2508 // -- NEW 002 --
2509
2510
2511 // ret->way.angle2 = road_angle_accurate(&c[0], &c[1], 0); // angle at start of way
2512 // ret->angle_end = road_angle_accurate(&c[i - 1], &c[i], 0); // angle at end of way
2513 ret->way.angle2 = road_angle(&c[0], &c[1], 0); // angle at start of way
2514 ret->angle_end = road_angle(&c[i - 1], &c[i], 0); // angle at end of way
2515
2516 ret->start = c[0];
2517 ret->end = c[i];
2518
2519 // -- NEW 002 --
2520 /* If we have a ramp check the map for higway_exit info,
2521 * but only on the first node of the ramp.
2522 * Ramps with nodes in reverse order and oneway=-1 are not
2523 * specifically handled, but no occurence known so far either.
2524 * If present, obtain exit_ref, exit_label and exit_to
2525 * from the map.
2526 * exit_to holds info similar to attr_street_destination, and
2527 * we place it in way.s_destination as well, unless the street_destination info
2528 * is already present. In the future it will have to be skipped if destiantion:lanes
2529 * info exists as well.
2530 *
2531 * Now it still holds a bug, if a ramp splits in 2, the exit_to info can end up on
2532 * both continuations of the ramp. Maybe this can be solved by passing the struct
2533 * navigation_maneuver up to here to help decide on exit_to.
2534 *
2535 */
2536
2537 if (item_is_ramp(*sitem)) /* hier motorway_link en trunk_link toevoegen */
2538 {
2539 struct map_selection mselexit;
2540 struct item *rampitem;
2541 struct map_rect *mr2;
2542 struct coord exitcoord;
2543
2544 mselexit.next = NULL;
2545 mselexit.u.c_rect.lu = c[0];
2546 mselexit.u.c_rect.rl = c[0];
2547 mselexit.range = item_range_all;
2548 mselexit.order = 18;
2549
2550 mr2 = map_rect_new(tmap, &mselexit);
2551
2552 while ((rampitem = map_rect_get_item(mr2)))
2553 {
2554 if (rampitem->type == type_highway_exit && item_coord_get(rampitem, &exitcoord, 1)
2555 && exitcoord.x == c[0].x && exitcoord.y == c[0].y)
2556 {
2557 while (item_attr_get(rampitem, attr_any, &attr))
2558 {
2559 if (attr.type && attr.type == attr_label)
2560 {
2561 #ifdef NAVIT_ROUTING_DEBUG_PRINT
2562 dbg(0,"DEST::exit_label=%s\n",attr.u.str);
2563 #endif
2564 if (ret->way.exit_label)
2565 {
2566 g_free(ret->way.exit_label);
2567 }
2568 ret->way.exit_label = map_convert_string(sitem->map,attr.u.str);
2569
2570 #ifdef NAVIT_FREE_TEXT_DEBUG_PRINT
2571 char *tt = g_strdup_printf("exit_label:%s", attr.u.str);
2572 route_add_to_freetext_list(&c[0], tt);
2573 g_free(tt);
2574 #endif
2575
2576 }
2577
2578 if (attr.type == attr_ref)
2579 {
2580 #ifdef NAVIT_ROUTING_DEBUG_PRINT
2581 dbg(0,"DEST::exit_ref=%s\n",attr.u.str);
2582 #endif
2583 if (ret->way.exit_ref)
2584 {
2585 g_free(ret->way.exit_ref);
2586 }
2587 ret->way.exit_ref = map_convert_string(sitem->map,attr.u.str);
2588
2589 #ifdef NAVIT_FREE_TEXT_DEBUG_PRINT
2590 char *tt = g_strdup_printf("exit_ref:%s", attr.u.str);
2591 route_add_to_freetext_list(&c[0], tt);
2592 g_free(tt);
2593 #endif
2594
2595 }
2596
2597 if (attr.type == attr_exit_to)
2598 {
2599 if (attr.u.str && !ret->way.s_destination)
2600 {
2601 char *destination_raw;
2602 destination_raw = map_convert_string(sitem->map,attr.u.str);
2603 #ifdef NAVIT_ROUTING_DEBUG_PRINT
2604 dbg(0,"DEST::destination_raw from exit_to =%s\n",destination_raw);
2605 #endif
2606
2607 // also save full text into "exit_label" --------------
2608 if (ret->way.exit_label)
2609 {
2610 g_free(ret->way.exit_label);
2611 }
2612 ret->way.exit_label = map_convert_string(sitem->map, destination_raw);
2613 // also save full text into "exit_label" --------------
2614
2615 #ifdef NAVIT_FREE_TEXT_DEBUG_PRINT
2616 char *tt = g_strdup_printf("exit_to:%s", destination_raw);
2617 route_add_to_freetext_list(&c[0], tt);
2618 g_free(tt);
2619 #endif
2620
2621 if ((navigation_split_string_to_list(&(ret->way),destination_raw, ';')) < 2)
2622 {
2623 /*
2624 * if a first try did not result in an actual splitting
2625 * retry with ',' as a separator
2626 *
2627 * */
2628 navigation_split_string_to_list(&(ret->way),destination_raw, ',');
2629 }
2630 g_free(destination_raw);
2631 }
2632 }
2633 }
2634 }
2635 }
2636
2637 if (mr2)
2638 {
2639 map_rect_destroy(mr2);
2640 }
2641 }
2642 // -- NEW 002 --
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655 item_attr_get(ritem, attr_route, &route_attr);
2656 graph_map = route_get_graph_map(route_attr.u.route);
2657 if (check_roundabout(ret, graph_map))
2658 {
2659 ret->way.flags |= NAVIT_AF_ROUNDABOUT;
2660 }
2661
2662 // dbg(1, "i=%d start %d end %d '%s' '%s'\n", i, ret->way.angle2, ret->angle_end, ret->way.name1, ret->way.name2);
2663 map_rect_destroy(mr);
2664 }
2665 else
2666 {
2667 if (this_->last)
2668 {
2669 ret->start = ret->end = this_->last->end;
2670 }
2671 }
2672
2673 if (!this_->first)
2674 {
2675 this_->first = ret;
2676 }
2677
2678 if (this_->last)
2679 {
2680 this_->last->next = ret;
2681 ret->prev = this_->last;
2682 if (graph_map)
2683 {
2684 navigation_itm_ways_update(ret, graph_map);
2685 }
2686 }
2687 //dbg(1, "ret=%p\n", ret);
2688 this_->last = ret;
2689 return ret;
2690 }
2691
2692 /**
2693 * @brief Counts how many times a driver could turn right/left
2694 *
2695 * This function counts how many times the driver theoretically could
2696 * turn right/left between two navigation items, not counting the final
2697 * turn itself.
2698 *
2699 * @param from The navigation item which should form the start
2700 * @param to The navigation item which should form the end
2701 * @param direction Set to < 0 to count turns to the left >= 0 for turns to the right
2702 * @return The number of possibilities to turn or -1 on error
2703 */
2704 static int count_possible_turns(struct navigation *nav, struct navigation_itm *from, struct navigation_itm *to, int direction)
2705 {
2706 int count;
2707 struct navigation_itm *curr;
2708 struct navigation_way *w;
2709
2710 if (direction == 0)
2711 {
2712 // we are going straight!!
2713 return -1;
2714 }
2715
2716 count = 0;
2717 curr = from->next;
2718
2719 int cur_next_is_lower_level_street = navigation_is_low_level_street(to->way.item.type);
2720
2721 while (curr && (curr != to))
2722 {
2723 w = curr->way.next;
2724
2725 while (w)
2726 {
2727 if (is_way_allowed(nav, w, 4))
2728 {
2729
2730 // dont count lower level streets, if next turn is NOT also a lower level street
2731 if ((cur_next_is_lower_level_street == 1) || (navigation_is_low_level_street(w->item.type) == 0))
2732 {
2733 if (direction < 0)
2734 {
2735 if (angle_delta(curr->prev->angle_end, w->angle2) < 0)
2736 {
2737 count++;
2738 break;
2739 }
2740 }
2741 else if (direction > 0)
2742 {
2743 if (angle_delta(curr->prev->angle_end, w->angle2) > 0)
2744 {
2745 count++;
2746 break;
2747 }
2748 }
2749 }
2750 }
2751 w = w->next;
2752 }
2753 curr = curr->next;
2754 }
2755
2756 if (!curr)
2757 {
2758 // from does not lead to to?
2759 return -1;
2760 }
2761
2762 return count;
2763 }
2764
2765 /**
2766 * @brief Calculates distance and time to the destination
2767 *
2768 * This function calculates the distance and the time to the destination of a
2769 * navigation. If incr is set, this is only calculated for the first navigation
2770 * item, which is a lot faster than re-calculation the whole destination, but works
2771 * only if the rest of the navigation already has been calculated.
2772 *
2773 * @param this_ The navigation whose destination / time should be calculated
2774 * @param incr Set this to true to only calculate the first item. See description.
2775 */
2776 static void calculate_dest_distance(struct navigation *this_, int incr)
2777 {
2778 int len = 0, time = 0, count = 0;
2779 struct navigation_itm *next = NULL;
2780 struct navigation_itm *itm = this_->last;
2781
2782 //dbg(1, "enter this_=%p, incr=%d\n", this_, incr);
2783
2784 if (incr)
2785 {
2786 if (itm)
2787 {
2788 //dbg(2, "old values: (%p) time=%d lenght=%d\n", itm,
2789 // itm->dest_length, itm->dest_time);
2790 }
2791 else
2792 {
2793 //dbg(2, "old values: itm is null\n");
2794 }
2795 itm = this_->first;
2796 next = itm->next;
2797 //dbg(2, "itm values: time=%d lenght=%d\n", itm->length, itm->time);
2798 //dbg(2, "next values: (%p) time=%d lenght=%d\n", next, next->dest_length, next->dest_time);
2799 itm->dest_length = next->dest_length + itm->length;
2800 itm->dest_count = next->dest_count + 1;
2801 itm->dest_time = next->dest_time + itm->time;
2802 //dbg(2, "new values: time=%d lenght=%d\n", itm->dest_length, itm->dest_time);
2803 return;
2804 }
2805
2806 while (itm)
2807 {
2808 len += itm->length;
2809 time += itm->time;
2810 itm->dest_length = len;
2811 itm->dest_time = time;
2812 itm->dest_count = count++;
2813 itm = itm->prev;
2814 }
2815 //dbg(1, "len %d time %d\n", len, time);
2816 }
2817
2818 /**
2819 *
2820 * check it w1 is the same as w2 (duplicate way)
2821 *
2822 * @param w1 The first way to be checked
2823 * @param w2 The second way to be checked
2824 * @return 0 -> no, 1 -> yes:it's the same way
2825 *
2826 */
2827 static int is_maybe_same_item(struct navigation_way *w1, struct navigation_way *w2, int reverse_match)
2828 {
2829
2830 dbg(0, "======================================\n");
2831
2832 dbg(0, "w1=%p w2=%p\n", w1, w2);
2833
2834 dbg(0, "w1 type=%s w2 type=%s\n", item_to_name(w1->item.type), item_to_name(w2->item.type));
2835 dbg(0, "w1 dir=%d w2 dir=%d\n", w1->dir, w2->dir);
2836 dbg(0, "w1 angle2=%d w2 angle2=%d\n", w1->angle2, w2->angle2);
2837 dbg(0, "w1 n1=%s w2 n1=%s\n", w1->name1, w2->name1);
2838 dbg(0, "w1 n2=%s w2 n2=%s\n", w1->name2, w2->name2);
2839
2840 #ifdef NAVIT_NAVIGATION_REMOVE_DUPL_WAYS
2841
2842 int dir_reverse = 0;
2843
2844 if (w1->item.type != w2->item.type)
2845 {
2846 dbg(0, "x:w1 type=%s w2 type=%s\n", item_to_name(w1->item.type), item_to_name(w2->item.type));
2847 return 0;
2848 }
2849
2850 #if 0
2851 if (w1->dir != w2->dir)
2852 {
2853 dir_reverse = 1;
2854 }
2855 #endif
2856
2857 if (reverse_match != 0)
2858 {
2859 dir_reverse = 1 - dir_reverse; // toggle "dir_reverse"
2860 }
2861
2862 if (dir_reverse == 0)
2863 {
2864 if ((abs(w1->angle2 - w2->angle2) != 0) && (abs(w1->angle2 - w2->angle2) != 360))
2865 {
2866 dbg(0, "x:000:w1 angle2=%d w2 angle2=%d\n", w1->angle2, w2->angle2);
2867 return 0;
2868 }
2869 }
2870 else
2871 {
2872 if (abs(w1->angle2 - w2->angle2) != 180)
2873 {
2874 dbg(0, "x:180:w1 angle2=%d w2 angle2=%d\n", w1->angle2, w2->angle2);
2875 return 0;
2876 }
2877 }
2878
2879
2880 if ((w1->name1 == NULL) && (w2->name1 == NULL))
2881 {
2882 }
2883 else
2884 {
2885 if ((w1->name1 == NULL) || (w2->name1 == NULL))
2886 {
2887 return 0;
2888 }
2889 else if (strcmp(w1->name1, w2->name1) != 0)
2890 {
2891 dbg(0, "x:w1 n1=%s w2 n1=%s\n", w1->name1, w2->name1);
2892 return 0;
2893 }
2894 }
2895
2896 if ((w1->name2 == NULL) && (w2->name2 == NULL))
2897 {
2898 }
2899 else
2900 {
2901 if ((w1->name2 == NULL) || (w2->name2 == NULL))
2902 {
2903 return 0;
2904 }
2905 else if (strcmp(w1->name2, w2->name2) != 0)
2906 {
2907 dbg(0, "x:w1 n2=%s w2 n2=%s\n", w1->name2, w2->name2);
2908 return 0;
2909 }
2910 }
2911
2912 return 1;
2913
2914 #else
2915
2916 return 0;
2917
2918 #endif
2919
2920 }
2921
2922 /**
2923 * @brief Checks if two navigation items are on the same street
2924 *
2925 * This function checks if two navigation items are on the same street. It returns
2926 * true if either their name or their "systematic name" (e.g. "A6" or "B256") are the
2927 * same.
2928 *
2929 * @param old The first item to be checked
2930 * @param new The second item to be checked
2931 * @return True if both old and new are on the same street
2932 */
2933 static int is_same_street2(char *old_name1, char *old_name2, char *new_name1, char *new_name2)
2934 {
2935 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
2936 {
2937 // always return false when in bicycle mode
2938 return 0;
2939 }
2940
2941 if (old_name1 && new_name1 && !strcmp(old_name1, new_name1))
2942 {
2943 // dbg(1, "is_same_street: '%s' '%s' vs '%s' '%s' yes (1.)\n", old_name2, new_name2, old_name1, new_name1);
2944 return 1;
2945 }
2946
2947 if (old_name2 && new_name2 && !strcmp(old_name2, new_name2))
2948 {
2949 // dbg(1, "is_same_street: '%s' '%s' vs '%s' '%s' yes (2.)\n", old_name2, new_name2, old_name1, new_name1);
2950 return 1;
2951 }
2952
2953 // dbg(1, "is_same_street: '%s' '%s' vs '%s' '%s' no\n", old_name2, new_name2, old_name1, new_name1);
2954 return 0;
2955 }
2956
2957 #if 0
2958 /**
2959 * @brief Checks if two navigation items are on the same street
2960 *
2961 * This function checks if two navigation items are on the same street. It returns
2962 * true if the first part of their "systematic name" is equal. If the "systematic name" is
2963 * for example "A352/E3" (a german highway which at the same time is part of the international
2964 * E-road network), it would only search for "A352" in the second item's systematic name.
2965 *
2966 * @param old The first item to be checked
2967 * @param new The second item to be checked
2968 * @return True if the "systematic name" of both items matches. See description.
2969 */
2970 static int
2971 is_same_street_systematic(struct navigation_itm *old, struct navigation_itm *new)
2972 {
2973 int slashold,slashnew;
2974 if (!old->name2 || !new->name2)
2975 return 1;
2976 slashold=strcspn(old->name2, "/");
2977 slashnew=strcspn(new->name2, "/");
2978 if (slashold != slashnew || strncmp(old->name2, new->name2, slashold))
2979 return 0;
2980 return 1;
2981 }
2982
2983 /**
2984 * @brief Check if there are multiple possibilities to drive from old
2985 *
2986 * This function checks, if there are multiple streets connected to the exit of "old".
2987 * Sometimes it happens that an item on a map is just segmented, without any other streets
2988 * being connected there, and it is not useful if navit creates a maneuver there.
2989 *
2990 * @param new The navigation item we're driving to
2991 * @return True if there are multiple streets
2992 */
2993 static int
2994 maneuver_multiple_streets(struct navigation_itm *new)
2995 {
2996 if (new->way.next)
2997 {
2998 return 1;
2999 }
3000 else
3001 {
3002 return 0;
3003 }
3004 }
3005
3006 /**
3007 * @brief Check if the new item is entered "straight"
3008 *
3009 * This function checks if the new item is entered "straight" from the old item, i.e. if there
3010 * is no other street one could take from the old item on with less steering.
3011 *
3012 * @param new The navigation item we're driving to
3013 * @param diff The absolute angle one needs to steer to drive to this item
3014 * @return True if the new item is entered "straight"
3015 */
3016 static int
3017 maneuver_straight(struct navigation_itm *new, int diff)
3018 {
3019 int curr_diff;
3020 struct navigation_way *w;
3021
3022 w = new->way.next;
3023 dbg(1,"diff=%d\n", diff);
3024 while (w)
3025 {
3026 curr_diff=abs(angle_delta(new->prev->angle_end, w->angle2));
3027 dbg(1,"curr_diff=%d\n", curr_diff);
3028 if (curr_diff < diff)
3029 {
3030 return 0;
3031 }
3032 w = w->next;
3033 }
3034 return 1;
3035 }
3036 #endif
3037
3038 static int maneuver_category(enum item_type type)
3039 {
3040 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
3041 {
3042 switch (type)
3043 {
3044 case type_cycleway:
3045 return 1;
3046 case type_footway:
3047 return 1;
3048 case type_street_service:
3049 return 1;
3050 case type_street_parking_lane:
3051 return 1;
3052 case type_living_street:
3053 return 1;
3054 case type_street_0:
3055 return 1;
3056 case type_street_1_city:
3057 return 2;
3058 case type_street_2_city:
3059 case type_ramp_street_2_city:
3060 return 3;
3061 case type_street_3_city:
3062 case type_ramp_street_3_city:
3063 return 4;
3064 case type_street_4_city:
3065 case type_ramp_street_4_city:
3066 return 5;
3067 case type_highway_city:
3068 return 7;
3069 case type_street_1_land:
3070 return 2;
3071 case type_street_2_land:
3072 return 3;
3073 case type_street_3_land:
3074 return 4;
3075 case type_street_4_land:
3076 return 5;
3077 case type_street_n_lanes:
3078 return 6;
3079 case type_ramp_highway_land:
3080 return 6;
3081 case type_highway_land:
3082 return 7;
3083 //case type_ramp:
3084 // return 0;
3085 case type_roundabout:
3086 return 0;
3087 case type_ferry:
3088 return 0;
3089 default:
3090 return 0;
3091 }
3092 }
3093 else // car mode ---------------
3094 {
3095 switch (type)
3096 {
3097 case type_street_0:
3098 return 1;
3099 case type_street_1_city:
3100 return 2;
3101 case type_street_2_city:
3102 case type_ramp_street_2_city:
3103 return 3;
3104 case type_street_3_city:
3105 case type_ramp_street_3_city:
3106 return 4;
3107 case type_street_4_city:
3108 case type_ramp_street_4_city:
3109 return 5;
3110 case type_highway_city:
3111 return 7;
3112 case type_street_1_land:
3113 return 2;
3114 case type_street_2_land:
3115 return 3;
3116 case type_street_3_land:
3117 return 4;
3118 case type_street_4_land:
3119 return 5;
3120 case type_street_n_lanes:
3121 return 6;
3122 case type_ramp_highway_land:
3123 return 6;
3124 case type_highway_land:
3125 return 7;
3126 //case type_ramp:
3127 // return 0;
3128 case type_roundabout:
3129 return 0;
3130 case type_ferry:
3131 return 0;
3132 default:
3133 return 0;
3134 }
3135 }
3136 }
3137
3138
3139
3140
3141
3142 static int maneuver_category_calc2(enum item_type type)
3143 {
3144 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
3145 {
3146 switch (type)
3147 {
3148 case type_cycleway:
3149 return 1;
3150 case type_footway:
3151 return 1;
3152 case type_street_service:
3153 return 1;
3154 case type_street_parking_lane:
3155 return 1;
3156 case type_living_street:
3157 return 1;
3158 case type_street_0:
3159 return 1;
3160 case type_street_1_city:
3161 return 2;
3162 case type_street_2_city:
3163 case type_ramp_street_2_city:
3164 return 3;
3165 case type_street_3_city:
3166 case type_ramp_street_3_city:
3167 return 4;
3168 case type_street_4_city:
3169 case type_ramp_street_4_city:
3170 return 5;
3171 case type_highway_city:
3172 return 7;
3173 case type_street_1_land:
3174 return 2;
3175 case type_street_2_land:
3176 return 3;
3177 case type_street_3_land:
3178 return 4;
3179 case type_street_4_land:
3180 return 5;
3181 case type_street_n_lanes:
3182 return 6;
3183 case type_ramp_highway_land:
3184 return 6;
3185 case type_highway_land:
3186 return 7;
3187 //case type_ramp:
3188 // return 0;
3189 case type_roundabout:
3190 return 0;
3191 case type_ferry:
3192 return 0;
3193 default:
3194 return 0;
3195 }
3196 }
3197 else
3198 {
3199 switch (type)
3200 {
3201 case type_street_0:
3202 return 1;
3203 case type_street_1_city:
3204 return 1;
3205 case type_street_2_city:
3206 case type_ramp_street_2_city:
3207 return 4;
3208 case type_street_3_city:
3209 case type_ramp_street_3_city:
3210 return 4;
3211 case type_street_4_city:
3212 case type_ramp_street_4_city:
3213 return 4;
3214 case type_highway_city:
3215 return 7;
3216 case type_street_1_land:
3217 return 1;
3218 case type_street_2_land:
3219 return 4;
3220 case type_street_3_land:
3221 return 4;
3222 case type_street_4_land:
3223 return 4;
3224 case type_street_n_lanes:
3225 return 6;
3226 case type_ramp_highway_land:
3227 return 6;
3228 case type_highway_land:
3229 return 7;
3230 //case type_ramp: // ramp need to be high enough
3231 // return 4;
3232 case type_roundabout:
3233 return 0;
3234 case type_ferry:
3235 return 0;
3236 default:
3237 return 0;
3238 }
3239 }
3240 }
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251 static int is_way_allowed(struct navigation *nav, struct navigation_way *way, int mode)
3252 {
3253 if (!nav->vehicleprofile)
3254 {
3255 return 1;
3256 }
3257
3258 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);
3259 }
3260
3261 /**
3262 * @brief Checks if navit has to create a maneuver to drive from old to new (run only once!!)
3263 *
3264 * This function checks if it has to create a "maneuver" - i.e. guide the user - to drive
3265 * from "old" to "new".
3266 *
3267 * @param old The old navigation item, where we're coming from
3268 * @param new The new navigation item, where we're going to
3269 * @param delta The angle the user has to steer to navigate from old to new
3270 * @param reason A text string explaining how the return value resulted
3271 * @return True if navit should guide the user, false otherwise
3272 */
3273 static int maneuver_required2(struct navigation *nav, struct navigation_itm *old, struct navigation_itm *new, int *delta, int *delta_real, char **reason)
3274 {
3275 int ret = 0, d, dw, dlim;
3276 char *r = NULL;
3277 struct navigation_way *w = NULL;
3278 int cat, ncat, wcat, maxcat, left = -180, right = 180, is_unambigous = 0, is_same_street;
3279 int cat_2 = 0;
3280 int ncat_2 = 0;
3281 int highest_other_cat = 0;
3282 int original_d = 0;
3283
3284 dbg(0, "STRAI:000:\n");
3285 dbg(0, "STRAI:000:======================================\n");
3286
3287 // ---------------------------
3288 //
3289 // HINT: angle < 0 --> left
3290 // > 0 --> right
3291 // = 0 --> straight
3292 //
3293 // ---------------------------
3294
3295 d = angle_delta(old->angle_end, new->way.angle2);
3296 original_d = d;
3297
3298 //long long wayid_old = navigation_item_get_wayid(&(old->way));
3299 //long long wayid_new = navigation_item_get_wayid(&(new->way));
3300 //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);
3301
3302 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2)) // bicycle mode
3303 {
3304 int flags_old = navigation_item_get_flags(&(old->way));
3305 int flags_new = navigation_item_get_flags(&(new->way));
3306
3307 //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);
3308 //dbg(0, "(b2)old flags=%x new flags=%x\n", (flags_old & NAVIT_AF_ONEWAY), (flags_new & NAVIT_AF_ONEWAY));
3309 //dbg(0, "(b3)old flags=%x new flags=%x\n", (flags_old & NAVIT_AF_ONEWAYREV), (flags_new & NAVIT_AF_ONEWAYREV));
3310
3311 if ((old->way.dir == 1) && ((new->way.dir == -1) && (new->way.flags & NAVIT_AF_ONEWAY_BICYCLE_NO)))
3312 {
3313 r = "yes: bicycle starts going against oneway here (1)";
3314 ret = 1;
3315 //dbg(0, "%s\n", r);
3316 }
3317 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)))
3318 {
3319 r = "yes: bicycle starts going against oneway here (2)";
3320 ret = 1;
3321 //dbg(0, "%s\n", r);
3322 }
3323 }
3324
3325
3326
3327
3328 // z2z2
3329 int have_more_than_one_way_to_turn = 0;
3330 int have_more_than_one_way_to_turn_cycleways = 0;
3331 struct navigation_way *w22;
3332 w22 = new->way.next;
3333 int new_angle_abs = 999;
3334 int new_angle_abs_min = 999;
3335 int new_angle_abs_min_allowed = 999;
3336 int new_angle_real = 999;
3337 int new_angle_min_allowed = 999;
3338 int new_angle_abs_min_ramp_allowed = 999;
3339 int old_angle_abs = abs(d);
3340 int new_angle_closest_to_cur = 999;
3341 int no_correction = 0;
3342
3343 dbg(0, "STRAI:001:d=%d original_d=%d\n", old_angle_abs, original_d);
3344
3345 while (w22)
3346 {
3347
3348 dbg(0, "STRAI:002\n");
3349
3350 //if ((w22->dir == -1) && (w22->flags & NAVIT_AF_ONEWAY))
3351 //{
3352 // // against oneway not allowed
3353 //}
3354 if (((global_vehicle_profile != 1) && (global_vehicle_profile != 2)) // NOT bicycle mode
3355 && (navigation_is_low_level_street(old->way.item.type) == 0)
3356 && (navigation_is_low_level_street(new->way.item.type) == 0)
3357 && (navigation_is_low_level_street(w22->item.type) == 1))
3358 {
3359 // dont count "lower" streets when not on "lower" street now or next
3360 }
3361 else
3362 {
3363
3364 if ( (is_maybe_same_item(&(new->way), w22, 0) == 0) && (is_maybe_same_item(&(old->way), w22, 1) == 0) )
3365 {
3366
3367 new_angle_real = angle_delta(old->angle_end, w22->angle2);
3368 new_angle_abs = abs(new_angle_real);
3369 if (new_angle_abs < new_angle_abs_min)
3370 {
3371 new_angle_abs_min = new_angle_abs;
3372 }
3373
3374 if (is_way_allowed(nav, w22, 1))
3375 {
3376 have_more_than_one_way_to_turn = 1;
3377
3378 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2)) // bicycle mode
3379 {
3380 if (w22->item.type == type_cycleway)
3381 {
3382 have_more_than_one_way_to_turn_cycleways = 1;
3383 }
3384 }
3385
3386 if (maneuver_category_calc2(w22->item.type) > highest_other_cat)
3387 {
3388 highest_other_cat = maneuver_category_calc2(w22->item.type);
3389 }
3390
3391 if (item_is_ramp(w22->item))
3392 {
3393 if (new_angle_abs < new_angle_abs_min_ramp_allowed)
3394 {
3395 new_angle_abs_min_ramp_allowed = new_angle_abs;
3396 }
3397 }
3398
3399 if (abs(new_angle_real - d) < abs(new_angle_closest_to_cur))
3400 {
3401 new_angle_closest_to_cur = new_angle_real;
3402 }
3403
3404 if (new_angle_abs < new_angle_abs_min_allowed)
3405 {
3406 new_angle_abs_min_allowed = new_angle_abs;
3407 new_angle_min_allowed = new_angle_real;
3408 }
3409 }
3410
3411 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);
3412
3413 }
3414 }
3415 w22 = w22->next;
3416 }
3417
3418 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);
3419
3420 if ((new_angle_abs_min_allowed > ROAD_ANGLE_IS_STRAIGHT_ABS) && (old_angle_abs <= ROAD_ANGLE_IS_STRAIGHT_ABS))
3421 {
3422 dbg(0, "STRAI:005 new_abs=%d old_abs=%d\n", new_angle_abs_min_allowed, old_angle_abs);
3423
3424 // we want to drive almost straight, set angle to "0"
3425 d = 0;
3426 }
3427
3428 dbg(0, "STRAI:005a:d=%d\n", d);
3429
3430 if (!r)
3431 {
3432 if (have_more_than_one_way_to_turn == 1) // more than 1 possibility
3433 {
3434 if (new->way.exit_label)
3435 {
3436 // highway to highway, nearest ramp is more than 15° angle turn
3437 if ( (cat > 6) && (ncat > 6) && (highest_other_cat <= 6) && (abs(d) < 12) && (new_angle_abs_min_ramp_allowed > 15) )
3438 {
3439 dbg(0, "STRAI:005a:d=%d\n", d);
3440 r = "no: driving almost straight on highway and no other highway possibilities (1)";
3441 }
3442 else
3443 {
3444 // r = "yes: we have an exit-sign to tell the user";
3445 // ret = 1;
3446 }
3447 }
3448 else if (new->way.s_destination)
3449 {
3450 if ( (cat > 6) && (ncat > 6) && (highest_other_cat <= 6) && (abs(d) < 12) && (new_angle_abs_min_ramp_allowed > 15) )
3451 {
3452 dbg(0, "STRAI:005a:d=%d\n", d);
3453 r = "no: driving almost straight on highway and no other highway possibilities (2)";
3454 }
3455 else
3456 {
3457 // r = "yes: we have a road-sign to tell the user";
3458 // ret = 1;
3459 }
3460 }
3461 else if (item_is_ramp(old->way.item))
3462 {
3463 r = "yes: we are currently on a ramp and have more than 1 road to take";
3464 ret = 1;
3465 }
3466 }
3467 }
3468
3469
3470 if ((global_vehicle_profile != 1) && (global_vehicle_profile != 2))
3471 {
3472 if (!new->way.next)
3473 {
3474 /* No announcement necessary */
3475 r = "no: Only one possibility";
3476 }
3477 else if (!new->way.next->next && item_is_ramp(new->way.next->item) && !is_way_allowed(nav, new->way.next, 1))
3478 {
3479 /* If the other way is only a ramp and it is one-way in the wrong direction, no announcement necessary */
3480 r = "no: Only ramp";
3481 }
3482 }
3483 else // bicycle mode --------------------
3484 {
3485 if (!r)
3486 {
3487 #if 0
3488 if ((!new->way.next) && (abs(d) < 20))
3489 {
3490 /* No announcement necessary */
3491 r = "no: Only one possibility and less than 20° turn";
3492 dbg(0, "%s\n", r);
3493 }
3494 else
3495 {
3496 if (abs(d) > 2)
3497 {
3498 r = "yes: bicycle mode";
3499 dbg(0, "%s\n", r);
3500 ret = 1;
3501 }
3502 else
3503 {
3504 r = "no: less than 3° turn";
3505 dbg(0, "%s\n", r);
3506 }
3507 }
3508 #endif
3509
3510 #if 0
3511 if (!new->way.next)
3512 {
3513 /* No announcement necessary */
3514 r = "no: Only one possibility";
3515 }
3516 #endif
3517
3518 #if 1
3519
3520 if ((old->way.item.type == type_cycleway) && (new->way.item.type == type_cycleway))
3521 {
3522 if (have_more_than_one_way_to_turn_cycleways == 0)
3523 {
3524 if (abs(d) > ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE_CYC_2_CYC)
3525 {
3526 r = "yes: delta over ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE_CYC_2_CYC in bicycle mode (Only one possibility cyc-2-cyc)";
3527 //dbg(0, "%s\n", r);
3528 ret = 1;
3529 }
3530 else
3531 {
3532 r = "no: delta less than ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE_CYC_2_CYC in bicycle mode (Only one possibility cyc-2-cyc)";
3533 //dbg(0, "%s\n", r);
3534 ret = 0;
3535 }
3536 }
3537 else
3538 {
3539 if (abs(d) > ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE_CYC_2_CYC__2)
3540 {
3541 r = "yes: delta over ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE_CYC_2_CYC__2 in bicycle mode (cyc-2cyc)";
3542 //dbg(0, "%s\n", r);
3543 ret = 1;
3544 }
3545 else
3546 {
3547 r = "no: delta less than ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE_CYC_2_CYC__2 in bicycle mode (cyc-2cyc)";
3548 //dbg(0, "%s\n", r);
3549 ret = 0;
3550 }
3551 }
3552 }
3553 else
3554 {
3555
3556 if (!new->way.next)
3557 {
3558 if (abs(d) > ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE)
3559 {
3560 r = "yes: delta over ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE in bicycle mode (Only one possibility)";
3561 //dbg(0, "%s\n", r);
3562 ret = 1;
3563 }
3564 else
3565 {
3566 r = "no: delta less than ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE in bicycle mode (Only one possibility)";
3567 //dbg(0, "%s\n", r);
3568 ret = 0;
3569 }
3570 }
3571 else
3572 {
3573 if (abs(d) > ROAD_ANGLE_MIN__FOR_TURN_BICYCLEMODE_ONLY_1_POSSIBILITY)
3574 {
3575 r = "yes: delta over ROAD_ANGLE_MIN__FOR_TURN_BICYCLEMODE_ONLY_1_POSSIBILITY in bicycle mode";
3576 //dbg(0, "%s\n", r);
3577 ret = 1;
3578 }
3579 else
3580 {
3581 r = "no: delta less than ROAD_ANGLE_MIN__FOR_TURN_BICYCLEMODE_ONLY_1_POSSIBILITY in bicycle mode";
3582 //dbg(0, "%s\n", r);
3583 ret = 0;
3584 }
3585 }
3586
3587 }
3588 #endif
3589
3590 }
3591 }
3592
3593 if (!r)
3594 {
3595 if ((old->way.flags & NAVIT_AF_ROUNDABOUT) && !(new->way.flags & NAVIT_AF_ROUNDABOUT))
3596 {
3597 r = "yes: leaving roundabout";
3598 ret = 1;
3599 }
3600 else if (!(old->way.flags & NAVIT_AF_ROUNDABOUT) && (new->way.flags & NAVIT_AF_ROUNDABOUT))
3601 {
3602 r = "no: entering roundabout";
3603 }
3604 else if ((old->way.flags & NAVIT_AF_ROUNDABOUT) && (new->way.flags & NAVIT_AF_ROUNDABOUT))
3605 {
3606 r = "no: staying in roundabout";
3607 }
3608 }
3609
3610 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
3611 {
3612 if (!r && abs(d) > ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE)
3613 {
3614 /* always make an announcement if you have to make a turn */
3615 r = "yes: delta over ROAD_ANGLE_MIN_FOR_TURN_BICYCLEMODE in bicycle mode";
3616 //dbg(0, "%s\n", r);
3617 ret = 1;
3618 }
3619 }
3620 else // car mode ---------------------
3621 {
3622 if (!r && abs(d) > 75)
3623 {
3624 /* always make an announcement if you have to make a sharp turn */
3625 r = "yes: delta over 75";
3626 ret = 1;
3627 }
3628 }
3629
3630 cat = maneuver_category(old->way.item.type);
3631 ncat = maneuver_category(new->way.item.type);
3632
3633 cat_2 = maneuver_category_calc2(old->way.item.type);
3634 ncat_2 = maneuver_category_calc2(new->way.item.type);
3635
3636
3637 if (!r)
3638 {
3639 /* Check whether the street keeps its name */
3640 is_same_street = is_same_street2(old->way.name1, old->way.name2, new->way.name1, new->way.name2);
3641
3642 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);
3643
3644 w = new->way.next;
3645 maxcat = -1;
3646 while (w)
3647 {
3648 if ( (is_maybe_same_item(&(new->way), w, 0) == 0) && (is_maybe_same_item(&(old->way), w, 1) == 0) )
3649 {
3650 dw = angle_delta(old->angle_end, w->angle2);
3651 dbg(0, "STRAI:011.02 dw=%d l=%d r=%d\n", dw, left, right);
3652
3653 if (dw < 0)
3654 {
3655 if (dw > left)
3656 {
3657 left = dw;
3658 }
3659 }
3660 else
3661 {
3662 if (dw < right)
3663 {
3664 right = dw;
3665 }
3666 }
3667
3668 wcat = maneuver_category(w->item.type);
3669 dbg(0, "STRAI:011.03 wcat=%d\n", wcat);
3670
3671 /* If any other street has the same name [ removed:"but isn't a highway (a highway might split up temporarily)" ], then
3672 we can't use the same name criterium */
3673 // 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))
3674 if (is_same_street && is_same_street2(old->way.name1, old->way.name2, w->name1, w->name2) && is_way_allowed(nav, w, 2))
3675 {
3676 is_same_street = 0;
3677 dbg(0, "STRAI:011.04 is_same_street=%d\n", is_same_street);
3678 }
3679
3680 /* Mark if the street has a higher or the same category */
3681 if (wcat > maxcat)
3682 {
3683 maxcat = wcat;
3684 dbg(0, "STRAI:011.06 maxcat=%d wcat=%d\n", maxcat, wcat);
3685 }
3686
3687 }
3688
3689 w = w->next;
3690 }
3691
3692 if (have_more_than_one_way_to_turn == 1) // more than 1 possibility
3693 {
3694 /* Even if the ramp has the same name, announce it */
3695 if (item_is_ramp(new->way.item) && !item_is_ramp(old->way.item))
3696 {
3697 is_same_street = 0;
3698 dbg(0, "STRAI:011.05.xx is_same_street=%d\n", is_same_street);
3699 }
3700 }
3701
3702 /* get the delta limit for checking for other streets. It is lower if the street has no other
3703 streets of the same or higher category */
3704 if (ncat < cat)
3705 {
3706 dlim = 80;
3707 }
3708 else
3709 {
3710 dlim = 120;
3711 }
3712
3713 /* if the street is really straight, the others might be closer to straight */
3714 if (abs(d) < 20)
3715 {
3716 dlim /= 2;
3717 }
3718
3719 if ((maxcat == ncat && maxcat == cat) || (ncat == 0 && cat == 0))
3720 {
3721 dlim = abs(d) * (620 / 256); // abs(d) * 2.4
3722 }
3723 else if (maxcat < ncat && maxcat < cat)
3724 {
3725 dlim = abs(d) * (128 / 256); // abs(d) * 0.5
3726 }
3727
3728 if (left < -dlim && right > dlim) // no other road is between -dlim : dlim angle (no other road is "dlim" close to straight)
3729 {
3730 is_unambigous = 1;
3731 }
3732
3733 if (!is_same_street && is_unambigous < 1)
3734 {
3735 ret = 1;
3736 r = "yes: (not same street) or (ambigous [nicht eindeutig])";
3737 }
3738 else
3739 {
3740 r = "no: (same street) and (unambigous [eindeutig])";
3741 }
3742
3743 if (ret == 0)
3744 {
3745 // add a new check here:
3746 if (have_more_than_one_way_to_turn == 1)
3747 {
3748
3749 dbg(0, "STRAI:11.07:4.0: cat=%d, ncat=%d, highest_other_cat=%d, d=%d, abs(d)=%d new_angle_closest_to_cur=%d original_d=%d\n", cat, ncat, highest_other_cat, d, abs(d), new_angle_closest_to_cur, original_d);
3750
3751 if ( (cat > 6) && (ncat > 6) && (highest_other_cat <= 6) && (abs(d) < 70) )
3752 {
3753 r = "no: from highway to highway (no other highway possibilities)";
3754 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);
3755 }
3756 else
3757 {
3758
3759 if ((ncat == 6) && (highest_other_cat == 6) && (abs(d) < 50) && (abs(new_angle_closest_to_cur - original_d) < 65))
3760 {
3761 ret = 1;
3762 r = "yes: we are driving onto a ramp and there a other ramps near (<50 degrees) to it";
3763 dbg(0, "STRAI:011.07:3.001 ncat=%d highest_other_cat=%d d=%d (new_angle_closest_to_cur=%d - original_d=%d)\n", ncat, highest_other_cat, d, new_angle_closest_to_cur, original_d);
3764 }
3765
3766
3767 if ((d == 0) && (new_angle_abs_min_allowed >= 25))
3768 {
3769 r = "no: driving almost straight, and other ways not very close to straight";
3770 dbg(0, "STRAI:011.07:3 abs(d)=%d new_angle_abs_min_allowed=%d\n", abs(d), new_angle_abs_min_allowed);
3771 }
3772 else
3773 {
3774
3775 if ( (d == 0) && (abs(new_angle_closest_to_cur - original_d) < 16) )
3776 {
3777 ret = 1;
3778 r = "yes: we are going straight and some other way is very close to it";
3779 dbg(0, "STRAI:011.07:0 abs(d)=%d new_angle_abs_min_allowed=%d\n", abs(d), new_angle_abs_min_allowed);
3780 }
3781 else if ( (ncat_2 <= highest_other_cat) && (d == 0) && (abs(new_angle_closest_to_cur - original_d) < 30) )
3782 {
3783 ret = 1;
3784 r = "yes: we are going straight and some other way is very close to it (same or higher cat)";
3785 dbg(0, "STRAI:011.07:7 abs(d)=%d new_angle_abs_min_allowed=%d\n", abs(d), new_angle_abs_min_allowed);
3786 }
3787 else if ((abs(d) > 0) && (new_angle_abs_min_allowed < abs(d)))
3788 {
3789 ret = 1;
3790 r = "yes: some other way is going more straight";
3791 dbg(0, "STRAI:011.07:0 abs(d)=%d new_angle_abs_min_allowed=%d\n", abs(d), new_angle_abs_min_allowed);
3792
3793
3794 if (abs(d) < 10)
3795 {
3796
3797 // ----------########### more way left/right of way ? ###########----------
3798 int more_ways_to_left_ = 0;
3799 int more_ways_to_right_ = 0;
3800 w = new->way.next;
3801 while (w)
3802 {
3803 if (is_way_allowed(nav, w, 1))
3804 {
3805 if ( (is_maybe_same_item(&(new->way), w, 0) == 0) && (is_maybe_same_item(&(old->way), w, 1) == 0) )
3806 {
3807 dbg(0, "STRAI:108.02a delta=%d\n", angle_delta(old->angle_end, w->angle2));
3808
3809 if (is_way_allowed(nav, w, 1))
3810 {
3811 if (angle_delta(old->angle_end, w->angle2) < d) // other ways are going more to the left?
3812 {
3813 more_ways_to_left_++;
3814 }
3815 else if (angle_delta(old->angle_end, w->angle2) > d) // other ways are going more to the right?
3816 {
3817 more_ways_to_right_++;
3818 }
3819 }
3820 }
3821 }
3822 w = w->next;
3823 }
3824
3825 dbg(0, "STRAI:108.02 %d %d\n", more_ways_to_left_, more_ways_to_right_);
3826
3827
3828 if ((d < 0) && (more_ways_to_left_ == 0)) // && (more_ways_to_right_ > 0))
3829 {
3830
3831 dbg(0, "STRAI:108.03:left\n");
3832 *delta_real = 0;
3833 d = -8;
3834 no_correction = 1;
3835 }
3836 else if ((d > 0) && (more_ways_to_left_ > 0)) // && (more_ways_to_right_ == 0))
3837 {
3838 dbg(0, "STRAI:108.04:right\n");
3839 *delta_real = 0;
3840 d = 8;
3841 no_correction = 1;
3842 }
3843
3844
3845
3846 // ----------########### more way left/right of way ? ###########----------
3847
3848 }
3849
3850
3851 }
3852 else if ((abs(d) > 0) && (new_angle_abs_min_allowed < 39) && (is_same_street))
3853 {
3854 if ( (cat == ncat) && (ncat_2 > highest_other_cat) )
3855 {
3856 r = "no: we need to make a turn, but other possibilites are much lower cat roads";
3857 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);
3858 }
3859 else
3860 {
3861 ret = 1;
3862 r = "yes: we need to make a turn";
3863 dbg(0, "STRAI:011.07:1iss abs(d)=%d new_angle_abs_min_allowed=%d\n", abs(d), new_angle_abs_min_allowed);
3864 }
3865 }
3866 else if ((abs(d) > 0) && (new_angle_abs_min_allowed < 52) && (!is_same_street))
3867 {
3868 if ( (cat == ncat) && (ncat_2 > highest_other_cat) )
3869 {
3870 r = "no: we need to make a turn, but other possibilites are much lower cat roads";
3871 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);
3872 }
3873 else
3874 {
3875 ret = 1;
3876 r = "yes: we need to make a turn";
3877 dbg(0, "STRAI:011.07:1nss abs(d)=%d new_angle_abs_min_allowed=%d\n", abs(d), new_angle_abs_min_allowed);
3878 }
3879 }
3880 else
3881 {
3882 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);
3883 }
3884 }
3885 }
3886 }
3887 }
3888
3889 dbg(0, "STRAI:011.07 is_unambigous[eindeutig]=%d ret=%d r=%s\n", is_unambigous, ret, r);
3890
3891 #ifdef DEBUG
3892 // 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);
3893 #endif
3894 }
3895
3896
3897
3898
3899
3900
3901 dbg(0, "STRAI:007.00aa:d=%d ******************++++++++++++\n", d);
3902
3903
3904
3905
3906
3907 // correct "delta" (turn angle) here !! ---------------------------
3908 // correct "delta" (turn angle) here !! ---------------------------
3909
3910 if (no_correction == 0)
3911 {
3912 *delta_real = d;
3913 }
3914
3915 if ((ret == 1) && (have_more_than_one_way_to_turn == 1) && (no_correction == 0))
3916 {
3917 w = new->way.next;
3918 //int d2 = angle_delta(old->angle_end, new->way.angle2);
3919 int d2 = d;
3920 //if (d == 0)
3921 //{
3922 // d2 = 0;
3923 //}
3924
3925 int correct_direction = 1;
3926
3927 dbg(0, "STRAI:007.01:d=%d d2=%d\n", d, d2);
3928
3929 if (d2 < 0) // left
3930 {
3931 while (w)
3932 {
3933 if (is_way_allowed(nav, w, 1))
3934 {
3935 if ( (is_maybe_same_item(&(new->way), w, 0) == 0) && (is_maybe_same_item(&(old->way), w, 1) == 0) )
3936 {
3937 if (angle_delta(old->angle_end, w->angle2) > d2) // other ways are going more to the right?
3938 {
3939 correct_direction = 0;
3940 break;
3941 }
3942 }
3943 }
3944 w = w->next;
3945 }
3946
3947 if (correct_direction == 1)
3948 {
3949 #ifdef NAVIT_ROUTING_DEBUG_PRINT
3950 dbg(0, "MAV:001:correct to right\n");
3951 #endif
3952 d = 8; // set to "slight right"
3953 }
3954 }
3955 else if (d2 > 0) // right
3956 {
3957 while (w)
3958 {
3959 if (is_way_allowed(nav, w, 1))
3960 {
3961 if ( (is_maybe_same_item(&(new->way), w, 0) == 0) && (is_maybe_same_item(&(old->way), w, 1) == 0) )
3962 {
3963 if (angle_delta(old->angle_end, w->angle2) < d2) // other ways are going more to the left?
3964 {
3965 correct_direction = 0;
3966 break;
3967 }
3968 }
3969 }
3970 w = w->next;
3971 }
3972
3973 if (correct_direction == 1)
3974 {
3975 #ifdef NAVIT_ROUTING_DEBUG_PRINT
3976 dbg(0, "MAV:002:correct to left\n");
3977 #endif
3978 d = -8; // set to "slight left"
3979 }
3980 }
3981 else // (d2 == 0) // straight
3982 {
3983
3984 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);
3985
3986 int more_ways_to_left = 0;
3987 int more_ways_to_right = 0;
3988
3989 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
3990 {
3991 dbg(0, "STRAI:008.02\n");
3992
3993
3994 if ((abs(new_angle_closest_to_cur - original_d) <= 25) || (abs(original_d) >= 10))
3995 // if (1 == 1)
3996 {
3997
3998 while (w)
3999 {
4000 if (is_way_allowed(nav, w, 1))
4001 {
4002 if ( (is_maybe_same_item(&(new->way), w, 0) == 0) && (is_maybe_same_item(&(old->way), w, 1) == 0) )
4003 {
4004 dbg(0, "STRAI:008.02a delta=%d\n", angle_delta(old->angle_end, w->angle2));
4005
4006 if (is_way_allowed(nav, w, 1))
4007 {
4008 if (angle_delta(old->angle_end, w->angle2) < d2) // other ways are going more to the left?
4009 {
4010 more_ways_to_left++;
4011 }
4012 else if (angle_delta(old->angle_end, w->angle2) > d2) // other ways are going more to the right?
4013 {
4014 more_ways_to_right++;
4015 }
4016 }
4017 }
4018 }
4019 w = w->next;
4020 }
4021
4022 dbg(0, "STRAI:008.02 %d %d\n", more_ways_to_left, more_ways_to_right);
4023
4024 if ((more_ways_to_left == 0) && (more_ways_to_right > 0))
4025 {
4026
4027 dbg(0, "STRAI:008.03:left\n");
4028
4029 #ifdef NAVIT_ROUTING_DEBUG_PRINT
4030 dbg(0, "MAV:003:correct to left\n");
4031 #endif
4032 d = -8;
4033 }
4034 else if ((more_ways_to_left > 0) && (more_ways_to_right == 0))
4035 {
4036 dbg(0, "STRAI:008.04:right\n");
4037
4038 #ifdef NAVIT_ROUTING_DEBUG_PRINT
4039 dbg(0, "MAV:003:correct to right\n");
4040 #endif
4041 d = 8;
4042 }
4043
4044 }
4045 else
4046 {
4047 dbg(0, "STRAI:008.02f street almost straight and nearest other street at least 25 away: closest=%d orig_d=%d\n", new_angle_closest_to_cur, original_d);
4048 }
4049
4050 }
4051
4052 }
4053
4054 }
4055
4056 // correct "delta" (turn angle) here !! ---------------------------
4057 // correct "delta" (turn angle) here !! ---------------------------
4058
4059
4060
4061
4062
4063
4064
4065
4066 dbg(0, "STRAI:099:ret=%d r=%s d=%d d_real=%d\n", ret, r, d, *delta_real);
4067 dbg(0, "STRAI:099:======================================\n");
4068
4069 *delta = d;
4070 if (reason)
4071 {
4072 *reason = r;
4073 }
4074
4075 return ret;
4076 }
4077
4078 static struct navigation_command *command_new(struct navigation *this_, struct navigation_itm *itm, int delta, int delta_real)
4079 {
4080 struct navigation_command *ret=g_new0(struct navigation_command, 1);
4081
4082 //dbg(1, "enter this_=%p itm=%p delta=%d\n", this_, itm, delta);
4083 ret->delta = delta;
4084 ret->delta_real = delta_real;
4085 ret->itm = itm;
4086
4087 if (itm && itm->prev && itm->way.next && itm->prev->way.next && !(itm->way.flags & NAVIT_AF_ROUNDABOUT) && (itm->prev->way.flags & NAVIT_AF_ROUNDABOUT))
4088 {
4089 int len = 0;
4090 int angle = 0;
4091 int entry_angle;
4092 struct navigation_itm *itm2 = itm->prev;
4093 int exit_angle = angle_median(itm->prev->angle_end, itm->way.next->angle2);
4094 //dbg(1, "exit %d median from %d,%d\n", exit_angle, itm->prev->angle_end, itm->way.next->angle2);
4095
4096 while (itm2 && (itm2->way.flags & NAVIT_AF_ROUNDABOUT))
4097 {
4098 len += itm2->length;
4099 angle = itm2->angle_end;
4100 itm2 = itm2->prev;
4101 }
4102
4103 if (itm2 && itm2->next && itm2->next->way.next)
4104 {
4105 itm2 = itm2->next;
4106 entry_angle = angle_median(angle_opposite(itm2->way.angle2), itm2->way.next->angle2);
4107 // dbg(1, "entry %d median from %d(%d),%d\n", entry_angle, angle_opposite(itm2->way.angle2), itm2->way.angle2, itm2->way.next->angle2);
4108 }
4109 else
4110 {
4111 entry_angle = angle_opposite(angle);
4112 }
4113 //dbg(0, "entry %d exit %d\n", entry_angle, exit_angle);
4114 ret->roundabout_delta = angle_delta(entry_angle, exit_angle);
4115 ret->length = len + roundabout_extra_length;
4116 }
4117
4118 if (this_->cmd_last)
4119 {
4120 this_->cmd_last->next = ret;
4121 ret->prev = this_->cmd_last;
4122 }
4123
4124 this_->cmd_last = ret;
4125
4126 if (!this_->cmd_first)
4127 {
4128 this_->cmd_first = ret;
4129 }
4130
4131 return ret;
4132 }
4133
4134
4135
4136 // ----------- main place where maneuvers generated (run only once) ------------
4137 // ----------- main place where maneuvers generated (run only once) ------------
4138 // ----------- main place where maneuvers generated (run only once) ------------
4139 static void make_maneuvers(struct navigation *this_, struct route *route)
4140 {
4141 __F_START__
4142
4143 struct navigation_itm *itm, *last = NULL, *last_itm = NULL;
4144 int delta;
4145 int delta_real;
4146 itm = this_->first;
4147 this_->cmd_last = NULL;
4148 this_->cmd_first = NULL;
4149 while (itm)
4150 {
4151 if (last)
4152 {
4153 if (maneuver_required2(this_, last_itm, itm, &delta, &delta_real, NULL))
4154 {
4155 //dbg(0, "maneuver_required2 = true\n");
4156 command_new(this_, itm, delta, delta_real);
4157 }
4158 }
4159 else
4160 {
4161 last = itm;
4162 }
4163 last_itm = itm;
4164 itm = itm->next;
4165 }
4166 command_new(this_, last_itm, 0, 0);
4167
4168 __F_END__
4169 }
4170 // ----------- main place where maneuvers generated ------------
4171 // ----------- main place where maneuvers generated ------------
4172 // ----------- main place where maneuvers generated ------------
4173
4174
4175
4176 static int contains_suffix(char *name, char *suffix)
4177 {
4178 if (!suffix)
4179 {
4180 return 0;
4181 }
4182
4183 if (strlen(name) < strlen(suffix))
4184 {
4185 return 0;
4186 }
4187
4188 return !g_strcasecmp(name + strlen(name) - strlen(suffix), suffix);
4189 }
4190
4191 static char *
4192 replace_suffix(char *name, char *search, char *replace)
4193 {
4194 int len = strlen(name) - strlen(search);
4195 char *ret = g_malloc(len + strlen(replace) + 1);
4196
4197 strncpy(ret, name, len);
4198 strcpy(ret + len, replace);
4199
4200 if (isupper(name[len]))
4201 {
4202 ret[len] = toupper(ret[len]);
4203 }
4204
4205 return ret;
4206 }
4207
4208 static char *
4209 navigation_item_destination(struct navigation *nav, struct navigation_itm *itm, struct navigation_itm *next, char *prefix)
4210 {
4211 char *ret = NULL, *name1, *sep, *name2;
4212 char *n1, *n2;
4213 int i, sex;
4214 int vocabulary1 = 65535;
4215 int vocabulary2 = 65535;
4216 struct attr attr;
4217
4218 if (!prefix)
4219 {
4220 prefix = "";
4221 }
4222
4223 if (nav->speech && speech_get_attr(nav->speech, attr_vocabulary_name, &attr, NULL))
4224 {
4225 vocabulary1 = attr.u.num;
4226 }
4227
4228 if (nav->speech && speech_get_attr(nav->speech, attr_vocabulary_name_systematic, &attr, NULL))
4229 {
4230 vocabulary2 = attr.u.num;
4231 }
4232
4233 n1 = itm->way.name1;
4234 n2 = itm->way.name2;
4235
4236 if (!vocabulary1)
4237 n1 = NULL;
4238
4239 if (!vocabulary2)
4240 n2 = NULL;
4241
4242 if (!n1 && !n2 && (item_is_ramp(itm->way.item)) && vocabulary2)
4243 {
4244 //dbg(1,">> Next is ramp %lx current is %lx \n", itm->way.item.type, next->way.item.type);
4245
4246
4247 // disabled for now !!!!!!!! -------------------------
4248 #if 0
4249 if (next->way.item.type == type_ramp)
4250 {
4251 return NULL;
4252 }
4253 #endif
4254 // disabled for now !!!!!!!! -------------------------
4255
4256
4257 //else
4258 //{
4259 // return g_strdup_printf("%s%s",prefix,_("into the ramp"));
4260 //}
4261
4262 #if 0
4263 if (itm->way.item.type == type_highway_city || itm->way.item.type == type_highway_land)
4264 {
4265 #ifdef HAVE_API_ANDROID
4266 #ifdef NAVIT_SAY_DEBUG_PRINT
4267 android_send_generic_text(1,"+*#O:exit\n");
4268 gchar* xy=g_strdup_printf("+*#1:%s\n", prefix);
4269 android_send_generic_text(1,xy);
4270 g_free(xy);
4271 #endif
4272 #endif
4273 return g_strdup_printf("%s%s", prefix, _("exit")); /* %FIXME Can this even be reached? and "exit" is the wrong text anyway ! */
4274 }
4275 else
4276 #endif
4277 {
4278 if (itm->way.street_dest_text)
4279 {
4280 #ifdef HAVE_API_ANDROID
4281 #ifdef NAVIT_SAY_DEBUG_PRINT
4282 gchar* xy=g_strdup_printf("+*#0:%s\n", itm->way.street_dest_text);
4283 android_send_generic_text(1,xy);
4284 g_free(xy);
4285 gchar* xy=g_strdup_printf("+*#1:%s\n", prefix);
4286 android_send_generic_text(1,xy);
4287 g_free(xy);
4288 #endif
4289 #endif
4290
4291 // say the name on the exit sign/destinaion sign
4292 return g_strdup_printf("%s%s", prefix, itm->way.street_dest_text);
4293 }
4294 else
4295 {
4296 #ifdef HAVE_API_ANDROID
4297 #ifdef NAVIT_SAY_DEBUG_PRINT
4298 android_send_generic_text(1,"+*#O:into the ramp\n");
4299 gchar* xy=g_strdup_printf("+*#1:%s\n", prefix);
4300 android_send_generic_text(1,xy);
4301 g_free(xy);
4302 #endif
4303 #endif
4304
4305 return g_strdup_printf("%s%s", prefix, _("into the ramp"));
4306 }
4307 }
4308
4309 }
4310
4311 if (!n1 && !n2 && !itm->way.street_dest_text)
4312 {
4313 return NULL;
4314 }
4315
4316 if (itm->way.street_dest_text)
4317 {
4318 #ifdef HAVE_API_ANDROID
4319 #ifdef NAVIT_SAY_DEBUG_PRINT
4320 gchar* xy=g_strdup_printf("+*#0:%s\n", itm->way.street_dest_text);
4321 android_send_generic_text(1,xy);
4322 g_free(xy);
4323 gchar* xy=g_strdup_printf("+*#1:%s\n", prefix);
4324 android_send_generic_text(1,xy);
4325 g_free(xy);
4326 #endif
4327 #endif
4328 // say the name on the exit sign/destinaion sign
4329 return g_strdup_printf("%s%s", prefix, itm->way.street_dest_text);
4330 }
4331 else if (n1)
4332 {
4333 sex = -1;
4334 name1 = NULL;
4335 for (i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); i++)
4336 {
4337 if (contains_suffix(n1, suffixes[i].fullname))
4338 {
4339 sex = suffixes[i].sex;
4340 name1 = g_strdup(n1);
4341 break;
4342 }
4343 if (contains_suffix(n1, suffixes[i].abbrev))
4344 {
4345 sex = suffixes[i].sex;
4346
4347 // TODO: replacing strings here maybe not so good?!?
4348 name1 = replace_suffix(n1, suffixes[i].abbrev, suffixes[i].fullname);
4349 break;
4350 }
4351 }
4352
4353 if (n2)
4354 {
4355 name2 = n2;
4356 sep = " ";
4357 }
4358 else
4359 {
4360 name2 = "";
4361 sep = "";
4362 }
4363
4364 gchar* xy;
4365 switch (sex)
4366 {
4367 case -1:
4368 #ifdef HAVE_API_ANDROID
4369 #ifdef NAVIT_SAY_DEBUG_PRINT
4370 android_send_generic_text(1,"+*#O:%sinto the street %s%s%s\n");
4371 xy=g_strdup_printf("+*#1:%s\n", prefix);
4372 android_send_generic_text(1,xy);
4373 g_free(xy);
4374 xy=g_strdup_printf("+*#1:%s\n", n1);
4375 android_send_generic_text(1,xy);
4376 g_free(xy);
4377 xy=g_strdup_printf("+*#1:%s\n", sep);
4378 android_send_generic_text(1,xy);
4379 g_free(xy);
4380 xy=g_strdup_printf("+*#1:%s\n", name2);
4381 android_send_generic_text(1,xy);
4382 g_free(xy);
4383 #endif
4384 #endif
4385 // TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name
4386 ret = g_strdup_printf(_("%sinto the street %s%s%s"), prefix, n1, sep, name2);
4387 break;
4388 case 1:
4389 #ifdef HAVE_API_ANDROID
4390 #ifdef NAVIT_SAY_DEBUG_PRINT
4391 android_send_generic_text(1,"+*#O:%sinto the %s%s%s|male form\n");
4392 xy=g_strdup_printf("+*#1:%s\n", prefix);
4393 android_send_generic_text(1,xy);
4394 g_free(xy);
4395 xy=g_strdup_printf("+*#1:%s\n", name1);
4396 android_send_generic_text(1,xy);
4397 g_free(xy);
4398 xy=g_strdup_printf("+*#1:%s\n", sep);
4399 android_send_generic_text(1,xy);
4400 g_free(xy);
4401 xy=g_strdup_printf("+*#1:%s\n", name2);
4402 android_send_generic_text(1,xy);
4403 g_free(xy);
4404 #endif
4405 #endif
4406 // 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
4407 ret = g_strdup_printf(_("%sinto the %s%s%s|male form"), prefix, name1, sep, name2);
4408 break;
4409 case 2:
4410 #ifdef HAVE_API_ANDROID
4411 #ifdef NAVIT_SAY_DEBUG_PRINT
4412 android_send_generic_text(1,"+*#O:%sinto the %s%s%s|female form\n");
4413 xy=g_strdup_printf("+*#1:%s\n", prefix);
4414 android_send_generic_text(1,xy);
4415 g_free(xy);
4416 xy=g_strdup_printf("+*#1:%s\n", name1);
4417 android_send_generic_text(1,xy);
4418 g_free(xy);
4419 xy=g_strdup_printf("+*#1:%s\n", sep);
4420 android_send_generic_text(1,xy);
4421 g_free(xy);
4422 xy=g_strdup_printf("+*#1:%s\n", name2);
4423 android_send_generic_text(1,xy);
4424 g_free(xy);
4425 #endif
4426 #endif
4427 // 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
4428 ret = g_strdup_printf(_("%sinto the %s%s%s|female form"), prefix, name1, sep, name2);
4429 break;
4430 case 3:
4431 #ifdef HAVE_API_ANDROID
4432 #ifdef NAVIT_SAY_DEBUG_PRINT
4433 android_send_generic_text(1,"+*#O:%sinto the %s%s%s|neutral form\n");
4434 xy=g_strdup_printf("+*#1:%s\n", prefix);
4435 android_send_generic_text(1,xy);
4436 g_free(xy);
4437 xy=g_strdup_printf("+*#1:%s\n", name1);
4438 android_send_generic_text(1,xy);
4439 g_free(xy);
4440 xy=g_strdup_printf("+*#1:%s\n", sep);
4441 android_send_generic_text(1,xy);
4442 g_free(xy);
4443 xy=g_strdup_printf("+*#1:%s\n", name2);
4444 android_send_generic_text(1,xy);
4445 g_free(xy);
4446 #endif
4447 #endif
4448 // 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
4449 ret = g_strdup_printf(_("%sinto the %s%s%s|neutral form"), prefix, name1, sep, name2);
4450 break;
4451 }
4452 g_free(name1);
4453
4454 }
4455 else
4456 {
4457 #ifdef HAVE_API_ANDROID
4458 #ifdef NAVIT_SAY_DEBUG_PRINT
4459 android_send_generic_text(1,"+*#O:sinto the %s\n");
4460 gchar* xy=g_strdup_printf("+*#1:%s\n", prefix);
4461 android_send_generic_text(1,xy);
4462 g_free(xy);
4463 xy=g_strdup_printf("+*#1:%s\n", n2);
4464 android_send_generic_text(1,xy);
4465 g_free(xy);
4466 #endif
4467 #endif
4468 // TRANSLATORS: gives the name of the next road to turn into (into the E17)
4469 ret = g_strdup_printf(_("%sinto the %s"), prefix, n2);
4470 }
4471
4472 name1 = ret;
4473
4474 while (name1 && *name1)
4475 {
4476 switch (*name1)
4477 {
4478 case '|':
4479 *name1 = '\0';
4480 break;
4481 case '/':
4482 *name1++ = ' ';
4483 break;
4484 default:
4485 name1++;
4486 }
4487 }
4488
4489 return ret;
4490 }
4491
4492
4493
4494
4495 #define DONT_KNOW_LEVEL -997
4496
4497
4498 static char *
4499 show_maneuver_bicycle(struct navigation *nav, struct navigation_itm *itm, struct navigation_command *cmd, enum attr_type type, int connect, int want_this_level)
4500 {
4501 __F_START__
4502
4503 // TRANSLATORS: right, as in 'Turn right'
4504 char *dir = _("right");
4505 char *strength = "";
4506 int distance = itm->dest_length - cmd->itm->dest_length;
4507 char *d, *ret = NULL;
4508 int delta = cmd->delta;
4509 int delta_real = cmd->delta_real;
4510 int level;
4511 int level_now = 99;
4512 int level3;
4513 int strength_needed;
4514 int skip_roads;
4515 int count_roundabout;
4516 struct navigation_itm *cur;
4517 struct navigation_way *w;
4518 int against_oneway = 0;
4519 int keep_dir = 0;
4520 int old_dir = 0;
4521
4522 if (want_this_level == DONT_KNOW_LEVEL)
4523 {
4524 level3 = 1;
4525 }
4526 else
4527 {
4528 level3 = want_this_level;
4529 }
4530
4531
4532 int cur_vehicle_speed = 0;
4533 if ((global_navit) && (global_navit->vehicle))
4534 {
4535 cur_vehicle_speed = global_navit->vehicle->speed; // in km/h
4536 }
4537
4538 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
4539 {
4540 //dbg(0, "itm->way.flags=%x\n", itm->way.flags);
4541 //dbg(0, "itm->next->way.flags=%x\n", itm->next->way.flags);
4542 //dbg(0, "itm->way.dir=%d itm->next->way.dir=%d\n", itm->way.dir, itm->next->way.dir);
4543
4544 //dbg(0, "2 itm->way.flags=%x\n", cmd->itm->way.flags);
4545 //dbg(0, "2 itm->next->way.flags=%x\n", cmd->itm->next->way.flags);
4546 //dbg(0, "2 itm->way.dir=%d itm->next->way.dir=%d\n", cmd->itm->way.dir, cmd->itm->next->way.dir);
4547
4548 int flags_old = navigation_item_get_flags(&itm->way);
4549 int flags_new = 0;
4550 if (itm->next)
4551 {
4552 flags_new = navigation_item_get_flags(&itm->next->way);
4553 }
4554 //dbg(0, "(2211)old flags=%x new flags=%x\n", flags_old, flags_new);
4555
4556 // long long wayid_old = navigation_item_get_wayid(&(itm->way));
4557 // long long wayid_new = navigation_item_get_wayid(&(itm->next->way));
4558 // dbg(0, "WID old_way_id=%lld new_way_id=%lld\n", wayid_old, wayid_new);
4559
4560
4561 if ( (itm->way.dir == 1) && ((itm->next->way.dir == -1) && (itm->next->way.flags & NAVIT_AF_ONEWAY_BICYCLE_NO)) )
4562 {
4563 against_oneway = 1;
4564 //dbg(0, "SPEAK: (1)going against oneway street!\n");
4565 }
4566 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)) )
4567 {
4568 against_oneway = 1;
4569 //dbg(0, "SPEAK: (2)going against oneway street!\n");
4570 }
4571 }
4572
4573 //dbg(0, "d=%d d3=%d\n", distance, (distance - cmd->length));
4574 level_now = navigation_get_announce_level(nav, itm->way.item.type, distance - cmd->length, 0);
4575 //dbg(0, "level_now=%d\n", level_now);
4576
4577 w = itm->next->way.next;
4578 strength_needed = 0;
4579
4580 if (angle_delta(itm->next->way.angle2, itm->angle_end) < 0) // left
4581 {
4582 while (w)
4583 {
4584 if (angle_delta(w->angle2, itm->angle_end) < 0) // other ways are going left
4585 {
4586 strength_needed = 1;
4587 break;
4588 }
4589 w = w->next;
4590 }
4591 }
4592 else // right
4593 {
4594 while (w)
4595 {
4596 if (angle_delta(w->angle2, itm->angle_end) > 0) // other ways are going right
4597 {
4598 strength_needed = 1;
4599 break;
4600 }
4601 w = w->next;
4602 }
4603 }
4604
4605
4606 if ((strength_needed == 0) && (delta < 9)) // for corrected turn (delta will be 8), use strength ("slight")
4607 {
4608 strength_needed = 1;
4609 }
4610
4611 //dbg(0, "cmd->delta=%d\n", delta);
4612
4613 if (delta < 0)
4614 {
4615 // TRANSLATORS: left, as in 'Turn left'
4616 dir = _("left");
4617 delta = -delta;
4618
4619 old_dir = -1; // left
4620 }
4621 else if (delta > 0)
4622 {
4623
4624 old_dir = 1; // right
4625
4626 // dir = right
4627 }
4628 else // delta == 0 // go straight
4629 {
4630 dir = _("straight");
4631 strength_needed = 0;
4632 }
4633
4634
4635 keep_dir = 0;
4636
4637 if (strength_needed)
4638 {
4639 if (delta < 45)
4640 {
4641 // TRANSLATORS: Don't forget the ending space
4642 // TRANSLATORS: EXAMPLE: turn slight right
4643 strength = _("slighty ");
4644 // TRANSLATORS: Don't forget the ending space
4645 // TRANSLATORS: EXAMPLE: turn slight right
4646 strength = _("slight ");
4647
4648 if (delta_real == 0) // keep left/right
4649 {
4650 if (old_dir == -1)
4651 {
4652 keep_dir = -1;
4653 }
4654 else
4655 {
4656 keep_dir = 1;
4657 }
4658 }
4659 }
4660 else if (delta < 105)
4661 {
4662 strength = "";
4663 }
4664 else if (delta < 165)
4665 {
4666 // TRANSLATORS: Don't forget the ending space
4667 // TRANSLATORS: EXAMPLE: turn hard right
4668 strength = _("hard ");
4669 }
4670 else if (delta < 180)
4671 {
4672 // TRANSLATORS: Don't forget the ending space
4673 // TRANSLATORS: EXAMPLE: turn really hard right
4674 strength = _("really hard ");
4675 }
4676 else
4677 {
4678 // TRANSLATORS: Don't forget the ending space
4679 strength = "";
4680 }
4681 }
4682
4683
4684 if (type != attr_navigation_long_exact)
4685 {
4686 //dbg(0, "round distance d=%d dr=%d\n", distance, round_distance(distance));
4687 distance = round_distance(distance);
4688 }
4689
4690
4691
4692
4693 if (type == attr_navigation_speech)
4694 {
4695 dbg(0, "NAV_TURNAROUND:003 ta=%d talimit=%d\n", nav->turn_around, nav->turn_around_limit);
4696
4697 if (nav->turn_around && nav->turn_around == nav->turn_around_limit)
4698 {
4699 dbg(0, "NAV_TURNAROUND:004\n");
4700
4701 return2 g_strdup(_("When possible, please turn around"));
4702 }
4703
4704 if (!connect)
4705 {
4706 if (want_this_level == DONT_KNOW_LEVEL)
4707 {
4708 level3 = navigation_get_announce_level_cmd(nav, itm, cmd, distance - cmd->length, ((float)cur_vehicle_speed / 3.6f) );
4709 }
4710 else
4711 {
4712 level3 = want_this_level;
4713 }
4714 }
4715
4716 if (want_this_level == DONT_KNOW_LEVEL)
4717 {
4718 level_now = navigation_get_announce_level(nav, itm->way.item.type, distance - cmd->length, ((float)cur_vehicle_speed / 3.6f) );
4719 }
4720 else
4721 {
4722 level_now = want_this_level;
4723 }
4724 }
4725
4726
4727
4728 switch (level3)
4729 {
4730 case 3:
4731 if (distance > 500)
4732 {
4733 d = get_distance(nav, distance, type, 1);
4734 ret = g_strdup_printf(_("Follow the road for the next %s"), d);
4735 g_free(d);
4736 }
4737 else
4738 {
4739 ret = g_strdup("");
4740 }
4741 return2 ret;
4742 // break;
4743 case 2:
4744 d = g_strdup(_("soon"));
4745 break;
4746 case 1:
4747 d = get_distance(nav, distance, attr_navigation_short, 0);
4748 break;
4749 case 0:
4750 // d = g_strdup(_("now"));
4751 d = g_strdup("");
4752 break;
4753 }
4754
4755
4756 // are there more commands left?
4757 if (cmd->itm->next)
4758 {
4759 int tellstreetname = 0;
4760 char *destination = NULL;
4761
4762 if (type == attr_navigation_speech)
4763 {
4764 if (level3 == 1)
4765 {
4766 tellstreetname = 1; // Ok so we tell the name of the street
4767 }
4768 else // if (level3 == 0)
4769 {
4770 tellstreetname = 0;
4771 }
4772 }
4773 else
4774 {
4775 tellstreetname = 1;
4776 }
4777
4778 if (global_speak_streetnames == 0)
4779 {
4780 // never speak streetnames (user config option)
4781 tellstreetname = 0;
4782 }
4783
4784 if (nav->tell_street_name && tellstreetname)
4785 {
4786 destination = navigation_item_destination(nav, cmd->itm, itm, " ");
4787 }
4788
4789
4790 if (connect == 0)
4791 {
4792 //dbg(0, "level3=%5$d str=%1$s%2$s %3$s%4$s\n", strength, dir, d, destination ? destination : "", level3);
4793
4794 if (level3 == 0)
4795 {
4796 if (against_oneway == 1)
4797 {
4798 #if 1
4799 if (delta < 10)
4800 {
4801 ret = g_strdup_printf("%s", _("oncoming traffic!")); // just say "attention oneway street!"
4802 }
4803 else
4804 {
4805 ret = g_strdup_printf("%s, %s", dir, _("oncoming traffic!")); // just say "left" or "right" at the turn + "attention oneway street!"
4806 }
4807 #endif
4808
4809 }
4810 else
4811 {
4812 #if 1
4813 if (delta >= 10)
4814 {
4815 ret = g_strdup(dir); // just say "left" or "right" at the turn
4816 }
4817 else
4818 {
4819 ret = g_strdup("");
4820 }
4821 #endif
4822
4823 #if 0
4824 if (delta == 0)
4825 {
4826 ret = g_strdup(dir); // just say "left" or "right" or "straight" at the turn
4827 }
4828 else
4829 {
4830 if (keep_dir != 0)
4831 {
4832 if (keep_dir == -1)
4833 {
4834 // TRANSLATORS: The argument is the distance. Example: 'keep left in 100 meters'
4835 ret = g_strdup_printf(_("keep left %s"), "");
4836 }
4837 else
4838 {
4839 // TRANSLATORS: The argument is the distance. Example: 'keep right in 100 meters'
4840 ret = g_strdup_printf(_("keep right %s"), "");
4841 }
4842 }
4843 else
4844 {
4845 if (delta >= 10)
4846 {
4847 ret = g_strdup(dir); // just say "left" or "right" at the turn
4848 }
4849 else
4850 {
4851 ret = g_strdup("");
4852 }
4853 }
4854 }
4855 #endif
4856
4857 }
4858 }
4859 else // if (level3 == 1)
4860 {
4861 if ((against_oneway == 1) && (delta < 10))
4862 {
4863 ret = g_strdup(""); // probably just going against a oneway street, but travelling straight on. dont say anything now
4864 }
4865 else
4866 {
4867 if (delta >= 10)
4868 {
4869 // 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'
4870 ret = g_strdup_printf_4_str(_("Turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination : "");
4871 }
4872 else
4873 {
4874 ret = g_strdup("");
4875 }
4876 }
4877 }
4878
4879 }
4880 else // (connect == 1)
4881 {
4882 if (level3 == 0)
4883 {
4884 if (against_oneway == 1)
4885 {
4886 if (delta < 10)
4887 {
4888 ret = g_strdup_printf("%s %s", _("then"), _("oncoming traffic!"));
4889 }
4890 else
4891 {
4892 ret = g_strdup_printf("%s %s %s", _("then"), dir, _("oncoming traffic!"));
4893 }
4894 }
4895 else
4896 {
4897 if (delta >= 10)
4898 {
4899 ret = g_strdup_printf("%s %s", _("then"), dir);
4900 }
4901 else
4902 {
4903 ret = g_strdup("");
4904 }
4905 }
4906 }
4907 else // if (level3 == 1)
4908 {
4909 if (against_oneway == 1)
4910 {
4911 if (delta < 10)
4912 {
4913 // nothing
4914 ret = g_strdup("");
4915 }
4916 else
4917 {
4918 // TRANSLATORS: First argument is strength, second direction, third how many roads to skip, fourth destination
4919 ret = g_strdup_printf_4_str(_("then turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination : "");
4920 }
4921 }
4922 else
4923 {
4924 if (delta >= 10)
4925 {
4926 // TRANSLATORS: First argument is strength, second direction, third how many roads to skip, fourth destination
4927 ret = g_strdup_printf_4_str(_("then turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination : "");
4928 }
4929 else
4930 {
4931 ret = g_strdup("");
4932 }
4933 }
4934 }
4935 }
4936
4937
4938 if (destination)
4939 {
4940 g_free(destination);
4941 destination = NULL;
4942 }
4943 }
4944 // no more commands left, must be at destination
4945 else
4946 {
4947 if (!connect)
4948 {
4949 d = get_distance(nav, distance, type, 1);
4950
4951 // TRANSLATORS: EXAMPLE: You have reached your destination in 300 meters
4952 ret = g_strdup_printf(_("You have reached your destination %s"), d);
4953
4954 g_free(d);
4955 }
4956 else
4957 {
4958 ret = g_strdup(_("then you have reached your destination."));
4959 }
4960 }
4961
4962 return2 ret;
4963
4964 __F_END__
4965 }
4966
4967 int navigation_is_low_level_street(enum item_type t)
4968 {
4969 if (global_vehicle_profile == 0) // only in car profile!
4970 {
4971 if (t == type_street_service)
4972 {
4973 return 1;
4974 }
4975 else if (t == type_street_parking_lane)
4976 {
4977 return 1;
4978 }
4979 else if (t == type_track_ground)
4980 {
4981 return 1;
4982 }
4983 else if (t == type_track_grass)
4984 {
4985 return 1;
4986 }
4987 else if (t == type_track_gravelled)
4988 {
4989 return 1;
4990 }
4991 else if (t == type_track_unpaved)
4992 {
4993 return 1;
4994 }
4995 else if (t == type_track_paved)
4996 {
4997 return 1;
4998 }
4999 }
5000
5001 return 0;
5002 }
5003
5004
5005
5006 static char *
5007 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)
5008 {
5009 __F_START__
5010
5011 // TRANSLATORS: right, as in 'Turn right'
5012 char *dir = _("right");
5013 char *strength = "";
5014 int distance = itm->dest_length - cmd->itm->dest_length;
5015 char *d, *ret = NULL;
5016 int delta = cmd->delta;
5017 int delta_real = cmd->delta_real;
5018 int level;
5019 int level_now = 99;
5020 int strength_needed;
5021 int skip_roads;
5022 int count_roundabout; // car mode ----
5023 struct navigation_itm *cur;
5024 struct navigation_way *w;
5025 int against_oneway = 0;
5026 int keep_dir = 0; // car mode ----
5027 int old_dir = 0;
5028
5029 if (connect)
5030 {
5031 level = -2; // level = -2 means "connect to another maneuver via 'then ...'"
5032 }
5033 else
5034 {
5035 if (want_this_level == DONT_KNOW_LEVEL)
5036 {
5037 level = 1;
5038 }
5039 else
5040 {
5041 level = want_this_level;
5042 }
5043 }
5044
5045 int cur_vehicle_speed = 0;
5046 if ((global_navit) && (global_navit->vehicle))
5047 {
5048 cur_vehicle_speed = global_navit->vehicle->speed; // in km/h
5049 }
5050
5051
5052 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
5053 {
5054 //dbg(0, "itm->way.flags=%x\n", itm->way.flags);
5055 //dbg(0, "itm->next->way.flags=%x\n", itm->next->way.flags);
5056
5057 // int flags_old = navigation_item_get_flags(&itm->way);
5058 // int flags_new = navigation_item_get_flags(&itm->next->way);
5059 // dbg(0, "old flags=%x new flags=%x\n", flags_old, flags_new);
5060
5061 if ( (itm->way.dir == 1) && ((itm->next->way.dir == -1) && (itm->next->way.flags & NAVIT_AF_ONEWAY_BICYCLE_NO)) )
5062 {
5063 against_oneway = 1;
5064 //dbg(0, "SPEAK: (1)going against oneway street!\n");
5065 }
5066 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)) )
5067 {
5068 against_oneway = 1;
5069 //dbg(0, "SPEAK: (2)going against oneway street!\n");
5070 }
5071 }
5072
5073 w = itm->next->way.next;
5074 strength_needed = 0;
5075
5076 //dbg(0, "STRENGTH:001:strength_needed = %d delta = %d\n", strength_needed, delta);
5077
5078 if (angle_delta(itm->next->way.angle2, itm->angle_end) < 0) // left
5079 {
5080 while (w)
5081 {
5082 if (angle_delta(w->angle2, itm->angle_end) < 0) // other ways are going left
5083 {
5084 strength_needed = 1;
5085 // dbg(0, "STRENGTH:002:strength_needed = %d\n", strength_needed);
5086 break;
5087 }
5088 w = w->next;
5089 }
5090 }
5091 else // right
5092 {
5093 while (w)
5094 {
5095 if (angle_delta(w->angle2, itm->angle_end) > 0) // other ways are going right
5096 {
5097 strength_needed = 1;
5098 // dbg(0, "STRENGTH:003:strength_needed = %d\n", strength_needed);
5099 break;
5100 }
5101 w = w->next;
5102 }
5103 }
5104
5105 if ((strength_needed == 0) && (delta < 9)) // for corrected turn (delta will be 8), use strength ("slight")
5106 {
5107 strength_needed = 1;
5108 }
5109
5110 // dbg(0, "STRAI:K001:strength_needed=%d delta=%d delta_real=%d\n", strength_needed, delta, delta_real);
5111
5112 //dbg(0, "cmd->delta=%d\n", delta);
5113
5114 if (delta < 0)
5115 {
5116 #ifdef HAVE_API_ANDROID
5117 #ifdef NAVIT_SAY_DEBUG_PRINT
5118 android_send_generic_text(1,"+*#O:left\n");
5119 #endif
5120 #endif
5121 // TRANSLATORS: left, as in 'Turn left'
5122 dir = _("left");
5123 delta = -delta;
5124
5125 old_dir = -1; // left
5126
5127 }
5128 else if (delta > 0)
5129 {
5130
5131 old_dir = 1; // right
5132
5133 // dir = right
5134 #ifdef HAVE_API_ANDROID
5135 #ifdef NAVIT_SAY_DEBUG_PRINT
5136 android_send_generic_text(1,"+*#O:right\n");
5137 #endif
5138 #endif
5139 }
5140 else // delta == 0 // go straight
5141 {
5142 dir = _("straight");
5143 strength_needed = 0;
5144 // dbg(0, "STRENGTH:004:strength_needed = %d\n", strength_needed);
5145 }
5146
5147 dbg(0, "STRAI:K002:*:strength_needed=%d delta=%d delta_real=%d\n", strength_needed, delta, delta_real);
5148
5149
5150 keep_dir = 0;
5151
5152 if (strength_needed)
5153 {
5154 // dbg(0, "STRENGTH:005:\n");
5155
5156
5157 if (delta < 45)
5158 {
5159 #ifdef HAVE_API_ANDROID
5160 #ifdef NAVIT_SAY_DEBUG_PRINT
5161 android_send_generic_text(1,"+*#O:slight \n");
5162 #endif
5163 #endif
5164 // TRANSLATORS: Don't forget the ending space
5165 // TRANSLATORS: EXAMPLE: turn slight right
5166 strength = _("slighty ");
5167 // TRANSLATORS: Don't forget the ending space
5168 // TRANSLATORS: EXAMPLE: turn slight right
5169 strength = _("slight ");
5170
5171 if (delta_real == 0) // keep left/right
5172 {
5173 if (old_dir == -1)
5174 {
5175 keep_dir = -1;
5176 }
5177 else
5178 {
5179 keep_dir = 1;
5180 }
5181 }
5182
5183 dbg(0, "STRENGTH:006:strength_needed = %s\n", strength);
5184
5185 }
5186 else if (delta < 105)
5187 {
5188 strength = "";
5189 }
5190 else if (delta < 165)
5191 {
5192 #ifdef HAVE_API_ANDROID
5193 #ifdef NAVIT_SAY_DEBUG_PRINT
5194 android_send_generic_text(1,"+*#O:hard \n");
5195 #endif
5196 #endif
5197 // TRANSLATORS: Don't forget the ending space
5198 // TRANSLATORS: EXAMPLE: turn hard right
5199 strength = _("hard ");
5200 }
5201 else if (delta < 180)
5202 {
5203 #ifdef HAVE_API_ANDROID
5204 #ifdef NAVIT_SAY_DEBUG_PRINT
5205 android_send_generic_text(1,"+*#O:really hard \n");
5206 #endif
5207 #endif
5208 // TRANSLATORS: Don't forget the ending space
5209 // TRANSLATORS: EXAMPLE: turn really hard right
5210 strength = _("really hard ");
5211 }
5212 else
5213 {
5214 // dbg(1,"delta=%d\n", delta);
5215 strength = "";
5216 }
5217 }
5218
5219 // dbg(0, "STRENGTH:010:strength_needed = %s\n", strength);
5220
5221
5222 if (type != attr_navigation_long_exact)
5223 {
5224 distance = round_distance(distance);
5225 }
5226
5227 if (type == attr_navigation_speech)
5228 {
5229 dbg(0, "NAV_TURNAROUND:001 ta=%d talimit=%d\n", nav->turn_around, nav->turn_around_limit);
5230
5231 if (nav->turn_around && nav->turn_around == nav->turn_around_limit)
5232 {
5233
5234 dbg(0, "NAV_TURNAROUND:002:*******\n");
5235
5236 #ifdef HAVE_API_ANDROID
5237 #ifdef NAVIT_SAY_DEBUG_PRINT
5238 android_send_generic_text(1,"+*#O:When possible, please turn around\n");
5239 #endif
5240 #endif
5241 return2 g_strdup(_("When possible, please turn around"));
5242 }
5243
5244 if (!connect)
5245 {
5246 if (want_this_level == DONT_KNOW_LEVEL)
5247 {
5248 level = navigation_get_announce_level_cmd(nav, itm, cmd, distance - cmd->length, ((float)cur_vehicle_speed / 3.6f) );
5249 }
5250 else
5251 {
5252 level = want_this_level;
5253 }
5254 }
5255
5256 if (want_this_level == DONT_KNOW_LEVEL)
5257 {
5258 level_now = navigation_get_announce_level(nav, itm->way.item.type, distance - cmd->length, ((float)cur_vehicle_speed / 3.6f) );
5259 }
5260 else
5261 {
5262 level_now = want_this_level;
5263 }
5264
5265 }
5266
5267 #ifdef NAVIT_DEBUG_COORD_LIST
5268 int need_clear = 1;
5269 #endif
5270
5271
5272
5273 #if 1
5274 // ------------------- jandegr -------------------
5275
5276 struct navigation_way *candidate_way;
5277
5278 if (cmd->itm->prev->way.flags & NAVIT_AF_ROUNDABOUT)
5279 {
5280 cur = cmd->itm->prev;
5281 count_roundabout = 0;
5282
5283 // ----- fix -----
5284 struct navigation_itm *cur_orig = cur->next;
5285
5286 enum item_type cur_street_type = 0;
5287 int exit_is_lover_street_type = 0;
5288 cur_street_type = cur_orig->way.item.type;
5289 // dbg(0, "curr item type=%s\n", item_to_name(cur_orig->way.item.type));
5290 exit_is_lover_street_type = navigation_is_low_level_street(cur_street_type);
5291
5292 int next_exit_is_lower_street_type = 0;
5293 // ----- fix -----
5294
5295
5296 dbg(0, "ROUNDABT:001:enter\n");
5297
5298 while (cur && (cur->way.flags & NAVIT_AF_ROUNDABOUT))
5299 {
5300
5301 // dbg(0, "ROUNDABT:002:loop-1:w\n");
5302
5303 candidate_way=cur->next->way.next;
5304 while (candidate_way)
5305 {
5306
5307 dbg(0, "ROUNDABT:002:loop-2:w2 type=%s\n", item_to_name(candidate_way->item.type));
5308
5309 // If the next segment has no exit or the exit isn't allowed, don't count it
5310 if (candidate_way && is_way_allowed(nav, candidate_way, 3))
5311 {
5312
5313 dbg(0, "ROUNDABT:003:is_allowed type=%s\n", item_to_name(candidate_way->item.type));
5314
5315 // only count street_service (and lesser streets) if we also exit on street_service (or any lesser street)
5316 if (cur->next)
5317 {
5318 next_exit_is_lower_street_type = navigation_is_low_level_street(candidate_way->item.type);
5319
5320 dbg(0, "ROUNDABT:004:next_exit_is_lower_street_type=%d type=%s\n", next_exit_is_lower_street_type, item_to_name(candidate_way->item.type));
5321 }
5322
5323 if ((exit_is_lover_street_type == 1) || (next_exit_is_lower_street_type == 0))
5324 {
5325 count_roundabout++;
5326
5327 dbg(0, "ROUNDABT:005:found:count_roundabout=%d\n", count_roundabout);
5328
5329 /* As soon as we have an allowed one on this node,
5330 * stop further counting for this node.
5331 */
5332 candidate_way = candidate_way->next;
5333 break;
5334 }
5335 }
5336 candidate_way=candidate_way->next;
5337 }
5338 cur = cur->prev;
5339 }
5340
5341 /*try to figure out if the entry node has a usable exit as well
5342 *
5343 * this will fail for left-hand driving areas
5344 */
5345 if (cur && cur->next)
5346 {
5347 dbg(0, "ROUNDABT:007:entry-check\n");
5348
5349 candidate_way = cur->next->way.next;
5350 while (candidate_way)
5351 {
5352 dbg(0, "ROUNDABT:008:loop-3:w3 type=%s\n", item_to_name(candidate_way->item.type));
5353
5354 if (candidate_way && is_way_allowed(nav,candidate_way,3)
5355 && (cur->angle_end < candidate_way->angle2) && ( candidate_way->angle2 > cur->next->way.angle2 ))
5356 /*for the entry node only count exits to the right ?*/
5357 {
5358 count_roundabout++;
5359
5360 dbg(0, "ROUNDABT:009:entry:found:count_roundabout=%d\n", count_roundabout);
5361 /* As soon as we have an allowed one on this node,
5362 * stop further counting for this node.
5363 */
5364 break;
5365 }
5366 candidate_way = candidate_way->next;
5367 }
5368 }
5369
5370 switch (level)
5371 {
5372 #if 0
5373 case 3:
5374 d=get_distance(nav, distance, type, 1);
5375 return g_strdup_printf(_("Follow the road for the next %s"), d);
5376 #endif
5377 case 2:
5378 return2 g_strdup(_("Enter the roundabout soon"));
5379 case 1:
5380 // TRANSLATORS: EXAMPLE: Leave the roundabout at the second exit
5381 return2 g_strdup_printf(_("Leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
5382 case -2:
5383 // TRANSLATORS: EXAMPLE: ... then leave the roundabout at the second exit
5384 return2 g_strdup_printf(_("then leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
5385 case 0:
5386 // TRANSLATORS: EXAMPLE: Leave the roundabout at the second exit
5387 return2 g_strdup_printf(_("Leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
5388 }
5389 }
5390
5391
5392 // ------------------- jandegr -------------------
5393 #endif
5394
5395
5396
5397
5398
5399
5400
5401 #if 0
5402 // ------------------- zoff -------------------
5403
5404 if (cmd->itm->prev->way.flags & NAVIT_AF_ROUNDABOUT)
5405 {
5406 cur = cmd->itm->prev;
5407 count_roundabout = 0;
5408
5409 struct navigation_itm *cur_orig = cur->next;
5410
5411 enum item_type cur_street_type = 0;
5412 int exit_is_lover_street_type = 0;
5413 cur_street_type = cur_orig->way.item.type;
5414 // dbg(0, "curr item type=%s\n", item_to_name(cur_orig->way.item.type));
5415 exit_is_lover_street_type = navigation_is_low_level_street(cur_street_type);
5416
5417 int next_exit_is_lower_street_type = 0;
5418
5419 while (cur && (cur->way.flags & NAVIT_AF_ROUNDABOUT))
5420 {
5421 // If the next segment has no exit or the exit isn't allowed, don't count it
5422 if (cur->next->way.next && is_way_allowed(nav, cur->next->way.next, 3))
5423 {
5424
5425 // only count street_service (and lesser streets) if we also exit on street_service (or any lesser street)
5426 if (cur->next)
5427 {
5428 next_exit_is_lower_street_type = navigation_is_low_level_street(cur->next->way.next->item.type);
5429 }
5430
5431 if ((exit_is_lover_street_type == 1) || (next_exit_is_lower_street_type == 0))
5432 {
5433 count_roundabout++;
5434
5435 #ifdef NAVIT_DEBUG_COORD_LIST
5436 if (need_clear == 1)
5437 {
5438 need_clear = 0;
5439 global_debug_coord_list_items = 0;
5440
5441 struct coord c2[5];
5442
5443 if (navigation_get_real_item_first_coord(&(cur_orig->way), c2))
5444 {
5445 global_debug_coord_list[global_debug_coord_list_items].x = c2[0].x;
5446 global_debug_coord_list[global_debug_coord_list_items].y = c2[0].y;
5447 global_debug_coord_list_items++;
5448 global_debug_coord_list[global_debug_coord_list_items].x = c2[1].x;
5449 global_debug_coord_list[global_debug_coord_list_items].y = c2[1].y;
5450 global_debug_coord_list_items++;
5451 }
5452
5453 }
5454
5455 struct coord c1[5];
5456 if (navigation_get_real_item_first_coord(cur->next->way.next, c1))
5457 {
5458 if ((global_debug_coord_list_items + 2) > MAX_DEBUG_COORDS)
5459 {
5460 global_debug_coord_list_items = 0;
5461 }
5462
5463 global_debug_coord_list[global_debug_coord_list_items].x = c1[0].x;
5464 global_debug_coord_list[global_debug_coord_list_items].y = c1[0].y;
5465 global_debug_coord_list_items++;
5466 global_debug_coord_list[global_debug_coord_list_items].x = c1[1].x;
5467 global_debug_coord_list[global_debug_coord_list_items].y = c1[1].y;
5468 global_debug_coord_list_items++;
5469 }
5470 #endif
5471
5472 }
5473 }
5474 cur = cur->prev;
5475 }
5476
5477 gchar* xy;
5478
5479 switch (level)
5480 {
5481 case 2:
5482 #ifdef HAVE_API_ANDROID
5483 #ifdef NAVIT_SAY_DEBUG_PRINT
5484 android_send_generic_text(1,"+*#O:Enter the roundabout soon\n");
5485 #endif
5486 #endif
5487 return2 g_strdup(_("Enter the roundabout soon"));
5488
5489
5490
5491
5492 case 1:
5493
5494
5495 #ifdef HAVE_API_ANDROID
5496 #ifdef NAVIT_SAY_DEBUG_PRINT
5497 android_send_generic_text(1,"+*#O:Leave the roundabout at the %s\n");
5498 xy=g_strdup_printf("+*#1:%s\n", get_exit_count_str(count_roundabout));
5499 android_send_generic_text(1,xy);
5500 g_free(xy);
5501 #endif
5502 #endif
5503 // TRANSLATORS: EXAMPLE: Leave the roundabout at the second exit
5504 return2 g_strdup_printf(_("Leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
5505
5506
5507 // ---- DISABLED ----
5508 #if 0
5509 d = get_distance(nav, distance, type, 1);
5510
5511 #ifdef HAVE_API_ANDROID
5512 #ifdef NAVIT_SAY_DEBUG_PRINT
5513 android_send_generic_text(1,"+*#O:In %s, enter the roundabout\n");
5514 xy=g_strdup_printf("+*#1:%s\n", d);
5515 android_send_generic_text(1,xy);
5516 g_free(xy);
5517 #endif
5518 #endif
5519 // TRANSLATORS: %s is the distance to the roundabout
5520 // TRANSLATORS: EXAMPLE: In 300m, enter the roundabout
5521 ret = g_strdup_printf(_("In %s, enter the roundabout"), d);
5522 g_free(d);
5523 return2 ret;
5524 #endif
5525 // ---- DISABLED ----
5526
5527
5528
5529 case -2:
5530 #ifdef HAVE_API_ANDROID
5531 #ifdef NAVIT_SAY_DEBUG_PRINT
5532 android_send_generic_text(1,"+*#O:then leave the roundabout at the %s\n");
5533 xy=g_strdup_printf("+*#1:%s\n", get_exit_count_str(count_roundabout));
5534 android_send_generic_text(1,xy);
5535 g_free(xy);
5536 #endif
5537 #endif
5538 // TRANSLATORS: EXAMPLE: ... then leave the roundabout at the second exit
5539 return2 g_strdup_printf(_("then leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
5540
5541
5542 case 0:
5543 #ifdef HAVE_API_ANDROID
5544 #ifdef NAVIT_SAY_DEBUG_PRINT
5545 android_send_generic_text(1,"+*#O:Leave the roundabout at the %s\n");
5546 xy=g_strdup_printf("+*#1:%s\n", get_exit_count_str(count_roundabout));
5547 android_send_generic_text(1,xy);
5548 g_free(xy);
5549 #endif
5550 #endif
5551 // TRANSLATORS: EXAMPLE: Leave the roundabout at the second exit
5552 return2 g_strdup_printf(_("Leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
5553 }
5554 }
5555
5556 // ------------------- zoff -------------------
5557 #endif
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567 // -- NEW 002 --
5568 if (cmd->itm)
5569 {
5570 // put correct destination into struct (to later show in GUI)
5571 navigation_select_announced_destinations(cmd);
5572 // string is in cmd->itm->way.street_dest_text
5573 }
5574 // -- NEW 002 --
5575
5576
5577
5578 switch (level)
5579 {
5580 case 3:
5581 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
5582 {
5583 if (distance > 500)
5584 {
5585 d = get_distance(nav, distance, type, 1);
5586
5587 #ifdef HAVE_API_ANDROID
5588 #ifdef NAVIT_SAY_DEBUG_PRINT
5589 android_send_generic_text(1,"+*#O:Follow the road for the next %s\n");
5590 gchar* xy=g_strdup_printf("+*#1:%s\n", d);
5591 android_send_generic_text(1,xy);
5592 g_free(xy);
5593 #endif
5594 #endif
5595
5596 ret = g_strdup_printf(_("Follow the road for the next %s"), d);
5597 g_free(d);
5598 }
5599 else
5600 {
5601 ret = g_strdup("");
5602 }
5603 }
5604 else
5605 {
5606 d = get_distance(nav, distance, type, 1);
5607
5608 #ifdef HAVE_API_ANDROID
5609 #ifdef NAVIT_SAY_DEBUG_PRINT
5610 android_send_generic_text(1,"+*#O:Follow the road for the next %s\n");
5611 gchar* xy=g_strdup_printf("+*#1:%s\n", d);
5612 android_send_generic_text(1,xy);
5613 g_free(xy);
5614 #endif
5615 #endif
5616 // TRANSLATORS: EXAMPLE: Follow the road for the next 300 meters
5617 ret = g_strdup_printf(_("Follow the road for the next %s"), d);
5618 g_free(d);
5619 }
5620 return2 ret;
5621 case 2:
5622 #ifdef HAVE_API_ANDROID
5623 #ifdef NAVIT_SAY_DEBUG_PRINT
5624 android_send_generic_text(1,"+*#O:soon\n");
5625 #endif
5626 #endif
5627
5628 // dbg(0, "SPK:*soon*\n");
5629
5630
5631 d = g_strdup(_("soon"));
5632 break;
5633 case 1:
5634 d = get_distance(nav, distance, attr_navigation_short, 0);
5635 break;
5636 case 0:
5637 skip_roads = count_possible_turns(nav, cmd->prev ? cmd->prev->itm : nav->first, cmd->itm, cmd->delta);
5638 if ((skip_roads > 0) && ((global_vehicle_profile != 1) && (global_vehicle_profile != 2)))
5639 {
5640 if (get_count_str(skip_roads + 1))
5641 {
5642 #ifdef HAVE_API_ANDROID
5643 #ifdef NAVIT_SAY_DEBUG_PRINT
5644 android_send_generic_text(1,"+*#O:Take the %1$s road to the %2$s\n");
5645 gchar* xy=g_strdup_printf("+*#1:%s\n", get_count_str(skip_roads + 1));
5646 android_send_generic_text(1,xy);
5647 g_free(xy);
5648 xy=g_strdup_printf("+*#1:%s\n", dir);
5649 android_send_generic_text(1,xy);
5650 g_free(xy);
5651 #endif
5652 #endif
5653 // TRANSLATORS: First argument is the how manieth street to take, second the direction
5654 ret = g_strdup_printf_2_str(_("Take the %1$s road to the %2$s"), get_count_str(skip_roads + 1), dir);
5655 return2 ret;
5656 }
5657 else
5658 {
5659 #ifdef HAVE_API_ANDROID
5660 #ifdef NAVIT_SAY_DEBUG_PRINT
5661 android_send_generic_text(1,"+*#O:after %i roads\n");
5662 gchar* xy=g_strdup_printf("+*#1:%i\n", skip_roads);
5663 android_send_generic_text(1,xy);
5664 g_free(xy);
5665 #endif
5666 #endif
5667 d = g_strdup_printf(_("after %i roads"), skip_roads);
5668 }
5669 }
5670 else
5671 {
5672 #ifdef HAVE_API_ANDROID
5673 #ifdef NAVIT_SAY_DEBUG_PRINT
5674 android_send_generic_text(1,"+*#O:now\n");
5675 #endif
5676 #endif
5677 d = g_strdup(_("now"));
5678 }
5679
5680 break;
5681
5682 case -2:
5683 skip_roads = count_possible_turns(nav, cmd->prev->itm, cmd->itm, cmd->delta);
5684 if ((skip_roads > 0) && ((global_vehicle_profile != 1) && (global_vehicle_profile != 2)))
5685 {
5686 // TRANSLATORS: First argument is the how manieth street to take, second the direction
5687 // TRANSLATORS: EXAMPLE: ... then take the second road to the right
5688 if (get_count_str(skip_roads + 1))
5689 {
5690 #ifdef HAVE_API_ANDROID
5691 #ifdef NAVIT_SAY_DEBUG_PRINT
5692 android_send_generic_text(1,"+*#O:then take the %1$s road to the %2$s\n");
5693 gchar* xy=g_strdup_printf("+*#1:%s\n", get_count_str(skip_roads + 1));
5694 android_send_generic_text(1,xy);
5695 g_free(xy);
5696 xy=g_strdup_printf("+*#1:%s\n", dir);
5697 android_send_generic_text(1,xy);
5698 g_free(xy);
5699 #endif
5700 #endif
5701 ret = g_strdup_printf_2_str(_("then take the %1$s road to the %2$s"), get_count_str(skip_roads + 1), dir);
5702 return2 ret;
5703 }
5704 else
5705 {
5706 #ifdef HAVE_API_ANDROID
5707 #ifdef NAVIT_SAY_DEBUG_PRINT
5708 android_send_generic_text(1,"+*#O:after %i roads\n");
5709 gchar* xy=g_strdup_printf("+*#1:%i\n", skip_roads);
5710 android_send_generic_text(1,xy);
5711 g_free(xy);
5712 #endif
5713 #endif
5714 d = g_strdup_printf(_("after %i roads"), skip_roads);
5715 }
5716
5717 }
5718 else
5719 {
5720 d = g_strdup("");
5721 }
5722 break;
5723 default:
5724 #ifdef HAVE_API_ANDROID
5725 #ifdef NAVIT_SAY_DEBUG_PRINT
5726 android_send_generic_text(1,"+*#O:error\n");
5727 #endif
5728 #endif
5729 d = g_strdup(_("error"));
5730 }
5731
5732
5733
5734 if (cmd->itm->next)
5735 {
5736 // dbg(0, "SPK:000a\n");
5737
5738 int tellstreetname = 0;
5739 char *destination = NULL;
5740
5741 if (type == attr_navigation_speech)
5742 {
5743 if (level == 1)
5744 {
5745 cmd->itm->streetname_told = 1;
5746 tellstreetname = 1; // Ok so we tell the name of the street
5747 }
5748
5749 if (level == 0)
5750 {
5751 if (cmd->itm->streetname_told == 0) // we are right at the intersection
5752 {
5753 tellstreetname = 1;
5754 }
5755 else
5756 {
5757 cmd->itm->streetname_told = 0; // reset just in case we come to the same street again
5758 }
5759 }
5760
5761 }
5762 else
5763 {
5764 tellstreetname = 1;
5765 }
5766
5767 if (global_speak_streetnames == 0)
5768 {
5769 // never speak streetnames (user config option)
5770 tellstreetname = 0;
5771 }
5772
5773
5774
5775 if (override_tellstreetname != -1)
5776 {
5777
5778 #ifdef NAVIT_ROUTING_DEBUG_PRINT
5779 dbg(0, "SPK:level=%d street_dest_text=%p tellstreetname=%d\n", level, cmd->itm->way.street_dest_text, tellstreetname);
5780 #endif
5781 if (nav->tell_street_name && tellstreetname)
5782 {
5783 destination = navigation_item_destination(nav, cmd->itm, itm, " ");
5784 #ifdef NAVIT_ROUTING_DEBUG_PRINT
5785 dbg(0, "SPK:levelX=%d dest=%s\n", level, destination);
5786 #endif
5787 }
5788 else if ((global_speak_streetnames == 1) && (cmd->itm->way.street_dest_text))
5789 {
5790 destination = navigation_item_destination(nav, cmd->itm, itm, " ");
5791 #ifdef NAVIT_ROUTING_DEBUG_PRINT
5792 dbg(0, "SPK:levely=%d dest=%s d=%s\n", level, destination, cmd->itm->way.street_dest_text);
5793 #endif
5794
5795 cmd->itm->streetname_told = 0;
5796 }
5797 }
5798
5799
5800 // dbg(0, "SPK:001\n");
5801
5802 if (level != -2)
5803 {
5804
5805 //dbg(0, "SPK:002\n");
5806
5807 #ifdef HAVE_API_ANDROID
5808 #ifdef NAVIT_SAY_DEBUG_PRINT
5809 android_send_generic_text(1,"+*#O:Turn %1$s%2$s %3$s%4$s\n");
5810 gchar* xy=g_strdup_printf("+*#1:%s\n", strength);
5811 android_send_generic_text(1,xy);
5812 g_free(xy);
5813 xy=g_strdup_printf("+*#1:%s\n", dir);
5814 android_send_generic_text(1,xy);
5815 g_free(xy);
5816 xy=g_strdup_printf("+*#1:%s\n", d);
5817 android_send_generic_text(1,xy);
5818 g_free(xy);
5819 xy=g_strdup_printf("+*#1:%s\n", destination ? destination : "");
5820 android_send_generic_text(1,xy);
5821 g_free(xy);
5822 #endif
5823 #endif
5824
5825 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2)) // bicycle mode
5826 {
5827 //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);
5828
5829 if (level_now == 0)
5830 {
5831 if (against_oneway == 1)
5832 {
5833 if (delta < 8)
5834 {
5835 ret = g_strdup_printf("%s", _("oncoming traffic!")); // just say "attention oneway street!"
5836 }
5837 else
5838 {
5839 ret = g_strdup_printf("%s, %s", dir, _("oncoming traffic!")); // just say "left" or "right" at the turn + "attention oneway street!"
5840 }
5841 }
5842 else
5843 {
5844 ret = g_strdup(dir); // just say "left" or "right" at the turn
5845 }
5846 }
5847 else
5848 {
5849 if ((against_oneway == 1) && (delta < 8))
5850 {
5851 ret = g_strdup(""); // probably just going against a oneway street, but travelling straight on. dont say anything now
5852 }
5853 else
5854 {
5855 if (delta == 0)
5856 {
5857 // 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'
5858 ret = g_strdup_printf_4_str(_("%1$s%2$s %3$s%4$s"), "", dir, d, destination ? destination : "");
5859 }
5860 else
5861 {
5862 // 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'
5863 ret = g_strdup_printf_4_str(_("Turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination : "");
5864 }
5865 }
5866 }
5867 }
5868 else // car mode
5869 {
5870 if (delta == 0)
5871 {
5872 // 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'
5873 ret = g_strdup_printf_4_str(_("%1$s%2$s %3$s%4$s"), "", dir, d, destination ? destination : "");
5874 }
5875 else
5876 {
5877 if (keep_dir != 0)
5878 {
5879 if (keep_dir == -1)
5880 {
5881 // TRANSLATORS: The argument is the distance. Example: 'keep left in 100 meters'
5882 ret = g_strdup_printf(_("keep left %s"), d);
5883
5884 // dirty hack, so we don't need new translations
5885 char *ret2 = g_strdup_printf("%s%s", ret, destination ? destination : "");
5886 g_free(ret);
5887 ret = ret2;
5888 // ret2 = NULL;
5889 }
5890 else
5891 {
5892 // TRANSLATORS: The argument is the distance. Example: 'keep right in 100 meters'
5893 ret = g_strdup_printf(_("keep right %s"), d);
5894
5895 // dirty hack, so we don't need new translations
5896 char *ret2 = g_strdup_printf("%s%s", ret, destination ? destination : "");
5897 g_free(ret);
5898 ret = ret2;
5899 // ret2 = NULL;
5900 }
5901 }
5902 else
5903 {
5904 // TRANSLATORS: The first argument is strength, the second direction, the third distance and the fourth destination Example: 'Turn 'slightly' 'left' in '100 m' 'onto baker street'
5905 ret = g_strdup_printf_4_str(_("Turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination : "");
5906 }
5907 }
5908 }
5909 }
5910 else // (level == -2)
5911 {
5912
5913 //dbg(0, "SPK:007\n");
5914
5915
5916 #ifdef HAVE_API_ANDROID
5917 #ifdef NAVIT_SAY_DEBUG_PRINT
5918 android_send_generic_text(1,"+*#O:then turn %1$s%2$s %3$s%4$s\n");
5919 gchar* xy=g_strdup_printf("+*#1:%s\n", strength);
5920 android_send_generic_text(1,xy);
5921 g_free(xy);
5922 xy=g_strdup_printf("+*#1:%s\n", dir);
5923 android_send_generic_text(1,xy);
5924 g_free(xy);
5925 xy=g_strdup_printf("+*#1:%s\n", d);
5926 android_send_generic_text(1,xy);
5927 g_free(xy);
5928 xy=g_strdup_printf("+*#1:%s\n", destination ? destination : "");
5929 android_send_generic_text(1,xy);
5930 g_free(xy);
5931 #endif
5932 #endif
5933 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2)) // bicycle mode
5934 {
5935 if ((against_oneway == 1) && (delta < 8))
5936 {
5937 ret = g_strdup(""); // probably just going against a oneway street, but travelling straight on. dont say anything now
5938 }
5939 else
5940 {
5941 if (delta == 0)
5942 {
5943 // TRANSLATORS: First argument is strength, second direction, third how many roads to skip, fourth destination
5944 ret = g_strdup_printf_4_str(_("then %1$s%2$s %3$s%4$s"), "", dir, d, destination ? destination : "");
5945 }
5946 else
5947 {
5948 // TRANSLATORS: First argument is strength, second direction, third how many roads to skip, fourth destination
5949 ret = g_strdup_printf_4_str(_("then turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination : "");
5950 }
5951 }
5952 }
5953 else // car mode
5954 {
5955 if (delta == 0)
5956 {
5957 // TRANSLATORS: First argument is strength, second direction, third how many roads to skip, fourth destination
5958 ret = g_strdup_printf_4_str(_("then %1$s%2$s %3$s%4$s"), "", dir, d, destination ? destination : "");
5959 }
5960 else
5961 {
5962 if (keep_dir != 0)
5963 {
5964 if (keep_dir == -1)
5965 {
5966 ret = g_strdup_printf("%s", _("then keep left"));
5967 }
5968 else
5969 {
5970 ret = g_strdup_printf("%s", _("then keep right"));
5971 }
5972 }
5973 else
5974 {
5975 // TRANSLATORS: First argument is strength, second direction, third how many roads to skip, fourth destination
5976 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!
5977 // ret = g_strdup_printf_4_str(_("then turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination : "");
5978 }
5979 }
5980 }
5981 }
5982 g_free(destination);
5983 }
5984 else
5985 {
5986 if (!connect)
5987 {
5988 #ifdef HAVE_API_ANDROID
5989 #ifdef NAVIT_SAY_DEBUG_PRINT
5990 android_send_generic_text(1,"+*#O:You have reached your destination %s\n");
5991 gchar* xy=g_strdup_printf("+*#1:%s\n", d);
5992 android_send_generic_text(1,xy);
5993 g_free(xy);
5994 #endif
5995 #endif
5996 // TRANSLATORS: EXAMPLE: You have reached your destination in 300 meters
5997 ret = g_strdup_printf(_("You have reached your destination %s"), d);
5998 }
5999 else
6000 {
6001 #ifdef HAVE_API_ANDROID
6002 #ifdef NAVIT_SAY_DEBUG_PRINT
6003 android_send_generic_text(1,"+*#O:then you have reached your destination.\n");
6004 #endif
6005 #endif
6006 ret = g_strdup(_("then you have reached your destination."));
6007 }
6008 }
6009 g_free(d);
6010
6011 return2 ret;
6012
6013 __F_END__
6014 }
6015
6016
6017
6018 static char *
6019 show_maneuver(struct navigation *nav, struct navigation_itm *itm, struct navigation_command *cmd, enum attr_type type, int connect)
6020 {
6021 return show_maneuver_at_level(nav, itm, cmd, type, connect, DONT_KNOW_LEVEL, 0);
6022 }
6023
6024
6025
6026
6027 /**
6028 * @brief Creates announcements for maneuvers, plus maneuvers immediately following the next maneuver
6029 *
6030 * This function does create an announcement for the current maneuver and for maneuvers
6031 * immediately following that maneuver, if these are too close and we're in speech navigation.
6032 *
6033 * @return An announcement that should be made
6034 */
6035 // central entry point for TTS maneuvers --------------
6036 // central entry point for TTS maneuvers --------------
6037 // central entry point for TTS maneuvers --------------
6038 static char *
6039 show_next_maneuvers(struct navigation *nav, struct navigation_itm *itm, struct navigation_command *cmd, enum attr_type type)
6040 {
6041 __F_START__
6042
6043 struct navigation_command *cur, *prev;
6044 int distance = itm->dest_length - cmd->itm->dest_length;
6045 int level, dist, i, time, level2;
6046 int speech_time, time2nav;
6047 char *ret, *old, *buf, *next;
6048 char *ret22;
6049
6050 char *temp_txt = NULL;
6051
6052
6053 //dbg(0, "Enter\n");
6054
6055 if (type != attr_navigation_speech)
6056 {
6057 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
6058 {
6059 return2 show_maneuver_bicycle(nav, itm, cmd, type, 0, DONT_KNOW_LEVEL); // not for speech, so just return the real values
6060 }
6061 else
6062 {
6063 return2 show_maneuver(nav, itm, cmd, type, 0); // not for speech, so just return the real values
6064 }
6065 }
6066
6067
6068 int cur_vehicle_speed = 0;
6069 if ((global_navit) && (global_navit->vehicle))
6070 {
6071 cur_vehicle_speed = global_navit->vehicle->speed; // in km/h
6072 }
6073
6074
6075 dbg(0, "SPEECH:[-0v-] current speed=%d\n", cur_vehicle_speed);
6076
6077
6078 // -- bicycle mode START -------------------------------------
6079 // -- bicycle mode START -------------------------------------
6080 // -- bicycle mode START -------------------------------------
6081 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
6082 {
6083 level = navigation_get_announce_level(nav, itm->way.item.type, distance - cmd->length, 0);
6084
6085 //dbg(0, "level = %d\n", level);
6086 //dbg(0, "(nn)itm->way.flags=%x\n", itm->way.flags);
6087 //dbg(0, "(nn)itm->next->way.flags=%x\n", itm->next->way.flags);
6088 //dbg(0, "(nn)distance=%d cmd->length=%d (minus)=%d\n", distance, cmd->length, (distance - cmd->length));
6089
6090 // in bike mode level should only be "0" or "1" or "3" !
6091
6092 if (level > 2)
6093 {
6094 //dbg(0, "just say the current command\n");
6095 return2 show_maneuver_bicycle(nav, itm, cmd, type, 0, level); // just say the current command
6096 }
6097
6098 if (cmd->itm->told)
6099 {
6100 // current command should not be spoken again!
6101 //dbg(0, "current command should not be spoken again\n");
6102 return2 g_strdup("");
6103 }
6104
6105
6106 //dbg(0, "xx 017a fsp, itm->told=%d l=%d\n", cmd->itm->told, level);
6107 if (level == 0)
6108 {
6109 // this command is spoken (now)
6110 //dbg(0, "this command is spoken (now)\n");
6111 cmd->itm->told = 1;
6112 }
6113 //dbg(0, "xx 017b fsp, itm->told=%d\n", cmd->itm->told);
6114
6115
6116 // current maneuver -------
6117 ret = show_maneuver_bicycle(nav, itm, cmd, type, 0, level); // generate TTS text for current command
6118 //dbg(0, "ret cmd=%s\n", ret);
6119 time2nav = navigation_time(itm, cmd->itm->prev);
6120 //dbg(0, "time2nav = %d\n", time2nav);
6121 old = NULL;
6122 // current maneuver -------
6123
6124 cur = cmd->next;
6125 prev = cmd;
6126
6127 if (cur && cur->itm) // we have a next command
6128 {
6129 dist = prev->itm->dest_length - cur->itm->dest_length;
6130 level2 = navigation_get_announce_level(nav, itm->next->way.item.type, dist, 0);
6131 //dbg(0, "(next)level2 = %d\n", level2);
6132 //dbg(0, "(next)dist=%d\n", dist);
6133
6134 if ((level2 < 2) && (dist < (2 * level_static_for_bicycle[0])))
6135 {
6136 //dbg(0, "link next command, and dont say it again!\n");
6137 old = ret;
6138 buf = show_maneuver_bicycle(nav, prev->itm, cur, type, 1, 0); // generate TTS text for next command, and dont say the next command again!
6139 //dbg(0, "next cmd=%s\n", next);
6140 ret = g_strdup_printf("%s, %s", old, buf);
6141 //dbg(0, "next cmd concat=%s\n", ret);
6142 g_free(buf);
6143 g_free(old);
6144 if (level == 0)
6145 {
6146 // dont say this next command again!
6147 cur->itm->told = 1;
6148 }
6149 }
6150 }
6151 }
6152 // -- bicycle mode END -------------------------------------
6153 // -- bicycle mode END -------------------------------------
6154 // -- bicycle mode END -------------------------------------
6155 else
6156 {
6157
6158
6159
6160 // -------------------------------------------------
6161 // -------------------------------------------------
6162 // -- ******************************************* --
6163 // CAR MODE
6164 // -- ******************************************* --
6165 // -------------------------------------------------
6166 // -------------------------------------------------
6167
6168 level = navigation_get_announce_level(nav, itm->way.item.type, distance - cmd->length, ((float)cur_vehicle_speed / 3.6f));
6169 //dbg(0, "level = %d\n", level);
6170 //dbg(0, "(nn)itm->way.flags=%x\n", itm->way.flags);
6171 //dbg(0, "(nn)itm->next->way.flags=%x\n", itm->next->way.flags);
6172
6173 long temp_ts = -1;
6174 debug_get_timestamp_millis(&temp_ts);
6175 if (global_last_spoken == -1)
6176 {
6177 temp_ts = 99999999;
6178 }
6179
6180 int time2nav_2 = navigation_time_real_speed(itm, cmd->itm->prev, cur_vehicle_speed);
6181
6182 dbg(0, "SPEECH:[-00-] last spoken ago=%f\n", (float)((temp_ts - global_last_spoken) / 1000.0f));
6183 dbg(0, "SPEECH:[-01-] meters to next maneuver=%d\n", (distance - cmd->length));
6184 dbg(0, "SPEECH:[-02-] level=%d\n", level);
6185
6186 #ifdef HAVE_API_ANDROID
6187 temp_txt = g_strdup_printf("SPEECH:[-00-] last spoken ago=%f\n", (float)((temp_ts - global_last_spoken) / 1000.0f));
6188 android_send_generic_text(20, temp_txt);
6189 g_free(temp_txt);
6190
6191 temp_txt = g_strdup_printf("SPEECH:[-01-] meters to next maneuver=%d\n", (distance - cmd->length));
6192 android_send_generic_text(20, temp_txt);
6193 g_free(temp_txt);
6194
6195 temp_txt = g_strdup_printf("SPEECH:[-02-] level=%d\n", level);
6196 android_send_generic_text(20, temp_txt);
6197 g_free(temp_txt);
6198 #endif
6199
6200 dbg(0, "SPEECH:[-03-] time2nav secs=%f\n", ((float)time2nav_2 / 10.0f));
6201
6202 int dist_to_next_spoken_command = -1;
6203 float secs_to_next_spoken_command = -1;
6204 if (level > 0)
6205 {
6206 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) ) );
6207
6208 if (cur_vehicle_speed > 0)
6209 {
6210 secs_to_next_spoken_command = ((float)dist_to_next_spoken_command / ((float)cur_vehicle_speed / 3.6f));
6211 }
6212 else
6213 {
6214 secs_to_next_spoken_command = ((float)dist_to_next_spoken_command / ((float)itm->speed / 3.6f));
6215 }
6216 }
6217
6218
6219 // current maneuver -------
6220 ret22 = show_maneuver_at_level(nav, itm, cmd, type, 0, level, 0);
6221 // current maneuver -------
6222
6223 if (nav->speech)
6224 {
6225 speech_time = speech_estimate_duration(nav->speech, ret22);
6226 dbg(0, "SPEECH:[-CUR-] secs=%f text=%s\n", ((float)speech_time)/10.0f, ret22);
6227 }
6228 else
6229 {
6230 speech_time = -1;
6231 dbg(0, "SPEECH:[-CUR-] secs=-1 text=%s\n", ret22);
6232 }
6233
6234
6235 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);
6236
6237 if (level == 3)
6238 {
6239
6240 // ===========----------- LEVEL 3 -----------===========
6241
6242 #if 0
6243 if (((float)((temp_ts - global_last_spoken) / 1000.0f)) < 3.0f)
6244 {
6245 dbg(0, "SPEECH:[-NOOP-] 004: already spoken in the last 3 secs.\n");
6246 return2 g_strdup(""); // dont speak this command now!
6247 }
6248 #endif
6249
6250 if (secs_to_next_spoken_command < 7 )
6251 {
6252 if (ret22)
6253 {
6254 g_free(ret22);
6255 ret22 = NULL;
6256 }
6257
6258 #ifdef _DEBUG_BUILD_
6259 // speak debug ----
6260 navit_say(global_navit, "level 3a wieder in 7 sekunden");
6261 // speak debug ----
6262 #endif
6263
6264 dbg(0, "SPEECH:[-NOOP-] 006b: want to speak again in less than %d secs. level=%d\n", 7, level);
6265 return2 g_strdup(""); // dont speak this command now!
6266 }
6267
6268 if (secs_to_next_spoken_command < (((float)speech_time/10.0f) + 3) )
6269 {
6270 if (ret22)
6271 {
6272 g_free(ret22);
6273 ret22 = NULL;
6274 }
6275
6276 #ifdef _DEBUG_BUILD_
6277 // speak debug ----
6278 temp_txt = g_strdup_printf("level 3b wieder in %d sekunden", (int)(((float)speech_time/10.0f) + 3));
6279 navit_say(global_navit, temp_txt);
6280 g_free(temp_txt);
6281 // speak debug ----
6282 #endif
6283
6284 dbg(0, "SPEECH:[-NOOP-] 006: want to speak again in less than %d secs. level=%d\n", (((float)speech_time/10.0f) + 3), level );
6285 return2 g_strdup(""); // dont speak this command now!
6286 }
6287 // ===========----------- LEVEL 3 -----------===========
6288
6289
6290 }
6291 else if (level == 2)
6292 {
6293
6294 // ===========----------- LEVEL 2 -----------===========
6295
6296
6297 #if 0
6298 if (secs_to_next_spoken_command < 3 )
6299 {
6300 if (ret22)
6301 {
6302 g_free(ret22);
6303 ret22 = NULL;
6304 }
6305
6306 #ifdef _DEBUG_BUILD_
6307 // speak debug ----
6308 navit_say(global_navit, "level 2a wieder in 3 sekunden");
6309 // speak debug ----
6310 #endif
6311
6312 dbg(0, "SPEECH:[-NOOP-] 007b: want to speak again in less than %d secs. level=%d\n", 3, level);
6313 return2 g_strdup(""); // dont speak this command now!
6314 }
6315 #endif
6316
6317 #if 1
6318 if (secs_to_next_spoken_command < (((float)speech_time/10.0f) + 1) )
6319 {
6320 if (ret22)
6321 {
6322 g_free(ret22);
6323 ret22 = NULL;
6324 }
6325
6326 #ifdef _DEBUG_BUILD_
6327 // speak debug ----
6328 temp_txt = g_strdup_printf("level 2b wieder in %d sekunden", (int)(((float)speech_time/10.0f) + 1));
6329 navit_say(global_navit, temp_txt);
6330 // speak debug ----
6331 #endif
6332
6333 dbg(0, "SPEECH:[-NOOP-] 007: want to speak again in less than %d secs. level=%d\n", (int)(((float)speech_time/10.0f) + 1), level);
6334 return2 g_strdup(""); // dont speak this command now!
6335 }
6336 #endif
6337
6338 #if 0
6339 if (((float)((temp_ts - global_last_spoken) / 1000.0f)) < 5.0f)
6340 {
6341 if (ret22)
6342 {
6343 g_free(ret22);
6344 ret22 = NULL;
6345 }
6346
6347 #ifdef _DEBUG_BUILD_
6348 // speak debug ----
6349 navit_say(global_navit, "level 2c schon vor 5 sekunden");
6350 // speak debug ----
6351 #endif
6352
6353 dbg(0, "SPEECH:[-NOOP-] 005: already spoken in the last 5 secs. level=%d\n", level);
6354 return2 g_strdup(""); // dont speak this command now!
6355 }
6356 #endif
6357
6358 // ===========----------- LEVEL 2 -----------===========
6359
6360
6361 }
6362 else if (level == 1)
6363 {
6364
6365 // ===========----------- LEVEL 1 -----------===========
6366
6367
6368 #if 0
6369 if (((float)time2nav_2 / 10.0f) < 5.0f)
6370 {
6371 dbg(0, "SPEECH:[-NOOP-] 001: less than 5 secs. to maneuver\n");
6372 return2 g_strdup(""); // dont speak this command now!
6373 }
6374 #endif
6375
6376 #if 0
6377 if ((distance - cmd->length) < 50)
6378 {
6379 dbg(0, "SPEECH:[-NOOP-] 003: less than 50 meters to maneuver\n");
6380 return2 g_strdup(""); // dont speak this command now!
6381 }
6382 #endif
6383
6384
6385 if (dist_to_next_spoken_command < 18)
6386 {
6387 if (ret22)
6388 {
6389 g_free(ret22);
6390 ret22 = NULL;
6391 }
6392
6393 #ifdef _DEBUG_BUILD_
6394 // speak debug ----
6395 temp_txt = g_strdup_printf("level 1a wieder in %d sekunden", 18);
6396 navit_say(global_navit, temp_txt);
6397 g_free(temp_txt);
6398 // speak debug ----
6399 #endif
6400
6401
6402 dbg(0, "SPEECH:[-NOOP-] 011: less than 18 meters to next announcement\n");
6403 return2 g_strdup(""); // dont speak this command now!
6404 }
6405
6406 #if 0
6407 if (((float)((temp_ts - global_last_spoken) / 1000.0f)) < 4.0f)
6408 {
6409 if (ret22)
6410 {
6411 g_free(ret22);
6412 ret22 = NULL;
6413 }
6414
6415 dbg(0, "SPEECH:[-NOOP-] 002: already spoken in the last 4 secs. level=%d\n", level);
6416 return2 g_strdup(""); // dont speak this command now!
6417 }
6418 #endif
6419
6420 if (secs_to_next_spoken_command < (((float)speech_time/10.0f) + 1) )
6421 {
6422 if (secs_to_next_spoken_command < 3.0f)
6423 {
6424 if (ret22)
6425 {
6426 g_free(ret22);
6427 ret22 = NULL;
6428 }
6429
6430 #ifdef _DEBUG_BUILD_
6431 // speak debug ----
6432 temp_txt = g_strdup_printf("level 1b wieder in %d sekunden", 3);
6433 navit_say(global_navit, temp_txt);
6434 g_free(temp_txt);
6435 // speak debug ----
6436 #endif
6437
6438
6439 dbg(0, "SPEECH:[-NOOP-] 008: want to speak again in less than %d secs. level=%d\n", (((float)speech_time/10.0f) + 1), level);
6440 return2 g_strdup(""); // dont speak this command now!
6441 }
6442 else
6443 {
6444 // if we have at least 3 seconds left, still say level 1 announcement (without the streetname/destination name)
6445 dbg(0, "SPEECH:[-NOOP-] 008lo: use level=%d announcement without destination name\n", level);
6446 if (ret22)
6447 {
6448 g_free(ret22);
6449 ret22 = NULL;
6450 }
6451 ret22 = show_maneuver_at_level(nav, itm, cmd, type, 0, level, -1);
6452 if (nav->speech)
6453 {
6454 speech_time = speech_estimate_duration(nav->speech, ret22);
6455 dbg(0, "SPEECH:[-CUR-] :lo: secs=%f text=%s\n", ((float)speech_time)/10.0f, ret22);
6456 }
6457 else
6458 {
6459 speech_time = -1;
6460 dbg(0, "SPEECH:[-CUR-] :lo: secs=-1 text=%s\n", next);
6461 }
6462
6463 if (secs_to_next_spoken_command < (((float)speech_time/10.0f) + 0) )
6464 {
6465 if (ret22)
6466 {
6467 g_free(ret22);
6468 ret22 = NULL;
6469 }
6470
6471 #ifdef _DEBUG_BUILD_
6472 // speak debug ----
6473 temp_txt = g_strdup_printf("level 1c wieder in %d sekunden", (int)(((float)speech_time/10.0f) + 0));
6474 navit_say(global_navit, temp_txt);
6475 g_free(temp_txt);
6476 // speak debug ----
6477 #endif
6478
6479
6480 dbg(0, "SPEECH:[-NOOP-] 008loEE: giving up on this announcement\n");
6481 return2 g_strdup(""); // dont speak this command now!
6482 }
6483 }
6484 }
6485
6486 // ===========----------- LEVEL 1 -----------===========
6487
6488 }
6489
6490
6491
6492
6493
6494
6495 #ifdef HAVE_API_ANDROID
6496 temp_txt = g_strdup_printf("SPEECH:[-03-] time2nav secs=%f\n", ((float)time2nav_2 / 10.0f));
6497 android_send_generic_text(20, temp_txt);
6498 g_free(temp_txt);
6499 #endif
6500
6501 if (level > 1)
6502 {
6503 dbg(0, "SPEECH:[-R1-]\n");
6504 return2 ret22; // We accumulate maneuvers only if they are close (level-0 and level-1)
6505 }
6506
6507 if (cmd->itm->told)
6508 {
6509 #ifdef HAVE_API_ANDROID
6510 #ifdef NAVIT_SAY_DEBUG_PRINT
6511 android_send_generic_text(1,"+*#C1:*CANCEL*\n");
6512 #endif
6513 #endif
6514 dbg(0, "SPEECH:[-R2-]\n");
6515 #ifdef HAVE_API_ANDROID
6516 temp_txt = g_strdup("SPEECH:[-R2-]\n");
6517 android_send_generic_text(20, temp_txt);
6518 g_free(temp_txt);
6519 #endif
6520 if (ret22)
6521 {
6522 g_free(ret22);
6523 ret22 = NULL;
6524 }
6525
6526
6527 return2 g_strdup("");
6528 }
6529
6530
6531 // current maneuver -------
6532 ret = ret22;
6533 time2nav = navigation_time_real_speed(itm, cmd->itm->prev, cur_vehicle_speed);
6534 // current maneuver -------
6535
6536
6537 #if 0
6538 if (nav->speech)
6539 {
6540 speech_time = speech_estimate_duration(nav->speech, ret);
6541 dbg(0, "SPEECH:[-CUR-] secs=%f text=%s\n", ((float)speech_time)/10.0f, ret);
6542 }
6543 else
6544 {
6545 speech_time = -1;
6546 dbg(0, "SPEECH:[-CUR-] secs=-1 text=%s\n", next);
6547 }
6548 #endif
6549
6550
6551 old = NULL;
6552
6553 dbg(0, "SPEECH:[-04-] time2nav secs=%f\n", ((float)time2nav / 10.0f));
6554 #ifdef HAVE_API_ANDROID
6555 temp_txt = g_strdup_printf("SPEECH:[-04-] time2nav secs=%f\n", ((float)time2nav / 10.0f));
6556 android_send_generic_text(20, temp_txt);
6557 g_free(temp_txt);
6558 #endif
6559
6560
6561
6562
6563 // next maneuver -------
6564 cur = cmd->next;
6565 prev = cmd;
6566 // next maneuver -------
6567
6568
6569 i = 0;
6570 int max_announcements = 3;
6571 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
6572 {
6573 max_announcements = 2;
6574 }
6575
6576 while (cur && cur->itm) // only accumulate at "level 0" or "level 1"
6577 {
6578 // We don't merge more than "max_announcements" announcements...
6579 if (i > (max_announcements - 2))
6580 {
6581 break;
6582 }
6583
6584 dist = prev->itm->dest_length - cur->itm->dest_length; // distance between next 2 maneuvers in meters
6585
6586 if (dist > 420) // too far apart, bail out
6587 {
6588 break;
6589 }
6590
6591 next = show_maneuver(nav, prev->itm, cur, type, 0);
6592 if (nav->speech)
6593 {
6594 speech_time = speech_estimate_duration(nav->speech, next);
6595 dbg(0, "SPEECH:[-NXT-] secs=%f text=%s\n", ((float)speech_time)/10.0f, next);
6596 }
6597 else
6598 {
6599 speech_time = -1;
6600 dbg(0, "SPEECH:[-NXT-] secs=-1 text=%s\n", next);
6601 }
6602 g_free(next);
6603
6604 if (speech_time == -1)
6605 {
6606 // user didn't set cps
6607 speech_time = 25; // assume 2.5 seconds
6608 dbg(0, "SPEECH:[-NXT-](2) secs=%f\n", ((float)speech_time)/10.0f);
6609 }
6610
6611 //if (cur_vehicle_speed > 0)
6612 //{
6613 // time = ((float)dist / ((float)cur_vehicle_speed / 3.6f)) * 10;
6614 //}
6615 //else
6616 //{
6617 // time = navigation_time_real_speed(prev->itm, cur->itm->prev, cur_vehicle_speed);
6618 time = navigation_time(prev->itm, cur->itm->prev);
6619 //}
6620
6621 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);
6622 #ifdef HAVE_API_ANDROID
6623 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);
6624 android_send_generic_text(20, temp_txt);
6625 g_free(temp_txt);
6626 #endif
6627
6628
6629 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
6630 {
6631 // !! should never get here !!
6632 }
6633 else
6634 {
6635 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);
6636
6637 if (i == 0)
6638 {
6639 if (dist < 170) // distance between maneuvers less than 170m --> always merge maneuvers
6640 {
6641 }
6642 else
6643 {
6644 // **OLD** // if (time >= (speech_time + 35)) // (time to turn) >= (time to speak command + 3.5 secs.)
6645 if (time > ((global_level1_announcement * 10.0f) - 3) ) // more than "global_level1_announcement" seconds to next maneuver -> don't merge it
6646 {
6647 dbg(0, "SPEECH:*break first*\n");
6648 break;
6649 }
6650 }
6651 }
6652 else
6653 {
6654 if (time > (global_level0_announcement * 10.0f)) // more than "global_level0_announcement" seconds to next maneuver -> don't merge it
6655 {
6656 dbg(0, "SPEECH:*break next*\n");
6657 break;
6658 }
6659 }
6660 }
6661
6662 old = ret;
6663 buf = show_maneuver(nav, prev->itm, cur, type, 1);
6664 ret = g_strdup_printf("%s, %s", old, buf);
6665 g_free(buf);
6666
6667 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);
6668 // if (nav->speech && speech_estimate_duration(nav->speech, ret) > time2nav)
6669 // {
6670 // g_free(ret);
6671 // ret = old;
6672 // i = (max_announcements - 1); // This will terminate the loop
6673 // dbg(0, "SPEECH:*terminate loop*\n");
6674 // }
6675 // else
6676 // {
6677 g_free(old);
6678 // }
6679
6680
6681 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
6682 {
6683 // !! should never get here !!
6684 }
6685 else
6686 {
6687 #if 0
6688 dbg(0, "SPEECH: time secs=%f speech_time secs=%f [if (time <= speech_time)]\n", ((float)time)/10.0f, ((float)speech_time)/10.0f);
6689 // If the two maneuvers are *really* close, we shouldn't tell the second one again, because TTS won't be fast enough
6690 if (time <= speech_time)
6691 {
6692 #ifdef HAVE_API_ANDROID
6693 #ifdef NAVIT_SAY_DEBUG_PRINT
6694 android_send_generic_text(1,"+*#C2:*CANCEL*\n");
6695 #endif
6696 #endif
6697 //dbg(0, "cancel speak:%s\n", ret);
6698 cur->itm->told = 1;
6699 }
6700 #endif
6701 }
6702
6703 prev = cur;
6704 cur = cur->next;
6705 i++;
6706 }
6707
6708 // -------------------------------------------------
6709 // -------------------------------------------------
6710 // -- ******************************************* --
6711 // CAR MODE
6712 // -- ******************************************* --
6713 // -------------------------------------------------
6714 // -------------------------------------------------
6715
6716 }
6717
6718 dbg(0, "SPEECH:[-Re-]\n");
6719 #ifdef HAVE_API_ANDROID
6720 temp_txt = g_strdup("SPEECH:[-Re-]\n");
6721 android_send_generic_text(20, temp_txt);
6722 g_free(temp_txt);
6723 #endif
6724
6725 return2 ret;
6726
6727 __F_END__
6728 }
6729 // central entry point for TTS maneuvers --------------
6730 // central entry point for TTS maneuvers --------------
6731 // central entry point for TTS maneuvers --------------
6732
6733
6734
6735 // ----- global var, BAD!! -------
6736 int global_spoke_last_position_update = 0;
6737 int previous_dest_length = -1;
6738 int previous_dest_length_save = -1;
6739 struct navigation_command *last_first_cmd_save = NULL;
6740 int global_turn_around_spoken = 0;
6741 // ----- global var, BAD!! -------
6742
6743 static void navigation_call_callbacks(struct navigation *this_, int force_speech)
6744 {
6745 __F_START__
6746
6747 int distance, level = 0;
6748 int level_cur;
6749 int distance_orig;
6750 void *p = this_;
6751 int dont_speak_yet = 0;
6752 int level_last_save = 99;
6753
6754 if (!this_->cmd_first)
6755 {
6756 //dbg(0, "ret 0001\n");
6757 global_spoke_last_position_update = 0;
6758 return2;
6759 }
6760
6761 // EMPTY: calls nothing!!
6762 // ****** // callback_list_call(this_->callback, 1, &p);
6763
6764 //if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
6765 //{
6766 // force_speech = 7;
6767 //}
6768
6769 //dbg(0, "force_speech=%d turn_around=%d turn_around_limit=%d\n", force_speech, this_->turn_around, this_->turn_around_limit);
6770
6771 distance = this_->first->dest_length - this_->cmd_first->itm->dest_length;
6772 //dbg(0, "fdl=%d cmdidl=%d\n", this_->first->dest_length, this_->cmd_first->itm->dest_length);
6773 distance_orig = distance;
6774 distance = round_distance(distance);
6775
6776 int cur_vehicle_speed = 0;
6777 if ((global_navit) && (global_navit->vehicle))
6778 {
6779 cur_vehicle_speed = global_navit->vehicle->speed;
6780 }
6781
6782 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);
6783
6784
6785 if (this_->turn_around_limit && this_->turn_around == this_->turn_around_limit)
6786 {
6787
6788 dbg(0, "NAV_TURNAROUND:005 ta=%d talimit=%d\n", this_->turn_around, this_->turn_around_limit);
6789
6790 //dbg(0, "xx 001 d=%d rd=%d dt=%d\n", distance_orig, distance_orig, this_->distance_turn);
6791 #if 0
6792 while (distance > this_->distance_turn)
6793 {
6794 this_->level_last = 4;
6795 level = 4;
6796 force_speech = 2;
6797
6798 if (this_->distance_turn >= 500)
6799 {
6800 this_->distance_turn *= 2;
6801 }
6802 else
6803 {
6804 this_->distance_turn = 500;
6805 }
6806 #endif
6807
6808 // we need to force a maneuver for "turn around" ------------------
6809 this_->level_last = 4;
6810 level = 4;
6811 force_speech = 2;
6812 // this_->distance_turn *= 100;
6813
6814 #if 1
6815 global_driven_away_from_route = 0;
6816 global_spoke_last_position_update = 0;
6817 global_last_spoken = -1;
6818 previous_dest_length = -1;
6819 previous_dest_length_save = -1;
6820 last_first_cmd_save = NULL;
6821 #endif
6822
6823 this_->level_last = 99;
6824
6825
6826 this_->level_last = level;
6827 this_->curr_delay = 0;
6828
6829 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);
6830 dbg(0, "NCC_:========= END ==========\n");
6831
6832 global_spoke_last_position_update = 1;
6833
6834 // ----------------------------------
6835 // ----------------------------------
6836 // calls -> calls navit_speak
6837 //
6838 callback_list_call(this_->callback_speech, 1, &p);
6839 // ----------------------------------
6840 // ----------------------------------
6841
6842
6843 return2;
6844
6845 // we need to force a maneuver for "turn around" ------------------
6846
6847 #if 0
6848 dbg(0, "NCC_:loop 001 d=%d dt=%d force_speech=%d\n", distance, this_->distance_turn, force_speech);
6849 }
6850 #endif
6851
6852 }
6853 else if (!this_->turn_around_limit || this_->turn_around != this_->turn_around_limit)
6854 {
6855 this_->distance_turn = 50;
6856
6857 global_turn_around_spoken = 0; // reset turn around speak flag
6858
6859 //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);
6860 //dbg(0, "xx 002a d=%d d2=%d diff=%d\n", distance, (distance - this_->cmd_first->length), (this_->cmd_first->itm->length - distance_orig));
6861
6862 //dbg(0, "xx 002a ll001=%d\n", (this_->cmd_first->itm->prev->dest_length - this_->cmd_first->itm->dest_length));
6863
6864 distance -= this_->cmd_first->length;
6865
6866
6867 level = navigation_get_announce_level_cmd(this_, this_->first, this_->cmd_first, distance_orig, ((float)cur_vehicle_speed / 3.6f) );
6868 level_cur = navigation_get_announce_level(this_, this_->first->way.item.type, distance_orig, ((float)cur_vehicle_speed / 3.6f));
6869
6870
6871
6872 if (last_first_cmd_save != this_->cmd_first)
6873 {
6874 last_first_cmd_save = this_->cmd_first;
6875 previous_dest_length = previous_dest_length_save;
6876 }
6877 previous_dest_length_save = this_->cmd_first->itm->dest_length;
6878 // level_last_save = this_->level_last;
6879
6880 //dbg(0, "NCC_:\n");
6881 //dbg(0, "NCC_:0---passed item?---\n");
6882 // 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);
6883
6884 #if 1
6885 if (previous_dest_length == -1)
6886 {
6887 dbg(0, "NCC_:no prev nav command\n");
6888 }
6889 else
6890 {
6891 if (distance_orig > 40)
6892 {
6893 if ((distance_orig + 25) >= (previous_dest_length - this_->cmd_first->itm->dest_length))
6894 {
6895 // we are still within 25 meters of the previous navigation command item
6896 dont_speak_yet = 1;
6897 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));
6898 }
6899 }
6900 #if 1
6901 else if (distance_orig > 20)
6902 {
6903 if ((distance_orig) > (previous_dest_length - this_->cmd_first->itm->dest_length))
6904 {
6905 // we are still at the position of the previous navigation command item
6906 dont_speak_yet = 1;
6907 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));
6908 }
6909 }
6910 #endif
6911 }
6912 #endif
6913
6914 //dbg(0, "NCC_:1---passed item?---\n");
6915 //dbg(0, "NCC_:\n");
6916
6917
6918
6919
6920 //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);
6921
6922 if (level < this_->level_last)
6923 {
6924 /* only tell if the level is valid for more than 3 seconds */
6925 int speed_distance = this_->first->speed * 30 / 36;
6926
6927 dbg(0, "NCC_:speed_distance=%d\n", speed_distance);
6928
6929
6930 //dbg(0, "xx 003 speed_distance=%d this_->first->speed=%d globalslp=%d\n", speed_distance, this_->first->speed, global_spoke_last_position_update);
6931
6932 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2))
6933 {
6934
6935 level = level_cur;
6936
6937 if ((level_cur > 0) && (global_spoke_last_position_update > 0))
6938 {
6939 // skip this time, speak command on the next update
6940 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);
6941 }
6942 else
6943 {
6944 this_->level_last = level_cur;
6945 force_speech = 3;
6946 dbg(0, "NCC_:force_speech(2)=%d\n", force_speech);
6947 }
6948 }
6949 else
6950 {
6951 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)
6952 {
6953 //dbg(0, "distance %d speed_distance %d\n", distance, speed_distance);
6954 //dbg(0, "level %d < %d\n", level, this_->level_last);
6955 this_->level_last = level;
6956 force_speech = 3;
6957 dbg(0, "NCC_:force_speech(3)=%d\n", force_speech);
6958 //dbg(0, "xx 004\n");
6959 }
6960 }
6961 }
6962
6963
6964 if (!item_is_equal(this_->cmd_first->itm->way.item, this_->item_last))
6965 {
6966 //dbg(0, "xx 005\n");
6967
6968 this_->item_last = this_->cmd_first->itm->way.item;
6969 this_->level_last = 99; // new item, reset command level
6970
6971 dbg(0, "NCC_:Ni---new navigation command item!!---\n");
6972
6973 if (this_->delay)
6974 {
6975 this_->curr_delay = this_->delay;
6976 }
6977 else
6978 {
6979 // if ((level_cur > 0) && (global_spoke_last_position_update > 0) && (distance_orig > 50))
6980 // {
6981 // // skip this time, speak command on the next update
6982 // dbg(0, "NCC_:SKIP[2] speech this update, speak at next update (%d)!\n", global_spoke_last_position_update);
6983 // }
6984 // else
6985 // {
6986 force_speech = 5;
6987 dbg(0, "NCC_:force_speech(4)=%d\n", force_speech);
6988 // }
6989 }
6990 }
6991 else
6992 {
6993 //dbg(0, "xx 006\n");
6994
6995 if (this_->curr_delay)
6996 {
6997 this_->curr_delay--;
6998
6999 if (!this_->curr_delay)
7000 {
7001 force_speech = 4;
7002 dbg(0, "NCC_:force_speech(5)=%d\n", force_speech);
7003 }
7004 }
7005 }
7006 }
7007
7008 if (global_spoke_last_position_update > 0)
7009 {
7010 //dbg(0,"globalslp(1)=%d\n", global_spoke_last_position_update);
7011 global_spoke_last_position_update--;
7012 //dbg(0,"globalslp(2)=%d\n", global_spoke_last_position_update);
7013 }
7014
7015
7016 #if 0
7017 //dbg(0,"XA 000\n");
7018 if ((global_vehicle_profile == 1) || (global_vehicle_profile == 2)) // bicycle mode
7019 {
7020 if ((this_->previous) && (!item_is_equal(this_->cmd_first->itm->way.item, this_->previous->way.item)))
7021 {
7022 // item has changed, check if we missed a spoken level 0 command
7023 if (this_->previous->told == 0)
7024 {
7025 dbg(0, "NCC_:MISSED a level 0 spoken command!\n");
7026
7027 char *dir2 = _("right");
7028 int delta2 = this_->cmd_previous->delta;
7029 dbg(0, "NCC_:missed delta = %d\n", delta2);
7030 if (delta2 < 0)
7031 {
7032 // TRANSLATORS: left, as in 'Turn left'
7033 dir2 = _("left");
7034 delta2 = -delta2;
7035 }
7036
7037 if (delta2 > 20)
7038 {
7039 dbg(0,"NCC_:XA 002a\n");
7040 navit_say(this_->navit, dir2);
7041 this_->previous->told = 1;
7042 }
7043 }
7044 }
7045 }
7046 #endif
7047
7048
7049 this_->previous = this_->cmd_first->itm;
7050 this_->cmd_previous = this_->cmd_first;
7051
7052 #if 1
7053 if ((dont_speak_yet == 1) && (force_speech))
7054 {
7055 dbg(0,"NCC_:this_->level_last = 99\n");
7056 this_->level_last = 99;
7057 }
7058 #endif
7059
7060 if (global_driven_away_from_route == 1)
7061 {
7062 dbg(0,"NCC_:** NEW PATH **\n");
7063 global_driven_away_from_route = 0;
7064 global_spoke_last_position_update = 0;
7065 global_last_spoken = -1;
7066 previous_dest_length = -1;
7067 previous_dest_length_save = -1;
7068 last_first_cmd_save = NULL;
7069
7070 this_->level_last = 99;
7071 }
7072
7073 if ( (dont_speak_yet == 0) || ((global_vehicle_profile == 1) || (global_vehicle_profile == 2)) )
7074 {
7075 if (force_speech)
7076 {
7077 this_->level_last = level;
7078 this_->curr_delay = 0;
7079
7080 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);
7081 dbg(0, "NCC_:========= END ==========\n");
7082
7083 global_spoke_last_position_update = 1;
7084
7085 // ----------------------------------
7086 // ----------------------------------
7087 // calls -> calls navit_speak
7088 //
7089 callback_list_call(this_->callback_speech, 1, &p);
7090 // ----------------------------------
7091 // ----------------------------------
7092 }
7093 }
7094
7095 __F_END__
7096 }
7097
7098
7099 // ----------- main place where navigation commands are generated ------------
7100 // ----------- main place where navigation commands are generated ------------
7101 // ----------- main place where navigation commands are generated ------------
7102 static void navigation_update(struct navigation *this_, struct route *route, struct attr *attr)
7103 {
7104 __F_START__
7105
7106 struct map *map;
7107 struct map_rect *mr;
7108 struct item *ritem; /* Holds an item from the route map */
7109 struct item *sitem; /* Holds the corresponding item from the actual map */
7110 struct attr street_item, street_direction;
7111 struct navigation_itm *itm;
7112 struct attr vehicleprofile;
7113 int mode = 0, incr = 0, first = 1;
7114
7115 //dbg(0, "Enter\n");
7116
7117 if (attr->type != attr_route_status)
7118 {
7119 //dbg(0, "return 001\n");
7120 return2;
7121 }
7122
7123 #ifdef NAVIT_ROUTING_DEBUG_PRINT
7124 dbg(0, "RS:001:route_status=%s\n", route_status_to_name(attr->u.num));
7125 #endif
7126
7127
7128 dbg(0, "NCC_:NU:RRRRSSSSSS::route_status=%s\n", route_status_to_name(attr->u.num));
7129
7130 if (attr->u.num == route_status_path_done_new)
7131 {
7132 // route calculated new, you drove a different path?
7133 global_driven_away_from_route = 1;
7134 }
7135
7136
7137 //dbg(1, "enter %d\n", mode);
7138 if (attr->u.num == route_status_no_destination || attr->u.num == route_status_not_found || attr->u.num == route_status_path_done_new)
7139 {
7140 dbg(0, "NCC_:NU:navigation_flush\n");
7141 navigation_flush(this_);
7142 }
7143
7144 if (attr->u.num != route_status_path_done_new && attr->u.num != route_status_path_done_incremental)
7145 {
7146 //dbg(0, "return 002\n");
7147 dbg(0, "NCC_:NU:ret 001\n");
7148
7149 return2;
7150 }
7151
7152 if (!this_->route)
7153 {
7154 //dbg(0, "return 003\n");
7155 dbg(0, "NCC_:NU:ret 002\n");
7156
7157 return2;
7158 }
7159
7160 map = route_get_map(this_->route);
7161 if (!map)
7162 {
7163 //dbg(0, "return 004\n");
7164 return2;
7165 }
7166
7167 mr = map_rect_new(map, NULL);
7168
7169 if (!mr)
7170 {
7171 //dbg(0, "return 005\n");
7172 return2;
7173 }
7174
7175 if (route_get_attr(route, attr_vehicleprofile, &vehicleprofile, NULL))
7176 {
7177 this_->vehicleprofile = vehicleprofile.u.vehicleprofile;
7178 }
7179 else
7180 {
7181 this_->vehicleprofile = NULL;
7182 }
7183
7184 //dbg(1,"enter\n");
7185
7186 dbg(0, "NCC_:NU:------ LOOP START ------\n");
7187
7188 int first_item = 1;
7189 this_->turn_around = 0;
7190
7191 while ((ritem = map_rect_get_item(mr)))
7192 {
7193
7194 dbg(0, "NAVR:001:%s\n", item_to_name(ritem->type));
7195
7196 #if 0
7197 if (ritem->type == type_route_start && this_->turn_around > -this_->turn_around_limit + 1)
7198 {
7199 this_->turn_around--;
7200 }
7201
7202 if (ritem->type == type_route_start_reverse && this_->turn_around < this_->turn_around_limit)
7203 {
7204 this_->turn_around++;
7205 dbg(0, "NAVR:001.1:** TURN AROUND **\n");
7206 }
7207 #endif
7208
7209 #if 1
7210 if (first_item == 1)
7211 {
7212 first_item = 0;
7213 if (ritem->type == type_route_start_reverse)
7214 {
7215 this_->turn_around = this_->turn_around_limit;
7216
7217 dbg(0, "NAV_TURNAROUND:006 ta=%d talimit=%d\n", this_->turn_around, this_->turn_around_limit);
7218
7219 dbg(0, "NAVR:001.1:T_A:** TURN AROUND **:%s\n", item_to_name(ritem->type));
7220 }
7221 else
7222 {
7223 dbg(0, "NAVR:001.1:T_A:first item=%s\n", item_to_name(ritem->type));
7224 }
7225 }
7226 #endif
7227
7228
7229 dbg(0, "NAVR:001:X1:%s\n", item_to_name(ritem->type));
7230 if ((ritem->type != type_street_route) && (ritem->type != type_street_route_waypoint))
7231 {
7232 dbg(0, "NAVR:001:X2R:%s\n", item_to_name(ritem->type));
7233 continue;
7234 }
7235 dbg(0, "NAVR:001:X3:%s\n", item_to_name(ritem->type));
7236
7237 if (first && item_attr_get(ritem, attr_street_item, &street_item))
7238 {
7239 first = 0;
7240 if (!item_attr_get(ritem, attr_direction, &street_direction))
7241 {
7242 street_direction.u.num = 0;
7243 }
7244
7245 sitem = street_item.u.item;
7246 //dbg(1,"sitem=%p\n", sitem);
7247 itm = item_hash_lookup(this_->hash, sitem);
7248 //dbg(2,"itm for item with id (0x%x,0x%x) is %p\n", sitem->id_hi, sitem->id_lo, itm);
7249
7250 if (itm && itm->way.dir != street_direction.u.num)
7251 {
7252 //dbg(2,"wrong direction\n");
7253 dbg(0, "NAVR:001.2:*+ WRONG DIRECTION +*\n");
7254 itm = NULL;
7255 }
7256
7257 dbg(0, "NCC_:NU:navigation_destroy_itms_cmds\n");
7258 navigation_destroy_itms_cmds(this_, itm);
7259
7260 if (itm)
7261 {
7262 dbg(0, "NCC_:NU:navigation_itm_update\n");
7263
7264 navigation_itm_update(itm, ritem);
7265 break;
7266 }
7267 //dbg(1,"not on track\n");
7268 }
7269
7270 dbg(0, "NAVR:001:X4:%s\n", item_to_name(ritem->type));
7271 dbg(0, "NCC_:NU:navigation_itm_new\n");
7272 navigation_itm_new(this_, ritem);
7273 dbg(0, "NAVR:001:X5:%s\n", item_to_name(ritem->type));
7274
7275 }
7276
7277
7278 dbg(0, "NCC_:NU:------ LOOP END ------\n");
7279
7280
7281 //dbg(2, "turn_around=%d\n", this_->turn_around);
7282
7283 if (first)
7284 {
7285
7286 #ifdef NAVIT_FREE_TEXT_DEBUG_PRINT
7287 dbg(0, "DEST::route_clear_freetext_list\n");
7288 route_clear_freetext_list();
7289 #endif
7290
7291 dbg(0, "NCC_:NU:navigation_destroy_itms_cmds[first]\n");
7292
7293 navigation_destroy_itms_cmds(this_, NULL);
7294 }
7295 else
7296 {
7297 if (!ritem)
7298 {
7299 dbg(0, "NCC_:NU:navigation_itm_new[!ritem]\n");
7300 navigation_itm_new(this_, NULL);
7301 //dbg(0, "Enter: make_maneuvers\n");
7302 dbg(0, "NAVR:001.2:*= MAKE MANEUVERS =*\n");
7303 dbg(0, "NCC_:NU:make_maneuvers[!ritem]\n");
7304 make_maneuvers(this_, this_->route);
7305 //dbg(0, "end : make_maneuvers\n");
7306 }
7307
7308 dbg(0, "NCC_:NU:calculate_dest_distance\n");
7309 calculate_dest_distance(this_, incr);
7310
7311 // calls navit_speak later !! ----------
7312 navigation_call_callbacks(this_, FALSE);
7313 // calls navit_speak later !! ----------
7314 }
7315 map_rect_destroy(mr);
7316
7317 __F_END__
7318 }
7319 // ----------- main place where navigation commands are generated ------------
7320 // ----------- main place where navigation commands are generated ------------
7321 // ----------- main place where navigation commands are generated ------------
7322
7323
7324 static void navigation_flush(struct navigation *this_)
7325 {
7326 __F_START__
7327 navigation_destroy_itms_cmds(this_, NULL);
7328 __F_END__
7329 }
7330
7331 void navigation_destroy(struct navigation *this_)
7332 {
7333 navigation_flush(this_);
7334 item_hash_destroy(this_->hash);
7335 callback_list_destroy(this_->callback);
7336 callback_list_destroy(this_->callback_speech);
7337 g_free(this_);
7338 }
7339
7340 int navigation_register_callback(struct navigation *this_, enum attr_type type, struct callback *cb)
7341 {
7342 __F_START__
7343
7344 if (type == attr_navigation_speech)
7345 {
7346 callback_list_add(this_->callback_speech, cb);
7347 }
7348 else
7349 {
7350 callback_list_add(this_->callback, cb);
7351 }
7352
7353 return2 1;
7354
7355 __F_END__
7356 }
7357
7358 void navigation_unregister_callback(struct navigation *this_, enum attr_type type, struct callback *cb)
7359 {
7360 __F_START__
7361
7362 if (type == attr_navigation_speech)
7363 {
7364 callback_list_remove_destroy(this_->callback_speech, cb);
7365 }
7366 else
7367 {
7368 callback_list_remove_destroy(this_->callback, cb);
7369 }
7370
7371 __F_END__
7372 }
7373
7374 struct map *
7375 navigation_get_map(struct navigation *this_)
7376 {
7377 struct attr *attrs[5];
7378 struct attr type, navigation, data, description;
7379 type.type = attr_type;
7380 type.u.str = "navigation";
7381 navigation.type = attr_navigation;
7382 navigation.u.navigation = this_;
7383 data.type = attr_data;
7384 data.u.str = "";
7385 description.type = attr_description;
7386 description.u.str = "Navigation";
7387
7388 attrs[0] = &type;
7389 attrs[1] = &navigation;
7390 attrs[2] = &data;
7391 attrs[3] = &description;
7392 attrs[4] = NULL;
7393
7394 if (!this_->map)
7395 {
7396 this_->map = map_new(NULL, attrs);
7397 }
7398
7399 return this_->map;
7400 }
7401
7402 struct map_priv
7403 {
7404 struct navigation *navigation;
7405 };
7406
7407 struct map_rect_priv
7408 {
7409 struct navigation *nav;
7410 struct navigation_command *cmd;
7411 struct navigation_command *cmd_next;
7412 struct navigation_itm *itm;
7413 struct navigation_itm *itm_next;
7414 struct navigation_itm *cmd_itm;
7415 struct navigation_itm *cmd_itm_next;
7416 struct item item;
7417 enum attr_type attr_next;
7418 int ccount;
7419 int debug_idx;
7420 struct navigation_way *ways;
7421 int show_all;
7422 char *str;
7423 };
7424
7425 static int navigation_map_item_coord_get(void *priv_data, struct coord *c, int count)
7426 {
7427 struct map_rect_priv *this = priv_data;
7428
7429 if (this->ccount || !count)
7430 {
7431 // dbg(0, "NAVICG:return 001 %d %d\n", this->ccount, count);
7432 return 0;
7433 }
7434
7435 if (this->item.type == type_nav_waypoint)
7436 {
7437 if (this->itm->way.dir == 99)
7438 {
7439 dbg(0, "NAVICG:waypoint:END of seg\n");
7440 *c = this->itm->end;
7441 }
7442 else
7443 {
7444 dbg(0, "NAVICG:waypoint:start of seg\n");
7445 *c = this->itm->start;
7446 }
7447 }
7448 else
7449 {
7450 // dbg(0, "NAVICG:normal type=%s cc=%d\n", item_to_name(this->item.type), this->ccount);
7451 *c = this->itm->start;
7452 }
7453
7454 this->ccount = 1;
7455
7456 return 1;
7457 }
7458
7459 static int navigation_map_item_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
7460 {
7461 struct map_rect_priv *this_ = priv_data;
7462 struct navigation_command *cmd = this_->cmd;
7463 struct navigation_itm *itm = this_->itm;
7464 struct navigation_itm *prev = itm->prev;
7465 attr->type = attr_type;
7466
7467 if (this_->str)
7468 {
7469 g_free(this_->str);
7470 this_->str = NULL;
7471 }
7472
7473 if (cmd)
7474 {
7475 if (cmd->itm != itm)
7476 {
7477 cmd = NULL;
7478 }
7479 }
7480
7481 switch (attr_type)
7482 {
7483 case attr_navigation_short:
7484 this_->attr_next = attr_navigation_long;
7485 if (cmd)
7486 {
7487 //dbg(0, "attr_navigation_short\n");
7488 this_->str = attr->u.str = show_next_maneuvers(this_->nav, this_->cmd_itm, cmd, attr_type);
7489 return 1;
7490 }
7491 return 0;
7492 case attr_navigation_long:
7493 this_->attr_next = attr_navigation_long_exact;
7494 if (cmd)
7495 {
7496 //dbg(0, "attr_navigation_long\n");
7497 this_->str = attr->u.str = show_next_maneuvers(this_->nav, this_->cmd_itm, cmd, attr_type);
7498 return 1;
7499 }
7500 return 0;
7501 case attr_navigation_long_exact:
7502 this_->attr_next = attr_navigation_speech;
7503 if (cmd)
7504 {
7505 //dbg(0, "attr_navigation_long_exact\n");
7506 this_->str = attr->u.str = show_next_maneuvers(this_->nav, this_->cmd_itm, cmd, attr_type);
7507 return 1;
7508 }
7509 return 0;
7510 case attr_navigation_speech:
7511 this_->attr_next = attr_length;
7512 if (cmd)
7513 {
7514 //dbg(0, "attr_navigation_speech\n");
7515 //dbg(0, "Enter: attr_navigation_speech\n");
7516 this_->str = attr->u.str = show_next_maneuvers(this_->nav, this_->cmd_itm, this_->cmd, attr_type);
7517 //dbg(0, "back : attr_navigation_speech\n");
7518 return 1;
7519 }
7520 else if (this_->nav->turn_around_limit && this_->nav->turn_around == this_->nav->turn_around_limit)
7521 {
7522 if (global_turn_around_spoken == 0)
7523 {
7524 this_->str = attr->u.str = g_strdup(_("When possible, please turn around"));
7525 global_turn_around_spoken = 1;
7526 return 1;
7527 }
7528 else
7529 {
7530 return 0;
7531 }
7532 }
7533 return 0;
7534 case attr_length:
7535 this_->attr_next = attr_time;
7536 if (cmd)
7537 {
7538 attr->u.num = this_->cmd_itm->dest_length - cmd->itm->dest_length;
7539 return 1;
7540 }
7541 return 0;
7542 case attr_time:
7543 this_->attr_next = attr_destination_length;
7544 if (cmd)
7545 {
7546 attr->u.num = this_->cmd_itm->dest_time - cmd->itm->dest_time;
7547 return 1;
7548 }
7549 return 0;
7550
7551 case attr_destination_length:
7552 attr->u.num = itm->dest_length;
7553 this_->attr_next = attr_destination_time;
7554 return 1;
7555
7556 case attr_destination_time:
7557 attr->u.num = itm->dest_time;
7558 this_->attr_next = attr_street_name;
7559 return 1;
7560
7561 case attr_street_name:
7562 attr->u.str = itm->way.name1;
7563 this_->attr_next = attr_street_name_systematic;
7564 if (attr->u.str)
7565 return 1;
7566 return 0;
7567
7568 case attr_street_name_systematic:
7569 attr->u.str = itm->way.name2;
7570 this_->attr_next = attr_street_destination;
7571 if (attr->u.str)
7572 return 1;
7573 return 0;
7574
7575 case attr_street_destination:
7576 attr->u.str = itm->way.street_dest_text;
7577 this_->attr_next = attr_debug;
7578 if (attr->u.str)
7579 {
7580 return 1;
7581 }
7582 return 0;
7583
7584 case attr_debug:
7585 switch (this_->debug_idx)
7586 {
7587 case 0:
7588 this_->debug_idx++;
7589 this_->str = attr->u.str = g_strdup_printf("angle:%d (- %d)", itm->way.angle2, itm->angle_end);
7590 return 1;
7591 case 1:
7592 this_->debug_idx++;
7593 this_->str = attr->u.str = g_strdup_printf("item type:%s", item_to_name(itm->way.item.type));
7594 return 1;
7595 case 2:
7596 this_->debug_idx++;
7597 if (cmd)
7598 {
7599 this_->str = attr->u.str = g_strdup_printf("delta:%d", cmd->delta);
7600 return 1;
7601 }
7602 case 3:
7603 this_->debug_idx++;
7604 if (prev)
7605 {
7606 this_->str = attr->u.str = g_strdup_printf("prev street_name:%s", prev->way.name1);
7607 return 1;
7608 }
7609 case 4:
7610 this_->debug_idx++;
7611 if (prev)
7612 {
7613 this_->str = attr->u.str = g_strdup_printf("prev street_name_systematic:%s", prev->way.name2);
7614 return 1;
7615 }
7616 case 5:
7617 this_->debug_idx++;
7618 if (prev)
7619 {
7620 this_->str = attr->u.str = g_strdup_printf("prev angle:(%d -) %d", prev->way.angle2, prev->angle_end);
7621 return 1;
7622 }
7623 case 6:
7624 this_->debug_idx++;
7625 this_->ways = itm->way.next;
7626 if (prev)
7627 {
7628 this_->str = attr->u.str = g_strdup_printf("prev item type:%s", item_to_name(prev->way.item.type));
7629 return 1;
7630 }
7631 case 7:
7632 if (this_->ways && prev)
7633 {
7634 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);
7635 this_->ways = this_->ways->next;
7636 return 1;
7637 }
7638 this_->debug_idx++;
7639 case 8:
7640 this_->debug_idx++;
7641 if (prev)
7642 {
7643 int delta = 0;
7644 int delta_real = 0;
7645 char *reason = NULL;
7646 maneuver_required2(this_->nav, prev, itm, &delta, &delta_real, &reason);
7647 this_->str = attr->u.str = g_strdup_printf("reason:%s", reason);
7648 return 1;
7649 }
7650
7651 default:
7652 this_->attr_next = attr_none;
7653 return 0;
7654 }
7655
7656 case attr_any:
7657 while (this_->attr_next != attr_none)
7658 {
7659 if (navigation_map_item_attr_get(priv_data, this_->attr_next, attr))
7660 return 1;
7661 }
7662 return 0;
7663
7664 default:
7665 attr->type = attr_none;
7666 return 0;
7667 }
7668 }
7669
7670 static struct item_methods navigation_map_item_methods = { NULL, navigation_map_item_coord_get, NULL, navigation_map_item_attr_get, };
7671
7672 static void navigation_map_destroy(struct map_priv *priv)
7673 {
7674 g_free(priv);
7675 }
7676
7677 static void navigation_map_rect_init(struct map_rect_priv *priv)
7678 {
7679 priv->cmd_next = priv->nav->cmd_first;
7680 priv->cmd_itm_next = priv->itm_next = priv->nav->first;
7681 }
7682
7683 static struct map_rect_priv *
7684 navigation_map_rect_new(struct map_priv *priv, struct map_selection *sel)
7685 {
7686 struct navigation *nav = priv->navigation;
7687 struct map_rect_priv *ret=g_new0(struct map_rect_priv, 1);
7688 ret->nav = nav;
7689
7690 navigation_map_rect_init(ret);
7691
7692 ret->item.meth = &navigation_map_item_methods;
7693 ret->item.priv_data = ret;
7694
7695 #ifdef DEBUG
7696 ret->show_all=1;
7697 #endif
7698
7699 return ret;
7700 }
7701
7702 static void navigation_map_rect_destroy(struct map_rect_priv *priv)
7703 {
7704 g_free(priv);
7705 }
7706
7707
7708
7709 void navigation_dump_items(struct navigation *this_)
7710 {
7711 if (this_->first)
7712 {
7713 dbg(0, "NAVR:dump:=================++++++++++++================\n");
7714 struct navigation_itm *i;
7715 int count = 0;
7716
7717 i = this_->first;
7718 while (i)
7719 {
7720 count++;
7721 i = i->next;
7722 }
7723
7724 i = this_->first;
7725 while (i)
7726 {
7727 count--;
7728 dbg(0, "NAVR:dump:count=%d %p %d\n", count, i, i->way.dir);
7729 i = i->next;
7730 }
7731 dbg(0, "NAVR:dump:=================++++++++++++================\n");
7732 }
7733 }
7734
7735
7736 // -----------------------------------
7737 static int save_last_dest_count = -1;
7738 // -----------------------------------
7739
7740 static struct item *
7741 navigation_map_get_item(struct map_rect_priv *priv)
7742 {
7743 struct item *ret = &priv->item;
7744 int delta;
7745
7746 int fake_dir1;
7747 int fake_dir2;
7748
7749 dbg(0, "NAVR:ROUTE:Enter:\n");
7750 dbg(0, "NAVR:ROUTE:Enter:------------------------\n");
7751
7752 if (!priv->itm_next)
7753 {
7754 dbg(0, "NAVR:ROUTE:006:0000\n");
7755 return NULL;
7756 }
7757
7758 int stepped_to_waypoint = 0;
7759
7760 // now check if we missed a waypoint, if so -> move back to waypoint -------------------------
7761 if (priv->itm)
7762 {
7763 if (save_last_dest_count != -1)
7764 {
7765 int count_back = (save_last_dest_count - priv->itm->dest_count - 1);
7766 int count_forw = count_back;
7767 dbg(0, "NAVR:ROUTE:006:cback:%d = (%d - %d - 1)\n", count_back, save_last_dest_count, priv->itm->dest_count);
7768
7769 struct navigation_itm *i = priv->itm;
7770
7771 // go to first item to check
7772 while (count_back > 0)
7773 {
7774 count_back--;
7775 if (i->prev)
7776 {
7777 i = i->prev;
7778 dbg(0, "NAVR:ROUTE:006:cback:stepping back to item #%d dir=%d\n", i->dest_count, i->way.dir);
7779 }
7780 }
7781
7782 // now step forward until waypoint found, or just skip the whole thing if we dont find any waypoint
7783 while (count_forw > 0)
7784 {
7785 if (i)
7786 {
7787 dbg(0, "NAVR:ROUTE:006:cback:stepping forw to item #%d dir=%d\n", i->dest_count, i->way.dir);
7788
7789 if ((i->way.dir == 99) || (i->way.dir == -99))
7790 {
7791 // found a waypoint
7792 priv->itm = i;
7793 stepped_to_waypoint = 1;
7794
7795 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);
7796
7797 break;
7798 }
7799
7800 count_forw--;
7801 if (i->next)
7802 {
7803 i = i->next;
7804 }
7805 }
7806 }
7807
7808 }
7809 }
7810 // now check if we missed a waypoint, if so -> move back to waypoint -------------------------
7811
7812
7813 if (priv->itm)
7814 {
7815 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);
7816 fake_dir1 = priv->itm->way.dir;
7817 save_last_dest_count = priv->itm->dest_count;
7818 }
7819 else
7820 {
7821 dbg(0, "NAVR:ROUTE:006:8888:1: NULL\n");
7822 fake_dir1 = 0;
7823 save_last_dest_count = -1;
7824 }
7825
7826 if (stepped_to_waypoint != 1)
7827 {
7828 priv->itm = priv->itm_next;
7829 }
7830
7831
7832 fake_dir2 = priv->itm->way.dir;
7833 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);
7834 priv->cmd = priv->cmd_next;
7835 priv->cmd_itm = priv->cmd_itm_next;
7836
7837 if ((priv->itm->way.dir == 99) || (priv->itm->way.dir == -99))
7838 {
7839 // return fake waypoint item!! ---------
7840 ret->type = type_nav_waypoint;
7841 ret->id_lo = priv->itm->dest_count;
7842 priv->ccount = 0;
7843
7844 priv->itm_next = priv->itm->next;
7845
7846 dbg(0, "NAVR:ROUTE:006:fake:%s dir=%d ,,,,,\n", item_to_name(ret->type), priv->itm->way.dir);
7847
7848 return ret;
7849 }
7850
7851
7852
7853 // navigation_dump_items(priv->nav);
7854
7855 if (!priv->cmd)
7856 {
7857 dbg(0, "NAVR:ROUTE:006:1111\n");
7858 return NULL;
7859 }
7860
7861
7862 if (!priv->show_all && priv->itm->prev != NULL)
7863 {
7864 dbg(0, "NAVR:ROUTE:006:112a\n");
7865 priv->itm = priv->cmd->itm;
7866 }
7867
7868 priv->itm_next = priv->itm->next;
7869
7870 if (priv->itm->prev)
7871 {
7872 ret->type = type_nav_none;
7873 }
7874 else
7875 {
7876 ret->type = type_nav_position;
7877 }
7878
7879 dbg(0, "NAVR:ROUTE:006:2222 %p dir=%d\n", priv->itm, priv->itm->way.dir);
7880
7881 if (priv->cmd->itm == priv->itm)
7882 {
7883
7884 dbg(0, "NAVR:ROUTE:006:3333 %p dir=%d %p\n", priv->itm, priv->itm->way.dir, route_get_map(global_navit->route));
7885 // item_dump_coords(priv->itm, route_get_map(global_navit->route));
7886
7887 priv->cmd_itm_next = priv->cmd->itm;
7888 priv->cmd_next = priv->cmd->next;
7889
7890 if (priv->cmd_itm_next && !priv->cmd_itm_next->next)
7891 {
7892 ret->type = type_nav_destination;
7893 }
7894 else
7895 {
7896 if (priv->itm && priv->itm->prev && !(priv->itm->way.flags & NAVIT_AF_ROUNDABOUT) && (priv->itm->prev->way.flags & NAVIT_AF_ROUNDABOUT))
7897 {
7898 enum item_type r = type_none, l = type_none;
7899 switch (((180 + 22) - priv->cmd->roundabout_delta) / 45)
7900 {
7901 case 0:
7902 case 1:
7903 r = type_nav_roundabout_r1;
7904 l = type_nav_roundabout_l7;
7905 break;
7906 case 2:
7907 r = type_nav_roundabout_r2;
7908 l = type_nav_roundabout_l6;
7909 break;
7910 case 3:
7911 r = type_nav_roundabout_r3;
7912 l = type_nav_roundabout_l5;
7913 break;
7914 case 4:
7915 r = type_nav_roundabout_r4;
7916 l = type_nav_roundabout_l4;
7917 break;
7918 case 5:
7919 r = type_nav_roundabout_r5;
7920 l = type_nav_roundabout_l3;
7921 break;
7922 case 6:
7923 r = type_nav_roundabout_r6;
7924 l = type_nav_roundabout_l2;
7925 break;
7926 case 7:
7927 r = type_nav_roundabout_r7;
7928 l = type_nav_roundabout_l1;
7929 break;
7930 case 8:
7931 r = type_nav_roundabout_r8;
7932 l = type_nav_roundabout_l8;
7933 break;
7934 }
7935 // dbg(0, "delta %d\n", priv->cmd->delta);
7936
7937 if (priv->cmd->delta < 0)
7938 {
7939 ret->type = l;
7940 }
7941 else
7942 {
7943 ret->type = r;
7944 }
7945 }
7946 else
7947 {
7948 delta = priv->cmd->delta;
7949 if (delta < 0)
7950 {
7951 delta = -delta;
7952 if (delta < 45)
7953 ret->type = type_nav_left_1;
7954 else if (delta < 105)
7955 ret->type = type_nav_left_2;
7956 else if (delta < 165)
7957 ret->type = type_nav_left_3;
7958 else
7959 ret->type = type_none;
7960 }
7961 else if (delta > 0)
7962 {
7963 if (delta < 45)
7964 ret->type = type_nav_right_1;
7965 else if (delta < 105)
7966 ret->type = type_nav_right_2;
7967 else if (delta < 165)
7968 ret->type = type_nav_right_3;
7969 else
7970 ret->type = type_none;
7971 }
7972 else // delta == 0
7973 {
7974 ret->type = type_nav_straight;
7975 }
7976 }
7977 }
7978 }
7979
7980 priv->ccount = 0;
7981 priv->debug_idx = 0;
7982 priv->attr_next = attr_navigation_short;
7983
7984 ret->id_lo = priv->itm->dest_count;
7985
7986 // 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);
7987
7988
7989 // check for "turn around" and return "type_nav_turnaround" !! ---------------
7990 if ((priv->nav->turn_around && priv->nav->turn_around == priv->nav->turn_around_limit) && (ret->type == type_nav_position))
7991 {
7992 // dbg(0, "priv->itm->dest_count=%d\n", priv->itm->dest_count);
7993 ret->type = type_nav_turnaround_right;
7994 }
7995 // check for "turn around" and return "type_nav_turnaround" !! ---------------
7996
7997 // dbg(0, "NAVR:ROUTE:007a:%s ,,,,, priv->itm->dest_count=%d\n", item_to_name(ret->type), priv->itm->dest_count);
7998
7999 return ret;
8000 }
8001
8002 static struct item *
8003 navigation_map_get_item_byid(struct map_rect_priv *priv, int id_hi, int id_lo)
8004 {
8005 struct item *ret;
8006 navigation_map_rect_init(priv);
8007 while ((ret = navigation_map_get_item(priv)))
8008 {
8009 if (ret->id_hi == id_hi && ret->id_lo == id_lo)
8010 return ret;
8011 }
8012 return NULL;
8013 }
8014
8015 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, };
8016
8017 struct map_priv *
8018 navigation_map_new(struct map_methods *meth, struct attr **attrs, struct callback_list *cbl)
8019 {
8020 struct map_priv *ret;
8021 struct attr *navigation_attr;
8022
8023 navigation_attr = attr_search(attrs, NULL, attr_navigation);
8024
8025 if (!navigation_attr)
8026 {
8027 return NULL;
8028 }
8029
8030 ret=g_new0(struct map_priv, 1);
8031 *meth = navigation_map_meth;
8032 ret->navigation = navigation_attr->u.navigation;
8033
8034 level_static_for_bicycle[0] = 22; // in meters
8035 level_static_for_bicycle[1] = 100; // in meters
8036 level_static_for_bicycle[2] = -1; // dont announce
8037
8038 return ret;
8039 }
8040
8041 void navigation_set_route(struct navigation *this_, struct route *route)
8042 {
8043 __F_START__
8044
8045 struct attr callback;
8046 this_->route = route;
8047 this_->route_cb = callback_new_attr_1(callback_cast(navigation_update), attr_route_status, this_);
8048 callback_add_names(this_->route_cb, "navigation_set_route", "navigation_update");
8049 callback.type = attr_callback;
8050 callback.u.callback = this_->route_cb;
8051 route_add_attr(route, &callback);
8052
8053 __F_END__
8054 }
8055
8056 void navigation_init(void)
8057 {
8058 #ifdef PLUGSSS
8059 plugin_register_map_type("navigation", navigation_map_new);
8060 #endif
8061 }
8062
8063

   
Visit the ZANavi Wiki