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

Contents of /navit/navit/navigation.c

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki