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_info_distances(struct route_info *ri, enum projection pro)
267 struct street_data *sd=ri->street;
268 /* 0 1 2 X 3 4 5 6 pos=2 npos=3 count=7 0,1,2 3,4,5,6*/
269 ri->lenextra=transform_distance(pro, &ri->lp, &ri->c);
270 ri->lenneg=transform_polyline_length(pro, sd->c, npos)+transform_distance(pro, &sd->c[ri->pos], &ri->lp);
271 ri->lenpos=transform_polyline_length(pro, sd->c+npos, sd->count-npos)+transform_distance(pro, &sd->c[npos], &ri->lp);
275 route_set_position(struct route *this, struct pcoord *pos)
278 route_info_free(this->pos);
280 this->pos=route_find_nearest_street(this->ms, pos);
281 dbg(1,"this->pos=%p\n", this->pos);
284 route_info_distances(this->pos, pos->pro);
286 route_path_update(this);
290 route_set_position_from_tracking(struct route *this, struct tracking *tracking)
293 struct route_info *ret;
296 c=tracking_get_pos(tracking);
297 ret=g_new0(struct route_info, 1);
299 printf("%s:Out of memory\n", __FUNCTION__);
303 route_info_free(this->pos);
307 ret->pos=tracking_get_segment_pos(tracking);
308 ret->street=street_data_dup(tracking_get_street_data(tracking));
309 route_info_distances(ret, projection_mg);
310 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);
311 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);
314 route_path_update(this);
318 /* Used for debuging of route_rect, what routing sees */
319 struct map_selection *route_selection;
321 struct map_selection *
322 route_rect(int order, struct coord *c1, struct coord *c2, int rel, int abs)
324 int dx,dy,sx=1,sy=1,d,m;
325 struct map_selection *sel=g_new(struct map_selection, 1);
327 printf("%s:Out of memory\n", __FUNCTION__);
330 sel->order[layer_town]=0;
331 sel->order[layer_poly]=0;
332 sel->order[layer_street]=order;
333 dbg(1,"%p %p\n", c1, c2);
338 sel->u.c_rect.lu.x=c1->x;
339 sel->u.c_rect.rl.x=c2->x;
341 sel->u.c_rect.lu.x=c2->x;
342 sel->u.c_rect.rl.x=c1->x;
346 sel->u.c_rect.lu.y=c2->y;
347 sel->u.c_rect.rl.y=c1->y;
349 sel->u.c_rect.lu.y=c1->y;
350 sel->u.c_rect.rl.y=c2->y;
357 sel->u.c_rect.lu.x-=m;
358 sel->u.c_rect.rl.x+=m;
359 sel->u.c_rect.lu.y+=m;
360 sel->u.c_rect.rl.y-=m;
365 static struct map_selection *
366 route_calc_selection(struct coord *c1, struct coord *c2)
368 struct map_selection *ret,*sel;
369 sel=route_rect(4, c1, c2, 25, 0);
371 sel->next=route_rect(8, c1, c1, 0, 40000);
373 sel->next=route_rect(18, c1, c1, 0, 10000);
375 sel->next=route_rect(8, c2, c2, 0, 40000);
377 sel->next=route_rect(18, c2, c2, 0, 10000);
378 /* route_selection=ret; */
383 route_free_selection(struct map_selection *sel)
385 struct map_selection *next;
397 route_set_destination(struct route *this, struct pcoord *dst)
401 route_info_free(this->dst);
404 this->dst=route_find_nearest_street(this->ms, dst);
405 route_info_distances(this->dst, dst->pro);
406 profile(1,"find_nearest_street");
407 route_graph_destroy(this->graph);
409 route_path_update(this);
413 static struct route_graph_point *
414 route_graph_get_point(struct route_graph *this, struct coord *c)
416 struct route_graph_point *p;
417 int hashval=HASHCOORD(c);
418 p=this->hash[hashval];
420 if (p->c.x == c->x && p->c.y == c->y)
428 static struct route_graph_point *
429 route_graph_add_point(struct route_graph *this, struct coord *f)
432 struct route_graph_point *p;
434 p=route_graph_get_point(this,f);
436 hashval=HASHCOORD(f);
438 printf("p (0x%x,0x%x)\n", f->x, f->y);
439 p=g_new(struct route_graph_point,1);
441 printf("%s:Out of memory\n", __FUNCTION__);
444 p->hash_next=this->hash[hashval];
445 this->hash[hashval]=p;
446 p->next=this->route_points;
453 this->route_points=p;
460 route_graph_free_points(struct route_graph *this)
462 struct route_graph_point *curr,*next;
463 curr=this->route_points;
469 this->route_points=NULL;
470 memset(this->hash, 0, sizeof(this->hash));
474 route_graph_add_segment(struct route_graph *this, struct route_graph_point *start,
475 struct route_graph_point *end, int len, struct item *item,
476 int flags, int offset)
478 struct route_graph_segment *s;
479 s = g_new0(struct route_graph_segment, 1);
481 printf("%s:Out of memory\n", __FUNCTION__);
485 s->start_next=start->start;
488 s->end_next=end->end;
495 s->next=this->route_segments;
496 this->route_segments=s;
498 printf("l (0x%x,0x%x)-(0x%x,0x%x)\n", start->c.x, start->c.y, end->c.x, end->c.y);
501 static int get_item_seg_coords(struct item *i, struct coord *c, int max,
502 struct coord *start, struct coord *end)
508 mr=map_rect_new(i->map, NULL);
511 item = map_rect_get_item_byid(mr, i->id_hi, i->id_lo);
513 rc = item_coord_get(item, &c1, 1);
514 while (rc && (c1.x != start->x || c1.y != start->y)) {
515 rc = item_coord_get(item, &c1, 1);
517 while (rc && p < max) {
519 if (c1.x == end->x && c1.y == end->y)
521 rc = item_coord_get(item, &c1, 1);
524 map_rect_destroy(mr);
528 static struct route_path_segment *
529 route_extract_segment_from_path(struct route_path *path, struct item *item,
532 struct route_path_segment *sp = NULL, *s;
535 if (s->offset == offset && item_is_equal(s->item,*item)) {
540 path->path = s->next;
548 item_hash_remove(path->path_hash, item);
553 route_path_add_segment(struct route_path *this, struct route_path_segment *segment)
558 this->path_last->next=segment;
559 this->path_last=segment;
563 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)
565 int i,idx=0,ccount=count + (first ? 1:0) + (last ? 1:0);
566 struct route_path_segment *segment;
568 segment=g_malloc0(sizeof(*segment) + sizeof(struct coord) * ccount);
569 segment->ncoords=ccount;
571 segment->c[idx++]=*first;
573 for (i = 0 ; i < count ; i++)
574 segment->c[idx++]=c[i];
576 for (i = 0 ; i < count ; i++)
577 segment->c[idx++]=c[count-i-1];
580 segment->c[idx++]=*last;
584 route_path_add_segment(this, segment);
588 route_path_add_item_from_graph(struct route_path *this, struct route_path *oldpath,
589 struct route_graph_segment *rgs, int len, int offset, int dir)
591 struct route_path_segment *segment;
593 struct coord ca[2048];
596 ccnt = (int)item_hash_lookup(oldpath->path_hash, &rgs->item);
598 segment = route_extract_segment_from_path(oldpath,
605 ccnt = get_item_seg_coords(&rgs->item, ca, 2047, &rgs->start->c, &rgs->end->c);
606 segment= g_malloc0(sizeof(*segment) + sizeof(struct coord) * ccnt);
608 printf("%s:Out of memory\n", __FUNCTION__);
612 for (i = 0 ; i < ccnt ; i++)
615 for (i = 0 ; i < ccnt ; i++)
616 segment->c[i]=ca[ccnt-i-1];
618 segment->ncoords = ccnt;
619 segment->item=rgs->item;
620 segment->offset = offset;
624 item_hash_insert(this->path_hash, &rgs->item, (void *)ccnt);
625 route_path_add_segment(this, segment);
629 route_graph_free_segments(struct route_graph *this)
631 struct route_graph_segment *curr,*next;
632 curr=this->route_segments;
638 this->route_segments=NULL;
642 route_graph_destroy(struct route_graph *this)
645 route_graph_free_points(this);
646 route_graph_free_segments(this);
652 route_time(int *speedlist, struct item *item, int len)
654 if (item->type < route_item_first || item->type > route_item_last) {
655 dbg(0,"street type %d out of range [%d,%d]", item->type, route_item_first, route_item_last);
658 return len*36/speedlist[item->type-route_item_first];
663 route_value(int *speedlist, struct item *item, int len)
667 printf("len=%d\n", len);
670 ret=route_time(speedlist, item, len);
671 dbg(1, "route_value(0x%x, %d)=%d\n", item->type, len, ret);
676 route_process_street_graph(struct route_graph *this, struct item *item)
683 struct route_graph_point *s_pnt,*e_pnt;
690 if (item_coord_get(item, &l, 1)) {
691 if (item_attr_get(item, attr_flags, &attr)) {
693 if (flags & AF_SEGMENTED)
696 s_pnt=route_graph_add_point(this,&l);
698 while (item_coord_get(item, &c, 1)) {
699 len+=transform_distance(map_projection(item->map), &l, &c);
702 e_pnt=route_graph_add_point(this,&l);
704 route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset);
709 isseg = item_coord_is_segment(item);
710 rc = item_coord_get(item, &c, 1);
712 len+=transform_distance(map_projection(item->map), &l, &c);
715 e_pnt=route_graph_add_point(this,&l);
716 route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset);
718 s_pnt=route_graph_add_point(this,&l);
723 e_pnt=route_graph_add_point(this,&l);
726 route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset);
732 compare(void *v1, void *v2)
734 struct route_graph_point *p1=v1;
735 struct route_graph_point *p2=v2;
738 printf("compare %d (%p) vs %d (%p)\n", p1->value,p1,p2->value,p2);
740 return p1->value-p2->value;
744 route_graph_flood(struct route_graph *this, struct route_info *dst, int *speedlist)
746 struct route_graph_point *p_min,*end=NULL;
747 struct route_graph_segment *s;
749 struct fibheap *heap;
750 struct street_data *sd=dst->street;
752 heap = fh_makeheap();
753 fh_setcmp(heap, compare);
755 if (! (sd->flags & AF_ONEWAYREV)) {
756 end=route_graph_get_point(this, &sd->c[0]);
758 end->value=route_value(speedlist, &sd->item, dst->lenneg);
759 end->el=fh_insert(heap, end);
762 if (! (sd->flags & AF_ONEWAY)) {
763 end=route_graph_get_point(this, &sd->c[sd->count-1]);
765 end->value=route_value(speedlist, &sd->item, dst->lenpos);
766 end->el=fh_insert(heap, end);
769 dbg(1,"0x%x,0x%x\n", end->c.x, end->c.y);
771 p_min=fh_extractmin(heap);
776 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);
780 val=route_value(speedlist, &s->item, s->len);
782 val+=val*2*street_route_contained(s->str->segid);
786 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);
787 if (new < s->end->value && !(s->flags & AF_ONEWAY)) {
792 printf("insert_end p=%p el=%p val=%d ", s->end, s->end->el, s->end->value);
793 s->end->el=fh_insert(heap, s->end);
795 printf("el new=%p\n", s->end->el);
799 printf("replace_end p=%p el=%p val=%d\n", s->end, s->end->el, s->end->value);
800 fh_replacedata(heap, s->end->el, s->end);
809 val=route_value(speedlist, &s->item, s->len);
812 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);
813 if (new < s->start->value && !(s->flags & AF_ONEWAYREV)) {
817 if (! s->start->el) {
819 printf("insert_start p=%p el=%p val=%d ", s->start, s->start->el, s->start->value);
820 s->start->el=fh_insert(heap, s->start);
822 printf("el new=%p\n", s->start->el);
826 printf("replace_start p=%p el=%p val=%d\n", s->start, s->start->el, s->start->value);
827 fh_replacedata(heap, s->start->el, s->start);
838 static struct route_path *
839 route_path_new_offroad(struct route_graph *this, struct route_info *pos, struct route_info *dst, int dir)
841 struct route_path *ret;
843 ret=g_new0(struct route_path, 1);
844 ret->path_hash=item_hash_new();
845 route_path_add_item(ret, NULL, pos->lenextra+dst->lenextra, &pos->c, NULL, 0, &dst->c, 1);
850 static struct route_path *
851 route_path_new_trivial(struct route_graph *this, struct route_info *pos, struct route_info *dst, int dir)
853 struct street_data *sd=pos->street;
854 struct route_path *ret;
857 if (pos->lenextra + dst->lenextra + pos->lenneg-dst->lenneg > transform_distance(map_projection(sd->item.map), &pos->c, &dst->c))
858 return route_path_new_offroad(this, pos, dst, dir);
860 if (pos->lenextra + dst->lenextra + pos->lenpos-dst->lenpos > transform_distance(map_projection(sd->item.map), &pos->c, &dst->c))
861 return route_path_new_offroad(this, pos, dst, dir);
863 ret=g_new0(struct route_path, 1);
864 ret->path_hash=item_hash_new();
866 route_path_add_item(ret, NULL, pos->lenextra, &pos->c, NULL, 0, &pos->lp, 1);
868 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);
870 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);
872 route_path_add_item(ret, NULL, dst->lenextra, &dst->lp, NULL, 0, &dst->c, 1);
876 static struct route_path *
877 route_path_new(struct route_graph *this, struct route_path *oldpath, struct route_info *pos, struct route_info *dst, int *speedlist)
879 struct route_graph_point *start1=NULL,*start2=NULL,*start;
880 struct route_graph_segment *s=NULL;
884 int time=0,hr,min,sec
886 unsigned int val1=0xffffffff,val2=0xffffffff;
887 struct street_data *sd=pos->street;
888 struct route_path *ret;
890 if (item_is_equal(pos->street->item, dst->street->item)) {
891 if (!(sd->flags & AF_ONEWAY) && pos->lenneg >= dst->lenneg) {
892 return route_path_new_trivial(this, pos, dst, -1);
894 if (!(sd->flags & AF_ONEWAYREV) && pos->lenpos >= dst->lenpos) {
895 return route_path_new_trivial(this, pos, dst, 1);
898 if (! (sd->flags & AF_ONEWAY)) {
899 start1=route_graph_get_point(this, &sd->c[0]);
902 val1=start1->value+route_value(speedlist, &sd->item, pos->lenneg);
903 dbg(1,"start1: %d(route)+%d=%d\n", start1->value, val1-start1->value, val1);
905 if (! (sd->flags & AF_ONEWAYREV)) {
906 start2=route_graph_get_point(this, &sd->c[sd->count-1]);
909 val2=start2->value+route_value(speedlist, &sd->item, pos->lenpos);
910 dbg(1,"start2: %d(route)+%d=%d\n", start2->value, val2-start2->value, val2);
912 dbg(1,"val1=%d val2=%d\n", val1, val2);
914 val1=start1->start->start->value;
915 val2=start2->end->end->value;
917 ret=g_new0(struct route_path, 1);
919 route_path_add_item(ret, NULL, pos->lenextra, &pos->c, NULL, 0, &pos->lp, 1);
920 if (start1 && (val1 < val2)) {
922 route_path_add_item(ret, &sd->item, pos->lenneg, &pos->lp, sd->c, pos->pos+1, NULL, -1);
926 route_path_add_item(ret, &sd->item, pos->lenpos, &pos->lp, sd->c+pos->pos+1, sd->count-pos->pos-1, NULL, 1);
928 printf("no route found, pos blocked\n");
932 ret->path_hash=item_hash_new();
933 while ((s=start->seg)) {
936 printf("start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y);
940 if (s->start == start) {
941 route_path_add_item_from_graph(ret, oldpath, s, seg_len, s->offset, 1);
944 route_path_add_item_from_graph(ret, oldpath, s, seg_len, s->offset, -1);
949 dbg(1,"start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y);
950 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);
951 if (start->c.x == sd->c[0].x && start->c.y == sd->c[0].y) {
952 route_path_add_item(ret, &sd->item, dst->lenneg, &dst->lp, sd->c, dst->pos+1, NULL, -1);
953 } else if (start->c.x == sd->c[sd->count-1].x && start->c.y == sd->c[sd->count-1].y) {
954 route_path_add_item(ret, &sd->item, dst->lenpos, &dst->lp, sd->c+dst->pos+1, sd->count-dst->pos-1, NULL, 1);
956 printf("no route found\n");
957 route_path_destroy(ret);
961 route_path_add_item(ret, NULL, dst->lenextra, &dst->lp, NULL, 0, &dst->c, 1);
962 dbg(1, "%d segments\n", segs);
966 static struct route_graph *
967 route_graph_build(struct mapset *ms, struct coord *c1, struct coord *c2)
969 struct route_graph *ret=g_new0(struct route_graph, 1);
970 struct map_selection *sel;
971 struct mapset_handle *h;
977 printf("%s:Out of memory\n", __FUNCTION__);
980 sel=route_calc_selection(c1, c2);
982 while ((m=mapset_next(h,1))) {
983 mr=map_rect_new(m, sel);
986 while ((item=map_rect_get_item(mr))) {
987 if (item->type >= type_street_0 && item->type <= type_ferry) {
988 route_process_street_graph(ret, item);
991 map_rect_destroy(mr);
994 route_free_selection(sel);
1000 route_graph_update(struct route *this)
1002 route_graph_destroy(this->graph);
1003 profile(1,"graph_free");
1004 this->graph=route_graph_build(this->ms, &this->pos->c, &this->dst->c);
1005 profile(1,"route_graph_build");
1006 route_graph_flood(this->graph, this->dst, this->speedlist);
1007 profile(1,"route_graph_flood");
1011 struct street_data *
1012 street_get_data (struct item *item)
1015 struct coord c[maxcount];
1017 struct street_data *ret;
1020 while (count < maxcount) {
1021 if (!item_coord_get(item, &c[count], 1))
1025 if (count >= maxcount) {
1026 dbg(0, "count=%d maxcount=%d id_hi=0x%x id_lo=0x%x\n", count, maxcount, item->id_hi, item->id_lo);
1027 if (item_attr_get(item, attr_debug, &attr))
1028 dbg(0,"debug='%s'\n", attr.u.str);
1030 g_assert(count < maxcount);
1031 ret=g_malloc(sizeof(struct street_data)+count*sizeof(struct coord));
1034 if (item_attr_get(item, attr_flags, &attr))
1035 ret->flags=attr.u.num;
1038 memcpy(ret->c, c, count*sizeof(struct coord));
1043 struct street_data *
1044 street_data_dup(struct street_data *orig)
1046 struct street_data *ret;
1047 int size=sizeof(struct street_data)+orig->count*sizeof(struct coord);
1050 memcpy(ret, orig, size);
1056 street_data_free(struct street_data *sd)
1061 static struct route_info *
1062 route_find_nearest_street(struct mapset *ms, struct pcoord *pc)
1064 struct route_info *ret=NULL;
1066 struct map_selection *sel;
1067 int dist,mindist=0,pos;
1068 struct mapset_handle *h;
1070 struct map_rect *mr;
1073 struct street_data *sd;
1080 * This is not correct for two reasons:
1081 * - You may need to go back first
1082 * - Currently we allow mixing of mapsets
1084 sel = route_rect(18, &c, &c, 0, max_dist);
1086 while ((m=mapset_next(h,1))) {
1089 if (map_projection(m) != pc->pro) {
1090 transform_to_geo(pc->pro, &c, &g);
1091 transform_from_geo(map_projection(m), &g, &c);
1093 mr=map_rect_new(m, sel);
1096 while ((item=map_rect_get_item(mr))) {
1097 if (item->type >= type_street_0 && item->type <= type_ferry) {
1098 sd=street_get_data(item);
1099 dist=transform_distance_polyline_sq(sd->c, sd->count, &c, &lp, &pos);
1100 if (!ret || dist < mindist) {
1102 street_data_free(ret->street);
1105 ret=g_new(struct route_info, 1);
1107 printf("%s:Out of memory\n", __FUNCTION__);
1115 dbg(1,"dist=%d id 0x%x 0x%x pos=%d\n", dist, item->id_hi, item->id_lo, pos);
1117 street_data_free(sd);
1120 map_rect_destroy(mr);
1123 map_selection_destroy(sel);
1129 route_info_free(struct route_info *inf)
1132 street_data_free(inf->street);
1139 struct street_data *
1140 route_info_street(struct route_info *rinf)
1142 return rinf->street;
1146 struct route_crossings *
1147 route_crossings_get(struct route *this, struct coord *c)
1149 struct route_point *pnt;
1150 struct route_segment *seg;
1152 struct route_crossings *ret;
1154 pnt=route_graph_get_point(this, c);
1157 printf("start: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo);
1159 seg=seg->start_next;
1163 printf("end: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo);
1167 ret=g_malloc(sizeof(struct route_crossings)+crossings*sizeof(struct route_crossing));
1168 ret->count=crossings;
1174 struct map_rect_priv {
1175 struct route_info_handle *ri;
1176 enum attr_type attr_next;
1178 struct map_priv *mpriv;
1181 unsigned int last_coord;
1182 struct route_path_segment *seg,*seg_next;
1183 struct route_graph_point *point;
1184 struct route_graph_segment *rseg;
1189 rm_coord_rewind(void *priv_data)
1191 struct map_rect_priv *mr = priv_data;
1196 rm_attr_rewind(void *priv_data)
1198 struct map_rect_priv *mr = priv_data;
1199 mr->attr_next = attr_street_item;
1203 rm_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
1205 struct map_rect_priv *mr = priv_data;
1206 struct route_path_segment *seg=mr->seg;
1207 struct route *route=mr->mpriv->route;
1208 attr->type=attr_type;
1209 switch (attr_type) {
1211 while (mr->attr_next != attr_none) {
1212 if (rm_attr_get(priv_data, mr->attr_next, attr))
1216 case attr_street_item:
1217 mr->attr_next=attr_length;
1218 if (seg && seg->item.map)
1219 attr->u.item=&seg->item;
1225 attr->u.num=seg->length;
1227 attr->u.num=mr->length;
1228 mr->attr_next=attr_time;
1231 mr->attr_next=attr_none;
1233 attr->u.num=route_time(route->speedlist, &seg->item, seg->length);
1238 attr->type=attr_none;
1245 rm_coord_get(void *priv_data, struct coord *c, int count)
1247 struct map_rect_priv *mr = priv_data;
1248 struct route_path_segment *seg = mr->seg;
1252 for (i=0; i < count; i++) {
1253 if (mr->last_coord >= seg->ncoords)
1255 if (i >= seg->ncoords)
1257 c[i] = seg->c[mr->last_coord++];
1260 dbg(1,"return %d\n",rc);
1264 static struct item_methods methods_route_item = {
1272 rp_attr_rewind(void *priv_data)
1274 struct map_rect_priv *mr = priv_data;
1275 mr->attr_next = attr_label;
1279 rp_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
1281 struct map_rect_priv *mr = priv_data;
1282 struct route_graph_point *p = mr->point;
1283 if (mr->item.type != type_rg_point)
1285 switch (attr_type) {
1287 while (mr->attr_next != attr_none) {
1288 if (rm_attr_get(priv_data, mr->attr_next, attr))
1292 attr->type = attr_label;
1295 if (p->value != INT_MAX)
1296 mr->str=g_strdup_printf("%d", p->value);
1298 mr->str=g_strdup("-");
1299 attr->u.str = mr->str;
1300 mr->attr_next=attr_none;
1303 attr->type = attr_debug;
1306 mr->str=g_strdup_printf("x=%d y=%d", p->c.x, p->c.y);
1307 attr->u.str = mr->str;
1308 mr->attr_next=attr_none;
1316 rp_coord_get(void *priv_data, struct coord *c, int count)
1318 struct map_rect_priv *mr = priv_data;
1319 struct route_graph_point *p = mr->point;
1320 struct route_graph_segment *seg = mr->rseg;
1322 for (i=0; i < count; i++) {
1323 if (mr->item.type == type_rg_point) {
1324 if (mr->last_coord >= 1)
1328 if (mr->last_coord >= 2)
1333 c[i] = seg->start->c;
1341 static struct item_methods methods_point_item = {
1349 rm_destroy(struct map_priv *priv)
1354 static struct map_rect_priv *
1355 rm_rect_new(struct map_priv *priv, struct map_selection *sel)
1357 struct map_rect_priv * mr;
1359 if (! route_get_pos(priv->route))
1361 if (! route_get_dst(priv->route))
1363 if (! priv->route->path2)
1365 mr=g_new0(struct map_rect_priv, 1);
1367 mr->item.priv_data = mr;
1368 mr->item.type = type_street_route;
1369 mr->item.meth = &methods_route_item;
1370 mr->seg_next=priv->route->path2->path;
1374 static struct map_rect_priv *
1375 rp_rect_new(struct map_priv *priv, struct map_selection *sel)
1377 struct map_rect_priv * mr;
1379 if (! priv->route->graph || ! priv->route->graph->route_points)
1381 mr=g_new0(struct map_rect_priv, 1);
1383 mr->item.priv_data = mr;
1384 mr->item.type = type_rg_point;
1385 mr->item.meth = &methods_point_item;
1390 rm_rect_destroy(struct map_rect_priv *mr)
1397 static struct item *
1398 rp_get_item(struct map_rect_priv *mr)
1400 struct route *r = mr->mpriv->route;
1401 struct route_graph_point *p = mr->point;
1402 struct route_graph_segment *seg = mr->rseg;
1404 if (mr->item.type == type_rg_point) {
1406 p = r->graph->route_points;
1412 rm_coord_rewind(mr);
1416 mr->item.type = type_rg_segment;
1419 seg=r->graph->route_segments;
1425 rm_coord_rewind(mr);
1433 static struct item *
1434 rp_get_item_byid(struct map_rect_priv *mr, int id_hi, int id_lo)
1436 struct item *ret=NULL;
1438 ret=rp_get_item(mr);
1443 static struct item *
1444 rm_get_item(struct map_rect_priv *mr)
1446 struct route *r = mr->mpriv->route;
1447 struct route_path_segment *seg = mr->seg;
1448 dbg(1,"enter\n", mr->pos);
1450 mr->seg=mr->seg_next;
1453 mr->seg_next=mr->seg->next;
1460 static struct item *
1461 rm_get_item_byid(struct map_rect_priv *mr, int id_hi, int id_lo)
1463 struct item *ret=NULL;
1465 ret=rm_get_item(mr);
1469 static struct map_methods route_meth = {
1482 static struct map_methods route_graph_meth = {
1496 route_toggle_routegraph_display(struct route *route)
1498 if (route->flags & RF_SHOWGRAPH) {
1499 route->flags &= ~RF_SHOWGRAPH;
1501 route->flags |= RF_SHOWGRAPH;
1505 static struct map_priv *
1506 route_map_new_helper(struct map_methods *meth, struct attr **attrs, int graph)
1508 struct map_priv *ret;
1509 struct attr *route_attr;
1511 route_attr=attr_search(attrs, NULL, attr_route);
1514 ret=g_new0(struct map_priv, 1);
1516 *meth=route_graph_meth;
1519 ret->route=route_attr->u.route;
1524 static struct map_priv *
1525 route_map_new(struct map_methods *meth, struct attr **attrs)
1527 return route_map_new_helper(meth, attrs, 0);
1530 static struct map_priv *
1531 route_graph_map_new(struct map_methods *meth, struct attr **attrs)
1533 return route_map_new_helper(meth, attrs, 1);
1537 route_get_map_helper(struct route *this_, struct map **map, char *type)
1540 *map=map_new((struct attr*[]){
1541 &(struct attr){attr_type,{type}},
1542 &(struct attr){attr_route,.u.route=this_},
1543 &(struct attr){attr_data,{""}},
1549 route_get_map(struct route *this_)
1551 return route_get_map_helper(this_, &this_->map, "route");
1556 route_get_graph_map(struct route *this_)
1558 return route_get_map_helper(this_, &this_->graph_map, "route_graph");
1562 route_set_projection(struct route *this_, enum projection pro)
1569 plugin_register_map_type("route", route_map_new);
1570 plugin_register_map_type("route_graph", route_graph_map_new);