2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2008 Navit Team
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.
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.
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.
34 #include "projection.h"
42 #include "transform.h"
53 struct route_graph_point {
54 struct route_graph_point *next;
55 struct route_graph_point *hash_next;
56 struct route_graph_segment *start;
57 struct route_graph_segment *end;
58 struct route_graph_segment *seg;
59 struct fibheap_el *el;
64 struct route_graph_segment {
65 struct route_graph_segment *next;
66 struct route_graph_segment *start_next;
67 struct route_graph_segment *end_next;
68 struct route_graph_point *start;
69 struct route_graph_point *end;
76 struct route_path_segment {
77 struct route_path_segment *next;
96 struct street_data *street;
100 struct route_path_segment *path;
101 struct route_path_segment *path_last;
102 /* XXX: path_hash is not necessery now */
103 struct item_hash *path_hash;
106 #define RF_FASTEST (1<<0)
107 #define RF_SHORTEST (1<<1)
108 #define RF_AVOIDHW (1<<2)
109 #define RF_AVOIDPAID (1<<3)
110 #define RF_LOCKONROAD (1<<4)
111 #define RF_SHOWGRAPH (1<<5)
117 struct route_info *pos;
118 struct route_info *dst;
120 struct route_graph *graph;
121 struct route_path *path2;
123 struct map *graph_map;
124 int speedlist[route_item_last-route_item_first+1];
128 struct route_graph_point *route_points;
129 struct route_graph_segment *route_segments;
130 #define HASH_SIZE 8192
131 struct route_graph_point *hash[HASH_SIZE];
134 #define HASHCOORD(c) ((((c)->x +(c)->y) * 2654435761UL) & (HASH_SIZE-1))
136 static struct route_info * route_find_nearest_street(struct mapset *ms, struct pcoord *c);
137 static struct route_graph_point *route_graph_get_point(struct route_graph *this, struct coord *c);
138 static void route_graph_update(struct route *this);
139 static struct route_path *route_path_new(struct route_graph *this, struct route_path *oldpath, struct route_info *pos, struct route_info *dst, int *speedlist);
140 static void route_process_street_graph(struct route_graph *this, struct item *item);
141 static void route_graph_destroy(struct route_graph *this);
142 static void route_path_update(struct route *this);
144 static enum projection route_projection(struct route *route)
146 struct street_data *street;
147 street = route->pos ? route->pos->street : route->dst->street;
148 return map_projection(street->item.map);
152 route_path_destroy(struct route_path *this)
154 struct route_path_segment *c,*n;
157 if (this->path_hash) {
158 item_hash_destroy(this->path_hash);
159 this->path_hash=NULL;
171 route_new(struct attr **attrs)
173 struct route *this=g_new0(struct route, 1);
175 printf("%s:Out of memory\n", __FUNCTION__);
182 route_set_mapset(struct route *this, struct mapset *ms)
188 route_get_mapset(struct route *this)
194 route_get_pos(struct route *this)
200 route_get_dst(struct route *this)
206 route_get_speedlist(struct route *this)
208 return this->speedlist;
212 route_get_path_set(struct route *this)
214 return this->path2 != NULL;
218 route_set_speed(struct route *this, enum item_type type, int value)
220 if (type < route_item_first || type > route_item_last) {
221 dbg(0,"street type %d out of range [%d,%d]", type, route_item_first, route_item_last);
224 this->speedlist[type-route_item_first]=value;
229 route_contains(struct route *this, struct item *item)
231 if (! this->path2 || !this->path2->path_hash)
233 return (int)item_hash_lookup(this->path2->path_hash, item);
237 route_pos_contains(struct route *this, struct item *item)
241 return item_is_equal(this->pos->street->item, *item);
246 route_path_update(struct route *this)
248 struct route_path *oldpath = NULL;
249 if (! this->pos || ! this->dst) {
250 route_path_destroy(this->path2);
254 /* the graph is destroyed when setting the destination */
255 if (this->graph && this->pos && this->dst && this->path2) {
256 // we can try to update
257 oldpath = this->path2;
260 if (! this->graph || !(this->path2=route_path_new(this->graph, oldpath, this->pos, this->dst, this->speedlist))) {
262 route_graph_update(this);
263 this->path2=route_path_new(this->graph, oldpath, this->pos, this->dst, this->speedlist);
264 profile(1,"route_path_new");
268 /* Destroy what's left */
269 route_path_destroy(oldpath);
274 route_info_distances(struct route_info *ri, enum projection pro)
277 struct street_data *sd=ri->street;
278 /* 0 1 2 X 3 4 5 6 pos=2 npos=3 count=7 0,1,2 3,4,5,6*/
279 ri->lenextra=transform_distance(pro, &ri->lp, &ri->c);
280 ri->lenneg=transform_polyline_length(pro, sd->c, npos)+transform_distance(pro, &sd->c[ri->pos], &ri->lp);
281 ri->lenpos=transform_polyline_length(pro, sd->c+npos, sd->count-npos)+transform_distance(pro, &sd->c[npos], &ri->lp);
285 route_set_position(struct route *this, struct pcoord *pos)
288 route_info_free(this->pos);
290 this->pos=route_find_nearest_street(this->ms, pos);
291 dbg(1,"this->pos=%p\n", this->pos);
294 route_info_distances(this->pos, pos->pro);
296 route_path_update(this);
300 route_set_position_from_tracking(struct route *this, struct tracking *tracking)
303 struct route_info *ret;
306 c=tracking_get_pos(tracking);
307 ret=g_new0(struct route_info, 1);
309 printf("%s:Out of memory\n", __FUNCTION__);
313 route_info_free(this->pos);
317 ret->pos=tracking_get_segment_pos(tracking);
318 ret->street=street_data_dup(tracking_get_street_data(tracking));
319 route_info_distances(ret, projection_mg);
320 dbg(3,"c->x=0x%x, c->y=0x%x pos=%d item=(0x%x,0x%x)\n", c->x, c->y, ret->pos, ret->street->item.id_hi, ret->street->item.id_lo);
321 dbg(3,"street 0=(0x%x,0x%x) %d=(0x%x,0x%x)\n", ret->street->c[0].x, ret->street->c[0].y, ret->street->count-1, ret->street->c[ret->street->count-1].x, ret->street->c[ret->street->count-1].y);
324 route_path_update(this);
328 /* Used for debuging of route_rect, what routing sees */
329 struct map_selection *route_selection;
331 struct map_selection *
332 route_rect(int order, struct coord *c1, struct coord *c2, int rel, int abs)
334 int dx,dy,sx=1,sy=1,d,m;
335 struct map_selection *sel=g_new(struct map_selection, 1);
337 printf("%s:Out of memory\n", __FUNCTION__);
340 sel->order[layer_town]=0;
341 sel->order[layer_poly]=0;
342 sel->order[layer_street]=order;
343 dbg(1,"%p %p\n", c1, c2);
348 sel->u.c_rect.lu.x=c1->x;
349 sel->u.c_rect.rl.x=c2->x;
351 sel->u.c_rect.lu.x=c2->x;
352 sel->u.c_rect.rl.x=c1->x;
356 sel->u.c_rect.lu.y=c2->y;
357 sel->u.c_rect.rl.y=c1->y;
359 sel->u.c_rect.lu.y=c1->y;
360 sel->u.c_rect.rl.y=c2->y;
367 sel->u.c_rect.lu.x-=m;
368 sel->u.c_rect.rl.x+=m;
369 sel->u.c_rect.lu.y+=m;
370 sel->u.c_rect.rl.y-=m;
375 static struct map_selection *
376 route_calc_selection(struct coord *c1, struct coord *c2)
378 struct map_selection *ret,*sel;
379 sel=route_rect(4, c1, c2, 25, 0);
381 sel->next=route_rect(8, c1, c1, 0, 40000);
383 sel->next=route_rect(18, c1, c1, 0, 10000);
385 sel->next=route_rect(8, c2, c2, 0, 40000);
387 sel->next=route_rect(18, c2, c2, 0, 10000);
388 /* route_selection=ret; */
393 route_free_selection(struct map_selection *sel)
395 struct map_selection *next;
407 route_set_destination(struct route *this, struct pcoord *dst)
411 route_info_free(this->dst);
414 this->dst=route_find_nearest_street(this->ms, dst);
415 route_info_distances(this->dst, dst->pro);
416 profile(1,"find_nearest_street");
417 route_graph_destroy(this->graph);
419 route_path_update(this);
423 static struct route_graph_point *
424 route_graph_get_point(struct route_graph *this, struct coord *c)
426 struct route_graph_point *p;
427 int hashval=HASHCOORD(c);
428 p=this->hash[hashval];
430 if (p->c.x == c->x && p->c.y == c->y)
438 static struct route_graph_point *
439 route_graph_add_point(struct route_graph *this, struct coord *f)
442 struct route_graph_point *p;
444 p=route_graph_get_point(this,f);
446 hashval=HASHCOORD(f);
448 printf("p (0x%x,0x%x)\n", f->x, f->y);
449 p=g_new(struct route_graph_point,1);
451 printf("%s:Out of memory\n", __FUNCTION__);
454 p->hash_next=this->hash[hashval];
455 this->hash[hashval]=p;
456 p->next=this->route_points;
463 this->route_points=p;
470 route_graph_free_points(struct route_graph *this)
472 struct route_graph_point *curr,*next;
473 curr=this->route_points;
479 this->route_points=NULL;
480 memset(this->hash, 0, sizeof(this->hash));
484 route_graph_add_segment(struct route_graph *this, struct route_graph_point *start,
485 struct route_graph_point *end, int len, struct item *item,
486 int flags, int offset)
488 struct route_graph_segment *s;
491 if (item_is_equal(*item, s->item))
495 s = g_new0(struct route_graph_segment, 1);
497 printf("%s:Out of memory\n", __FUNCTION__);
501 s->start_next=start->start;
504 s->end_next=end->end;
511 s->next=this->route_segments;
512 this->route_segments=s;
514 printf("l (0x%x,0x%x)-(0x%x,0x%x)\n", start->c.x, start->c.y, end->c.x, end->c.y);
517 static int get_item_seg_coords(struct item *i, struct coord *c, int max,
518 struct coord *start, struct coord *end)
524 mr=map_rect_new(i->map, NULL);
527 item = map_rect_get_item_byid(mr, i->id_hi, i->id_lo);
529 rc = item_coord_get(item, &c1, 1);
530 while (rc && (c1.x != start->x || c1.y != start->y)) {
531 rc = item_coord_get(item, &c1, 1);
533 while (rc && p < max) {
535 if (c1.x == end->x && c1.y == end->y)
537 rc = item_coord_get(item, &c1, 1);
540 map_rect_destroy(mr);
544 static struct route_path_segment *
545 route_extract_segment_from_path(struct route_path *path, struct item *item,
548 struct route_path_segment *sp = NULL, *s;
551 if (s->offset == offset && item_is_equal(s->item,*item)) {
556 path->path = s->next;
564 item_hash_remove(path->path_hash, item);
569 route_path_add_segment(struct route_path *this, struct route_path_segment *segment)
574 this->path_last->next=segment;
575 this->path_last=segment;
579 route_path_add_item(struct route_path *this, struct item *item, int len, struct coord *first, struct coord *c, int count, struct coord *last, int dir)
581 int i,idx=0,ccount=count + (first ? 1:0) + (last ? 1:0);
582 struct route_path_segment *segment;
584 segment=g_malloc0(sizeof(*segment) + sizeof(struct coord) * ccount);
585 segment->ncoords=ccount;
586 segment->direction=dir;
588 segment->c[idx++]=*first;
590 for (i = 0 ; i < count ; i++)
591 segment->c[idx++]=c[i];
593 for (i = 0 ; i < count ; i++)
594 segment->c[idx++]=c[count-i-1];
597 segment->c[idx++]=*last;
601 route_path_add_segment(this, segment);
605 route_path_add_item_from_graph(struct route_path *this, struct route_path *oldpath,
606 struct route_graph_segment *rgs, int len, int offset, int dir)
608 struct route_path_segment *segment;
610 struct coord ca[2048];
613 ccnt = (int)item_hash_lookup(oldpath->path_hash, &rgs->item);
615 segment = route_extract_segment_from_path(oldpath,
622 ccnt = get_item_seg_coords(&rgs->item, ca, 2047, &rgs->start->c, &rgs->end->c);
623 segment= g_malloc0(sizeof(*segment) + sizeof(struct coord) * ccnt);
625 printf("%s:Out of memory\n", __FUNCTION__);
628 segment->direction=dir;
630 for (i = 0 ; i < ccnt ; i++)
633 for (i = 0 ; i < ccnt ; i++)
634 segment->c[i]=ca[ccnt-i-1];
636 segment->ncoords = ccnt;
637 segment->item=rgs->item;
638 segment->offset = offset;
642 item_hash_insert(this->path_hash, &rgs->item, (void *)ccnt);
643 route_path_add_segment(this, segment);
647 route_graph_free_segments(struct route_graph *this)
649 struct route_graph_segment *curr,*next;
650 curr=this->route_segments;
656 this->route_segments=NULL;
660 route_graph_destroy(struct route_graph *this)
663 route_graph_free_points(this);
664 route_graph_free_segments(this);
670 route_time(int *speedlist, struct item *item, int len)
672 if (item->type < route_item_first || item->type > route_item_last) {
673 dbg(0,"street type %d out of range [%d,%d]", item->type, route_item_first, route_item_last);
676 return len*36/speedlist[item->type-route_item_first];
681 route_value(int *speedlist, struct item *item, int len)
685 printf("len=%d\n", len);
688 ret=route_time(speedlist, item, len);
689 dbg(1, "route_value(0x%x, %d)=%d\n", item->type, len, ret);
694 route_process_street_graph(struct route_graph *this, struct item *item)
701 struct route_graph_point *s_pnt,*e_pnt;
708 if (item_coord_get(item, &l, 1)) {
709 if (item_attr_get(item, attr_flags, &attr)) {
711 if (flags & AF_SEGMENTED)
714 s_pnt=route_graph_add_point(this,&l);
716 while (item_coord_get(item, &c, 1)) {
717 len+=transform_distance(map_projection(item->map), &l, &c);
720 e_pnt=route_graph_add_point(this,&l);
722 route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset);
727 isseg = item_coord_is_segment(item);
728 rc = item_coord_get(item, &c, 1);
730 len+=transform_distance(map_projection(item->map), &l, &c);
733 e_pnt=route_graph_add_point(this,&l);
734 route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset);
736 s_pnt=route_graph_add_point(this,&l);
741 e_pnt=route_graph_add_point(this,&l);
744 route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset);
750 compare(void *v1, void *v2)
752 struct route_graph_point *p1=v1;
753 struct route_graph_point *p2=v2;
756 printf("compare %d (%p) vs %d (%p)\n", p1->value,p1,p2->value,p2);
758 return p1->value-p2->value;
762 route_graph_flood(struct route_graph *this, struct route_info *dst, int *speedlist)
764 struct route_graph_point *p_min,*end=NULL;
765 struct route_graph_segment *s;
767 struct fibheap *heap;
768 struct street_data *sd=dst->street;
770 heap = fh_makeheap();
771 fh_setcmp(heap, compare);
773 if (! (sd->flags & AF_ONEWAYREV)) {
774 end=route_graph_get_point(this, &sd->c[0]);
776 end->value=route_value(speedlist, &sd->item, dst->lenneg);
777 end->el=fh_insert(heap, end);
780 if (! (sd->flags & AF_ONEWAY)) {
781 end=route_graph_get_point(this, &sd->c[sd->count-1]);
783 end->value=route_value(speedlist, &sd->item, dst->lenpos);
784 end->el=fh_insert(heap, end);
787 dbg(1,"0x%x,0x%x\n", end->c.x, end->c.y);
789 p_min=fh_extractmin(heap);
794 printf("extract p=%p free el=%p min=%d, 0x%x, 0x%x\n", p_min, p_min->el, min, p_min->c.x, p_min->c.y);
798 val=route_value(speedlist, &s->item, s->len);
800 val+=val*2*street_route_contained(s->str->segid);
804 printf("begin %d len %d vs %d (0x%x,0x%x)\n",new,val,s->end->value, s->end->c.x, s->end->c.y);
805 if (new < s->end->value && !(s->flags & AF_ONEWAY)) {
810 printf("insert_end p=%p el=%p val=%d ", s->end, s->end->el, s->end->value);
811 s->end->el=fh_insert(heap, s->end);
813 printf("el new=%p\n", s->end->el);
817 printf("replace_end p=%p el=%p val=%d\n", s->end, s->end->el, s->end->value);
818 fh_replacedata(heap, s->end->el, s->end);
827 val=route_value(speedlist, &s->item, s->len);
830 printf("end %d len %d vs %d (0x%x,0x%x)\n",new,val,s->start->value,s->start->c.x, s->start->c.y);
831 if (new < s->start->value && !(s->flags & AF_ONEWAYREV)) {
835 if (! s->start->el) {
837 printf("insert_start p=%p el=%p val=%d ", s->start, s->start->el, s->start->value);
838 s->start->el=fh_insert(heap, s->start);
840 printf("el new=%p\n", s->start->el);
844 printf("replace_start p=%p el=%p val=%d\n", s->start, s->start->el, s->start->value);
845 fh_replacedata(heap, s->start->el, s->start);
856 static struct route_path *
857 route_path_new_offroad(struct route_graph *this, struct route_info *pos, struct route_info *dst, int dir)
859 struct route_path *ret;
861 ret=g_new0(struct route_path, 1);
862 ret->path_hash=item_hash_new();
863 route_path_add_item(ret, NULL, pos->lenextra+dst->lenextra, &pos->c, NULL, 0, &dst->c, 1);
868 static struct route_path *
869 route_path_new_trivial(struct route_graph *this, struct route_info *pos, struct route_info *dst, int dir)
871 struct street_data *sd=pos->street;
872 struct route_path *ret;
875 if (pos->lenextra + dst->lenextra + pos->lenneg-dst->lenneg > transform_distance(map_projection(sd->item.map), &pos->c, &dst->c))
876 return route_path_new_offroad(this, pos, dst, dir);
878 if (pos->lenextra + dst->lenextra + pos->lenpos-dst->lenpos > transform_distance(map_projection(sd->item.map), &pos->c, &dst->c))
879 return route_path_new_offroad(this, pos, dst, dir);
881 ret=g_new0(struct route_path, 1);
882 ret->path_hash=item_hash_new();
884 route_path_add_item(ret, NULL, pos->lenextra, &pos->c, NULL, 0, &pos->lp, 1);
886 route_path_add_item(ret, &sd->item, pos->lenneg-dst->lenneg, &pos->lp, sd->c+pos->pos+1, dst->pos+pos->pos, &dst->lp, 1);
888 route_path_add_item(ret, &sd->item, pos->lenpos-dst->lenpos, &pos->lp, sd->c+dst->pos+1, pos->pos-dst->pos, &dst->lp, -1);
890 route_path_add_item(ret, NULL, dst->lenextra, &dst->lp, NULL, 0, &dst->c, 1);
894 static struct route_path *
895 route_path_new(struct route_graph *this, struct route_path *oldpath, struct route_info *pos, struct route_info *dst, int *speedlist)
897 struct route_graph_point *start1=NULL,*start2=NULL,*start;
898 struct route_graph_segment *s=NULL;
902 int time=0,hr,min,sec
904 unsigned int val1=0xffffffff,val2=0xffffffff;
905 struct street_data *sd=pos->street;
906 struct route_path *ret;
908 if (item_is_equal(pos->street->item, dst->street->item)) {
909 if (!(sd->flags & AF_ONEWAY) && pos->lenneg >= dst->lenneg) {
910 return route_path_new_trivial(this, pos, dst, -1);
912 if (!(sd->flags & AF_ONEWAYREV) && pos->lenpos >= dst->lenpos) {
913 return route_path_new_trivial(this, pos, dst, 1);
916 if (! (sd->flags & AF_ONEWAY)) {
917 start1=route_graph_get_point(this, &sd->c[0]);
920 val1=start1->value+route_value(speedlist, &sd->item, pos->lenneg);
921 dbg(1,"start1: %d(route)+%d=%d\n", start1->value, val1-start1->value, val1);
923 if (! (sd->flags & AF_ONEWAYREV)) {
924 start2=route_graph_get_point(this, &sd->c[sd->count-1]);
927 val2=start2->value+route_value(speedlist, &sd->item, pos->lenpos);
928 dbg(1,"start2: %d(route)+%d=%d\n", start2->value, val2-start2->value, val2);
930 dbg(1,"val1=%d val2=%d\n", val1, val2);
932 val1=start1->start->start->value;
933 val2=start2->end->end->value;
935 ret=g_new0(struct route_path, 1);
937 route_path_add_item(ret, NULL, pos->lenextra, &pos->c, NULL, 0, &pos->lp, 1);
938 if (start1 && (val1 < val2)) {
940 route_path_add_item(ret, &sd->item, pos->lenneg, &pos->lp, sd->c, pos->pos+1, NULL, -1);
944 route_path_add_item(ret, &sd->item, pos->lenpos, &pos->lp, sd->c+pos->pos+1, sd->count-pos->pos-1, NULL, 1);
946 printf("no route found, pos blocked\n");
950 ret->path_hash=item_hash_new();
951 while ((s=start->seg)) {
954 printf("start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y);
958 if (s->start == start) {
959 route_path_add_item_from_graph(ret, oldpath, s, seg_len, s->offset, 1);
962 route_path_add_item_from_graph(ret, oldpath, s, seg_len, s->offset, -1);
967 dbg(1,"start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y);
968 dbg(1,"dst sd->flags=%d sd->c[0]=0x%x,0x%x sd->c[sd->count-1]=0x%x,0x%x\n", sd->flags, sd->c[0].x,sd->c[0].y, sd->c[sd->count-1].x, sd->c[sd->count-1].y);
969 if (start->c.x == sd->c[0].x && start->c.y == sd->c[0].y) {
970 route_path_add_item(ret, &sd->item, dst->lenneg, &dst->lp, sd->c, dst->pos+1, NULL, -1);
971 } else if (start->c.x == sd->c[sd->count-1].x && start->c.y == sd->c[sd->count-1].y) {
972 route_path_add_item(ret, &sd->item, dst->lenpos, &dst->lp, sd->c+dst->pos+1, sd->count-dst->pos-1, NULL, 1);
974 printf("no route found\n");
975 route_path_destroy(ret);
979 route_path_add_item(ret, NULL, dst->lenextra, &dst->lp, NULL, 0, &dst->c, 1);
980 dbg(1, "%d segments\n", segs);
984 static struct route_graph *
985 route_graph_build(struct mapset *ms, struct coord *c1, struct coord *c2)
987 struct route_graph *ret=g_new0(struct route_graph, 1);
988 struct map_selection *sel;
989 struct mapset_handle *h;
995 printf("%s:Out of memory\n", __FUNCTION__);
998 sel=route_calc_selection(c1, c2);
1000 while ((m=mapset_next(h,1))) {
1001 mr=map_rect_new(m, sel);
1004 while ((item=map_rect_get_item(mr))) {
1005 if (item->type >= type_street_0 && item->type <= type_ferry) {
1006 route_process_street_graph(ret, item);
1009 map_rect_destroy(mr);
1012 route_free_selection(sel);
1018 route_graph_update(struct route *this)
1020 route_graph_destroy(this->graph);
1021 profile(1,"graph_free");
1022 this->graph=route_graph_build(this->ms, &this->pos->c, &this->dst->c);
1023 profile(1,"route_graph_build");
1024 route_graph_flood(this->graph, this->dst, this->speedlist);
1025 profile(1,"route_graph_flood");
1029 struct street_data *
1030 street_get_data (struct item *item)
1033 struct coord c[maxcount];
1035 struct street_data *ret;
1038 while (count < maxcount) {
1039 if (!item_coord_get(item, &c[count], 1))
1043 if (count >= maxcount) {
1044 dbg(0, "count=%d maxcount=%d id_hi=0x%x id_lo=0x%x\n", count, maxcount, item->id_hi, item->id_lo);
1045 if (item_attr_get(item, attr_debug, &attr))
1046 dbg(0,"debug='%s'\n", attr.u.str);
1048 g_assert(count < maxcount);
1049 ret=g_malloc(sizeof(struct street_data)+count*sizeof(struct coord));
1052 if (item_attr_get(item, attr_flags, &attr))
1053 ret->flags=attr.u.num;
1056 memcpy(ret->c, c, count*sizeof(struct coord));
1061 struct street_data *
1062 street_data_dup(struct street_data *orig)
1064 struct street_data *ret;
1065 int size=sizeof(struct street_data)+orig->count*sizeof(struct coord);
1068 memcpy(ret, orig, size);
1074 street_data_free(struct street_data *sd)
1079 static struct route_info *
1080 route_find_nearest_street(struct mapset *ms, struct pcoord *pc)
1082 struct route_info *ret=NULL;
1084 struct map_selection *sel;
1085 int dist,mindist=0,pos;
1086 struct mapset_handle *h;
1088 struct map_rect *mr;
1091 struct street_data *sd;
1098 * This is not correct for two reasons:
1099 * - You may need to go back first
1100 * - Currently we allow mixing of mapsets
1102 sel = route_rect(18, &c, &c, 0, max_dist);
1104 while ((m=mapset_next(h,1))) {
1107 if (map_projection(m) != pc->pro) {
1108 transform_to_geo(pc->pro, &c, &g);
1109 transform_from_geo(map_projection(m), &g, &c);
1111 mr=map_rect_new(m, sel);
1114 while ((item=map_rect_get_item(mr))) {
1115 if (item->type >= type_street_0 && item->type <= type_ferry) {
1116 sd=street_get_data(item);
1117 dist=transform_distance_polyline_sq(sd->c, sd->count, &c, &lp, &pos);
1118 if (!ret || dist < mindist) {
1120 street_data_free(ret->street);
1123 ret=g_new(struct route_info, 1);
1125 printf("%s:Out of memory\n", __FUNCTION__);
1133 dbg(1,"dist=%d id 0x%x 0x%x pos=%d\n", dist, item->id_hi, item->id_lo, pos);
1135 street_data_free(sd);
1138 map_rect_destroy(mr);
1141 map_selection_destroy(sel);
1147 route_info_free(struct route_info *inf)
1150 street_data_free(inf->street);
1157 struct street_data *
1158 route_info_street(struct route_info *rinf)
1160 return rinf->street;
1164 struct route_crossings *
1165 route_crossings_get(struct route *this, struct coord *c)
1167 struct route_point *pnt;
1168 struct route_segment *seg;
1170 struct route_crossings *ret;
1172 pnt=route_graph_get_point(this, c);
1175 printf("start: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo);
1177 seg=seg->start_next;
1181 printf("end: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo);
1185 ret=g_malloc(sizeof(struct route_crossings)+crossings*sizeof(struct route_crossing));
1186 ret->count=crossings;
1192 struct map_rect_priv {
1193 struct route_info_handle *ri;
1194 enum attr_type attr_next;
1196 struct map_priv *mpriv;
1199 unsigned int last_coord;
1200 struct route_path_segment *seg,*seg_next;
1201 struct route_graph_point *point;
1202 struct route_graph_segment *rseg;
1207 rm_coord_rewind(void *priv_data)
1209 struct map_rect_priv *mr = priv_data;
1214 rm_attr_rewind(void *priv_data)
1216 struct map_rect_priv *mr = priv_data;
1217 mr->attr_next = attr_street_item;
1221 rm_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
1223 struct map_rect_priv *mr = priv_data;
1224 struct route_path_segment *seg=mr->seg;
1225 struct route *route=mr->mpriv->route;
1226 attr->type=attr_type;
1227 switch (attr_type) {
1229 while (mr->attr_next != attr_none) {
1230 if (rm_attr_get(priv_data, mr->attr_next, attr))
1234 case attr_street_item:
1235 mr->attr_next=attr_direction;
1236 if (seg && seg->item.map)
1237 attr->u.item=&seg->item;
1241 case attr_direction:
1242 mr->attr_next=attr_length;
1244 attr->u.num=seg->direction;
1250 attr->u.num=seg->length;
1252 attr->u.num=mr->length;
1253 mr->attr_next=attr_time;
1256 mr->attr_next=attr_none;
1258 attr->u.num=route_time(route->speedlist, &seg->item, seg->length);
1263 attr->type=attr_none;
1270 rm_coord_get(void *priv_data, struct coord *c, int count)
1272 struct map_rect_priv *mr = priv_data;
1273 struct route_path_segment *seg = mr->seg;
1277 for (i=0; i < count; i++) {
1278 if (mr->last_coord >= seg->ncoords)
1280 if (i >= seg->ncoords)
1282 c[i] = seg->c[mr->last_coord++];
1285 dbg(1,"return %d\n",rc);
1289 static struct item_methods methods_route_item = {
1297 rp_attr_rewind(void *priv_data)
1299 struct map_rect_priv *mr = priv_data;
1300 mr->attr_next = attr_label;
1304 rp_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
1306 struct map_rect_priv *mr = priv_data;
1307 struct route_graph_point *p = mr->point;
1308 if (mr->item.type != type_rg_point)
1310 switch (attr_type) {
1312 while (mr->attr_next != attr_none) {
1313 if (rm_attr_get(priv_data, mr->attr_next, attr))
1317 attr->type = attr_label;
1320 if (p->value != INT_MAX)
1321 mr->str=g_strdup_printf("%d", p->value);
1323 mr->str=g_strdup("-");
1324 attr->u.str = mr->str;
1325 mr->attr_next=attr_none;
1328 attr->type = attr_debug;
1331 mr->str=g_strdup_printf("x=%d y=%d", p->c.x, p->c.y);
1332 attr->u.str = mr->str;
1333 mr->attr_next=attr_none;
1341 rp_coord_get(void *priv_data, struct coord *c, int count)
1343 struct map_rect_priv *mr = priv_data;
1344 struct route_graph_point *p = mr->point;
1345 struct route_graph_segment *seg = mr->rseg;
1347 for (i=0; i < count; i++) {
1348 if (mr->item.type == type_rg_point) {
1349 if (mr->last_coord >= 1)
1353 if (mr->last_coord >= 2)
1356 if (seg->end->seg == seg)
1363 c[i] = seg->start->c;
1371 static struct item_methods methods_point_item = {
1379 rm_destroy(struct map_priv *priv)
1384 static struct map_rect_priv *
1385 rm_rect_new(struct map_priv *priv, struct map_selection *sel)
1387 struct map_rect_priv * mr;
1389 if (! route_get_pos(priv->route))
1391 if (! route_get_dst(priv->route))
1393 if (! priv->route->path2)
1395 mr=g_new0(struct map_rect_priv, 1);
1397 mr->item.priv_data = mr;
1398 mr->item.type = type_street_route;
1399 mr->item.meth = &methods_route_item;
1400 mr->seg_next=priv->route->path2->path;
1404 static struct map_rect_priv *
1405 rp_rect_new(struct map_priv *priv, struct map_selection *sel)
1407 struct map_rect_priv * mr;
1409 if (! priv->route->graph || ! priv->route->graph->route_points)
1411 mr=g_new0(struct map_rect_priv, 1);
1413 mr->item.priv_data = mr;
1414 mr->item.type = type_rg_point;
1415 mr->item.meth = &methods_point_item;
1420 rm_rect_destroy(struct map_rect_priv *mr)
1427 static struct item *
1428 rp_get_item(struct map_rect_priv *mr)
1430 struct route *r = mr->mpriv->route;
1431 struct route_graph_point *p = mr->point;
1432 struct route_graph_segment *seg = mr->rseg;
1434 if (mr->item.type == type_rg_point) {
1436 p = r->graph->route_points;
1442 rm_coord_rewind(mr);
1446 mr->item.type = type_rg_segment;
1449 seg=r->graph->route_segments;
1455 rm_coord_rewind(mr);
1463 static struct item *
1464 rp_get_item_byid(struct map_rect_priv *mr, int id_hi, int id_lo)
1466 struct item *ret=NULL;
1468 ret=rp_get_item(mr);
1473 static struct item *
1474 rm_get_item(struct map_rect_priv *mr)
1476 struct route *r = mr->mpriv->route;
1477 struct route_path_segment *seg = mr->seg;
1478 dbg(1,"enter\n", mr->pos);
1480 mr->seg=mr->seg_next;
1483 mr->seg_next=mr->seg->next;
1490 static struct item *
1491 rm_get_item_byid(struct map_rect_priv *mr, int id_hi, int id_lo)
1493 struct item *ret=NULL;
1495 ret=rm_get_item(mr);
1499 static struct map_methods route_meth = {
1512 static struct map_methods route_graph_meth = {
1526 route_toggle_routegraph_display(struct route *route)
1528 if (route->flags & RF_SHOWGRAPH) {
1529 route->flags &= ~RF_SHOWGRAPH;
1531 route->flags |= RF_SHOWGRAPH;
1535 static struct map_priv *
1536 route_map_new_helper(struct map_methods *meth, struct attr **attrs, int graph)
1538 struct map_priv *ret;
1539 struct attr *route_attr;
1541 route_attr=attr_search(attrs, NULL, attr_route);
1544 ret=g_new0(struct map_priv, 1);
1546 *meth=route_graph_meth;
1549 ret->route=route_attr->u.route;
1554 static struct map_priv *
1555 route_map_new(struct map_methods *meth, struct attr **attrs)
1557 return route_map_new_helper(meth, attrs, 0);
1560 static struct map_priv *
1561 route_graph_map_new(struct map_methods *meth, struct attr **attrs)
1563 return route_map_new_helper(meth, attrs, 1);
1567 route_get_map_helper(struct route *this_, struct map **map, char *type, char *description)
1570 *map=map_new((struct attr*[]){
1571 &(struct attr){attr_type,{type}},
1572 &(struct attr){attr_route,.u.route=this_},
1573 &(struct attr){attr_data,{""}},
1574 &(struct attr){attr_description,{description}},
1580 route_get_map(struct route *this_)
1582 return route_get_map_helper(this_, &this_->map, "route","Route");
1587 route_get_graph_map(struct route *this_)
1589 return route_get_map_helper(this_, &this_->graph_map, "route_graph","Route Graph");
1593 route_set_projection(struct route *this_, enum projection pro)
1600 plugin_register_map_type("route", route_map_new);
1601 plugin_register_map_type("route_graph", route_graph_map_new);