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

Contents of /navit/navit/navigation.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (show annotations) (download)
Fri Oct 28 21:19:04 2011 UTC (12 years, 5 months ago) by zoff99
File MIME type: text/plain
File size: 63253 byte(s)
import files
1 /**
2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2008 Navit Team
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 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <math.h>
24 #include <ctype.h>
25 #include <glib.h>
26 #include "debug.h"
27 #include "profile.h"
28 #include "navigation.h"
29 #include "coord.h"
30 #include "item.h"
31 #include "route.h"
32 #include "transform.h"
33 #include "mapset.h"
34 #include "projection.h"
35 #include "map.h"
36 #include "navit.h"
37 #include "callback.h"
38 #include "speech.h"
39 #include "vehicleprofile.h"
40 #include "plugin.h"
41 #include "navit_nls.h"
42
43 /* #define DEBUG */
44
45 static int roundabout_extra_length=50;
46
47
48 struct suffix {
49 char *fullname;
50 char *abbrev;
51 int sex;
52 } suffixes[]= {
53 {"weg",NULL,1},
54 {"platz","pl.",1},
55 {"ring",NULL,1},
56 {"allee",NULL,2},
57 {"gasse",NULL,2},
58 {"straße","str.",2},
59 {"strasse",NULL,2},
60 };
61
62 struct navigation {
63 struct route *route;
64 struct map *map;
65 struct item_hash *hash;
66 struct vehicleprofile *vehicleprofile;
67 struct navigation_itm *first;
68 struct navigation_itm *last;
69 struct navigation_command *cmd_first;
70 struct navigation_command *cmd_last;
71 struct callback_list *callback_speech;
72 struct callback_list *callback;
73 struct navit *navit;
74 struct speech *speech;
75 int level_last;
76 struct item item_last;
77 int turn_around;
78 int turn_around_limit;
79 int distance_turn;
80 struct callback *route_cb;
81 int announce[route_item_last-route_item_first+1][3];
82 int tell_street_name;
83 int delay;
84 int curr_delay;
85 };
86
87 int distances[]={1,2,3,4,5,10,25,50,75,100,150,200,250,300,400,500,750,-1};
88
89
90 struct navigation_command {
91 struct navigation_itm *itm;
92 struct navigation_command *next;
93 struct navigation_command *prev;
94 int delta;
95 int roundabout_delta;
96 int length;
97 };
98
99 static void navigation_flush(struct navigation *this_);
100
101 /**
102 * @brief Calculates the delta between two angles
103 * @param angle1 The first angle
104 * @param angle2 The second angle
105 * @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
106 */
107
108 static int
109 angle_delta(int angle1, int angle2)
110 {
111 int delta=angle2-angle1;
112 if (delta <= -180)
113 delta+=360;
114 if (delta > 180)
115 delta-=360;
116 return delta;
117 }
118
119 static int
120 angle_median(int angle1, int angle2)
121 {
122 int delta=angle_delta(angle1, angle2);
123 int ret=angle1+delta/2;
124 if (ret < 0)
125 ret+=360;
126 if (ret > 360)
127 ret-=360;
128 return ret;
129 }
130
131 static int
132 angle_opposite(int angle)
133 {
134 return ((angle+180)%360);
135 }
136
137 int
138 navigation_get_attr(struct navigation *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter)
139 {
140 struct map_rect *mr;
141 struct item *item;
142 dbg(1,"enter %s\n", attr_to_name(type));
143 switch (type) {
144 case attr_map:
145 attr->u.map=this_->map;
146 break;
147 case attr_item_type:
148 case attr_length:
149 case attr_navigation_speech:
150 mr=map_rect_new(this_->map, NULL);
151 while ((item=map_rect_get_item(mr))) {
152 if (item->type != type_nav_none && item->type != type_nav_position) {
153 if (type == attr_item_type)
154 attr->u.item_type=item->type;
155 else {
156 if (!item_attr_get(item, type, attr))
157 item=NULL;
158 }
159 break;
160 }
161 }
162 map_rect_destroy(mr);
163 if (!item)
164 return 0;
165 break;
166 default:
167 return 0;
168 }
169 attr->type=type;
170 return 1;
171 }
172
173 int
174 navigation_set_attr(struct navigation *this_, struct attr *attr)
175 {
176 switch (attr->type) {
177 case attr_speech:
178 this_->speech=attr->u.speech;
179 return 1;
180 default:
181 return 0;
182 }
183 }
184
185
186 struct navigation *
187 navigation_new(struct attr *parent, struct attr **attrs)
188 {
189 int i,j;
190 struct attr * attr;
191 struct navigation *ret=g_new0(struct navigation, 1);
192 ret->hash=item_hash_new();
193 ret->callback=callback_list_new();
194 ret->callback_speech=callback_list_new();
195 ret->level_last=-2;
196 ret->distance_turn=50;
197 ret->turn_around_limit=3;
198 ret->navit=parent->u.navit;
199 ret->tell_street_name=1;
200
201 for (j = 0 ; j <= route_item_last-route_item_first ; j++) {
202 for (i = 0 ; i < 3 ; i++) {
203 ret->announce[j][i]=-1;
204 }
205 }
206
207 if ((attr=attr_search(attrs, NULL, attr_tell_street_name))) {
208 ret->tell_street_name = attr->u.num;
209 }
210 if ((attr=attr_search(attrs, NULL, attr_delay))) {
211 ret->delay = attr->u.num;
212 }
213
214 return ret;
215 }
216
217 int
218 navigation_set_announce(struct navigation *this_, enum item_type type, int *level)
219 {
220 int i;
221 if (type < route_item_first || type > route_item_last) {
222 dbg(0,"street type %d out of range [%d,%d]", type, route_item_first, route_item_last);
223 return 0;
224 }
225 for (i = 0 ; i < 3 ; i++)
226 this_->announce[type-route_item_first][i]=level[i];
227 return 1;
228 }
229
230 static int
231 navigation_get_announce_level(struct navigation *this_, enum item_type type, int dist)
232 {
233 int i;
234
235 if (type < route_item_first || type > route_item_last)
236 return -1;
237 for (i = 0 ; i < 3 ; i++) {
238 if (dist <= this_->announce[type-route_item_first][i])
239 return i;
240 }
241 return i;
242 }
243
244
245 /**
246 * @brief Holds a way that one could possibly drive from a navigation item
247 */
248 struct navigation_way {
249 struct navigation_way *next; /**< Pointer to a linked-list of all navigation_ways from this navigation item */
250 short dir; /**< The direction -1 or 1 of the way */
251 short angle2; /**< The angle one has to steer to drive from the old item to this street */
252 int flags; /**< The flags of the way */
253 struct item item; /**< The item of the way */
254 char *name1;
255 char *name2;
256 };
257
258 struct navigation_itm {
259 struct navigation_way way;
260 int angle_end;
261 struct coord start,end;
262 int time;
263 int length;
264 int speed;
265 int dest_time;
266 int dest_length;
267 int told; /**< Indicates if this item's announcement has been told earlier and should not be told again*/
268 int streetname_told; /**< Indicates if this item's streetname has been told in speech navigation*/
269 int dest_count;
270 struct navigation_itm *next;
271 struct navigation_itm *prev;
272 };
273
274 static int is_way_allowed(struct navigation *nav, struct navigation_way *way, int mode);
275
276 static int
277 navigation_get_announce_level_cmd(struct navigation *this_, struct navigation_itm *itm, struct navigation_command *cmd, int distance)
278 {
279 int level2,level=navigation_get_announce_level(this_, itm->way.item.type, distance);
280 if (this_->cmd_first->itm->prev) {
281 level2=navigation_get_announce_level(this_, cmd->itm->prev->way.item.type, distance);
282 if (level2 > level)
283 level=level2;
284 }
285 return level;
286 }
287
288 /* 0=N,90=E */
289 static int
290 road_angle(struct coord *c1, struct coord *c2, int dir)
291 {
292 int ret=transform_get_angle_delta(c1, c2, dir);
293 dbg(1, "road_angle(0x%x,0x%x - 0x%x,0x%x)=%d\n", c1->x, c1->y, c2->x, c2->y, ret);
294 return ret;
295 }
296
297 static char
298 *get_count_str(int n)
299 {
300 switch (n) {
301 case 0:
302 /* TRANSLATORS: the following counts refer to streets */
303 return _("zeroth"); // Not sure if this exists, neither if it will ever be needed
304 case 1:
305 return _("first");
306 case 2:
307 return _("second");
308 case 3:
309 return _("third");
310 case 4:
311 return _("fourth");
312 case 5:
313 return _("fifth");
314 case 6:
315 return _("sixth");
316 default:
317 return NULL;
318 }
319 }
320
321 static char
322 *get_exit_count_str(int n)
323 {
324 switch (n) {
325 case 0:
326 /* TRANSLATORS: the following counts refer to roundabout exits */
327 return _("zeroth exit"); // Not sure if this exists, neither if it will ever be needed
328 case 1:
329 return _("first exit");
330 case 2:
331 return _("second exit");
332 case 3:
333 return _("third exit");
334 case 4:
335 return _("fourth exit");
336 case 5:
337 return _("fifth exit");
338 case 6:
339 return _("sixth exit");
340 default:
341 return NULL;
342 }
343 }
344 static int
345 round_distance(int dist)
346 {
347 if (dist < 100) {
348 dist=(dist+5)/10;
349 return dist*10;
350 }
351 if (dist < 250) {
352 dist=(dist+13)/25;
353 return dist*25;
354 }
355 if (dist < 500) {
356 dist=(dist+25)/50;
357 return dist*50;
358 }
359 if (dist < 1000) {
360 dist=(dist+50)/100;
361 return dist*100;
362 }
363 if (dist < 5000) {
364 dist=(dist+50)/100;
365 return dist*100;
366 }
367 if (dist < 100000) {
368 dist=(dist+500)/1000;
369 return dist*1000;
370 }
371 dist=(dist+5000)/10000;
372 return dist*10000;
373 }
374
375 static int
376 round_for_vocabulary(int vocabulary, int dist, int factor)
377 {
378 if (!(vocabulary & 256)) {
379 if (factor != 1)
380 dist=(dist+factor/2)/factor;
381 } else
382 factor=1;
383 if (!(vocabulary & 255)) {
384 int i=0,d=0,m=0;
385 while (distances[i] > 0) {
386 if (!i || abs(distances[i]-dist) <= d) {
387 d=abs(distances[i]-dist);
388 m=i;
389 }
390 if (distances[i] > dist)
391 break;
392 i++;
393 }
394 dbg(0,"converted %d to %d with factor %d\n",dist,distances[m],factor);
395 dist=distances[m];
396 }
397 return dist*factor;
398 }
399
400 static int
401 vocabulary_last(int vocabulary)
402 {
403 int i=0;
404 if (vocabulary == 65535)
405 return 1000;
406 while (distances[i] > 0)
407 i++;
408 return distances[i-1];
409 }
410
411 static char *
412 get_distance(struct navigation *nav, int dist, enum attr_type type, int is_length)
413 {
414 int imperial=0,vocabulary=65535;
415 struct attr attr;
416
417 if (type == attr_navigation_long) {
418 if (is_length)
419 return g_strdup_printf(_("%d m"), dist);
420 else
421 return g_strdup_printf(_("in %d m"), dist);
422 }
423 if (navit_get_attr(nav->navit, attr_imperial, &attr, NULL))
424 imperial=attr.u.num;
425 if (nav->speech && speech_get_attr(nav->speech, attr_vocabulary_distances, &attr, NULL))
426 vocabulary=attr.u.num;
427 if (imperial) {
428 if (dist*FEET_PER_METER < vocabulary_last(vocabulary)) {
429 dist=round_for_vocabulary(vocabulary, dist*FEET_PER_METER, 1);
430 if (is_length)
431 return g_strdup_printf(_("%d feet"), dist);
432 else
433 return g_strdup_printf(_("in %d feet"), dist);
434 }
435 } else {
436 if (dist < vocabulary_last(vocabulary)) {
437 dist=round_for_vocabulary(vocabulary, dist, 1);
438 if (is_length)
439 return g_strdup_printf(_("%d meters"), dist);
440 else
441 return g_strdup_printf(_("in %d meters"), dist);
442 }
443 }
444 if (imperial)
445 dist=round_for_vocabulary(vocabulary, dist*FEET_PER_METER*1000/FEET_PER_MILE, 1000);
446 else
447 dist=round_for_vocabulary(vocabulary, dist, 1000);
448 if (dist < 5000) {
449 int rem=(dist/100)%10;
450 if (rem) {
451 if (imperial) {
452 if (is_length)
453 return g_strdup_printf(_("%d.%d miles"), dist/1000, rem);
454 else
455 return g_strdup_printf(_("in %d.%d miles"), dist/1000, rem);
456 } else {
457 if (is_length)
458 return g_strdup_printf(_("%d.%d kilometers"), dist/1000, rem);
459 else
460 return g_strdup_printf(_("in %d.%d kilometers"), dist/1000, rem);
461 }
462 }
463 }
464 if (imperial) {
465 if (is_length)
466 return g_strdup_printf(ngettext("one mile","%d miles", dist/1000), dist/1000);
467 else
468 return g_strdup_printf(ngettext("in one mile","in %d miles", dist/1000), dist/1000);
469 } else {
470 if (is_length)
471 return g_strdup_printf(ngettext("one kilometer","%d kilometers", dist/1000), dist/1000);
472 else
473 return g_strdup_printf(ngettext("in one kilometer","in %d kilometers", dist/1000), dist/1000);
474 }
475 }
476
477
478 /**
479 * @brief This calculates the angle with which an item starts or ends
480 *
481 * This function can be used to get the angle an item (from a route graph map)
482 * starts or ends with. Note that the angle will point towards the inner of
483 * the item.
484 *
485 * This is meant to be used with items from a route graph map
486 * With other items this will probably not be optimal...
487 *
488 * @param w The way which should be calculated
489 */
490 static void
491 calculate_angle(struct navigation_way *w)
492 {
493 struct coord cbuf[2];
494 struct item *ritem; // the "real" item
495 struct coord c;
496 struct map_rect *mr;
497 struct attr attr;
498
499 w->angle2=361;
500 mr = map_rect_new(w->item.map, NULL);
501 if (!mr)
502 return;
503
504 ritem = map_rect_get_item_byid(mr, w->item.id_hi, w->item.id_lo);
505 if (!ritem) {
506 dbg(1,"Item from segment not found on map!\n");
507 map_rect_destroy(mr);
508 return;
509 }
510
511 if (ritem->type < type_line || ritem->type >= type_area) {
512 map_rect_destroy(mr);
513 return;
514 }
515 if (item_attr_get(ritem, attr_flags, &attr))
516 w->flags=attr.u.num;
517 else
518 w->flags=0;
519 if (item_attr_get(ritem, attr_street_name, &attr))
520 w->name1=map_convert_string(ritem->map,attr.u.str);
521 else
522 w->name1=NULL;
523 if (item_attr_get(ritem, attr_street_name_systematic, &attr))
524 w->name2=map_convert_string(ritem->map,attr.u.str);
525 else
526 w->name2=NULL;
527
528 if (w->dir < 0) {
529 if (item_coord_get(ritem, cbuf, 2) != 2) {
530 dbg(1,"Using calculate_angle() with a less-than-two-coords-item?\n");
531 map_rect_destroy(mr);
532 return;
533 }
534
535 while (item_coord_get(ritem, &c, 1)) {
536 cbuf[0] = cbuf[1];
537 cbuf[1] = c;
538 }
539
540 } else {
541 if (item_coord_get(ritem, cbuf, 2) != 2) {
542 dbg(1,"Using calculate_angle() with a less-than-two-coords-item?\n");
543 map_rect_destroy(mr);
544 return;
545 }
546 c = cbuf[0];
547 cbuf[0] = cbuf[1];
548 cbuf[1] = c;
549 }
550
551 map_rect_destroy(mr);
552
553 w->angle2=road_angle(&cbuf[1],&cbuf[0],0);
554 }
555
556 /**
557 * @brief Returns the time (in seconds) one will drive between two navigation items
558 *
559 * This function returns the time needed to drive between two items, including both of them,
560 * in seconds.
561 *
562 * @param from The first item
563 * @param to The last item
564 * @return The travel time in seconds, or -1 on error
565 */
566 static int
567 navigation_time(struct navigation_itm *from, struct navigation_itm *to)
568 {
569 struct navigation_itm *cur;
570 int time;
571
572 time = 0;
573 cur = from;
574 while (cur) {
575 time += cur->time;
576
577 if (cur == to) {
578 break;
579 }
580 cur = cur->next;
581 }
582
583 if (!cur) {
584 return -1;
585 }
586
587 return time;
588 }
589
590 /**
591 * @brief Clears the ways one can drive from itm
592 *
593 * @param itm The item that should have its ways cleared
594 */
595 static void
596 navigation_itm_ways_clear(struct navigation_itm *itm)
597 {
598 struct navigation_way *c,*n;
599
600 c = itm->way.next;
601 while (c) {
602 n = c->next;
603 map_convert_free(c->name1);
604 map_convert_free(c->name2);
605 g_free(c);
606 c = n;
607 }
608
609 itm->way.next = NULL;
610 }
611
612 /**
613 * @brief Updates the ways one can drive from itm
614 *
615 * This updates the list of possible ways to drive to from itm. The item "itm" is on
616 * and the next navigation item are excluded.
617 *
618 * @param itm The item that should be updated
619 * @param graph_map The route graph's map that these items are on
620 */
621 static void
622 navigation_itm_ways_update(struct navigation_itm *itm, struct map *graph_map)
623 {
624 struct map_selection coord_sel;
625 struct map_rect *g_rect; // Contains a map rectangle from the route graph's map
626 struct item *i,*sitem;
627 struct attr sitem_attr,direction_attr;
628 struct navigation_way *w,*l;
629
630 navigation_itm_ways_clear(itm);
631
632 // These values cause the code in route.c to get us only the route graph point and connected segments
633 coord_sel.next = NULL;
634 coord_sel.u.c_rect.lu = itm->start;
635 coord_sel.u.c_rect.rl = itm->start;
636 // the selection's order is ignored
637
638 g_rect = map_rect_new(graph_map, &coord_sel);
639
640 i = map_rect_get_item(g_rect);
641 if (!i || i->type != type_rg_point) { // probably offroad?
642 return ;
643 }
644
645 w = NULL;
646
647 while (1) {
648 i = map_rect_get_item(g_rect);
649
650 if (!i) {
651 break;
652 }
653
654 if (i->type != type_rg_segment) {
655 continue;
656 }
657
658 if (!item_attr_get(i,attr_street_item,&sitem_attr)) {
659 dbg(1, "Got no street item for route graph item in entering_straight()\n");
660 continue;
661 }
662
663 if (!item_attr_get(i,attr_direction,&direction_attr)) {
664 continue;
665 }
666
667 sitem = sitem_attr.u.item;
668 if (sitem->type == type_street_turn_restriction_no || sitem->type == type_street_turn_restriction_only)
669 continue;
670
671 if (item_is_equal(itm->way.item,*sitem) || ((itm->prev) && item_is_equal(itm->prev->way.item,*sitem))) {
672 continue;
673 }
674
675 l = w;
676 w = g_new(struct navigation_way, 1);
677 w->dir = direction_attr.u.num;
678 w->item = *sitem;
679 w->next = l;
680 calculate_angle(w);
681 }
682
683 map_rect_destroy(g_rect);
684
685 itm->way.next = w;
686 }
687
688 static void
689 navigation_destroy_itms_cmds(struct navigation *this_, struct navigation_itm *end)
690 {
691 struct navigation_itm *itm;
692 struct navigation_command *cmd;
693 dbg(2,"enter this_=%p this_->first=%p this_->cmd_first=%p end=%p\n", this_, this_->first, this_->cmd_first, end);
694 if (this_->cmd_first)
695 dbg(2,"this_->cmd_first->itm=%p\n", this_->cmd_first->itm);
696 while (this_->first && this_->first != end) {
697 itm=this_->first;
698 dbg(3,"destroying %p\n", itm);
699 item_hash_remove(this_->hash, &itm->way.item);
700 this_->first=itm->next;
701 if (this_->first)
702 this_->first->prev=NULL;
703 if (this_->cmd_first && this_->cmd_first->itm == itm->next) {
704 cmd=this_->cmd_first;
705 this_->cmd_first=cmd->next;
706 if (cmd->next) {
707 cmd->next->prev = NULL;
708 }
709 g_free(cmd);
710 }
711 map_convert_free(itm->way.name1);
712 map_convert_free(itm->way.name2);
713 navigation_itm_ways_clear(itm);
714 g_free(itm);
715 }
716 if (! this_->first)
717 this_->last=NULL;
718 if (! this_->first && end)
719 dbg(0,"end wrong\n");
720 dbg(2,"ret this_->first=%p this_->cmd_first=%p\n",this_->first, this_->cmd_first);
721 }
722
723 static void
724 navigation_itm_update(struct navigation_itm *itm, struct item *ritem)
725 {
726 struct attr length, time, speed;
727
728 if (! item_attr_get(ritem, attr_length, &length)) {
729 dbg(0,"no length\n");
730 return;
731 }
732 if (! item_attr_get(ritem, attr_time, &time)) {
733 dbg(0,"no time\n");
734 return;
735 }
736 if (! item_attr_get(ritem, attr_speed, &speed)) {
737 dbg(0,"no time\n");
738 return;
739 }
740
741 dbg(1,"length=%d time=%d speed=%d\n", length.u.num, time.u.num, speed.u.num);
742 itm->length=length.u.num;
743 itm->time=time.u.num;
744 itm->speed=speed.u.num;
745 }
746
747 /**
748 * @brief This check if an item is part of a roundabout
749 *
750 * @param itm The item to be checked
751 * @return True if the item is part of a roundabout
752 */
753 static int
754 check_roundabout(struct navigation_itm *itm, struct map *graph_map)
755 {
756 struct map_selection coord_sel;
757 struct map_rect *g_rect; // Contains a map rectangle from the route graph's map
758 struct item *i,*sitem;
759 struct attr sitem_attr,flags_attr;
760
761 // These values cause the code in route.c to get us only the route graph point and connected segments
762 coord_sel.next = NULL;
763 coord_sel.u.c_rect.lu = itm->start;
764 coord_sel.u.c_rect.rl = itm->start;
765 // the selection's order is ignored
766
767 g_rect = map_rect_new(graph_map, &coord_sel);
768
769 i = map_rect_get_item(g_rect);
770 if (!i || i->type != type_rg_point) { // probably offroad?
771 map_rect_destroy(g_rect);
772 return 0;
773 }
774
775 while (1) {
776 i = map_rect_get_item(g_rect);
777
778 if (!i) {
779 break;
780 }
781
782 if (i->type != type_rg_segment) {
783 continue;
784 }
785
786 if (!item_attr_get(i,attr_street_item,&sitem_attr)) {
787 continue;
788 }
789
790 sitem = sitem_attr.u.item;
791 if (item_is_equal(itm->way.item,*sitem)) {
792 if (item_attr_get(i,attr_flags,&flags_attr) && (flags_attr.u.num & AF_ROUNDABOUT)) {
793 map_rect_destroy(g_rect);
794 return 1;
795 }
796 }
797 }
798
799 map_rect_destroy(g_rect);
800 return 0;
801 }
802
803 static struct navigation_itm *
804 navigation_itm_new(struct navigation *this_, struct item *ritem)
805 {
806 struct navigation_itm *ret=g_new0(struct navigation_itm, 1);
807 int i=0;
808 struct item *sitem;
809 struct map *graph_map = NULL;
810 struct attr street_item,direction,route_attr;
811 struct map_rect *mr;
812 struct attr attr;
813 struct coord c[5];
814
815 if (ritem) {
816 ret->streetname_told=0;
817 if (! item_attr_get(ritem, attr_street_item, &street_item)) {
818 dbg(1, "no street item\n");
819 g_free(ret);
820 ret = NULL;
821 return ret;
822 }
823 if (item_attr_get(ritem, attr_direction, &direction))
824 ret->way.dir=direction.u.num;
825 else
826 ret->way.dir=0;
827
828 sitem=street_item.u.item;
829 ret->way.item=*sitem;
830 item_hash_insert(this_->hash, sitem, ret);
831 mr=map_rect_new(sitem->map, NULL);
832 if (! (sitem=map_rect_get_item_byid(mr, sitem->id_hi, sitem->id_lo)))
833 return NULL;
834 if (item_attr_get(sitem, attr_street_name, &attr))
835 ret->way.name1=map_convert_string(sitem->map,attr.u.str);
836 if (item_attr_get(sitem, attr_street_name_systematic, &attr))
837 ret->way.name2=map_convert_string(sitem->map,attr.u.str);
838 navigation_itm_update(ret, ritem);
839
840 while (item_coord_get(ritem, &c[i], 1)) {
841 dbg(1, "coord %d 0x%x 0x%x\n", i, c[i].x ,c[i].y);
842
843 if (i < 4)
844 i++;
845 else {
846 c[2]=c[3];
847 c[3]=c[4];
848 }
849 }
850 dbg(1,"count=%d\n", i);
851 i--;
852
853 ret->way.angle2=road_angle(&c[0], &c[1], 0);
854 ret->angle_end=road_angle(&c[i-1], &c[i], 0);
855
856 ret->start=c[0];
857 ret->end=c[i];
858
859 item_attr_get(ritem, attr_route, &route_attr);
860 graph_map = route_get_graph_map(route_attr.u.route);
861 if (check_roundabout(ret, graph_map)) {
862 ret->way.flags |= AF_ROUNDABOUT;
863 }
864
865 dbg(1,"i=%d start %d end %d '%s' '%s'\n", i, ret->way.angle2, ret->angle_end, ret->way.name1, ret->way.name2);
866 map_rect_destroy(mr);
867 } else {
868 if (this_->last)
869 ret->start=ret->end=this_->last->end;
870 }
871 if (! this_->first)
872 this_->first=ret;
873 if (this_->last) {
874 this_->last->next=ret;
875 ret->prev=this_->last;
876 if (graph_map) {
877 navigation_itm_ways_update(ret,graph_map);
878 }
879 }
880 dbg(1,"ret=%p\n", ret);
881 this_->last=ret;
882 return ret;
883 }
884
885 /**
886 * @brief Counts how many times a driver could turn right/left
887 *
888 * This function counts how many times the driver theoretically could
889 * turn right/left between two navigation items, not counting the final
890 * turn itself.
891 *
892 * @param from The navigation item which should form the start
893 * @param to The navigation item which should form the end
894 * @param direction Set to < 0 to count turns to the left >= 0 for turns to the right
895 * @return The number of possibilities to turn or -1 on error
896 */
897 static int
898 count_possible_turns(struct navigation *nav, struct navigation_itm *from, struct navigation_itm *to, int direction)
899 {
900 int count;
901 struct navigation_itm *curr;
902 struct navigation_way *w;
903
904 count = 0;
905 curr = from->next;
906 while (curr && (curr != to)) {
907 w = curr->way.next;
908
909 while (w) {
910 if (is_way_allowed(nav, w, 4)) {
911 if (direction < 0) {
912 if (angle_delta(curr->prev->angle_end, w->angle2) < 0) {
913 count++;
914 break;
915 }
916 } else {
917 if (angle_delta(curr->prev->angle_end, w->angle2) > 0) {
918 count++;
919 break;
920 }
921 }
922 }
923 w = w->next;
924 }
925 curr = curr->next;
926 }
927
928 if (!curr) { // from does not lead to to?
929 return -1;
930 }
931
932 return count;
933 }
934
935 /**
936 * @brief Calculates distance and time to the destination
937 *
938 * This function calculates the distance and the time to the destination of a
939 * navigation. If incr is set, this is only calculated for the first navigation
940 * item, which is a lot faster than re-calculation the whole destination, but works
941 * only if the rest of the navigation already has been calculated.
942 *
943 * @param this_ The navigation whose destination / time should be calculated
944 * @param incr Set this to true to only calculate the first item. See description.
945 */
946 static void
947 calculate_dest_distance(struct navigation *this_, int incr)
948 {
949 int len=0, time=0, count=0;
950 struct navigation_itm *next,*itm=this_->last;
951 dbg(1, "enter this_=%p, incr=%d\n", this_, incr);
952 if (incr) {
953 if (itm) {
954 dbg(2, "old values: (%p) time=%d lenght=%d\n", itm, itm->dest_length, itm->dest_time);
955 } else {
956 dbg(2, "old values: itm is null\n");
957 }
958 itm=this_->first;
959 next=itm->next;
960 dbg(2, "itm values: time=%d lenght=%d\n", itm->length, itm->time);
961 dbg(2, "next values: (%p) time=%d lenght=%d\n", next, next->dest_length, next->dest_time);
962 itm->dest_length=next->dest_length+itm->length;
963 itm->dest_count=next->dest_count+1;
964 itm->dest_time=next->dest_time+itm->time;
965 dbg(2, "new values: time=%d lenght=%d\n", itm->dest_length, itm->dest_time);
966 return;
967 }
968 while (itm) {
969 len+=itm->length;
970 time+=itm->time;
971 itm->dest_length=len;
972 itm->dest_time=time;
973 itm->dest_count=count++;
974 itm=itm->prev;
975 }
976 dbg(1,"len %d time %d\n", len, time);
977 }
978
979 /**
980 * @brief Checks if two navigation items are on the same street
981 *
982 * This function checks if two navigation items are on the same street. It returns
983 * true if either their name or their "systematic name" (e.g. "A6" or "B256") are the
984 * same.
985 *
986 * @param old The first item to be checked
987 * @param new The second item to be checked
988 * @return True if both old and new are on the same street
989 */
990 static int
991 is_same_street2(char *old_name1, char *old_name2, char *new_name1, char *new_name2)
992 {
993 if (old_name1 && new_name1 && !strcmp(old_name1, new_name1)) {
994 dbg(1,"is_same_street: '%s' '%s' vs '%s' '%s' yes (1.)\n", old_name2, new_name2, old_name1, new_name1);
995 return 1;
996 }
997 if (old_name2 && new_name2 && !strcmp(old_name2, new_name2)) {
998 dbg(1,"is_same_street: '%s' '%s' vs '%s' '%s' yes (2.)\n", old_name2, new_name2, old_name1, new_name1);
999 return 1;
1000 }
1001 dbg(1,"is_same_street: '%s' '%s' vs '%s' '%s' no\n", old_name2, new_name2, old_name1, new_name1);
1002 return 0;
1003 }
1004
1005 #if 0
1006 /**
1007 * @brief Checks if two navigation items are on the same street
1008 *
1009 * This function checks if two navigation items are on the same street. It returns
1010 * true if the first part of their "systematic name" is equal. If the "systematic name" is
1011 * for example "A352/E3" (a german highway which at the same time is part of the international
1012 * E-road network), it would only search for "A352" in the second item's systematic name.
1013 *
1014 * @param old The first item to be checked
1015 * @param new The second item to be checked
1016 * @return True if the "systematic name" of both items matches. See description.
1017 */
1018 static int
1019 is_same_street_systematic(struct navigation_itm *old, struct navigation_itm *new)
1020 {
1021 int slashold,slashnew;
1022 if (!old->name2 || !new->name2)
1023 return 1;
1024 slashold=strcspn(old->name2, "/");
1025 slashnew=strcspn(new->name2, "/");
1026 if (slashold != slashnew || strncmp(old->name2, new->name2, slashold))
1027 return 0;
1028 return 1;
1029 }
1030
1031
1032 /**
1033 * @brief Check if there are multiple possibilities to drive from old
1034 *
1035 * This function checks, if there are multiple streets connected to the exit of "old".
1036 * Sometimes it happens that an item on a map is just segmented, without any other streets
1037 * being connected there, and it is not useful if navit creates a maneuver there.
1038 *
1039 * @param new The navigation item we're driving to
1040 * @return True if there are multiple streets
1041 */
1042 static int
1043 maneuver_multiple_streets(struct navigation_itm *new)
1044 {
1045 if (new->way.next) {
1046 return 1;
1047 } else {
1048 return 0;
1049 }
1050 }
1051
1052
1053 /**
1054 * @brief Check if the new item is entered "straight"
1055 *
1056 * This function checks if the new item is entered "straight" from the old item, i.e. if there
1057 * is no other street one could take from the old item on with less steering.
1058 *
1059 * @param new The navigation item we're driving to
1060 * @param diff The absolute angle one needs to steer to drive to this item
1061 * @return True if the new item is entered "straight"
1062 */
1063 static int
1064 maneuver_straight(struct navigation_itm *new, int diff)
1065 {
1066 int curr_diff;
1067 struct navigation_way *w;
1068
1069 w = new->way.next;
1070 dbg(1,"diff=%d\n", diff);
1071 while (w) {
1072 curr_diff=abs(angle_delta(new->prev->angle_end, w->angle2));
1073 dbg(1,"curr_diff=%d\n", curr_diff);
1074 if (curr_diff < diff) {
1075 return 0;
1076 }
1077 w = w->next;
1078 }
1079 return 1;
1080 }
1081 #endif
1082
1083 static int maneuver_category(enum item_type type)
1084 {
1085 switch (type) {
1086 case type_street_0:
1087 return 1;
1088 case type_street_1_city:
1089 return 2;
1090 case type_street_2_city:
1091 return 3;
1092 case type_street_3_city:
1093 return 4;
1094 case type_street_4_city:
1095 return 5;
1096 case type_highway_city:
1097 return 7;
1098 case type_street_1_land:
1099 return 2;
1100 case type_street_2_land:
1101 return 3;
1102 case type_street_3_land:
1103 return 4;
1104 case type_street_4_land:
1105 return 5;
1106 case type_street_n_lanes:
1107 return 6;
1108 case type_highway_land:
1109 return 7;
1110 case type_ramp:
1111 return 0;
1112 case type_roundabout:
1113 return 0;
1114 case type_ferry:
1115 return 0;
1116 default:
1117 return 0;
1118 }
1119
1120
1121 }
1122
1123 static int
1124 is_way_allowed(struct navigation *nav, struct navigation_way *way, int mode)
1125 {
1126 if (!nav->vehicleprofile)
1127 return 1;
1128 return !way->flags || ((way->flags & (way->dir >= 0 ? nav->vehicleprofile->flags_forward_mask : nav->vehicleprofile->flags_reverse_mask)) == nav->vehicleprofile->flags);
1129 }
1130
1131 /**
1132 * @brief Checks if navit has to create a maneuver to drive from old to new
1133 *
1134 * This function checks if it has to create a "maneuver" - i.e. guide the user - to drive
1135 * from "old" to "new".
1136 *
1137 * @param old The old navigation item, where we're coming from
1138 * @param new The new navigation item, where we're going to
1139 * @param delta The angle the user has to steer to navigate from old to new
1140 * @param reason A text string explaining how the return value resulted
1141 * @return True if navit should guide the user, false otherwise
1142 */
1143 static int
1144 maneuver_required2(struct navigation *nav, struct navigation_itm *old, struct navigation_itm *new, int *delta, char **reason)
1145 {
1146 int ret=0,d,dw,dlim;
1147 char *r=NULL;
1148 struct navigation_way *w;
1149 int cat,ncat,wcat,maxcat,left=-180,right=180,is_unambigous=0,is_same_street;
1150
1151 dbg(1,"enter %p %p %p\n",old, new, delta);
1152 d=angle_delta(old->angle_end, new->way.angle2);
1153 if (!new->way.next) {
1154 /* No announcement necessary */
1155 r="no: Only one possibility";
1156 } else if (!new->way.next->next && new->way.next->item.type == type_ramp && !is_way_allowed(nav,new->way.next,1)) {
1157 /* If the other way is only a ramp and it is one-way in the wrong direction, no announcement necessary */
1158 r="no: Only ramp";
1159 }
1160 if (! r) {
1161 if ((old->way.flags & AF_ROUNDABOUT) && ! (new->way.flags & AF_ROUNDABOUT)) {
1162 r="yes: leaving roundabout";
1163 ret=1;
1164 } else if (!(old->way.flags & AF_ROUNDABOUT) && (new->way.flags & AF_ROUNDABOUT)) {
1165 r="no: entering roundabout";
1166 } else if ((old->way.flags & AF_ROUNDABOUT) && (new->way.flags & AF_ROUNDABOUT))
1167 r="no: staying in roundabout";
1168 }
1169 if (!r && abs(d) > 75) {
1170 /* always make an announcement if you have to make a sharp turn */
1171 r="yes: delta over 75";
1172 ret=1;
1173 }
1174 cat=maneuver_category(old->way.item.type);
1175 ncat=maneuver_category(new->way.item.type);
1176 if (!r) {
1177 /* Check whether the street keeps its name */
1178 is_same_street=is_same_street2(old->way.name1, old->way.name2, new->way.name1, new->way.name2);
1179 w = new->way.next;
1180 maxcat=-1;
1181 while (w) {
1182 dw=angle_delta(old->angle_end, w->angle2);
1183 if (dw < 0) {
1184 if (dw > left)
1185 left=dw;
1186 } else {
1187 if (dw < right)
1188 right=dw;
1189 }
1190 wcat=maneuver_category(w->item.type);
1191 /* If any other street has the same name but isn't a highway (a highway might split up temporarily), then
1192 we can't use the same name criterium */
1193 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))
1194 is_same_street=0;
1195 /* Even if the ramp has the same name, announce it */
1196 if (new->way.item.type == type_ramp && old->way.item.type != type_ramp)
1197 is_same_street=0;
1198 /* Mark if the street has a higher or the same category */
1199 if (wcat > maxcat)
1200 maxcat=wcat;
1201 w = w->next;
1202 }
1203 /* get the delta limit for checking for other streets. It is lower if the street has no other
1204 streets of the same or higher category */
1205 if (ncat < cat)
1206 dlim=80;
1207 else
1208 dlim=120;
1209 /* if the street is really straight, the others might be closer to straight */
1210 if (abs(d) < 20)
1211 dlim/=2;
1212 if ((maxcat == ncat && maxcat == cat) || (ncat == 0 && cat == 0))
1213 dlim=abs(d)*620/256;
1214 else if (maxcat < ncat && maxcat < cat)
1215 dlim=abs(d)*128/256;
1216 if (left < -dlim && right > dlim)
1217 is_unambigous=1;
1218 if (!is_same_street && is_unambigous < 1) {
1219 ret=1;
1220 r="yes: not same street or ambigous";
1221 } else
1222 r="no: same street and unambigous";
1223 #ifdef DEBUG
1224 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);
1225 #endif
1226 }
1227 *delta=d;
1228 if (reason)
1229 *reason=r;
1230 return ret;
1231
1232
1233 #if 0
1234 if (new->item.type == old->item.type || (new->item.type != type_ramp && old->item.type != type_ramp)) {
1235 if (is_same_street2(old, new)) {
1236 if (! entering_straight(new, abs(*delta))) {
1237 dbg(1, "maneuver_required: Not driving straight: yes\n");
1238 if (reason)
1239 *reason="yes: Not driving straight";
1240 return 1;
1241 }
1242
1243 if (check_multiple_streets(new)) {
1244 if (entering_straight(new,abs(*delta)*2)) {
1245 if (reason)
1246 *reason="no: delta < ext_limit for same name";
1247 return 0;
1248 }
1249 if (reason)
1250 *reason="yes: delta > ext_limit for same name";
1251 return 1;
1252 } else {
1253 dbg(1, "maneuver_required: Staying on the same street: no\n");
1254 if (reason)
1255 *reason="no: Staying on same street";
1256 return 0;
1257 }
1258 }
1259 } else
1260 dbg(1, "maneuver_required: old or new is ramp\n");
1261 #if 0
1262 if (old->item.type == type_ramp && (new->item.type == type_highway_city || new->item.type == type_highway_land)) {
1263 dbg(1, "no_maneuver_required: old is ramp new is highway\n");
1264 if (reason)
1265 *reason="no: old is ramp new is highway";
1266 return 0;
1267 }
1268 #endif
1269 #if 0
1270 if (old->crossings_end == 2) {
1271 dbg(1, "maneuver_required: only 2 connections: no\n");
1272 return 0;
1273 }
1274 #endif
1275 dbg(1,"delta=%d-%d=%d\n", new->way.angle2, old->angle_end, *delta);
1276 if ((new->item.type == type_highway_land || new->item.type == type_highway_city || old->item.type == type_highway_land || old->item.type == type_highway_city) && (!is_same_street_systematic(old, new) || (old->name2 != NULL && new->name2 == NULL))) {
1277 dbg(1, "maneuver_required: highway changed name\n");
1278 if (reason)
1279 *reason="yes: highway changed name";
1280 return 1;
1281 }
1282 if (abs(*delta) < straight_limit) {
1283 if (! entering_straight(new,abs(*delta))) {
1284 if (reason)
1285 *reason="yes: not straight";
1286 dbg(1, "maneuver_required: not driving straight: yes\n");
1287 return 1;
1288 }
1289
1290 dbg(1, "maneuver_required: delta(%d) < %d: no\n", *delta, straight_limit);
1291 if (reason)
1292 *reason="no: delta < limit";
1293 return 0;
1294 }
1295 if (abs(*delta) < ext_straight_limit) {
1296 if (entering_straight(new,abs(*delta)*2)) {
1297 if (reason)
1298 *reason="no: delta < ext_limit";
1299 return 0;
1300 }
1301 }
1302
1303 if (! check_multiple_streets(new)) {
1304 dbg(1, "maneuver_required: only one possibility: no\n");
1305 if (reason)
1306 *reason="no: only one possibility";
1307 return 0;
1308 }
1309
1310 dbg(1, "maneuver_required: delta=%d: yes\n", *delta);
1311 if (reason)
1312 *reason="yes: delta >= limit";
1313 return 1;
1314 #endif
1315 }
1316
1317 static struct navigation_command *
1318 command_new(struct navigation *this_, struct navigation_itm *itm, int delta)
1319 {
1320 struct navigation_command *ret=g_new0(struct navigation_command, 1);
1321 dbg(1,"enter this_=%p itm=%p delta=%d\n", this_, itm, delta);
1322 ret->delta=delta;
1323 ret->itm=itm;
1324 if (itm && itm->prev && itm->way.next && itm->prev->way.next && !(itm->way.flags & AF_ROUNDABOUT) && (itm->prev->way.flags & AF_ROUNDABOUT)) {
1325 int len=0;
1326 int angle=0;
1327 int entry_angle;
1328 struct navigation_itm *itm2=itm->prev;
1329 int exit_angle=angle_median(itm->prev->angle_end, itm->way.next->angle2);
1330 dbg(1,"exit %d median from %d,%d\n", exit_angle,itm->prev->angle_end, itm->way.next->angle2);
1331 while (itm2 && (itm2->way.flags & AF_ROUNDABOUT)) {
1332 len+=itm2->length;
1333 angle=itm2->angle_end;
1334 itm2=itm2->prev;
1335 }
1336 if (itm2 && itm2->next && itm2->next->way.next) {
1337 itm2=itm2->next;
1338 entry_angle=angle_median(angle_opposite(itm2->way.angle2), itm2->way.next->angle2);
1339 dbg(1,"entry %d median from %d(%d),%d\n", entry_angle,angle_opposite(itm2->way.angle2), itm2->way.angle2, itm2->way.next->angle2);
1340 } else {
1341 entry_angle=angle_opposite(angle);
1342 }
1343 dbg(0,"entry %d exit %d\n", entry_angle, exit_angle);
1344 ret->roundabout_delta=angle_delta(entry_angle, exit_angle);
1345 ret->length=len+roundabout_extra_length;
1346 }
1347 if (this_->cmd_last) {
1348 this_->cmd_last->next=ret;
1349 ret->prev = this_->cmd_last;
1350 }
1351 this_->cmd_last=ret;
1352
1353 if (!this_->cmd_first)
1354 this_->cmd_first=ret;
1355 return ret;
1356 }
1357
1358 static void
1359 make_maneuvers(struct navigation *this_, struct route *route)
1360 {
1361 struct navigation_itm *itm, *last=NULL, *last_itm=NULL;
1362 int delta;
1363 itm=this_->first;
1364 this_->cmd_last=NULL;
1365 this_->cmd_first=NULL;
1366 while (itm) {
1367 if (last) {
1368 if (maneuver_required2(this_, last_itm, itm,&delta,NULL)) {
1369 command_new(this_, itm, delta);
1370 }
1371 } else
1372 last=itm;
1373 last_itm=itm;
1374 itm=itm->next;
1375 }
1376 command_new(this_, last_itm, 0);
1377 }
1378
1379 static int
1380 contains_suffix(char *name, char *suffix)
1381 {
1382 if (!suffix)
1383 return 0;
1384 if (strlen(name) < strlen(suffix))
1385 return 0;
1386 return !g_strcasecmp(name+strlen(name)-strlen(suffix), suffix);
1387 }
1388
1389 static char *
1390 replace_suffix(char *name, char *search, char *replace)
1391 {
1392 int len=strlen(name)-strlen(search);
1393 char *ret=g_malloc(len+strlen(replace)+1);
1394 strncpy(ret, name, len);
1395 strcpy(ret+len, replace);
1396 if (isupper(name[len])) {
1397 ret[len]=toupper(ret[len]);
1398 }
1399
1400 return ret;
1401 }
1402
1403 static char *
1404 navigation_item_destination(struct navigation *nav, struct navigation_itm *itm, struct navigation_itm *next, char *prefix)
1405 {
1406 char *ret=NULL,*name1,*sep,*name2;
1407 char *n1,*n2;
1408 int i,sex;
1409 int vocabulary1=65535;
1410 int vocabulary2=65535;
1411 struct attr attr;
1412
1413 if (! prefix)
1414 prefix="";
1415 if (nav->speech && speech_get_attr(nav->speech, attr_vocabulary_name, &attr, NULL))
1416 vocabulary1=attr.u.num;
1417 if (nav->speech && speech_get_attr(nav->speech, attr_vocabulary_name_systematic, &attr, NULL))
1418 vocabulary2=attr.u.num;
1419 n1=itm->way.name1;
1420 n2=itm->way.name2;
1421 if (!vocabulary1)
1422 n1=NULL;
1423 if (!vocabulary2)
1424 n2=NULL;
1425 if(!n1 && !n2 && itm->way.item.type == type_ramp && vocabulary2) {
1426 dbg(1,">> Next is ramp %lx current is %lx \n", itm->way.item.type, next->way.item.type);
1427
1428 if(next->way.item.type == type_ramp)
1429 return NULL;
1430 if(itm->way.item.type == type_highway_city || itm->way.item.type == type_highway_land )
1431 return g_strdup_printf("%s%s",prefix,_("exit")); /* %FIXME Can this even be reached? */
1432 else
1433 return g_strdup_printf("%s%s",prefix,_("into the ramp"));
1434
1435 }
1436 if (!n1 && !n2)
1437 return NULL;
1438 if (n1) {
1439 sex=-1;
1440 name1=NULL;
1441 for (i = 0 ; i < sizeof(suffixes)/sizeof(suffixes[0]) ; i++) {
1442 if (contains_suffix(n1,suffixes[i].fullname)) {
1443 sex=suffixes[i].sex;
1444 name1=g_strdup(n1);
1445 break;
1446 }
1447 if (contains_suffix(n1,suffixes[i].abbrev)) {
1448 sex=suffixes[i].sex;
1449 name1=replace_suffix(n1, suffixes[i].abbrev, suffixes[i].fullname);
1450 break;
1451 }
1452 }
1453 if (n2) {
1454 name2=n2;
1455 sep=" ";
1456 } else {
1457 name2="";
1458 sep="";
1459 }
1460 switch (sex) {
1461 case -1:
1462 /* TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name */
1463 ret=g_strdup_printf(_("%sinto the street %s%s%s"),prefix,n1, sep, name2);
1464 break;
1465 case 1:
1466 /* 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 */
1467 ret=g_strdup_printf(_("%sinto the %s%s%s|male form"),prefix,name1, sep, name2);
1468 break;
1469 case 2:
1470 /* 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 */
1471 ret=g_strdup_printf(_("%sinto the %s%s%s|female form"),prefix,name1, sep, name2);
1472 break;
1473 case 3:
1474 /* 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 */
1475 ret=g_strdup_printf(_("%sinto the %s%s%s|neutral form"),prefix,name1, sep, name2);
1476 break;
1477 }
1478 g_free(name1);
1479
1480 } else
1481 /* TRANSLATORS: gives the name of the next road to turn into (into the E17) */
1482 ret=g_strdup_printf(_("%sinto the %s"),prefix,n2);
1483 name1=ret;
1484 while (name1 && *name1) {
1485 switch (*name1) {
1486 case '|':
1487 *name1='\0';
1488 break;
1489 case '/':
1490 *name1++=' ';
1491 break;
1492 default:
1493 name1++;
1494 }
1495 }
1496 return ret;
1497 }
1498
1499 static char *
1500 show_maneuver(struct navigation *nav, struct navigation_itm *itm, struct navigation_command *cmd, enum attr_type type, int connect)
1501 {
1502 /* TRANSLATORS: right, as in 'Turn right' */
1503 char *dir=_("right"),*strength="";
1504 int distance=itm->dest_length-cmd->itm->dest_length;
1505 char *d,*ret=NULL;
1506 int delta=cmd->delta;
1507 int level;
1508 int strength_needed;
1509 int skip_roads;
1510 int count_roundabout;
1511 struct navigation_itm *cur;
1512 struct navigation_way *w;
1513
1514 if (connect) {
1515 level = -2; // level = -2 means "connect to another maneuver via 'then ...'"
1516 } else {
1517 level=1;
1518 }
1519
1520 w = itm->next->way.next;
1521 strength_needed = 0;
1522 if (angle_delta(itm->next->way.angle2,itm->angle_end) < 0) {
1523 while (w) {
1524 if (angle_delta(w->angle2,itm->angle_end) < 0) {
1525 strength_needed = 1;
1526 break;
1527 }
1528 w = w->next;
1529 }
1530 } else {
1531 while (w) {
1532 if (angle_delta(w->angle2,itm->angle_end) > 0) {
1533 strength_needed = 1;
1534 break;
1535 }
1536 w = w->next;
1537 }
1538 }
1539
1540 if (delta < 0) {
1541 /* TRANSLATORS: left, as in 'Turn left' */
1542 dir=_("left");
1543 delta=-delta;
1544 }
1545
1546 if (strength_needed) {
1547 if (delta < 45) {
1548 /* TRANSLATORS: Don't forget the ending space */
1549 strength=_("easily ");
1550 } else if (delta < 105) {
1551 strength="";
1552 } else if (delta < 165) {
1553 /* TRANSLATORS: Don't forget the ending space */
1554 strength=_("strongly ");
1555 } else if (delta < 180) {
1556 /* TRANSLATORS: Don't forget the ending space */
1557 strength=_("really strongly ");
1558 } else {
1559 dbg(1,"delta=%d\n", delta);
1560 /* TRANSLATORS: Don't forget the ending space */
1561 strength=_("unknown ");
1562 }
1563 }
1564 if (type != attr_navigation_long_exact)
1565 distance=round_distance(distance);
1566 if (type == attr_navigation_speech) {
1567 if (nav->turn_around && nav->turn_around == nav->turn_around_limit)
1568 return g_strdup(_("When possible, please turn around"));
1569 if (!connect) {
1570 level=navigation_get_announce_level_cmd(nav, itm, cmd, distance-cmd->length);
1571 }
1572 dbg(1,"distance=%d level=%d type=0x%x\n", distance, level, itm->way.item.type);
1573 }
1574
1575 if (cmd->itm->prev->way.flags & AF_ROUNDABOUT) {
1576 cur = cmd->itm->prev;
1577 count_roundabout = 0;
1578 while (cur && (cur->way.flags & AF_ROUNDABOUT)) {
1579 if (cur->next->way.next && is_way_allowed(nav,cur->next->way.next,3)) { // If the next segment has no exit or the exit isn't allowed, don't count it
1580 count_roundabout++;
1581 }
1582 cur = cur->prev;
1583 }
1584 switch (level) {
1585 case 2:
1586 return g_strdup(_("Enter the roundabout soon"));
1587 case 1:
1588 d = get_distance(nav, distance, type, 0);
1589 /* TRANSLATORS: %s is the distance to the roundabout */
1590 ret = g_strdup_printf(_("In %s, enter the roundabout"), d);
1591 g_free(d);
1592 return ret;
1593 case -2:
1594 return g_strdup_printf(_("then leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
1595 case 0:
1596 return g_strdup_printf(_("Leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
1597 }
1598 }
1599
1600 switch(level) {
1601 case 3:
1602 d=get_distance(nav, distance, type, 1);
1603 ret=g_strdup_printf(_("Follow the road for the next %s"), d);
1604 g_free(d);
1605 return ret;
1606 case 2:
1607 d=g_strdup(_("soon"));
1608 break;
1609 case 1:
1610 d=get_distance(nav, distance, attr_navigation_short, 0);
1611 break;
1612 case 0:
1613 skip_roads = count_possible_turns(nav,cmd->prev?cmd->prev->itm:nav->first,cmd->itm,cmd->delta);
1614 if (skip_roads > 0) {
1615 if (get_count_str(skip_roads+1)) {
1616 /* TRANSLATORS: First argument is the how manieth street to take, second the direction */
1617 ret = g_strdup_printf(_("Take the %1$s road to the %2$s"), get_count_str(skip_roads+1), dir);
1618 return ret;
1619 } else {
1620 d = g_strdup_printf(_("after %i roads"), skip_roads);
1621 }
1622 } else {
1623 d=g_strdup(_("now"));
1624 }
1625 break;
1626 case -2:
1627 skip_roads = count_possible_turns(nav,cmd->prev->itm,cmd->itm,cmd->delta);
1628 if (skip_roads > 0) {
1629 /* TRANSLATORS: First argument is the how manieth street to take, second the direction */
1630 if (get_count_str(skip_roads+1)) {
1631 ret = g_strdup_printf(_("then take the %1$s road to the %2$s"), get_count_str(skip_roads+1), dir);
1632 return ret;
1633 } else {
1634 d = g_strdup_printf(_("after %i roads"), skip_roads);
1635 }
1636
1637 } else {
1638 d = g_strdup("");
1639 }
1640 break;
1641 default:
1642 d=g_strdup(_("error"));
1643 }
1644 if (cmd->itm->next) {
1645 int tellstreetname = 0;
1646 char *destination = NULL;
1647
1648 if(type == attr_navigation_speech) { // In voice mode
1649 // In Voice Mode only tell the street name in level 1 or in level 0 if level 1
1650 // was skipped
1651
1652 if (level == 1) { // we are close to the intersection
1653 cmd->itm->streetname_told = 1; // remeber to be checked when we turn
1654 tellstreetname = 1; // Ok so we tell the name of the street
1655 }
1656
1657 if (level == 0) {
1658 if(cmd->itm->streetname_told == 0) // we are right at the intersection
1659 tellstreetname = 1;
1660 else
1661 cmd->itm->streetname_told = 0; // reset just in case we come to the same street again
1662 }
1663
1664 }
1665 else
1666 tellstreetname = 1;
1667
1668 if(nav->tell_street_name && tellstreetname)
1669 destination=navigation_item_destination(nav, cmd->itm, itm, " ");
1670
1671 if (level != -2) {
1672 /* 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' */
1673 ret=g_strdup_printf(_("Turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination:"");
1674 } else {
1675 /* TRANSLATORS: First argument is strength, second direction, third how many roads to skip, fourth destination */
1676 ret=g_strdup_printf(_("then turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination:"");
1677 }
1678 g_free(destination);
1679 } else {
1680 if (!connect) {
1681 ret=g_strdup_printf(_("You have reached your destination %s"), d);
1682 } else {
1683 ret=g_strdup_printf(_("then you have reached your destination."));
1684 }
1685 }
1686 g_free(d);
1687 return ret;
1688 }
1689
1690 /**
1691 * @brief Creates announcements for maneuvers, plus maneuvers immediately following the next maneuver
1692 *
1693 * This function does create an announcement for the current maneuver and for maneuvers
1694 * immediately following that maneuver, if these are too close and we're in speech navigation.
1695 *
1696 * @return An announcement that should be made
1697 */
1698 static char *
1699 show_next_maneuvers(struct navigation *nav, struct navigation_itm *itm, struct navigation_command *cmd, enum attr_type type)
1700 {
1701 struct navigation_command *cur,*prev;
1702 int distance=itm->dest_length-cmd->itm->dest_length;
1703 int level, dist, i, time;
1704 int speech_time,time2nav;
1705 char *ret,*old,*buf,*next;
1706
1707 if (type != attr_navigation_speech) {
1708 return show_maneuver(nav, itm, cmd, type, 0); // We accumulate maneuvers only in speech navigation
1709 }
1710
1711 level=navigation_get_announce_level(nav, itm->way.item.type, distance-cmd->length);
1712
1713 if (level > 1) {
1714 return show_maneuver(nav, itm, cmd, type, 0); // We accumulate maneuvers only if they are close
1715 }
1716
1717 if (cmd->itm->told) {
1718 return g_strdup("");
1719 }
1720
1721 ret = show_maneuver(nav, itm, cmd, type, 0);
1722 time2nav = navigation_time(itm,cmd->itm->prev);
1723 old = NULL;
1724
1725 cur = cmd->next;
1726 prev = cmd;
1727 i = 0;
1728 while (cur && cur->itm) {
1729 // We don't merge more than 3 announcements...
1730 if (i > 1) { // if you change this, please also change the value below, that is used to terminate the loop
1731 break;
1732 }
1733
1734 next = show_maneuver(nav,prev->itm, cur, type, 0);
1735 if (nav->speech)
1736 speech_time = speech_estimate_duration(nav->speech,next);
1737 else
1738 speech_time = -1;
1739 g_free(next);
1740
1741 if (speech_time == -1) { // user didn't set cps
1742 speech_time = 30; // assume 3 seconds
1743 }
1744
1745 dist = prev->itm->dest_length - cur->itm->dest_length;
1746 time = navigation_time(prev->itm,cur->itm->prev);
1747
1748 if (time >= (speech_time + 30)) { // 3 seconds for understanding what has been said
1749 break;
1750 }
1751
1752 old = ret;
1753 buf = show_maneuver(nav, prev->itm, cur, type, 1);
1754 ret = g_strdup_printf("%s, %s", old, buf);
1755 g_free(buf);
1756 if (nav->speech && speech_estimate_duration(nav->speech,ret) > time2nav) {
1757 g_free(ret);
1758 ret = old;
1759 i = 2; // This will terminate the loop
1760 } else {
1761 g_free(old);
1762 }
1763
1764 // If the two maneuvers are *really* close, we shouldn't tell the second one again, because TTS won't be fast enough
1765 if (time <= speech_time) {
1766 cur->itm->told = 1;
1767 }
1768
1769 prev = cur;
1770 cur = cur->next;
1771 i++;
1772 }
1773
1774 return ret;
1775 }
1776
1777 static void
1778 navigation_call_callbacks(struct navigation *this_, int force_speech)
1779 {
1780 int distance, level = 0;
1781 void *p=this_;
1782 if (!this_->cmd_first)
1783 return;
1784 callback_list_call(this_->callback, 1, &p);
1785 dbg(1,"force_speech=%d turn_around=%d turn_around_limit=%d\n", force_speech, this_->turn_around, this_->turn_around_limit);
1786 distance=round_distance(this_->first->dest_length-this_->cmd_first->itm->dest_length);
1787 if (this_->turn_around_limit && this_->turn_around == this_->turn_around_limit) {
1788 dbg(1,"distance=%d distance_turn=%d\n", distance, this_->distance_turn);
1789 while (distance > this_->distance_turn) {
1790 this_->level_last=4;
1791 level=4;
1792 force_speech=2;
1793 if (this_->distance_turn >= 500)
1794 this_->distance_turn*=2;
1795 else
1796 this_->distance_turn=500;
1797 }
1798 } else if (!this_->turn_around_limit || this_->turn_around == -this_->turn_around_limit+1) {
1799 this_->distance_turn=50;
1800 distance-=this_->cmd_first->length;
1801 level=navigation_get_announce_level_cmd(this_, this_->first, this_->cmd_first, distance);
1802 if (level < this_->level_last) {
1803 /* only tell if the level is valid for more than 3 seconds */
1804 int speed_distance=this_->first->speed*30/36;
1805 if (distance < speed_distance || navigation_get_announce_level_cmd(this_, this_->first, this_->cmd_first, distance-speed_distance) == level) {
1806 dbg(1,"distance %d speed_distance %d\n",distance,speed_distance);
1807 dbg(1,"level %d < %d\n", level, this_->level_last);
1808 this_->level_last=level;
1809 force_speech=3;
1810 }
1811 }
1812 if (!item_is_equal(this_->cmd_first->itm->way.item, this_->item_last)) {
1813 this_->item_last=this_->cmd_first->itm->way.item;
1814 if (this_->delay)
1815 this_->curr_delay=this_->delay;
1816 else
1817 force_speech=5;
1818 } else {
1819 if (this_->curr_delay) {
1820 this_->curr_delay--;
1821 if (!this_->curr_delay)
1822 force_speech=4;
1823 }
1824 }
1825 }
1826 if (force_speech) {
1827 this_->level_last=level;
1828 this_->curr_delay=0;
1829 dbg(1,"force_speech=%d distance=%d level=%d type=0x%x\n", force_speech, distance, level, this_->first->way.item.type);
1830 callback_list_call(this_->callback_speech, 1, &p);
1831 }
1832 }
1833
1834 static void
1835 navigation_update(struct navigation *this_, struct route *route, struct attr *attr)
1836 {
1837 struct map *map;
1838 struct map_rect *mr;
1839 struct item *ritem; /* Holds an item from the route map */
1840 struct item *sitem; /* Holds the corresponding item from the actual map */
1841 struct attr street_item,street_direction;
1842 struct navigation_itm *itm;
1843 struct attr vehicleprofile;
1844 int mode=0, incr=0, first=1;
1845 if (attr->type != attr_route_status)
1846 return;
1847
1848 dbg(1,"enter %d\n", mode);
1849 if (attr->u.num == route_status_no_destination || attr->u.num == route_status_not_found || attr->u.num == route_status_path_done_new)
1850 navigation_flush(this_);
1851 if (attr->u.num != route_status_path_done_new && attr->u.num != route_status_path_done_incremental)
1852 return;
1853
1854 if (! this_->route)
1855 return;
1856 map=route_get_map(this_->route);
1857 if (! map)
1858 return;
1859 mr=map_rect_new(map, NULL);
1860 if (! mr)
1861 return;
1862 if (route_get_attr(route, attr_vehicleprofile, &vehicleprofile, NULL))
1863 this_->vehicleprofile=vehicleprofile.u.vehicleprofile;
1864 else
1865 this_->vehicleprofile=NULL;
1866 dbg(1,"enter\n");
1867 while ((ritem=map_rect_get_item(mr))) {
1868 if (ritem->type == type_route_start && this_->turn_around > -this_->turn_around_limit+1)
1869 this_->turn_around--;
1870 if (ritem->type == type_route_start_reverse && this_->turn_around < this_->turn_around_limit)
1871 this_->turn_around++;
1872 if (ritem->type != type_street_route)
1873 continue;
1874 if (first && item_attr_get(ritem, attr_street_item, &street_item)) {
1875 first=0;
1876 if (!item_attr_get(ritem, attr_direction, &street_direction))
1877 street_direction.u.num=0;
1878 sitem=street_item.u.item;
1879 dbg(1,"sitem=%p\n", sitem);
1880 itm=item_hash_lookup(this_->hash, sitem);
1881 dbg(2,"itm for item with id (0x%x,0x%x) is %p\n", sitem->id_hi, sitem->id_lo, itm);
1882 if (itm && itm->way.dir != street_direction.u.num) {
1883 dbg(2,"wrong direction\n");
1884 itm=NULL;
1885 }
1886 navigation_destroy_itms_cmds(this_, itm);
1887 if (itm) {
1888 navigation_itm_update(itm, ritem);
1889 break;
1890 }
1891 dbg(1,"not on track\n");
1892 }
1893 navigation_itm_new(this_, ritem);
1894 }
1895 dbg(2,"turn_around=%d\n", this_->turn_around);
1896 if (first)
1897 navigation_destroy_itms_cmds(this_, NULL);
1898 else {
1899 if (! ritem) {
1900 navigation_itm_new(this_, NULL);
1901 make_maneuvers(this_,this_->route);
1902 }
1903 calculate_dest_distance(this_, incr);
1904 profile(0,"end");
1905 navigation_call_callbacks(this_, FALSE);
1906 }
1907 map_rect_destroy(mr);
1908 }
1909
1910 static void
1911 navigation_flush(struct navigation *this_)
1912 {
1913 navigation_destroy_itms_cmds(this_, NULL);
1914 }
1915
1916
1917 void
1918 navigation_destroy(struct navigation *this_)
1919 {
1920 navigation_flush(this_);
1921 item_hash_destroy(this_->hash);
1922 callback_list_destroy(this_->callback);
1923 callback_list_destroy(this_->callback_speech);
1924 g_free(this_);
1925 }
1926
1927 int
1928 navigation_register_callback(struct navigation *this_, enum attr_type type, struct callback *cb)
1929 {
1930 if (type == attr_navigation_speech)
1931 callback_list_add(this_->callback_speech, cb);
1932 else
1933 callback_list_add(this_->callback, cb);
1934 return 1;
1935 }
1936
1937 void
1938 navigation_unregister_callback(struct navigation *this_, enum attr_type type, struct callback *cb)
1939 {
1940 if (type == attr_navigation_speech)
1941 callback_list_remove_destroy(this_->callback_speech, cb);
1942 else
1943 callback_list_remove_destroy(this_->callback, cb);
1944 }
1945
1946 struct map *
1947 navigation_get_map(struct navigation *this_)
1948 {
1949 struct attr *attrs[5];
1950 struct attr type,navigation,data,description;
1951 type.type=attr_type;
1952 type.u.str="navigation";
1953 navigation.type=attr_navigation;
1954 navigation.u.navigation=this_;
1955 data.type=attr_data;
1956 data.u.str="";
1957 description.type=attr_description;
1958 description.u.str="Navigation";
1959
1960 attrs[0]=&type;
1961 attrs[1]=&navigation;
1962 attrs[2]=&data;
1963 attrs[3]=&description;
1964 attrs[4]=NULL;
1965 if (! this_->map)
1966 this_->map=map_new(NULL, attrs);
1967 return this_->map;
1968 }
1969
1970 struct map_priv {
1971 struct navigation *navigation;
1972 };
1973
1974 struct map_rect_priv {
1975 struct navigation *nav;
1976 struct navigation_command *cmd;
1977 struct navigation_command *cmd_next;
1978 struct navigation_itm *itm;
1979 struct navigation_itm *itm_next;
1980 struct navigation_itm *cmd_itm;
1981 struct navigation_itm *cmd_itm_next;
1982 struct item item;
1983 enum attr_type attr_next;
1984 int ccount;
1985 int debug_idx;
1986 struct navigation_way *ways;
1987 int show_all;
1988 char *str;
1989 };
1990
1991 static int
1992 navigation_map_item_coord_get(void *priv_data, struct coord *c, int count)
1993 {
1994 struct map_rect_priv *this=priv_data;
1995 if (this->ccount || ! count)
1996 return 0;
1997 *c=this->itm->start;
1998 this->ccount=1;
1999 return 1;
2000 }
2001
2002 static int
2003 navigation_map_item_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
2004 {
2005 struct map_rect_priv *this_=priv_data;
2006 struct navigation_command *cmd=this_->cmd;
2007 struct navigation_itm *itm=this_->itm;
2008 struct navigation_itm *prev=itm->prev;
2009 attr->type=attr_type;
2010
2011 if (this_->str) {
2012 g_free(this_->str);
2013 this_->str=NULL;
2014 }
2015
2016 if (cmd) {
2017 if (cmd->itm != itm)
2018 cmd=NULL;
2019 }
2020 switch(attr_type) {
2021 case attr_navigation_short:
2022 this_->attr_next=attr_navigation_long;
2023 if (cmd) {
2024 this_->str=attr->u.str=show_next_maneuvers(this_->nav, this_->cmd_itm, cmd, attr_type);
2025 return 1;
2026 }
2027 return 0;
2028 case attr_navigation_long:
2029 this_->attr_next=attr_navigation_long_exact;
2030 if (cmd) {
2031 this_->str=attr->u.str=show_next_maneuvers(this_->nav, this_->cmd_itm, cmd, attr_type);
2032 return 1;
2033 }
2034 return 0;
2035 case attr_navigation_long_exact:
2036 this_->attr_next=attr_navigation_speech;
2037 if (cmd) {
2038 this_->str=attr->u.str=show_next_maneuvers(this_->nav, this_->cmd_itm, cmd, attr_type);
2039 return 1;
2040 }
2041 return 0;
2042 case attr_navigation_speech:
2043 this_->attr_next=attr_length;
2044 if (cmd) {
2045 this_->str=attr->u.str=show_next_maneuvers(this_->nav, this_->cmd_itm, this_->cmd, attr_type);
2046 return 1;
2047 }
2048 return 0;
2049 case attr_length:
2050 this_->attr_next=attr_time;
2051 if (cmd) {
2052 attr->u.num=this_->cmd_itm->dest_length-cmd->itm->dest_length;
2053 return 1;
2054 }
2055 return 0;
2056 case attr_time:
2057 this_->attr_next=attr_destination_length;
2058 if (cmd) {
2059 attr->u.num=this_->cmd_itm->dest_time-cmd->itm->dest_time;
2060 return 1;
2061 }
2062 return 0;
2063 case attr_destination_length:
2064 attr->u.num=itm->dest_length;
2065 this_->attr_next=attr_destination_time;
2066 return 1;
2067 case attr_destination_time:
2068 attr->u.num=itm->dest_time;
2069 this_->attr_next=attr_street_name;
2070 return 1;
2071 case attr_street_name:
2072 attr->u.str=itm->way.name1;
2073 this_->attr_next=attr_street_name_systematic;
2074 if (attr->u.str)
2075 return 1;
2076 return 0;
2077 case attr_street_name_systematic:
2078 attr->u.str=itm->way.name2;
2079 this_->attr_next=attr_debug;
2080 if (attr->u.str)
2081 return 1;
2082 return 0;
2083 case attr_debug:
2084 switch(this_->debug_idx) {
2085 case 0:
2086 this_->debug_idx++;
2087 this_->str=attr->u.str=g_strdup_printf("angle:%d (- %d)", itm->way.angle2, itm->angle_end);
2088 return 1;
2089 case 1:
2090 this_->debug_idx++;
2091 this_->str=attr->u.str=g_strdup_printf("item type:%s", item_to_name(itm->way.item.type));
2092 return 1;
2093 case 2:
2094 this_->debug_idx++;
2095 if (cmd) {
2096 this_->str=attr->u.str=g_strdup_printf("delta:%d", cmd->delta);
2097 return 1;
2098 }
2099 case 3:
2100 this_->debug_idx++;
2101 if (prev) {
2102 this_->str=attr->u.str=g_strdup_printf("prev street_name:%s", prev->way.name1);
2103 return 1;
2104 }
2105 case 4:
2106 this_->debug_idx++;
2107 if (prev) {
2108 this_->str=attr->u.str=g_strdup_printf("prev street_name_systematic:%s", prev->way.name2);
2109 return 1;
2110 }
2111 case 5:
2112 this_->debug_idx++;
2113 if (prev) {
2114 this_->str=attr->u.str=g_strdup_printf("prev angle:(%d -) %d", prev->way.angle2, prev->angle_end);
2115 return 1;
2116 }
2117 case 6:
2118 this_->debug_idx++;
2119 this_->ways=itm->way.next;
2120 if (prev) {
2121 this_->str=attr->u.str=g_strdup_printf("prev item type:%s", item_to_name(prev->way.item.type));
2122 return 1;
2123 }
2124 case 7:
2125 if (this_->ways && prev) {
2126 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);
2127 this_->ways=this_->ways->next;
2128 return 1;
2129 }
2130 this_->debug_idx++;
2131 case 8:
2132 this_->debug_idx++;
2133 if (prev) {
2134 int delta=0;
2135 char *reason=NULL;
2136 maneuver_required2(this_->nav, prev, itm, &delta, &reason);
2137 this_->str=attr->u.str=g_strdup_printf("reason:%s",reason);
2138 return 1;
2139 }
2140
2141 default:
2142 this_->attr_next=attr_none;
2143 return 0;
2144 }
2145 case attr_any:
2146 while (this_->attr_next != attr_none) {
2147 if (navigation_map_item_attr_get(priv_data, this_->attr_next, attr))
2148 return 1;
2149 }
2150 return 0;
2151 default:
2152 attr->type=attr_none;
2153 return 0;
2154 }
2155 }
2156
2157 static struct item_methods navigation_map_item_methods = {
2158 NULL,
2159 navigation_map_item_coord_get,
2160 NULL,
2161 navigation_map_item_attr_get,
2162 };
2163
2164
2165 static void
2166 navigation_map_destroy(struct map_priv *priv)
2167 {
2168 g_free(priv);
2169 }
2170
2171 static void
2172 navigation_map_rect_init(struct map_rect_priv *priv)
2173 {
2174 priv->cmd_next=priv->nav->cmd_first;
2175 priv->cmd_itm_next=priv->itm_next=priv->nav->first;
2176 }
2177
2178 static struct map_rect_priv *
2179 navigation_map_rect_new(struct map_priv *priv, struct map_selection *sel)
2180 {
2181 struct navigation *nav=priv->navigation;
2182 struct map_rect_priv *ret=g_new0(struct map_rect_priv, 1);
2183 ret->nav=nav;
2184 navigation_map_rect_init(ret);
2185 ret->item.meth=&navigation_map_item_methods;
2186 ret->item.priv_data=ret;
2187 #ifdef DEBUG
2188 ret->show_all=1;
2189 #endif
2190 return ret;
2191 }
2192
2193 static void
2194 navigation_map_rect_destroy(struct map_rect_priv *priv)
2195 {
2196 g_free(priv);
2197 }
2198
2199 static struct item *
2200 navigation_map_get_item(struct map_rect_priv *priv)
2201 {
2202 struct item *ret=&priv->item;
2203 int delta;
2204 if (!priv->itm_next)
2205 return NULL;
2206 priv->itm=priv->itm_next;
2207 priv->cmd=priv->cmd_next;
2208 priv->cmd_itm=priv->cmd_itm_next;
2209 if (!priv->cmd)
2210 return NULL;
2211 if (!priv->show_all && priv->itm->prev != NULL)
2212 priv->itm=priv->cmd->itm;
2213 priv->itm_next=priv->itm->next;
2214 if (priv->itm->prev)
2215 ret->type=type_nav_none;
2216 else
2217 ret->type=type_nav_position;
2218 if (priv->cmd->itm == priv->itm) {
2219 priv->cmd_itm_next=priv->cmd->itm;
2220 priv->cmd_next=priv->cmd->next;
2221 if (priv->cmd_itm_next && !priv->cmd_itm_next->next)
2222 ret->type=type_nav_destination;
2223 else {
2224 if (priv->itm && priv->itm->prev && !(priv->itm->way.flags & AF_ROUNDABOUT) && (priv->itm->prev->way.flags & AF_ROUNDABOUT)) {
2225 enum item_type r=type_none,l=type_none;
2226 switch (((180+22)-priv->cmd->roundabout_delta)/45) {
2227 case 0:
2228 case 1:
2229 r=type_nav_roundabout_r1;
2230 l=type_nav_roundabout_l7;
2231 break;
2232 case 2:
2233 r=type_nav_roundabout_r2;
2234 l=type_nav_roundabout_l6;
2235 break;
2236 case 3:
2237 r=type_nav_roundabout_r3;
2238 l=type_nav_roundabout_l5;
2239 break;
2240 case 4:
2241 r=type_nav_roundabout_r4;
2242 l=type_nav_roundabout_l4;
2243 break;
2244 case 5:
2245 r=type_nav_roundabout_r5;
2246 l=type_nav_roundabout_l3;
2247 break;
2248 case 6:
2249 r=type_nav_roundabout_r6;
2250 l=type_nav_roundabout_l2;
2251 break;
2252 case 7:
2253 r=type_nav_roundabout_r7;
2254 l=type_nav_roundabout_l1;
2255 break;
2256 case 8:
2257 r=type_nav_roundabout_r8;
2258 l=type_nav_roundabout_l8;
2259 break;
2260 }
2261 dbg(1,"delta %d\n",priv->cmd->delta);
2262 if (priv->cmd->delta < 0)
2263 ret->type=l;
2264 else
2265 ret->type=r;
2266 } else {
2267 delta=priv->cmd->delta;
2268 if (delta < 0) {
2269 delta=-delta;
2270 if (delta < 45)
2271 ret->type=type_nav_left_1;
2272 else if (delta < 105)
2273 ret->type=type_nav_left_2;
2274 else if (delta < 165)
2275 ret->type=type_nav_left_3;
2276 else
2277 ret->type=type_none;
2278 } else {
2279 if (delta < 45)
2280 ret->type=type_nav_right_1;
2281 else if (delta < 105)
2282 ret->type=type_nav_right_2;
2283 else if (delta < 165)
2284 ret->type=type_nav_right_3;
2285 else
2286 ret->type=type_none;
2287 }
2288 }
2289 }
2290 }
2291 priv->ccount=0;
2292 priv->debug_idx=0;
2293 priv->attr_next=attr_navigation_short;
2294
2295 ret->id_lo=priv->itm->dest_count;
2296 dbg(1,"type=%d\n", ret->type);
2297 return ret;
2298 }
2299
2300 static struct item *
2301 navigation_map_get_item_byid(struct map_rect_priv *priv, int id_hi, int id_lo)
2302 {
2303 struct item *ret;
2304 navigation_map_rect_init(priv);
2305 while ((ret=navigation_map_get_item(priv))) {
2306 if (ret->id_hi == id_hi && ret->id_lo == id_lo)
2307 return ret;
2308 }
2309 return NULL;
2310 }
2311
2312 static struct map_methods navigation_map_meth = {
2313 projection_mg,
2314 "utf-8",
2315 navigation_map_destroy,
2316 navigation_map_rect_new,
2317 navigation_map_rect_destroy,
2318 navigation_map_get_item,
2319 navigation_map_get_item_byid,
2320 NULL,
2321 NULL,
2322 NULL,
2323 };
2324
2325 static struct map_priv *
2326 navigation_map_new(struct map_methods *meth, struct attr **attrs, struct callback_list *cbl)
2327 {
2328 struct map_priv *ret;
2329 struct attr *navigation_attr;
2330
2331 navigation_attr=attr_search(attrs, NULL, attr_navigation);
2332 if (! navigation_attr)
2333 return NULL;
2334 ret=g_new0(struct map_priv, 1);
2335 *meth=navigation_map_meth;
2336 ret->navigation=navigation_attr->u.navigation;
2337
2338 return ret;
2339 }
2340
2341 void
2342 navigation_set_route(struct navigation *this_, struct route *route)
2343 {
2344 struct attr callback;
2345 this_->route=route;
2346 this_->route_cb=callback_new_attr_1(callback_cast(navigation_update), attr_route_status, this_);
2347 callback.type=attr_callback;
2348 callback.u.callback=this_->route_cb;
2349 route_add_attr(route, &callback);
2350 }
2351
2352 void
2353 navigation_init(void)
2354 {
2355 plugin_register_map_type("navigation", navigation_map_new);
2356 }

   
Visit the ZANavi Wiki