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;
95 struct street_data *street;
99 struct route_path_segment *path;
100 struct route_path_segment *path_last;
101 /* XXX: path_hash is not necessery now */
102 struct item_hash *path_hash;
105 #define RF_FASTEST (1<<0)
106 #define RF_SHORTEST (1<<1)
107 #define RF_AVOIDHW (1<<2)
108 #define RF_AVOIDPAID (1<<3)
109 #define RF_LOCKONROAD (1<<4)
110 #define RF_SHOWGRAPH (1<<5)
116 struct route_info *pos;
117 struct route_info *dst;
119 struct route_graph *graph;
120 struct route_path *path2;
122 struct map *graph_map;
123 int speedlist[route_item_last-route_item_first+1];
127 struct route_graph_point *route_points;
128 struct route_graph_segment *route_segments;
129 #define HASH_SIZE 8192
130 struct route_graph_point *hash[HASH_SIZE];
133 #define HASHCOORD(c) ((((c)->x +(c)->y) * 2654435761UL) & (HASH_SIZE-1))
135 static struct route_info * route_find_nearest_street(struct mapset *ms, struct pcoord *c);
136 static struct route_graph_point *route_graph_get_point(struct route_graph *this, struct coord *c);
137 static void route_graph_update(struct route *this);
138 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);
139 static void route_process_street_graph(struct route_graph *this, struct item *item);
140 static void route_graph_destroy(struct route_graph *this);
141 static void route_path_update(struct route *this);
143 static enum projection route_projection(struct route *route)
145 struct street_data *street;
146 street = route->pos ? route->pos->street : route->dst->street;
147 return map_projection(street->item.map);
151 route_path_destroy(struct route_path *this)
153 struct route_path_segment *c,*n;
156 if (this->path_hash) {
157 item_hash_destroy(this->path_hash);
158 this->path_hash=NULL;
170 route_new(struct attr **attrs)
172 struct route *this=g_new0(struct route, 1);
174 printf("%s:Out of memory\n", __FUNCTION__);
181 route_set_mapset(struct route *this, struct mapset *ms)
187 route_get_mapset(struct route *this)
193 route_get_pos(struct route *this)
199 route_get_dst(struct route *this)
205 route_get_speedlist(struct route *this)
207 return this->speedlist;
211 route_get_path_set(struct route *this)
213 return this->path2 != NULL;
217 route_set_speed(struct route *this, enum item_type type, int value)
219 if (type < route_item_first || type > route_item_last) {
220 dbg(0,"street type %d out of range [%d,%d]", type, route_item_first, route_item_last);
223 this->speedlist[type-route_item_first]=value;
228 route_contains(struct route *this, struct item *item)
230 if (! this->path2 || !this->path2->path_hash)
232 return (int)item_hash_lookup(this->path2->path_hash, item);
236 route_pos_contains(struct route *this, struct item *item)
240 return item_is_equal(this->pos->street->item, *item);
245 route_path_update(struct route *this)
247 struct route_path *oldpath = NULL;
248 if (! this->pos || ! this->dst) {
249 route_path_destroy(this->path2);
253 /* the graph is destroyed when setting the destination */
254 if (this->graph && this->pos && this->dst && this->path2) {
255 // we can try to update
256 oldpath = this->path2;
259 if (! this->graph || !(this->path2=route_path_new(this->graph, oldpath, this->pos, this->dst, this->speedlist))) {
261 route_graph_update(this);
262 this->path2=route_path_new(this->graph, oldpath, this->pos, this->dst, this->speedlist);
263 profile(1,"route_path_new");
267 /* Destroy what's left */
268 route_path_destroy(oldpath);
273 route_info_distances(struct route_info *ri, enum projection pro)
276 struct street_data *sd=ri->street;
277 /* 0 1 2 X 3 4 5 6 pos=2 npos=3 count=7 0,1,2 3,4,5,6*/
278 ri->lenextra=transform_distance(pro, &ri->lp, &ri->c);
279 ri->lenneg=transform_polyline_length(pro, sd->c, npos)+transform_distance(pro, &sd->c[ri->pos], &ri->lp);
280 ri->lenpos=transform_polyline_length(pro, sd->c+npos, sd->count-npos)+transform_distance(pro, &sd->c[npos], &ri->lp);
284 route_set_position(struct route *this, struct pcoord *pos)
287 route_info_free(this->pos);
289 this->pos=route_find_nearest_street(this->ms, pos);
290 dbg(1,"this->pos=%p\n", this->pos);
293 route_info_distances(this->pos, pos->pro);
295 route_path_update(this);
299 route_set_position_from_tracking(struct route *this, struct tracking *tracking)
302 struct route_info *ret;
305 c=tracking_get_pos(tracking);
306 ret=g_new0(struct route_info, 1);
308 printf("%s:Out of memory\n", __FUNCTION__);
312 route_info_free(this->pos);
316 ret->pos=tracking_get_segment_pos(tracking);
317 ret->street=street_data_dup(tracking_get_street_data(tracking));
318 route_info_distances(ret, projection_mg);
319 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);
320 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);
323 route_path_update(this);
327 /* Used for debuging of route_rect, what routing sees */
328 struct map_selection *route_selection;
330 struct map_selection *
331 route_rect(int order, struct coord *c1, struct coord *c2, int rel, int abs)
333 int dx,dy,sx=1,sy=1,d,m;
334 struct map_selection *sel=g_new(struct map_selection, 1);
336 printf("%s:Out of memory\n", __FUNCTION__);
339 sel->order[layer_town]=0;
340 sel->order[layer_poly]=0;
341 sel->order[layer_street]=order;
342 dbg(1,"%p %p\n", c1, c2);
347 sel->u.c_rect.lu.x=c1->x;
348 sel->u.c_rect.rl.x=c2->x;
350 sel->u.c_rect.lu.x=c2->x;
351 sel->u.c_rect.rl.x=c1->x;
355 sel->u.c_rect.lu.y=c2->y;
356 sel->u.c_rect.rl.y=c1->y;
358 sel->u.c_rect.lu.y=c1->y;
359 sel->u.c_rect.rl.y=c2->y;
366 sel->u.c_rect.lu.x-=m;
367 sel->u.c_rect.rl.x+=m;
368 sel->u.c_rect.lu.y+=m;
369 sel->u.c_rect.rl.y-=m;
374 static struct map_selection *
375 route_calc_selection(struct coord *c1, struct coord *c2)
377 struct map_selection *ret,*sel;
378 sel=route_rect(4, c1, c2, 25, 0);
380 sel->next=route_rect(8, c1, c1, 0, 40000);
382 sel->next=route_rect(18, c1, c1, 0, 10000);
384 sel->next=route_rect(8, c2, c2, 0, 40000);
386 sel->next=route_rect(18, c2, c2, 0, 10000);
387 /* route_selection=ret; */
392 route_free_selection(struct map_selection *sel)
394 struct map_selection *next;
406 route_set_destination(struct route *this, struct pcoord *dst)
410 route_info_free(this->dst);
413 this->dst=route_find_nearest_street(this->ms, dst);
414 route_info_distances(this->dst, dst->pro);
415 profile(1,"find_nearest_street");
416 route_graph_destroy(this->graph);
418 route_path_update(this);
422 static struct route_graph_point *
423 route_graph_get_point(struct route_graph *this, struct coord *c)
425 struct route_graph_point *p;
426 int hashval=HASHCOORD(c);
427 p=this->hash[hashval];
429 if (p->c.x == c->x && p->c.y == c->y)
437 static struct route_graph_point *
438 route_graph_add_point(struct route_graph *this, struct coord *f)
441 struct route_graph_point *p;
443 p=route_graph_get_point(this,f);
445 hashval=HASHCOORD(f);
447 printf("p (0x%x,0x%x)\n", f->x, f->y);
448 p=g_new(struct route_graph_point,1);
450 printf("%s:Out of memory\n", __FUNCTION__);
453 p->hash_next=this->hash[hashval];
454 this->hash[hashval]=p;
455 p->next=this->route_points;
462 this->route_points=p;
469 route_graph_free_points(struct route_graph *this)
471 struct route_graph_point *curr,*next;
472 curr=this->route_points;
478 this->route_points=NULL;
479 memset(this->hash, 0, sizeof(this->hash));
483 route_graph_add_segment(struct route_graph *this, struct route_graph_point *start,
484 struct route_graph_point *end, int len, struct item *item,
485 int flags, int offset)
487 struct route_graph_segment *s;
488 s = g_new0(struct route_graph_segment, 1);
490 printf("%s:Out of memory\n", __FUNCTION__);
494 s->start_next=start->start;
497 s->end_next=end->end;
504 s->next=this->route_segments;
505 this->route_segments=s;
507 printf("l (0x%x,0x%x)-(0x%x,0x%x)\n", start->c.x, start->c.y, end->c.x, end->c.y);
510 static int get_item_seg_coords(struct item *i, struct coord *c, int max,
511 struct coord *start, struct coord *end)
517 mr=map_rect_new(i->map, NULL);
520 item = map_rect_get_item_byid(mr, i->id_hi, i->id_lo);
522 rc = item_coord_get(item, &c1, 1);
523 while (rc && (c1.x != start->x || c1.y != start->y)) {
524 rc = item_coord_get(item, &c1, 1);
526 while (rc && p < max) {
528 if (c1.x == end->x && c1.y == end->y)
530 rc = item_coord_get(item, &c1, 1);
533 map_rect_destroy(mr);
537 static struct route_path_segment *
538 route_extract_segment_from_path(struct route_path *path, struct item *item,
541 struct route_path_segment *sp = NULL, *s;
544 if (s->offset == offset && item_is_equal(s->item,*item)) {
549 path->path = s->next;
557 item_hash_remove(path->path_hash, item);
562 route_path_add_segment(struct route_path *this, struct route_path_segment *segment)
567 this->path_last->next=segment;
568 this->path_last=segment;
572 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)
574 int i,idx=0,ccount=count + (first ? 1:0) + (last ? 1:0);
575 struct route_path_segment *segment;
577 segment=g_malloc0(sizeof(*segment) + sizeof(struct coord) * ccount);
578 segment->ncoords=ccount;
580 segment->c[idx++]=*first;
582 for (i = 0 ; i < count ; i++)
583 segment->c[idx++]=c[i];
585 for (i = 0 ; i < count ; i++)
586 segment->c[idx++]=c[count-i-1];
589 segment->c[idx++]=*last;
593 route_path_add_segment(this, segment);
597 route_path_add_item_from_graph(struct route_path *this, struct route_path *oldpath,
598 struct route_graph_segment *rgs, int len, int offset, int dir)
600 struct route_path_segment *segment;
602 struct coord ca[2048];
605 ccnt = (int)item_hash_lookup(oldpath->path_hash, &rgs->item);
607 segment = route_extract_segment_from_path(oldpath,
614 ccnt = get_item_seg_coords(&rgs->item, ca, 2047, &rgs->start->c, &rgs->end->c);
615 segment= g_malloc0(sizeof(*segment) + sizeof(struct coord) * ccnt);
617 printf("%s:Out of memory\n", __FUNCTION__);
621 for (i = 0 ; i < ccnt ; i++)
624 for (i = 0 ; i < ccnt ; i++)
625 segment->c[i]=ca[ccnt-i-1];
627 segment->ncoords = ccnt;
628 segment->item=rgs->item;
629 segment->offset = offset;
633 item_hash_insert(this->path_hash, &rgs->item, (void *)ccnt);
634 route_path_add_segment(this, segment);
638 route_graph_free_segments(struct route_graph *this)
640 struct route_graph_segment *curr,*next;
641 curr=this->route_segments;
647 this->route_segments=NULL;
651 route_graph_destroy(struct route_graph *this)
654 route_graph_free_points(this);
655 route_graph_free_segments(this);
661 route_time(int *speedlist, struct item *item, int len)
663 if (item->type < route_item_first || item->type > route_item_last) {
664 dbg(0,"street type %d out of range [%d,%d]", item->type, route_item_first, route_item_last);
667 return len*36/speedlist[item->type-route_item_first];
672 route_value(int *speedlist, struct item *item, int len)
676 printf("len=%d\n", len);
679 ret=route_time(speedlist, item, len);
680 dbg(1, "route_value(0x%x, %d)=%d\n", item->type, len, ret);
685 route_process_street_graph(struct route_graph *this, struct item *item)
692 struct route_graph_point *s_pnt,*e_pnt;
699 if (item_coord_get(item, &l, 1)) {
700 if (item_attr_get(item, attr_flags, &attr)) {
702 if (flags & AF_SEGMENTED)
705 s_pnt=route_graph_add_point(this,&l);
707 while (item_coord_get(item, &c, 1)) {
708 len+=transform_distance(map_projection(item->map), &l, &c);
711 e_pnt=route_graph_add_point(this,&l);
713 route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset);
718 isseg = item_coord_is_segment(item);
719 rc = item_coord_get(item, &c, 1);
721 len+=transform_distance(map_projection(item->map), &l, &c);
724 e_pnt=route_graph_add_point(this,&l);
725 route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset);
727 s_pnt=route_graph_add_point(this,&l);
732 e_pnt=route_graph_add_point(this,&l);
735 route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset);
741 compare(void *v1, void *v2)
743 struct route_graph_point *p1=v1;
744 struct route_graph_point *p2=v2;
747 printf("compare %d (%p) vs %d (%p)\n", p1->value,p1,p2->value,p2);
749 return p1->value-p2->value;
753 route_graph_flood(struct route_graph *this, struct route_info *dst, int *speedlist)
755 struct route_graph_point *p_min,*end=NULL;
756 struct route_graph_segment *s;
758 struct fibheap *heap;
759 struct street_data *sd=dst->street;
761 heap = fh_makeheap();
762 fh_setcmp(heap, compare);
764 if (! (sd->flags & AF_ONEWAYREV)) {
765 end=route_graph_get_point(this, &sd->c[0]);
767 end->value=route_value(speedlist, &sd->item, dst->lenneg);
768 end->el=fh_insert(heap, end);
771 if (! (sd->flags & AF_ONEWAY)) {
772 end=route_graph_get_point(this, &sd->c[sd->count-1]);
774 end->value=route_value(speedlist, &sd->item, dst->lenpos);
775 end->el=fh_insert(heap, end);
778 dbg(1,"0x%x,0x%x\n", end->c.x, end->c.y);
780 p_min=fh_extractmin(heap);
785 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);
789 val=route_value(speedlist, &s->item, s->len);
791 val+=val*2*street_route_contained(s->str->segid);
795 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);
796 if (new < s->end->value && !(s->flags & AF_ONEWAY)) {
801 printf("insert_end p=%p el=%p val=%d ", s->end, s->end->el, s->end->value);
802 s->end->el=fh_insert(heap, s->end);
804 printf("el new=%p\n", s->end->el);
808 printf("replace_end p=%p el=%p val=%d\n", s->end, s->end->el, s->end->value);
809 fh_replacedata(heap, s->end->el, s->end);
818 val=route_value(speedlist, &s->item, s->len);
821 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);
822 if (new < s->start->value && !(s->flags & AF_ONEWAYREV)) {
826 if (! s->start->el) {
828 printf("insert_start p=%p el=%p val=%d ", s->start, s->start->el, s->start->value);
829 s->start->el=fh_insert(heap, s->start);
831 printf("el new=%p\n", s->start->el);
835 printf("replace_start p=%p el=%p val=%d\n", s->start, s->start->el, s->start->value);
836 fh_replacedata(heap, s->start->el, s->start);
847 static struct route_path *
848 route_path_new_offroad(struct route_graph *this, struct route_info *pos, struct route_info *dst, int dir)
850 struct route_path *ret;
852 ret=g_new0(struct route_path, 1);
853 ret->path_hash=item_hash_new();
854 route_path_add_item(ret, NULL, pos->lenextra+dst->lenextra, &pos->c, NULL, 0, &dst->c, 1);
859 static struct route_path *
860 route_path_new_trivial(struct route_graph *this, struct route_info *pos, struct route_info *dst, int dir)
862 struct street_data *sd=pos->street;
863 struct route_path *ret;
866 if (pos->lenextra + dst->lenextra + pos->lenneg-dst->lenneg > transform_distance(map_projection(sd->item.map), &pos->c, &dst->c))
867 return route_path_new_offroad(this, pos, dst, dir);
869 if (pos->lenextra + dst->lenextra + pos->lenpos-dst->lenpos > transform_distance(map_projection(sd->item.map), &pos->c, &dst->c))
870 return route_path_new_offroad(this, pos, dst, dir);
872 ret=g_new0(struct route_path, 1);
873 ret->path_hash=item_hash_new();
875 route_path_add_item(ret, NULL, pos->lenextra, &pos->c, NULL, 0, &pos->lp, 1);
877 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);
879 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);
881 route_path_add_item(ret, NULL, dst->lenextra, &dst->lp, NULL, 0, &dst->c, 1);
885 static struct route_path *
886 route_path_new(struct route_graph *this, struct route_path *oldpath, struct route_info *pos, struct route_info *dst, int *speedlist)
888 struct route_graph_point *start1=NULL,*start2=NULL,*start;
889 struct route_graph_segment *s=NULL;
893 int time=0,hr,min,sec
895 unsigned int val1=0xffffffff,val2=0xffffffff;
896 struct street_data *sd=pos->street;
897 struct route_path *ret;
899 if (item_is_equal(pos->street->item, dst->street->item)) {
900 if (!(sd->flags & AF_ONEWAY) && pos->lenneg >= dst->lenneg) {
901 return route_path_new_trivial(this, pos, dst, -1);
903 if (!(sd->flags & AF_ONEWAYREV) && pos->lenpos >= dst->lenpos) {
904 return route_path_new_trivial(this, pos, dst, 1);
907 if (! (sd->flags & AF_ONEWAY)) {
908 start1=route_graph_get_point(this, &sd->c[0]);
911 val1=start1->value+route_value(speedlist, &sd->item, pos->lenneg);
912 dbg(1,"start1: %d(route)+%d=%d\n", start1->value, val1-start1->value, val1);
914 if (! (sd->flags & AF_ONEWAYREV)) {
915 start2=route_graph_get_point(this, &sd->c[sd->count-1]);
918 val2=start2->value+route_value(speedlist, &sd->item, pos->lenpos);
919 dbg(1,"start2: %d(route)+%d=%d\n", start2->value, val2-start2->value, val2);
921 dbg(1,"val1=%d val2=%d\n", val1, val2);
923 val1=start1->start->start->value;
924 val2=start2->end->end->value;
926 ret=g_new0(struct route_path, 1);
928 route_path_add_item(ret, NULL, pos->lenextra, &pos->c, NULL, 0, &pos->lp, 1);
929 if (start1 && (val1 < val2)) {
931 route_path_add_item(ret, &sd->item, pos->lenneg, &pos->lp, sd->c, pos->pos+1, NULL, -1);
935 route_path_add_item(ret, &sd->item, pos->lenpos, &pos->lp, sd->c+pos->pos+1, sd->count-pos->pos-1, NULL, 1);
937 printf("no route found, pos blocked\n");
941 ret->path_hash=item_hash_new();
942 while ((s=start->seg)) {
945 printf("start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y);
949 if (s->start == start) {
950 route_path_add_item_from_graph(ret, oldpath, s, seg_len, s->offset, 1);
953 route_path_add_item_from_graph(ret, oldpath, s, seg_len, s->offset, -1);
958 dbg(1,"start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y);
959 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);
960 if (start->c.x == sd->c[0].x && start->c.y == sd->c[0].y) {
961 route_path_add_item(ret, &sd->item, dst->lenneg, &dst->lp, sd->c, dst->pos+1, NULL, -1);
962 } else if (start->c.x == sd->c[sd->count-1].x && start->c.y == sd->c[sd->count-1].y) {
963 route_path_add_item(ret, &sd->item, dst->lenpos, &dst->lp, sd->c+dst->pos+1, sd->count-dst->pos-1, NULL, 1);
965 printf("no route found\n");
966 route_path_destroy(ret);
970 route_path_add_item(ret, NULL, dst->lenextra, &dst->lp, NULL, 0, &dst->c, 1);
971 dbg(1, "%d segments\n", segs);
975 static struct route_graph *
976 route_graph_build(struct mapset *ms, struct coord *c1, struct coord *c2)
978 struct route_graph *ret=g_new0(struct route_graph, 1);
979 struct map_selection *sel;
980 struct mapset_handle *h;
986 printf("%s:Out of memory\n", __FUNCTION__);
989 sel=route_calc_selection(c1, c2);
991 while ((m=mapset_next(h,1))) {
992 mr=map_rect_new(m, sel);
995 while ((item=map_rect_get_item(mr))) {
996 if (item->type >= type_street_0 && item->type <= type_ferry) {
997 route_process_street_graph(ret, item);
1000 map_rect_destroy(mr);
1003 route_free_selection(sel);
1009 route_graph_update(struct route *this)
1011 route_graph_destroy(this->graph);
1012 profile(1,"graph_free");
1013 this->graph=route_graph_build(this->ms, &this->pos->c, &this->dst->c);
1014 profile(1,"route_graph_build");
1015 route_graph_flood(this->graph, this->dst, this->speedlist);
1016 profile(1,"route_graph_flood");
1020 struct street_data *
1021 street_get_data (struct item *item)
1024 struct coord c[maxcount];
1026 struct street_data *ret;
1029 while (count < maxcount) {
1030 if (!item_coord_get(item, &c[count], 1))
1034 if (count >= maxcount) {
1035 dbg(0, "count=%d maxcount=%d id_hi=0x%x id_lo=0x%x\n", count, maxcount, item->id_hi, item->id_lo);
1036 if (item_attr_get(item, attr_debug, &attr))
1037 dbg(0,"debug='%s'\n", attr.u.str);
1039 g_assert(count < maxcount);
1040 ret=g_malloc(sizeof(struct street_data)+count*sizeof(struct coord));
1043 if (item_attr_get(item, attr_flags, &attr))
1044 ret->flags=attr.u.num;
1047 memcpy(ret->c, c, count*sizeof(struct coord));
1052 struct street_data *
1053 street_data_dup(struct street_data *orig)
1055 struct street_data *ret;
1056 int size=sizeof(struct street_data)+orig->count*sizeof(struct coord);
1059 memcpy(ret, orig, size);
1065 street_data_free(struct street_data *sd)
1070 static struct route_info *
1071 route_find_nearest_street(struct mapset *ms, struct pcoord *pc)
1073 struct route_info *ret=NULL;
1075 struct map_selection *sel;
1076 int dist,mindist=0,pos;
1077 struct mapset_handle *h;
1079 struct map_rect *mr;
1082 struct street_data *sd;
1089 * This is not correct for two reasons:
1090 * - You may need to go back first
1091 * - Currently we allow mixing of mapsets
1093 sel = route_rect(18, &c, &c, 0, max_dist);
1095 while ((m=mapset_next(h,1))) {
1098 if (map_projection(m) != pc->pro) {
1099 transform_to_geo(pc->pro, &c, &g);
1100 transform_from_geo(map_projection(m), &g, &c);
1102 mr=map_rect_new(m, sel);
1105 while ((item=map_rect_get_item(mr))) {
1106 if (item->type >= type_street_0 && item->type <= type_ferry) {
1107 sd=street_get_data(item);
1108 dist=transform_distance_polyline_sq(sd->c, sd->count, &c, &lp, &pos);
1109 if (!ret || dist < mindist) {
1111 street_data_free(ret->street);
1114 ret=g_new(struct route_info, 1);
1116 printf("%s:Out of memory\n", __FUNCTION__);
1124 dbg(1,"dist=%d id 0x%x 0x%x pos=%d\n", dist, item->id_hi, item->id_lo, pos);
1126 street_data_free(sd);
1129 map_rect_destroy(mr);
1132 map_selection_destroy(sel);
1138 route_info_free(struct route_info *inf)
1141 street_data_free(inf->street);
1148 struct street_data *
1149 route_info_street(struct route_info *rinf)
1151 return rinf->street;
1155 struct route_crossings *
1156 route_crossings_get(struct route *this, struct coord *c)
1158 struct route_point *pnt;
1159 struct route_segment *seg;
1161 struct route_crossings *ret;
1163 pnt=route_graph_get_point(this, c);
1166 printf("start: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo);
1168 seg=seg->start_next;
1172 printf("end: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo);
1176 ret=g_malloc(sizeof(struct route_crossings)+crossings*sizeof(struct route_crossing));
1177 ret->count=crossings;
1183 struct map_rect_priv {
1184 struct route_info_handle *ri;
1185 enum attr_type attr_next;
1187 struct map_priv *mpriv;
1190 unsigned int last_coord;
1191 struct route_path_segment *seg,*seg_next;
1192 struct route_graph_point *point;
1193 struct route_graph_segment *rseg;
1198 rm_coord_rewind(void *priv_data)
1200 struct map_rect_priv *mr = priv_data;
1205 rm_attr_rewind(void *priv_data)
1207 struct map_rect_priv *mr = priv_data;
1208 mr->attr_next = attr_street_item;
1212 rm_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
1214 struct map_rect_priv *mr = priv_data;
1215 struct route_path_segment *seg=mr->seg;
1216 struct route *route=mr->mpriv->route;
1217 attr->type=attr_type;
1218 switch (attr_type) {
1220 while (mr->attr_next != attr_none) {
1221 if (rm_attr_get(priv_data, mr->attr_next, attr))
1225 case attr_street_item:
1226 mr->attr_next=attr_length;
1227 if (seg && seg->item.map)
1228 attr->u.item=&seg->item;
1234 attr->u.num=seg->length;
1236 attr->u.num=mr->length;
1237 mr->attr_next=attr_time;
1240 mr->attr_next=attr_none;
1242 attr->u.num=route_time(route->speedlist, &seg->item, seg->length);
1247 attr->type=attr_none;
1254 rm_coord_get(void *priv_data, struct coord *c, int count)
1256 struct map_rect_priv *mr = priv_data;
1257 struct route_path_segment *seg = mr->seg;
1261 for (i=0; i < count; i++) {
1262 if (mr->last_coord >= seg->ncoords)
1264 if (i >= seg->ncoords)
1266 c[i] = seg->c[mr->last_coord++];
1269 dbg(1,"return %d\n",rc);
1273 static struct item_methods methods_route_item = {
1281 rp_attr_rewind(void *priv_data)
1283 struct map_rect_priv *mr = priv_data;
1284 mr->attr_next = attr_label;
1288 rp_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
1290 struct map_rect_priv *mr = priv_data;
1291 struct route_graph_point *p = mr->point;
1292 if (mr->item.type != type_rg_point)
1294 switch (attr_type) {
1296 while (mr->attr_next != attr_none) {
1297 if (rm_attr_get(priv_data, mr->attr_next, attr))
1301 attr->type = attr_label;
1304 if (p->value != INT_MAX)
1305 mr->str=g_strdup_printf("%d", p->value);
1307 mr->str=g_strdup("-");
1308 attr->u.str = mr->str;
1309 mr->attr_next=attr_none;
1312 attr->type = attr_debug;
1315 mr->str=g_strdup_printf("x=%d y=%d", p->c.x, p->c.y);
1316 attr->u.str = mr->str;
1317 mr->attr_next=attr_none;
1325 rp_coord_get(void *priv_data, struct coord *c, int count)
1327 struct map_rect_priv *mr = priv_data;
1328 struct route_graph_point *p = mr->point;
1329 struct route_graph_segment *seg = mr->rseg;
1331 for (i=0; i < count; i++) {
1332 if (mr->item.type == type_rg_point) {
1333 if (mr->last_coord >= 1)
1337 if (mr->last_coord >= 2)
1342 c[i] = seg->start->c;
1350 static struct item_methods methods_point_item = {
1358 rm_destroy(struct map_priv *priv)
1363 static struct map_rect_priv *
1364 rm_rect_new(struct map_priv *priv, struct map_selection *sel)
1366 struct map_rect_priv * mr;
1368 if (! route_get_pos(priv->route))
1370 if (! route_get_dst(priv->route))
1372 if (! priv->route->path2)
1374 mr=g_new0(struct map_rect_priv, 1);
1376 mr->item.priv_data = mr;
1377 mr->item.type = type_street_route;
1378 mr->item.meth = &methods_route_item;
1379 mr->seg_next=priv->route->path2->path;
1383 static struct map_rect_priv *
1384 rp_rect_new(struct map_priv *priv, struct map_selection *sel)
1386 struct map_rect_priv * mr;
1388 if (! priv->route->graph || ! priv->route->graph->route_points)
1390 mr=g_new0(struct map_rect_priv, 1);
1392 mr->item.priv_data = mr;
1393 mr->item.type = type_rg_point;
1394 mr->item.meth = &methods_point_item;
1399 rm_rect_destroy(struct map_rect_priv *mr)
1406 static struct item *
1407 rp_get_item(struct map_rect_priv *mr)
1409 struct route *r = mr->mpriv->route;
1410 struct route_graph_point *p = mr->point;
1411 struct route_graph_segment *seg = mr->rseg;
1413 if (mr->item.type == type_rg_point) {
1415 p = r->graph->route_points;
1421 rm_coord_rewind(mr);
1425 mr->item.type = type_rg_segment;
1428 seg=r->graph->route_segments;
1434 rm_coord_rewind(mr);
1442 static struct item *
1443 rp_get_item_byid(struct map_rect_priv *mr, int id_hi, int id_lo)
1445 struct item *ret=NULL;
1447 ret=rp_get_item(mr);
1452 static struct item *
1453 rm_get_item(struct map_rect_priv *mr)
1455 struct route *r = mr->mpriv->route;
1456 struct route_path_segment *seg = mr->seg;
1457 dbg(1,"enter\n", mr->pos);
1459 mr->seg=mr->seg_next;
1462 mr->seg_next=mr->seg->next;
1469 static struct item *
1470 rm_get_item_byid(struct map_rect_priv *mr, int id_hi, int id_lo)
1472 struct item *ret=NULL;
1474 ret=rm_get_item(mr);
1478 static struct map_methods route_meth = {
1491 static struct map_methods route_graph_meth = {
1505 route_toggle_routegraph_display(struct route *route)
1507 if (route->flags & RF_SHOWGRAPH) {
1508 route->flags &= ~RF_SHOWGRAPH;
1510 route->flags |= RF_SHOWGRAPH;
1514 static struct map_priv *
1515 route_map_new_helper(struct map_methods *meth, struct attr **attrs, int graph)
1517 struct map_priv *ret;
1518 struct attr *route_attr;
1520 route_attr=attr_search(attrs, NULL, attr_route);
1523 ret=g_new0(struct map_priv, 1);
1525 *meth=route_graph_meth;
1528 ret->route=route_attr->u.route;
1533 static struct map_priv *
1534 route_map_new(struct map_methods *meth, struct attr **attrs)
1536 return route_map_new_helper(meth, attrs, 0);
1539 static struct map_priv *
1540 route_graph_map_new(struct map_methods *meth, struct attr **attrs)
1542 return route_map_new_helper(meth, attrs, 1);
1546 route_get_map_helper(struct route *this_, struct map **map, char *type, char *description)
1549 *map=map_new((struct attr*[]){
1550 &(struct attr){attr_type,{type}},
1551 &(struct attr){attr_route,.u.route=this_},
1552 &(struct attr){attr_data,{""}},
1553 &(struct attr){attr_description,{description}},
1559 route_get_map(struct route *this_)
1561 return route_get_map_helper(this_, &this_->map, "route","Route");
1566 route_get_graph_map(struct route *this_)
1568 return route_get_map_helper(this_, &this_->graph_map, "route_graph","Route Graph");
1572 route_set_projection(struct route *this_, enum projection pro)
1579 plugin_register_map_type("route", route_map_new);
1580 plugin_register_map_type("route_graph", route_graph_map_new);