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_path_update(struct route *this)
238 struct route_path *oldpath = NULL;
239 if (! this->pos || ! this->dst) {
240 route_path_destroy(this->path2);
244 /* the graph is destroyed when setting the destination */
245 if (this->graph && this->pos && this->dst && this->path2) {
246 // we can try to update
247 oldpath = this->path2;
250 if (! this->graph || !(this->path2=route_path_new(this->graph, oldpath, this->pos, this->dst, this->speedlist))) {
252 route_graph_update(this);
253 this->path2=route_path_new(this->graph, oldpath, this->pos, this->dst, this->speedlist);
254 profile(1,"route_path_new");
258 /* Destroy what's left */
259 route_path_destroy(oldpath);
264 route_set_position(struct route *this, struct pcoord *pos)
267 route_info_free(this->pos);
269 this->pos=route_find_nearest_street(this->ms, pos);
270 dbg(1,"this->pos=%p\n", this->pos);
274 route_path_update(this);
278 route_set_position_from_tracking(struct route *this, struct tracking *tracking)
281 struct route_info *ret;
284 c=tracking_get_pos(tracking);
285 ret=g_new0(struct route_info, 1);
287 printf("%s:Out of memory\n", __FUNCTION__);
291 route_info_free(this->pos);
295 ret->pos=tracking_get_segment_pos(tracking);
296 ret->street=street_data_dup(tracking_get_street_data(tracking));
297 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);
298 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);
301 route_path_update(this);
305 /* Used for debuging of route_rect, what routing sees */
306 struct map_selection *route_selection;
308 struct map_selection *
309 route_rect(int order, struct coord *c1, struct coord *c2, int rel, int abs)
311 int dx,dy,sx=1,sy=1,d,m;
312 struct map_selection *sel=g_new(struct map_selection, 1);
314 printf("%s:Out of memory\n", __FUNCTION__);
317 sel->order[layer_town]=0;
318 sel->order[layer_poly]=0;
319 sel->order[layer_street]=order;
320 dbg(1,"%p %p\n", c1, c2);
325 sel->u.c_rect.lu.x=c1->x;
326 sel->u.c_rect.rl.x=c2->x;
328 sel->u.c_rect.lu.x=c2->x;
329 sel->u.c_rect.rl.x=c1->x;
333 sel->u.c_rect.lu.y=c2->y;
334 sel->u.c_rect.rl.y=c1->y;
336 sel->u.c_rect.lu.y=c1->y;
337 sel->u.c_rect.rl.y=c2->y;
344 sel->u.c_rect.lu.x-=m;
345 sel->u.c_rect.rl.x+=m;
346 sel->u.c_rect.lu.y+=m;
347 sel->u.c_rect.rl.y-=m;
352 static struct map_selection *
353 route_calc_selection(struct coord *c1, struct coord *c2)
355 struct map_selection *ret,*sel;
356 sel=route_rect(4, c1, c2, 25, 0);
358 sel->next=route_rect(8, c1, c1, 0, 40000);
360 sel->next=route_rect(18, c1, c1, 0, 10000);
362 sel->next=route_rect(8, c2, c2, 0, 40000);
364 sel->next=route_rect(18, c2, c2, 0, 10000);
365 /* route_selection=ret; */
370 route_free_selection(struct map_selection *sel)
372 struct map_selection *next;
382 route_info_distances(struct route_info *ri, enum projection pro)
385 struct street_data *sd=ri->street;
386 /* 0 1 2 X 3 4 5 6 pos=2 npos=3 count=7 0,1,2 3,4,5,6*/
387 ri->lenextra=transform_distance(pro, &ri->lp, &ri->c);
388 ri->lenneg=transform_polyline_length(pro, sd->c, npos)+transform_distance(pro, &sd->c[ri->pos], &ri->lp);
389 ri->lenpos=transform_polyline_length(pro, sd->c+npos, sd->count-npos)+transform_distance(pro, &sd->c[npos], &ri->lp);
394 route_set_destination(struct route *this, struct pcoord *dst)
398 route_info_free(this->dst);
401 this->dst=route_find_nearest_street(this->ms, dst);
402 route_info_distances(this->dst, dst->pro);
403 profile(1,"find_nearest_street");
404 route_graph_destroy(this->graph);
406 route_path_update(this);
410 static struct route_graph_point *
411 route_graph_get_point(struct route_graph *this, struct coord *c)
413 struct route_graph_point *p;
414 int hashval=HASHCOORD(c);
415 p=this->hash[hashval];
417 if (p->c.x == c->x && p->c.y == c->y)
425 static struct route_graph_point *
426 route_graph_add_point(struct route_graph *this, struct coord *f)
429 struct route_graph_point *p;
431 p=route_graph_get_point(this,f);
433 hashval=HASHCOORD(f);
435 printf("p (0x%x,0x%x)\n", f->x, f->y);
436 p=g_new(struct route_graph_point,1);
438 printf("%s:Out of memory\n", __FUNCTION__);
441 p->hash_next=this->hash[hashval];
442 this->hash[hashval]=p;
443 p->next=this->route_points;
450 this->route_points=p;
457 route_graph_free_points(struct route_graph *this)
459 struct route_graph_point *curr,*next;
460 curr=this->route_points;
466 this->route_points=NULL;
467 memset(this->hash, 0, sizeof(this->hash));
471 route_graph_add_segment(struct route_graph *this, struct route_graph_point *start,
472 struct route_graph_point *end, int len, struct item *item,
473 int flags, int offset)
475 struct route_graph_segment *s;
476 s = g_new0(struct route_graph_segment, 1);
478 printf("%s:Out of memory\n", __FUNCTION__);
482 s->start_next=start->start;
485 s->end_next=end->end;
492 s->next=this->route_segments;
493 this->route_segments=s;
495 printf("l (0x%x,0x%x)-(0x%x,0x%x)\n", start->c.x, start->c.y, end->c.x, end->c.y);
498 static int get_item_seg_coords(struct item *i, struct coord *c, int max,
499 struct coord *start, struct coord *end)
505 mr=map_rect_new(i->map, NULL);
508 item = map_rect_get_item_byid(mr, i->id_hi, i->id_lo);
510 rc = item_coord_get(item, &c1, 1);
511 while (rc && (c1.x != start->x || c1.y != start->y)) {
512 rc = item_coord_get(item, &c1, 1);
514 while (rc && p < max) {
516 if (c1.x == end->x && c1.y == end->y)
518 rc = item_coord_get(item, &c1, 1);
521 map_rect_destroy(mr);
525 static struct route_path_segment *
526 route_extract_segment_from_path(struct route_path *path, struct item *item,
529 struct route_path_segment *sp = NULL, *s;
532 if (s->offset == offset && item_is_equal(s->item,*item)) {
537 path->path = s->next;
545 item_hash_remove(path->path_hash, item);
550 route_path_add_segment(struct route_path *this, struct route_path_segment *segment)
555 this->path_last->next=segment;
556 this->path_last=segment;
560 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)
562 int i,idx=0,ccount=count + (first ? 1:0) + (last ? 1:0);
563 struct route_path_segment *segment;
565 segment=g_malloc0(sizeof(*segment) + sizeof(struct coord) * ccount);
566 segment->ncoords=ccount;
568 segment->c[idx++]=*first;
570 for (i = 0 ; i < count ; i++)
571 segment->c[idx++]=c[i];
573 for (i = 0 ; i < count ; i++)
574 segment->c[idx++]=c[count-i-1];
577 segment->c[idx++]=*last;
581 route_path_add_segment(this, segment);
585 route_path_add_item_from_graph(struct route_path *this, struct route_path *oldpath,
586 struct route_graph_segment *rgs, int len, int offset, int dir)
588 struct route_path_segment *segment;
590 struct coord ca[2048];
593 ccnt = (int)item_hash_lookup(oldpath->path_hash, &rgs->item);
595 segment = route_extract_segment_from_path(oldpath,
602 ccnt = get_item_seg_coords(&rgs->item, ca, 2047, &rgs->start->c, &rgs->end->c);
603 segment= g_malloc0(sizeof(*segment) + sizeof(struct coord) * ccnt);
605 printf("%s:Out of memory\n", __FUNCTION__);
609 for (i = 0 ; i < ccnt ; i++)
612 for (i = 0 ; i < ccnt ; i++)
613 segment->c[i]=ca[ccnt-i-1];
615 segment->ncoords = ccnt;
616 segment->item=rgs->item;
617 segment->offset = offset;
621 item_hash_insert(this->path_hash, &rgs->item, (void *)ccnt);
622 route_path_add_segment(this, segment);
626 route_graph_free_segments(struct route_graph *this)
628 struct route_graph_segment *curr,*next;
629 curr=this->route_segments;
635 this->route_segments=NULL;
639 route_graph_destroy(struct route_graph *this)
642 route_graph_free_points(this);
643 route_graph_free_segments(this);
649 route_time(int *speedlist, struct item *item, int len)
651 if (item->type < route_item_first || item->type > route_item_last) {
652 dbg(0,"street type %d out of range [%d,%d]", item->type, route_item_first, route_item_last);
655 return len*36/speedlist[item->type-route_item_first];
660 route_value(int *speedlist, struct item *item, int len)
664 printf("len=%d\n", len);
667 ret=route_time(speedlist, item, len);
668 dbg(1, "route_value(0x%x, %d)=%d\n", item->type, len, ret);
673 route_process_street_graph(struct route_graph *this, struct item *item)
680 struct route_graph_point *s_pnt,*e_pnt;
687 if (item_coord_get(item, &l, 1)) {
688 if (item_attr_get(item, attr_flags, &attr)) {
690 if (flags & AF_SEGMENTED)
693 s_pnt=route_graph_add_point(this,&l);
695 while (item_coord_get(item, &c, 1)) {
696 len+=transform_distance(map_projection(item->map), &l, &c);
699 e_pnt=route_graph_add_point(this,&l);
701 route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset);
706 isseg = item_coord_is_segment(item);
707 rc = item_coord_get(item, &c, 1);
709 len+=transform_distance(map_projection(item->map), &l, &c);
712 e_pnt=route_graph_add_point(this,&l);
713 route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset);
715 s_pnt=route_graph_add_point(this,&l);
720 e_pnt=route_graph_add_point(this,&l);
723 route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset);
729 compare(void *v1, void *v2)
731 struct route_graph_point *p1=v1;
732 struct route_graph_point *p2=v2;
735 printf("compare %d (%p) vs %d (%p)\n", p1->value,p1,p2->value,p2);
737 return p1->value-p2->value;
741 route_graph_flood(struct route_graph *this, struct route_info *dst, int *speedlist)
743 struct route_graph_point *p_min,*end=NULL;
744 struct route_graph_segment *s;
746 struct fibheap *heap;
747 struct street_data *sd=dst->street;
749 heap = fh_makeheap();
750 fh_setcmp(heap, compare);
752 if (! (sd->flags & AF_ONEWAYREV)) {
753 end=route_graph_get_point(this, &sd->c[0]);
755 end->value=route_value(speedlist, &sd->item, dst->lenneg);
756 end->el=fh_insert(heap, end);
759 if (! (sd->flags & AF_ONEWAY)) {
760 end=route_graph_get_point(this, &sd->c[sd->count-1]);
762 end->value=route_value(speedlist, &sd->item, dst->lenpos);
763 end->el=fh_insert(heap, end);
766 dbg(1,"0x%x,0x%x\n", end->c.x, end->c.y);
768 p_min=fh_extractmin(heap);
773 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);
777 val=route_value(speedlist, &s->item, s->len);
779 val+=val*2*street_route_contained(s->str->segid);
783 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);
784 if (new < s->end->value && !(s->flags & AF_ONEWAY)) {
789 printf("insert_end p=%p el=%p val=%d ", s->end, s->end->el, s->end->value);
790 s->end->el=fh_insert(heap, s->end);
792 printf("el new=%p\n", s->end->el);
796 printf("replace_end p=%p el=%p val=%d\n", s->end, s->end->el, s->end->value);
797 fh_replacedata(heap, s->end->el, s->end);
806 val=route_value(speedlist, &s->item, s->len);
809 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);
810 if (new < s->start->value && !(s->flags & AF_ONEWAYREV)) {
814 if (! s->start->el) {
816 printf("insert_start p=%p el=%p val=%d ", s->start, s->start->el, s->start->value);
817 s->start->el=fh_insert(heap, s->start);
819 printf("el new=%p\n", s->start->el);
823 printf("replace_start p=%p el=%p val=%d\n", s->start, s->start->el, s->start->value);
824 fh_replacedata(heap, s->start->el, s->start);
835 static struct route_path *
836 route_path_new_offroad(struct route_graph *this, struct route_info *pos, struct route_info *dst, int dir)
838 struct route_path *ret;
840 ret=g_new0(struct route_path, 1);
841 ret->path_hash=item_hash_new();
842 route_path_add_item(ret, NULL, pos->lenextra+dst->lenextra, &pos->c, NULL, 0, &dst->c, 1);
847 static struct route_path *
848 route_path_new_trivial(struct route_graph *this, struct route_info *pos, struct route_info *dst, int dir)
850 struct street_data *sd=pos->street;
851 struct route_path *ret;
854 if (pos->lenextra + dst->lenextra + pos->lenneg-dst->lenneg > transform_distance(map_projection(sd->item.map), &pos->c, &dst->c))
855 return route_path_new_offroad(this, pos, dst, dir);
857 if (pos->lenextra + dst->lenextra + pos->lenpos-dst->lenpos > transform_distance(map_projection(sd->item.map), &pos->c, &dst->c))
858 return route_path_new_offroad(this, pos, dst, dir);
860 ret=g_new0(struct route_path, 1);
861 ret->path_hash=item_hash_new();
863 route_path_add_item(ret, NULL, pos->lenextra, &pos->c, NULL, 0, &pos->lp, 1);
865 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);
867 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);
869 route_path_add_item(ret, NULL, dst->lenextra, &dst->lp, NULL, 0, &dst->c, 1);
873 static struct route_path *
874 route_path_new(struct route_graph *this, struct route_path *oldpath, struct route_info *pos, struct route_info *dst, int *speedlist)
876 struct route_graph_point *start1=NULL,*start2=NULL,*start;
877 struct route_graph_segment *s=NULL;
881 int time=0,hr,min,sec
883 unsigned int val1=0xffffffff,val2=0xffffffff;
884 struct street_data *sd=pos->street;
885 struct route_path *ret;
887 if (item_is_equal(pos->street->item, dst->street->item)) {
888 if (!(sd->flags & AF_ONEWAY) && pos->lenneg >= dst->lenneg) {
889 return route_path_new_trivial(this, pos, dst, -1);
891 if (!(sd->flags & AF_ONEWAYREV) && pos->lenpos >= dst->lenpos) {
892 return route_path_new_trivial(this, pos, dst, 1);
895 if (! (sd->flags & AF_ONEWAY)) {
896 start1=route_graph_get_point(this, &sd->c[0]);
899 val1=start1->value+route_value(speedlist, &sd->item, pos->lenneg);
900 dbg(1,"start1: %d(route)+%d=%d\n", start1->value, val1-start1->value, val1);
902 if (! (sd->flags & AF_ONEWAYREV)) {
903 start2=route_graph_get_point(this, &sd->c[sd->count-1]);
906 val2=start2->value+route_value(speedlist, &sd->item, pos->lenpos);
907 dbg(1,"start2: %d(route)+%d=%d\n", start2->value, val2-start2->value, val2);
909 dbg(1,"val1=%d val2=%d\n", val1, val2);
911 val1=start1->start->start->value;
912 val2=start2->end->end->value;
914 ret=g_new0(struct route_path, 1);
916 route_path_add_item(ret, NULL, pos->lenextra, &pos->c, NULL, 0, &pos->lp, 1);
917 if (start1 && (val1 < val2)) {
919 route_path_add_item(ret, &sd->item, pos->lenneg, &pos->lp, sd->c, pos->pos+1, NULL, -1);
923 route_path_add_item(ret, &sd->item, pos->lenpos, &pos->lp, sd->c+pos->pos+1, sd->count-pos->pos-1, NULL, 1);
925 printf("no route found, pos blocked\n");
929 ret->path_hash=item_hash_new();
930 while ((s=start->seg)) {
933 printf("start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y);
937 if (s->start == start) {
938 route_path_add_item_from_graph(ret, oldpath, s, seg_len, s->offset, 1);
941 route_path_add_item_from_graph(ret, oldpath, s, seg_len, s->offset, -1);
946 dbg(1,"start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y);
947 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);
948 if (start->c.x == sd->c[0].x && start->c.y == sd->c[0].y) {
949 route_path_add_item(ret, &sd->item, dst->lenneg, &dst->lp, sd->c, dst->pos+1, NULL, -1);
950 } else if (start->c.x == sd->c[sd->count-1].x && start->c.y == sd->c[sd->count-1].y) {
951 route_path_add_item(ret, &sd->item, dst->lenpos, &dst->lp, sd->c+dst->pos+1, sd->count-dst->pos-1, NULL, 1);
953 printf("no route found\n");
954 route_path_destroy(ret);
958 route_path_add_item(ret, NULL, dst->lenextra, &dst->lp, NULL, 0, &dst->c, 1);
959 dbg(1, "%d segments\n", segs);
963 static struct route_graph *
964 route_graph_build(struct mapset *ms, struct coord *c1, struct coord *c2)
966 struct route_graph *ret=g_new0(struct route_graph, 1);
967 struct map_selection *sel;
968 struct mapset_handle *h;
974 printf("%s:Out of memory\n", __FUNCTION__);
977 sel=route_calc_selection(c1, c2);
979 while ((m=mapset_next(h,1))) {
980 mr=map_rect_new(m, sel);
983 while ((item=map_rect_get_item(mr))) {
984 if (item->type >= type_street_0 && item->type <= type_ferry) {
985 route_process_street_graph(ret, item);
988 map_rect_destroy(mr);
991 route_free_selection(sel);
997 route_graph_update(struct route *this)
999 route_graph_destroy(this->graph);
1000 profile(1,"graph_free");
1001 this->graph=route_graph_build(this->ms, &this->pos->c, &this->dst->c);
1002 profile(1,"route_graph_build");
1003 route_graph_flood(this->graph, this->dst, this->speedlist);
1004 profile(1,"route_graph_flood");
1008 struct street_data *
1009 street_get_data (struct item *item)
1012 struct coord c[maxcount];
1014 struct street_data *ret;
1017 while (count < maxcount) {
1018 if (!item_coord_get(item, &c[count], 1))
1022 if (count >= maxcount) {
1023 dbg(0, "count=%d maxcount=%d id_hi=0x%x id_lo=0x%x\n", count, maxcount, item->id_hi, item->id_lo);
1024 if (item_attr_get(item, attr_debug, &attr))
1025 dbg(0,"debug='%s'\n", attr.u.str);
1027 g_assert(count < maxcount);
1028 ret=g_malloc(sizeof(struct street_data)+count*sizeof(struct coord));
1031 if (item_attr_get(item, attr_flags, &attr))
1032 ret->flags=attr.u.num;
1035 memcpy(ret->c, c, count*sizeof(struct coord));
1040 struct street_data *
1041 street_data_dup(struct street_data *orig)
1043 struct street_data *ret;
1044 int size=sizeof(struct street_data)+orig->count*sizeof(struct coord);
1047 memcpy(ret, orig, size);
1053 street_data_free(struct street_data *sd)
1058 static struct route_info *
1059 route_find_nearest_street(struct mapset *ms, struct pcoord *pc)
1061 struct route_info *ret=NULL;
1063 struct map_selection *sel;
1064 int dist,mindist=0,pos;
1065 struct mapset_handle *h;
1067 struct map_rect *mr;
1070 struct street_data *sd;
1077 * This is not correct for two reasons:
1078 * - You may need to go back first
1079 * - Currently we allow mixing of mapsets
1081 sel = route_rect(18, &c, &c, 0, max_dist);
1083 while ((m=mapset_next(h,1))) {
1086 if (map_projection(m) != pc->pro) {
1087 transform_to_geo(pc->pro, &c, &g);
1088 transform_from_geo(map_projection(m), &g, &c);
1090 mr=map_rect_new(m, sel);
1093 while ((item=map_rect_get_item(mr))) {
1094 if (item->type >= type_street_0 && item->type <= type_ferry) {
1095 sd=street_get_data(item);
1096 dist=transform_distance_polyline_sq(sd->c, sd->count, &c, &lp, &pos);
1097 if (!ret || dist < mindist) {
1099 street_data_free(ret->street);
1102 ret=g_new(struct route_info, 1);
1104 printf("%s:Out of memory\n", __FUNCTION__);
1112 dbg(1,"dist=%d id 0x%x 0x%x pos=%d\n", dist, item->id_hi, item->id_lo, pos);
1114 street_data_free(sd);
1117 map_rect_destroy(mr);
1120 map_selection_destroy(sel);
1122 route_info_distances(ret, pc->pro);
1127 route_info_free(struct route_info *inf)
1130 street_data_free(inf->street);
1137 struct street_data *
1138 route_info_street(struct route_info *rinf)
1140 return rinf->street;
1144 struct route_crossings *
1145 route_crossings_get(struct route *this, struct coord *c)
1147 struct route_point *pnt;
1148 struct route_segment *seg;
1150 struct route_crossings *ret;
1152 pnt=route_graph_get_point(this, c);
1155 printf("start: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo);
1157 seg=seg->start_next;
1161 printf("end: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo);
1165 ret=g_malloc(sizeof(struct route_crossings)+crossings*sizeof(struct route_crossing));
1166 ret->count=crossings;
1172 struct map_rect_priv {
1173 struct route_info_handle *ri;
1174 enum attr_type attr_next;
1176 struct map_priv *mpriv;
1179 unsigned int last_coord;
1180 struct route_path_segment *seg,*seg_next;
1181 struct route_graph_point *point;
1182 struct route_graph_segment *rseg;
1187 rm_coord_rewind(void *priv_data)
1189 struct map_rect_priv *mr = priv_data;
1194 rm_attr_rewind(void *priv_data)
1196 struct map_rect_priv *mr = priv_data;
1197 mr->attr_next = attr_street_item;
1201 rm_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
1203 struct map_rect_priv *mr = priv_data;
1204 struct route_path_segment *seg=mr->seg;
1205 struct route *route=mr->mpriv->route;
1206 attr->type=attr_type;
1207 switch (attr_type) {
1209 while (mr->attr_next != attr_none) {
1210 if (rm_attr_get(priv_data, mr->attr_next, attr))
1214 case attr_street_item:
1215 mr->attr_next=attr_length;
1216 if (seg && seg->item.map)
1217 attr->u.item=&seg->item;
1223 attr->u.num=seg->length;
1225 attr->u.num=mr->length;
1226 mr->attr_next=attr_time;
1229 mr->attr_next=attr_none;
1231 attr->u.num=route_time(route->speedlist, &seg->item, seg->length);
1236 attr->type=attr_none;
1243 rm_coord_get(void *priv_data, struct coord *c, int count)
1245 struct map_rect_priv *mr = priv_data;
1246 struct route_path_segment *seg = mr->seg;
1250 for (i=0; i < count; i++) {
1251 if (mr->last_coord >= seg->ncoords)
1253 if (i >= seg->ncoords)
1255 c[i] = seg->c[mr->last_coord++];
1258 dbg(1,"return %d\n",rc);
1262 static struct item_methods methods_route_item = {
1270 rp_attr_rewind(void *priv_data)
1272 struct map_rect_priv *mr = priv_data;
1273 mr->attr_next = attr_label;
1277 rp_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
1279 struct map_rect_priv *mr = priv_data;
1280 struct route_graph_point *p = mr->point;
1281 if (mr->item.type != type_rg_point)
1283 switch (attr_type) {
1285 while (mr->attr_next != attr_none) {
1286 if (rm_attr_get(priv_data, mr->attr_next, attr))
1290 attr->type = attr_label;
1293 if (p->value != INT_MAX)
1294 mr->str=g_strdup_printf("%d", p->value);
1296 mr->str=g_strdup("-");
1297 attr->u.str = mr->str;
1298 mr->attr_next=attr_none;
1301 attr->type = attr_debug;
1304 mr->str=g_strdup_printf("x=%d y=%d", p->c.x, p->c.y);
1305 attr->u.str = mr->str;
1306 mr->attr_next=attr_none;
1314 rp_coord_get(void *priv_data, struct coord *c, int count)
1316 struct map_rect_priv *mr = priv_data;
1317 struct route_graph_point *p = mr->point;
1318 struct route_graph_segment *seg = mr->rseg;
1320 for (i=0; i < count; i++) {
1321 if (mr->item.type == type_rg_point) {
1322 if (mr->last_coord >= 1)
1326 if (mr->last_coord >= 2)
1331 c[i] = seg->start->c;
1339 static struct item_methods methods_point_item = {
1347 rm_destroy(struct map_priv *priv)
1352 static struct map_rect_priv *
1353 rm_rect_new(struct map_priv *priv, struct map_selection *sel)
1355 struct map_rect_priv * mr;
1357 if (! route_get_pos(priv->route))
1359 if (! route_get_dst(priv->route))
1361 if (! priv->route->path2)
1363 mr=g_new0(struct map_rect_priv, 1);
1365 mr->item.priv_data = mr;
1366 mr->item.type = type_street_route;
1367 mr->item.meth = &methods_route_item;
1368 mr->seg_next=priv->route->path2->path;
1372 static struct map_rect_priv *
1373 rp_rect_new(struct map_priv *priv, struct map_selection *sel)
1375 struct map_rect_priv * mr;
1377 if (! priv->route->graph || ! priv->route->graph->route_points)
1379 mr=g_new0(struct map_rect_priv, 1);
1381 mr->item.priv_data = mr;
1382 mr->item.type = type_rg_point;
1383 mr->item.meth = &methods_point_item;
1388 rm_rect_destroy(struct map_rect_priv *mr)
1395 static struct item *
1396 rp_get_item(struct map_rect_priv *mr)
1398 struct route *r = mr->mpriv->route;
1399 struct route_graph_point *p = mr->point;
1400 struct route_graph_segment *seg = mr->rseg;
1402 if (mr->item.type == type_rg_point) {
1404 p = r->graph->route_points;
1410 rm_coord_rewind(mr);
1414 mr->item.type = type_rg_segment;
1417 seg=r->graph->route_segments;
1423 rm_coord_rewind(mr);
1431 static struct item *
1432 rp_get_item_byid(struct map_rect_priv *mr, int id_hi, int id_lo)
1434 struct item *ret=NULL;
1436 ret=rp_get_item(mr);
1441 static struct item *
1442 rm_get_item(struct map_rect_priv *mr)
1444 struct route *r = mr->mpriv->route;
1445 struct route_path_segment *seg = mr->seg;
1446 dbg(1,"enter\n", mr->pos);
1448 mr->seg=mr->seg_next;
1451 mr->seg_next=mr->seg->next;
1458 static struct item *
1459 rm_get_item_byid(struct map_rect_priv *mr, int id_hi, int id_lo)
1461 struct item *ret=NULL;
1463 ret=rm_get_item(mr);
1467 static struct map_methods route_meth = {
1480 static struct map_methods route_graph_meth = {
1494 route_toggle_routegraph_display(struct route *route)
1496 if (route->flags & RF_SHOWGRAPH) {
1497 route->flags &= ~RF_SHOWGRAPH;
1499 route->flags |= RF_SHOWGRAPH;
1503 static struct map_priv *
1504 route_map_new_helper(struct map_methods *meth, struct attr **attrs, int graph)
1506 struct map_priv *ret;
1507 struct attr *route_attr;
1509 route_attr=attr_search(attrs, NULL, attr_route);
1512 ret=g_new0(struct map_priv, 1);
1514 *meth=route_graph_meth;
1517 ret->route=route_attr->u.route;
1522 static struct map_priv *
1523 route_map_new(struct map_methods *meth, struct attr **attrs)
1525 return route_map_new_helper(meth, attrs, 0);
1528 static struct map_priv *
1529 route_graph_map_new(struct map_methods *meth, struct attr **attrs)
1531 return route_map_new_helper(meth, attrs, 1);
1535 route_get_map_helper(struct route *this_, struct map **map, char *type)
1538 *map=map_new((struct attr*[]){
1539 &(struct attr){attr_type,{type}},
1540 &(struct attr){attr_route,.u.route=this_},
1541 &(struct attr){attr_data,{""}},
1547 route_get_map(struct route *this_)
1549 return route_get_map_helper(this_, &this_->map, "route");
1554 route_get_graph_map(struct route *this_)
1556 return route_get_map_helper(this_, &this_->graph_map, "route_graph");
1560 route_set_projection(struct route *this_, enum projection pro)
1567 plugin_register_map_type("route", route_map_new);
1568 plugin_register_map_type("route_graph", route_graph_map_new);