20 #include "transform.h"
21 #include "fib-1.0/fib.h"
23 static int speed_list[]={
25 10, /* street_1_city */
26 30, /* street_2_city */
27 40, /* street_3_city */
28 50, /* street_4_city */
29 80, /* highway_city */
30 60, /* street_1_land */
31 65, /* street_2_land */
32 70, /* street_3_land */
33 80, /* street_4_land */
34 120, /* street_n_lanes */
35 120, /* highway_land */
43 struct route_graph_point {
44 struct route_graph_point *next;
45 struct route_graph_point *hash_next;
46 struct route_graph_segment *start;
47 struct route_graph_segment *end;
48 struct route_graph_segment *seg;
49 struct fibheap_el *el;
55 struct route_graph_segment {
56 struct route_graph_segment *next;
57 struct route_graph_segment *start_next;
58 struct route_graph_segment *end_next;
59 struct route_graph_point *start;
60 struct route_graph_point *end;
66 struct route_path_segment {
71 struct route_path_segment *next;
90 struct street_data *street;
94 struct route_path_segment *path;
95 struct route_path_segment *path_last;
96 struct item_hash *path_hash;
103 struct route_info *pos;
104 struct route_info *dst;
106 struct route_graph *graph;
107 struct route_path *path2;
112 struct route_graph_point *route_points;
113 struct route_graph_segment *route_segments;
114 #define HASH_SIZE 8192
115 struct route_graph_point *hash[HASH_SIZE];
118 static struct route_info * route_find_nearest_street(struct mapset *ms, struct coord *c);
119 static struct route_graph_point *route_graph_get_point(struct route_graph *this, struct coord *c);
120 static void route_graph_update(struct route *this);
121 static struct route_path *route_path_new(struct route_graph *this, struct route_info *pos, struct route_info *dst);
122 static void route_process_street_graph(struct route_graph *this, struct item *item);
123 static void route_graph_destroy(struct route_graph *this);
124 static void route_path_update(struct route *this);
128 route_path_destroy(struct route_path *this)
130 struct route_path_segment *c,*n;
133 if (this->path_hash) {
134 item_hash_destroy(this->path_hash);
135 this->path_hash=NULL;
147 route_new(struct mapset *ms)
149 struct route *this=g_new0(struct route, 1);
155 route_get_mapset(struct route *this)
161 route_get_pos(struct route *this)
167 route_get_dst(struct route *this)
173 route_contains(struct route *this, struct item *item)
175 if (! this->path2 || !item_hash_lookup(this->path2->path_hash, item))
181 route_path_update(struct route *this)
183 route_path_destroy(this->path2);
184 if (! this->graph || !(this->path2=route_path_new(this->graph, this->pos, this->dst))) {
186 route_graph_update(this);
187 this->path2=route_path_new(this->graph, this->pos, this->dst);
188 profile(1,"route_path_new");
194 route_set_position(struct route *this, struct coord *pos)
197 route_info_free(this->pos);
198 this->pos=route_find_nearest_street(this->ms, pos);
199 dbg(0,"this->pos=%p\n", this->pos);
203 route_path_update(this);
207 route_set_position_from_track(struct route *this, struct track *track)
210 struct route_info *ret;
212 c=track_get_pos(track);
213 ret=g_new0(struct route_info, 1);
215 route_info_free(this->pos);
218 ret->pos=track_get_segment_pos(track);
221 ret->street=street_data_dup(track_get_street_data(track));
224 route_path_update(this);
227 struct map_selection *route_selection;
229 struct map_selection *
230 route_rect(int order, struct coord *c1, struct coord *c2, int rel, int abs)
232 int dx,dy,sx=1,sy=1,d,m;
233 struct map_selection *sel=g_new(struct map_selection, 1);
234 sel->order[layer_town]=0;
235 sel->order[layer_poly]=0;
236 sel->order[layer_street]=order;
237 dbg(1,"%p %p\n", c1, c2);
242 sel->rect.lu.x=c1->x;
243 sel->rect.rl.x=c2->x;
245 sel->rect.lu.x=c2->x;
246 sel->rect.rl.x=c1->x;
250 sel->rect.lu.y=c2->y;
251 sel->rect.rl.y=c1->y;
253 sel->rect.lu.y=c1->y;
254 sel->rect.rl.y=c2->y;
269 static struct map_selection *
270 route_calc_selection(struct coord *c1, struct coord *c2)
272 struct map_selection *ret,*sel;
273 sel=route_rect(4, c1, c2, 25, 0);
275 sel->next=route_rect(8, c1, c1, 0, 40000);
277 sel->next=route_rect(18, c1, c1, 0, 10000);
279 sel->next=route_rect(8, c2, c2, 0, 40000);
281 sel->next=route_rect(18, c2, c2, 0, 10000);
282 /* route_selection=ret; */
287 route_free_selection(struct map_selection *sel)
289 struct map_selection *next;
300 route_set_destination(struct route *this, struct coord *dst)
304 route_info_free(this->dst);
305 this->dst=route_find_nearest_street(this->ms, dst);
306 if (! this->dst || ! this->pos)
308 profile(1,"find_nearest_street");
310 route_graph_destroy(this->graph);
312 route_path_update(this);
316 static struct route_graph_point *
317 route_graph_get_point(struct route_graph *this, struct coord *c)
319 struct route_graph_point *p=this->route_points;
320 int hashval=(c->x + c->y) & (HASH_SIZE-1);
321 p=this->hash[hashval];
323 if (p->c.x == c->x && p->c.y == c->y)
331 static struct route_graph_point *
332 route_graph_add_point(struct route_graph *this, struct coord *f)
335 struct route_graph_point *p;
337 p=route_graph_get_point(this,f);
339 hashval=(f->x + f->y) & (HASH_SIZE-1);
341 printf("p (0x%x,0x%x)\n", f->x, f->y);
342 p=g_new(struct route_graph_point,1);
343 p->hash_next=this->hash[hashval];
344 this->hash[hashval]=p;
345 p->next=this->route_points;
352 this->route_points=p;
359 route_graph_free_points(struct route_graph *this)
361 struct route_graph_point *curr,*next;
362 curr=this->route_points;
368 this->route_points=NULL;
369 memset(this->hash, 0, sizeof(this->hash));
373 route_graph_add_segment(struct route_graph *this, struct route_graph_point *start, struct route_graph_point *end, int len, struct item *item, int limit)
375 struct route_graph_segment *s;
376 s=g_new0(struct route_graph_segment,1);
378 s->start_next=start->start;
381 s->end_next=end->end;
387 s->next=this->route_segments;
388 this->route_segments=s;
390 printf("l (0x%x,0x%x)-(0x%x,0x%x)\n", start->c.x, start->c.y, end->c.x, end->c.y);
395 route_path_add_item(struct route_path *this, struct item *itm, struct coord *start, struct coord *end, int len, int time)
397 struct route_path_segment *segment=g_new0(struct route_path_segment,1);
398 item_hash_insert(this->path_hash, itm, (void *)1);
404 segment->c[0]=*start;
410 this->path_last->next=segment;
411 this->path_last=segment;
415 struct route_path_handle {
416 struct route_path_segment *s;
419 struct route_path_handle *
420 route_path_open(struct route *this)
422 struct route_path_handle *ret=g_new(struct route_path_handle, 1);
424 ret->s=this->path2->path;
428 struct route_path_segment *
429 route_path_get_segment(struct route_path_handle *h)
431 struct route_path_segment *ret=h->s;
440 route_path_segment_get_start(struct route_path_segment *s)
446 route_path_segment_get_end(struct route_path_segment *s)
452 route_path_segment_get_item(struct route_path_segment *s)
458 route_path_segment_get_length(struct route_path_segment *s)
464 route_path_segment_get_time(struct route_path_segment *s)
470 route_path_close(struct route_path_handle *h)
477 route_graph_free_segments(struct route_graph *this)
479 struct route_graph_segment *curr,*next;
480 curr=this->route_segments;
486 this->route_segments=NULL;
490 route_graph_destroy(struct route_graph *this)
493 route_graph_free_points(this);
494 route_graph_free_segments(this);
500 route_time(struct item *item, int len)
502 int idx=(item->type-type_street_0);
503 if (idx >= sizeof(speed_list)/sizeof(int) || idx < 0) {
504 dbg(0,"street idx(%d) out of range [0,%d[", sizeof(speed_list)/sizeof(int));
507 return len*36/speed_list[idx];
512 route_value(struct item *item, int len)
516 printf("len=%d\n", len);
519 ret=route_time(item, len);
520 dbg(1, "route_value(0x%x, %d)=%d\n", item->type, len, ret);
525 route_process_street_graph(struct route_graph *this, struct item *item)
532 struct route_graph_point *s_pnt,*e_pnt;
537 if (item_coord_get(item, &l, 1)) {
538 s_pnt=route_graph_add_point(this,&l);
539 while (item_coord_get(item, &c, 1)) {
540 len+=transform_distance(&l, &c);
543 e_pnt=route_graph_add_point(this,&l);
545 if (item_attr_get(item, attr_limit, &attr))
546 route_graph_add_segment(this, s_pnt, e_pnt, len, item, attr.u.num);
548 route_graph_add_segment(this, s_pnt, e_pnt, len, item, 0);
553 compare(void *v1, void *v2)
555 struct route_graph_point *p1=v1;
556 struct route_graph_point *p2=v2;
559 printf("compare %d (%p) vs %d (%p)\n", p1->value,p1,p2->value,p2);
561 return p1->value-p2->value;
565 route_info_length(struct route_info *pos, struct route_info *dst, int dir)
567 struct route_info_handle *h;
571 h=route_info_open(pos, dst, dir);
575 while ((c=route_info_get(h))) {
576 ret+=transform_distance(c, l);
583 route_graph_flood(struct route_graph *this, struct route_info *dst)
585 struct route_graph_point *p_min,*end=NULL;
586 struct route_graph_segment *s;
588 struct fibheap *heap;
589 struct street_data *sd=dst->street;
591 heap = fh_makeheap();
592 fh_setcmp(heap, compare);
594 if (! (sd->limit & 2)) {
595 end=route_graph_get_point(this, &sd->c[0]);
597 end->value=route_value(&sd->item, route_value(&sd->item, route_info_length(NULL, dst, -1)));
598 end->el=fh_insert(heap, end);
601 if (! (sd->limit & 1)) {
602 end=route_graph_get_point(this, &sd->c[sd->count-1]);
604 end->value=route_value(&sd->item, route_value(&sd->item, route_info_length(NULL, dst, 1)));
605 end->el=fh_insert(heap, end);
608 dbg(1,"0x%x,0x%x\n", end->c.x, end->c.y);
610 p_min=fh_extractmin(heap);
615 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);
619 val=route_value(&s->item, s->len);
621 val+=val*2*street_route_contained(s->str->segid);
625 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);
626 if (new < s->end->value && !(s->limit & 1)) {
631 printf("insert_end p=%p el=%p val=%d ", s->end, s->end->el, s->end->value);
632 s->end->el=fh_insert(heap, s->end);
634 printf("el new=%p\n", s->end->el);
638 printf("replace_end p=%p el=%p val=%d\n", s->end, s->end->el, s->end->value);
639 fh_replacedata(heap, s->end->el, s->end);
648 val=route_value(&s->item, s->len);
651 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);
652 if (new < s->start->value && !(s->limit & 2)) {
656 if (! s->start->el) {
658 printf("insert_start p=%p el=%p val=%d ", s->start, s->start->el, s->start->value);
659 s->start->el=fh_insert(heap, s->start);
661 printf("el new=%p\n", s->start->el);
665 printf("replace_start p=%p el=%p val=%d\n", s->start, s->start->el, s->start->value);
666 fh_replacedata(heap, s->start->el, s->start);
677 static struct route_path *
678 route_path_new(struct route_graph *this, struct route_info *pos, struct route_info *dst)
680 struct route_graph_point *start1=NULL,*start2=NULL,*start;
681 struct route_graph_segment *s=NULL;
683 int ilen,hr,min,sec,time=0,seg_time,seg_len;
684 unsigned int val1=0xffffffff,val2=0xffffffff;
685 struct street_data *sd=pos->street;
686 struct route_path *ret;
688 if (! (sd->limit & 1)) {
689 start1=route_graph_get_point(this, &sd->c[0]);
692 val1=start1->value+route_value(&sd->item, route_info_length(pos, NULL, -1));
693 dbg(0,"start1: %d(route)+%d=%d\n", start1->value, val1-start1->value, val1);
695 if (! (sd->limit & 2)) {
696 start2=route_graph_get_point(this, &sd->c[sd->count-1]);
699 val2=start2->value+route_value(&sd->item, route_info_length(pos, NULL, 1));
700 dbg(0,"start2: %d(route)+%d=%d\n", start2->value, val2-start2->value, val2);
702 if (start1 && (val1 < val2)) {
710 printf("no route found, pos blocked\n");
714 ret=g_new0(struct route_path, 1);
715 ret->path_hash=item_hash_new();
716 dbg(0,"dir=%d\n", pos->dir);
717 while ((s=start->seg)) {
720 printf("start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y);
723 seg_time=route_time(&s->item, seg_len);
726 if (s->start == start) {
727 route_path_add_item(ret, &s->item, &s->start->c, &s->end->c, seg_len, seg_time);
730 route_path_add_item(ret, &s->item, &s->end->c, &s->start->c, seg_len, seg_time);
735 dbg(0,"start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y);
736 dbg(0,"dst sd->limit=%d sd->c[0]=0x%x,0x%x sd->c[sd->count-1]=0x%x,0x%x\n", sd->limit, sd->c[0].x,sd->c[0].y, sd->c[sd->count-1].x, sd->c[sd->count-1].y);
737 if (start->c.x == sd->c[0].x && start->c.y == sd->c[0].y)
739 else if (start->c.x == sd->c[sd->count-1].x && start->c.y == sd->c[sd->count-1].y)
742 printf("no route found\n");
743 route_path_destroy(ret);
746 ilen=route_info_length(pos, NULL, 0);
747 time+=route_time(&pos->street->item, ilen);
750 ilen=route_info_length(NULL, dst, 0);
751 time+=route_time(&dst->street->item, ilen);
754 dbg(0, "%d segments\n", segs);
755 dbg(0, "len %5.3f\n", len/1000.0);
762 dbg(0, "time %02d:%02d:%02d (%d sec)\n", hr, min, time, sec);
763 dbg(0, "speed %f km/h\n", len/sec*3.6);
767 static struct route_graph *
768 route_graph_build(struct mapset *ms, struct coord *c1, struct coord *c2)
770 struct route_graph *ret=g_new0(struct route_graph, 1);
771 struct map_selection *sel;
772 struct mapset_handle *h;
778 sel=route_calc_selection(c1, c2);
780 while ((m=mapset_next(h,1))) {
781 mr=map_rect_new(m, sel);
782 while ((item=map_rect_get_item(mr))) {
783 if (item->type >= type_street_0 && item->type <= type_ferry) {
784 route_process_street_graph(ret, item);
786 while (item_coord_get(item, &e, 1));
788 map_rect_destroy(mr);
791 route_free_selection(sel);
797 route_graph_update(struct route *this)
799 route_graph_destroy(this->graph);
800 profile(1,"graph_free");
801 this->graph=route_graph_build(this->ms, &this->pos->c, &this->dst->c);
802 profile(1,"route_graph_build");
803 route_graph_flood(this->graph, this->dst);
804 profile(1,"route_graph_flood");
809 street_get_data (struct item *item)
811 struct coord c[1000];
813 struct street_data *ret;
816 while (count < 1000) {
817 if (!item_coord_get(item, &c[count], 1))
821 g_assert(count < 1000);
822 ret=g_malloc(sizeof(struct street_data)+count*sizeof(struct coord));
825 if (item_attr_get(item, attr_limit, &attr))
826 ret->limit=attr.u.num;
829 memcpy(ret->c, c, count*sizeof(struct coord));
836 street_data_dup(struct street_data *orig)
838 struct street_data *ret;
839 int size=sizeof(struct street_data)+orig->count*sizeof(struct coord);
842 memcpy(ret, orig, size);
848 street_data_free(struct street_data *sd)
853 static struct route_info *
854 route_find_nearest_street(struct mapset *ms, struct coord *c)
856 struct route_info *ret=NULL;
858 struct map_selection *sel=route_rect(18, c, c, 0, max_dist);
860 struct mapset_handle *h;
864 struct coord lp, sc[1000];
865 struct street_data *sd;
868 while ((m=mapset_next(h,1))) {
869 mr=map_rect_new(m, sel);
870 while ((item=map_rect_get_item(mr))) {
871 if (item->type >= type_street_0 && item->type <= type_ferry) {
872 sd=street_get_data(item);
873 dist=transform_distance_polyline_sq(sd->c, sd->count, c, &lp, &pos);
874 if (!ret || dist < ret->dist) {
876 street_data_free(ret->street);
879 ret=g_new(struct route_info, 1);
886 dbg(1,"dist=%d id 0x%x 0x%x pos=%d\n", dist, item->id_hi, item->id_lo, pos);
888 street_data_free(sd);
890 while (item_coord_get(item, &sc[0], 1));
892 map_rect_destroy(mr);
900 route_info_free(struct route_info *inf)
903 street_data_free(inf->street);
909 #include "projection.h"
912 route_info_street(struct route_info *rinf)
918 route_info_point(struct route_info *rinf, int point)
920 struct street_data *sd=rinf->street;
926 dir=point == 2 ? rinf->dir : -rinf->dir;
928 return &sd->c[sd->count-1];
940 struct route_info_handle {
941 struct route_info *start;
942 struct route_info *curr;
943 struct route_info *end;
952 struct route_info_handle *
953 route_info_open(struct route_info *start, struct route_info *end, int dir)
955 struct route_info_handle *ret=g_new0(struct route_info_handle, 1);
957 struct route_info *curr;
967 if (start->street->item.map != end->street->item.map || start->street->item.id_hi != end->street->item.id_hi || start->street->item.id_lo != end->street->item.id_lo) {
968 dbg(1,"return NULL\n");
971 printf("trivial start=%d end=%d start dir %d end dir %d\n", start->pos, end->pos, start->dir, end->dir);
972 if (start->pos == end->pos) {
977 if (start->pos > end->pos) {
982 if (start->pos < end->pos) {
987 printf("trivial now start=%d end=%d start dir %d end dir %d\n", start->pos, end->pos, start->dir, end->dir);
988 ret->endpos=end->pos;
1000 dbg(1,"return %p\n",ret);
1005 route_info_get(struct route_info_handle *h)
1010 dbg(1,"iter=%d\n", h->iter);
1026 dbg(1,"h->pos=%d\n", h->pos);
1027 if (h->dir && h->pos >= 0 && h->pos < h->curr->street->count && (h->end == NULL || h->endpos!=h->pos)) {
1028 new=&h->curr->street->c[h->pos];
1049 dbg(1,"new=%p (0x%x,0x%x) last=%p\n", new, new->x, new->y, h->last);
1050 if (h->last && new->x == h->last->x && new->y == h->last->y)
1060 route_info_close(struct route_info_handle *h)
1069 route_draw_route_info(struct route_info *pos, struct route_info *dst, struct transformation *t, struct displaylist *dsp)
1071 struct route_info_handle *h;
1073 struct coord_rect r;
1075 struct point pnt[100];
1081 item.type=type_street_route;
1084 h=route_info_open(pos, dst, 0);
1087 dbg(1, "return 0\n");
1091 dbg(1, "pos=%p pos->dir=%d pos->pos=%d\n", pos, pos->dir, pos->pos);
1092 c=route_info_get(h);
1095 while (c && count < 100) {
1096 dbg(1,"c=%p (0x%x,0x%x)\n", c, c->x, c->y);
1097 transform(t, projection_mg, c, &pnt[count++]);
1098 coord_rect_extend(&r, c);
1099 c=route_info_get(h);
1102 if (count && transform_contains(t, projection_mg, &r))
1103 display_add(dsp, &item, count, pnt, "Route");
1104 route_info_close(h);
1105 dbg(1, "return 1\n");
1110 route_draw(struct route *this, struct transformation *t, struct displaylist *dsp)
1113 if (! this->pos || ! this->dst)
1115 if (! route_draw_route_info(this->pos, this->dst, t, dsp)) {
1116 route_draw_route_info(this->pos, NULL, t, dsp);
1117 route_draw_route_info(NULL, this->dst, t, dsp);
1123 struct route_crossings *
1124 route_crossings_get(struct route *this, struct coord *c)
1126 struct route_point *pnt;
1127 struct route_segment *seg;
1129 struct route_crossings *ret;
1131 pnt=route_graph_get_point(this, c);
1134 printf("start: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo);
1136 seg=seg->start_next;
1140 printf("end: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo);
1144 ret=g_malloc(sizeof(struct route_crossings)+crossings*sizeof(struct route_crossing));
1145 ret->count=crossings;